]> err.no Git - linux-2.6/commitdiff
[ALSA] emu10k1: Add Audio capture support for Audigy 2 ZS Notebook.
authorJames Courtier-Dutton <James@superbug.co.uk>
Wed, 6 Dec 2006 15:58:02 +0000 (15:58 +0000)
committerJaroslav Kysela <perex@suse.cz>
Fri, 9 Feb 2007 08:02:17 +0000 (09:02 +0100)
Implement functionallity in order to fixe ALSA bug#2058.

Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
include/sound/emu10k1.h
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/io.c
sound/pci/emu10k1/p17v.h

index 8b28304f2c42a830a4ded604f46e3f1e38c81126..32ce4bd31b463d6017516566481d97e5dbcad696 100644 (file)
@@ -1427,6 +1427,8 @@ struct snd_emu10k1 {
        spinlock_t memblk_lock;
 
        unsigned int spdif_bits[3];             /* s/pdif out setup */
+       unsigned int i2c_capture_source;
+       u8 i2c_capture_volume[4][2];
 
        struct snd_emu10k1_fx8010 fx8010;               /* FX8010 info */
        int gpr_base;
@@ -1532,6 +1534,7 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i
 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn);
 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
+int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
 int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value);
 int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value);
 int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src);
index 711e819e4a0bdbf5cc34b580ce3fa4f577d8ad5f..80aa585eade4560231c44a320c5649eba3fb2018 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/firmware.h>
 #include "p16v.h"
 #include "tina2.h"
+#include "p17v.h"
 
 
 /*************************************************************************
@@ -120,11 +121,28 @@ static unsigned int spi_dac_init[] = {
                0x0622,
                0x1400,
 };
+
+static unsigned int i2c_adc_init[][2] = {
+       { 0x17, 0x00 }, /* Reset */
+       { 0x07, 0x00 }, /* Timeout */
+       { 0x0b, 0x22 },  /* Interface control */
+       { 0x0c, 0x22 },  /* Master mode control */
+       { 0x0d, 0x08 },  /* Powerdown control */
+       { 0x0e, 0xcf },  /* Attenuation Left  0x01 = -103dB, 0xff = 24dB */
+       { 0x0f, 0xcf },  /* Attenuation Right 0.5dB steps */
+       { 0x10, 0x7b },  /* ALC Control 1 */
+       { 0x11, 0x00 },  /* ALC Control 2 */
+       { 0x12, 0x32 },  /* ALC Control 3 */
+       { 0x13, 0x00 },  /* Noise gate control */
+       { 0x14, 0xa6 },  /* Limiter control */
+       { 0x15, ADC_MUX_2 },  /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */
+};
        
 static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
 {
        unsigned int silent_page;
        int ch;
+       u32 tmp;
 
        /* disable audio and lock cache */
        outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
@@ -163,8 +181,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
 
        if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
                /* Hacks for Alice3 to work independent of haP16V driver */
-               u32 tmp;
-
                //Setup SRCMulti_I2S SamplingRate
                tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
                tmp &= 0xfffff1ff;
@@ -184,8 +200,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
        }
        if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
                /* Hacks for Alice3 to work independent of haP16V driver */
-               u32 tmp;
-
                snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
                //Setup SRCMulti_I2S SamplingRate
                tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
@@ -231,6 +245,23 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */
 
        }
+       if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */
+               int size, n;
+
+               snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f);
+               tmp = inl(emu->port + A_IOCFG);
+               outl(tmp | 0x4, emu->port + A_IOCFG);  /* Set bit 2 for mic input */
+               tmp = inl(emu->port + A_IOCFG);
+               size = ARRAY_SIZE(i2c_adc_init);
+               for (n = 0; n < size; n++)
+                       snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]);
+               for (n=0; n < 4; n++) {
+                       emu->i2c_capture_volume[n][0]= 0xcf;
+                       emu->i2c_capture_volume[n][1]= 0xcf;
+               }
+
+       }
+
        
        snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
        snd_emu10k1_ptr_write(emu, TCB, 0, 0);  /* taken from original driver */
