]> err.no Git - linux-2.6/blobdiff - sound/pci/ice1712/prodigy192.c
Merge branches 'at91', 'dyntick', 'ep93xx', 'iop', 'ixp', 'misc', 'orion', 'omap...
[linux-2.6] / sound / pci / ice1712 / prodigy192.c
index 6d81a1c61d4147169dc143c2172d5c1807308fc5..48d3679292a7f81a4137e055a1724f2e21dbfd74 100644 (file)
@@ -54,7 +54,6 @@
  *
  */      
 
-#include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include "stac946x.h"
 #include <sound/tlv.h>
 
+struct prodigy192_spec {
+       struct ak4114 *ak4114;
+       /* rate change needs atomic mute/unmute of all dacs*/
+       struct mutex mute_mutex;
+};
+
 static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val)
 {
        snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val);
@@ -119,6 +124,7 @@ static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       struct prodigy192_spec *spec = ice->spec;
        int idx, change;
 
        if (kcontrol->private_value)
@@ -126,11 +132,11 @@ static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        else
                idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
        /* due to possible conflicts with stac9460_set_rate_val, mutexing */
-       mutex_lock(&ice->spec.prodigy192.mute_mutex);
+       mutex_lock(&spec->mute_mutex);
        /*printk("Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx,
                ucontrol->value.integer.value[0]);*/
        change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]);
-       mutex_unlock(&ice->spec.prodigy192.mute_mutex);
+       mutex_unlock(&spec->mute_mutex);
        return change;
 }
 
@@ -313,12 +319,12 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
 /*
  * Handler for setting correct codec rate - called when rate change is detected
  */
-static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
 {
        unsigned char old, new;
        int idx;
        unsigned char changed[7];
-       struct snd_ice1712 *ice = ak->private_data[0];
+       struct prodigy192_spec *spec = ice->spec;
 
        if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
                return;
@@ -333,7 +339,7 @@ static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
                return;
        /* change detected, setting master clock, muting first */
        /* due to possible conflicts with mute controls - mutexing */
-       mutex_lock(&ice->spec.prodigy192.mute_mutex);
+       mutex_lock(&spec->mute_mutex);
        /* we have to remember current mute status for each DAC */
        for (idx = 0; idx < 7 ; ++idx)
                changed[idx] = stac9460_dac_mute(ice,
@@ -347,19 +353,9 @@ static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
                if (changed[idx])
                        stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 1);
        }
-       mutex_unlock(&ice->spec.prodigy192.mute_mutex);
+       mutex_unlock(&spec->mute_mutex);
 }
 
-/* using akm infrastructure for setting rate of the codec */
-static struct snd_akm4xxx akmlike_stac9460 __devinitdata = {
-       .type = NON_AKM,        /* special value */
-       .num_adcs = 6,          /* not used in any way, just for completeness */
-       .num_dacs = 2,
-       .ops = {
-               .set_rate_val = stac9460_set_rate_val
-       }
-};
-
 
 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
@@ -634,12 +630,20 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
        static const unsigned char ak4114_init_txcsb[] = {
                0x41, 0x02, 0x2c, 0x00, 0x00
        };
+       struct prodigy192_spec *spec = ice->spec;
+       int err;
 
-       return snd_ak4114_create(ice->card,
+       err = snd_ak4114_create(ice->card,
                                 prodigy192_ak4114_read,
                                 prodigy192_ak4114_write,
                                 ak4114_init_vals, ak4114_init_txcsb,
-                                ice, &ice->spec.prodigy192.ak4114);
+                                ice, &spec->ak4114);
+       if (err < 0)
+               return err;
+       /* AK4114 in Prodigy192 cannot detect external rate correctly.
+        * No reason to stop capture stream due to incorrect checks */
+       spec->ak4114->check_flags = AK4114_CHECK_NO_RATE;
+       return 0;
 }
 
 static void stac9460_proc_regs_read(struct snd_info_entry *entry,
@@ -665,6 +669,7 @@ static void stac9460_proc_init(struct snd_ice1712 *ice)
 
 static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
 {
+       struct prodigy192_spec *spec = ice->spec;
        unsigned int i;
        int err;
 
@@ -674,7 +679,7 @@ static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
                if (err < 0)
                        return err;
        }
-       if (ice->spec.prodigy192.ak4114) {
+       if (spec->ak4114) {
                /* ak4114 is connected */
                for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) {
                        err = snd_ctl_add(ice->card,
@@ -683,7 +688,7 @@ static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
                        if (err < 0)
                                return err;
                }
-               err = snd_ak4114_build(ice->spec.prodigy192.ak4114,
+               err = snd_ak4114_build(spec->ak4114,
                                NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */
                                ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
                if (err < 0)
@@ -734,32 +739,30 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
        };
        const unsigned short *p;
        int err = 0;
-       struct snd_akm4xxx *ak;
+       struct prodigy192_spec *spec;
 
        /* prodigy 192 */
        ice->num_total_dacs = 6;
        ice->num_total_adcs = 2;
        ice->vt1720 = 0;  /* ice1724, e.g. 23 GPIOs */
        
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+       ice->spec = spec;
+       mutex_init(&spec->mute_mutex);
+
        /* initialize codec */
        p = stac_inits_prodigy;
        for (; *p != (unsigned short)-1; p += 2)
                stac9460_put(ice, p[0], p[1]);
-       /* reusing the akm codecs infrastructure,
-        * for setting rate on stac9460 */
-       ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
-       if (!ak)
-               return -ENOMEM;
-       ice->akm_codecs = 1;
-       err = snd_ice1712_akm4xxx_init(ak, &akmlike_stac9460, NULL, ice);
-       if (err < 0)
-               return err;
+       ice->gpio.set_pro_rate = stac9460_set_rate_val;
 
        /* MI/ODI/O add on card with AK4114 */
        if (prodigy192_miodio_exists(ice)) {
                err = prodigy192_ak4114_init(ice);
                /* from this moment if err = 0 then
-                * ice->spec.prodigy192.ak4114 should not be null
+                * spec->ak4114 should not be null
                 */
                snd_printdd("AK4114 initialized with status %d\n", err);
        } else
@@ -767,8 +770,6 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
        if (err < 0)
                return err;
 
-       mutex_init(&ice->spec.prodigy192.mute_mutex);
-
        return 0;
 }
 
@@ -811,10 +812,6 @@ struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
                .build_controls = prodigy192_add_controls,
                .eeprom_size = sizeof(prodigy71_eeprom),
                .eeprom_data = prodigy71_eeprom,
-               /* the current MPU401 code loops infinitely
-                * when opening midi device
-                */
-               .no_mpu401 = 1,
        },
        { } /* terminator */
 };