diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -374,6 +374,8 @@ #define AC97_HAS_NO_PC_BEEP (1<<12) /* no PC Beep volume */ #define AC97_HAS_NO_VIDEO (1<<13) /* no Video volume */ #define AC97_HAS_NO_CD (1<<14) /* no CD volume */ +#define AC97_HAS_NO_MIC (1<<15) /* no MIC volume */ +#define AC97_HAS_NO_TONE (1<<16) /* no Tone control */ /* rates indexes */ #define AC97_RATES_FRONT_DAC 0 diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1300,14 +1300,17 @@ static int snd_ac97_mixer_build(ac97_t * } /* build master tone controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) { - for (idx = 0; idx < 2; idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) - return err; - if (ac97->id == AC97_ID_YMF753) { - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= 7 << 16; + if (!(ac97->flags & AC97_HAS_NO_TONE)) { + if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) { + for (idx = 0; idx < 2; idx++) { + if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) + return err; + if (ac97->id == AC97_ID_YMF753) { + kctl->private_value &= ~(0xff << 16); + kctl->private_value |= 7 << 16; + } } + snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f); } snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f); } @@ -1332,11 +1335,13 @@ static int snd_ac97_mixer_build(ac97_t * } /* build MIC controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { - if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0) - return err; - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) - return err; + if (!(ac97->flags & AC97_HAS_NO_MIC)) { + if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { + if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0) + return err; + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) + return err; + } } /* build Line controls */ diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -370,48 +370,226 @@ int patch_yamaha_ymf753(ac97_t * ac97) * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717. */ -int patch_wolfson03(ac97_t * ac97) +static const snd_kcontrol_new_t wm97xx_snd_ac97_controls[] = { +AC97_DOUBLE("Front Mix Vol", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1), +AC97_SINGLE("Front Mix Mute", AC97_WM97XX_FMIXER_VOL, 15, 1, 1), +}; + +int patch_wolfson_wm9703_specific(ac97_t * ac97) { /* This is known to work for the ViewSonic ViewPad 1000 - Randolph Bentson */ + * Randolph Bentson + * WM9703/9707/9708/9717 + */ + int err, i; + + for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808); + return 0; +} - // WM9703/9707/9708/9717 - snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808); - snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x8000); +static struct snd_ac97_build_ops patch_wolfson_wm9703_ops = { + .build_specific = patch_wolfson_wm9703_specific, +}; + +int patch_wolfson03(ac97_t * ac97) +{ + ac97->build_ops = &patch_wolfson_wm9703_ops; return 0; } - -int patch_wolfson04(ac97_t * ac97) + +static const snd_kcontrol_new_t wm9704_snd_ac97_controls[] = { +AC97_DOUBLE("Front Mix Vol", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1), +AC97_SINGLE("Front Mix Mute", AC97_WM97XX_FMIXER_VOL, 15, 1, 1), +AC97_DOUBLE("Rear Mix Vol", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1), +AC97_SINGLE("Rear Mix Mute", AC97_WM9704_RMIXER_VOL, 15, 1, 1), +AC97_DOUBLE("Rear PCM Vol", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1), +AC97_DOUBLE("Surround Vol", AC97_SURROUND_MASTER, 8, 0, 31, 1), +}; + +int patch_wolfson_wm9704_specific(ac97_t * ac97) { - // WM9704M/9704Q - // set front and rear mixer volume - snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808); - snd_ac97_write_cache(ac97, AC97_WM9704_RMIXER_VOL, 0x0808); - - // patch for DVD noise + int err, i; + for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97))) < 0) + return err; + } + /* patch for DVD noise */ snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200); - - // init vol - snd_ac97_write_cache(ac97, AC97_WM9704_RPCM_VOL, 0x0808); - - // set rear surround volume - snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000); return 0; } - + +static struct snd_ac97_build_ops patch_wolfson_wm9704_ops = { + .build_specific = patch_wolfson_wm9704_specific, +}; + +int patch_wolfson04(ac97_t * ac97) +{ + /* WM9704M/9704Q */ + ac97->build_ops = &patch_wolfson_wm9704_ops; + return 0; +} + +int patch_wolfson_wm9705_specific(ac97_t * ac97) +{ + int err, i; + for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, 0x72, 0x0808); + return 0; +} +static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = { + .build_specific = patch_wolfson_wm9705_specific, +}; + int patch_wolfson05(ac97_t * ac97) { - // WM9705, WM9710 - // set front mixer volume - snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808); + /* WM9705, WM9710 */ + ac97->build_ops = &patch_wolfson_wm9705_ops; + return 0; +} + +static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"}; +static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"}; +static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"}; +static const char* wm9711_out3_lrsrc[] = {"Spk Mix", "HP Mix"}; +static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"}; +static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"}; +static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"}; +static const char* wm9711_mic[] = {"Mic1", "Differential", "Mic2", "Stereo"}; +static const char* wm9711_rec_sell[] = {"Mic 1", "NC", "NC", "Spk Mix", "Line L", "HP Mix L", "Phone Mix", "Phone"}; +static const char* wm9711_rec_selr[] = {"Mic 2", "NC", "NC", "Spk Mix", "Line R", "HP Mix R", "Phone Mix", "Phone"}; + +static const struct ac97_enum wm9711_enum[] = { +AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select), +AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix), +AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src), +AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc), +AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc), +AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 2, wm9711_rec_gain), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 6, 2, wm9711_rec_gain), +AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic), +AC97_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9711_rec_sell), +AC97_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9711_rec_selr), +}; + +static const snd_kcontrol_new_t wm9711_snd_ac97_controls[] = { +AC97_SINGLE("ALC Target", AC97_CODEC_CLASS_REV, 12, 15, 0), +AC97_SINGLE("ALC Hold", AC97_CODEC_CLASS_REV, 8, 15, 0), +AC97_SINGLE("ALC Decay", AC97_CODEC_CLASS_REV, 4, 15, 0), +AC97_SINGLE("ALC Attack", AC97_CODEC_CLASS_REV, 0, 15, 0), + +AC97_ENUM("ALC Select", wm9711_enum[0]), +AC97_SINGLE("ALC Max Gain", AC97_PCI_SVID, 11, 7, 1), +AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1), +AC97_SINGLE("ALC ZC", AC97_PCI_SVID, 8, 1, 1), +AC97_SINGLE("ALC NG", AC97_PCI_SVID, 7, 1, 1), +AC97_SINGLE("ALC NG Mute", AC97_PCI_SVID, 5, 1, 1), +AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1), + +AC97_SINGLE("Side Tone Mute", AC97_VIDEO, 15, 1, 1), +AC97_SINGLE("Side Tone Vol", AC97_VIDEO, 12, 7, 1), +AC97_ENUM("ALC HP Mix", wm9711_enum[1]), +AC97_SINGLE("ALC HP Volume", AC97_VIDEO, 7, 7, 1), + +AC97_SINGLE("Out3 Mute", AC97_AUX, 15, 1, 1), +AC97_SINGLE("Out3 ZC", AC97_AUX, 7, 1, 1), +AC97_ENUM("Out3 Source", wm9711_enum[2]), +AC97_ENUM("Out3 LR Source", wm9711_enum[3]), +AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1), + +AC97_SINGLE("Beep to HP Mute", AC97_PC_BEEP, 15, 1, 1), +AC97_SINGLE("Beep to HP Vol", AC97_PC_BEEP, 12, 7, 1), +AC97_SINGLE("Beep to ST Mute", AC97_PC_BEEP, 11, 1, 1), +AC97_SINGLE("Beep to ST Vol", AC97_PC_BEEP, 8, 7, 1), +AC97_SINGLE("Beep to Phone Mute", AC97_PC_BEEP, 7, 1, 1), +AC97_SINGLE("Beep to Phone Vol", AC97_PC_BEEP, 4, 7, 1), + +AC97_SINGLE("AUX DAC to HP Mute", AC97_CD, 15, 1, 1), +AC97_SINGLE("AUX DAC to HP Vol", AC97_CD, 12, 7, 1), +AC97_SINGLE("AUX DAC to ST Mute", AC97_CD, 11, 1, 1), +AC97_SINGLE("AUX DAC to ST Vol", AC97_CD, 8, 7, 1), +AC97_SINGLE("AUX DAC to Phone Mute", AC97_CD, 7, 1, 1), +AC97_SINGLE("AUX DAC to Phone Vol", AC97_CD, 4, 7, 1), + +AC97_SINGLE("Phone to HP Mute", AC97_PHONE, 15, 1, 1), +AC97_SINGLE("Phone to Spk Mute", AC97_PHONE, 14, 1, 1), + +AC97_SINGLE("Line to HP Mute", AC97_LINE, 15, 1, 1), +AC97_SINGLE("Line to Spk Mute", AC97_LINE, 14, 1, 1), +AC97_SINGLE("Line to Phone Mute", AC97_LINE, 13, 1, 1), + +AC97_SINGLE("DAC to HP Mute", AC97_PCM, 15, 1, 1), +AC97_SINGLE("DAC to Spk Mute", AC97_PCM, 14, 1, 1), +AC97_SINGLE("DAC to Phone Mute", AC97_PCM, 13, 1, 1), + +AC97_SINGLE("Rec 20dB Boost", AC97_REC_SEL, 14, 1, 1), +AC97_ENUM("ADC to Phone Mix", wm9711_enum[4]), +AC97_SINGLE("ADC to Phone 20dB Boost", AC97_REC_SEL, 11, 1, 1), +AC97_ENUM("Record Select L", wm9711_enum[9]), +AC97_ENUM("Record Select R", wm9711_enum[10]), + +AC97_SINGLE("3D upper cut-off", AC97_3D_CONTROL, 5, 1, 1), +AC97_SINGLE("3D lower cut-off", AC97_3D_CONTROL, 4, 1, 1), + +AC97_ENUM("Bass Control", wm9711_enum[5]), +AC97_SINGLE("Bass cut-off", AC97_MASTER_TONE, 12, 1, 1), +AC97_SINGLE("Tone cut-off", AC97_MASTER_TONE, 4, 1, 1), +AC97_SINGLE("DAC Attenuate (-6dB)", AC97_MASTER_TONE, 6, 1, 0), + +AC97_SINGLE("Rec Mute", AC97_REC_GAIN, 15, 1, 1), +AC97_ENUM("Rec Gain L Steps", wm9711_enum[6]), +AC97_ENUM("Rec Gain R Steps", wm9711_enum[7]), +AC97_SINGLE("Rec Gain L", AC97_REC_GAIN, 8, 15, 1), +AC97_SINGLE("Rec Gain R", AC97_REC_GAIN, 0, 15, 1), +AC97_SINGLE("Rec ZC", AC97_REC_GAIN, 7, 1, 1), + +AC97_SINGLE("Mic1 to Phone Mute", AC97_MIC, 14, 1, 1), +AC97_SINGLE("Mic2 to Phone Mute", AC97_MIC, 13, 1, 1), +AC97_ENUM("Mic Select (Ext)", wm9711_enum[8]), +AC97_SINGLE("Mic1 Vol", AC97_MIC, 8, 32, 1), +AC97_SINGLE("Mic 20dB Boost", AC97_MIC, 7, 1, 1), + +AC97_SINGLE("Master Vol ZC", AC97_MASTER, 7, 1, 1), +AC97_SINGLE("HP Vol ZC", AC97_HEADPHONE, 7, 1, 1), +AC97_SINGLE("Mono Vol ZC", AC97_MASTER_MONO, 7, 1, 1), +}; + +int patch_wolfson_wm9711_specific(ac97_t * ac97) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808); + snd_ac97_write_cache(ac97, AC97_PCI_SVID, 0x0808); + snd_ac97_write_cache(ac97, AC97_VIDEO, 0x0808); + snd_ac97_write_cache(ac97, AC97_AUX, 0x0808); + snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); + snd_ac97_write_cache(ac97, AC97_CD, 0x0000); return 0; } +static struct snd_ac97_build_ops patch_wolfson_wm9711_ops = { + .build_specific = patch_wolfson_wm9711_specific, +}; + int patch_wolfson11(ac97_t * ac97) { - // WM9711, WM9712 - // set out3 volume - snd_ac97_write_cache(ac97, AC97_WM9711_OUT3VOL, 0x0808); + /* WM9711, WM9712 */ + ac97->build_ops = &patch_wolfson_wm9711_ops; + + ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC | + AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD; + return 0; } @@ -419,6 +597,17 @@ static const char* wm9713_mic_mixer[] = static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; static const char* wm9713_rec_src_l[] = {"Mic1", "Mic2", "Line L", "Mono In", "HP Mix L", "Spk Mix", "Mono Mix", "Zh"}; static const char* wm9713_rec_src_r[] = {"Mic1", "Mic2", "Line R", "Mono In", "HP Mix R", "Spk Mix", "Mono Mix", "Zh"}; +static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"}; +static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"}; +static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"}; +static const char* wm9713_spkl_pga[] = {"Vmid", "Zh", "HP Mix L", "Spk Mix", "Inv 1", "NC", "NC", "NC"}; +static const char* wm9713_spkr_pga[] = {"Vmid", "Zh", "HP Mix R", "Spk Mix", "Inv 2", "NC", "NC", "NC"}; +static const char* wm9713_hpl_pga[] = {"Vmid", "Zh", "HP Mix L", "NC"}; +static const char* wm9713_hpr_pga[] = {"Vmid", "Zh", "HP Mix R", "NC"}; +static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"}; +static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"}; +static const char* wm9713_dac_inv[] = {"Off", "Mono Mix", "Spk Mix", "HP Mix L", "HP Mix R", "HP Mix Mono", "NC", "Vmid"}; +static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"}; static const struct ac97_enum wm9713_enum[] = { AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), @@ -426,85 +615,156 @@ AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm97 AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux), AC97_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src_l), AC97_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src_r), -}; - -static const snd_kcontrol_new_t wm13_snd_ac97_controls_line_in[] = { -AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1), -AC97_SINGLE("Line In to Headphone Mute", AC97_PC_BEEP, 15, 1, 1), -AC97_SINGLE("Line In to Speaker Mute", AC97_PC_BEEP, 14, 1, 1), +AC97_ENUM_SINGLE(AC97_CD, 14, 2, wm9713_rec_gain), +AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spkl_pga), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spkr_pga), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 6, 4, wm9713_hpl_pga), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 4, 4, wm9713_hpr_pga), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), +AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), +AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv), +AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base), +AC97_ENUM_SINGLE(AC97_CD, 6, 2, wm9713_rec_gain), +}; + +static const snd_kcontrol_new_t wm13_snd_ac97_controls[] = { +AC97_SINGLE("Line In Vol L", AC97_PC_BEEP, 8, 31, 0), +AC97_SINGLE("Line In Vol R", AC97_PC_BEEP, 0, 31, 0), +AC97_SINGLE("Line In to HP Mute", AC97_PC_BEEP, 15, 1, 1), +AC97_SINGLE("Line In to Spk Mute", AC97_PC_BEEP, 14, 1, 1), AC97_SINGLE("Line In to Mono Mute", AC97_PC_BEEP, 13, 1, 1), -}; -static const snd_kcontrol_new_t wm13_snd_ac97_controls_dac[] = { -AC97_DOUBLE("DAC Volume", AC97_PHONE, 8, 0, 31, 1), +AC97_SINGLE("DAC Vol L", AC97_PHONE, 8, 31, 1), +AC97_SINGLE("DAC Vol R", AC97_PHONE, 0, 31, 1), AC97_SINGLE("DAC to Headphone Mute", AC97_PHONE, 15, 1, 1), AC97_SINGLE("DAC to Speaker Mute", AC97_PHONE, 14, 1, 1), AC97_SINGLE("DAC to Mono Mute", AC97_PHONE, 13, 1, 1), -}; -static const snd_kcontrol_new_t wm13_snd_ac97_controls_mic[] = { AC97_SINGLE("MICA Volume", AC97_MIC, 8, 31, 1), AC97_SINGLE("MICB Volume", AC97_MIC, 0, 31, 1), AC97_SINGLE("MICA to Mono Mute", AC97_LINE, 7, 1, 1), AC97_SINGLE("MICB to Mono Mute", AC97_LINE, 6, 1, 1), AC97_SINGLE("MIC Boost (+20dB)", AC97_LINE, 5, 1, 1), -AC97_ENUM("MIC Headphone Routing", wm9713_enum[0]), -AC97_SINGLE("MIC Headphone Mixer Volume", AC97_LINE, 0, 7, 1) -}; +AC97_ENUM("MIC HP Routing", wm9713_enum[0]), +AC97_SINGLE("MIC HP Mix Vol", AC97_LINE, 0, 7, 1), -static const snd_kcontrol_new_t wm13_snd_ac97_controls_adc[] = { AC97_SINGLE("ADC Mute", AC97_CD, 15, 1, 1), -AC97_DOUBLE("Gain Step Size (1.5dB/0.75dB)", AC97_CD, 14, 6, 1, 1), -AC97_DOUBLE("ADC Volume",AC97_CD, 8, 0, 15, 0), +AC97_ENUM("Gain Step L", wm9713_enum[5]), +AC97_ENUM("Gain Step R", wm9713_enum[16]), +AC97_SINGLE("ADC Vol L", AC97_CD, 8, 15, 0), +AC97_SINGLE("ADC Vol R", AC97_CD, 0, 15, 0), AC97_SINGLE("ADC Zero Cross", AC97_CD, 7, 1, 1), -}; -static const snd_kcontrol_new_t wm13_snd_ac97_controls_recsel[] = { -AC97_ENUM("Record to Headphone Path", wm9713_enum[1]), -AC97_SINGLE("Record to Headphone Volume", AC97_VIDEO, 11, 7, 0), +AC97_ENUM("Record to HP Mix", wm9713_enum[1]), +AC97_SINGLE("Record to HP Vol", AC97_VIDEO, 11, 7, 1), AC97_ENUM("Record to Mono Path", wm9713_enum[2]), AC97_SINGLE("Record to Mono Boost (+20dB)", AC97_VIDEO, 8, 1, 0), AC97_SINGLE("Record ADC Boost (+20dB)", AC97_VIDEO, 6, 1, 0), AC97_ENUM("Record Select Left", wm9713_enum[3]), AC97_ENUM("Record Select Right", wm9713_enum[4]), + +AC97_SINGLE("ALC Target", AC97_CODEC_CLASS_REV, 12, 15, 0), +AC97_SINGLE("ALC Hold", AC97_CODEC_CLASS_REV, 8, 15, 0), +AC97_SINGLE("ALC Decay", AC97_CODEC_CLASS_REV, 4, 15, 0), +AC97_SINGLE("ALC Attack", AC97_CODEC_CLASS_REV, 0, 15, 0), + +AC97_ENUM("ALC Select", wm9713_enum[6]), +AC97_SINGLE("ALC Max Gain", AC97_PCI_SVID, 11, 7, 0), +AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0), +AC97_SINGLE("ALC ZC", AC97_PCI_SVID, 8, 1, 0), +AC97_SINGLE("ALC NG", AC97_PCI_SVID, 7, 1, 0), +AC97_SINGLE("ALC NG Mute", AC97_PCI_SVID, 5, 1, 1), +AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0), + +AC97_SINGLE("Master Vol ZC Left", AC97_MASTER, 14, 1, 0), +AC97_SINGLE("Master Vol ZC Right", AC97_MASTER, 6, 1, 0), +AC97_SINGLE("HP Vol ZC Left", AC97_HEADPHONE, 14, 1, 0), +AC97_SINGLE("HP Vol ZC Right", AC97_HEADPHONE, 6, 1, 0), +AC97_SINGLE("Out3/4 Vol ZC Left", AC97_MASTER_MONO, 14, 1, 0), +AC97_SINGLE("Out3/4 Vol ZC Right", AC97_MASTER_MONO, 6, 1, 0), +AC97_SINGLE("Master Vol Mute Left", AC97_MASTER, 7, 1, 1), +AC97_SINGLE("HP Vol Mute Left", AC97_HEADPHONE, 7, 1, 1), +AC97_SINGLE("Out3/4 Vol Mute Left", AC97_MASTER_MONO, 7, 1, 1), + +AC97_SINGLE("Mono In to HP Mute", AC97_MASTER_TONE, 15, 1, 1), +AC97_SINGLE("Mono In to Spk Mute", AC97_MASTER_TONE, 14, 1, 1), +AC97_SINGLE("Mono In Vol", AC97_MASTER_TONE, 8, 31, 1), +AC97_SINGLE("Mono Mute", AC97_MASTER_TONE, 7, 1, 1), +AC97_SINGLE("Mono ZC", AC97_MASTER_TONE, 6, 1, 1), +AC97_SINGLE("Mono Vol", AC97_MASTER_TONE, 0, 31, 1), + +AC97_SINGLE("PCBEEP to HP Mute", AC97_AUX, 15, 1, 1), +AC97_SINGLE("PCBEEP to HP Vol", AC97_AUX, 12, 7, 1), +AC97_SINGLE("PCBEEP to Spk Mute", AC97_AUX, 11, 1, 1), +AC97_SINGLE("PCBEEP to Spk Vol", AC97_AUX, 8, 7, 1), +AC97_SINGLE("PCBEEP to Mono Mute", AC97_AUX, 7, 1, 1), +AC97_SINGLE("PCBEEP to Mono Vol", AC97_AUX, 4, 7, 1), + +AC97_SINGLE("Voice to HP Mute", AC97_PCM, 15, 1, 1), +AC97_SINGLE("Voice to HP Vol", AC97_PCM, 12, 7, 1), +AC97_SINGLE("Voice to Spk Mute", AC97_PCM, 11, 1, 1), +AC97_SINGLE("Voice to Spk Vol", AC97_PCM, 8, 7, 1), +AC97_SINGLE("Voice to Mono Mute", AC97_PCM, 7, 1, 1), +AC97_SINGLE("Voice to Mono Vol", AC97_PCM, 4, 7, 1), + +AC97_SINGLE("Aux to HP Mute", AC97_REC_SEL, 15, 1, 1), +AC97_SINGLE("Aux to HP Vol", AC97_REC_SEL, 12, 7, 1), +AC97_SINGLE("Aux to Spk Mute", AC97_REC_SEL, 11, 1, 1), +AC97_SINGLE("Aux to Spk Vol", AC97_REC_SEL, 8, 7, 1), +AC97_SINGLE("Aux to Mono Mute", AC97_REC_SEL, 7, 1, 1), +AC97_SINGLE("Aux to Mono Vol", AC97_REC_SEL, 4, 7, 1), + +AC97_ENUM("Mono Input", wm9713_enum[7]), +AC97_ENUM("Spk L Input", wm9713_enum[8]), +AC97_ENUM("Spk R Input", wm9713_enum[9]), +AC97_ENUM("HP L Input", wm9713_enum[10]), +AC97_ENUM("HP R Input", wm9713_enum[11]), +AC97_ENUM("Out 3 Input", wm9713_enum[12]), +AC97_ENUM("Out 4 Input", wm9713_enum[13]), + +AC97_ENUM("Bass Control", wm9713_enum[15]), +AC97_SINGLE("Bass cut-off", AC97_GENERAL_PURPOSE, 12, 1, 1), +AC97_SINGLE("Tone cut-off", AC97_GENERAL_PURPOSE, 4, 1, 1), +AC97_SINGLE("DAC Attenuate (-6dB)", AC97_GENERAL_PURPOSE, 6, 1, 0), +AC97_SINGLE("Bass Intensity", AC97_GENERAL_PURPOSE, 8, 15, 1), +AC97_SINGLE("Tone Intensity", AC97_GENERAL_PURPOSE, 0, 15, 1), +}; + +static const snd_kcontrol_new_t wm13_snd_ac97_controls_3d[] = { +AC97_ENUM("Inv Input", wm9713_enum[14]), +AC97_SINGLE("3D upper cut-off", AC97_REC_GAIN_MIC, 5, 1, 0), +AC97_SINGLE("3D lower cut-off", AC97_REC_GAIN_MIC, 4, 1, 0), +AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), }; -static int patch_wolfson_wm9713_specific(ac97_t * ac97) +static int patch_wolfson_wm9713_3d (ac97_t * ac97) { int err, i; - - for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_line_in); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_line_in[i], ac97))) < 0) + + for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97))) < 0) return err; } - snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); + return 0; +} + +static int patch_wolfson_wm9713_specific(ac97_t * ac97) +{ + int err, i; - for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_dac); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_dac[i], ac97))) < 0) + for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97))) < 0) return err; } + snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808); - - for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_mic); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_mic[i], ac97))) < 0) - return err; - } snd_ac97_write_cache(ac97, AC97_MIC, 0x0808); snd_ac97_write_cache(ac97, AC97_LINE, 0x00da); - - for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_adc); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_adc[i], ac97))) < 0) - return err; - } snd_ac97_write_cache(ac97, AC97_CD, 0x0808); - - for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_recsel); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_recsel[i], ac97))) < 0) - return err; - } snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612); snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0); - return 0; } @@ -525,6 +785,7 @@ static void patch_wolfson_wm9713_resume static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = { .build_specific = patch_wolfson_wm9713_specific, + .build_3d = patch_wolfson_wm9713_3d, #ifdef CONFIG_PM .suspend = patch_wolfson_wm9713_suspend, .resume = patch_wolfson_wm9713_resume @@ -533,10 +794,11 @@ static struct snd_ac97_build_ops patch_w int patch_wolfson13(ac97_t * ac97) { + /* WM9713, WM9714 */ ac97->build_ops = &patch_wolfson_wm9713_ops; ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE | - AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD; + AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE; snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00); snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);