@@ -274,6 +305,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
        if (enable_ir) {        /* enable IR for SB Live */
                if (emu->card_capabilities->emu1010) {
                        ;  /* Disable all access to A_IOCFG for the emu1010 */
+               } else if (emu->card_capabilities->i2c_adc) {
+                       ;  /* Disable A_IOCFG for Audigy 2 ZS Notebook */
                } else if (emu->audigy) {
                        unsigned int reg = inl(emu->port + A_IOCFG);
                        outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
@@ -293,6 +326,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
        
        if (emu->card_capabilities->emu1010) {
                ;  /* Disable all access to A_IOCFG for the emu1010 */
+       } else if (emu->card_capabilities->i2c_adc) {
+               ;  /* Disable A_IOCFG for Audigy 2 ZS Notebook */
        } else if (emu->audigy) {       /* enable analog output */
                unsigned int reg = inl(emu->port + A_IOCFG);
                outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
@@ -311,6 +346,8 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
        /* Enable analog/digital outs on audigy */
        if (emu->card_capabilities->emu1010) {
                ;  /* Disable all access to A_IOCFG for the emu1010 */
+       } else if (emu->card_capabilities->i2c_adc) {
+               ;  /* Disable A_IOCFG for Audigy 2 ZS Notebook */
        } else if (emu->audigy) {
                outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
  
@@ -1139,10 +1176,11 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .adc_1361t = 1,  /* 24 bit capture instead of 16bit */
         .ac97_chip = 1} ,
        /* Audigy 2 ZS Notebook Cardbus card.*/
-       /* Tested by James@superbug.co.uk 22th December 2005 */
+       /* Tested by James@superbug.co.uk 6th November 2006 */
        /* Audio output 7.1/Headphones working.
         * Digital output working. (AC3 not checked, only PCM)
-        * Audio inputs not tested.
+        * Audio Mic/Line inputs working.
+        * Digital input not tested.
         */ 
        /* DSP: Tina2
         * DAC: Wolfson WM8768/WM8568
@@ -1150,6 +1188,25 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         * AC97: None
         * CA0151: None
         */
+       /* Tested by James@superbug.co.uk 4th April 2006 */
+       /* A_IOCFG bits
+        * Output
+        * 0: Not Used
+        * 1: 0 = Mute all the 7.1 channel out. 1 = unmute.
+        * 2: Analog input 0 = line in, 1 = mic in
+        * 3: Not Used
+        * 4: Digital output 0 = off, 1 = on.
+        * 5: Not Used
+        * 6: Not Used
+        * 7: Not Used
+        * Input
+        *      All bits 1 (0x3fxx) means nothing plugged in.
+        * 8-9: 0 = Line in/Mic, 2 = Optical in, 3 = Nothing.
+        * A-B: 0 = Headphones, 2 = Optical out, 3 = Nothing.
+        * C-D: 2 = Front/Rear/etc, 3 = nothing.
+        * E-F: Always 0
+        *
+        */
        {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
         .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", 
         .id = "Audigy2",
@@ -1157,6 +1214,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0108_chip = 1,
         .ca_cardbus_chip = 1,
         .spi_dac = 1,
+        .i2c_adc = 1,
         .spk71 = 1} ,
        {.vendor = 0x1102, .device = 0x0008, 
         .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 
index 9b7fd564343e59a478b7c2a246a8881529b6f2ff..b8221f385ff906264545ea6dc1c851375723bb24 100644 (file)
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 #include <linux/delay.h>
+#include <sound/tlv.h>
+
+#include "p17v.h"
 
 #define AC97_ID_STAC9758       0x83847658
 
+static DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
+
 static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -579,6 +584,162 @@ static struct snd_kcontrol_new snd_emu1010_internal_clock =
        .put =          snd_emu1010_internal_clock_put
 };
 
+static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
+                                         struct snd_ctl_elem_info *uinfo)
+{
+#if 0
+       static char *texts[4] = {
+               "Unknown1", "Unknown2", "Mic", "Line"
+       };
+#endif
+       static char *texts[2] = {
+               "Mic", "Line"
+       };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item > 1)
+                uinfo->value.enumerated.item = 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
+       return 0;
+}
+
+static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+       unsigned int source_id;
+       unsigned int ngain, ogain;
+       u32 gpio;
+       int change = 0;
+       unsigned long flags;
+       u32 source;
+       /* If the capture source has changed,
+        * update the capture volume from the cached value
+        * for the particular source.
+        */
+       source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */
+       change = (emu->i2c_capture_source != source_id);
+       if (change) {
+               snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
+               spin_lock_irqsave(&emu->emu_lock, flags);
+               gpio = inl(emu->port + A_IOCFG);
+               if (source_id==0)
+                       outl(gpio | 0x4, emu->port + A_IOCFG);
+               else
+                       outl(gpio & ~0x4, emu->port + A_IOCFG);
+               spin_unlock_irqrestore(&emu->emu_lock, flags);
+
+               ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
+               ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
+               if (ngain != ogain)
+                       snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
+               ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
+               ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
+               if (ngain != ogain)
+                       snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
+
+               source = 1 << (source_id + 2);
+               snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
+               emu->i2c_capture_source = source_id;
+       }
+        return change;
+}
+
+static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
+{
+               .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name =         "Capture Source",
+               .info =         snd_audigy_i2c_capture_source_info,
+               .get =          snd_audigy_i2c_capture_source_get,
+               .put =          snd_audigy_i2c_capture_source_put
+};
+
+static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 255;
+       return 0;
+}
+
+static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+       int source_id;
+
+       source_id = kcontrol->private_value;
+
+       ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
+       ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
+       return 0;
+}
+
+static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+       unsigned int ogain;
+       unsigned int ngain;
+       int source_id;
+       int change = 0;
+
+       source_id = kcontrol->private_value;
+       ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
+       ngain = ucontrol->value.integer.value[0];
+       if (ngain > 0xff)
+               return 0;
+       if (ogain != ngain) {
+               if (emu->i2c_capture_source == source_id)
+                       snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
+               emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
+               change = 1;
+       }
+       ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
+       ngain = ucontrol->value.integer.value[1];
+       if (ngain > 0xff)
+               return 0;
+       if (ogain != ngain) {
+               if (emu->i2c_capture_source == source_id)
+                       snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
+               emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
+               change = 1;
+       }
+
+       return change;
+}
+
+#define I2C_VOLUME(xname,chid) \
+{                                                              \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
+                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
+       .info =  snd_audigy_i2c_volume_info,                    \
+       .get =   snd_audigy_i2c_volume_get,                     \
+       .put =   snd_audigy_i2c_volume_put,                     \
+       .tlv = { .p = snd_audigy_db_scale2 },                   \
+       .private_value = chid                                   \
+}
+
+
+static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
+       I2C_VOLUME("Mic Capture Volume", 0),
+       I2C_VOLUME("Line Capture Volume", 0)
+};
+
 #if 0
 static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
