aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJames Courtier-Dutton <James@superbug.co.uk>2006-12-06 10:58:02 -0500
committerJaroslav Kysela <perex@suse.cz>2007-02-09 03:02:17 -0500
commit184c1e2c4c4221c2b8d1e16c33314595373fa73f (patch)
treef041f147ba8c92e5587163d0b76863fdf4f0318b /sound
parent9ed1261e3e617d99b0eb74041d0337ff664e4f5b (diff)
[ALSA] emu10k1: Add Audio capture support for Audigy 2 ZS Notebook.
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>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c70
-rw-r--r--sound/pci/emu10k1/emumixer.c201
-rw-r--r--sound/pci/emu10k1/io.c59
-rw-r--r--sound/pci/emu10k1/p17v.h47
4 files changed, 370 insertions, 7 deletions
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 711e819e4a0b..80aa585eade4 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -46,6 +46,7 @@
46#include <linux/firmware.h> 46#include <linux/firmware.h>
47#include "p16v.h" 47#include "p16v.h"
48#include "tina2.h" 48#include "tina2.h"
49#include "p17v.h"
49 50
50 51
51/************************************************************************* 52/*************************************************************************
@@ -120,11 +121,28 @@ static unsigned int spi_dac_init[] = {
120 0x0622, 121 0x0622,
121 0x1400, 122 0x1400,
122}; 123};
124
125static unsigned int i2c_adc_init[][2] = {
126 { 0x17, 0x00 }, /* Reset */
127 { 0x07, 0x00 }, /* Timeout */
128 { 0x0b, 0x22 }, /* Interface control */
129 { 0x0c, 0x22 }, /* Master mode control */
130 { 0x0d, 0x08 }, /* Powerdown control */
131 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
132 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
133 { 0x10, 0x7b }, /* ALC Control 1 */
134 { 0x11, 0x00 }, /* ALC Control 2 */
135 { 0x12, 0x32 }, /* ALC Control 3 */
136 { 0x13, 0x00 }, /* Noise gate control */
137 { 0x14, 0xa6 }, /* Limiter control */
138 { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */
139};
123 140
124static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) 141static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
125{ 142{
126 unsigned int silent_page; 143 unsigned int silent_page;
127 int ch; 144 int ch;
145 u32 tmp;
128 146
129 /* disable audio and lock cache */ 147 /* disable audio and lock cache */
130 outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 148 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)
163 181
164 if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ 182 if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
165 /* Hacks for Alice3 to work independent of haP16V driver */ 183 /* Hacks for Alice3 to work independent of haP16V driver */
166 u32 tmp;
167
168 //Setup SRCMulti_I2S SamplingRate 184 //Setup SRCMulti_I2S SamplingRate
169 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); 185 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
170 tmp &= 0xfffff1ff; 186 tmp &= 0xfffff1ff;
@@ -184,8 +200,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
184 } 200 }
185 if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ 201 if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
186 /* Hacks for Alice3 to work independent of haP16V driver */ 202 /* Hacks for Alice3 to work independent of haP16V driver */
187 u32 tmp;
188
189 snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); 203 snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
190 //Setup SRCMulti_I2S SamplingRate 204 //Setup SRCMulti_I2S SamplingRate
191 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); 205 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)
231 outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ 245 outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */
232 246
233 } 247 }
248 if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */
249 int size, n;
250
251 snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f);
252 tmp = inl(emu->port + A_IOCFG);
253 outl(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */
254 tmp = inl(emu->port + A_IOCFG);
255 size = ARRAY_SIZE(i2c_adc_init);
256 for (n = 0; n < size; n++)
257 snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]);
258 for (n=0; n < 4; n++) {
259 emu->i2c_capture_volume[n][0]= 0xcf;
260 emu->i2c_capture_volume[n][1]= 0xcf;
261 }
262
263 }
264
234 265
235 snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr); 266 snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
236 snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ 267 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)
274 if (enable_ir) { /* enable IR for SB Live */ 305 if (enable_ir) { /* enable IR for SB Live */
275 if (emu->card_capabilities->emu1010) { 306 if (emu->card_capabilities->emu1010) {
276 ; /* Disable all access to A_IOCFG for the emu1010 */ 307 ; /* Disable all access to A_IOCFG for the emu1010 */
308 } else if (emu->card_capabilities->i2c_adc) {
309 ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
277 } else if (emu->audigy) { 310 } else if (emu->audigy) {
278 unsigned int reg = inl(emu->port + A_IOCFG); 311 unsigned int reg = inl(emu->port + A_IOCFG);
279 outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); 312 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)
293 326
294 if (emu->card_capabilities->emu1010) { 327 if (emu->card_capabilities->emu1010) {
295 ; /* Disable all access to A_IOCFG for the emu1010 */ 328 ; /* Disable all access to A_IOCFG for the emu1010 */
329 } else if (emu->card_capabilities->i2c_adc) {
330 ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
296 } else if (emu->audigy) { /* enable analog output */ 331 } else if (emu->audigy) { /* enable analog output */
297 unsigned int reg = inl(emu->port + A_IOCFG); 332 unsigned int reg = inl(emu->port + A_IOCFG);
298 outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); 333 outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
@@ -311,6 +346,8 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
311 /* Enable analog/digital outs on audigy */ 346 /* Enable analog/digital outs on audigy */
312 if (emu->card_capabilities->emu1010) { 347 if (emu->card_capabilities->emu1010) {
313 ; /* Disable all access to A_IOCFG for the emu1010 */ 348 ; /* Disable all access to A_IOCFG for the emu1010 */
349 } else if (emu->card_capabilities->i2c_adc) {
350 ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
314 } else if (emu->audigy) { 351 } else if (emu->audigy) {
315 outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); 352 outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
316 353
@@ -1139,10 +1176,11 @@ static struct snd_emu_chip_details emu_chip_details[] = {
1139 .adc_1361t = 1, /* 24 bit capture instead of 16bit */ 1176 .adc_1361t = 1, /* 24 bit capture instead of 16bit */
1140 .ac97_chip = 1} , 1177 .ac97_chip = 1} ,
1141 /* Audigy 2 ZS Notebook Cardbus card.*/ 1178 /* Audigy 2 ZS Notebook Cardbus card.*/
1142 /* Tested by James@superbug.co.uk 22th December 2005 */ 1179 /* Tested by James@superbug.co.uk 6th November 2006 */
1143 /* Audio output 7.1/Headphones working. 1180 /* Audio output 7.1/Headphones working.
1144 * Digital output working. (AC3 not checked, only PCM) 1181 * Digital output working. (AC3 not checked, only PCM)
1145 * Audio inputs not tested. 1182 * Audio Mic/Line inputs working.
1183 * Digital input not tested.
1146 */ 1184 */
1147 /* DSP: Tina2 1185 /* DSP: Tina2
1148 * DAC: Wolfson WM8768/WM8568 1186 * DAC: Wolfson WM8768/WM8568
@@ -1150,6 +1188,25 @@ static struct snd_emu_chip_details emu_chip_details[] = {
1150 * AC97: None 1188 * AC97: None
1151 * CA0151: None 1189 * CA0151: None
1152 */ 1190 */
1191 /* Tested by James@superbug.co.uk 4th April 2006 */
1192 /* A_IOCFG bits
1193 * Output
1194 * 0: Not Used
1195 * 1: 0 = Mute all the 7.1 channel out. 1 = unmute.
1196 * 2: Analog input 0 = line in, 1 = mic in
1197 * 3: Not Used
1198 * 4: Digital output 0 = off, 1 = on.
1199 * 5: Not Used
1200 * 6: Not Used
1201 * 7: Not Used
1202 * Input
1203 * All bits 1 (0x3fxx) means nothing plugged in.
1204 * 8-9: 0 = Line in/Mic, 2 = Optical in, 3 = Nothing.
1205 * A-B: 0 = Headphones, 2 = Optical out, 3 = Nothing.
1206 * C-D: 2 = Front/Rear/etc, 3 = nothing.
1207 * E-F: Always 0
1208 *
1209 */
1153 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, 1210 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
1154 .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", 1211 .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
1155 .id = "Audigy2", 1212 .id = "Audigy2",
@@ -1157,6 +1214,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
1157 .ca0108_chip = 1, 1214 .ca0108_chip = 1,
1158 .ca_cardbus_chip = 1, 1215 .ca_cardbus_chip = 1,
1159 .spi_dac = 1, 1216 .spi_dac = 1,
1217 .i2c_adc = 1,
1160 .spk71 = 1} , 1218 .spk71 = 1} ,
1161 {.vendor = 0x1102, .device = 0x0008, 1219 {.vendor = 0x1102, .device = 0x0008,
1162 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 1220 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 9b7fd564343e..b8221f385ff9 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -36,9 +36,14 @@
36#include <sound/core.h> 36#include <sound/core.h>
37#include <sound/emu10k1.h> 37#include <sound/emu10k1.h>
38#include <linux/delay.h> 38#include <linux/delay.h>
39#include <sound/tlv.h>
40
41#include "p17v.h"
39 42
40#define AC97_ID_STAC9758 0x83847658 43#define AC97_ID_STAC9758 0x83847658
41 44
45static DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
46
42static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 47static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
43{ 48{
44 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 49 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -579,6 +584,162 @@ static struct snd_kcontrol_new snd_emu1010_internal_clock =
579 .put = snd_emu1010_internal_clock_put 584 .put = snd_emu1010_internal_clock_put
580}; 585};
581 586
587static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
588 struct snd_ctl_elem_info *uinfo)
589{
590#if 0
591 static char *texts[4] = {
592 "Unknown1", "Unknown2", "Mic", "Line"
593 };
594#endif
595 static char *texts[2] = {
596 "Mic", "Line"
597 };
598
599 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
600 uinfo->count = 1;
601 uinfo->value.enumerated.items = 2;
602 if (uinfo->value.enumerated.item > 1)
603 uinfo->value.enumerated.item = 1;
604 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
605 return 0;
606}
607
608static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
609 struct snd_ctl_elem_value *ucontrol)
610{
611 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
612
613 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
614 return 0;
615}
616
617static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
618 struct snd_ctl_elem_value *ucontrol)
619{
620 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
621 unsigned int source_id;
622 unsigned int ngain, ogain;
623 u32 gpio;
624 int change = 0;
625 unsigned long flags;
626 u32 source;
627 /* If the capture source has changed,
628 * update the capture volume from the cached value
629 * for the particular source.
630 */
631 source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */
632 change = (emu->i2c_capture_source != source_id);
633 if (change) {
634 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
635 spin_lock_irqsave(&emu->emu_lock, flags);
636 gpio = inl(emu->port + A_IOCFG);
637 if (source_id==0)
638 outl(gpio | 0x4, emu->port + A_IOCFG);
639 else
640 outl(gpio & ~0x4, emu->port + A_IOCFG);
641 spin_unlock_irqrestore(&emu->emu_lock, flags);
642
643 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
644 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
645 if (ngain != ogain)
646 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
647 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
648 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
649 if (ngain != ogain)
650 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
651
652 source = 1 << (source_id + 2);
653 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
654 emu->i2c_capture_source = source_id;
655 }
656 return change;
657}
658
659static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
660{
661 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
662 .name = "Capture Source",
663 .info = snd_audigy_i2c_capture_source_info,
664 .get = snd_audigy_i2c_capture_source_get,
665 .put = snd_audigy_i2c_capture_source_put
666};
667
668static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
669 struct snd_ctl_elem_info *uinfo)
670{
671 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
672 uinfo->count = 2;
673 uinfo->value.integer.min = 0;
674 uinfo->value.integer.max = 255;
675 return 0;
676}
677
678static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
679 struct snd_ctl_elem_value *ucontrol)
680{
681 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
682 int source_id;
683
684 source_id = kcontrol->private_value;
685
686 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
687 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
688 return 0;
689}
690
691static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
692 struct snd_ctl_elem_value *ucontrol)
693{
694 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
695 unsigned int ogain;
696 unsigned int ngain;
697 int source_id;
698 int change = 0;
699
700 source_id = kcontrol->private_value;
701 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
702 ngain = ucontrol->value.integer.value[0];
703 if (ngain > 0xff)
704 return 0;
705 if (ogain != ngain) {
706 if (emu->i2c_capture_source == source_id)
707 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
708 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
709 change = 1;
710 }
711 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
712 ngain = ucontrol->value.integer.value[1];
713 if (ngain > 0xff)
714 return 0;
715 if (ogain != ngain) {
716 if (emu->i2c_capture_source == source_id)
717 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
718 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
719 change = 1;
720 }
721
722 return change;
723}
724
725#define I2C_VOLUME(xname,chid) \
726{ \
727 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
728 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
729 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
730 .info = snd_audigy_i2c_volume_info, \
731 .get = snd_audigy_i2c_volume_get, \
732 .put = snd_audigy_i2c_volume_put, \
733 .tlv = { .p = snd_audigy_db_scale2 }, \
734 .private_value = chid \
735}
736
737
738static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
739 I2C_VOLUME("Mic Capture Volume", 0),
740 I2C_VOLUME("Line Capture Volume", 0)
741};
742
582#if 0 743#if 0
583static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 744static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
584{ 745{
@@ -1179,7 +1340,9 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1179 int change = 0; 1340 int change = 0;
1180 1341
1181 spin_lock_irqsave(&emu->reg_lock, flags); 1342 spin_lock_irqsave(&emu->reg_lock, flags);
1182 if (emu->audigy) { 1343 if ( emu->card_capabilities->i2c_adc) {
1344 /* Do nothing for Audigy 2 ZS Notebook */
1345 } else if (emu->audigy) {
1183 reg = inl(emu->port + A_IOCFG); 1346 reg = inl(emu->port + A_IOCFG);
1184 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0; 1347 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1185 change = (reg & A_IOCFG_GPOUT0) != val; 1348 change = (reg & A_IOCFG_GPOUT0) != val;
@@ -1317,6 +1480,22 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1317 "AMic Playback Volume", "Mic Playback Volume", 1480 "AMic Playback Volume", "Mic Playback Volume",
1318 NULL 1481 NULL
1319 }; 1482 };
1483 static char *audigy_rename_ctls_i2c_adc[] = {
1484 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1485 "Line Capture Volume", "Analog Mix Capture Volume",
1486 "Wave Playback Volume", "OLD PCM Playback Volume",
1487 "Wave Master Playback Volume", "Master Playback Volume",
1488 "AMic Playback Volume", "Old Mic Playback Volume",
1489 NULL
1490 };
1491 static char *audigy_remove_ctls_i2c_adc[] = {
1492 /* On the Audigy2 ZS Notebook
1493 * Capture via WM8775 */
1494 "Mic Capture Volume",
1495 "Analog Mix Capture Volume",
1496 "Aux Capture Volume",
1497 NULL
1498 };
1320 static char *audigy_remove_ctls_1361t_adc[] = { 1499 static char *audigy_remove_ctls_1361t_adc[] = {
1321 /* On the Audigy2 the AC97 playback is piped into 1500 /* On the Audigy2 the AC97 playback is piped into
1322 * the Philips ADC for 24bit capture */ 1501 * the Philips ADC for 24bit capture */
@@ -1409,6 +1588,10 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1409 } 1588 }
1410 for (; *c; c++) 1589 for (; *c; c++)
1411 remove_ctl(card, *c); 1590 remove_ctl(card, *c);
1591 } else if (emu->card_capabilities->i2c_adc) {
1592 c = audigy_remove_ctls_i2c_adc;
1593 for (; *c; c++)
1594 remove_ctl(card, *c);
1412 } else { 1595 } else {
1413 no_ac97: 1596 no_ac97:
1414 if (emu->card_capabilities->ecard) 1597 if (emu->card_capabilities->ecard)
@@ -1422,6 +1605,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1422 if (emu->audigy) 1605 if (emu->audigy)
1423 if (emu->card_capabilities->adc_1361t) 1606 if (emu->card_capabilities->adc_1361t)
1424 c = audigy_rename_ctls_1361t_adc; 1607 c = audigy_rename_ctls_1361t_adc;
1608 else if (emu->card_capabilities->i2c_adc)
1609 c = audigy_rename_ctls_i2c_adc;
1425 else 1610 else
1426 c = audigy_rename_ctls; 1611 c = audigy_rename_ctls;
1427 else 1612 else
@@ -1584,6 +1769,20 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1584 if (err < 0) 1769 if (err < 0)
1585 return err; 1770 return err;
1586 } 1771 }
1772
1773 if ( emu->card_capabilities->i2c_adc) {
1774 int i;
1775
1776 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1777 if (err < 0)
1778 return err;
1779
1780 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1781 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1782 if (err < 0)
1783 return err;
1784 }
1785 }
1587 1786
1588 return 0; 1787 return 0;
1589} 1788}
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 27ab7d1788a0..116e1c8d9361 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -30,6 +30,7 @@
30#include <sound/core.h> 30#include <sound/core.h>
31#include <sound/emu10k1.h> 31#include <sound/emu10k1.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include "p17v.h"
33 34
34unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) 35unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
35{ 36{
@@ -167,6 +168,64 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
167 return 0; 168 return 0;
168} 169}
169 170
171/* The ADC does not support i2c read, so only write is implemented */
172int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
173 u32 reg,
174 u32 value)
175{
176 u32 tmp;
177 int timeout = 0;
178 int status;
179 int retry;
180 if ((reg > 0x7f) || (value > 0x1ff)) {
181 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
182 return -EINVAL;
183 }
184
185 tmp = reg << 25 | value << 16;
186 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
187 /* Not sure what this I2C channel controls. */
188 /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */
189
190 /* This controls the I2C connected to the WM8775 ADC Codec */
191 snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
192 tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
193
194 for (retry = 0; retry < 10; retry++) {
195 /* Send the data to i2c */
196 //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0);
197 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
198 tmp = 0;
199 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
200 snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
201
202 /* Wait till the transaction ends */
203 while (1) {
204 udelay(10);
205 status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
206 // snd_printk("I2C:status=0x%x\n", status);
207 timeout++;
208 if ((status & I2C_A_ADC_START) == 0)
209 break;
210
211 if (timeout > 1000) {
212 snd_printk("emu10k1:I2C:timeout status=0x%x\n", status);
213 break;
214 }
215 }
216 //Read back and see if the transaction is successful
217 if ((status & I2C_A_ADC_ABORT) == 0)
218 break;
219 }
220
221 if (retry == 10) {
222 snd_printk(KERN_ERR "Writing to ADC failed!\n");
223 return -EINVAL;
224 }
225
226 return 0;
227}
228
170int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value) 229int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
171{ 230{
172 if (reg < 0 || reg > 0x3f) 231 if (reg < 0 || reg > 0x3f)
diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h
index 7ddb5be632cf..4ef5f68a9cd0 100644
--- a/sound/pci/emu10k1/p17v.h
+++ b/sound/pci/emu10k1/p17v.h
@@ -43,6 +43,53 @@
43#define P17V_I2C_ADDR 0x3d /* I2C Address */ 43#define P17V_I2C_ADDR 0x3d /* I2C Address */
44#define P17V_I2C_0 0x3e /* I2C Data */ 44#define P17V_I2C_0 0x3e /* I2C Data */
45#define P17V_I2C_1 0x3f /* I2C Data */ 45#define P17V_I2C_1 0x3f /* I2C Data */
46/* I2C values */
47#define I2C_A_ADC_ADD_MASK 0x000000fe /*The address is a 7 bit address */
48#define I2C_A_ADC_RW_MASK 0x00000001 /*bit mask for R/W */
49#define I2C_A_ADC_TRANS_MASK 0x00000010 /*Bit mask for I2c address DAC value */
50#define I2C_A_ADC_ABORT_MASK 0x00000020 /*Bit mask for I2C transaction abort flag */
51#define I2C_A_ADC_LAST_MASK 0x00000040 /*Bit mask for Last word transaction */
52#define I2C_A_ADC_BYTE_MASK 0x00000080 /*Bit mask for Byte Mode */
53
54#define I2C_A_ADC_ADD 0x00000034 /*This is the Device address for ADC */
55#define I2C_A_ADC_READ 0x00000001 /*To perform a read operation */
56#define I2C_A_ADC_START 0x00000100 /*Start I2C transaction */
57#define I2C_A_ADC_ABORT 0x00000200 /*I2C transaction abort */
58#define I2C_A_ADC_LAST 0x00000400 /*I2C last transaction */
59#define I2C_A_ADC_BYTE 0x00000800 /*I2C one byte mode */
60
61#define I2C_D_ADC_REG_MASK 0xfe000000 /*ADC address register */
62#define I2C_D_ADC_DAT_MASK 0x01ff0000 /*ADC data register */
63
64#define ADC_TIMEOUT 0x00000007 /*ADC Timeout Clock Disable */
65#define ADC_IFC_CTRL 0x0000000b /*ADC Interface Control */
66#define ADC_MASTER 0x0000000c /*ADC Master Mode Control */
67#define ADC_POWER 0x0000000d /*ADC PowerDown Control */
68#define ADC_ATTEN_ADCL 0x0000000e /*ADC Attenuation ADCL */
69#define ADC_ATTEN_ADCR 0x0000000f /*ADC Attenuation ADCR */
70#define ADC_ALC_CTRL1 0x00000010 /*ADC ALC Control 1 */
71#define ADC_ALC_CTRL2 0x00000011 /*ADC ALC Control 2 */
72#define ADC_ALC_CTRL3 0x00000012 /*ADC ALC Control 3 */
73#define ADC_NOISE_CTRL 0x00000013 /*ADC Noise Gate Control */
74#define ADC_LIMIT_CTRL 0x00000014 /*ADC Limiter Control */
75#define ADC_MUX 0x00000015 /*ADC Mux offset */
76#if 0
77/* FIXME: Not tested yet. */
78#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain
79#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB
80#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute
81#define ADC_MUTE 0x000000c0 //Value to mute ADC
82#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select
83#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock
84#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter
85#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window
86#endif
87
88#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux
89#define ADC_MUX_0 0x00000001 //Value to select Unknown at ADC Mux (Not used)
90#define ADC_MUX_1 0x00000002 //Value to select Unknown at ADC Mux (Not used)
91#define ADC_MUX_2 0x00000004 //Value to select Mic at ADC Mux
92#define ADC_MUX_3 0x00000008 //Value to select Line-In at ADC Mux
46 93
47#define P17V_START_AUDIO 0x40 /* Start Audio bit */ 94#define P17V_START_AUDIO 0x40 /* Start Audio bit */
48/* 41 - 47: Reserved */ 95/* 41 - 47: Reserved */