Loading sound/pci/ca0106/ca0106.h +3 −1 Original line number Diff line number Diff line Loading @@ -537,9 +537,9 @@ #endif #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ Loading Loading @@ -604,6 +604,8 @@ struct snd_ca0106 { u32 spdif_bits[4]; /* s/pdif out setup */ int spdif_enable; int capture_source; int i2c_capture_source; u8 i2c_capture_volume[4][2]; int capture_mic_line_in; struct snd_dma_buffer buffer; Loading sound/pci/ca0106/ca0106_main.c +40 −4 Original line number Diff line number Diff line Loading @@ -326,6 +326,7 @@ int snd_ca0106_spi_write(struct snd_ca0106 * emu, return 0; } /* The ADC does not support i2c read, so only write is implemented */ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value) Loading @@ -340,6 +341,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, } 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_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ Loading @@ -348,8 +350,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, for (retry = 0; retry < 10; retry++) { /* Send the data to i2c */ tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); //tmp = snd_ca0106_ptr_read(emu, I2C_A, 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_ca0106_ptr_write(emu, I2C_A, 0, tmp); Loading Loading @@ -1200,6 +1203,22 @@ static unsigned int spi_dac_init[] = { 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_LINEIN }, /* ADC Mixer control */ }; static int __devinit snd_ca0106_create(struct snd_card *card, struct pci_dev *pci, struct snd_ca0106 **rchip) Loading Loading @@ -1361,7 +1380,12 @@ static int __devinit snd_ca0106_create(struct snd_card *card, snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ chip->capture_source = 3; /* Set CAPTURE_SOURCE */ if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ if (chip->details->gpio_type == 2) { /* The SB0410 and SB0413 use GPIO differently. */ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ outl(0x0, chip->port+GPIO); //outl(0x00f0e000, chip->port+GPIO); /* Analog */ outl(0x005f5301, chip->port+GPIO); /* Analog */ } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ outl(0x0, chip->port+GPIO); //outl(0x00f0e000, chip->port+GPIO); /* Analog */ Loading @@ -1379,7 +1403,19 @@ static int __devinit snd_ca0106_create(struct snd_card *card, outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ int size, n; size = ARRAY_SIZE(i2c_adc_init); //snd_printk("I2C:array size=0x%x\n", size); for (n=0; n < size; n++) { snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); } for (n=0; n < 4; n++) { chip->i2c_capture_volume[n][0]= 0xcf; chip->i2c_capture_volume[n][1]= 0xcf; } chip->i2c_capture_source=2; /* Line in */ //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ } if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ int size, n; Loading sound/pci/ca0106/ca0106_mixer.c +143 −9 Original line number Diff line number Diff line Loading @@ -171,6 +171,62 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, return change; } static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[6] = { "Phone", "Mic", "Line in", "Aux" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item > 3) uinfo->value.enumerated.item = 3; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0; } static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; return 0; } static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int source_id; unsigned int ngain, ogain; int change = 0; 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] ; change = (emu->i2c_capture_source != source_id); if (change) { snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ if (ngain != ogain) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); ngain = emu->i2c_capture_volume[source_id][1]; /* Left */ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */ if (ngain != ogain) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); source = 1 << source_id; snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ emu->i2c_capture_source = source_id; } return change; } static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { Loading Loading @@ -207,16 +263,16 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, if (change) { emu->capture_mic_line_in = val; if (val) { snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ tmp = inl(emu->port+GPIO) & ~0x400; tmp = tmp | 0x400; outl(tmp, emu->port+GPIO); snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); } else { snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ tmp = inl(emu->port+GPIO) & ~0x400; outl(tmp, emu->port+GPIO); snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); } } return change; Loading @@ -225,7 +281,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic/Line in Capture", .name = "Shared Mic/Line in Capture Switch", .info = snd_ca0106_capture_mic_line_in_info, .get = snd_ca0106_capture_mic_line_in_get, .put = snd_ca0106_capture_mic_line_in_put Loading Loading @@ -329,6 +385,63 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, return 1; } static int snd_ca0106_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_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *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_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *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_ca0106_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_ca0106_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 CA_VOLUME(xname,chid,reg) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ Loading @@ -338,6 +451,15 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, .private_value = ((chid) << 8) | (reg) \ } #define I2C_VOLUME(xname,chid) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_ca0106_i2c_volume_info, \ .get = snd_ca0106_i2c_volume_get, \ .put = snd_ca0106_i2c_volume_put, \ .private_value = chid \ } static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { CA_VOLUME("Analog Front Playback Volume", Loading @@ -361,6 +483,11 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { CA_VOLUME("CAPTURE feedback Playback Volume", 1, CAPTURE_CONTROL), I2C_VOLUME("Phone Capture Volume", 0), I2C_VOLUME("Mic Capture Volume", 1), I2C_VOLUME("Line in Capture Volume", 2), I2C_VOLUME("Aux Capture Volume", 3), { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, Loading @@ -378,11 +505,18 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .name = "Digital Capture Source", .info = snd_ca0106_capture_source_info, .get = snd_ca0106_capture_source_get, .put = snd_ca0106_capture_source_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = snd_ca0106_i2c_capture_source_info, .get = snd_ca0106_i2c_capture_source_get, .put = snd_ca0106_i2c_capture_source_put }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), Loading Loading
sound/pci/ca0106/ca0106.h +3 −1 Original line number Diff line number Diff line Loading @@ -537,9 +537,9 @@ #endif #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ Loading Loading @@ -604,6 +604,8 @@ struct snd_ca0106 { u32 spdif_bits[4]; /* s/pdif out setup */ int spdif_enable; int capture_source; int i2c_capture_source; u8 i2c_capture_volume[4][2]; int capture_mic_line_in; struct snd_dma_buffer buffer; Loading
sound/pci/ca0106/ca0106_main.c +40 −4 Original line number Diff line number Diff line Loading @@ -326,6 +326,7 @@ int snd_ca0106_spi_write(struct snd_ca0106 * emu, return 0; } /* The ADC does not support i2c read, so only write is implemented */ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value) Loading @@ -340,6 +341,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, } 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_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ Loading @@ -348,8 +350,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, for (retry = 0; retry < 10; retry++) { /* Send the data to i2c */ tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); //tmp = snd_ca0106_ptr_read(emu, I2C_A, 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_ca0106_ptr_write(emu, I2C_A, 0, tmp); Loading Loading @@ -1200,6 +1203,22 @@ static unsigned int spi_dac_init[] = { 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_LINEIN }, /* ADC Mixer control */ }; static int __devinit snd_ca0106_create(struct snd_card *card, struct pci_dev *pci, struct snd_ca0106 **rchip) Loading Loading @@ -1361,7 +1380,12 @@ static int __devinit snd_ca0106_create(struct snd_card *card, snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ chip->capture_source = 3; /* Set CAPTURE_SOURCE */ if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ if (chip->details->gpio_type == 2) { /* The SB0410 and SB0413 use GPIO differently. */ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ outl(0x0, chip->port+GPIO); //outl(0x00f0e000, chip->port+GPIO); /* Analog */ outl(0x005f5301, chip->port+GPIO); /* Analog */ } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ outl(0x0, chip->port+GPIO); //outl(0x00f0e000, chip->port+GPIO); /* Analog */ Loading @@ -1379,7 +1403,19 @@ static int __devinit snd_ca0106_create(struct snd_card *card, outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ int size, n; size = ARRAY_SIZE(i2c_adc_init); //snd_printk("I2C:array size=0x%x\n", size); for (n=0; n < size; n++) { snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); } for (n=0; n < 4; n++) { chip->i2c_capture_volume[n][0]= 0xcf; chip->i2c_capture_volume[n][1]= 0xcf; } chip->i2c_capture_source=2; /* Line in */ //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ } if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ int size, n; Loading
sound/pci/ca0106/ca0106_mixer.c +143 −9 Original line number Diff line number Diff line Loading @@ -171,6 +171,62 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, return change; } static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[6] = { "Phone", "Mic", "Line in", "Aux" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item > 3) uinfo->value.enumerated.item = 3; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0; } static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; return 0; } static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int source_id; unsigned int ngain, ogain; int change = 0; 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] ; change = (emu->i2c_capture_source != source_id); if (change) { snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ if (ngain != ogain) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); ngain = emu->i2c_capture_volume[source_id][1]; /* Left */ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */ if (ngain != ogain) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); source = 1 << source_id; snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ emu->i2c_capture_source = source_id; } return change; } static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { Loading Loading @@ -207,16 +263,16 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, if (change) { emu->capture_mic_line_in = val; if (val) { snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ tmp = inl(emu->port+GPIO) & ~0x400; tmp = tmp | 0x400; outl(tmp, emu->port+GPIO); snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); } else { snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ tmp = inl(emu->port+GPIO) & ~0x400; outl(tmp, emu->port+GPIO); snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); } } return change; Loading @@ -225,7 +281,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic/Line in Capture", .name = "Shared Mic/Line in Capture Switch", .info = snd_ca0106_capture_mic_line_in_info, .get = snd_ca0106_capture_mic_line_in_get, .put = snd_ca0106_capture_mic_line_in_put Loading Loading @@ -329,6 +385,63 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, return 1; } static int snd_ca0106_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_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *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_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *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_ca0106_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_ca0106_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 CA_VOLUME(xname,chid,reg) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ Loading @@ -338,6 +451,15 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, .private_value = ((chid) << 8) | (reg) \ } #define I2C_VOLUME(xname,chid) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_ca0106_i2c_volume_info, \ .get = snd_ca0106_i2c_volume_get, \ .put = snd_ca0106_i2c_volume_put, \ .private_value = chid \ } static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { CA_VOLUME("Analog Front Playback Volume", Loading @@ -361,6 +483,11 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { CA_VOLUME("CAPTURE feedback Playback Volume", 1, CAPTURE_CONTROL), I2C_VOLUME("Phone Capture Volume", 0), I2C_VOLUME("Mic Capture Volume", 1), I2C_VOLUME("Line in Capture Volume", 2), I2C_VOLUME("Aux Capture Volume", 3), { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, Loading @@ -378,11 +505,18 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .name = "Digital Capture Source", .info = snd_ca0106_capture_source_info, .get = snd_ca0106_capture_source_get, .put = snd_ca0106_capture_source_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = snd_ca0106_i2c_capture_source_info, .get = snd_ca0106_i2c_capture_source_get, .put = snd_ca0106_i2c_capture_source_put }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), Loading