@@ -1179,7 +1340,9 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
        int change = 0;
 
        spin_lock_irqsave(&emu->reg_lock, flags);
-       if (emu->audigy) {
+       if ( emu->card_capabilities->i2c_adc) {
+               /* Do nothing for Audigy 2 ZS Notebook */
+       } else if (emu->audigy) {
                reg = inl(emu->port + A_IOCFG);
                val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
                change = (reg & A_IOCFG_GPOUT0) != val;
@@ -1317,6 +1480,22 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                "AMic Playback Volume", "Mic Playback Volume",
                NULL
        };
+       static char *audigy_rename_ctls_i2c_adc[] = {
+               //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
+               "Line Capture Volume", "Analog Mix Capture Volume",
+               "Wave Playback Volume", "OLD PCM Playback Volume",
+               "Wave Master Playback Volume", "Master Playback Volume",
+               "AMic Playback Volume", "Old Mic Playback Volume",
+               NULL
+       };
+       static char *audigy_remove_ctls_i2c_adc[] = {
+               /* On the Audigy2 ZS Notebook
+                * Capture via WM8775  */
+               "Mic Capture Volume",
+               "Analog Mix Capture Volume",
+               "Aux Capture Volume",
+               NULL
+       };
        static char *audigy_remove_ctls_1361t_adc[] = {
                /* On the Audigy2 the AC97 playback is piped into
                 * the Philips ADC for 24bit capture */
@@ -1409,6 +1588,10 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                }
                for (; *c; c++)
                        remove_ctl(card, *c);
+       } else if (emu->card_capabilities->i2c_adc) {
+               c = audigy_remove_ctls_i2c_adc;
+               for (; *c; c++)
+                       remove_ctl(card, *c);
        } else {
        no_ac97:
                if (emu->card_capabilities->ecard)
@@ -1422,6 +1605,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
        if (emu->audigy)
                if (emu->card_capabilities->adc_1361t)
                        c = audigy_rename_ctls_1361t_adc;
+               else if (emu->card_capabilities->i2c_adc)
+                       c = audigy_rename_ctls_i2c_adc;
                else
                        c = audigy_rename_ctls;
        else
@@ -1584,6 +1769,20 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                if (err < 0)
                        return err;
        }
+
+       if ( emu->card_capabilities->i2c_adc) {
+               int i;
+
+               err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
+               if (err < 0)
+                       return err;
+
+               for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
+                       err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
+                       if (err < 0)
+                               return err;
+               }
+       }
                
        return 0;
 }
index 27ab7d1788a039136f24c9589b04f79a79e6e503..116e1c8d93616bd9df9c6b19452a9e4781f59400 100644 (file)
@@ -30,6 +30,7 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 #include <linux/delay.h>
+#include "p17v.h"
 
 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
 {
@@ -167,6 +168,64 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
        return 0;
 }
 
+/* The ADC does not support i2c read, so only write is implemented */
+int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
+                               u32 reg,
+                               u32 value)
+{
+       u32 tmp;
+       int timeout = 0;
+       int status;
+       int retry;
+       if ((reg > 0x7f) || (value > 0x1ff)) {
+               snd_printk(KERN_ERR "i2c_write: invalid values.\n");
+               return -EINVAL;
+       }
+
+       tmp = reg << 25 | value << 16;
+       // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
+       /* Not sure what this I2C channel controls. */
+       /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */
+
+       /* This controls the I2C connected to the WM8775 ADC Codec */
+       snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
+       tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
+
+       for (retry = 0; retry < 10; retry++) {
+               /* Send the data to i2c */
+               //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0);
+               //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
+               tmp = 0;
+               tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
+               snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
+
+               /* Wait till the transaction ends */
+               while (1) {
+                       udelay(10);
+                       status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
+                       // snd_printk("I2C:status=0x%x\n", status);
+                       timeout++;
+                       if ((status & I2C_A_ADC_START) == 0)
+                               break;
+
+                       if (timeout > 1000) {
+                               snd_printk("emu10k1:I2C:timeout status=0x%x\n", status);
+                               break;
+                       }
+               }
+               //Read back and see if the transaction is successful
+               if ((status & I2C_A_ADC_ABORT) == 0)
+                       break;
+       }
+
+       if (retry == 10) {
+               snd_printk(KERN_ERR "Writing to ADC failed!\n");
+               return -EINVAL;
+       }
+    
+       return 0;
+}
+
 int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
 {
        if (reg < 0 || reg > 0x3f)
index 7ddb5be632cf8ad83a75564c1599470f8e27cfa6..4ef5f68a9cd0654c6a512d297dc3a0c2cc5cd0d0 100644 (file)
 #define P17V_I2C_ADDR          0x3d    /* I2C Address */
 #define P17V_I2C_0             0x3e    /* I2C Data */
 #define P17V_I2C_1             0x3f    /* I2C Data */
+/* I2C values */
+#define I2C_A_ADC_ADD_MASK     0x000000fe      /*The address is a 7 bit address */
+#define I2C_A_ADC_RW_MASK      0x00000001      /*bit mask for R/W */
+#define I2C_A_ADC_TRANS_MASK   0x00000010      /*Bit mask for I2c address DAC value  */
+#define I2C_A_ADC_ABORT_MASK   0x00000020      /*Bit mask for I2C transaction abort flag */
+#define I2C_A_ADC_LAST_MASK    0x00000040      /*Bit mask for Last word transaction */
+#define I2C_A_ADC_BYTE_MASK    0x00000080      /*Bit mask for Byte Mode */
+
+#define I2C_A_ADC_ADD          0x00000034      /*This is the Device address for ADC  */
+#define I2C_A_ADC_READ         0x00000001      /*To perform a read operation */
+#define I2C_A_ADC_START                0x00000100      /*Start I2C transaction */
+#define I2C_A_ADC_ABORT                0x00000200      /*I2C transaction abort */
+#define I2C_A_ADC_LAST         0x00000400      /*I2C last transaction */
+#define I2C_A_ADC_BYTE         0x00000800      /*I2C one byte mode */
+
+#define I2C_D_ADC_REG_MASK     0xfe000000      /*ADC address register */ 
+#define I2C_D_ADC_DAT_MASK     0x01ff0000      /*ADC data register */
+
+#define ADC_TIMEOUT            0x00000007      /*ADC Timeout Clock Disable */
+#define ADC_IFC_CTRL           0x0000000b      /*ADC Interface Control */
+#define ADC_MASTER             0x0000000c      /*ADC Master Mode Control */
+#define ADC_POWER              0x0000000d      /*ADC PowerDown Control */
+#define ADC_ATTEN_ADCL         0x0000000e      /*ADC Attenuation ADCL */
+#define ADC_ATTEN_ADCR         0x0000000f      /*ADC Attenuation ADCR */
+#define ADC_ALC_CTRL1          0x00000010      /*ADC ALC Control 1 */
+#define ADC_ALC_CTRL2          0x00000011      /*ADC ALC Control 2 */
+#define ADC_ALC_CTRL3          0x00000012      /*ADC ALC Control 3 */
+#define ADC_NOISE_CTRL         0x00000013      /*ADC Noise Gate Control */
+#define ADC_LIMIT_CTRL         0x00000014      /*ADC Limiter Control */
+#define ADC_MUX                        0x00000015      /*ADC Mux offset */
+#if 0
+/* FIXME: Not tested yet. */
+#define ADC_GAIN_MASK          0x000000ff      //Mask for ADC Gain
+#define ADC_ZERODB             0x000000cf      //Value to set ADC to 0dB
+#define ADC_MUTE_MASK          0x000000c0      //Mask for ADC mute
+#define ADC_MUTE               0x000000c0      //Value to mute ADC
+#define ADC_OSR                        0x00000008      //Mask for ADC oversample rate select
+#define ADC_TIMEOUT_DISABLE    0x00000008      //Value and mask to disable Timeout clock
+#define ADC_HPF_DISABLE                0x00000100      //Value and mask to disable High pass filter
+#define ADC_TRANWIN_MASK       0x00000070      //Mask for Length of Transient Window
+#endif
+
+#define ADC_MUX_MASK           0x0000000f      //Mask for ADC Mux
+#define ADC_MUX_0              0x00000001      //Value to select Unknown at ADC Mux (Not used)
+#define ADC_MUX_1              0x00000002      //Value to select Unknown at ADC Mux (Not used)
+#define ADC_MUX_2              0x00000004      //Value to select Mic at ADC Mux
+#define ADC_MUX_3              0x00000008      //Value to select Line-In at ADC Mux
 
 #define P17V_START_AUDIO       0x40    /* Start Audio bit */
 /* 41 - 47: Reserved */