From ac9ef6cf9196107115930e9fc66207199ef395b3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Jan 2012 12:08:44 +0100 Subject: ALSA: hda - Use bint for enable_msi option The new bint module option type suits well with this one. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fb35474c1203..9cbde2fc7b17 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -94,7 +94,7 @@ MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); module_param(single_cmd, bool, 0444); MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " "(for debugging only)."); -module_param(enable_msi, int, 0444); +module_param(enable_msi, bint, 0444); MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); #ifdef CONFIG_SND_HDA_PATCH_LOADER module_param_array(patch, charp, NULL, 0444); -- cgit v1.2.3 From 7bfe059e38b06a0d813d92b9b3e500455f6a2c99 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Jan 2012 17:53:39 +0100 Subject: ALSA: hda - explicitly set buffer-align flag for Nvidia controllers It turned out that Nvidial (HDMI) controllers require the buffer alignment. Thus it's better to mark it requiring the alignment, so that we can switch to non-aligned behavior as default in future. Also, change the module paramter to be bint, in order to let user overriding the default value. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fa4442e8e1a4..d3bd3e748067 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -121,8 +121,8 @@ module_param(power_save_controller, bool, 0644); MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); #endif -static bool align_buffer_size = 1; -module_param(align_buffer_size, bool, 0644); +static int align_buffer_size = -1; +module_param(align_buffer_size, bint, 0644); MODULE_PARM_DESC(align_buffer_size, "Force buffer and period sizes to be multiple of 128 bytes."); @@ -515,6 +515,7 @@ enum { #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ +#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -527,7 +528,8 @@ enum { /* quirks for Nvidia */ #define AZX_DCAPS_PRESET_NVIDIA \ - (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI) + (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\ + AZX_DCAPS_ALIGN_BUFSIZE) static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_ICH] = "HDA Intel", @@ -2774,9 +2776,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } /* disable buffer size rounding to 128-byte multiples if supported */ - chip->align_buffer_size = align_buffer_size; - if (chip->driver_caps & AZX_DCAPS_BUFSIZE) - chip->align_buffer_size = 0; + if (align_buffer_size >= 0) + chip->align_buffer_size = !!align_buffer_size; + else { + if (chip->driver_caps & AZX_DCAPS_BUFSIZE) + chip->align_buffer_size = 0; + else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE) + chip->align_buffer_size = 1; + else + chip->align_buffer_size = 1; + } /* allow 64bit DMA address if supported by H/W */ if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) -- cgit v1.2.3 From 4f2864a49bf058184e85c9f5a2f4578f11992c7d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jan 2012 11:54:19 +0100 Subject: ALSA: hda - Enable sync_write and reset for Conexant codecs This is an attempt to fix S3-resume problems reported for a few laptops with different Conexant codecs. They show the communication stalls at some time in S3, and the driver falls back into the single-cmd mode. This leads to the silent output or the lack of auto-mute feature. As a workaround, here enables the sync_write and the bus-reset flags to make the communication more stable. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=740115 Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=738397 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a7a5733aa4d2..117ae4c22be0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -4414,6 +4414,18 @@ static int patch_conexant_auto(struct hda_codec *codec) codec->patch_ops = cx_auto_patch_ops; if (spec->beep_amp) snd_hda_attach_beep_device(codec, spec->beep_amp); + + /* Some laptops with Conexant chips show stalls in S3 resume, + * which falls into the single-cmd mode. + * Better to make reset, then. + */ + if (!codec->bus->sync_write) { + snd_printd("hda_codec: " + "Enable sync_write for stable communication\n"); + codec->bus->sync_write = 1; + codec->bus->allow_bus_reset = 1; + } + return 0; } -- cgit v1.2.3 From 356268bde2efc8aa36364d3f3113a7cf92e079a8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Feb 2012 10:18:48 +0100 Subject: ALSA: hda - Remove fallback to model=ideapad for Lenovo with cx5066 The Lenovo laptops with cx5066 chips seem to work better with model=auto. Let's get rid of the fallback to the wrong model. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=738397 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 117ae4c22be0..0eb526c672bd 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3034,7 +3034,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), - SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), {} }; -- cgit v1.2.3 From 9322ca549771f2e84a93ac3f509ade1e4c3cdb35 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Feb 2012 14:28:01 +0100 Subject: ALSA: hda - Add suffix argument to snd_hda_add_vmaster() In most cases, the slave strings for vmaster are identical between volumes and switches except for "xxx Volume" and "xxx Switch" suffix. Now snd_hda_add_vmaster() takes the optional suffix argument so that each string can be composed with the given suffix, and we can share the slave name strings in both volume and switch calls nicely. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 22 ++++++++++---- sound/pci/hda/hda_local.h | 3 +- sound/pci/hda/patch_analog.c | 66 +++++++++--------------------------------- sound/pci/hda/patch_conexant.c | 23 ++++----------- sound/pci/hda/patch_realtek.c | 40 +++++-------------------- sound/pci/hda/patch_sigmatel.c | 29 +++++-------------- sound/pci/hda/patch_via.c | 28 +++++------------- 7 files changed, 59 insertions(+), 152 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c2c65f63bf06..8a2f9dddbf0a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2300,7 +2300,7 @@ typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); /* apply the function to all matching slave ctls in the mixer list */ static int map_slaves(struct hda_codec *codec, const char * const *slaves, - map_slave_func_t func, void *data) + const char *suffix, map_slave_func_t func, void *data) { struct hda_nid_item *items; const char * const *s; @@ -2313,7 +2313,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) continue; for (s = slaves; *s; s++) { - if (!strcmp(sctl->id.name, *s)) { + char tmpname[sizeof(sctl->id.name)]; + const char *name = *s; + if (suffix) { + snprintf(tmpname, sizeof(tmpname), "%s %s", + name, suffix); + name = tmpname; + } + printk("XXX comparing %s vs %s\n", sctl->id.name, name); + if (!strcmp(sctl->id.name, name)) { err = func(data, sctl); if (err) return err; @@ -2335,6 +2343,7 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) * @name: vmaster control name * @tlv: TLV data (optional) * @slaves: slave control names (optional) + * @suffix: suffix string to each slave name (optional) * * Create a virtual master control with the given name. The TLV data * must be either NULL or a valid data. @@ -2346,12 +2355,13 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) * This function returns zero if successful or a negative error code. */ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, - unsigned int *tlv, const char * const *slaves) + unsigned int *tlv, const char * const *slaves, + const char *suffix) { struct snd_kcontrol *kctl; int err; - err = map_slaves(codec, slaves, check_slave_present, NULL); + err = map_slaves(codec, slaves, suffix, check_slave_present, NULL); if (err != 1) { snd_printdd("No slave found for %s\n", name); return 0; @@ -2363,8 +2373,8 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, if (err < 0) return err; - err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, - kctl); + err = map_slaves(codec, slaves, suffix, + (map_slave_func_t)snd_ctl_add_slave, kctl); if (err < 0) return err; return 0; diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index aca8d3193b95..6094dea82bc3 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -140,7 +140,8 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, const char *name); int snd_hda_add_vmaster(struct hda_codec *codec, char *name, - unsigned int *tlv, const char * const *slaves); + unsigned int *tlv, const char * const *slaves, + const char *suffix); int snd_hda_codec_reset(struct hda_codec *codec); /* amp value bits */ diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 9cb14b42dfff..9771b0702455 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -137,51 +137,17 @@ static int ad198x_init(struct hda_codec *codec) return 0; } -static const char * const ad_slave_vols[] = { - "Front Playback Volume", - "Surround Playback Volume", - "Center Playback Volume", - "LFE Playback Volume", - "Side Playback Volume", - "Headphone Playback Volume", - "Mono Playback Volume", - "Speaker Playback Volume", - "IEC958 Playback Volume", +static const char * const ad_slave_pfxs[] = { + "Front", "Surround", "Center", "LFE", "Side", + "Headphone", "Mono", "Speaker", "IEC958", NULL }; -static const char * const ad_slave_sws[] = { - "Front Playback Switch", - "Surround Playback Switch", - "Center Playback Switch", - "LFE Playback Switch", - "Side Playback Switch", - "Headphone Playback Switch", - "Mono Playback Switch", - "Speaker Playback Switch", - "IEC958 Playback Switch", +static const char * const ad1988_6stack_fp_slave_pfxs[] = { + "Front", "Surround", "Center", "LFE", "Side", "IEC958", NULL }; -static const char * const ad1988_6stack_fp_slave_vols[] = { - "Front Playback Volume", - "Surround Playback Volume", - "Center Playback Volume", - "LFE Playback Volume", - "Side Playback Volume", - "IEC958 Playback Volume", - NULL -}; - -static const char * const ad1988_6stack_fp_slave_sws[] = { - "Front Playback Switch", - "Surround Playback Switch", - "Center Playback Switch", - "LFE Playback Switch", - "Side Playback Switch", - "IEC958 Playback Switch", - NULL -}; static void ad198x_free_kctls(struct hda_codec *codec); #ifdef CONFIG_SND_HDA_INPUT_BEEP @@ -260,7 +226,8 @@ static int ad198x_build_controls(struct hda_codec *codec) err = snd_hda_add_vmaster(codec, "Master Playback Volume", vmaster_tlv, (spec->slave_vols ? - spec->slave_vols : ad_slave_vols)); + spec->slave_vols : ad_slave_pfxs), + "Playback Volume"); if (err < 0) return err; } @@ -268,7 +235,8 @@ static int ad198x_build_controls(struct hda_codec *codec) err = snd_hda_add_vmaster(codec, "Master Playback Switch", NULL, (spec->slave_sws ? - spec->slave_sws : ad_slave_sws)); + spec->slave_sws : ad_slave_pfxs), + "Playback Switch"); if (err < 0) return err; } @@ -3385,8 +3353,8 @@ static int patch_ad1988(struct hda_codec *codec) if (spec->autocfg.hp_pins[0]) { spec->mixers[spec->num_mixers++] = ad1988_hp_mixers; - spec->slave_vols = ad1988_6stack_fp_slave_vols; - spec->slave_sws = ad1988_6stack_fp_slave_sws; + spec->slave_vols = ad1988_6stack_fp_slave_pfxs; + spec->slave_sws = ad1988_6stack_fp_slave_pfxs; spec->alt_dac_nid = ad1988_alt_dac_nid; spec->stream_analog_alt_playback = &ad198x_pcm_analog_alt_playback; @@ -3594,16 +3562,8 @@ static const struct hda_amp_list ad1884_loopbacks[] = { #endif static const char * const ad1884_slave_vols[] = { - "PCM Playback Volume", - "Mic Playback Volume", - "Mono Playback Volume", - "Front Mic Playback Volume", - "Mic Playback Volume", - "CD Playback Volume", - "Internal Mic Playback Volume", - "Docking Mic Playback Volume", - /* "Beep Playback Volume", */ - "IEC958 Playback Volume", + "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", + "Internal Mic", "Docking Mic", /* "Beep", */ "IEC958", NULL }; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 0eb526c672bd..266e5a68bafa 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -465,21 +465,8 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = { }; #endif -static const char * const slave_vols[] = { - "Headphone Playback Volume", - "Speaker Playback Volume", - "Front Playback Volume", - "Surround Playback Volume", - "CLFE Playback Volume", - NULL -}; - -static const char * const slave_sws[] = { - "Headphone Playback Switch", - "Speaker Playback Switch", - "Front Playback Switch", - "Surround Playback Switch", - "CLFE Playback Switch", +static const char * const slave_pfxs[] = { + "Headphone", "Speaker", "Front", "Surround", "CLFE", NULL }; @@ -519,14 +506,16 @@ static int conexant_build_controls(struct hda_codec *codec) snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, HDA_OUTPUT, vmaster_tlv); err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, slave_vols); + vmaster_tlv, slave_pfxs, + "Playback Volume"); if (err < 0) return err; } if (spec->vmaster_nid && !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, slave_sws); + NULL, slave_pfxs, + "Playback Switch"); if (err < 0) return err; } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 33b6077fcdb8..42f18449b82a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1845,36 +1845,10 @@ DEFINE_CAPMIX_NOSRC(3); /* * slave controls for virtual master */ -static const char * const alc_slave_vols[] = { - "Front Playback Volume", - "Surround Playback Volume", - "Center Playback Volume", - "LFE Playback Volume", - "Side Playback Volume", - "Headphone Playback Volume", - "Speaker Playback Volume", - "Mono Playback Volume", - "Line-Out Playback Volume", - "CLFE Playback Volume", - "Bass Speaker Playback Volume", - "PCM Playback Volume", - NULL, -}; - -static const char * const alc_slave_sws[] = { - "Front Playback Switch", - "Surround Playback Switch", - "Center Playback Switch", - "LFE Playback Switch", - "Side Playback Switch", - "Headphone Playback Switch", - "Speaker Playback Switch", - "Mono Playback Switch", - "IEC958 Playback Switch", - "Line-Out Playback Switch", - "CLFE Playback Switch", - "Bass Speaker Playback Switch", - "PCM Playback Switch", +static const char * const alc_slave_pfxs[] = { + "Front", "Surround", "Center", "LFE", "Side", + "Headphone", "Speaker", "Mono", "Line-Out", + "CLFE", "Bass Speaker", "PCM", NULL, }; @@ -1965,14 +1939,16 @@ static int __alc_build_controls(struct hda_codec *codec) snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, HDA_OUTPUT, vmaster_tlv); err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, alc_slave_vols); + vmaster_tlv, alc_slave_pfxs, + "Playback Volume"); if (err < 0) return err; } if (!spec->no_analog && !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, alc_slave_sws); + NULL, alc_slave_pfxs, + "Playback Switch"); if (err < 0) return err; } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 948f0be2f4f3..de7166a65f8b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1060,26 +1060,9 @@ static struct snd_kcontrol_new stac_smux_mixer = { .put = stac92xx_smux_enum_put, }; -static const char * const slave_vols[] = { - "Front Playback Volume", - "Surround Playback Volume", - "Center Playback Volume", - "LFE Playback Volume", - "Side Playback Volume", - "Headphone Playback Volume", - "Speaker Playback Volume", - NULL -}; - -static const char * const slave_sws[] = { - "Front Playback Switch", - "Surround Playback Switch", - "Center Playback Switch", - "LFE Playback Switch", - "Side Playback Switch", - "Headphone Playback Switch", - "Speaker Playback Switch", - "IEC958 Playback Switch", +static const char * const slave_pfxs[] = { + "Front", "Surround", "Center", "LFE", "Side", + "Headphone", "Speaker", "IEC958", NULL }; @@ -1153,13 +1136,15 @@ static int stac92xx_build_controls(struct hda_codec *codec) /* minimum value is actually mute */ vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, slave_vols); + vmaster_tlv, slave_pfxs, + "Playback Volume"); if (err < 0) return err; } if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, slave_sws); + NULL, slave_pfxs, + "Playback Switch"); if (err < 0) return err; } diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 284e311040fe..e5842fe1b1e8 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1442,25 +1442,9 @@ static const struct hda_pcm_stream via_pcm_digital_capture = { /* * slave controls for virtual master */ -static const char * const via_slave_vols[] = { - "Front Playback Volume", - "Surround Playback Volume", - "Center Playback Volume", - "LFE Playback Volume", - "Side Playback Volume", - "Headphone Playback Volume", - "Speaker Playback Volume", - NULL, -}; - -static const char * const via_slave_sws[] = { - "Front Playback Switch", - "Surround Playback Switch", - "Center Playback Switch", - "LFE Playback Switch", - "Side Playback Switch", - "Headphone Playback Switch", - "Speaker Playback Switch", +static const char * const via_slave_pfxs[] = { + "Front", "Surround", "Center", "LFE", "Side", + "Headphone", "Speaker", NULL, }; @@ -1505,13 +1489,15 @@ static int via_build_controls(struct hda_codec *codec) snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], HDA_OUTPUT, vmaster_tlv); err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, via_slave_vols); + vmaster_tlv, via_slave_pfxs, + "Playback Volume"); if (err < 0) return err; } if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, via_slave_sws); + NULL, via_slave_pfxs, + "Playback Switch"); if (err < 0) return err; } -- cgit v1.2.3 From fc9e5c6f42f4706dfb9f06f369ddd81f38b0a3fa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 6 Feb 2012 14:46:01 +0100 Subject: ALSA: hda - Remove a debug print in vmaster code Wrongly slipped in from the commit 9322ca54. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8a2f9dddbf0a..65c01798d843 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2320,7 +2320,6 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, name, suffix); name = tmpname; } - printk("XXX comparing %s vs %s\n", sctl->id.name, name); if (!strcmp(sctl->id.name, name)) { err = func(data, sctl); if (err) -- cgit v1.2.3 From 8bc039a1e15a72da8426b84293723fb7181f0b5e Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Mon, 23 Jan 2012 16:24:31 -0800 Subject: ALSA: hda - Add Lynx Point HD Audio Controller DeviceIDs This patch adds the HD Audio DeviceIDs for the Intel Lynx Point PCH. Signed-off-by: Seth Heasley Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d3bd3e748067..e354c1616541 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -148,6 +148,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, PCH}," "{Intel, CPT}," "{Intel, PPT}," + "{Intel, LPT}," "{Intel, PBG}," "{Intel, SCH}," "{ATI, SB450}," @@ -3001,6 +3002,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE}, + /* Lynx Point */ + { PCI_DEVICE(0x8086, 0x8c20), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | + AZX_DCAPS_BUFSIZE}, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | -- cgit v1.2.3 From a9c74173f4be2a536ef8d8c88642e41527f2d8b4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Feb 2012 11:41:42 +0100 Subject: ALSA: hda - Make is_jack_detectable() as non-inlined It's a bit too big and used too often as an inline function. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_jack.c | 14 ++++++++++++++ sound/pci/hda/hda_jack.h | 13 +------------ 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 9d819c4b4923..ac7e57c40398 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -19,6 +19,20 @@ #include "hda_local.h" #include "hda_jack.h" +bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) +{ + if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) + return false; + if (!codec->ignore_misc_bit && + (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & + AC_DEFCFG_MISC_NO_PRESENCE)) + return false; + if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) + return false; + return true; +} +EXPORT_SYMBOL_HDA(is_jack_detectable); + /* execute pin sense measurement */ static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) { diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index f8f97c71c9c1..c66655cf413a 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -62,18 +62,7 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); -static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) -{ - if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) - return false; - if (!codec->ignore_misc_bit && - (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & - AC_DEFCFG_MISC_NO_PRESENCE)) - return false; - if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) - return false; - return true; -} +bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, const char *name, int idx); -- cgit v1.2.3 From 71b1e9e43d5199f57c109e20c0f4dffc5c048130 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Feb 2012 11:55:02 +0100 Subject: ALSA: hda - Add codec->no_jack_detect flag Add a new flag to indicate that the codec has no jack-detection cap. This flag should be set for hardwares that have no jack-detect implementation although the codec chip itself supports it. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.h | 1 + sound/pci/hda/hda_jack.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index e9f71dc0d464..654d2e41e25d 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -852,6 +852,7 @@ struct hda_codec { unsigned int pins_shutup:1; /* pins are shut up */ unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ + unsigned int no_jack_detect:1; /* Machine has no jack-detection */ #ifdef CONFIG_SND_HDA_POWER_SAVE unsigned int power_on :1; /* current (global) power-state */ unsigned int power_transition :1; /* power-state in transition */ diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index ac7e57c40398..d68948499fbc 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -21,6 +21,8 @@ bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) { + if (codec->no_jack_detect) + return false; if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) return false; if (!codec->ignore_misc_bit && -- cgit v1.2.3 From e652f4c861fb7f1f59ff0828db0d85578471932d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Feb 2012 11:56:25 +0100 Subject: ALSA: hda - Suppress auto-mute feature on some machines with ALC861 A few machines with ALC861 & co are reported not to work properly with the auto-mute feature in software. The auto-mute feature is implemented in the hardware level, and the jack-detection never works with them. Also, rename the fixup index as ALC861_FIXUP_* to follow the standard. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4a2a49fd92a5..c6305984816c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5563,8 +5563,10 @@ static const struct hda_amp_list alc861_loopbacks[] = { /* Pin config fixes */ enum { - PINFIX_FSC_AMILO_PI1505, - PINFIX_ASUS_A6RP, + ALC861_FIXUP_FSC_AMILO_PI1505, + ALC861_FIXUP_AMP_VREF_0F, + ALC861_FIXUP_NO_JACK_DETECT, + ALC861_FIXUP_ASUS_A6RP, }; /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ @@ -5586,8 +5588,16 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, spec->keep_vref_in_automute = 1; } +/* suppress the jack-detection */ +static void alc_fixup_no_jack_detect(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + if (action == ALC_FIXUP_ACT_PRE_PROBE) + codec->no_jack_detect = 1; +} + static const struct alc_fixup alc861_fixups[] = { - [PINFIX_FSC_AMILO_PI1505] = { + [ALC861_FIXUP_FSC_AMILO_PI1505] = { .type = ALC_FIXUP_PINS, .v.pins = (const struct alc_pincfg[]) { { 0x0b, 0x0221101f }, /* HP */ @@ -5595,17 +5605,29 @@ static const struct alc_fixup alc861_fixups[] = { { } } }, - [PINFIX_ASUS_A6RP] = { + [ALC861_FIXUP_AMP_VREF_0F] = { .type = ALC_FIXUP_FUNC, .v.func = alc861_fixup_asus_amp_vref_0f, }, + [ALC861_FIXUP_NO_JACK_DETECT] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc_fixup_no_jack_detect, + }, + [ALC861_FIXUP_ASUS_A6RP] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc861_fixup_asus_amp_vref_0f, + .chained = true, + .chain_id = ALC861_FIXUP_NO_JACK_DETECT, + } }; static const struct snd_pci_quirk alc861_fixup_tbl[] = { - SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), - SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP), - SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), - SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), + SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP), + SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F), + SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT), + SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F), + SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F), + SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505), {} }; -- cgit v1.2.3 From 1565cc358585be40608b46f18f7ac431a1aae2bc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Feb 2012 12:03:25 +0100 Subject: ALSA: hda - Add another jack-detection suppression for ASUS ALC892 Add the jack-detect suppression for an ASUS machine with ALC892 codec. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42655 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c6305984816c..30ef877e6284 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5875,6 +5875,7 @@ enum { ALC662_FIXUP_ASUS_MODE6, ALC662_FIXUP_ASUS_MODE7, ALC662_FIXUP_ASUS_MODE8, + ALC662_FIXUP_NO_JACK_DETECT, }; static const struct alc_fixup alc662_fixups[] = { @@ -6020,6 +6021,10 @@ static const struct alc_fixup alc662_fixups[] = { .chained = true, .chain_id = ALC662_FIXUP_SKU_IGNORE }, + [ALC662_FIXUP_NO_JACK_DETECT] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc_fixup_no_jack_detect, + }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -6028,6 +6033,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), + SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), -- cgit v1.2.3 From ca8f04247eaaec554528279686a514c6ce087bb9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 11:51:19 +0100 Subject: ALSA: hda/realtek - Add the fixup codes for ALC260 model=will The model=will for ALC260 requires the pin 0x0f to be a headphone and some special verbs for the COEF to turn on the amp. Now added these as fixup entries and removed the static model quirk. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc260_quirks.c | 43 ---------------------------- sound/pci/hda/patch_realtek.c | 27 +++++++++++++++-- 3 files changed, 24 insertions(+), 47 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index c8c54544abc5..fd09f050c808 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -31,7 +31,6 @@ ALC260 ====== fujitsu Fujitsu S7020 acer Acer TravelMate - will Will laptops (PB V7900) replacer Replacer 672V favorit100 Maxdata Favorit 100XS basic fixed pin assignment (old default model) diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c index 3b5170b9700f..79aaae8e0d9c 100644 --- a/sound/pci/hda/alc260_quirks.c +++ b/sound/pci/hda/alc260_quirks.c @@ -9,7 +9,6 @@ enum { ALC260_BASIC, ALC260_FUJITSU_S702X, ALC260_ACER, - ALC260_WILL, ALC260_REPLACER_672V, ALC260_FAVORIT100, #ifdef CONFIG_SND_DEBUG @@ -236,23 +235,6 @@ static const struct snd_kcontrol_new alc260_favorit100_mixer[] = { { } /* end */ }; -/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, - * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. - */ -static const struct snd_kcontrol_new alc260_will_mixer[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), - ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), - HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), - ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), - { } /* end */ -}; - /* Replacer 672V ALC260 pin usage: Mic jack = 0x12, * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. */ @@ -590,16 +572,6 @@ static const struct hda_verb alc260_favorit100_init_verbs[] = { { } }; -static const struct hda_verb alc260_will_verbs[] = { - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, - {} -}; - static const struct hda_verb alc260_replacer_672v_verbs[] = { {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, @@ -851,7 +823,6 @@ static const char * const alc260_models[ALC260_MODEL_LAST] = { [ALC260_BASIC] = "basic", [ALC260_FUJITSU_S702X] = "fujitsu", [ALC260_ACER] = "acer", - [ALC260_WILL] = "will", [ALC260_REPLACER_672V] = "replacer", [ALC260_FAVORIT100] = "favorit100", #ifdef CONFIG_SND_DEBUG @@ -862,7 +833,6 @@ static const char * const alc260_models[ALC260_MODEL_LAST] = { static const struct snd_pci_quirk alc260_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), - SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL), SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), @@ -871,7 +841,6 @@ static const struct snd_pci_quirk alc260_cfg_tbl[] = { SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), - SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), {} }; @@ -924,18 +893,6 @@ static const struct alc_config_preset alc260_presets[] = { .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources), .input_mux = alc260_favorit100_capture_sources, }, - [ALC260_WILL] = { - .mixers = { alc260_will_mixer }, - .init_verbs = { alc260_init_verbs, alc260_will_verbs }, - .num_dacs = ARRAY_SIZE(alc260_dac_nids), - .dac_nids = alc260_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), - .adc_nids = alc260_adc_nids, - .dig_out_nid = ALC260_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc260_modes), - .channel_mode = alc260_modes, - .input_mux = &alc260_capture_source, - }, [ALC260_REPLACER_672V] = { .mixers = { alc260_replacer_672v_mixer }, .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 30ef877e6284..f5f371036234 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4207,21 +4207,42 @@ static const struct hda_amp_list alc260_loopbacks[] = { * Pin config fixes */ enum { - PINFIX_HP_DC5750, + ALC260_FIXUP_HP_DC5750, + ALC260_FIXUP_HP_PIN_0F, + ALC260_FIXUP_COEF, }; static const struct alc_fixup alc260_fixups[] = { - [PINFIX_HP_DC5750] = { + [ALC260_FIXUP_HP_DC5750] = { .type = ALC_FIXUP_PINS, .v.pins = (const struct alc_pincfg[]) { { 0x11, 0x90130110 }, /* speaker */ { } } }, + [ALC260_FIXUP_HP_PIN_0F] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x0f, 0x01214000 }, /* HP */ + { } + } + }, + [ALC260_FIXUP_COEF] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 }, + { } + }, + .chained = true, + .chain_id = ALC260_FIXUP_HP_PIN_0F, + }, }; static const struct snd_pci_quirk alc260_fixup_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750), + SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF), + SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), + SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), {} }; -- cgit v1.2.3 From 15317ab21686044f1af96dd329ba809a08f04b89 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 12:02:53 +0100 Subject: ALSA: hda/realtek - Replace ALC260 model=acer with the auto-parser The ALC260 model=acer needs GPIO1 setup. It could be selected well if the codec SSID is set properly by BIOS, but to make sure, enable it forcibly. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc260_quirks.c | 146 --------------------------- sound/pci/hda/patch_realtek.c | 7 ++ 3 files changed, 7 insertions(+), 147 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index fd09f050c808..5cc76090f5d6 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -30,7 +30,6 @@ ALC880 ALC260 ====== fujitsu Fujitsu S7020 - acer Acer TravelMate replacer Replacer 672V favorit100 Maxdata Favorit 100XS basic fixed pin assignment (old default model) diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c index 79aaae8e0d9c..2f1594b3d4bd 100644 --- a/sound/pci/hda/alc260_quirks.c +++ b/sound/pci/hda/alc260_quirks.c @@ -8,7 +8,6 @@ enum { ALC260_AUTO, ALC260_BASIC, ALC260_FUJITSU_S702X, - ALC260_ACER, ALC260_REPLACER_672V, ALC260_FAVORIT100, #ifdef CONFIG_SND_DEBUG @@ -181,48 +180,6 @@ static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = { { } /* end */ }; -/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current - * versions of the ALC260 don't act on requests to enable mic bias from NID - * 0x0f (used to drive the headphone jack in these laptops). The ALC260 - * datasheet doesn't mention this restriction. At this stage it's not clear - * whether this behaviour is intentional or is a hardware bug in chip - * revisions available in early 2006. Therefore for now allow the - * "Headphone Jack Mode" control to span all choices, but if it turns out - * that the lack of mic bias for this NID is intentional we could change the - * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. - * - * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 - * don't appear to make the mic bias available from the "line" jack, even - * though the NID used for this jack (0x14) can supply it. The theory is - * that perhaps Acer have included blocking capacitors between the ALC260 - * and the output jack. If this turns out to be the case for all such - * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT - * to ALC_PIN_DIR_INOUT_NOMICBIAS. - * - * The C20x Tablet series have a mono internal speaker which is controlled - * via the chip's Mono sum widget and pin complex, so include the necessary - * controls for such models. On models without a "mono speaker" the control - * won't do anything. - */ -static const struct snd_kcontrol_new alc260_acer_mixer[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), - ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), - HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, - HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, - HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), - ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), - HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), - ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), - { } /* end */ -}; - /* Maxdata Favorit 100XS: one output and one input (0x12) jack */ static const struct snd_kcontrol_new alc260_favorit100_mixer[] = { @@ -401,94 +358,6 @@ static const struct hda_verb alc260_fujitsu_init_verbs[] = { { } }; -/* Initialisation sequence for ALC260 as configured in Acer TravelMate and - * similar laptops (adapted from Fujitsu init verbs). - */ -static const struct hda_verb alc260_acer_init_verbs[] = { - /* On TravelMate laptops, GPIO 0 enables the internal speaker and - * the headphone jack. Turn this on and rely on the standard mute - * methods whenever the user wants to turn these outputs off. - */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - /* Internal speaker/Headphone jack is connected to Line-out pin */ - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* Internal microphone/Mic jack is connected to Mic1 pin */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, - /* Line In jack is connected to Line1 pin */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */ - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* Ensure all other unused pins are disabled and muted. */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - /* Disable digital (SPDIF) pins */ - {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, - {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, - - /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum - * bus when acting as outputs. - */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, - - /* Start with output sum widgets muted and their output gains at min */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - - /* Unmute Line-out pin widget amp left and right - * (no equiv mixer ctrl) - */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Unmute Mic1 and Line1 pin widget input buffers since they start as - * inputs. If the pin mode is changed by the user the pin mode control - * will take care of enabling the pin's input/output buffers as needed. - * Therefore there's no need to enable the input buffer at this - * stage. - */ - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Mute capture amp left and right */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - /* Set ADC connection select to match default mixer setting - mic - * (on mic1 pin) - */ - {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Do similar with the second ADC: mute capture input amp and - * set ADC connection to mic to match ALSA's default state. - */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Mute all inputs to mixer widget (even unconnected ones) */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ - - { } -}; - /* Initialisation sequence for Maxdata Favorit 100XS * (adapted from Acer init verbs). */ @@ -822,7 +691,6 @@ static const struct hda_verb alc260_test_init_verbs[] = { static const char * const alc260_models[ALC260_MODEL_LAST] = { [ALC260_BASIC] = "basic", [ALC260_FUJITSU_S702X] = "fujitsu", - [ALC260_ACER] = "acer", [ALC260_REPLACER_672V] = "replacer", [ALC260_FAVORIT100] = "favorit100", #ifdef CONFIG_SND_DEBUG @@ -832,8 +700,6 @@ static const char * const alc260_models[ALC260_MODEL_LAST] = { }; static const struct snd_pci_quirk alc260_cfg_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), - SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), @@ -869,18 +735,6 @@ static const struct alc_config_preset alc260_presets[] = { .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), .input_mux = alc260_fujitsu_capture_sources, }, - [ALC260_ACER] = { - .mixers = { alc260_acer_mixer }, - .init_verbs = { alc260_acer_init_verbs }, - .num_dacs = ARRAY_SIZE(alc260_dac_nids), - .dac_nids = alc260_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), - .adc_nids = alc260_dual_adc_nids, - .num_channel_mode = ARRAY_SIZE(alc260_modes), - .channel_mode = alc260_modes, - .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), - .input_mux = alc260_acer_capture_sources, - }, [ALC260_FAVORIT100] = { .mixers = { alc260_favorit100_mixer }, .init_verbs = { alc260_favorit100_init_verbs }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f5f371036234..95ef722e4075 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4210,6 +4210,7 @@ enum { ALC260_FIXUP_HP_DC5750, ALC260_FIXUP_HP_PIN_0F, ALC260_FIXUP_COEF, + ALC260_FIXUP_GPIO1, }; static const struct alc_fixup alc260_fixups[] = { @@ -4237,10 +4238,16 @@ static const struct alc_fixup alc260_fixups[] = { .chained = true, .chain_id = ALC260_FIXUP_HP_PIN_0F, }, + [ALC260_FIXUP_GPIO1] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = alc_gpio1_init_verbs, + }, }; static const struct snd_pci_quirk alc260_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF), + SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), {} -- cgit v1.2.3 From 20f7d928fa6e51ca81648946ead6244c58a0b4c0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 12:35:16 +0100 Subject: ALSA: hda/realtek - Replace ALC260 model=replacer with the auto-parser The support for Replacer 627V in the auto-parser needs the unique unsol event handling: although the machine has a single output pin 0x0f, it's used for both the headphone and the speaker, and the driver needs to toggle the output route via GPIO 1. In addition, it needs a special COEF setup with 0x3050. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc260_quirks.c | 76 ---------------------------- sound/pci/hda/patch_realtek.c | 44 ++++++++++++++++ 3 files changed, 44 insertions(+), 77 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 5cc76090f5d6..870cb1a22473 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -30,7 +30,6 @@ ALC880 ALC260 ====== fujitsu Fujitsu S7020 - replacer Replacer 672V favorit100 Maxdata Favorit 100XS basic fixed pin assignment (old default model) test for testing/debugging purpose, almost all controls can diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c index 2f1594b3d4bd..55da43dddf38 100644 --- a/sound/pci/hda/alc260_quirks.c +++ b/sound/pci/hda/alc260_quirks.c @@ -8,7 +8,6 @@ enum { ALC260_AUTO, ALC260_BASIC, ALC260_FUJITSU_S702X, - ALC260_REPLACER_672V, ALC260_FAVORIT100, #ifdef CONFIG_SND_DEBUG ALC260_TEST, @@ -192,23 +191,6 @@ static const struct snd_kcontrol_new alc260_favorit100_mixer[] = { { } /* end */ }; -/* Replacer 672V ALC260 pin usage: Mic jack = 0x12, - * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. - */ -static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), - ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), - HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), - ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), - { } /* end */ -}; - /* * initialization verbs */ @@ -441,48 +423,6 @@ static const struct hda_verb alc260_favorit100_init_verbs[] = { { } }; -static const struct hda_verb alc260_replacer_672v_verbs[] = { - {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, - - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - - {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {} -}; - -/* toggle speaker-output according to the hp-jack state */ -static void alc260_replacer_672v_automute(struct hda_codec *codec) -{ - unsigned int present; - - /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ - present = snd_hda_jack_detect(codec, 0x0f); - if (present) { - snd_hda_codec_write_cache(codec, 0x01, 0, - AC_VERB_SET_GPIO_DATA, 1); - snd_hda_codec_write_cache(codec, 0x0f, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_HP); - } else { - snd_hda_codec_write_cache(codec, 0x01, 0, - AC_VERB_SET_GPIO_DATA, 0); - snd_hda_codec_write_cache(codec, 0x0f, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_OUT); - } -} - -static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - if ((res >> 26) == ALC_HP_EVENT) - alc260_replacer_672v_automute(codec); -} - static const struct hda_verb alc260_hp_dc7600_verbs[] = { {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, @@ -691,7 +631,6 @@ static const struct hda_verb alc260_test_init_verbs[] = { static const char * const alc260_models[ALC260_MODEL_LAST] = { [ALC260_BASIC] = "basic", [ALC260_FUJITSU_S702X] = "fujitsu", - [ALC260_REPLACER_672V] = "replacer", [ALC260_FAVORIT100] = "favorit100", #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = "test", @@ -706,7 +645,6 @@ static const struct snd_pci_quirk alc260_cfg_tbl[] = { SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), - SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), {} }; @@ -747,20 +685,6 @@ static const struct alc_config_preset alc260_presets[] = { .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources), .input_mux = alc260_favorit100_capture_sources, }, - [ALC260_REPLACER_672V] = { - .mixers = { alc260_replacer_672v_mixer }, - .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, - .num_dacs = ARRAY_SIZE(alc260_dac_nids), - .dac_nids = alc260_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), - .adc_nids = alc260_adc_nids, - .dig_out_nid = ALC260_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc260_modes), - .channel_mode = alc260_modes, - .input_mux = &alc260_capture_source, - .unsol_event = alc260_replacer_672v_unsol_event, - .init_hook = alc260_replacer_672v_automute, - }, #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = { .mixers = { alc260_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 95ef722e4075..cfa6ad758343 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4211,8 +4211,35 @@ enum { ALC260_FIXUP_HP_PIN_0F, ALC260_FIXUP_COEF, ALC260_FIXUP_GPIO1, + ALC260_FIXUP_GPIO1_TOGGLE, + ALC260_FIXUP_REPLACER, }; +static void alc260_gpio1_automute(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, + spec->hp_jack_present); +} + +static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + if (action == ALC_FIXUP_ACT_PROBE) { + /* although the machine has only one output pin, we need to + * toggle GPIO1 according to the jack state + */ + spec->automute_hook = alc260_gpio1_automute; + spec->detect_hp = 1; + spec->automute_speaker = 1; + spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ + snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); + spec->unsol_event = alc_sku_unsol_event; + add_verb(codec->spec, alc_gpio1_init_verbs); + } +} + static const struct alc_fixup alc260_fixups[] = { [ALC260_FIXUP_HP_DC5750] = { .type = ALC_FIXUP_PINS, @@ -4242,6 +4269,22 @@ static const struct alc_fixup alc260_fixups[] = { .type = ALC_FIXUP_VERBS, .v.verbs = alc_gpio1_init_verbs, }, + [ALC260_FIXUP_GPIO1_TOGGLE] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc260_fixup_gpio1_toggle, + .chained = true, + .chain_id = ALC260_FIXUP_HP_PIN_0F, + }, + [ALC260_FIXUP_REPLACER] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, + { } + }, + .chained = true, + .chain_id = ALC260_FIXUP_GPIO1_TOGGLE, + }, }; static const struct snd_pci_quirk alc260_fixup_tbl[] = { @@ -4249,6 +4292,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF), SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), + SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), {} }; -- cgit v1.2.3 From 0a1c4fa2085de68a543f28827fb6614d28924540 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 12:42:30 +0100 Subject: ALSA: hda/realtek - Add the support for HP Presario B1900 HP Presario B1900 needs a similar hack like Replacer, toggling GPIO1 per the jack state, in addition to the COEF setup used for other Acer laptops. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cfa6ad758343..db1d8c888da4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4213,6 +4213,7 @@ enum { ALC260_FIXUP_GPIO1, ALC260_FIXUP_GPIO1_TOGGLE, ALC260_FIXUP_REPLACER, + ALC260_FIXUP_HP_B1900, }; static void alc260_gpio1_automute(struct hda_codec *codec) @@ -4285,6 +4286,12 @@ static const struct alc_fixup alc260_fixups[] = { .chained = true, .chain_id = ALC260_FIXUP_GPIO1_TOGGLE, }, + [ALC260_FIXUP_HP_B1900] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc260_fixup_gpio1_toggle, + .chained = true, + .chain_id = ALC260_FIXUP_COEF, + } }; static const struct snd_pci_quirk alc260_fixup_tbl[] = { @@ -4292,6 +4299,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF), SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), + SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), {} -- cgit v1.2.3 From b1f58085a9c01e8ffab954fd77a45f1143edf34d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 12:45:03 +0100 Subject: ALSA: hda/realtek - Drop model=favorit100 for ALC260 It's working with the auto-parser just with the standard GPIO 1 setup. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc260_quirks.c | 129 --------------------------- sound/pci/hda/patch_realtek.c | 1 + 3 files changed, 1 insertion(+), 130 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 870cb1a22473..e63d5e2ed470 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -30,7 +30,6 @@ ALC880 ALC260 ====== fujitsu Fujitsu S7020 - favorit100 Maxdata Favorit 100XS basic fixed pin assignment (old default model) test for testing/debugging purpose, almost all controls can adjusted. Appearing only when compiled with diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c index 55da43dddf38..94e7a270c5a9 100644 --- a/sound/pci/hda/alc260_quirks.c +++ b/sound/pci/hda/alc260_quirks.c @@ -8,7 +8,6 @@ enum { ALC260_AUTO, ALC260_BASIC, ALC260_FUJITSU_S702X, - ALC260_FAVORIT100, #ifdef CONFIG_SND_DEBUG ALC260_TEST, #endif @@ -103,25 +102,6 @@ static const struct hda_input_mux alc260_acer_capture_sources[2] = { }, }; -/* Maxdata Favorit 100XS */ -static const struct hda_input_mux alc260_favorit100_capture_sources[2] = { - { - .num_items = 2, - .items = { - { "Line/Mic", 0x0 }, - { "CD", 0x4 }, - }, - }, - { - .num_items = 3, - .items = { - { "Line/Mic", 0x0 }, - { "CD", 0x4 }, - { "Mixer", 0x5 }, - }, - }, -}; - /* * This is just place-holder, so there's something for alc_build_pcms to look * at when it calculates the maximum number of channels. ALC260 has no mixer @@ -179,18 +159,6 @@ static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = { { } /* end */ }; -/* Maxdata Favorit 100XS: one output and one input (0x12) jack - */ -static const struct snd_kcontrol_new alc260_favorit100_mixer[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), - ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), - HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT), - ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), - { } /* end */ -}; - /* * initialization verbs */ @@ -340,89 +308,6 @@ static const struct hda_verb alc260_fujitsu_init_verbs[] = { { } }; -/* Initialisation sequence for Maxdata Favorit 100XS - * (adapted from Acer init verbs). - */ -static const struct hda_verb alc260_favorit100_init_verbs[] = { - /* GPIO 0 enables the output jack. - * Turn this on and rely on the standard mute - * methods whenever the user wants to turn these outputs off. - */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - /* Line/Mic input jack is connected to Mic1 pin */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, - /* Ensure all other unused pins are disabled and muted. */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - /* Disable digital (SPDIF) pins */ - {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, - {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, - - /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum - * bus when acting as outputs. - */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, - - /* Start with output sum widgets muted and their output gains at min */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - - /* Unmute Line-out pin widget amp left and right - * (no equiv mixer ctrl) - */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Unmute Mic1 and Line1 pin widget input buffers since they start as - * inputs. If the pin mode is changed by the user the pin mode control - * will take care of enabling the pin's input/output buffers as needed. - * Therefore there's no need to enable the input buffer at this - * stage. - */ - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Mute capture amp left and right */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - /* Set ADC connection select to match default mixer setting - mic - * (on mic1 pin) - */ - {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Do similar with the second ADC: mute capture input amp and - * set ADC connection to mic to match ALSA's default state. - */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Mute all inputs to mixer widget (even unconnected ones) */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ - - { } -}; - static const struct hda_verb alc260_hp_dc7600_verbs[] = { {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, @@ -631,7 +516,6 @@ static const struct hda_verb alc260_test_init_verbs[] = { static const char * const alc260_models[ALC260_MODEL_LAST] = { [ALC260_BASIC] = "basic", [ALC260_FUJITSU_S702X] = "fujitsu", - [ALC260_FAVORIT100] = "favorit100", #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = "test", #endif @@ -639,7 +523,6 @@ static const char * const alc260_models[ALC260_MODEL_LAST] = { }; static const struct snd_pci_quirk alc260_cfg_tbl[] = { - SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), @@ -673,18 +556,6 @@ static const struct alc_config_preset alc260_presets[] = { .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), .input_mux = alc260_fujitsu_capture_sources, }, - [ALC260_FAVORIT100] = { - .mixers = { alc260_favorit100_mixer }, - .init_verbs = { alc260_favorit100_init_verbs }, - .num_dacs = ARRAY_SIZE(alc260_dac_nids), - .dac_nids = alc260_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), - .adc_nids = alc260_dual_adc_nids, - .num_channel_mode = ARRAY_SIZE(alc260_modes), - .channel_mode = alc260_modes, - .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources), - .input_mux = alc260_favorit100_capture_sources, - }, #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = { .mixers = { alc260_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index db1d8c888da4..0d81eeb563c7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4300,6 +4300,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), + SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), {} -- cgit v1.2.3 From c29b3f6dd7798964d77199af4925be72a3a48349 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 12:47:36 +0100 Subject: ALSA: hda/realtek - Drop model=fujitsu from ALC260 static quirks The model works with the auto-parser as is, thus now good to drop. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc260_quirks.c | 142 --------------------------- 2 files changed, 143 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index e63d5e2ed470..53703392053a 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -29,7 +29,6 @@ ALC880 ALC260 ====== - fujitsu Fujitsu S7020 basic fixed pin assignment (old default model) test for testing/debugging purpose, almost all controls can adjusted. Appearing only when compiled with diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c index 94e7a270c5a9..305341f892c5 100644 --- a/sound/pci/hda/alc260_quirks.c +++ b/sound/pci/hda/alc260_quirks.c @@ -7,7 +7,6 @@ enum { ALC260_AUTO, ALC260_BASIC, - ALC260_FUJITSU_S702X, #ifdef CONFIG_SND_DEBUG ALC260_TEST, #endif @@ -50,33 +49,6 @@ static const struct hda_input_mux alc260_capture_source = { }, }; -/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, - * headphone jack and the internal CD lines since these are the only pins at - * which audio can appear. For flexibility, also allow the option of - * recording the mixer output on the second ADC (ADC0 doesn't have a - * connection to the mixer output). - */ -static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = { - { - .num_items = 3, - .items = { - { "Mic/Line", 0x0 }, - { "CD", 0x4 }, - { "Headphone", 0x2 }, - }, - }, - { - .num_items = 4, - .items = { - { "Mic/Line", 0x0 }, - { "CD", 0x4 }, - { "Headphone", 0x2 }, - { "Mixer", 0x5 }, - }, - }, - -}; - /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to * the Fujitsu S702x, but jacks are marked differently. */ @@ -142,23 +114,6 @@ static const struct snd_kcontrol_new alc260_input_mixer[] = { { } /* end */ }; -/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, - * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. - */ -static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), - ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), - ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), - { } /* end */ -}; - /* * initialization verbs */ @@ -225,89 +180,6 @@ static const struct hda_verb alc260_init_verbs[] = { { } }; -/* Initialisation sequence for ALC260 as configured in Fujitsu S702x - * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD - * audio = 0x16, internal speaker = 0x10. - */ -static const struct hda_verb alc260_fujitsu_init_verbs[] = { - /* Disable all GPIOs */ - {0x01, AC_VERB_SET_GPIO_MASK, 0}, - /* Internal speaker is connected to headphone pin */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* Headphone/Line-out jack connects to Line1 pin; make it an output */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* Ensure all other unused pins are disabled and muted. */ - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - - /* Disable digital (SPDIF) pins */ - {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, - {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, - - /* Ensure Line1 pin widget takes its input from the OUT1 sum bus - * when acting as an output. - */ - {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, - - /* Start with output sum widgets muted and their output gains at min */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - - /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Unmute Line1 pin widget output buffer since it starts as an output. - * If the pin mode is changed by the user the pin mode control will - * take care of enabling the pin's input/output buffers as needed. - * Therefore there's no need to enable the input buffer at this - * stage. - */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Unmute input buffer of pin widget used for Line-in (no equiv - * mixer ctrl) - */ - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Mute capture amp left and right */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - /* Set ADC connection select to match default mixer setting - line - * in (on mic1 pin) - */ - {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Do the same for the second ADC: mute capture input amp and - * set ADC connection to line in (on mic1 pin) - */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Mute all inputs to mixer widget (even unconnected ones) */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ - - { } -}; - static const struct hda_verb alc260_hp_dc7600_verbs[] = { {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, @@ -515,7 +387,6 @@ static const struct hda_verb alc260_test_init_verbs[] = { */ static const char * const alc260_models[ALC260_MODEL_LAST] = { [ALC260_BASIC] = "basic", - [ALC260_FUJITSU_S702X] = "fujitsu", #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = "test", #endif @@ -526,7 +397,6 @@ static const struct snd_pci_quirk alc260_cfg_tbl[] = { SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), - SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), {} }; @@ -544,18 +414,6 @@ static const struct alc_config_preset alc260_presets[] = { .channel_mode = alc260_modes, .input_mux = &alc260_capture_source, }, - [ALC260_FUJITSU_S702X] = { - .mixers = { alc260_fujitsu_mixer }, - .init_verbs = { alc260_fujitsu_init_verbs }, - .num_dacs = ARRAY_SIZE(alc260_dac_nids), - .dac_nids = alc260_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), - .adc_nids = alc260_dual_adc_nids, - .num_channel_mode = ARRAY_SIZE(alc260_modes), - .channel_mode = alc260_modes, - .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), - .input_mux = alc260_fujitsu_capture_sources, - }, #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = { .mixers = { alc260_test_mixer }, -- cgit v1.2.3 From c3c2c9e7ff3e38bd9ff5b721b6ae8634fce42802 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 12:59:55 +0100 Subject: ALSA: hda/realtek - Remove leftover static quirks for ALC260 Now we can clean up all static quirks for ALC260. Also many codes in alc_quirks.c can be ripped off since they have been used only by ALC260 static quirks. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 6 +- sound/pci/hda/alc260_quirks.c | 432 --------------------------- sound/pci/hda/alc_quirks.c | 301 ------------------- sound/pci/hda/patch_realtek.c | 48 +-- 4 files changed, 9 insertions(+), 778 deletions(-) delete mode 100644 sound/pci/hda/alc260_quirks.c (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 53703392053a..2d34be304654 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -29,11 +29,7 @@ ALC880 ALC260 ====== - basic fixed pin assignment (old default model) - test for testing/debugging purpose, almost all controls can - adjusted. Appearing only when compiled with - $CONFIG_SND_DEBUG=y - auto auto-config reading BIOS (default) + N/A ALC262 ====== diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c deleted file mode 100644 index 305341f892c5..000000000000 --- a/sound/pci/hda/alc260_quirks.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * ALC260 quirk models - * included by patch_realtek.c - */ - -/* ALC260 models */ -enum { - ALC260_AUTO, - ALC260_BASIC, -#ifdef CONFIG_SND_DEBUG - ALC260_TEST, -#endif - ALC260_MODEL_LAST /* last tag */ -}; - -static const hda_nid_t alc260_dac_nids[1] = { - /* front */ - 0x02, -}; - -static const hda_nid_t alc260_adc_nids[1] = { - /* ADC0 */ - 0x04, -}; - -static const hda_nid_t alc260_adc_nids_alt[1] = { - /* ADC1 */ - 0x05, -}; - -/* NIDs used when simultaneous access to both ADCs makes sense. Note that - * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. - */ -static const hda_nid_t alc260_dual_adc_nids[2] = { - /* ADC0, ADC1 */ - 0x04, 0x05 -}; - -#define ALC260_DIGOUT_NID 0x03 -#define ALC260_DIGIN_NID 0x06 - -static const struct hda_input_mux alc260_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to - * the Fujitsu S702x, but jacks are marked differently. - */ -static const struct hda_input_mux alc260_acer_capture_sources[2] = { - { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - { "Headphone", 0x5 }, - }, - }, - { - .num_items = 5, - .items = { - { "Mic", 0x0 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - { "Headphone", 0x6 }, - { "Mixer", 0x5 }, - }, - }, -}; - -/* - * This is just place-holder, so there's something for alc_build_pcms to look - * at when it calculates the maximum number of channels. ALC260 has no mixer - * element which allows changing the channel mode, so the verb list is - * never used. - */ -static const struct hda_channel_mode alc260_modes[1] = { - { 2, NULL }, -}; - - -/* Mixer combinations - * - * basic: base_output + input + pc_beep + capture - * fujitsu: fujitsu + capture - * acer: acer + capture - */ - -static const struct snd_kcontrol_new alc260_base_output_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new alc260_input_mixer[] = { - HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), - { } /* end */ -}; - -/* - * initialization verbs - */ -static const struct hda_verb alc260_init_verbs[] = { - /* Line In pin widget for input */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* CD pin widget for input */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* Mic1 (rear panel) pin widget for input and vref at 80% */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - /* Mic2 (front panel) pin widget for input and vref at 80% */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - /* LINE-2 is used for line-out in rear */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* select line-out */ - {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* LINE-OUT pin */ - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* enable HP */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* enable Mono */ - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* mute capture amp left and right */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* set connection select to line in (default select for this ADC) */ - {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* mute capture amp left and right */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* set connection select to line in (default select for this ADC) */ - {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* set vol=0 Line-Out mixer amp left and right */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* unmute pin widget amp left and right (no gain on this amp) */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* set vol=0 HP mixer amp left and right */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* unmute pin widget amp left and right (no gain on this amp) */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* set vol=0 Mono mixer amp left and right */ - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* unmute pin widget amp left and right (no gain on this amp) */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* unmute LINE-2 out pin */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & - * Line In 2 = 0x03 - */ - /* mute analog inputs */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ - /* mute Front out path */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* mute Headphone out path */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* mute Mono out path */ - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - { } -}; - -static const struct hda_verb alc260_hp_dc7600_verbs[] = { - {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {} -}; - -/* Test configuration for debugging, modelled after the ALC880 test - * configuration. - */ -#ifdef CONFIG_SND_DEBUG -static const hda_nid_t alc260_test_dac_nids[1] = { - 0x02, -}; -static const hda_nid_t alc260_test_adc_nids[2] = { - 0x04, 0x05, -}; -/* For testing the ALC260, each input MUX needs its own definition since - * the signal assignments are different. This assumes that the first ADC - * is NID 0x04. - */ -static const struct hda_input_mux alc260_test_capture_sources[2] = { - { - .num_items = 7, - .items = { - { "MIC1 pin", 0x0 }, - { "MIC2 pin", 0x1 }, - { "LINE1 pin", 0x2 }, - { "LINE2 pin", 0x3 }, - { "CD pin", 0x4 }, - { "LINE-OUT pin", 0x5 }, - { "HP-OUT pin", 0x6 }, - }, - }, - { - .num_items = 8, - .items = { - { "MIC1 pin", 0x0 }, - { "MIC2 pin", 0x1 }, - { "LINE1 pin", 0x2 }, - { "LINE2 pin", 0x3 }, - { "CD pin", 0x4 }, - { "Mixer", 0x5 }, - { "LINE-OUT pin", 0x6 }, - { "HP-OUT pin", 0x7 }, - }, - }, -}; -static const struct snd_kcontrol_new alc260_test_mixer[] = { - /* Output driver widgets */ - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), - HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT), - HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), - - /* Modes for retasking pin widgets - * Note: the ALC260 doesn't seem to act on requests to enable mic - * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't - * mention this restriction. At this stage it's not clear whether - * this behaviour is intentional or is a hardware bug in chip - * revisions available at least up until early 2006. Therefore for - * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all - * choices, but if it turns out that the lack of mic bias for these - * NIDs is intentional we could change their modes from - * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. - */ - ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), - ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), - ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), - ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT), - ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT), - ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT), - - /* Loopback mixer controls */ - HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), - HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), - HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), - HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), - - /* Controls for GPIO pins, assuming they are configured as outputs */ - ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), - ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), - ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), - ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), - - /* Switches to allow the digital IO pins to be enabled. The datasheet - * is ambigious as to which NID is which; testing on laptops which - * make this output available should provide clarification. - */ - ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01), - ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01), - - /* A switch allowing EAPD to be enabled. Some laptops seem to use - * this output to turn on an external amplifier. - */ - ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02), - ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02), - - { } /* end */ -}; -static const struct hda_verb alc260_test_init_verbs[] = { - /* Enable all GPIOs as outputs with an initial value of 0 */ - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, - - /* Enable retasking pins as output, initially without power amp */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - - /* Disable digital (SPDIF) pins initially, but users can enable - * them via a mixer switch. In the case of SPDIF-out, this initverb - * payload also sets the generation to 0, output to be in "consumer" - * PCM format, copyright asserted, no pre-emphasis and no validity - * control. - */ - {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, - {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, - - /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the - * OUT1 sum bus when acting as an output. - */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, - {0x0c, AC_VERB_SET_CONNECT_SEL, 0}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, - {0x0e, AC_VERB_SET_CONNECT_SEL, 0}, - - /* Start with output sum widgets muted and their output gains at min */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - - /* Unmute retasking pin widget output buffers since the default - * state appears to be output. As the pin mode is changed by the - * user the pin mode control will take care of enabling the pin's - * input/output buffers as needed. - */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Also unmute the mono-out pin widget */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Mute capture amp left and right */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - /* Set ADC connection select to match default mixer setting (mic1 - * pin) - */ - {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Do the same for the second ADC: mute capture input amp and - * set ADC connection to mic1 pin - */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Mute all inputs to mixer widget (even unconnected ones) */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ - - { } -}; -#endif - -/* - * ALC260 configurations - */ -static const char * const alc260_models[ALC260_MODEL_LAST] = { - [ALC260_BASIC] = "basic", -#ifdef CONFIG_SND_DEBUG - [ALC260_TEST] = "test", -#endif - [ALC260_AUTO] = "auto", -}; - -static const struct snd_pci_quirk alc260_cfg_tbl[] = { - SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), - SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), - SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), - SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), - {} -}; - -static const struct alc_config_preset alc260_presets[] = { - [ALC260_BASIC] = { - .mixers = { alc260_base_output_mixer, - alc260_input_mixer }, - .init_verbs = { alc260_init_verbs }, - .num_dacs = ARRAY_SIZE(alc260_dac_nids), - .dac_nids = alc260_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), - .adc_nids = alc260_dual_adc_nids, - .num_channel_mode = ARRAY_SIZE(alc260_modes), - .channel_mode = alc260_modes, - .input_mux = &alc260_capture_source, - }, -#ifdef CONFIG_SND_DEBUG - [ALC260_TEST] = { - .mixers = { alc260_test_mixer }, - .init_verbs = { alc260_test_init_verbs }, - .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), - .dac_nids = alc260_test_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids), - .adc_nids = alc260_test_adc_nids, - .num_channel_mode = ARRAY_SIZE(alc260_modes), - .channel_mode = alc260_modes, - .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), - .input_mux = alc260_test_capture_sources, - }, -#endif -}; - diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c index a18952ed4311..b344603ac06d 100644 --- a/sound/pci/hda/alc_quirks.c +++ b/sound/pci/hda/alc_quirks.c @@ -74,307 +74,6 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, return err; } -/* - * Control the mode of pin widget settings via the mixer. "pc" is used - * instead of "%" to avoid consequences of accidentally treating the % as - * being part of a format specifier. Maximum allowed length of a value is - * 63 characters plus NULL terminator. - * - * Note: some retasking pin complexes seem to ignore requests for input - * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these - * are requested. Therefore order this list so that this behaviour will not - * cause problems when mixer clients move through the enum sequentially. - * NIDs 0x0f and 0x10 have been observed to have this behaviour as of - * March 2006. - */ -static const char * const alc_pin_mode_names[] = { - "Mic 50pc bias", "Mic 80pc bias", - "Line in", "Line out", "Headphone out", -}; -static const unsigned char alc_pin_mode_values[] = { - PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, -}; -/* The control can present all 5 options, or it can limit the options based - * in the pin being assumed to be exclusively an input or an output pin. In - * addition, "input" pins may or may not process the mic bias option - * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to - * accept requests for bias as of chip versions up to March 2006) and/or - * wiring in the computer. - */ -#define ALC_PIN_DIR_IN 0x00 -#define ALC_PIN_DIR_OUT 0x01 -#define ALC_PIN_DIR_INOUT 0x02 -#define ALC_PIN_DIR_IN_NOMICBIAS 0x03 -#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 - -/* Info about the pin modes supported by the different pin direction modes. - * For each direction the minimum and maximum values are given. - */ -static const signed char alc_pin_mode_dir_info[5][2] = { - { 0, 2 }, /* ALC_PIN_DIR_IN */ - { 3, 4 }, /* ALC_PIN_DIR_OUT */ - { 0, 4 }, /* ALC_PIN_DIR_INOUT */ - { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ - { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ -}; -#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) -#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) -#define alc_pin_mode_n_items(_dir) \ - (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) - -static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int item_num = uinfo->value.enumerated.item; - unsigned char dir = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = alc_pin_mode_n_items(dir); - - if (item_numalc_pin_mode_max(dir)) - item_num = alc_pin_mode_min(dir); - strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]); - return 0; -} - -static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned int i; - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char dir = (kcontrol->private_value >> 16) & 0xff; - long *valp = ucontrol->value.integer.value; - unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, - 0x00); - - /* Find enumerated value for current pinctl setting */ - i = alc_pin_mode_min(dir); - while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl) - i++; - *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); - return 0; -} - -static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - signed int change; - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char dir = (kcontrol->private_value >> 16) & 0xff; - long val = *ucontrol->value.integer.value; - unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, - 0x00); - - if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) - val = alc_pin_mode_min(dir); - - change = pinctl != alc_pin_mode_values[val]; - if (change) { - /* Set pin mode to that requested */ - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - alc_pin_mode_values[val]); - - /* Also enable the retasking pin's input/output as required - * for the requested pin mode. Enum values of 2 or less are - * input modes. - * - * Dynamically switching the input/output buffers probably - * reduces noise slightly (particularly on input) so we'll - * do it. However, having both input and output buffers - * enabled simultaneously doesn't seem to be problematic if - * this turns out to be necessary in the future. - */ - if (val <= 2) { - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, HDA_AMP_MUTE); - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, - HDA_AMP_MUTE, 0); - } else { - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, - HDA_AMP_MUTE, HDA_AMP_MUTE); - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, 0); - } - } - return change; -} - -#define ALC_PIN_MODE(xname, nid, dir) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ - .info = alc_pin_mode_info, \ - .get = alc_pin_mode_get, \ - .put = alc_pin_mode_put, \ - .private_value = nid | (dir<<16) } - -/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged - * together using a mask with more than one bit set. This control is - * currently used only by the ALC260 test model. At this stage they are not - * needed for any "production" models. - */ -#ifdef CONFIG_SND_DEBUG -#define alc_gpio_data_info snd_ctl_boolean_mono_info - -static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long *valp = ucontrol->value.integer.value; - unsigned int val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DATA, 0x00); - - *valp = (val & mask) != 0; - return 0; -} -static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - signed int change; - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long val = *ucontrol->value.integer.value; - unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DATA, - 0x00); - - /* Set/unset the masked GPIO bit(s) as needed */ - change = (val == 0 ? 0 : mask) != (gpio_data & mask); - if (val == 0) - gpio_data &= ~mask; - else - gpio_data |= mask; - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_GPIO_DATA, gpio_data); - - return change; -} -#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ - .info = alc_gpio_data_info, \ - .get = alc_gpio_data_get, \ - .put = alc_gpio_data_put, \ - .private_value = nid | (mask<<16) } -#endif /* CONFIG_SND_DEBUG */ - -/* A switch control to allow the enabling of the digital IO pins on the - * ALC260. This is incredibly simplistic; the intention of this control is - * to provide something in the test model allowing digital outputs to be - * identified if present. If models are found which can utilise these - * outputs a more complete mixer control can be devised for those models if - * necessary. - */ -#ifdef CONFIG_SND_DEBUG -#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info - -static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long *valp = ucontrol->value.integer.value; - unsigned int val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT_1, 0x00); - - *valp = (val & mask) != 0; - return 0; -} -static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - signed int change; - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long val = *ucontrol->value.integer.value; - unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT_1, - 0x00); - - /* Set/unset the masked control bit(s) as needed */ - change = (val == 0 ? 0 : mask) != (ctrl_data & mask); - if (val==0) - ctrl_data &= ~mask; - else - ctrl_data |= mask; - snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, - ctrl_data); - - return change; -} -#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ - .info = alc_spdif_ctrl_info, \ - .get = alc_spdif_ctrl_get, \ - .put = alc_spdif_ctrl_put, \ - .private_value = nid | (mask<<16) } -#endif /* CONFIG_SND_DEBUG */ - -/* A switch control to allow the enabling EAPD digital outputs on the ALC26x. - * Again, this is only used in the ALC26x test models to help identify when - * the EAPD line must be asserted for features to work. - */ -#ifdef CONFIG_SND_DEBUG -#define alc_eapd_ctrl_info snd_ctl_boolean_mono_info - -static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long *valp = ucontrol->value.integer.value; - unsigned int val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_EAPD_BTLENABLE, 0x00); - - *valp = (val & mask) != 0; - return 0; -} - -static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change; - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long val = *ucontrol->value.integer.value; - unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_EAPD_BTLENABLE, - 0x00); - - /* Set/unset the masked control bit(s) as needed */ - change = (!val ? 0 : mask) != (ctrl_data & mask); - if (!val) - ctrl_data &= ~mask; - else - ctrl_data |= mask; - snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, - ctrl_data); - - return change; -} - -#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ - .info = alc_eapd_ctrl_info, \ - .get = alc_eapd_ctrl_get, \ - .put = alc_eapd_ctrl_put, \ - .private_value = nid | (mask<<16) } -#endif /* CONFIG_SND_DEBUG */ - static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0d81eeb563c7..3ea42069b8ee 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4308,14 +4308,10 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { /* */ -#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS -#include "alc260_quirks.c" -#endif - static int patch_alc260(struct hda_codec *codec) { struct alc_spec *spec; - int err, board_config; + int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -4325,38 +4321,13 @@ static int patch_alc260(struct hda_codec *codec) spec->mixer_nid = 0x07; - board_config = alc_board_config(codec, ALC260_MODEL_LAST, - alc260_models, alc260_cfg_tbl); - if (board_config < 0) { - snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - board_config = ALC_MODEL_AUTO; - } - - if (board_config == ALC_MODEL_AUTO) { - alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - } - - if (board_config == ALC_MODEL_AUTO) { - /* automatic parse from the BIOS config */ - err = alc260_parse_auto_config(codec); - if (err < 0) - goto error; -#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS - else if (!err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using base mode...\n"); - board_config = ALC260_BASIC; - } -#endif - } + alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - if (board_config != ALC_MODEL_AUTO) { - setup_preset(codec, &alc260_presets[board_config]); - spec->vmaster_nid = 0x08; - } + /* automatic parse from the BIOS config */ + err = alc260_parse_auto_config(codec); + if (err < 0) + goto error; if (!spec->no_analog && !spec->adc_nids) { alc_auto_fill_adc_caps(codec); @@ -4377,10 +4348,7 @@ static int patch_alc260(struct hda_codec *codec) alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); codec->patch_ops = alc_patch_ops; - if (board_config == ALC_MODEL_AUTO) - spec->init_hook = alc_auto_init_std; - else - codec->patch_ops.build_controls = __alc_build_controls; + spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) -- cgit v1.2.3 From a7f3eedc88b547e0ec35ba4cc4ae61cd9bc760ac Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 13:03:18 +0100 Subject: ALSA: hda/realtek - Disable static fixups for ASUS with ALC269 We've enabled the static fixups for ASUS machines with ALC269 codec, just for making things compatible during the transition to the auto- parser. However, it seems that the static configurations do more harmful than good, as some of entries don't match with the actual hardware setups. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3ea42069b8ee..b8e06eb96e11 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5396,7 +5396,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), -#if 1 +#if 0 /* Below is a quirk table taken from the old code. * Basically the device should work as is without the fixup table. * If BIOS doesn't give a proper info, enable the corresponding -- cgit v1.2.3 From 140547ef4ee9ad5f9ee9e6546f6027e8737c4149 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 17:23:46 +0100 Subject: ALSA: hda/realtek - Improve the signel-connection check When the connections from the pin selector contain only two widgets, a route to DAC and the aa-mixer, it's certainly a single connection. In such a case, get_dac_if_single() should return the connected DAC, too. This will improve the detection of the individual DAC assignment for each pin. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0ffccc178957..a5697c3b30b8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2972,8 +2972,12 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec, static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) { + struct alc_spec *spec = codec->spec; hda_nid_t sel = alc_go_down_to_selector(codec, pin); - if (snd_hda_get_conn_list(codec, sel, NULL) == 1) + hda_nid_t srcs[5]; + int num = snd_hda_get_connections(codec, sel, srcs, + ARRAY_SIZE(srcs)); + if (num == 1 || (num == 2 && srcs[1] == spec->mixer_nid)) return alc_auto_look_for_dac(codec, pin); return 0; } -- cgit v1.2.3 From 1c4a54b4513c175ba1a56d0aba8d9cf8f231d407 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 16:45:59 +0100 Subject: ALSA: hda/realtek - Finer tuning of auto-parser with badness evaluation This patch improves the Realtek auto-parser for assigning the DACs and mixers in more suitable ways by evaluating the assignment with "badness" calculations. When assigning a DAC hinders the assignment of individual DACs for other pins, some badness point is given. Similarly, when it blocks the assignment of unique mixer controls, another badness point is added. Also, if no DAC, even shared DAC, can be assigned, more badness is pointed. Finally, comparing the accumulated badness, the best route is chosen among several trials. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 377 ++++++++++++++++++++++++++++++++---------- 1 file changed, 293 insertions(+), 84 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a5697c3b30b8..4746afa25db8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2982,76 +2982,191 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) return 0; } -/* return 0 if no possible DAC is found, 1 if one or more found */ +/* mark up volume and mute control NIDs: used during badness parsing and + * at creating actual controls + */ +static inline unsigned int get_ctl_pos(unsigned int data) +{ + hda_nid_t nid = get_amp_nid_(data); + unsigned int dir; + if (snd_BUG_ON(nid >= MAX_VOL_NIDS)) + return 0; + dir = get_amp_direction_(data); + return (nid << 1) | dir; +} + +#define is_ctl_used(bits, data) \ + test_bit(get_ctl_pos(data), bits) +#define mark_ctl_usage(bits, data) \ + set_bit(get_ctl_pos(data), bits) + +static void clear_vol_marks(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls)); + memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls)); +} + +/* badness definition */ +enum { + /* No primary DAC is found for the main output */ + BAD_NO_PRIMARY_DAC = 0x10000, + /* No DAC is found for the extra output */ + BAD_NO_DAC = 0x4000, + /* No individual DAC for extra output */ + BAD_NO_EXTRA_DAC = 0x1000, + /* No individual DAC for extra surrounds */ + BAD_NO_EXTRA_SURR_DAC = 0x200, + /* Primary DAC shared with main surrounds */ + BAD_SHARED_SURROUND = 0x100, + /* Volume widget is shared */ + BAD_SHARED_VOL = 0x10, + /* Primary DAC shared with main CLFE */ + BAD_SHARED_CLFE = 0x10, + /* Primary DAC shared with extra surrounds */ + BAD_SHARED_EXTRA_SURROUND = 0x10, + /* No possible multi-ios */ + BAD_MULTI_IO = 0x1, +}; + +static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, + hda_nid_t pin, hda_nid_t dac); +static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, + hda_nid_t pin, hda_nid_t dac); + +static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin, + hda_nid_t dac) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t nid; + unsigned int val; + int badness = 0; + + nid = alc_look_for_out_vol_nid(codec, pin, dac); + if (nid) { + val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); + if (is_ctl_used(spec->vol_ctls, nid)) + badness += BAD_SHARED_VOL; + else + mark_ctl_usage(spec->vol_ctls, val); + } else + badness += BAD_SHARED_VOL; + nid = alc_look_for_out_mute_nid(codec, pin, dac); + if (nid) { + unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid)); + if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) + val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); + else + val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT); + if (is_ctl_used(spec->sw_ctls, val)) + badness += BAD_SHARED_VOL; + else + mark_ctl_usage(spec->sw_ctls, val); + } else + badness += BAD_SHARED_VOL; + return badness; +} + +/* try to assign DACs to extra pins and return the resultant badness */ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, const hda_nid_t *pins, hda_nid_t *dacs) { + struct alc_spec *spec = codec->spec; int i; + int badness = 0; + hda_nid_t dac; if (num_outs && !dacs[0]) { - dacs[0] = alc_auto_look_for_dac(codec, pins[0]); - if (!dacs[0]) - return 0; + dac = dacs[0] = alc_auto_look_for_dac(codec, pins[0]); + if (!dacs[0]) { + dac = spec->private_dac_nids[0]; + if (!alc_auto_is_dac_reachable(codec, pins[0], dac)) + return BAD_NO_DAC; + badness += BAD_NO_EXTRA_DAC; + } + badness += eval_shared_vol_badness(codec, pins[0], dac); } for (i = 1; i < num_outs; i++) dacs[i] = get_dac_if_single(codec, pins[i]); for (i = 1; i < num_outs; i++) { - if (!dacs[i]) - dacs[i] = alc_auto_look_for_dac(codec, pins[i]); + dac = dacs[i]; + if (!dac) + dac = dacs[i] = alc_auto_look_for_dac(codec, pins[i]); + if (!dac) { + if (alc_auto_is_dac_reachable(codec, pins[i], dacs[0])) { + dac = dacs[0]; + badness += BAD_SHARED_EXTRA_SURROUND; + } else if (alc_auto_is_dac_reachable(codec, pins[i], + spec->private_dac_nids[0])) { + dac = spec->private_dac_nids[0]; + badness += BAD_NO_EXTRA_SURR_DAC; + } else + badness += BAD_NO_DAC; + } + if (dac) + badness += eval_shared_vol_badness(codec, pins[i], dac); } - return 1; + return badness; } static int alc_auto_fill_multi_ios(struct hda_codec *codec, unsigned int location, int offset); -static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, - hda_nid_t pin, hda_nid_t dac); /* fill in the dac_nids table from the parsed pin configuration */ -static int alc_auto_fill_dac_nids(struct hda_codec *codec) +static int fill_and_eval_dacs(struct hda_codec *codec, + bool fill_hardwired) { struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int location, defcfg; - int num_pins; - bool redone = false; - int i; + int i, err, badness; - again: /* set num_dacs once to full for alc_auto_look_for_dac() */ spec->multiout.num_dacs = cfg->line_outs; - spec->multiout.hp_out_nid[0] = 0; - spec->multiout.extra_out_nid[0] = 0; - memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); spec->multiout.dac_nids = spec->private_dac_nids; + memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); + memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid)); + memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid)); spec->multi_ios = 0; + clear_vol_marks(codec); + badness = 0; /* fill hard-wired DACs first */ - if (!redone) { + if (fill_hardwired) { for (i = 0; i < cfg->line_outs; i++) spec->private_dac_nids[i] = get_dac_if_single(codec, cfg->line_out_pins[i]); - if (cfg->hp_outs) - spec->multiout.hp_out_nid[0] = - get_dac_if_single(codec, cfg->hp_pins[0]); - if (cfg->speaker_outs) - spec->multiout.extra_out_nid[0] = - get_dac_if_single(codec, cfg->speaker_pins[0]); + for (i = 0; i < cfg->hp_outs; i++) + spec->multiout.hp_out_nid[i] = + get_dac_if_single(codec, cfg->hp_pins[i]); + for (i = 0; i < cfg->speaker_outs; i++) + spec->multiout.extra_out_nid[i] = + get_dac_if_single(codec, cfg->speaker_pins[i]); } for (i = 0; i < cfg->line_outs; i++) { hda_nid_t pin = cfg->line_out_pins[i]; - if (spec->private_dac_nids[i]) - continue; - spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin); - if (!spec->private_dac_nids[i] && !redone) { - /* if we can't find primary DACs, re-probe without - * checking the hard-wired DACs - */ - redone = true; - goto again; + hda_nid_t dac; + if (!spec->private_dac_nids[i]) + spec->private_dac_nids[i] = + alc_auto_look_for_dac(codec, pin); + dac = spec->private_dac_nids[i]; + if (!dac) { + if (!i) + badness += BAD_NO_PRIMARY_DAC; + else if (alc_auto_is_dac_reachable(codec, pin, + spec->private_dac_nids[0])) { + if (i == 1) + badness += BAD_SHARED_SURROUND; + else + badness += BAD_SHARED_CLFE; + dac = spec->private_dac_nids[0]; + } else + badness += BAD_NO_DAC; } + if (dac) + badness += eval_shared_vol_badness(codec, pin, dac); } /* re-count num_dacs and squash invalid entries */ @@ -3071,26 +3186,114 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) /* try to fill multi-io first */ defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]); location = get_defcfg_location(defcfg); - - num_pins = alc_auto_fill_multi_ios(codec, location, 0); - if (num_pins > 0) { - spec->multi_ios = num_pins; - spec->ext_channel_count = 2; - spec->multiout.num_dacs = num_pins + 1; - } + err = alc_auto_fill_multi_ios(codec, location, 0); + if (err < 0) + return err; + badness += err; } - if (cfg->line_out_type != AUTO_PIN_HP_OUT) - alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, - spec->multiout.hp_out_nid); + if (cfg->line_out_type != AUTO_PIN_HP_OUT) { + err = alc_auto_fill_extra_dacs(codec, cfg->hp_outs, + cfg->hp_pins, + spec->multiout.hp_out_nid); + if (err < 0) + return err; + badness += err; + } if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { - int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, - cfg->speaker_pins, - spec->multiout.extra_out_nid); - /* if no speaker volume is assigned, try again as the primary - * output - */ - if (!err && cfg->speaker_outs > 0 && + err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, + cfg->speaker_pins, + spec->multiout.extra_out_nid); + if (err < 0) + return err; + badness += err; + } + if (!spec->multi_ios && + cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && + cfg->hp_outs) { + /* try multi-ios with HP + inputs */ + defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]); + location = get_defcfg_location(defcfg); + err = alc_auto_fill_multi_ios(codec, location, 1); + if (err < 0) + return err; + badness += err; + } + + return badness; +} + +#define DEBUG_BADNESS + +#ifdef DEBUG_BADNESS +#define debug_badness snd_printdd +#else +#define debug_badness(...) +#endif + +static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg) +{ + debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", + cfg->line_out_pins[0], cfg->line_out_pins[1], + cfg->line_out_pins[2], cfg->line_out_pins[2], + spec->multiout.dac_nids[0], + spec->multiout.dac_nids[1], + spec->multiout.dac_nids[2], + spec->multiout.dac_nids[3]); + debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", + cfg->hp_pins[0], cfg->hp_pins[1], + cfg->hp_pins[2], cfg->hp_pins[2], + spec->multiout.hp_out_nid[0], + spec->multiout.hp_out_nid[1], + spec->multiout.hp_out_nid[2], + spec->multiout.hp_out_nid[3]); + debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", + cfg->speaker_pins[0], cfg->speaker_pins[1], + cfg->speaker_pins[2], cfg->speaker_pins[3], + spec->multiout.extra_out_nid[0], + spec->multiout.extra_out_nid[1], + spec->multiout.extra_out_nid[2], + spec->multiout.extra_out_nid[3]); +} + +static int alc_auto_fill_dac_nids(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + struct auto_pin_cfg *best_cfg; + int best_badness = INT_MAX; + int badness; + bool fill_hardwired = true; + bool best_wired = true; + bool hp_spk_swapped = false; + + best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); + if (!best_cfg) + return -ENOMEM; + *best_cfg = *cfg; + + for (;;) { + badness = fill_and_eval_dacs(codec, fill_hardwired); + if (badness < 0) + return badness; + debug_badness("==> lo_type=%d, wired=%d, badness=0x%x\n", + cfg->line_out_type, fill_hardwired, badness); + debug_show_configs(spec, cfg); + if (badness < best_badness) { + best_badness = badness; + *best_cfg = *cfg; + best_wired = fill_hardwired; + } + if (!badness) + break; + if (fill_hardwired) { + fill_hardwired = false; + continue; + } + if (hp_spk_swapped) + break; + hp_spk_swapped = true; + if (cfg->speaker_outs > 0 && cfg->line_out_type == AUTO_PIN_HP_OUT) { cfg->hp_outs = cfg->line_outs; memcpy(cfg->hp_pins, cfg->line_out_pins, @@ -3101,48 +3304,45 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) cfg->speaker_outs = 0; memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; - redone = false; - goto again; - } + fill_hardwired = true; + continue; + } + if (cfg->hp_outs > 0 && + cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { + cfg->speaker_outs = cfg->line_outs; + memcpy(cfg->speaker_pins, cfg->line_out_pins, + sizeof(cfg->speaker_pins)); + cfg->line_outs = cfg->hp_outs; + memcpy(cfg->line_out_pins, cfg->hp_pins, + sizeof(cfg->hp_pins)); + cfg->hp_outs = 0; + memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); + cfg->line_out_type = AUTO_PIN_HP_OUT; + fill_hardwired = true; + continue; + } + break; } - if (!spec->multi_ios && - cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && - cfg->hp_outs) { - /* try multi-ios with HP + inputs */ - defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]); - location = get_defcfg_location(defcfg); - - num_pins = alc_auto_fill_multi_ios(codec, location, 1); - if (num_pins > 0) { - spec->multi_ios = num_pins; - spec->ext_channel_count = 2; - spec->multiout.num_dacs = num_pins + 1; - } + if (badness) { + *cfg = *best_cfg; + fill_and_eval_dacs(codec, best_wired); } + debug_badness("==> Best config: lo_type=%d, wired=%d\n", + cfg->line_out_type, best_wired); + debug_show_configs(spec, cfg); if (cfg->line_out_pins[0]) spec->vmaster_nid = alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0], spec->multiout.dac_nids[0]); - return 0; -} -static inline unsigned int get_ctl_pos(unsigned int data) -{ - hda_nid_t nid = get_amp_nid_(data); - unsigned int dir; - if (snd_BUG_ON(nid >= MAX_VOL_NIDS)) - return 0; - dir = get_amp_direction_(data); - return (nid << 1) | dir; + /* clear the bitmap flags for creating controls */ + clear_vol_marks(codec); + kfree(best_cfg); + return 0; } -#define is_ctl_used(bits, data) \ - test_bit(get_ctl_pos(data), bits) -#define mark_ctl_usage(bits, data) \ - set_bit(get_ctl_pos(data), bits) - static int alc_auto_add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx, hda_nid_t nid, unsigned int chs) @@ -3539,6 +3739,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, struct auto_pin_cfg *cfg = &spec->autocfg; hda_nid_t prime_dac = spec->private_dac_nids[0]; int type, i, dacs, num_pins = 0; + int badness = 0; dacs = spec->multiout.num_dacs; for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { @@ -3563,12 +3764,16 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, } if (!dac) dac = alc_auto_look_for_dac(codec, nid); - if (!dac) + if (!dac) { + badness += BAD_MULTI_IO; continue; + } spec->multi_io[num_pins].pin = nid; spec->multi_io[num_pins].dac = dac; num_pins++; spec->private_dac_nids[spec->multiout.num_dacs++] = dac; + if (num_pins >= 2) + break; } } spec->multiout.num_dacs = dacs; @@ -3577,9 +3782,13 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, memset(spec->private_dac_nids + dacs, 0, sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs)); spec->private_dac_nids[0] = prime_dac; - return 0; + return badness; } - return num_pins; + + spec->multi_ios = num_pins; + spec->ext_channel_count = 2; + spec->multiout.num_dacs = num_pins + 1; + return 0; } static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol, -- cgit v1.2.3 From 185d99f1924ee0047bcd524c58a01c9f8d58d673 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Feb 2012 18:39:45 +0100 Subject: ALSA: hda/realtek - Try harder to fit the single-connections So far, the Realtek driver tires to assign the single-connected routes for all pins only once at the beginning. However, since some DACs have been already mapped, the rest pins might have also single conections. In this patch, the driver does the single-connection assignment in a loop until all possbile single-connections are checked. This will improve the DAC assignment, e.g. for ASUS G72. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 124 +++++++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 33 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4746afa25db8..29c1925e9184 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2926,10 +2926,22 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin, return 0; } +static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) +{ + struct alc_spec *spec = codec->spec; + if (found_in_nid_list(nid, spec->multiout.dac_nids, + ARRAY_SIZE(spec->private_dac_nids)) || + found_in_nid_list(nid, spec->multiout.hp_out_nid, + ARRAY_SIZE(spec->multiout.hp_out_nid)) || + found_in_nid_list(nid, spec->multiout.extra_out_nid, + ARRAY_SIZE(spec->multiout.extra_out_nid))) + return true; + return false; +} + /* look for an empty DAC slot */ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) { - struct alc_spec *spec = codec->spec; hda_nid_t srcs[5]; int i, num; @@ -2939,16 +2951,8 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); if (!nid) continue; - if (found_in_nid_list(nid, spec->multiout.dac_nids, - ARRAY_SIZE(spec->private_dac_nids))) - continue; - if (found_in_nid_list(nid, spec->multiout.hp_out_nid, - ARRAY_SIZE(spec->multiout.hp_out_nid))) - continue; - if (found_in_nid_list(nid, spec->multiout.extra_out_nid, - ARRAY_SIZE(spec->multiout.extra_out_nid))) - continue; - return nid; + if (!alc_is_dac_already_used(codec, nid)) + return nid; } return 0; } @@ -2974,12 +2978,23 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) { struct alc_spec *spec = codec->spec; hda_nid_t sel = alc_go_down_to_selector(codec, pin); - hda_nid_t srcs[5]; - int num = snd_hda_get_connections(codec, sel, srcs, + hda_nid_t nid, nid_found, srcs[5]; + int i, num = snd_hda_get_connections(codec, sel, srcs, ARRAY_SIZE(srcs)); - if (num == 1 || (num == 2 && srcs[1] == spec->mixer_nid)) + if (num == 1) return alc_auto_look_for_dac(codec, pin); - return 0; + nid_found = 0; + for (i = 0; i < num; i++) { + if (srcs[i] == spec->mixer_nid) + continue; + nid = alc_auto_mix_to_dac(codec, srcs[i]); + if (nid && !alc_is_dac_already_used(codec, nid)) { + if (nid_found) + return 0; + nid_found = nid; + } + } + return nid_found; } /* mark up volume and mute control NIDs: used during badness parsing and @@ -3076,16 +3091,30 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, int badness = 0; hda_nid_t dac; - if (num_outs && !dacs[0]) { - dac = dacs[0] = alc_auto_look_for_dac(codec, pins[0]); - if (!dacs[0]) { - dac = spec->private_dac_nids[0]; - if (!alc_auto_is_dac_reachable(codec, pins[0], dac)) - return BAD_NO_DAC; - badness += BAD_NO_EXTRA_DAC; + if (!num_outs) + return 0; + + if (!dacs[0]) + dacs[0] = alc_auto_look_for_dac(codec, pins[0]); + if (!dacs[0]) { + for (i = 1; i < num_outs; i++) { + dac = dacs[i]; + if (dac && alc_auto_is_dac_reachable(codec, pins[0], dac)) { + dacs[0] = dac; + dacs[i] = 0; + break; + } } - badness += eval_shared_vol_badness(codec, pins[0], dac); } + dac = dacs[0]; + if (!dac) { + dac = spec->private_dac_nids[0]; + if (!alc_auto_is_dac_reachable(codec, pins[0], dac)) + return BAD_NO_DAC; + badness += BAD_NO_EXTRA_DAC; + } + if (dac) + badness += eval_shared_vol_badness(codec, pins[0], dac); for (i = 1; i < num_outs; i++) dacs[i] = get_dac_if_single(codec, pins[i]); @@ -3113,6 +3142,21 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, static int alc_auto_fill_multi_ios(struct hda_codec *codec, unsigned int location, int offset); +static bool alc_map_singles(struct hda_codec *codec, int outs, + const hda_nid_t *pins, hda_nid_t *dacs) +{ + int i; + bool found = false; + for (i = 0; i < outs; i++) { + if (dacs[i]) + continue; + dacs[i] = get_dac_if_single(codec, pins[i]); + if (dacs[i]) + found = true; + } + return found; +} + /* fill in the dac_nids table from the parsed pin configuration */ static int fill_and_eval_dacs(struct hda_codec *codec, bool fill_hardwired) @@ -3120,7 +3164,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int location, defcfg; - int i, err, badness; + int i, j, err, badness; /* set num_dacs once to full for alc_auto_look_for_dac() */ spec->multiout.num_dacs = cfg->line_outs; @@ -3134,15 +3178,18 @@ static int fill_and_eval_dacs(struct hda_codec *codec, /* fill hard-wired DACs first */ if (fill_hardwired) { - for (i = 0; i < cfg->line_outs; i++) - spec->private_dac_nids[i] = - get_dac_if_single(codec, cfg->line_out_pins[i]); - for (i = 0; i < cfg->hp_outs; i++) - spec->multiout.hp_out_nid[i] = - get_dac_if_single(codec, cfg->hp_pins[i]); - for (i = 0; i < cfg->speaker_outs; i++) - spec->multiout.extra_out_nid[i] = - get_dac_if_single(codec, cfg->speaker_pins[i]); + bool mapped; + do { + mapped = alc_map_singles(codec, cfg->line_outs, + cfg->line_out_pins, + spec->private_dac_nids); + mapped |= alc_map_singles(codec, cfg->hp_outs, + cfg->hp_pins, + spec->multiout.hp_out_nid); + mapped |= alc_map_singles(codec, cfg->speaker_outs, + cfg->speaker_pins, + spec->multiout.extra_out_nid); + } while (mapped); } for (i = 0; i < cfg->line_outs; i++) { @@ -3152,6 +3199,17 @@ static int fill_and_eval_dacs(struct hda_codec *codec, spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin); dac = spec->private_dac_nids[i]; + if (!dac && !i) { + for (j = 1; j < cfg->line_outs; j++) { + hda_nid_t dac2 = spec->private_dac_nids[j]; + if (dac2 && + alc_auto_is_dac_reachable(codec, pin, dac2)) { + dac = spec->private_dac_nids[0] = dac2; + spec->private_dac_nids[j] = 0; + break; + } + } + } if (!dac) { if (!i) badness += BAD_NO_PRIMARY_DAC; -- cgit v1.2.3 From 6f4530409199e7c3f8a4bdbd1391b7b25951e397 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Feb 2012 14:09:20 +0100 Subject: ALSA: hda/realtek - Show multi-io pins in debug prints Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 29c1925e9184..4b2ecbcbe66b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3298,6 +3298,11 @@ static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg) spec->multiout.dac_nids[1], spec->multiout.dac_nids[2], spec->multiout.dac_nids[3]); + if (spec->multi_ios > 0) + debug_badness("multi_ios(%d) = %x/%x : %x/%x\n", + spec->multi_ios, + spec->multi_io[0].pin, spec->multi_io[1].pin, + spec->multi_io[0].dac, spec->multi_io[1].dac); debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", cfg->hp_pins[0], cfg->hp_pins[1], cfg->hp_pins[2], cfg->hp_pins[2], -- cgit v1.2.3 From 276dd70baebe6334e603227c064a9beb07cb4e9e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Feb 2012 16:17:03 +0100 Subject: ALSA: hda/realtek - Adjust badness calculation for multi-ios Try harder to fit the multi-io pins also by checking the hard-wired connections for multi-ios. Also, the badness values are adjusted to prioritize the multi-ios as more valuable. These changes will enable the multi-io on some machines without losing the current capability. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 196 +++++++++++++++++++++++++++++------------- 1 file changed, 134 insertions(+), 62 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4b2ecbcbe66b..d0c71d5be83f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2929,6 +2929,7 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin, static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) { struct alc_spec *spec = codec->spec; + int i; if (found_in_nid_list(nid, spec->multiout.dac_nids, ARRAY_SIZE(spec->private_dac_nids)) || found_in_nid_list(nid, spec->multiout.hp_out_nid, @@ -2936,6 +2937,10 @@ static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) found_in_nid_list(nid, spec->multiout.extra_out_nid, ARRAY_SIZE(spec->multiout.extra_out_nid))) return true; + for (i = 0; i < spec->multi_ios; i++) { + if (spec->multi_io[i].dac == nid) + return true; + } return false; } @@ -3028,20 +3033,20 @@ enum { BAD_NO_PRIMARY_DAC = 0x10000, /* No DAC is found for the extra output */ BAD_NO_DAC = 0x4000, + /* No possible multi-ios */ + BAD_MULTI_IO = 0x103, /* No individual DAC for extra output */ - BAD_NO_EXTRA_DAC = 0x1000, + BAD_NO_EXTRA_DAC = 0x102, /* No individual DAC for extra surrounds */ - BAD_NO_EXTRA_SURR_DAC = 0x200, + BAD_NO_EXTRA_SURR_DAC = 0x101, /* Primary DAC shared with main surrounds */ BAD_SHARED_SURROUND = 0x100, - /* Volume widget is shared */ - BAD_SHARED_VOL = 0x10, /* Primary DAC shared with main CLFE */ BAD_SHARED_CLFE = 0x10, /* Primary DAC shared with extra surrounds */ BAD_SHARED_EXTRA_SURROUND = 0x10, - /* No possible multi-ios */ - BAD_MULTI_IO = 0x1, + /* Volume widget is shared */ + BAD_SHARED_VOL = 0x10, }; static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, @@ -3140,7 +3145,8 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, } static int alc_auto_fill_multi_ios(struct hda_codec *codec, - unsigned int location, int offset); + hda_nid_t reference_pin, + bool hardwired, int offset); static bool alc_map_singles(struct hda_codec *codec, int outs, const hda_nid_t *pins, hda_nid_t *dacs) @@ -3159,11 +3165,11 @@ static bool alc_map_singles(struct hda_codec *codec, int outs, /* fill in the dac_nids table from the parsed pin configuration */ static int fill_and_eval_dacs(struct hda_codec *codec, - bool fill_hardwired) + bool fill_hardwired, + bool fill_mio_first) { struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int location, defcfg; int i, j, err, badness; /* set num_dacs once to full for alc_auto_look_for_dac() */ @@ -3181,14 +3187,20 @@ static int fill_and_eval_dacs(struct hda_codec *codec, bool mapped; do { mapped = alc_map_singles(codec, cfg->line_outs, - cfg->line_out_pins, - spec->private_dac_nids); + cfg->line_out_pins, + spec->private_dac_nids); mapped |= alc_map_singles(codec, cfg->hp_outs, cfg->hp_pins, spec->multiout.hp_out_nid); mapped |= alc_map_singles(codec, cfg->speaker_outs, cfg->speaker_pins, spec->multiout.extra_out_nid); + if (fill_mio_first && cfg->line_outs == 1 && + cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { + err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0); + if (!err) + mapped = true; + } } while (mapped); } @@ -3240,14 +3252,13 @@ static int fill_and_eval_dacs(struct hda_codec *codec, } } - if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { + if (fill_mio_first && + cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { /* try to fill multi-io first */ - defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]); - location = get_defcfg_location(defcfg); - err = alc_auto_fill_multi_ios(codec, location, 0); + err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); if (err < 0) return err; - badness += err; + /* we don't count badness at this stage yet */ } if (cfg->line_out_type != AUTO_PIN_HP_OUT) { @@ -3266,18 +3277,30 @@ static int fill_and_eval_dacs(struct hda_codec *codec, return err; badness += err; } - if (!spec->multi_ios && - cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && - cfg->hp_outs) { + if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { + err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); + if (err < 0) + return err; + badness += err; + } + if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { /* try multi-ios with HP + inputs */ - defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]); - location = get_defcfg_location(defcfg); - err = alc_auto_fill_multi_ios(codec, location, 1); + err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false, 1); if (err < 0) return err; badness += err; } + if (spec->multi_ios == 2) { + for (i = 0; i < 2; i++) + spec->private_dac_nids[spec->multiout.num_dacs++] = + spec->multi_io[i].dac; + spec->ext_channel_count = 2; + } else if (spec->multi_ios) { + spec->multi_ios = 0; + badness += BAD_MULTI_IO; + } + return badness; } @@ -3326,8 +3349,8 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) struct auto_pin_cfg *best_cfg; int best_badness = INT_MAX; int badness; - bool fill_hardwired = true; - bool best_wired = true; + bool fill_hardwired = true, fill_mio_first = true; + bool best_wired = true, best_mio = true; bool hp_spk_swapped = false; best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); @@ -3336,23 +3359,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) *best_cfg = *cfg; for (;;) { - badness = fill_and_eval_dacs(codec, fill_hardwired); + badness = fill_and_eval_dacs(codec, fill_hardwired, + fill_mio_first); if (badness < 0) return badness; - debug_badness("==> lo_type=%d, wired=%d, badness=0x%x\n", - cfg->line_out_type, fill_hardwired, badness); + debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n", + cfg->line_out_type, fill_hardwired, fill_mio_first, + badness); debug_show_configs(spec, cfg); if (badness < best_badness) { best_badness = badness; *best_cfg = *cfg; best_wired = fill_hardwired; + best_mio = fill_mio_first; } if (!badness) break; - if (fill_hardwired) { - fill_hardwired = false; + fill_mio_first = !fill_mio_first; + if (!fill_mio_first) + continue; + fill_hardwired = !fill_hardwired; + if (!fill_hardwired) continue; - } if (hp_spk_swapped) break; hp_spk_swapped = true; @@ -3389,10 +3417,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) if (badness) { *cfg = *best_cfg; - fill_and_eval_dacs(codec, best_wired); + fill_and_eval_dacs(codec, best_wired, best_mio); } - debug_badness("==> Best config: lo_type=%d, wired=%d\n", - cfg->line_out_type, best_wired); + debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n", + cfg->line_out_type, best_wired, best_mio); debug_show_configs(spec, cfg); if (cfg->line_out_pins[0]) @@ -3791,66 +3819,110 @@ static void alc_auto_init_extra_out(struct hda_codec *codec) } } +/* check whether the given pin can be a multi-io pin */ +static bool can_be_multiio_pin(struct hda_codec *codec, + unsigned int location, hda_nid_t nid) +{ + unsigned int defcfg, caps; + + defcfg = snd_hda_codec_get_pincfg(codec, nid); + if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX) + return false; + if (location && get_defcfg_location(defcfg) != location) + return false; + caps = snd_hda_query_pin_caps(codec, nid); + if (!(caps & AC_PINCAP_OUT)) + return false; + return true; +} + /* * multi-io helper + * + * When hardwired is set, try to fill ony hardwired pins, and returns + * zero if any pins are filled, non-zero if nothing found. + * When hardwired is off, try to fill possible input pins, and returns + * the badness value. */ static int alc_auto_fill_multi_ios(struct hda_codec *codec, - unsigned int location, - int offset) + hda_nid_t reference_pin, + bool hardwired, int offset) { struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t prime_dac = spec->private_dac_nids[0]; - int type, i, dacs, num_pins = 0; + int type, i, j, dacs, num_pins, old_pins; + unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin); + unsigned int location = get_defcfg_location(defcfg); int badness = 0; + old_pins = spec->multi_ios; + if (old_pins >= 2) + goto end_fill; + + num_pins = 0; + for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { + for (i = 0; i < cfg->num_inputs; i++) { + if (cfg->inputs[i].type != type) + continue; + if (can_be_multiio_pin(codec, location, + cfg->inputs[i].pin)) + num_pins++; + } + } + if (num_pins < 2) + goto end_fill; + dacs = spec->multiout.num_dacs; for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { for (i = 0; i < cfg->num_inputs; i++) { hda_nid_t nid = cfg->inputs[i].pin; hda_nid_t dac = 0; - unsigned int defcfg, caps; + if (cfg->inputs[i].type != type) continue; - defcfg = snd_hda_codec_get_pincfg(codec, nid); - if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX) - continue; - if (location && get_defcfg_location(defcfg) != location) + if (!can_be_multiio_pin(codec, location, nid)) continue; - caps = snd_hda_query_pin_caps(codec, nid); - if (!(caps & AC_PINCAP_OUT)) + for (j = 0; j < spec->multi_ios; j++) { + if (nid == spec->multi_io[j].pin) + break; + } + if (j < spec->multi_ios) continue; - if (offset && offset + num_pins < dacs) { - dac = spec->private_dac_nids[offset + num_pins]; + + if (offset && offset + spec->multi_ios < dacs) { + dac = spec->private_dac_nids[offset + spec->multi_ios]; if (!alc_auto_is_dac_reachable(codec, nid, dac)) dac = 0; } - if (!dac) + if (hardwired) + dac = get_dac_if_single(codec, nid); + else if (!dac) dac = alc_auto_look_for_dac(codec, nid); if (!dac) { - badness += BAD_MULTI_IO; + badness++; continue; } - spec->multi_io[num_pins].pin = nid; - spec->multi_io[num_pins].dac = dac; - num_pins++; - spec->private_dac_nids[spec->multiout.num_dacs++] = dac; - if (num_pins >= 2) + spec->multi_io[spec->multi_ios].pin = nid; + spec->multi_io[spec->multi_ios].dac = dac; + spec->multi_ios++; + if (spec->multi_ios >= 2) break; } } - spec->multiout.num_dacs = dacs; - if (num_pins < 2) { - /* clear up again */ - memset(spec->private_dac_nids + dacs, 0, - sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs)); - spec->private_dac_nids[0] = prime_dac; + end_fill: + if (badness) + badness = BAD_MULTI_IO; + if (old_pins == spec->multi_ios) { + if (hardwired) + return 1; /* nothing found */ + else + return badness; /* no badness if nothing found */ + } + if (!hardwired && spec->multi_ios < 2) { + spec->multi_ios = old_pins; return badness; } - spec->multi_ios = num_pins; - spec->ext_channel_count = 2; - spec->multiout.num_dacs = num_pins + 1; return 0; } -- cgit v1.2.3 From dc6af52dea5ada1269095cad5ed2c04e92114399 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Feb 2012 16:18:59 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=lg with the auto-parser ALC880 model=lg could work fine with the auto-parser due to the recent rewrite, but it still needs the manual adjustment; namely, the BIOS leaves unused pins as some real active jacks. This confuses the parser. Thus we just cover these pins and override the pin-configs as a fix-up. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 158 --------------------------- sound/pci/hda/patch_realtek.c | 14 +++ 3 files changed, 14 insertions(+), 159 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 2d34be304654..6387b41f35af 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -17,7 +17,6 @@ ALC880 uniwill 3-jack fujitsu Fujitsu Laptops (Pi1536) F1734 2-jack - lg LG laptop (m1 express dual) lg-lw LG LW20/LW25 laptop tcl TCL S700 clevo Clevo laptops (m520G, m665n) diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 501501ef36a9..3b88bc561e16 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -25,7 +25,6 @@ enum { ALC880_UNIWILL_P53, ALC880_CLEVO, ALC880_TCL_S700, - ALC880_LG, #ifdef CONFIG_SND_DEBUG ALC880_TEST, #endif @@ -773,11 +772,6 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec, } } -static void alc880_unsol_event(struct hda_codec *codec, unsigned int res) -{ - alc_exec_unsol_event(codec, res >> 28); -} - static void alc880_uniwill_p53_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -936,136 +930,6 @@ static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { { } }; -/* - * LG m1 express dual - * - * Pin assignment: - * Rear Line-In/Out (blue): 0x14 - * Build-in Mic-In: 0x15 - * Speaker-out: 0x17 - * HP-Out (green): 0x1b - * Mic-In/Out (red): 0x19 - * SPDIF-Out: 0x1e - */ - -/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */ -static const hda_nid_t alc880_lg_dac_nids[3] = { - 0x05, 0x02, 0x03 -}; - -/* seems analog CD is not working */ -static const struct hda_input_mux alc880_lg_capture_source = { - .num_items = 3, - .items = { - { "Mic", 0x1 }, - { "Line", 0x5 }, - { "Internal Mic", 0x6 }, - }, -}; - -/* 2,4,6 channel modes */ -static const struct hda_verb alc880_lg_ch2_init[] = { - /* set line-in and mic-in to input */ - { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { } -}; - -static const struct hda_verb alc880_lg_ch4_init[] = { - /* set line-in to out and mic-in to input */ - { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { } -}; - -static const struct hda_verb alc880_lg_ch6_init[] = { - /* set line-in and mic-in to output */ - { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { } -}; - -static const struct hda_channel_mode alc880_lg_ch_modes[3] = { - { 2, alc880_lg_ch2_init }, - { 4, alc880_lg_ch4_init }, - { 6, alc880_lg_ch6_init }, -}; - -static const struct snd_kcontrol_new alc880_lg_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - -static const struct hda_verb alc880_lg_init_verbs[] = { - /* set capture source to mic-in */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* mute all amp mixer inputs */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, - /* line-in to input */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* built-in mic */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* speaker-out */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* mic-in to input */ - {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* HP-out */ - {0x13, AC_VERB_SET_CONNECT_SEL, 0x03}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* jack sense */ - {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - { } -}; - -/* toggle speaker-output according to the hp-jack state */ -static void alc880_lg_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x1b; - spec->autocfg.speaker_pins[0] = 0x17; - alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list alc880_lg_loopbacks[] = { - { 0x0b, HDA_INPUT, 1 }, - { 0x0b, HDA_INPUT, 6 }, - { 0x0b, HDA_INPUT, 7 }, - { } /* end */ -}; -#endif - /* * Test configuration for debugging * @@ -1352,7 +1216,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_UNIWILL_P53] = "uniwill-p53", [ALC880_FUJITSU] = "fujitsu", [ALC880_F1734] = "F1734", - [ALC880_LG] = "lg", #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = "test", #endif @@ -1409,9 +1272,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), - SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), - SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG), - SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), @@ -1673,24 +1533,6 @@ static const struct alc_config_preset alc880_presets[] = { .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, - [ALC880_LG] = { - .mixers = { alc880_lg_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_lg_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids), - .dac_nids = alc880_lg_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), - .channel_mode = alc880_lg_ch_modes, - .need_dac_fix = 1, - .input_mux = &alc880_lg_capture_source, - .unsol_event = alc880_unsol_event, - .setup = alc880_lg_setup, - .init_hook = alc_hp_automute, -#ifdef CONFIG_SND_HDA_POWER_SAVE - .loopbacks = alc880_lg_loopbacks, -#endif - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d0c71d5be83f..a39146528c24 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4404,6 +4404,7 @@ static const struct hda_amp_list alc880_loopbacks[] = { enum { ALC880_FIXUP_GPIO2, ALC880_FIXUP_MEDION_RIM, + ALC880_FIXUP_LG, }; static const struct alc_fixup alc880_fixups[] = { @@ -4421,10 +4422,23 @@ static const struct alc_fixup alc880_fixups[] = { .chained = true, .chain_id = ALC880_FIXUP_GPIO2, }, + [ALC880_FIXUP_LG] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + /* disable bogus unused pins */ + { 0x16, 0x411111f0 }, + { 0x18, 0x411111f0 }, + { 0x1a, 0x411111f0 }, + { } + } + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), + SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), + SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), {} }; -- cgit v1.2.3 From f02aab5d7fd53da95a78bb27bfbacc972ed75c10 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Feb 2012 16:33:56 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=w810 with auto-parser The Medion W810 with ALC880 has a typical BIOS bug, copying the pin-defaults without disabling the unused pins. At least, the pin 0x17 must be disabled. Also, it requires GPIO-2 setup. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 84 +--------------------------- sound/pci/hda/patch_realtek.c | 13 +++++ 3 files changed, 14 insertions(+), 84 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 6387b41f35af..24df3ab41932 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -8,7 +8,6 @@ ALC880 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out 6stack 6-jack in back, 2-jack in front 6stack-digout 6-jack with a SPDIF out - w810 3-jack z71v 3-jack (HP shared SPDIF) asus 3-jack (ASUS Mobo) asus-w1v ASUS W1V diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 3b88bc561e16..41aecda30a87 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -10,7 +10,6 @@ enum { ALC880_3ST_DIG, ALC880_5ST, ALC880_5ST_DIG, - ALC880_W810, ALC880_Z71V, ALC880_6ST, ALC880_6ST_DIG, @@ -226,56 +225,11 @@ static const struct snd_kcontrol_new alc880_six_stack_mixer[] = { }; -/* - * ALC880 W810 model - * - * W810 has rear IO for: - * Front (DAC 02) - * Surround (DAC 03) - * Center/LFE (DAC 04) - * Digital out (06) - * - * The system also has a pair of internal speakers, and a headphone jack. - * These are both connected to Line2 on the codec, hence to DAC 02. - * - * There is a variable resistor to control the speaker or headphone - * volume. This is a hardware-only device without a software API. - * - * Plugging headphones in will disable the internal speakers. This is - * implemented in hardware, not via the driver using jack sense. In - * a similar fashion, plugging into the rear socket marked "front" will - * disable both the speakers and headphones. - * - * For input, there's a microphone jack, and an "audio in" jack. - * These may not do anything useful with this driver yet, because I - * haven't setup any initialization verbs for these yet... - */ - static const hda_nid_t alc880_w810_dac_nids[3] = { /* front, rear/surround, clfe */ 0x02, 0x03, 0x04 }; -/* fixed 6 channels */ -static const struct hda_channel_mode alc880_w810_modes[1] = { - { 6, NULL } -}; - -/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ -static const struct snd_kcontrol_new alc880_w810_base_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - { } /* end */ -}; - - /* * Z710V model * @@ -593,27 +547,6 @@ static const struct hda_verb alc880_pin_5stack_init_verbs[] = { { } }; -/* - * W810 pin configuration: - * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b - */ -static const struct hda_verb alc880_pin_w810_init_verbs[] = { - /* hphone/speaker input selector: front DAC */ - {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - { } -}; - /* * Z71V pin configuration: * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) @@ -1204,7 +1137,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_CLEVO] = "clevo", [ALC880_5ST] = "5stack", [ALC880_5ST_DIG] = "5stack-digout", - [ALC880_W810] = "w810", [ALC880_Z71V] = "z71v", [ALC880_6ST] = "6stack", [ALC880_6ST_DIG] = "6stack-digout", @@ -1223,7 +1155,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { }; static const struct snd_pci_quirk alc880_cfg_tbl[] = { - SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810), SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST), SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG), @@ -1265,7 +1196,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734), SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), - SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), @@ -1377,18 +1307,6 @@ static const struct alc_config_preset alc880_presets[] = { .channel_mode = alc880_sixstack_modes, .input_mux = &alc880_6stack_capture_source, }, - [ALC880_W810] = { - .mixers = { alc880_w810_base_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_w810_init_verbs, - alc880_gpio2_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), - .dac_nids = alc880_w810_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), - .channel_mode = alc880_w810_modes, - .input_mux = &alc880_capture_source, - }, [ALC880_Z71V] = { .mixers = { alc880_z71v_mixer }, .init_verbs = { alc880_volume_init_verbs, @@ -1499,7 +1417,7 @@ static const struct alc_config_preset alc880_presets[] = { alc880_uniwill_p53_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), .dac_nids = alc880_asus_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), + .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), .channel_mode = alc880_threestack_modes, .input_mux = &alc880_capture_source, .unsol_event = alc880_uniwill_p53_unsol_event, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a39146528c24..1cad6748e337 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4405,6 +4405,7 @@ enum { ALC880_FIXUP_GPIO2, ALC880_FIXUP_MEDION_RIM, ALC880_FIXUP_LG, + ALC880_FIXUP_W810, }; static const struct alc_fixup alc880_fixups[] = { @@ -4432,9 +4433,21 @@ static const struct alc_fixup alc880_fixups[] = { { } } }, + [ALC880_FIXUP_W810] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + /* disable bogus unused pins */ + { 0x17, 0x411111f0 }, + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_GPIO2, + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { + SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), + SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), -- cgit v1.2.3 From dc31b58dbc63a37685f153568b21ed65e3e22f0e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Feb 2012 17:27:53 +0100 Subject: ALSA: hda/realtek - Refactor the DAC filler function Refactor the DAC filling function to be used for both the primary line outputs and extra outputs using the individual badness tables. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 154 +++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 77 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1cad6748e337..a0df05d03864 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2969,6 +2969,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec, hda_nid_t srcs[5]; int i, num; + if (!pin || !dac) + return false; pin = alc_go_down_to_selector(codec, pin); num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); for (i = 0; i < num; i++) { @@ -3087,60 +3089,88 @@ static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin, return badness; } -/* try to assign DACs to extra pins and return the resultant badness */ -static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, - const hda_nid_t *pins, hda_nid_t *dacs) +struct badness_table { + int no_primary_dac; /* no primary DAC */ + int no_dac; /* no secondary DACs */ + int shared_primary; /* primary DAC is shared with main output */ + int shared_surr; /* secondary DAC shared with main or primary */ + int shared_clfe; /* third DAC shared with main or primary */ + int shared_surr_main; /* secondary DAC sahred with main/DAC0 */ +}; + +static struct badness_table main_out_badness = { + .no_primary_dac = BAD_NO_PRIMARY_DAC, + .no_dac = BAD_NO_DAC, + .shared_primary = BAD_NO_PRIMARY_DAC, + .shared_surr = BAD_SHARED_SURROUND, + .shared_clfe = BAD_SHARED_CLFE, + .shared_surr_main = BAD_SHARED_SURROUND, +}; + +static struct badness_table extra_out_badness = { + .no_primary_dac = BAD_NO_DAC, + .no_dac = BAD_NO_DAC, + .shared_primary = BAD_NO_EXTRA_DAC, + .shared_surr = BAD_SHARED_EXTRA_SURROUND, + .shared_clfe = BAD_SHARED_EXTRA_SURROUND, + .shared_surr_main = BAD_NO_EXTRA_SURR_DAC, +}; + +/* try to assign DACs to pins and return the resultant badness */ +static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs, + const hda_nid_t *pins, hda_nid_t *dacs, + const struct badness_table *bad) { struct alc_spec *spec = codec->spec; - int i; + struct auto_pin_cfg *cfg = &spec->autocfg; + int i, j; int badness = 0; hda_nid_t dac; if (!num_outs) return 0; - if (!dacs[0]) - dacs[0] = alc_auto_look_for_dac(codec, pins[0]); - if (!dacs[0]) { - for (i = 1; i < num_outs; i++) { - dac = dacs[i]; - if (dac && alc_auto_is_dac_reachable(codec, pins[0], dac)) { - dacs[0] = dac; - dacs[i] = 0; - break; + for (i = 0; i < num_outs; i++) { + hda_nid_t pin = pins[i]; + if (!dacs[i]) + dacs[i] = alc_auto_look_for_dac(codec, pin); + if (!dacs[i] && !i) { + for (j = 1; j < num_outs; j++) { + if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) { + dacs[0] = dacs[j]; + dacs[j] = 0; + break; + } } } - } - dac = dacs[0]; - if (!dac) { - dac = spec->private_dac_nids[0]; - if (!alc_auto_is_dac_reachable(codec, pins[0], dac)) - return BAD_NO_DAC; - badness += BAD_NO_EXTRA_DAC; - } - if (dac) - badness += eval_shared_vol_badness(codec, pins[0], dac); - - for (i = 1; i < num_outs; i++) - dacs[i] = get_dac_if_single(codec, pins[i]); - for (i = 1; i < num_outs; i++) { dac = dacs[i]; - if (!dac) - dac = dacs[i] = alc_auto_look_for_dac(codec, pins[i]); if (!dac) { - if (alc_auto_is_dac_reachable(codec, pins[i], dacs[0])) { + if (alc_auto_is_dac_reachable(codec, pin, dacs[0])) dac = dacs[0]; - badness += BAD_SHARED_EXTRA_SURROUND; - } else if (alc_auto_is_dac_reachable(codec, pins[i], + else if (cfg->line_outs > i && + alc_auto_is_dac_reachable(codec, pin, + spec->private_dac_nids[i])) + dac = spec->private_dac_nids[i]; + if (dac) { + if (!i) + badness += bad->shared_primary; + else if (i == 1) + badness += bad->shared_surr; + else + badness += bad->shared_clfe; + } else if (alc_auto_is_dac_reachable(codec, pin, spec->private_dac_nids[0])) { dac = spec->private_dac_nids[0]; - badness += BAD_NO_EXTRA_SURR_DAC; - } else - badness += BAD_NO_DAC; + badness += bad->shared_surr_main; + } else if (!i) + badness += bad->no_primary_dac; + else + badness += bad->no_dac; } if (dac) - badness += eval_shared_vol_badness(codec, pins[i], dac); + badness += eval_shared_vol_badness(codec, pin, dac); } + return badness; } @@ -3170,7 +3200,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, { struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - int i, j, err, badness; + int i, err, badness; /* set num_dacs once to full for alc_auto_look_for_dac() */ spec->multiout.num_dacs = cfg->line_outs; @@ -3204,40 +3234,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec, } while (mapped); } - for (i = 0; i < cfg->line_outs; i++) { - hda_nid_t pin = cfg->line_out_pins[i]; - hda_nid_t dac; - if (!spec->private_dac_nids[i]) - spec->private_dac_nids[i] = - alc_auto_look_for_dac(codec, pin); - dac = spec->private_dac_nids[i]; - if (!dac && !i) { - for (j = 1; j < cfg->line_outs; j++) { - hda_nid_t dac2 = spec->private_dac_nids[j]; - if (dac2 && - alc_auto_is_dac_reachable(codec, pin, dac2)) { - dac = spec->private_dac_nids[0] = dac2; - spec->private_dac_nids[j] = 0; - break; - } - } - } - if (!dac) { - if (!i) - badness += BAD_NO_PRIMARY_DAC; - else if (alc_auto_is_dac_reachable(codec, pin, - spec->private_dac_nids[0])) { - if (i == 1) - badness += BAD_SHARED_SURROUND; - else - badness += BAD_SHARED_CLFE; - dac = spec->private_dac_nids[0]; - } else - badness += BAD_NO_DAC; - } - if (dac) - badness += eval_shared_vol_badness(codec, pin, dac); - } + badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins, + spec->private_dac_nids, + &main_out_badness); /* re-count num_dacs and squash invalid entries */ spec->multiout.num_dacs = 0; @@ -3262,17 +3261,18 @@ static int fill_and_eval_dacs(struct hda_codec *codec, } if (cfg->line_out_type != AUTO_PIN_HP_OUT) { - err = alc_auto_fill_extra_dacs(codec, cfg->hp_outs, - cfg->hp_pins, - spec->multiout.hp_out_nid); + err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins, + spec->multiout.hp_out_nid, + &extra_out_badness); if (err < 0) return err; badness += err; } if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { - err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, - cfg->speaker_pins, - spec->multiout.extra_out_nid); + err = alc_auto_fill_dacs(codec, cfg->speaker_outs, + cfg->speaker_pins, + spec->multiout.extra_out_nid, + &extra_out_badness); if (err < 0) return err; badness += err; -- cgit v1.2.3 From 27e917f82bfcf8c51a2c025ddfb69e0b5947f50b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Feb 2012 17:49:54 +0100 Subject: ALSA: hda/realtek - Drop ALC880 model=clevo Clevo machines with ALC880 are all well with proper BIOS setup. It seems still requiring the additional COEF setup for the EAPD. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 45 ---------------------------- sound/pci/hda/patch_realtek.c | 11 +++++++ 3 files changed, 11 insertions(+), 46 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 24df3ab41932..58e8aac40a98 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -18,7 +18,6 @@ ALC880 F1734 2-jack lg-lw LG LW20/LW25 laptop tcl TCL S700 - clevo Clevo laptops (m520G, m665n) medion Medion Rim 2150 test for testing/debugging purpose, almost all controls can be adjusted. Appearing only when compiled with diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 41aecda30a87..b64d2464a780 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -22,7 +22,6 @@ enum { ALC880_UNIWILL_DIG, ALC880_UNIWILL, ALC880_UNIWILL_P53, - ALC880_CLEVO, ALC880_TCL_S700, #ifdef CONFIG_SND_DEBUG ALC880_TEST, @@ -809,35 +808,6 @@ static const struct hda_verb alc880_pin_asus_init_verbs[] = { #define alc880_gpio2_init_verbs alc_gpio2_init_verbs #define alc880_gpio3_init_verbs alc_gpio3_init_verbs -/* Clevo m520g init */ -static const struct hda_verb alc880_pin_clevo_init_verbs[] = { - /* headphone output */ - {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* line-out */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Line-in */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* CD */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Mic1 (rear panel) */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Mic2 (front panel) */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* headphone */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* change to EAPD mode */ - {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, - - { } -}; - static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { /* change to EAPD mode */ {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, @@ -1134,7 +1104,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_3ST] = "3stack", [ALC880_TCL_S700] = "tcl", [ALC880_3ST_DIG] = "3stack-digout", - [ALC880_CLEVO] = "clevo", [ALC880_5ST] = "5stack", [ALC880_5ST_DIG] = "5stack-digout", [ALC880_Z71V] = "z71v", @@ -1188,8 +1157,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO), - SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO), SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), @@ -1439,18 +1406,6 @@ static const struct alc_config_preset alc880_presets[] = { .setup = alc880_uniwill_p53_setup, .init_hook = alc_hp_automute, }, - [ALC880_CLEVO] = { - .mixers = { alc880_three_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_clevo_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .hp_nid = 0x03, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a0df05d03864..4f8c36207997 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4406,6 +4406,7 @@ enum { ALC880_FIXUP_MEDION_RIM, ALC880_FIXUP_LG, ALC880_FIXUP_W810, + ALC880_FIXUP_EAPD_COEF, }; static const struct alc_fixup alc880_fixups[] = { @@ -4443,10 +4444,20 @@ static const struct alc_fixup alc880_fixups[] = { .chained = true, .chain_id = ALC880_FIXUP_GPIO2, }, + [ALC880_FIXUP_EAPD_COEF] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* change to EAPD mode */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 }, + {} + }, + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), + SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), -- cgit v1.2.3 From b9368f5c10b15f2b79a58666849827edc1f2f3d4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Feb 2012 17:54:44 +0100 Subject: ALSA: hda/realtek - Replace ALC880 model=tcl with auto-parser It needs a few extra setups for EAPD, but others look fairly straightforward. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 3 -- sound/pci/hda/alc880_quirks.c | 56 ---------------------------- sound/pci/hda/patch_realtek.c | 13 +++++++ 3 files changed, 13 insertions(+), 59 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 58e8aac40a98..fd3b3b25bd75 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -16,9 +16,6 @@ ALC880 uniwill 3-jack fujitsu Fujitsu Laptops (Pi1536) F1734 2-jack - lg-lw LG LW20/LW25 laptop - tcl TCL S700 - medion Medion Rim 2150 test for testing/debugging purpose, almost all controls can be adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index b64d2464a780..56f8fa1e3460 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -22,7 +22,6 @@ enum { ALC880_UNIWILL_DIG, ALC880_UNIWILL, ALC880_UNIWILL_P53, - ALC880_TCL_S700, #ifdef CONFIG_SND_DEBUG ALC880_TEST, #endif @@ -344,20 +343,6 @@ static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { { } /* end */ }; -/* TCL S700 */ -static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - { } /* end */ -}; - /* Uniwill */ static const struct snd_kcontrol_new alc880_uniwill_mixer[] = { HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -808,31 +793,6 @@ static const struct hda_verb alc880_pin_asus_init_verbs[] = { #define alc880_gpio2_init_verbs alc_gpio2_init_verbs #define alc880_gpio3_init_verbs alc_gpio3_init_verbs -static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { - /* change to EAPD mode */ - {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, - - /* Headphone output */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* Front output*/ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Line In pin widget for input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* Mic1 (rear panel) pin widget for input and vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - - /* change to EAPD mode */ - {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, - - { } -}; - /* * Test configuration for debugging * @@ -1102,7 +1062,6 @@ static const struct hda_verb alc880_test_init_verbs[] = { static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_3ST] = "3stack", - [ALC880_TCL_S700] = "tcl", [ALC880_3ST_DIG] = "3stack-digout", [ALC880_5ST] = "5stack", [ALC880_5ST_DIG] = "5stack-digout", @@ -1169,7 +1128,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), - SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), @@ -1216,20 +1174,6 @@ static const struct alc_config_preset alc880_presets[] = { .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, - [ALC880_TCL_S700] = { - .mixers = { alc880_tcl_s700_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_tcl_S700_init_verbs, - alc880_gpio2_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */ - .num_adc_nids = 1, /* single ADC */ - .hp_nid = 0x03, - .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), - .channel_mode = alc880_2_jack_modes, - .input_mux = &alc880_capture_source, - }, [ALC880_5ST] = { .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4f8c36207997..e6eec9a9ab47 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4407,6 +4407,7 @@ enum { ALC880_FIXUP_LG, ALC880_FIXUP_W810, ALC880_FIXUP_EAPD_COEF, + ALC880_FIXUP_TCL_S700, }; static const struct alc_fixup alc880_fixups[] = { @@ -4453,6 +4454,17 @@ static const struct alc_fixup alc880_fixups[] = { {} }, }, + [ALC880_FIXUP_TCL_S700] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* change to EAPD mode */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 }, + {} + }, + .chained = true, + .chain_id = ALC880_FIXUP_GPIO2, + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { @@ -4463,6 +4475,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), + SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700), {} }; -- cgit v1.2.3 From 589876e243bb14343d09d9fd7f9ddf79f1d80158 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 15:47:55 +0100 Subject: ALSA: hda/realtek - Apply probe-fixup really after probing Move the call of alc_apply_fixup() with ALC_FIXUP_ACT_PROBE after the whole setups of patch_ops & co, so that the fix-up function may override the default setup. This will be needed for installing the own unsol event handler (e.g. for volume-knob controls). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e6eec9a9ab47..895113ee3857 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4566,8 +4566,6 @@ static int patch_alc880(struct hda_codec *codec) set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; if (board_config == ALC_MODEL_AUTO) spec->init_hook = alc_auto_init_std; @@ -4578,6 +4576,8 @@ static int patch_alc880(struct hda_codec *codec) spec->loopback.amplist = alc880_loopbacks; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -4749,8 +4749,6 @@ static int patch_alc260(struct hda_codec *codec) set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; @@ -4759,6 +4757,8 @@ static int patch_alc260(struct hda_codec *codec) spec->loopback.amplist = alc260_loopbacks; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -5165,8 +5165,6 @@ static int patch_alc882(struct hda_codec *codec) set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; if (board_config == ALC_MODEL_AUTO) spec->init_hook = alc_auto_init_std; @@ -5178,6 +5176,8 @@ static int patch_alc882(struct hda_codec *codec) spec->loopback.amplist = alc882_loopbacks; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -5331,8 +5331,6 @@ static int patch_alc262(struct hda_codec *codec) set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; @@ -5342,6 +5340,8 @@ static int patch_alc262(struct hda_codec *codec) spec->loopback.amplist = alc262_loopbacks; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -5992,8 +5992,6 @@ static int patch_alc269(struct hda_codec *codec) set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; #ifdef CONFIG_PM codec->patch_ops.resume = alc269_resume; @@ -6008,6 +6006,8 @@ static int patch_alc269(struct hda_codec *codec) codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -6146,8 +6146,6 @@ static int patch_alc861(struct hda_codec *codec) set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; #ifdef CONFIG_SND_HDA_POWER_SAVE @@ -6156,6 +6154,8 @@ static int patch_alc861(struct hda_codec *codec) spec->loopback.amplist = alc861_loopbacks; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -6270,8 +6270,6 @@ static int patch_alc861vd(struct hda_codec *codec) set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; @@ -6281,6 +6279,8 @@ static int patch_alc861vd(struct hda_codec *codec) spec->loopback.amplist = alc861vd_loopbacks; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -6659,8 +6659,6 @@ static int patch_alc662(struct hda_codec *codec) } } - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; @@ -6670,6 +6668,8 @@ static int patch_alc662(struct hda_codec *codec) spec->loopback.amplist = alc662_loopbacks; #endif + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: -- cgit v1.2.3 From cf5a22793cfa54c056655d374722dc5dfd496eca Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 16:31:07 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=futjisu with auto-parser Now adding the support for the volume-knob widget, we can move the static quirk for ALC880 model=fujitsu to the auto-parser completely. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 33 ------------ sound/pci/hda/patch_realtek.c | 76 +++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 36 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index fd3b3b25bd75..936eef31ff99 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -14,7 +14,6 @@ ALC880 asus-dig ASUS with SPDIF out asus-dig2 ASUS with SPDIF out (using GPIO2) uniwill 3-jack - fujitsu Fujitsu Laptops (Pi1536) F1734 2-jack test for testing/debugging purpose, almost all controls can be adjusted. Appearing only when compiled with diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 56f8fa1e3460..f062eaae6b1e 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -18,7 +18,6 @@ enum { ALC880_ASUS_DIG, ALC880_ASUS_W1V, ALC880_ASUS_DIG2, - ALC880_FUJITSU, ALC880_UNIWILL_DIG, ALC880_UNIWILL, ALC880_UNIWILL_P53, @@ -371,20 +370,6 @@ static const struct snd_kcontrol_new alc880_uniwill_mixer[] = { { } /* end */ }; -static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - { } /* end */ -}; - static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = { HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), @@ -1074,7 +1059,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_ASUS_DIG2] = "asus-dig2", [ALC880_UNIWILL_DIG] = "uniwill", [ALC880_UNIWILL_P53] = "uniwill-p53", - [ALC880_FUJITSU] = "fujitsu", [ALC880_F1734] = "F1734", #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = "test", @@ -1125,9 +1109,7 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), - SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), - SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), @@ -1335,21 +1317,6 @@ static const struct alc_config_preset alc880_presets[] = { .setup = alc880_uniwill_p53_setup, .init_hook = alc_hp_automute, }, - [ALC880_FUJITSU] = { - .mixers = { alc880_fujitsu_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_uniwill_p53_init_verbs, - alc880_beep_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), - .channel_mode = alc880_2_jack_modes, - .input_mux = &alc880_capture_source, - .unsol_event = alc880_uniwill_p53_unsol_event, - .setup = alc880_uniwill_p53_setup, - .init_hook = alc_hp_automute, - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 895113ee3857..6a6436a54f07 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -651,15 +651,51 @@ static void alc_exec_unsol_event(struct hda_codec *codec, int action) snd_hda_jack_report_sync(codec); } +/* update the master volume per volume-knob's unsol event */ +static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) +{ + unsigned int val; + struct snd_kcontrol *kctl; + struct snd_ctl_elem_value *uctl; + + kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume"); + if (!kctl) + return; + uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); + if (!uctl) + return; + val = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); + val &= HDA_AMP_VOLMASK; + uctl->value.integer.value[0] = val; + uctl->value.integer.value[1] = val; + kctl->put(kctl, uctl); + kfree(uctl); +} + /* unsolicited event for HP jack sensing */ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) { + int action; + if (codec->vendor_id == 0x10ec0880) res >>= 28; else res >>= 26; - res = snd_hda_jack_get_action(codec, res); - alc_exec_unsol_event(codec, res); + action = snd_hda_jack_get_action(codec, res); + if (res == ALC_DCVOL_EVENT) { + /* Execute the dc-vol event here as it requires the NID + * but we don't pass NID to alc_exec_unsol_event(). + * Once when we convert all static quirks to the auto-parser, + * this can be integerated into there. + */ + struct hda_jack_tbl *jack; + jack = snd_hda_jack_tbl_get_from_tag(codec, res); + if (jack) + alc_update_knob_master(codec, jack->nid); + return; + } + alc_exec_unsol_event(codec, action); } /* call init functions of standard auto-mute helpers */ @@ -4408,8 +4444,18 @@ enum { ALC880_FIXUP_W810, ALC880_FIXUP_EAPD_COEF, ALC880_FIXUP_TCL_S700, + ALC880_FIXUP_VOL_KNOB, + ALC880_FIXUP_FUJITSU, }; +/* enable the volume-knob widget support on NID 0x21 */ +static void alc880_fixup_vol_knob(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + if (action == ALC_FIXUP_ACT_PROBE) + snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT); +} + static const struct alc_fixup alc880_fixups[] = { [ALC880_FIXUP_GPIO2] = { .type = ALC_FIXUP_VERBS, @@ -4465,6 +4511,30 @@ static const struct alc_fixup alc880_fixups[] = { .chained = true, .chain_id = ALC880_FIXUP_GPIO2, }, + [ALC880_FIXUP_VOL_KNOB] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc880_fixup_vol_knob, + }, + [ALC880_FIXUP_FUJITSU] = { + /* override all pins as BIOS on old Amilo is broken */ + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x14, 0x0121411f }, /* HP */ + { 0x15, 0x99030120 }, /* speaker */ + { 0x16, 0x99030130 }, /* bass speaker */ + { 0x17, 0x411111f0 }, /* N/A */ + { 0x18, 0x411111f0 }, /* N/A */ + { 0x19, 0x01a19950 }, /* mic-in */ + { 0x1a, 0x411111f0 }, /* N/A */ + { 0x1b, 0x411111f0 }, /* N/A */ + { 0x1c, 0x411111f0 }, /* N/A */ + { 0x1d, 0x411111f0 }, /* N/A */ + { 0x1e, 0x01454140 }, /* SPDIF out */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_VOL_KNOB, + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { @@ -4472,6 +4542,8 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), + SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU), SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), -- cgit v1.2.3 From ba5338185dd522696f1c0d0957a724a1fdd1f39d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 16:36:52 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=F1734 with auto-parser Similar as the previous patch for model=fujitsu, we can now move the static quirk for F1734 to the auto-parser. The only difference is the default pin configurations: F1734 has less pins than Amilo's. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 85 ---------------------------- sound/pci/hda/patch_realtek.c | 24 ++++++++ 3 files changed, 24 insertions(+), 86 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 936eef31ff99..a57d7718e4fd 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -14,7 +14,6 @@ ALC880 asus-dig ASUS with SPDIF out asus-dig2 ASUS with SPDIF out (using GPIO2) uniwill 3-jack - F1734 2-jack test for testing/debugging purpose, almost all controls can be adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index f062eaae6b1e..2ab7c3b9bb9b 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -13,7 +13,6 @@ enum { ALC880_Z71V, ALC880_6ST, ALC880_6ST_DIG, - ALC880_F1734, ALC880_ASUS, ALC880_ASUS_DIG, ALC880_ASUS_W1V, @@ -257,40 +256,6 @@ static const struct snd_kcontrol_new alc880_z71v_mixer[] = { { } /* end */ }; - -/* - * ALC880 F1734 model - * - * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) - * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 - */ - -static const hda_nid_t alc880_f1734_dac_nids[1] = { - 0x03 -}; -#define ALC880_F1734_HP_DAC 0x02 - -static const struct snd_kcontrol_new alc880_f1734_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - { } /* end */ -}; - -static const struct hda_input_mux alc880_f1734_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x1 }, - { "CD", 0x4 }, - }, -}; - - /* * ALC880 ASUS model * @@ -709,38 +674,6 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, alc_exec_unsol_event(codec, res); } -/* - * F1734 pin configuration: - * HP = 0x14, speaker-out = 0x15, mic = 0x18 - */ -static const struct hda_verb alc880_pin_f1734_init_verbs[] = { - {0x07, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT}, - {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_DCVOL_EVENT}, - - { } -}; - /* * ASUS pin configuration: * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a @@ -1059,7 +992,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_ASUS_DIG2] = "asus-dig2", [ALC880_UNIWILL_DIG] = "uniwill", [ALC880_UNIWILL_P53] = "uniwill-p53", - [ALC880_F1734] = "F1734", #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = "test", #endif @@ -1103,13 +1035,10 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), - SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734), SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), - SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), @@ -1212,20 +1141,6 @@ static const struct alc_config_preset alc880_presets[] = { .channel_mode = alc880_2_jack_modes, .input_mux = &alc880_capture_source, }, - [ALC880_F1734] = { - .mixers = { alc880_f1734_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_f1734_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), - .dac_nids = alc880_f1734_dac_nids, - .hp_nid = 0x02, - .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), - .channel_mode = alc880_2_jack_modes, - .input_mux = &alc880_f1734_capture_source, - .unsol_event = alc880_uniwill_p53_unsol_event, - .setup = alc880_uniwill_p53_setup, - .init_hook = alc_hp_automute, - }, [ALC880_ASUS] = { .mixers = { alc880_asus_mixer }, .init_verbs = { alc880_volume_init_verbs, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6a6436a54f07..2d102f70f787 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4446,6 +4446,7 @@ enum { ALC880_FIXUP_TCL_S700, ALC880_FIXUP_VOL_KNOB, ALC880_FIXUP_FUJITSU, + ALC880_FIXUP_F1734, }; /* enable the volume-knob widget support on NID 0x21 */ @@ -4535,14 +4536,37 @@ static const struct alc_fixup alc880_fixups[] = { .chained = true, .chain_id = ALC880_FIXUP_VOL_KNOB, }, + [ALC880_FIXUP_F1734] = { + /* almost compatible with FUJITSU, but no bass and SPDIF */ + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x14, 0x0121411f }, /* HP */ + { 0x15, 0x99030120 }, /* speaker */ + { 0x16, 0x411111f0 }, /* N/A */ + { 0x17, 0x411111f0 }, /* N/A */ + { 0x18, 0x411111f0 }, /* N/A */ + { 0x19, 0x01a19950 }, /* mic-in */ + { 0x1a, 0x411111f0 }, /* N/A */ + { 0x1b, 0x411111f0 }, /* N/A */ + { 0x1c, 0x411111f0 }, /* N/A */ + { 0x1d, 0x411111f0 }, /* N/A */ + { 0x1e, 0x411111f0 }, /* N/A */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_VOL_KNOB, + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), + SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), + SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU), SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), -- cgit v1.2.3 From 7833c7e8b41d4c778e18481d7115dafa4bfaee0a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 17:11:38 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=uniwill-p53 with auto-parser Uniwill p53 has a sane BIOS setup but just needs the volume-knob handling like Fujitsu laptops with ALC880. Signed-off-by: Takashi Iwai --- sound/pci/hda/alc880_quirks.c | 94 ------------------------------------------- sound/pci/hda/patch_realtek.c | 1 + 2 files changed, 1 insertion(+), 94 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 2ab7c3b9bb9b..2a00271e0651 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -19,7 +19,6 @@ enum { ALC880_ASUS_DIG2, ALC880_UNIWILL_DIG, ALC880_UNIWILL, - ALC880_UNIWILL_P53, #ifdef CONFIG_SND_DEBUG ALC880_TEST, #endif @@ -335,16 +334,6 @@ static const struct snd_kcontrol_new alc880_uniwill_mixer[] = { { } /* end */ }; -static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - { } /* end */ -}; - /* * initialize the codec volumes, etc */ @@ -568,39 +557,6 @@ static const struct hda_verb alc880_uniwill_init_verbs[] = { { } }; -/* -* Uniwill P53 -* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19, - */ -static const struct hda_verb alc880_uniwill_p53_init_verbs[] = { - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_DCVOL_EVENT}, - - { } -}; - static const struct hda_verb alc880_beep_init_verbs[] = { { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, { } @@ -639,41 +595,6 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec, } } -static void alc880_uniwill_p53_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x14; - spec->autocfg.speaker_pins[0] = 0x15; - alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); -} - -static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_codec_read(codec, 0x21, 0, - AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); - present &= HDA_AMP_VOLMASK; - snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, - HDA_AMP_VOLMASK, present); - snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0, - HDA_AMP_VOLMASK, present); -} - -static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - /* Looks like the unsol event is incompatible with the standard - * definition. 4bit tag is placed at 28 bit! - */ - res >>= 28; - if (res == ALC_DCVOL_EVENT) - alc880_uniwill_p53_dcvol_automute(codec); - else - alc_exec_unsol_event(codec, res); -} - /* * ASUS pin configuration: * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a @@ -991,7 +912,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_ASUS_DIG] = "asus-dig", [ALC880_ASUS_DIG2] = "asus-dig2", [ALC880_UNIWILL_DIG] = "uniwill", - [ALC880_UNIWILL_P53] = "uniwill-p53", #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = "test", #endif @@ -1036,7 +956,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), - SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ @@ -1219,19 +1138,6 @@ static const struct alc_config_preset alc880_presets[] = { .setup = alc880_uniwill_setup, .init_hook = alc880_uniwill_init_hook, }, - [ALC880_UNIWILL_P53] = { - .mixers = { alc880_uniwill_p53_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_uniwill_p53_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .input_mux = &alc880_capture_source, - .unsol_event = alc880_uniwill_p53_unsol_event, - .setup = alc880_uniwill_p53_setup, - .init_hook = alc_hp_automute, - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2d102f70f787..3c0a46ed9ca9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4562,6 +4562,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), + SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), -- cgit v1.2.3 From 817de92f1b52358f28534bb0b0c373f75e4b4baa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 17:20:48 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=uniwill with auto-parser The model=uniwill would work almost as is, but a couple of adjustments are needed to make the mutli-io working correctly. The headphone and speaker pins have to be marked properly in pin configs. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 118 --------------------------- sound/pci/hda/alc_quirks.c | 12 --- sound/pci/hda/patch_realtek.c | 12 +++ 4 files changed, 12 insertions(+), 131 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index a57d7718e4fd..1af6354ec549 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -13,7 +13,6 @@ ALC880 asus-w1v ASUS W1V asus-dig ASUS with SPDIF out asus-dig2 ASUS with SPDIF out (using GPIO2) - uniwill 3-jack test for testing/debugging purpose, almost all controls can be adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 2a00271e0651..c40f2446fcc4 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -18,7 +18,6 @@ enum { ALC880_ASUS_W1V, ALC880_ASUS_DIG2, ALC880_UNIWILL_DIG, - ALC880_UNIWILL, #ifdef CONFIG_SND_DEBUG ALC880_TEST, #endif @@ -306,34 +305,6 @@ static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { { } /* end */ }; -/* Uniwill */ -static const struct snd_kcontrol_new alc880_uniwill_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - /* * initialize the codec volumes, etc */ @@ -518,83 +489,11 @@ static const struct hda_verb alc880_pin_6stack_init_verbs[] = { { } }; -/* - * Uniwill pin configuration: - * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19, - * line = 0x1a - */ -static const struct hda_verb alc880_uniwill_init_verbs[] = { - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */ - /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, - {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT}, - - { } -}; - static const struct hda_verb alc880_beep_init_verbs[] = { { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, { } }; -static void alc880_uniwill_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x14; - spec->autocfg.speaker_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x16; - alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); -} - -static void alc880_uniwill_init_hook(struct hda_codec *codec) -{ - alc_hp_automute(codec); - alc88x_simple_mic_automute(codec); -} - -static void alc880_uniwill_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - /* Looks like the unsol event is incompatible with the standard - * definition. 4bit tag is placed at 28 bit! - */ - res >>= 28; - switch (res) { - case ALC_MIC_EVENT: - alc88x_simple_mic_automute(codec); - break; - default: - alc_exec_unsol_event(codec, res); - break; - } -} - /* * ASUS pin configuration: * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a @@ -911,7 +810,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_ASUS_W1V] = "asus-w1v", [ALC880_ASUS_DIG] = "asus-dig", [ALC880_ASUS_DIG2] = "asus-dig2", - [ALC880_UNIWILL_DIG] = "uniwill", #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = "test", #endif @@ -955,7 +853,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), - SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ @@ -1123,21 +1020,6 @@ static const struct alc_config_preset alc880_presets[] = { .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, - [ALC880_UNIWILL] = { - .mixers = { alc880_uniwill_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_uniwill_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - .unsol_event = alc880_uniwill_unsol_event, - .setup = alc880_uniwill_setup, - .init_hook = alc880_uniwill_init_hook, - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c index b344603ac06d..a63a517780d6 100644 --- a/sound/pci/hda/alc_quirks.c +++ b/sound/pci/hda/alc_quirks.c @@ -165,15 +165,3 @@ static void alc_simple_setup_automute(struct alc_spec *spec, int mode) spec->automute_lo = spec->automute_lo_possible = !!lo_pin; spec->automute_speaker = spec->automute_speaker_possible = !!spec->autocfg.speaker_pins[0]; } - -/* auto-toggle front mic */ -static void alc88x_simple_mic_automute(struct hda_codec *codec) -{ - unsigned int present; - unsigned char bits; - - present = snd_hda_jack_detect(codec, 0x18); - bits = present ? HDA_AMP_MUTE : 0; - snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); -} - diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3c0a46ed9ca9..ff4410cf75a6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4447,6 +4447,7 @@ enum { ALC880_FIXUP_VOL_KNOB, ALC880_FIXUP_FUJITSU, ALC880_FIXUP_F1734, + ALC880_FIXUP_UNIWILL, }; /* enable the volume-knob widget support on NID 0x21 */ @@ -4556,12 +4557,23 @@ static const struct alc_fixup alc880_fixups[] = { .chained = true, .chain_id = ALC880_FIXUP_VOL_KNOB, }, + [ALC880_FIXUP_UNIWILL] = { + /* need to fix HP and speaker pins to be parsed correctly */ + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x14, 0x0121411f }, /* HP */ + { 0x15, 0x99030120 }, /* speaker */ + { 0x16, 0x99030130 }, /* bass speaker */ + { } + }, + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), + SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL), SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), -- cgit v1.2.3 From 967b88c47744f7ec424c71630c1f551d34e08eef Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 17:31:02 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=uniwill-dig with auto-parser ALC880 model=uniwill-dig requires the fix-up of bogus BIOS pin default configurations. Other than that, it's pretty normal. Signed-off-by: Takashi Iwai --- sound/pci/hda/alc880_quirks.c | 14 -------------- sound/pci/hda/patch_realtek.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index c40f2446fcc4..59899f8b056f 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -17,7 +17,6 @@ enum { ALC880_ASUS_DIG, ALC880_ASUS_W1V, ALC880_ASUS_DIG2, - ALC880_UNIWILL_DIG, #ifdef CONFIG_SND_DEBUG ALC880_TEST, #endif @@ -852,7 +851,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ @@ -1008,18 +1006,6 @@ static const struct alc_config_preset alc880_presets[] = { .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, - [ALC880_UNIWILL_DIG] = { - .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_asus_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ff4410cf75a6..e88c753743dc 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4448,6 +4448,7 @@ enum { ALC880_FIXUP_FUJITSU, ALC880_FIXUP_F1734, ALC880_FIXUP_UNIWILL, + ALC880_FIXUP_UNIWILL_DIG, }; /* enable the volume-knob widget support on NID 0x21 */ @@ -4567,11 +4568,23 @@ static const struct alc_fixup alc880_fixups[] = { { } }, }, + [ALC880_FIXUP_UNIWILL_DIG] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + /* disable bogus unused pins */ + { 0x17, 0x411111f0 }, + { 0x19, 0x411111f0 }, + { 0x1b, 0x411111f0 }, + { 0x1f, 0x411111f0 }, + { } + } + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), + SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL), SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), -- cgit v1.2.3 From 96e225f6922ecf3afafb55fdb0e6e771b3f71e94 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 17:41:51 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=z71v with auto-parser ASUS Z71V has a totally broken BIOS setup (at least the info I got), thus we need to override the whole pin-config table to make the auto-parser working correctly. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 58 ---------------------------- sound/pci/hda/patch_realtek.c | 20 ++++++++++ 3 files changed, 20 insertions(+), 59 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 1af6354ec549..43f3c7113950 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -8,7 +8,6 @@ ALC880 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out 6stack 6-jack in back, 2-jack in front 6stack-digout 6-jack with a SPDIF out - z71v 3-jack (HP shared SPDIF) asus 3-jack (ASUS Mobo) asus-w1v ASUS W1V asus-dig ASUS with SPDIF out diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 59899f8b056f..6caa2010a851 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -10,7 +10,6 @@ enum { ALC880_3ST_DIG, ALC880_5ST, ALC880_5ST_DIG, - ALC880_Z71V, ALC880_6ST, ALC880_6ST_DIG, ALC880_ASUS, @@ -223,36 +222,11 @@ static const hda_nid_t alc880_w810_dac_nids[3] = { 0x02, 0x03, 0x04 }; -/* - * Z710V model - * - * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) - * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), - * Line = 0x1a - */ - -static const hda_nid_t alc880_z71v_dac_nids[1] = { - 0x02 -}; -#define ALC880_Z71V_HP_DAC 0x03 - /* fixed 2 channels */ static const struct hda_channel_mode alc880_2_jack_modes[1] = { { 2, NULL } }; -static const struct snd_kcontrol_new alc880_z71v_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - { } /* end */ -}; - /* * ALC880 ASUS model * @@ -440,24 +414,6 @@ static const struct hda_verb alc880_pin_5stack_init_verbs[] = { { } }; -/* - * Z71V pin configuration: - * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) - */ -static const struct hda_verb alc880_pin_z71v_init_verbs[] = { - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - { } -}; - /* * 6-stack pin configuration: * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, @@ -802,7 +758,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_3ST_DIG] = "3stack-digout", [ALC880_5ST] = "5stack", [ALC880_5ST_DIG] = "5stack-digout", - [ALC880_Z71V] = "z71v", [ALC880_6ST] = "6stack", [ALC880_6ST_DIG] = "6stack-digout", [ALC880_ASUS] = "asus", @@ -831,7 +786,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V), /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), @@ -943,18 +897,6 @@ static const struct alc_config_preset alc880_presets[] = { .channel_mode = alc880_sixstack_modes, .input_mux = &alc880_6stack_capture_source, }, - [ALC880_Z71V] = { - .mixers = { alc880_z71v_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_z71v_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), - .dac_nids = alc880_z71v_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .hp_nid = 0x03, - .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), - .channel_mode = alc880_2_jack_modes, - .input_mux = &alc880_capture_source, - }, [ALC880_ASUS] = { .mixers = { alc880_asus_mixer }, .init_verbs = { alc880_volume_init_verbs, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e88c753743dc..71acd9b9a88d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4449,6 +4449,7 @@ enum { ALC880_FIXUP_F1734, ALC880_FIXUP_UNIWILL, ALC880_FIXUP_UNIWILL_DIG, + ALC880_FIXUP_Z71V, }; /* enable the volume-knob widget support on NID 0x21 */ @@ -4579,10 +4580,29 @@ static const struct alc_fixup alc880_fixups[] = { { } } }, + [ALC880_FIXUP_Z71V] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + /* set up the whole pins as BIOS is utterly broken */ + { 0x14, 0x99030120 }, /* speaker */ + { 0x15, 0x0121411f }, /* HP */ + { 0x16, 0x411111f0 }, /* N/A */ + { 0x17, 0x411111f0 }, /* N/A */ + { 0x18, 0x01a19950 }, /* mic-in */ + { 0x19, 0x411111f0 }, /* N/A */ + { 0x1a, 0x01813031 }, /* line-in */ + { 0x1b, 0x411111f0 }, /* N/A */ + { 0x1c, 0x411111f0 }, /* N/A */ + { 0x1d, 0x411111f0 }, /* N/A */ + { 0x1e, 0x0144111e }, /* SPDIF */ + { } + } + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), + SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), -- cgit v1.2.3 From 411225a01e57189b4116d5c61c0d64bd4b76e602 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 17:48:19 +0100 Subject: ALSA: hda/realtek - Rewrite ALC880 model=asus-w1v with auto-parser ASUS W1V has a sane pin-config table set by BIOS. The only missing piece is the setup of GPIO1. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 - sound/pci/hda/alc880_quirks.c | 31 ---------------------------- sound/pci/hda/patch_realtek.c | 6 ++++++ 3 files changed, 6 insertions(+), 32 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 43f3c7113950..f18206799850 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -9,7 +9,6 @@ ALC880 6stack 6-jack in back, 2-jack in front 6stack-digout 6-jack with a SPDIF out asus 3-jack (ASUS Mobo) - asus-w1v ASUS W1V asus-dig ASUS with SPDIF out asus-dig2 ASUS with SPDIF out (using GPIO2) test for testing/debugging purpose, almost all controls can be diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 6caa2010a851..c8af01b7f853 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -14,7 +14,6 @@ enum { ALC880_6ST_DIG, ALC880_ASUS, ALC880_ASUS_DIG, - ALC880_ASUS_W1V, ALC880_ASUS_DIG2, #ifdef CONFIG_SND_DEBUG ALC880_TEST, @@ -263,21 +262,6 @@ static const struct snd_kcontrol_new alc880_asus_mixer[] = { { } /* end */ }; -/* - * ALC880 ASUS W1V model - * - * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) - * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, - * Mic = 0x18, Line = 0x1a, Line2 = 0x1b - */ - -/* additional mixers to alc880_asus_mixer */ -static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { - HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), - { } /* end */ -}; - /* * initialize the codec volumes, etc */ @@ -761,7 +745,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_6ST] = "6stack", [ALC880_6ST_DIG] = "6stack-digout", [ALC880_ASUS] = "asus", - [ALC880_ASUS_W1V] = "asus-w1v", [ALC880_ASUS_DIG] = "asus-dig", [ALC880_ASUS_DIG2] = "asus-dig2", #ifdef CONFIG_SND_DEBUG @@ -780,7 +763,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), @@ -935,19 +917,6 @@ static const struct alc_config_preset alc880_presets[] = { .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, - [ALC880_ASUS_W1V] = { - .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_asus_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 71acd9b9a88d..510ca928b840 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4438,6 +4438,7 @@ static const struct hda_amp_list alc880_loopbacks[] = { * ALC880 fix-ups */ enum { + ALC880_FIXUP_GPIO1, ALC880_FIXUP_GPIO2, ALC880_FIXUP_MEDION_RIM, ALC880_FIXUP_LG, @@ -4461,6 +4462,10 @@ static void alc880_fixup_vol_knob(struct hda_codec *codec, } static const struct alc_fixup alc880_fixups[] = { + [ALC880_FIXUP_GPIO1] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = alc_gpio1_init_verbs, + }, [ALC880_FIXUP_GPIO2] = { .type = ALC_FIXUP_VERBS, .v.verbs = alc_gpio2_init_verbs, @@ -4602,6 +4607,7 @@ static const struct alc_fixup alc880_fixups[] = { static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), + SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_FIXUP_GPIO1), SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), -- cgit v1.2.3 From 29e3fdcc84e5da04cb7e6a36fee0a772c91d3b28 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 17:56:57 +0100 Subject: ALSA: hda/realtek - Drop model=asus* from ALC880 It turned out that BIOS on most of ASUS mobo's set the pin-config tables reasonably well for the auto-parser. We'd need GPIO setups, but should work as is other than that. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 3 - sound/pci/hda/alc880_quirks.c | 127 +-------------------------- sound/pci/hda/patch_realtek.c | 3 +- 3 files changed, 3 insertions(+), 130 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index f18206799850..62a67896fcaf 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -8,9 +8,6 @@ ALC880 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out 6stack 6-jack in back, 2-jack in front 6stack-digout 6-jack with a SPDIF out - asus 3-jack (ASUS Mobo) - asus-dig ASUS with SPDIF out - asus-dig2 ASUS with SPDIF out (using GPIO2) test for testing/debugging purpose, almost all controls can be adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index c8af01b7f853..6917d78d4dcd 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -12,9 +12,6 @@ enum { ALC880_5ST_DIG, ALC880_6ST, ALC880_6ST_DIG, - ALC880_ASUS, - ALC880_ASUS_DIG, - ALC880_ASUS_DIG2, #ifdef CONFIG_SND_DEBUG ALC880_TEST, #endif @@ -226,42 +223,6 @@ static const struct hda_channel_mode alc880_2_jack_modes[1] = { { 2, NULL } }; -/* - * ALC880 ASUS model - * - * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) - * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, - * Mic = 0x18, Line = 0x1a - */ - -#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ -#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ - -static const struct snd_kcontrol_new alc880_asus_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - /* * initialize the codec volumes, etc */ @@ -433,38 +394,6 @@ static const struct hda_verb alc880_beep_init_verbs[] = { { } }; -/* - * ASUS pin configuration: - * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a - */ -static const struct hda_verb alc880_pin_asus_init_verbs[] = { - {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - { } -}; - /* Enable GPIO mask and set output */ #define alc880_gpio1_init_verbs alc_gpio1_init_verbs #define alc880_gpio2_init_verbs alc_gpio2_init_verbs @@ -744,9 +673,6 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = { [ALC880_5ST_DIG] = "5stack-digout", [ALC880_6ST] = "6stack", [ALC880_6ST_DIG] = "6stack-digout", - [ALC880_ASUS] = "asus", - [ALC880_ASUS_DIG] = "asus-dig", - [ALC880_ASUS_DIG2] = "asus-dig2", #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = "test", #endif @@ -763,19 +689,7 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG), - /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ - SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), - SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), - SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), - SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */ + SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), @@ -785,7 +699,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), @@ -879,44 +792,6 @@ static const struct alc_config_preset alc880_presets[] = { .channel_mode = alc880_sixstack_modes, .input_mux = &alc880_6stack_capture_source, }, - [ALC880_ASUS] = { - .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_asus_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, - [ALC880_ASUS_DIG] = { - .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_asus_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, - [ALC880_ASUS_DIG2] = { - .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_asus_init_verbs, - alc880_gpio2_init_verbs }, /* use GPIO2 */ - .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), - .dac_nids = alc880_asus_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), - .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, #ifdef CONFIG_SND_DEBUG [ALC880_TEST] = { .mixers = { alc880_test_mixer }, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 510ca928b840..fce31b050f42 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4607,8 +4607,9 @@ static const struct alc_fixup alc880_fixups[] = { static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), - SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_FIXUP_GPIO1), SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), + SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1), + SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), -- cgit v1.2.3 From 67b6ec3196da235317ff1b9474f17379b78f3294 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 18:20:42 +0100 Subject: ALSA: hda/realtek - Drop all ALC880 static quirks Finally the all static quirks for ALC880 are converted to the auto-parser. Since we are never sure whether the BIOS on so many old machines are really correct, the quirk table entries are copied as they are, but just providing the proper pin-config values accordingly. Since alc880_quirks.c is removed, alc882_quirks.c has to be adjusted slightly to be built again. There might be some compile warnings due to the remaining alc882 quirks, but these shall be killed sooner or later, I don't care it much at this point. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 4 - sound/pci/hda/alc880_quirks.c | 808 --------------------------- sound/pci/hda/alc882_quirks.c | 24 +- sound/pci/hda/patch_realtek.c | 219 ++++++-- 4 files changed, 195 insertions(+), 860 deletions(-) delete mode 100644 sound/pci/hda/alc880_quirks.c (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 62a67896fcaf..1f64fb810522 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -8,10 +8,6 @@ ALC880 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out 6stack 6-jack in back, 2-jack in front 6stack-digout 6-jack with a SPDIF out - test for testing/debugging purpose, almost all controls can be - adjusted. Appearing only when compiled with - $CONFIG_SND_DEBUG=y - auto auto-config reading BIOS (default) ALC260 ====== diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c deleted file mode 100644 index 6917d78d4dcd..000000000000 --- a/sound/pci/hda/alc880_quirks.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * ALC880 quirk models - * included by patch_realtek.c - */ - -/* ALC880 board config type */ -enum { - ALC880_AUTO, - ALC880_3ST, - ALC880_3ST_DIG, - ALC880_5ST, - ALC880_5ST_DIG, - ALC880_6ST, - ALC880_6ST_DIG, -#ifdef CONFIG_SND_DEBUG - ALC880_TEST, -#endif - ALC880_MODEL_LAST /* last tag */ -}; - -/* - * ALC880 3-stack model - * - * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) - * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, - * F-Mic = 0x1b, HP = 0x19 - */ - -static const hda_nid_t alc880_dac_nids[4] = { - /* front, rear, clfe, rear_surr */ - 0x02, 0x05, 0x04, 0x03 -}; - -static const hda_nid_t alc880_adc_nids[3] = { - /* ADC0-2 */ - 0x07, 0x08, 0x09, -}; - -/* The datasheet says the node 0x07 is connected from inputs, - * but it shows zero connection in the real implementation on some devices. - * Note: this is a 915GAV bug, fixed on 915GLV - */ -static const hda_nid_t alc880_adc_nids_alt[2] = { - /* ADC1-2 */ - 0x08, 0x09, -}; - -#define ALC880_DIGOUT_NID 0x06 -#define ALC880_DIGIN_NID 0x0a -#define ALC880_PIN_CD_NID 0x1c - -static const struct hda_input_mux alc880_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x3 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -/* channel source setting (2/6 channel selection for 3-stack) */ -/* 2ch mode */ -static const struct hda_verb alc880_threestack_ch2_init[] = { - /* set line-in to input, mute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - /* set mic-in to input vref 80%, mute it */ - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* 6ch mode */ -static const struct hda_verb alc880_threestack_ch6_init[] = { - /* set line-in to output, unmute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - /* set mic-in to output, unmute it */ - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { } /* end */ -}; - -static const struct hda_channel_mode alc880_threestack_modes[2] = { - { 2, alc880_threestack_ch2_init }, - { 6, alc880_threestack_ch6_init }, -}; - -static const struct snd_kcontrol_new alc880_three_stack_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - -/* - * ALC880 5-stack model - * - * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), - * Side = 0x02 (0xd) - * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 - * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 - */ - -/* additional mixers to alc880_three_stack_mixer */ -static const struct snd_kcontrol_new alc880_five_stack_mixer[] = { - HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), - { } /* end */ -}; - -/* channel source setting (6/8 channel selection for 5-stack) */ -/* 6ch mode */ -static const struct hda_verb alc880_fivestack_ch6_init[] = { - /* set line-in to input, mute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* 8ch mode */ -static const struct hda_verb alc880_fivestack_ch8_init[] = { - /* set line-in to output, unmute it */ - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { } /* end */ -}; - -static const struct hda_channel_mode alc880_fivestack_modes[2] = { - { 6, alc880_fivestack_ch6_init }, - { 8, alc880_fivestack_ch8_init }, -}; - - -/* - * ALC880 6-stack model - * - * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), - * Side = 0x05 (0x0f) - * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, - * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b - */ - -static const hda_nid_t alc880_6st_dac_nids[4] = { - /* front, rear, clfe, rear_surr */ - 0x02, 0x03, 0x04, 0x05 -}; - -static const struct hda_input_mux alc880_6stack_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -/* fixed 8-channels */ -static const struct hda_channel_mode alc880_sixstack_modes[1] = { - { 8, NULL }, -}; - -static const struct snd_kcontrol_new alc880_six_stack_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - - -static const hda_nid_t alc880_w810_dac_nids[3] = { - /* front, rear/surround, clfe */ - 0x02, 0x03, 0x04 -}; - -/* fixed 2 channels */ -static const struct hda_channel_mode alc880_2_jack_modes[1] = { - { 2, NULL } -}; - -/* - * initialize the codec volumes, etc - */ - -/* - * generic initialization of ADC, input mixers and output mixers - */ -static const struct hda_verb alc880_volume_init_verbs[] = { - /* - * Unmute ADC0-2 and set the default input to mic-in - */ - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback - * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front - * panel mic (mic 2) - */ - /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, - - /* - * Set up output mixers (0x0c - 0x0f) - */ - /* set vol=0 to output mixers */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* set up input amps for analog loopback */ - /* Amp Indices: DAC = 0, mixer = 1 */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - - { } -}; - -/* - * 3-stack pin configuration: - * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b - */ -static const struct hda_verb alc880_pin_3stack_init_verbs[] = { - /* - * preset connection lists of input pins - * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround - */ - {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ - - /* - * Set pin mode and muting - */ - /* set front pin widgets 0x14 for output */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Mic1 (rear panel) pin widget for input and vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mic2 (as headphone out) for HP output */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Line In pin widget for input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line2 (as front mic) pin widget for input and vref at 80% */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - { } -}; - -/* - * 5-stack pin configuration: - * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, - * line-in/side = 0x1a, f-mic = 0x1b - */ -static const struct hda_verb alc880_pin_5stack_init_verbs[] = { - /* - * preset connection lists of input pins - * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround - */ - {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ - - /* - * Set pin mode and muting - */ - /* set pin widgets 0x14-0x17 for output */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* unmute pins for output (no gain on this amp) */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Mic1 (rear panel) pin widget for input and vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mic2 (as headphone out) for HP output */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Line In pin widget for input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line2 (as front mic) pin widget for input and vref at 80% */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - { } -}; - -/* - * 6-stack pin configuration: - * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, - * f-mic = 0x19, line = 0x1a, HP = 0x1b - */ -static const struct hda_verb alc880_pin_6stack_init_verbs[] = { - {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - { } -}; - -static const struct hda_verb alc880_beep_init_verbs[] = { - { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, - { } -}; - -/* Enable GPIO mask and set output */ -#define alc880_gpio1_init_verbs alc_gpio1_init_verbs -#define alc880_gpio2_init_verbs alc_gpio2_init_verbs -#define alc880_gpio3_init_verbs alc_gpio3_init_verbs - -/* - * Test configuration for debugging - * - * Almost all inputs/outputs are enabled. I/O pins can be configured via - * enum controls. - */ -#ifdef CONFIG_SND_DEBUG -static const hda_nid_t alc880_test_dac_nids[4] = { - 0x02, 0x03, 0x04, 0x05 -}; - -static const struct hda_input_mux alc880_test_capture_source = { - .num_items = 7, - .items = { - { "In-1", 0x0 }, - { "In-2", 0x1 }, - { "In-3", 0x2 }, - { "In-4", 0x3 }, - { "CD", 0x4 }, - { "Front", 0x5 }, - { "Surround", 0x6 }, - }, -}; - -static const struct hda_channel_mode alc880_test_modes[4] = { - { 2, NULL }, - { 4, NULL }, - { 6, NULL }, - { 8, NULL }, -}; - -static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "N/A", "Line Out", "HP Out", - "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item >= 8) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - unsigned int pin_ctl, item = 0; - - pin_ctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - if (pin_ctl & AC_PINCTL_OUT_EN) { - if (pin_ctl & AC_PINCTL_HP_EN) - item = 2; - else - item = 1; - } else if (pin_ctl & AC_PINCTL_IN_EN) { - switch (pin_ctl & AC_PINCTL_VREFEN) { - case AC_PINCTL_VREF_HIZ: item = 3; break; - case AC_PINCTL_VREF_50: item = 4; break; - case AC_PINCTL_VREF_GRD: item = 5; break; - case AC_PINCTL_VREF_80: item = 6; break; - case AC_PINCTL_VREF_100: item = 7; break; - } - } - ucontrol->value.enumerated.item[0] = item; - return 0; -} - -static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - static const unsigned int ctls[] = { - 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, - }; - unsigned int old_ctl, new_ctl; - - old_ctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - new_ctl = ctls[ucontrol->value.enumerated.item[0]]; - if (old_ctl != new_ctl) { - int val; - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - new_ctl); - val = ucontrol->value.enumerated.item[0] >= 3 ? - HDA_AMP_MUTE : 0; - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, val); - return 1; - } - return 0; -} - -static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "Front", "Surround", "CLFE", "Side" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= 4) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - unsigned int sel; - - sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); - ucontrol->value.enumerated.item[0] = sel & 3; - return 0; -} - -static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = (hda_nid_t)kcontrol->private_value; - unsigned int sel; - - sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; - if (ucontrol->value.enumerated.item[0] != sel) { - sel = ucontrol->value.enumerated.item[0] & 3; - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, sel); - return 1; - } - return 0; -} - -#define PIN_CTL_TEST(xname,nid) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ - .info = alc_test_pin_ctl_info, \ - .get = alc_test_pin_ctl_get, \ - .put = alc_test_pin_ctl_put, \ - .private_value = nid \ - } - -#define PIN_SRC_TEST(xname,nid) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ - .info = alc_test_pin_src_info, \ - .get = alc_test_pin_src_get, \ - .put = alc_test_pin_src_put, \ - .private_value = nid \ - } - -static const struct snd_kcontrol_new alc880_test_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), - HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), - PIN_CTL_TEST("Front Pin Mode", 0x14), - PIN_CTL_TEST("Surround Pin Mode", 0x15), - PIN_CTL_TEST("CLFE Pin Mode", 0x16), - PIN_CTL_TEST("Side Pin Mode", 0x17), - PIN_CTL_TEST("In-1 Pin Mode", 0x18), - PIN_CTL_TEST("In-2 Pin Mode", 0x19), - PIN_CTL_TEST("In-3 Pin Mode", 0x1a), - PIN_CTL_TEST("In-4 Pin Mode", 0x1b), - PIN_SRC_TEST("In-1 Pin Source", 0x18), - PIN_SRC_TEST("In-2 Pin Source", 0x19), - PIN_SRC_TEST("In-3 Pin Source", 0x1a), - PIN_SRC_TEST("In-4 Pin Source", 0x1b), - HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - -static const struct hda_verb alc880_test_init_verbs[] = { - /* Unmute inputs of 0x0c - 0x0f */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Vol output for 0x0c-0x0f */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Set output pins 0x14-0x17 */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Unmute output pins 0x14-0x17 */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Set input pins 0x18-0x1c */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* Mute input pins 0x18-0x1b */ - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* ADC set up */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Analog input/passthru */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - { } -}; -#endif - -/* - */ - -static const char * const alc880_models[ALC880_MODEL_LAST] = { - [ALC880_3ST] = "3stack", - [ALC880_3ST_DIG] = "3stack-digout", - [ALC880_5ST] = "5stack", - [ALC880_5ST_DIG] = "5stack-digout", - [ALC880_6ST] = "6stack", - [ALC880_6ST_DIG] = "6stack-digout", -#ifdef CONFIG_SND_DEBUG - [ALC880_TEST] = "test", -#endif - [ALC880_AUTO] = "auto", -}; - -static const struct snd_pci_quirk alc880_cfg_tbl[] = { - SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST), - SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG), - SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), - SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), - SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), - - SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), - SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), - SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), - SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST), - SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST), - SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), - SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ - SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), - SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), - /* default Intel */ - SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST), - SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), - SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), - {} -}; - -/* - * ALC880 codec presets - */ -static const struct alc_config_preset alc880_presets[] = { - [ALC880_3ST] = { - .mixers = { alc880_three_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_3stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, - [ALC880_3ST_DIG] = { - .mixers = { alc880_three_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_3stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, - .input_mux = &alc880_capture_source, - }, - [ALC880_5ST] = { - .mixers = { alc880_three_stack_mixer, - alc880_five_stack_mixer}, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_5stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), - .channel_mode = alc880_fivestack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_5ST_DIG] = { - .mixers = { alc880_three_stack_mixer, - alc880_five_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_5stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_dac_nids), - .dac_nids = alc880_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), - .channel_mode = alc880_fivestack_modes, - .input_mux = &alc880_capture_source, - }, - [ALC880_6ST] = { - .mixers = { alc880_six_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_6stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), - .dac_nids = alc880_6st_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), - .channel_mode = alc880_sixstack_modes, - .input_mux = &alc880_6stack_capture_source, - }, - [ALC880_6ST_DIG] = { - .mixers = { alc880_six_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, - alc880_pin_6stack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), - .dac_nids = alc880_6st_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), - .channel_mode = alc880_sixstack_modes, - .input_mux = &alc880_6stack_capture_source, - }, -#ifdef CONFIG_SND_DEBUG - [ALC880_TEST] = { - .mixers = { alc880_test_mixer }, - .init_verbs = { alc880_test_init_verbs }, - .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), - .dac_nids = alc880_test_dac_nids, - .dig_out_nid = ALC880_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_test_modes), - .channel_mode = alc880_test_modes, - .input_mux = &alc880_test_capture_source, - }, -#endif -}; - diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c index bb364a53f546..0f4292688e18 100644 --- a/sound/pci/hda/alc882_quirks.c +++ b/sound/pci/hda/alc882_quirks.c @@ -34,8 +34,16 @@ static const hda_nid_t alc882_dac_nids[4] = { #define alc883_dac_nids alc882_dac_nids /* ADCs */ -#define alc882_adc_nids alc880_adc_nids -#define alc882_adc_nids_alt alc880_adc_nids_alt +static const hda_nid_t alc882_adc_nids[3] = { + /* ADC0-2 */ + 0x07, 0x08, 0x09, +}; + +static const hda_nid_t alc882_adc_nids_alt[2] = { + /* ADC1-2 */ + 0x08, 0x09, +}; + #define alc883_adc_nids alc882_adc_nids_alt static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 }; @@ -774,7 +782,7 @@ static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { static const struct alc_config_preset alc882_presets[] = { [ALC885_MBA21] = { .mixers = { alc885_mba21_mixer }, - .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs }, + .init_verbs = { alc885_mba21_init_verbs, alc_gpio1_init_verbs }, .num_dacs = 2, .dac_nids = alc882_dac_nids, .channel_mode = alc885_mba21_ch_modes, @@ -787,7 +795,7 @@ static const struct alc_config_preset alc882_presets[] = { [ALC885_MBP3] = { .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, .init_verbs = { alc885_mbp3_init_verbs, - alc880_gpio1_init_verbs }, + alc_gpio1_init_verbs }, .num_dacs = 2, .dac_nids = alc882_dac_nids, .hp_nid = 0x04, @@ -803,7 +811,7 @@ static const struct alc_config_preset alc882_presets[] = { [ALC885_MB5] = { .mixers = { alc885_mb5_mixer, alc882_chmode_mixer }, .init_verbs = { alc885_mb5_init_verbs, - alc880_gpio1_init_verbs }, + alc_gpio1_init_verbs }, .num_dacs = ARRAY_SIZE(alc882_dac_nids), .dac_nids = alc882_dac_nids, .channel_mode = alc885_mb5_6ch_modes, @@ -818,7 +826,7 @@ static const struct alc_config_preset alc882_presets[] = { [ALC885_MACMINI3] = { .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer }, .init_verbs = { alc885_macmini3_init_verbs, - alc880_gpio1_init_verbs }, + alc_gpio1_init_verbs }, .num_dacs = ARRAY_SIZE(alc882_dac_nids), .dac_nids = alc882_dac_nids, .channel_mode = alc885_macmini3_6ch_modes, @@ -833,7 +841,7 @@ static const struct alc_config_preset alc882_presets[] = { [ALC885_IMAC91] = { .mixers = {alc885_imac91_mixer}, .init_verbs = { alc885_imac91_init_verbs, - alc880_gpio1_init_verbs }, + alc_gpio1_init_verbs }, .num_dacs = ARRAY_SIZE(alc882_dac_nids), .dac_nids = alc882_dac_nids, .channel_mode = alc885_mba21_ch_modes, @@ -848,7 +856,7 @@ static const struct alc_config_preset alc882_presets[] = { [ALC889A_MB31] = { .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer}, .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs, - alc880_gpio1_init_verbs }, + alc_gpio1_init_verbs }, .adc_nids = alc883_adc_nids, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), .capsrc_nids = alc883_capsrc_nids, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fce31b050f42..4ac1e3830af4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4451,6 +4451,15 @@ enum { ALC880_FIXUP_UNIWILL, ALC880_FIXUP_UNIWILL_DIG, ALC880_FIXUP_Z71V, + ALC880_FIXUP_3ST_BASE, + ALC880_FIXUP_3ST, + ALC880_FIXUP_3ST_DIG, + ALC880_FIXUP_5ST_BASE, + ALC880_FIXUP_5ST, + ALC880_FIXUP_5ST_DIG, + ALC880_FIXUP_6ST_BASE, + ALC880_FIXUP_6ST, + ALC880_FIXUP_6ST_DIG, }; /* enable the volume-knob widget support on NID 0x21 */ @@ -4603,6 +4612,114 @@ static const struct alc_fixup alc880_fixups[] = { { } } }, + [ALC880_FIXUP_3ST_BASE] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x14, 0x01014010 }, /* line-out */ + { 0x15, 0x411111f0 }, /* N/A */ + { 0x16, 0x411111f0 }, /* N/A */ + { 0x17, 0x411111f0 }, /* N/A */ + { 0x18, 0x01a19c30 }, /* mic-in */ + { 0x19, 0x0121411f }, /* HP */ + { 0x1a, 0x01813031 }, /* line-in */ + { 0x1b, 0x02a19c40 }, /* front-mic */ + { 0x1c, 0x411111f0 }, /* N/A */ + { 0x1d, 0x411111f0 }, /* N/A */ + /* 0x1e is filled in below */ + { 0x1f, 0x411111f0 }, /* N/A */ + { } + } + }, + [ALC880_FIXUP_3ST] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1e, 0x411111f0 }, /* N/A */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_3ST_BASE, + }, + [ALC880_FIXUP_3ST_DIG] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1e, 0x0144111e }, /* SPDIF */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_3ST_BASE, + }, + [ALC880_FIXUP_5ST_BASE] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x14, 0x01014010 }, /* front */ + { 0x15, 0x411111f0 }, /* N/A */ + { 0x16, 0x01011411 }, /* CLFE */ + { 0x17, 0x01016412 }, /* surr */ + { 0x18, 0x01a19c30 }, /* mic-in */ + { 0x19, 0x0121411f }, /* HP */ + { 0x1a, 0x01813031 }, /* line-in */ + { 0x1b, 0x02a19c40 }, /* front-mic */ + { 0x1c, 0x411111f0 }, /* N/A */ + { 0x1d, 0x411111f0 }, /* N/A */ + /* 0x1e is filled in below */ + { 0x1f, 0x411111f0 }, /* N/A */ + { } + } + }, + [ALC880_FIXUP_5ST] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1e, 0x411111f0 }, /* N/A */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_5ST_BASE, + }, + [ALC880_FIXUP_5ST_DIG] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1e, 0x0144111e }, /* SPDIF */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_5ST_BASE, + }, + [ALC880_FIXUP_6ST_BASE] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x14, 0x01014010 }, /* front */ + { 0x15, 0x01016412 }, /* surr */ + { 0x16, 0x01011411 }, /* CLFE */ + { 0x17, 0x01012414 }, /* side */ + { 0x18, 0x01a19c30 }, /* mic-in */ + { 0x19, 0x02a19c40 }, /* front-mic */ + { 0x1a, 0x01813031 }, /* line-in */ + { 0x1b, 0x0121411f }, /* HP */ + { 0x1c, 0x411111f0 }, /* N/A */ + { 0x1d, 0x411111f0 }, /* N/A */ + /* 0x1e is filled in below */ + { 0x1f, 0x411111f0 }, /* N/A */ + { } + } + }, + [ALC880_FIXUP_6ST] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1e, 0x411111f0 }, /* N/A */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_6ST_BASE, + }, + [ALC880_FIXUP_6ST_DIG] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1e, 0x0144111e }, /* SPDIF */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_6ST_BASE, + }, }; static const struct snd_pci_quirk alc880_fixup_tbl[] = { @@ -4625,6 +4742,60 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700), + + /* Below is the copied entries from alc880_quirks.c. + * It's not quite sure whether BIOS sets the correct pin-config table + * on these machines, thus they are kept to be compatible with + * the old static quirks. Once when it's confirmed to work without + * these overrides, it'd be better to remove. + */ + SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST), + SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG), + SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG), + SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST), + SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST), + SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST), + SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST), + SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST), + SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST), + SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */ + SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG), + SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG), + SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG), + SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG), + SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG), + /* default Intel */ + SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST), + SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG), + SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG), + {} +}; + +static const struct alc_model_fixup alc880_fixup_models[] = { + {.id = ALC880_FIXUP_3ST, .name = "3stack"}, + {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"}, + {.id = ALC880_FIXUP_5ST, .name = "5stack"}, + {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"}, + {.id = ALC880_FIXUP_6ST, .name = "6stack"}, + {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"}, {} }; @@ -4647,14 +4818,9 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { /* * OK, here we have finally the patch for ALC880 */ -#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS -#include "alc880_quirks.c" -#endif - static int patch_alc880(struct hda_codec *codec) { struct alc_spec *spec; - int board_config; int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -4666,38 +4832,14 @@ static int patch_alc880(struct hda_codec *codec) spec->mixer_nid = 0x0b; spec->need_dac_fix = 1; - board_config = alc_board_config(codec, ALC880_MODEL_LAST, - alc880_models, alc880_cfg_tbl); - if (board_config < 0) { - printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - board_config = ALC_MODEL_AUTO; - } - - if (board_config == ALC_MODEL_AUTO) { - alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - } - - if (board_config == ALC_MODEL_AUTO) { - /* automatic parse from the BIOS config */ - err = alc880_parse_auto_config(codec); - if (err < 0) - goto error; -#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS - else if (!err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using 3-stack mode...\n"); - board_config = ALC880_3ST; - } -#endif - } + alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, + alc880_fixups); + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - if (board_config != ALC_MODEL_AUTO) { - spec->vmaster_nid = 0x0c; - setup_preset(codec, &alc880_presets[board_config]); - } + /* automatic parse from the BIOS config */ + err = alc880_parse_auto_config(codec); + if (err < 0) + goto error; if (!spec->no_analog && !spec->adc_nids) { alc_auto_fill_adc_caps(codec); @@ -4716,10 +4858,7 @@ static int patch_alc880(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - if (board_config == ALC_MODEL_AUTO) - spec->init_hook = alc_auto_init_std; - else - codec->patch_ops.build_controls = __alc_build_controls; + spec->init_hook = alc_auto_init_std; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) spec->loopback.amplist = alc880_loopbacks; -- cgit v1.2.3 From 9155f82a6a26da4a5b8d2d29f1d31836906b4712 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 18:41:02 +0100 Subject: ALSA: hda/realtek - Add model=fixup not to apply fix-ups If anyone wants to debug the driver and avoid the existing fix-ups, pass model=nofixup option. Then the driver will skip to pick up the fixup list. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4ac1e3830af4..3c6f5b5161f0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1556,6 +1556,13 @@ static void alc_pick_fixup(struct hda_codec *codec, int id = -1; const char *name = NULL; + /* when model=nofixup is given, don't pick up any fixups */ + if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { + spec->fixup_list = NULL; + spec->fixup_id = -1; + return; + } + if (codec->modelname && models) { while (models->name) { if (!strcmp(codec->modelname, models->name)) { -- cgit v1.2.3 From 1a97b7f22774b454531f013638b181803fba470f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Feb 2012 11:11:48 +0100 Subject: ALSA: hda/realtek - Remove the last static quirks for ALC882 Resitance is futile. The remaining static model quirks for Apple machines with ALC882-compatible codecs are converted to the auto-parser now. We can remove all alc*_quirks.c finally. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 50 +- sound/pci/hda/alc882_quirks.c | 874 --------------------------- sound/pci/hda/alc_quirks.c | 167 ----- sound/pci/hda/patch_realtek.c | 143 +++-- 4 files changed, 93 insertions(+), 1141 deletions(-) delete mode 100644 sound/pci/hda/alc882_quirks.c delete mode 100644 sound/pci/hda/alc_quirks.c (limited to 'sound') diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 1f64fb810522..d97d992ced14 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -43,55 +43,7 @@ ALC680 ALC882/883/885/888/889 ====================== - 3stack-dig 3-jack with SPDIF I/O - 6stack-dig 6-jack digital with SPDIF I/O - arima Arima W820Di1 - targa Targa T8, MSI-1049 T8 - asus-a7j ASUS A7J - asus-a7m ASUS A7M - macpro MacPro support - mb5 Macbook 5,1 - macmini3 Macmini 3,1 - mba21 Macbook Air 2,1 - mbp3 Macbook Pro rev3 - imac24 iMac 24'' with jack detection - imac91 iMac 9,1 - w2jc ASUS W2JC - 3stack-2ch-dig 3-jack with SPDIF I/O (ALC883) - alc883-6stack-dig 6-jack digital with SPDIF I/O (ALC883) - 3stack-6ch 3-jack 6-channel - 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O - 6stack-dig-demo 6-jack digital for Intel demo board - acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) - acer-aspire Acer Aspire 9810 - acer-aspire-4930g Acer Aspire 4930G - acer-aspire-6530g Acer Aspire 6530G - acer-aspire-7730g Acer Aspire 7730G - acer-aspire-8930g Acer Aspire 8930G - medion Medion Laptops - targa-dig Targa/MSI - targa-2ch-dig Targa/MSI with 2-channel - targa-8ch-dig Targa/MSI with 8-channel (MSI GX620) - laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE) - lenovo-101e Lenovo 101E - lenovo-nb0763 Lenovo NB0763 - lenovo-ms7195-dig Lenovo MS7195 - lenovo-sky Lenovo Sky - haier-w66 Haier W66 - 3stack-hp HP machines with 3stack (Lucknow, Samba boards) - 6stack-dell Dell machines with 6stack (Inspiron 530) - mitac Mitac 8252D - clevo-m540r Clevo M540R (6ch + digital) - clevo-m720 Clevo M720 laptop series - fujitsu-pi2515 Fujitsu AMILO Pi2515 - fujitsu-xa3530 Fujitsu AMILO XA3530 - 3stack-6ch-intel Intel DG33* boards - intel-alc889a Intel IbexPeak with ALC889A - intel-x58 Intel DX58 with ALC889 - asus-p5q ASUS P5Q-EM boards - mb31 MacBook 3,1 - sony-vaio-tt Sony VAIO TT - auto auto-config reading BIOS (default) + N/A ALC861/660 ========== diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c deleted file mode 100644 index 0f4292688e18..000000000000 --- a/sound/pci/hda/alc882_quirks.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * ALC882/ALC883/ALC888/ALC889 quirk models - * included by patch_realtek.c - */ - -/* ALC882 models */ -enum { - ALC882_AUTO, - ALC885_MBA21, - ALC885_MBP3, - ALC885_MB5, - ALC885_MACMINI3, - ALC885_IMAC91, - ALC889A_MB31, - ALC882_MODEL_LAST, -}; - -#define ALC882_DIGOUT_NID 0x06 -#define ALC882_DIGIN_NID 0x0a -#define ALC883_DIGOUT_NID ALC882_DIGOUT_NID -#define ALC883_DIGIN_NID ALC882_DIGIN_NID -#define ALC1200_DIGOUT_NID 0x10 - - -static const struct hda_channel_mode alc882_ch_modes[1] = { - { 8, NULL } -}; - -/* DACs */ -static const hda_nid_t alc882_dac_nids[4] = { - /* front, rear, clfe, rear_surr */ - 0x02, 0x03, 0x04, 0x05 -}; -#define alc883_dac_nids alc882_dac_nids - -/* ADCs */ -static const hda_nid_t alc882_adc_nids[3] = { - /* ADC0-2 */ - 0x07, 0x08, 0x09, -}; - -static const hda_nid_t alc882_adc_nids_alt[2] = { - /* ADC1-2 */ - 0x08, 0x09, -}; - -#define alc883_adc_nids alc882_adc_nids_alt - -static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 }; -#define alc883_capsrc_nids alc882_capsrc_nids_alt - -/* input MUX */ -/* FIXME: should be a matrix-type input source selection */ - -static const struct hda_input_mux alc882_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -#define alc883_capture_source alc882_capture_source - -static const struct hda_input_mux mb5_capture_source = { - .num_items = 3, - .items = { - { "Mic", 0x1 }, - { "Line", 0x7 }, - { "CD", 0x4 }, - }, -}; - -static const struct hda_input_mux macmini3_capture_source = { - .num_items = 2, - .items = { - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -static const struct hda_input_mux alc883_3stack_6ch_intel = { - .num_items = 4, - .items = { - { "Mic", 0x1 }, - { "Front Mic", 0x0 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -static const struct hda_input_mux alc889A_mb31_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x0 }, - /* Front Mic (0x01) unused */ - { "Line", 0x2 }, - /* Line 2 (0x03) unused */ - /* CD (0x04) unused? */ - }, -}; - -static const struct hda_input_mux alc889A_imac91_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x01 }, - { "Line", 0x2 }, /* Not sure! */ - }, -}; - -/* Macbook Air 2,1 */ - -static const struct hda_channel_mode alc885_mba21_ch_modes[1] = { - { 2, NULL }, -}; - -/* - * macbook pro ALC885 can switch LineIn to LineOut without losing Mic - */ - -/* - * 2ch mode - */ -static const struct hda_verb alc885_mbp_ch2_init[] = { - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - { } /* end */ -}; - -/* - * 4ch mode - */ -static const struct hda_verb alc885_mbp_ch4_init[] = { - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - { } /* end */ -}; - -static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = { - { 2, alc885_mbp_ch2_init }, - { 4, alc885_mbp_ch4_init }, -}; - -/* - * 2ch - * Speakers/Woofer/HP = Front - * LineIn = Input - */ -static const struct hda_verb alc885_mb5_ch2_init[] = { - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - { } /* end */ -}; - -/* - * 6ch mode - * Speakers/HP = Front - * Woofer = LFE - * LineIn = Surround - */ -static const struct hda_verb alc885_mb5_ch6_init[] = { - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, - { } /* end */ -}; - -static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = { - { 2, alc885_mb5_ch2_init }, - { 6, alc885_mb5_ch6_init }, -}; - -#define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes - -/* Macbook Air 2,1 same control for HP and internal Speaker */ - -static const struct snd_kcontrol_new alc885_mba21_mixer[] = { - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT), - { } -}; - - -static const struct snd_kcontrol_new alc885_mbp3_mixer[] = { - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), - HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new alc885_mb5_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), - HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), - HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new alc885_macmini3_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), - HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), - HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new alc885_imac91_mixer[] = { - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), - { } /* end */ -}; - - -static const struct snd_kcontrol_new alc882_chmode_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - -static const struct hda_verb alc882_base_init_verbs[] = { - /* Front mixer: unmute input/output amp left and right (volume = 0) */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Rear mixer */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* CLFE mixer */ - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Side mixer */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - - /* Front Pin: output 0 (0x0c) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Rear Pin: output 1 (0x0d) */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* CLFE Pin: output 2 (0x0e) */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* Side Pin: output 3 (0x0f) */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, - /* Mic (rear) pin: input vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Front Mic pin: input vref at 80% */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line In pin: input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line-2 In: Headphone output (output 0 - 0x0c) */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer2 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* Input mixer3 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* ADC2: mute amp left and right */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* ADC3: mute amp left and right */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - - { } -}; - -#define alc883_init_verbs alc882_base_init_verbs - -/* Macbook 5,1 */ -static const struct hda_verb alc885_mb5_init_verbs[] = { - /* DACs */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Front mixer */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Surround mixer */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* LFE mixer */ - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* HP mixer */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Front Pin (0x0c) */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* LFE Pin (0x0e) */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* HP Pin (0x0f) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, - /* Front Mic pin: input vref at 80% */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line In pin */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)}, - { } -}; - -/* Macmini 3,1 */ -static const struct hda_verb alc885_macmini3_init_verbs[] = { - /* DACs */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Front mixer */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Surround mixer */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* LFE mixer */ - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* HP mixer */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Front Pin (0x0c) */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* LFE Pin (0x0e) */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* HP Pin (0x0f) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, - /* Line In pin */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - { } -}; - - -static const struct hda_verb alc885_mba21_init_verbs[] = { - /*Internal and HP Speaker Mixer*/ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /*Internal Speaker Pin (0x0c)*/ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP Pin: output 0 (0x0e) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)}, - /* Line in (is hp when jack connected)*/ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - { } - }; - - -/* Macbook Pro rev3 */ -static const struct hda_verb alc885_mbp3_init_verbs[] = { - /* Front mixer: unmute input/output amp left and right (volume = 0) */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Rear mixer */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* HP mixer */ - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Front Pin: output 0 (0x0c) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP Pin: output 0 (0x0e) */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, - {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, - /* Mic (rear) pin: input vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Front Mic pin: input vref at 80% */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line In pin: use output 1 when in LineOut mode */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, - - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* Input mixer2 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* Input mixer3 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* ADC1: mute amp left and right */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* ADC2: mute amp left and right */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* ADC3: mute amp left and right */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - - { } -}; - -/* iMac 9,1 */ -static const struct hda_verb alc885_imac91_init_verbs[] = { - /* Internal Speaker Pin (0x0c) */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP Pin: Rear */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)}, - /* Line in Rear */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Front Mic pin: input vref at 80% */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Rear mixer */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - { } -}; - -/* Toggle speaker-output according to the hp-jack state */ -static void alc885_imac24_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x14; - spec->autocfg.speaker_pins[0] = 0x18; - spec->autocfg.speaker_pins[1] = 0x1a; - alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); -} - -#define alc885_mb5_setup alc885_imac24_setup -#define alc885_macmini3_setup alc885_imac24_setup - -/* Macbook Air 2,1 */ -static void alc885_mba21_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x14; - spec->autocfg.speaker_pins[0] = 0x18; - alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); -} - - - -static void alc885_mbp3_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x14; - alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); -} - -static void alc885_imac91_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x14; - spec->autocfg.speaker_pins[0] = 0x18; - spec->autocfg.speaker_pins[1] = 0x1a; - alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); -} - -/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */ -static const struct hda_verb alc889A_mb31_ch2_init[] = { - {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */ - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */ - { } /* end */ -}; - -/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */ -static const struct hda_verb alc889A_mb31_ch4_init[] = { - {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */ - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */ - { } /* end */ -}; - -/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */ -static const struct hda_verb alc889A_mb31_ch5_init[] = { - {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */ - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */ - { } /* end */ -}; - -/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */ -static const struct hda_verb alc889A_mb31_ch6_init[] = { - {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */ - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */ - { } /* end */ -}; - -static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = { - { 2, alc889A_mb31_ch2_init }, - { 4, alc889A_mb31_ch4_init }, - { 5, alc889A_mb31_ch5_init }, - { 6, alc889A_mb31_ch6_init }, -}; - -static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new alc889A_mb31_mixer[] = { - /* Output mixers */ - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00, - HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT), - /* Output switches */ - HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT), - /* Boost mixers */ - HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), - /* Input mixers */ - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new alc883_chmode_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - -static const struct hda_verb alc889A_mb31_verbs[] = { - /* Init rear pin (used as headphone output) */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */ - {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, - /* Init line pin (used as output in 4ch and 6ch mode) */ - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */ - /* Init line 2 pin (used as headphone out by default) */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */ - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */ - { } /* end */ -}; - -/* Mute speakers according to the headphone jack state */ -static void alc889A_mb31_automute(struct hda_codec *codec) -{ - unsigned int present; - - /* Mute only in 2ch or 4ch mode */ - if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0) - == 0x00) { - present = snd_hda_jack_detect(codec, 0x15); - snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, - HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); - snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, - HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); - } -} - -static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res) -{ - if ((res >> 26) == ALC_HP_EVENT) - alc889A_mb31_automute(codec); -} - -static void alc882_unsol_event(struct hda_codec *codec, unsigned int res) -{ - alc_exec_unsol_event(codec, res >> 26); -} - -/* - * configuration and preset - */ -static const char * const alc882_models[ALC882_MODEL_LAST] = { - [ALC885_MB5] = "mb5", - [ALC885_MACMINI3] = "macmini3", - [ALC885_MBA21] = "mba21", - [ALC885_MBP3] = "mbp3", - [ALC885_IMAC91] = "imac91", - [ALC889A_MB31] = "mb31", - [ALC882_AUTO] = "auto", -}; - -/* codec SSID table for Intel Mac */ -static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { - SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3), - SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3), - SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3), - SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3), - SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31), - SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3), - SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21), - SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31), - SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3), - SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91), - SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5), - SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5), - /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2, - * so apparently no perfect solution yet - */ - SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5), - SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5), - SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3), - {} /* terminator */ -}; - -static const struct alc_config_preset alc882_presets[] = { - [ALC885_MBA21] = { - .mixers = { alc885_mba21_mixer }, - .init_verbs = { alc885_mba21_init_verbs, alc_gpio1_init_verbs }, - .num_dacs = 2, - .dac_nids = alc882_dac_nids, - .channel_mode = alc885_mba21_ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), - .input_mux = &alc882_capture_source, - .unsol_event = alc882_unsol_event, - .setup = alc885_mba21_setup, - .init_hook = alc_hp_automute, - }, - [ALC885_MBP3] = { - .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, - .init_verbs = { alc885_mbp3_init_verbs, - alc_gpio1_init_verbs }, - .num_dacs = 2, - .dac_nids = alc882_dac_nids, - .hp_nid = 0x04, - .channel_mode = alc885_mbp_4ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes), - .input_mux = &alc882_capture_source, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc882_unsol_event, - .setup = alc885_mbp3_setup, - .init_hook = alc_hp_automute, - }, - [ALC885_MB5] = { - .mixers = { alc885_mb5_mixer, alc882_chmode_mixer }, - .init_verbs = { alc885_mb5_init_verbs, - alc_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .channel_mode = alc885_mb5_6ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes), - .input_mux = &mb5_capture_source, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc882_unsol_event, - .setup = alc885_mb5_setup, - .init_hook = alc_hp_automute, - }, - [ALC885_MACMINI3] = { - .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer }, - .init_verbs = { alc885_macmini3_init_verbs, - alc_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .channel_mode = alc885_macmini3_6ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes), - .input_mux = &macmini3_capture_source, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc882_unsol_event, - .setup = alc885_macmini3_setup, - .init_hook = alc_hp_automute, - }, - [ALC885_IMAC91] = { - .mixers = {alc885_imac91_mixer}, - .init_verbs = { alc885_imac91_init_verbs, - alc_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .channel_mode = alc885_mba21_ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), - .input_mux = &alc889A_imac91_capture_source, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc882_unsol_event, - .setup = alc885_imac91_setup, - .init_hook = alc_hp_automute, - }, - [ALC889A_MB31] = { - .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer}, - .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs, - alc_gpio1_init_verbs }, - .adc_nids = alc883_adc_nids, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .capsrc_nids = alc883_capsrc_nids, - .dac_nids = alc883_dac_nids, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .channel_mode = alc889A_mb31_6ch_modes, - .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes), - .input_mux = &alc889A_mb31_capture_source, - .dig_out_nid = ALC883_DIGOUT_NID, - .unsol_event = alc889A_mb31_unsol_event, - .init_hook = alc889A_mb31_automute, - }, -}; - - diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c deleted file mode 100644 index a63a517780d6..000000000000 --- a/sound/pci/hda/alc_quirks.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Common codes for Realtek codec quirks - * included by patch_realtek.c - */ - -/* - * configuration template - to be copied to the spec instance - */ -struct alc_config_preset { - const struct snd_kcontrol_new *mixers[5]; /* should be identical size - * with spec - */ - const struct snd_kcontrol_new *cap_mixer; /* capture mixer */ - const struct hda_verb *init_verbs[5]; - unsigned int num_dacs; - const hda_nid_t *dac_nids; - hda_nid_t dig_out_nid; /* optional */ - hda_nid_t hp_nid; /* optional */ - const hda_nid_t *slave_dig_outs; - unsigned int num_adc_nids; - const hda_nid_t *adc_nids; - const hda_nid_t *capsrc_nids; - hda_nid_t dig_in_nid; - unsigned int num_channel_mode; - const struct hda_channel_mode *channel_mode; - int need_dac_fix; - int const_channel_count; - unsigned int num_mux_defs; - const struct hda_input_mux *input_mux; - void (*unsol_event)(struct hda_codec *, unsigned int); - void (*setup)(struct hda_codec *); - void (*init_hook)(struct hda_codec *); -#ifdef CONFIG_SND_HDA_POWER_SAVE - const struct hda_amp_list *loopbacks; - void (*power_hook)(struct hda_codec *codec); -#endif -}; - -/* - * channel mode setting - */ -static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, - spec->num_channel_mode); -} - -static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - spec->ext_channel_count); -} - -static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - &spec->ext_channel_count); - if (err >= 0 && !spec->const_channel_count) { - spec->multiout.max_channels = spec->ext_channel_count; - if (spec->need_dac_fix) - spec->multiout.num_dacs = spec->multiout.max_channels / 2; - } - return err; -} - -static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - - if (!cfg->line_outs) { - while (cfg->line_outs < AUTO_CFG_MAX_OUTS && - cfg->line_out_pins[cfg->line_outs]) - cfg->line_outs++; - } - if (!cfg->speaker_outs) { - while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS && - cfg->speaker_pins[cfg->speaker_outs]) - cfg->speaker_outs++; - } - if (!cfg->hp_outs) { - while (cfg->hp_outs < AUTO_CFG_MAX_OUTS && - cfg->hp_pins[cfg->hp_outs]) - cfg->hp_outs++; - } -} - -/* - * set up from the preset table - */ -static void setup_preset(struct hda_codec *codec, - const struct alc_config_preset *preset) -{ - struct alc_spec *spec = codec->spec; - int i; - - for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) - add_mixer(spec, preset->mixers[i]); - spec->cap_mixer = preset->cap_mixer; - for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; - i++) - add_verb(spec, preset->init_verbs[i]); - - spec->channel_mode = preset->channel_mode; - spec->num_channel_mode = preset->num_channel_mode; - spec->need_dac_fix = preset->need_dac_fix; - spec->const_channel_count = preset->const_channel_count; - - if (preset->const_channel_count) - spec->multiout.max_channels = preset->const_channel_count; - else - spec->multiout.max_channels = spec->channel_mode[0].channels; - spec->ext_channel_count = spec->channel_mode[0].channels; - - spec->multiout.num_dacs = preset->num_dacs; - spec->multiout.dac_nids = preset->dac_nids; - spec->multiout.dig_out_nid = preset->dig_out_nid; - spec->multiout.slave_dig_outs = preset->slave_dig_outs; - spec->multiout.hp_nid = preset->hp_nid; - - spec->num_mux_defs = preset->num_mux_defs; - if (!spec->num_mux_defs) - spec->num_mux_defs = 1; - spec->input_mux = preset->input_mux; - - spec->num_adc_nids = preset->num_adc_nids; - spec->adc_nids = preset->adc_nids; - spec->capsrc_nids = preset->capsrc_nids; - spec->dig_in_nid = preset->dig_in_nid; - - spec->unsol_event = preset->unsol_event; - spec->init_hook = preset->init_hook; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->power_hook = preset->power_hook; - spec->loopback.amplist = preset->loopbacks; -#endif - - if (preset->setup) - preset->setup(codec); - - alc_fixup_autocfg_pin_nums(codec); -} - -static void alc_simple_setup_automute(struct alc_spec *spec, int mode) -{ - int lo_pin = spec->autocfg.line_out_pins[0]; - - if (lo_pin == spec->autocfg.speaker_pins[0] || - lo_pin == spec->autocfg.hp_pins[0]) - lo_pin = 0; - spec->automute_mode = mode; - spec->detect_hp = !!spec->autocfg.hp_pins[0]; - spec->detect_lo = !!lo_pin; - spec->automute_lo = spec->automute_lo_possible = !!lo_pin; - spec->automute_speaker = spec->automute_speaker_possible = !!spec->autocfg.speaker_pins[0]; -} diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3c6f5b5161f0..c5216b58d218 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4807,21 +4807,6 @@ static const struct alc_model_fixup alc880_fixup_models[] = { }; -/* - * board setups - */ -#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS -#define alc_board_config \ - snd_hda_check_board_config -#define alc_board_codec_sid_config \ - snd_hda_check_board_codec_sid_config -#include "alc_quirks.c" -#else -#define alc_board_config(codec, nums, models, tbl) -1 -#define alc_board_codec_sid_config(codec, nums, models, tbl) -1 -#define setup_preset(codec, x) /* NOP */ -#endif - /* * OK, here we have finally the patch for ALC880 */ @@ -5091,6 +5076,8 @@ enum { ALC882_FIXUP_EAPD, ALC883_FIXUP_EAPD, ALC883_FIXUP_ACER_EAPD, + ALC882_FIXUP_GPIO1, + ALC882_FIXUP_GPIO2, ALC882_FIXUP_GPIO3, ALC889_FIXUP_COEF, ALC882_FIXUP_ASUS_W2JC, @@ -5099,6 +5086,8 @@ enum { ALC882_FIXUP_ASPIRE_8930G_VERBS, ALC885_FIXUP_MACPRO_GPIO, ALC889_FIXUP_DAC_ROUTE, + ALC889_FIXUP_MBP_VREF, + ALC889_FIXUP_IMAC91_VREF, }; static void alc889_fixup_coef(struct hda_codec *codec, @@ -5169,6 +5158,51 @@ static void alc889_fixup_dac_route(struct hda_codec *codec, } } +/* Set VREF on HP pin */ +static void alc889_fixup_mbp_vref(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + static hda_nid_t nids[2] = { 0x14, 0x15 }; + int i; + + if (action != ALC_FIXUP_ACT_INIT) + return; + for (i = 0; i < ARRAY_SIZE(nids); i++) { + unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]); + if (get_defcfg_device(val) != AC_JACK_HP_OUT) + continue; + val = snd_hda_codec_read(codec, nids[i], 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + val |= AC_PINCTL_VREF_80; + snd_hda_codec_write(codec, nids[i], 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, val); + spec->keep_vref_in_automute = 1; + break; + } +} + +/* Set VREF on speaker pins on imac91 */ +static void alc889_fixup_imac91_vref(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + static hda_nid_t nids[2] = { 0x18, 0x1a }; + int i; + + if (action != ALC_FIXUP_ACT_INIT) + return; + for (i = 0; i < ARRAY_SIZE(nids); i++) { + unsigned int val; + val = snd_hda_codec_read(codec, nids[i], 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + val |= AC_PINCTL_VREF_50; + snd_hda_codec_write(codec, nids[i], 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, val); + } + spec->keep_vref_in_automute = 1; +} + static const struct alc_fixup alc882_fixups[] = { [ALC882_FIXUP_ABIT_AW9D_MAX] = { .type = ALC_FIXUP_PINS, @@ -5247,6 +5281,14 @@ static const struct alc_fixup alc882_fixups[] = { { } } }, + [ALC882_FIXUP_GPIO1] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = alc_gpio1_init_verbs, + }, + [ALC882_FIXUP_GPIO2] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = alc_gpio2_init_verbs, + }, [ALC882_FIXUP_GPIO3] = { .type = ALC_FIXUP_VERBS, .v.verbs = alc_gpio3_init_verbs, @@ -5320,6 +5362,18 @@ static const struct alc_fixup alc882_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc889_fixup_dac_route, }, + [ALC889_FIXUP_MBP_VREF] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc889_fixup_mbp_vref, + .chained = true, + .chain_id = ALC882_FIXUP_GPIO1, + }, + [ALC889_FIXUP_IMAC91_VREF] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc889_fixup_imac91_vref, + .chained = true, + .chain_id = ALC882_FIXUP_GPIO1, + }, }; static const struct snd_pci_quirk alc882_fixup_tbl[] = { @@ -5353,11 +5407,26 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), /* All Apple entries are in codec SSIDs */ + SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), + SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF), + SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO), SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF), + SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF), SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF), + SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF), + SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF), + SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), @@ -5382,14 +5451,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec) /* */ -#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS -#include "alc882_quirks.c" -#endif - static int patch_alc882(struct hda_codec *codec) { struct alc_spec *spec; - int err, board_config; + int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -5413,36 +5478,15 @@ static int patch_alc882(struct hda_codec *codec) if (err < 0) goto error; - board_config = alc_board_config(codec, ALC882_MODEL_LAST, - alc882_models, NULL); - if (board_config < 0) - board_config = alc_board_codec_sid_config(codec, - ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl); - - if (board_config < 0) { - printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - board_config = ALC_MODEL_AUTO; - } - - if (board_config == ALC_MODEL_AUTO) { - alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - } + alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups); + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); alc_auto_parse_customize_define(codec); - if (board_config == ALC_MODEL_AUTO) { - /* automatic parse from the BIOS config */ - err = alc882_parse_auto_config(codec); - if (err < 0) - goto error; - } - - if (board_config != ALC_MODEL_AUTO) { - setup_preset(codec, &alc882_presets[board_config]); - spec->vmaster_nid = 0x0c; - } + /* automatic parse from the BIOS config */ + err = alc882_parse_auto_config(codec); + if (err < 0) + goto error; if (!spec->no_analog && !spec->adc_nids) { alc_auto_fill_adc_caps(codec); @@ -5461,10 +5505,7 @@ static int patch_alc882(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - if (board_config == ALC_MODEL_AUTO) - spec->init_hook = alc_auto_init_std; - else - codec->patch_ops.build_controls = __alc_build_controls; + spec->init_hook = alc_auto_init_std; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) -- cgit v1.2.3 From 164f73ee93131f67a61eaca6a6f6180580c39445 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Feb 2012 11:27:09 +0100 Subject: ALSA: hda/realtek - Parse aa-loopback items dynamically Similarly in patch_via.c, parse the active analog-loopback connections and create a list dynamically rather than static arrays. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 104 +++++++++--------------------------------- 1 file changed, 22 insertions(+), 82 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c5216b58d218..eba50dff6130 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -200,6 +200,8 @@ struct alc_spec { hda_nid_t vmaster_nid; #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_loopback_check loopback; + int num_loopbacks; + struct hda_amp_list loopback_list[8]; #endif /* for PLL fix */ @@ -2690,6 +2692,25 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, return channel_name[ch]; } +#ifdef CONFIG_SND_HDA_POWER_SAVE +/* add the powersave loopback-list entry */ +static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx) +{ + struct hda_amp_list *list; + + if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1) + return; + list = spec->loopback_list + spec->num_loopbacks; + list->nid = mix; + list->dir = HDA_INPUT; + list->idx = idx; + spec->num_loopbacks++; + spec->loopback.amplist = spec->loopback_list; +} +#else +#define add_loopback_list(spec, mix, idx) /* NOP */ +#endif + /* create input playback/capture controls for the given pin */ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname, int ctlidx, @@ -2705,6 +2726,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); if (err < 0) return err; + add_loopback_list(spec, mix_nid, idx); return 0; } @@ -4430,17 +4452,6 @@ static int alc880_parse_auto_config(struct hda_codec *codec) return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids); } -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list alc880_loopbacks[] = { - { 0x0b, HDA_INPUT, 0 }, - { 0x0b, HDA_INPUT, 1 }, - { 0x0b, HDA_INPUT, 2 }, - { 0x0b, HDA_INPUT, 3 }, - { 0x0b, HDA_INPUT, 4 }, - { } /* end */ -}; -#endif - /* * ALC880 fix-ups */ @@ -4851,10 +4862,6 @@ static int patch_alc880(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc880_loopbacks; -#endif alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -4876,17 +4883,6 @@ static int alc260_parse_auto_config(struct hda_codec *codec) return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids); } -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list alc260_loopbacks[] = { - { 0x07, HDA_INPUT, 0 }, - { 0x07, HDA_INPUT, 1 }, - { 0x07, HDA_INPUT, 2 }, - { 0x07, HDA_INPUT, 3 }, - { 0x07, HDA_INPUT, 4 }, - { } /* end */ -}; -#endif - /* * Pin config fixes */ @@ -5032,10 +5028,6 @@ static int patch_alc260(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc260_loopbacks; -#endif alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -5058,9 +5050,6 @@ static int patch_alc260(struct hda_codec *codec) * In addition, an independent DAC for the multi-playback (not used in this * driver yet). */ -#ifdef CONFIG_SND_HDA_POWER_SAVE -#define alc882_loopbacks alc880_loopbacks -#endif /* * Pin config fixes @@ -5507,11 +5496,6 @@ static int patch_alc882(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; spec->init_hook = alc_auto_init_std; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc882_loopbacks; -#endif - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); return 0; @@ -5608,10 +5592,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { }; -#ifdef CONFIG_SND_HDA_POWER_SAVE -#define alc262_loopbacks alc880_loopbacks -#endif - /* */ static int patch_alc262(struct hda_codec *codec) @@ -5671,11 +5651,6 @@ static int patch_alc262(struct hda_codec *codec) spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc262_loopbacks; -#endif - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); return 0; @@ -5793,10 +5768,6 @@ static int patch_alc268(struct hda_codec *codec) /* * ALC269 */ -#ifdef CONFIG_SND_HDA_POWER_SAVE -#define alc269_loopbacks alc880_loopbacks -#endif - static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = { .substreams = 1, .channels_min = 2, @@ -6336,8 +6307,6 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc269_shutup; #ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc269_loopbacks; if (alc269_mic2_for_mute_led(codec)) codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps; #endif @@ -6362,17 +6331,6 @@ static int alc861_parse_auto_config(struct hda_codec *codec) return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids); } -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list alc861_loopbacks[] = { - { 0x15, HDA_INPUT, 0 }, - { 0x15, HDA_INPUT, 1 }, - { 0x15, HDA_INPUT, 2 }, - { 0x15, HDA_INPUT, 3 }, - { } /* end */ -}; -#endif - - /* Pin config fixes */ enum { ALC861_FIXUP_FSC_AMILO_PI1505, @@ -6486,8 +6444,6 @@ static int patch_alc861(struct hda_codec *codec) spec->init_hook = alc_auto_init_std; #ifdef CONFIG_SND_HDA_POWER_SAVE spec->power_hook = alc_power_eapd; - if (!spec->loopback.amplist) - spec->loopback.amplist = alc861_loopbacks; #endif alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -6506,10 +6462,6 @@ static int patch_alc861(struct hda_codec *codec) * * In addition, an independent DAC */ -#ifdef CONFIG_SND_HDA_POWER_SAVE -#define alc861vd_loopbacks alc880_loopbacks -#endif - static int alc861vd_parse_auto_config(struct hda_codec *codec) { static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; @@ -6610,10 +6562,6 @@ static int patch_alc861vd(struct hda_codec *codec) spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc861vd_loopbacks; -#endif alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -6635,9 +6583,6 @@ static int patch_alc861vd(struct hda_codec *codec) * In addition, an independent DAC for the multi-playback (not used in this * driver yet). */ -#ifdef CONFIG_SND_HDA_POWER_SAVE -#define alc662_loopbacks alc880_loopbacks -#endif /* * BIOS auto configuration @@ -6999,11 +6944,6 @@ static int patch_alc662(struct hda_codec *codec) spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc662_loopbacks; -#endif - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); return 0; -- cgit v1.2.3 From 5803a326465e38ee3cab8badbd8947732a8277f5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Feb 2012 11:59:45 +0100 Subject: ALSA: hda/realtek - Fix possible Oops with NULL input_mux When BIOS is damn crazy and gives no pin-config at all, the driver might lead to a NULL dereference. Let's add a NULL check for such a case. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index eba50dff6130..997cc8127a08 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -302,6 +302,9 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, int i, type, num_conns; hda_nid_t nid; + if (!spec->input_mux) + return 0; + mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; imux = &spec->input_mux[mux_idx]; if (!imux->num_items && mux_idx > 0) -- cgit v1.2.3 From c96f0bf4adc0663a69cdb0e2b73d33e6be312d1c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Feb 2012 12:12:57 +0100 Subject: ALSA: hda/realtek - Create individual mute switches for shared DAC Even if the outputs are using shared DACs, we can still create individual mute siwtches since they are assigned per pin. This allows to create, e.g. Speaker and Bass Speaker mute switches while the single volume is used for these outputs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 50 +++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 30 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 997cc8127a08..3cedb26f9cf5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3717,41 +3717,31 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); } - if (dacs[num_pins - 1]) { - /* OK, we have a multi-output system with individual volumes */ - for (i = 0; i < num_pins; i++) { - if (num_pins >= 3) { - snprintf(name, sizeof(name), "%s %s", - pfx, channel_name[i]); - err = alc_auto_create_extra_out(codec, pins[i], dacs[i], - name, 0); - } else { - err = alc_auto_create_extra_out(codec, pins[i], dacs[i], - pfx, i); - } - if (err < 0) - return err; - } - return 0; - } - - /* Let's create a bind-controls */ - ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw); - if (!ctl) - return -ENOMEM; - n = 0; for (i = 0; i < num_pins; i++) { - if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP) - ctl->values[n++] = - HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT); - } - if (n) { - snprintf(name, sizeof(name), "%s Playback Switch", pfx); - err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl); + hda_nid_t dac; + if (dacs[num_pins - 1]) + dac = dacs[i]; /* with individual volumes */ + else + dac = 0; + if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) { + err = alc_auto_create_extra_out(codec, pins[i], dac, + "Bass Speaker", 0); + } else if (num_pins >= 3) { + snprintf(name, sizeof(name), "%s %s", + pfx, channel_name[i]); + err = alc_auto_create_extra_out(codec, pins[i], dac, + name, 0); + } else { + err = alc_auto_create_extra_out(codec, pins[i], dac, + pfx, i); + } if (err < 0) return err; } + if (dacs[num_pins - 1]) + return 0; + /* Let's create a bind-controls for volumes */ ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol); if (!ctl) return -ENOMEM; -- cgit v1.2.3 From 689cabf6d07c82003310c221f719130f3a4f29c7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Feb 2012 12:35:27 +0100 Subject: ALSA: hda/realtek - Fix the possible conflicts of Bass Speaker name When the multi-io is added to the two speaker output configuration, the parser would try to add yet another "Bass Speaker" control since it checks only cfg->line_outs. Add a workaround for it by simply passing the channel name in the case of multi-io outputs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3cedb26f9cf5..e5c04593d360 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3613,14 +3613,17 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, dac = spec->multiout.dac_nids[i]; if (!dac) continue; - if (i >= cfg->line_outs) + if (i >= cfg->line_outs) { pin = spec->multi_io[i - 1].pin; - else + index = 0; + name = channel_name[i]; + } else { pin = cfg->line_out_pins[i]; + name = alc_get_line_out_pfx(spec, i, true, &index); + } sw = alc_look_for_out_mute_nid(codec, pin, dac); vol = alc_look_for_out_vol_nid(codec, pin, dac); - name = alc_get_line_out_pfx(spec, i, true, &index); if (!name || !strcmp(name, "CLFE")) { /* Center/LFE */ err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); -- cgit v1.2.3 From f568291ef571522202e8b9f893ab33694bb2fc31 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Feb 2012 12:37:00 +0100 Subject: ALSA: hda/realtek - Fix the wrong offset for two-speaker systems When the machine has two speakers but wants to put more multi-io jacks, the parser shouldn't consider about the shared DAC but try to assign the individual DACs. Otherwise the channel mapping would be fairly confused and lead to the wrong DACs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e5c04593d360..e82911ab0f8c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3353,7 +3353,11 @@ static int fill_and_eval_dacs(struct hda_codec *codec, } if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { /* try multi-ios with HP + inputs */ - err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false, 1); + int offset = 0; + if (cfg->line_outs >= 3) + offset = 1; + err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false, + offset); if (err < 0) return err; badness += err; -- cgit v1.2.3 From 070cff4cfd267b9d266f4f8362ea99532234eb21 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Feb 2012 12:54:17 +0100 Subject: ALSA: hda/realtek - Small code cleanups A few clean-ups for post-static-quirk time: - Call alc_auto_init_std() statically in alc_init() instead of setting spec->init_hook in each caller. spec->init_hook field is left unused for any future use. - Move the call of set_capture_mixer() to to alc_parse_auto_config() instead of each caller. - Get rid of the ADC-filling and imux check in each parser function. This is no longer needed since the auto-parser always check ADCs and imux. It was only for the static quirks. - Kill unused defines Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 140 ++---------------------------------------- 1 file changed, 5 insertions(+), 135 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e82911ab0f8c..e142f6f5c499 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -222,8 +222,6 @@ struct alc_spec { struct snd_array bind_ctls; }; -#define ALC_MODEL_AUTO 0 /* common for all chips */ - static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, unsigned int bits) { @@ -1074,45 +1072,6 @@ static bool alc_check_dyn_adc_switch(struct hda_codec *codec) return true; } -/* rebuild imux for matching with the given auto-mic pins (if not yet) */ -static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct hda_input_mux *imux; - static char * const texts[3] = { - "Mic", "Internal Mic", "Dock Mic" - }; - int i; - - if (!spec->auto_mic) - return false; - imux = &spec->private_imux[0]; - if (spec->input_mux == imux) - return true; - spec->imux_pins[0] = spec->ext_mic_pin; - spec->imux_pins[1] = spec->int_mic_pin; - spec->imux_pins[2] = spec->dock_mic_pin; - for (i = 0; i < 3; i++) { - strcpy(imux->items[i].label, texts[i]); - if (spec->imux_pins[i]) { - hda_nid_t pin = spec->imux_pins[i]; - int c; - for (c = 0; c < spec->num_adc_nids; c++) { - hda_nid_t cap = get_capsrc(spec, c); - int idx = get_connection_index(codec, cap, pin); - if (idx >= 0) { - imux->items[i].index = idx; - break; - } - } - imux->num_items = i + 1; - } - } - spec->num_mux_defs = 1; - spec->input_mux = imux; - return true; -} - /* check whether all auto-mic pins are valid; setup indices if OK */ static bool alc_auto_mic_check_imux(struct hda_codec *codec) { @@ -2092,6 +2051,7 @@ static int alc_build_controls(struct hda_codec *codec) */ static void alc_init_special_input_src(struct hda_codec *codec); +static void alc_auto_init_std(struct hda_codec *codec); static int alc_init(struct hda_codec *codec) { @@ -2104,6 +2064,7 @@ static int alc_init(struct hda_codec *codec) for (i = 0; i < spec->num_init_verbs; i++) snd_hda_sequence_write(codec, spec->init_verbs[i]); alc_init_special_input_src(codec); + alc_auto_init_std(codec); if (spec->init_hook) spec->init_hook(codec); @@ -4442,6 +4403,9 @@ static int alc_parse_auto_config(struct hda_codec *codec, if (spec->kctls.list) add_mixer(spec, spec->kctls.list); + if (!spec->no_analog && !spec->cap_mixer) + set_capture_mixer(codec); + return 1; } @@ -4844,15 +4808,6 @@ static int patch_alc880(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog) { err = snd_hda_attach_beep_device(codec, 0x1); if (err < 0) @@ -4861,7 +4816,6 @@ static int patch_alc880(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -5009,15 +4963,6 @@ static int patch_alc260(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog) { err = snd_hda_attach_beep_device(codec, 0x1); if (err < 0) @@ -5026,7 +4971,6 @@ static int patch_alc260(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -5477,15 +5421,6 @@ static int patch_alc882(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog && has_cdefine_beep(codec)) { err = snd_hda_attach_beep_device(codec, 0x1); if (err < 0) @@ -5494,7 +5429,6 @@ static int patch_alc882(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -5631,15 +5565,6 @@ static int patch_alc262(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog && has_cdefine_beep(codec)) { err = snd_hda_attach_beep_device(codec, 0x1); if (err < 0) @@ -5648,7 +5573,6 @@ static int patch_alc262(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -5745,17 +5669,7 @@ static int patch_alc268(struct hda_codec *codec) (0 << AC_AMPCAP_MUTE_SHIFT)); } - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; return 0; @@ -6283,15 +6197,6 @@ static int patch_alc269(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog && has_cdefine_beep(codec)) { err = snd_hda_attach_beep_device(codec, 0x1); if (err < 0) @@ -6303,7 +6208,6 @@ static int patch_alc269(struct hda_codec *codec) #ifdef CONFIG_PM codec->patch_ops.resume = alc269_resume; #endif - spec->init_hook = alc_auto_init_std; spec->shutup = alc269_shutup; #ifdef CONFIG_SND_HDA_POWER_SAVE @@ -6424,15 +6328,6 @@ static int patch_alc861(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog) { err = snd_hda_attach_beep_device(codec, 0x23); if (err < 0) @@ -6441,7 +6336,6 @@ static int patch_alc861(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; #ifdef CONFIG_SND_HDA_POWER_SAVE spec->power_hook = alc_power_eapd; #endif @@ -6542,15 +6436,6 @@ static int patch_alc861vd(struct hda_codec *codec) add_verb(spec, alc660vd_eapd_verbs); } - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog) { err = snd_hda_attach_beep_device(codec, 0x23); if (err < 0) @@ -6560,7 +6445,6 @@ static int patch_alc861vd(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -6912,15 +6796,6 @@ static int patch_alc662(struct hda_codec *codec) if (err < 0) goto error; - if (!spec->no_analog && !spec->adc_nids) { - alc_auto_fill_adc_caps(codec); - alc_rebuild_imux_for_auto_mic(codec); - alc_remove_invalid_adc_nids(codec); - } - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - if (!spec->no_analog && has_cdefine_beep(codec)) { err = snd_hda_attach_beep_device(codec, 0x1); if (err < 0) @@ -6941,7 +6816,6 @@ static int patch_alc662(struct hda_codec *codec) } codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; spec->shutup = alc_eapd_shutup; alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); @@ -6984,11 +6858,7 @@ static int patch_alc680(struct hda_codec *codec) return err; } - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - codec->patch_ops = alc_patch_ops; - spec->init_hook = alc_auto_init_std; return 0; } -- cgit v1.2.3 From 8d8bbc6f17b2a28c58de804064dbdab036d4318e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 22 Feb 2012 12:26:38 +0100 Subject: ALSA: hda/via - Don't create duplicated boost controls The driver may create duplicated mic boost controls when there are multiple mics with the very same type / location, and this leads to the error at actual kcontrol creation. It needs to check the validity of the created control and add a proper index if it's duplicated. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index c7eb4d7d05c0..93d52fc605fb 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -2474,6 +2474,8 @@ static int create_mic_boost_ctls(struct hda_codec *codec) { struct via_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; + const char *prev_label = NULL; + int type_idx = 0; int i, err; for (i = 0; i < cfg->num_inputs; i++) { @@ -2488,8 +2490,13 @@ static int create_mic_boost_ctls(struct hda_codec *codec) if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS)) continue; label = hda_get_autocfg_input_label(codec, cfg, i); + if (prev_label && !strcmp(label, prev_label)) + type_idx++; + else + type_idx = 0; + prev_label = label; snprintf(name, sizeof(name), "%s Boost Volume", label); - err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, + err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT)); if (err < 0) return err; -- cgit v1.2.3 From 77e314f72241daeac575158f946e905191611f0e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 22 Feb 2012 12:34:08 +0100 Subject: ALSA: hda/via - Add a few sanity checks Added sanity checks in a few places not to assume the pins having the certain amp caps or the input-source being always assigned to a mux. No actual bugs have been triggered by these, but surely better to be a bit more robust. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 93d52fc605fb..06214fdc9486 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -550,7 +550,10 @@ static void via_auto_init_output(struct hda_codec *codec, pin = path->path[path->depth - 1]; init_output_pin(codec, pin, pin_type); - caps = query_amp_caps(codec, pin, HDA_OUTPUT); + if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) + caps = query_amp_caps(codec, pin, HDA_OUTPUT); + else + caps = 0; if (caps & AC_AMPCAP_MUTE) { unsigned int val; val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; @@ -645,6 +648,10 @@ static void via_auto_init_analog_input(struct hda_codec *codec) /* init ADCs */ for (i = 0; i < spec->num_adc_nids; i++) { + hda_nid_t nid = spec->adc_nids[i]; + if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP) || + !(query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE)) + continue; snd_hda_codec_write(codec, spec->adc_nids[i], 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)); @@ -1508,6 +1515,8 @@ static int via_build_controls(struct hda_codec *codec) /* assign Capture Source enums to NID */ kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); for (i = 0; kctl && i < kctl->count; i++) { + if (!spec->mux_nids[i]) + continue; err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]); if (err < 0) return err; -- cgit v1.2.3 From 6edc59e602b36cd3c95a426ef6e8cad0344af8c7 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Thu, 23 Feb 2012 15:07:44 +0800 Subject: ALSA: hda - add id for Atom Cedar Trail HDMI codec [the order sorted by tiwai] Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1168ebd3fb5c..540cd13f7f15 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1912,6 +1912,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, +{ .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, {} /* terminator */ }; @@ -1958,6 +1959,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803"); MODULE_ALIAS("snd-hda-codec-id:80862804"); MODULE_ALIAS("snd-hda-codec-id:80862805"); MODULE_ALIAS("snd-hda-codec-id:80862806"); +MODULE_ALIAS("snd-hda-codec-id:80862880"); MODULE_ALIAS("snd-hda-codec-id:808629fb"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 5556e147083fb4d473d5c1a82f73205b8b145cd9 Mon Sep 17 00:00:00 2001 From: Vitaliy Kulikov Date: Mon, 27 Feb 2012 16:47:37 -0600 Subject: ALSA: hda - Fix audio playback support on HP Zephyr system Enables port E of IDT 92HD91 codec as output and sets correct output phase between ports E and D and high pass filter. Signed-off-by: Vitaliy Kulikov Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4c769405d72a..8c346ac59d46 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -99,6 +99,7 @@ enum { STAC_DELL_VOSTRO_3500, STAC_92HD83XXX_HP_cNB11_INTQUAD, STAC_HP_DV7_4000, + STAC_HP_ZEPHYR, STAC_92HD83XXX_MODELS }; @@ -894,6 +895,13 @@ static const struct hda_verb stac92hd83xxx_core_init[] = { {} }; +static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = { + { 0x22, 0x785, 0x43 }, + { 0x22, 0x782, 0xe0 }, + { 0x22, 0x795, 0x00 }, + {} +}; + static const struct hda_verb stac92hd71bxx_core_init[] = { /* set master volume and direct control */ { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, @@ -1621,6 +1629,12 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = { 0x40f000f0, 0x40f000f0, }; +static const unsigned int hp_zephyr_pin_configs[10] = { + 0x01813050, 0x0421201f, 0x04a1205e, 0x96130310, + 0x96130310, 0x0101401f, 0x1111611f, 0xd5a30130, + 0, 0, +}; + static const unsigned int hp_cNB11_intquad_pin_configs[10] = { 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, @@ -1634,6 +1648,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, + [STAC_HP_ZEPHYR] = hp_zephyr_pin_configs, }; static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { @@ -1644,6 +1659,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", [STAC_HP_DV7_4000] = "hp-dv7-4000", + [STAC_HP_ZEPHYR] = "hp-zephyr", }; static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { @@ -1696,6 +1712,14 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, + "HP", STAC_HP_ZEPHYR), + {} /* terminator */ +}; + +static const struct snd_pci_quirk stac92hd83xxx_codec_id_cfg_tbl[] = { + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, + "HP", STAC_HP_ZEPHYR), {} /* terminator */ }; @@ -5565,6 +5589,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) STAC_92HD83XXX_MODELS, stac92hd83xxx_models, stac92hd83xxx_cfg_tbl); + /* check codec subsystem id if not found */ + if (spec->board_config < 0) + spec->board_config = + snd_hda_check_board_codec_sid_config(codec, + STAC_92HD83XXX_MODELS, stac92hd83xxx_models, + stac92hd83xxx_codec_id_cfg_tbl); again: if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", @@ -5575,6 +5605,12 @@ again: codec->patch_ops = stac92xx_patch_ops; + switch (spec->board_config) { + case STAC_HP_ZEPHYR: + spec->init = stac92hd83xxx_hp_zephyr_init; + break; + } + if (find_mute_led_cfg(codec, -1/*no default cfg*/)) snd_printd("mute LED gpio %d polarity %d\n", spec->gpio_led, -- cgit v1.2.3 From a6f2fd557f993aecc93d51afd9e339524107937f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 28 Feb 2012 11:58:40 +0100 Subject: ALSA: hda - Add position_fix=4 (COMBO) option This patch adds a new position_fix option value, 4, as a combo mode to use LPIB for playbacks and POSBUF for captures. It's the way recommended by Intel hardware guys. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 8 +++++++- Documentation/sound/alsa/HD-Audio.txt | 7 ++++++- sound/pci/hda/hda_intel.c | 10 +++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 936699e4f04b..9af64c508ab4 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -860,7 +860,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. [Multiple options for each card instance] model - force the model name - position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF) + position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF, + 3 = VIACOMBO, 4 = COMBO) probe_mask - Bitmask to probe codecs (default = -1, meaning all slots) When the bit 8 (0x100) is set, the lower 8 bits are used as the "fixed" codec slots; i.e. the driver probes the @@ -925,6 +926,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. (Usually SD_LPIB register is more accurate than the position buffer.) + position_fix=3 is specific to VIA devices. The position + of the capture stream is checked from both LPIB and POSBUF + values. position_fix=4 is a combination mode, using LPIB + for playback and POSBUF for capture. + NB: If you get many "azx_get_response timeout" messages at loading, it's likely a problem of interrupts (e.g. ACPI irq routing). Try to boot with options like "pci=noacpi". Also, you diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 91fee3b45fb8..7813c06a5c71 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -59,7 +59,12 @@ a case, you can change the default method via `position_fix` option. `position_fix=1` means to use LPIB method explicitly. `position_fix=2` means to use the position-buffer. `position_fix=3` means to use a combination of both methods, needed -for some VIA and ATI controllers. 0 is the default value for all other +for some VIA controllers. The capture stream position is corrected +by comparing both LPIB and position-buffer values. +`position_fix=4` is another combination available for all controllers, +and uses LPIB for the playback and the position-buffer for the capture +streams. +0 is the default value for all other controllers, the automatic check and fallback to LPIB as described in the above. If you get a problem of repeated sounds, this option might help. diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index e354c1616541..6e958bf94191 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -84,7 +84,7 @@ module_param_array(model, charp, NULL, 0444); MODULE_PARM_DESC(model, "Use the given board model."); module_param_array(position_fix, int, NULL, 0444); MODULE_PARM_DESC(position_fix, "DMA pointer read method." - "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO)."); + "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO)."); module_param_array(bdl_pos_adj, int, NULL, 0644); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); module_param_array(probe_mask, int, NULL, 0444); @@ -330,6 +330,7 @@ enum { POS_FIX_LPIB, POS_FIX_POSBUF, POS_FIX_VIACOMBO, + POS_FIX_COMBO, }; /* Defines for ATI HD Audio support in SB450 south bridge */ @@ -2520,6 +2521,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix) case POS_FIX_LPIB: case POS_FIX_POSBUF: case POS_FIX_VIACOMBO: + case POS_FIX_COMBO: return fix; } @@ -2699,6 +2701,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->position_fix[0] = chip->position_fix[1] = check_position_fix(chip, position_fix[dev]); + /* combo mode uses LPIB for playback */ + if (chip->position_fix[0] == POS_FIX_COMBO) { + chip->position_fix[0] = POS_FIX_LPIB; + chip->position_fix[1] = POS_FIX_AUTO; + } + check_probe_mask(chip, dev); chip->single_cmd = single_cmd; -- cgit v1.2.3 From 3e93f5efaf9cd48bae97ae6436cbc5f91be8003c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 28 Feb 2012 21:49:55 +0100 Subject: ALSA: hda - Enable docking-station SPDIF for Thinkpad The docking-station of Thinkpad X200 & co supports also an SPDIF output, and the corresponding pin 0x1c has to be enabled for using it. Reported-and-tested-by: Sebastian Glita Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 266e5a68bafa..6bbdbb6dd4e5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -4355,6 +4355,7 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { { 0x16, 0x042140ff }, /* HP (seq# overridden) */ { 0x17, 0x21a11000 }, /* dock-mic */ { 0x19, 0x2121103f }, /* dock-HP */ + { 0x1c, 0x21440100 }, /* dock SPDIF out */ {} }; -- cgit v1.2.3 From 07cafff288266c3aa082f4bda3d47989e73ee85d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Feb 2012 12:30:59 +0100 Subject: ALSA: hda/conexant - Clear unsol events on unused pins It seems that Lenovo machines (or codec chip itself?) leave the unsol event tags and the enablement-flag from other pins bogusly even on the unused pins. Although this shouldn't be too critical, it's better to clear them up sanely. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6bbdbb6dd4e5..f3b79031fcca 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3931,6 +3931,50 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins, snd_hda_jack_detect_enable(codec, pins[i], action); } +static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) +{ + int i; + for (i = 0; i < nums; i++) + if (list[i] == nid) + return true; + return false; +} + +/* is the given NID found in any of autocfg items? */ +static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid) +{ + int i; + + if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || + found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || + found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) || + found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs)) + return true; + for (i = 0; i < cfg->num_inputs; i++) + if (cfg->inputs[i].pin == nid) + return true; + if (cfg->dig_in_pin == nid) + return true; + return false; +} + +/* clear unsol-event tags on unused pins; Conexant codecs seem to leave + * invalid unsol tags by some reason + */ +static void clear_unsol_on_unused_pins(struct hda_codec *codec) +{ + struct conexant_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + int i; + + for (i = 0; i < codec->init_pins.used; i++) { + struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); + if (!found_in_autocfg(cfg, pin->nid)) + snd_hda_codec_write(codec, pin->nid, 0, + AC_VERB_SET_UNSOLICITED_ENABLE, 0); + } +} + static void cx_auto_init_output(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; @@ -3971,6 +4015,7 @@ static void cx_auto_init_output(struct hda_codec *codec) /* turn on all EAPDs if no individual EAPD control is available */ if (!spec->pin_eapd_ctrls) cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); + clear_unsol_on_unused_pins(codec); } static void cx_auto_init_input(struct hda_codec *codec) -- cgit v1.2.3 From e21af48583380ed9b5ca07b6dd962dbcd3748e0a Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 5 Mar 2012 11:38:46 +0100 Subject: ALSA: hda - fix broken automute/autoswitch for Realtek The recent addition of volume-knob widget in the auto-parser broke automute/autoswitch for some Realtek devices. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 01179d53edcd..7e651682eece 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -686,7 +686,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) else res >>= 26; action = snd_hda_jack_get_action(codec, res); - if (res == ALC_DCVOL_EVENT) { + if (action == ALC_DCVOL_EVENT) { /* Execute the dc-vol event here as it requires the NID * but we don't pass NID to alc_exec_unsol_event(). * Once when we convert all static quirks to the auto-parser, -- cgit v1.2.3 From 78f8baf138311be3e170526388b0530a172bdbff Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 Mar 2012 14:02:32 +0100 Subject: ALSA: hda - Add Gigabyte GA-MA790X to the beep whitelist Its BIOS suppresses the PC beep although it's implemented. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7e651682eece..2ae6bfbc6788 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4304,6 +4304,7 @@ static const struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), + SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1), SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), {} }; -- cgit v1.2.3 From 546bb6785265f3413fa76e06b9fdce58ee15ea87 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Mar 2012 08:37:19 +0100 Subject: ALSA: hda/realtek - Reuse init_hook for ALC269VB coef setup Move the currently unused spec->init_hook at the beginning of the init sequence so that the recently added ALC269VB coef setup can be put there. The alc_init() is again clean without an ugly check. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 65955dabc152..1de0c1629bab 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2052,15 +2052,14 @@ static int alc_build_controls(struct hda_codec *codec) static void alc_init_special_input_src(struct hda_codec *codec); static void alc_auto_init_std(struct hda_codec *codec); -static int alc269_fill_coef(struct hda_codec *codec); static int alc_init(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; unsigned int i; - if (codec->vendor_id == 0x10ec0269) - alc269_fill_coef(codec); + if (spec->init_hook) + spec->init_hook(codec); alc_fix_pll(codec); alc_auto_init_amp(codec, spec->init_amp); @@ -2070,9 +2069,6 @@ static int alc_init(struct hda_codec *codec) alc_init_special_input_src(codec); alc_auto_init_std(codec); - if (spec->init_hook) - spec->init_hook(codec); - alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); snd_hda_jack_report_sync(codec); @@ -6124,13 +6120,13 @@ static const struct alc_model_fixup alc269_fixup_models[] = { }; -static int alc269_fill_coef(struct hda_codec *codec) +static void alc269_fill_coef(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int val; if (spec->codec_variant != ALC269_TYPE_ALC269VB) - return 0; + return; if ((alc_get_coef0(codec) & 0x00ff) < 0x015) { alc_write_coef_idx(codec, 0xf, 0x960b); @@ -6166,8 +6162,6 @@ static int alc269_fill_coef(struct hda_codec *codec) val = alc_read_coef_idx(codec, 0x4); /* HP */ alc_write_coef_idx(codec, 0x4, val | (1<<11)); - - return 0; } /* @@ -6211,6 +6205,7 @@ static int patch_alc269(struct hda_codec *codec) } if (err < 0) goto error; + spec->init_hook = alc269_fill_coef; alc269_fill_coef(codec); } -- cgit v1.2.3 From 785f857d1cb0856b612b46a0545b74aa2596e44a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Mar 2012 10:58:39 +0100 Subject: ALSA: hda - Set codec to D3 forcibly even if not used We've seen a problem with a pop-noise at suspend/resume on a HP machine with ALC269, and it turned out to be an issue that the controller going to D3 while the codec is unused. When the device is once suspended and resumed and kept unused, the driver doesn't initialize the codecs. Instead, the codec chips are set up dynamically at the first usage. Now, suppose the device going to suspend again before the codec is set up. The controller is turned off to D3 while the codec chips are untouched. This caused a pop noise because the codec chip might have been turned on implicitly by the hardware. As a workaround, the codec chip needs to be set to D3 when going to suspend no matter whether it was used or not. Also, for making it happening, the controller has to be always set up in the resume path. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 4 ++++ sound/pci/hda/hda_intel.c | 14 +------------- 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 76bac4fc0472..0527ae1ab96e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -5281,6 +5281,10 @@ int snd_hda_suspend(struct hda_bus *bus) list_for_each_entry(codec, &bus->codec_list, list) { if (hda_codec_is_power_on(codec)) hda_call_codec_suspend(codec); + else /* forcibly change the power to D3 even if not used */ + hda_set_power_state(codec, + codec->afg ? codec->afg : codec->mfg, + AC_PWRST_D3); if (codec->patch_ops.post_suspend) codec->patch_ops.post_suspend(codec); } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6e958bf94191..c19e71a94e1b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2351,17 +2351,6 @@ static void azx_power_notify(struct hda_bus *bus) * power management */ -static int snd_hda_codecs_inuse(struct hda_bus *bus) -{ - struct hda_codec *codec; - - list_for_each_entry(codec, &bus->codec_list, list) { - if (snd_hda_codec_needs_resume(codec)) - return 1; - } - return 0; -} - static int azx_suspend(struct pci_dev *pci, pm_message_t state) { struct snd_card *card = pci_get_drvdata(pci); @@ -2408,8 +2397,7 @@ static int azx_resume(struct pci_dev *pci) return -EIO; azx_init_pci(chip); - if (snd_hda_codecs_inuse(chip->bus)) - azx_init_chip(chip, 1); + azx_init_chip(chip, 1); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); -- cgit v1.2.3 From 18478e8b626edc2d181dcb1b93e1f99ad72095e9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 Mar 2012 17:51:10 +0100 Subject: ALSA: hda - Initialize vmaster slave volumes When the driver is changed to use vmaster or a new slave element is added by the improvement of the parser code, user may face often the silent output because of the muted slave mixer although Master volume is properly set. And they complain. And I get upset. Although such a mixer element should be initialized via "alsactl init", it'd be more user-friendly if the known output slaves are unmuted and set to 0dB so that user can control the volume only with Master as default. Since Master is still set muted as default even with this change, no risk of the speaker blow up, too. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 65 ++++++++++++++++++++++++++++++++++++++++++-- sound/pci/hda/hda_local.h | 6 ++-- sound/pci/hda/patch_analog.c | 8 ++++-- 3 files changed, 72 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0527ae1ab96e..0c0ac0e1d504 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -2340,6 +2341,56 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) return 1; } +/* guess the value corresponding to 0dB */ +static int get_kctl_0dB_offset(struct snd_kcontrol *kctl) +{ + int _tlv[4]; + const int *tlv = NULL; + int val = -1; + + if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { + /* FIXME: set_fs() hack for obtaining user-space TLV data */ + mm_segment_t fs = get_fs(); + set_fs(get_ds()); + if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv)) + tlv = _tlv; + set_fs(fs); + } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) + tlv = kctl->tlv.p; + if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) + val = -tlv[2] / tlv[3]; + return val; +} + +/* call kctl->put with the given value(s) */ +static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) +{ + struct snd_ctl_elem_value *ucontrol; + ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL); + if (!ucontrol) + return -ENOMEM; + ucontrol->value.integer.value[0] = val; + ucontrol->value.integer.value[1] = val; + kctl->put(kctl, ucontrol); + kfree(ucontrol); + return 0; +} + +/* initialize the slave volume with 0dB */ +static int init_slave_0dB(void *data, struct snd_kcontrol *slave) +{ + int offset = get_kctl_0dB_offset(slave); + if (offset > 0) + put_kctl_with_value(slave, offset); + return 0; +} + +/* unmute the slave */ +static int init_slave_unmute(void *data, struct snd_kcontrol *slave) +{ + return put_kctl_with_value(slave, 1); +} + /** * snd_hda_add_vmaster - create a virtual master control and add slaves * @codec: HD-audio codec @@ -2347,6 +2398,7 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) * @tlv: TLV data (optional) * @slaves: slave control names (optional) * @suffix: suffix string to each slave name (optional) + * @init_slave_vol: initialize slaves to unmute/0dB * * Create a virtual master control with the given name. The TLV data * must be either NULL or a valid data. @@ -2357,9 +2409,9 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) * * This function returns zero if successful or a negative error code. */ -int snd_hda_add_vmaster(struct hda_codec *codec, char *name, +int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char * const *slaves, - const char *suffix) + const char *suffix, bool init_slave_vol) { struct snd_kcontrol *kctl; int err; @@ -2380,9 +2432,16 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, (map_slave_func_t)snd_ctl_add_slave, kctl); if (err < 0) return err; + + /* init with master mute & zero volume */ + put_kctl_with_value(kctl, 0); + if (init_slave_vol) + map_slaves(codec, slaves, suffix, + tlv ? init_slave_0dB : init_slave_unmute, kctl); + return 0; } -EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); +EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster); /** * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 6094dea82bc3..caa64686267b 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -139,9 +139,11 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, unsigned int *tlv); struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, const char *name); -int snd_hda_add_vmaster(struct hda_codec *codec, char *name, +int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char * const *slaves, - const char *suffix); + const char *suffix, bool init_slave_vol); +#define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \ + __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true) int snd_hda_codec_reset(struct hda_codec *codec); /* amp value bits */ diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 9771b0702455..fa97a0c5ced0 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -82,6 +82,7 @@ struct ad198x_spec { unsigned int inv_jack_detect: 1;/* inverted jack-detection */ unsigned int inv_eapd: 1; /* inverted EAPD implementation */ unsigned int analog_beep: 1; /* analog beep input present */ + unsigned int avoid_init_slave_vol:1; #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_loopback_check loopback; @@ -223,11 +224,12 @@ static int ad198x_build_controls(struct hda_codec *codec) unsigned int vmaster_tlv[4]; snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, HDA_OUTPUT, vmaster_tlv); - err = snd_hda_add_vmaster(codec, "Master Playback Volume", + err = __snd_hda_add_vmaster(codec, "Master Playback Volume", vmaster_tlv, (spec->slave_vols ? spec->slave_vols : ad_slave_pfxs), - "Playback Volume"); + "Playback Volume", + !spec->avoid_init_slave_vol); if (err < 0) return err; } @@ -3604,6 +3606,8 @@ static int patch_ad1884(struct hda_codec *codec) spec->vmaster_nid = 0x04; /* we need to cover all playback volumes */ spec->slave_vols = ad1884_slave_vols; + /* slaves may contain input volumes, so we can't raise to 0dB blindly */ + spec->avoid_init_slave_vol = 1; codec->patch_ops = ad198x_patch_ops; -- cgit v1.2.3 From 2ad787e9aae8bfac14fa96748c0f2b034577be6a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Mar 2012 12:18:37 +0100 Subject: ALSA: Add a hook capability to vmaster controls This patch adds a hook to vmaster control to be called at each time when the master value is changed. It'd be handy for an additional mute LED control following the Master switch, for example. Signed-off-by: Takashi Iwai --- include/sound/control.h | 5 +++++ sound/core/vmaster.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/include/sound/control.h b/include/sound/control.h index b2796e83c7ac..eff96dc7a278 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -227,6 +227,11 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master, return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE); } +int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, + void (*hook)(void *private_data, int), + void *private_data); +void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl); + /* * Helper functions for jack-detection controls */ diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 130cfe677d60..14a286a7bf2b 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -37,6 +37,8 @@ struct link_master { struct link_ctl_info info; int val; /* the master value */ unsigned int tlv[4]; + void (*hook)(void *private_data, int); + void *hook_private_data; }; /* @@ -126,7 +128,9 @@ static int master_init(struct link_master *master) master->info.count = 1; /* always mono */ /* set full volume as default (= no attenuation) */ master->val = master->info.max_val; - return 0; + if (master->hook) + master->hook(master->hook_private_data, master->val); + return 1; } return -ENOENT; } @@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol, slave_put_val(slave, uval); } kfree(uval); + if (master->hook && !err) + master->hook(master->hook_private_data, master->val); return 1; } @@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, return kctl; } EXPORT_SYMBOL(snd_ctl_make_virtual_master); + +/** + * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control + * @kcontrol: vmaster kctl element + * @hook: the hook function + * + * Adds the given hook to the vmaster control element so that it's called + * at each time when the value is changed. + */ +int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol, + void (*hook)(void *private_data, int), + void *private_data) +{ + struct link_master *master = snd_kcontrol_chip(kcontrol); + master->hook = hook; + master->hook_private_data = private_data; + return 0; +} +EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); + +/** + * snd_ctl_sync_vmaster_hook - Sync the vmaster hook + * @kcontrol: vmaster kctl element + * + * Call the hook function to synchronize with the current value of the given + * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't + * exist. + */ +void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol) +{ + struct link_master *master; + if (!kcontrol) + return; + master = snd_kcontrol_chip(kcontrol); + if (master->hook) + master->hook(master->hook_private_data, master->val); +} +EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook); -- cgit v1.2.3 From 29e5853d618282d8277ce8a8304f7424eb60deb5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Mar 2012 12:25:03 +0100 Subject: ALSA: hda - Return the created kcontrol in __snd_hda_add_vmaster() It'll be used for adding hooks in later patches. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 9 ++++++++- sound/pci/hda/hda_local.h | 7 ++++--- sound/pci/hda/patch_analog.c | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0c0ac0e1d504..b79ee3444654 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2399,6 +2399,7 @@ static int init_slave_unmute(void *data, struct snd_kcontrol *slave) * @slaves: slave control names (optional) * @suffix: suffix string to each slave name (optional) * @init_slave_vol: initialize slaves to unmute/0dB + * @ctl_ret: store the vmaster kcontrol in return * * Create a virtual master control with the given name. The TLV data * must be either NULL or a valid data. @@ -2411,11 +2412,15 @@ static int init_slave_unmute(void *data, struct snd_kcontrol *slave) */ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char * const *slaves, - const char *suffix, bool init_slave_vol) + const char *suffix, bool init_slave_vol, + struct snd_kcontrol **ctl_ret) { struct snd_kcontrol *kctl; int err; + if (ctl_ret) + *ctl_ret = NULL; + err = map_slaves(codec, slaves, suffix, check_slave_present, NULL); if (err != 1) { snd_printdd("No slave found for %s\n", name); @@ -2439,6 +2444,8 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, map_slaves(codec, slaves, suffix, tlv ? init_slave_0dB : init_slave_unmute, kctl); + if (ctl_ret) + *ctl_ret = kctl; return 0; } EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster); diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index caa64686267b..c3ee4ede4482 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -140,10 +140,11 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, const char *name); int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, - unsigned int *tlv, const char * const *slaves, - const char *suffix, bool init_slave_vol); + unsigned int *tlv, const char * const *slaves, + const char *suffix, bool init_slave_vol, + struct snd_kcontrol **ctl_ret); #define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \ - __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true) + __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL) int snd_hda_codec_reset(struct hda_codec *codec); /* amp value bits */ diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index fa97a0c5ced0..7143393927da 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -229,7 +229,7 @@ static int ad198x_build_controls(struct hda_codec *codec) (spec->slave_vols ? spec->slave_vols : ad_slave_pfxs), "Playback Volume", - !spec->avoid_init_slave_vol); + !spec->avoid_init_slave_vol, NULL); if (err < 0) return err; } -- cgit v1.2.3 From 2faa3bf15ba69fa12bc53926b88982b3875abb3f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Mar 2012 12:30:22 +0100 Subject: ALSA: hda - Rewrite the mute-LED hook with vmaster hook in patch_sigmatel.c The mute-LED is controlled in patch_sigmatel.c by (ab-)using the powersave hook. This can be now rewritten with the vmaster hook instead, which is much simpler and can work even without CONFIG_SND_HDA_POWER_SAVE kconfig. A drawback is that the mute-LED corresponds _only_ to the Master mixer switch instead of checking the whole DACs. But usually this shouldn't be a big problem as PA enables the mixer elements accordingly. Also, this patch changes the code to create vmaster always even on STAC9200 and STAC925x. The former "Master" on these chips are renamed as "PCM" now. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 136 +++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 87 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 5988dbdedc4e..6e926497b230 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -310,6 +310,8 @@ struct sigmatel_spec { unsigned long auto_capvols[MAX_ADCS_NUM]; unsigned auto_dmic_cnt; hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; + + struct snd_kcontrol *vmaster_sw_kctl; }; static const hda_nid_t stac9200_adc_nids[1] = { @@ -1007,8 +1009,8 @@ static const struct hda_verb stac9205_core_init[] = { } static const struct snd_kcontrol_new stac9200_mixer[] = { - HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), { } /* end */ @@ -1035,8 +1037,8 @@ static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = { }; static const struct snd_kcontrol_new stac925x_mixer[] = { - HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT), { } /* end */ }; @@ -1074,11 +1076,19 @@ static const char * const slave_pfxs[] = { NULL }; +static void stac92xx_update_led_status(struct hda_codec *codec, int enabled); + +static void stac92xx_vmaster_hook(void *private_data, int val) +{ + stac92xx_update_led_status(private_data, val); +} + static void stac92xx_free_kctls(struct hda_codec *codec); static int stac92xx_build_controls(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; + unsigned int vmaster_tlv[4]; int err; int i; @@ -1135,26 +1145,29 @@ static int stac92xx_build_controls(struct hda_codec *codec) } /* if we have no master control, let's create it */ - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { - unsigned int vmaster_tlv[4]; - snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], - HDA_OUTPUT, vmaster_tlv); - /* correct volume offset */ - vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; - /* minimum value is actually mute */ - vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; - err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, slave_pfxs, - "Playback Volume"); - if (err < 0) - return err; - } - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { - err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, slave_pfxs, - "Playback Switch"); - if (err < 0) - return err; + snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], + HDA_OUTPUT, vmaster_tlv); + /* correct volume offset */ + vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; + /* minimum value is actually mute */ + vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; + err = snd_hda_add_vmaster(codec, "Master Playback Volume", + vmaster_tlv, slave_pfxs, + "Playback Volume"); + if (err < 0) + return err; + + err = __snd_hda_add_vmaster(codec, "Master Playback Switch", + NULL, slave_pfxs, + "Playback Switch", true, + &spec->vmaster_sw_kctl); + if (err < 0) + return err; + + if (spec->gpio_led) { + snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl, + stac92xx_vmaster_hook, codec); + snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); } if (spec->aloopback_ctl && @@ -4419,8 +4432,7 @@ static int stac92xx_init(struct hda_codec *codec) snd_hda_jack_report_sync(codec); /* sync mute LED */ - if (spec->gpio_led) - hda_call_check_power_status(codec, 0x01); + snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); if (spec->dac_list) stac92xx_power_down(codec); return 0; @@ -5033,83 +5045,37 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, afg_power_state); snd_hda_codec_set_power_to_all(codec, fg, power_state, true); } +#endif /* CONFIG_SND_HDA_POWER_SAVE */ +#endif /* CONFIG_PM */ -/* - * For this feature CONFIG_SND_HDA_POWER_SAVE is needed - * as mute LED state is updated in check_power_status hook - */ -static int stac92xx_update_led_status(struct hda_codec *codec) +/* update mute-LED accoring to the master switch */ +static void stac92xx_update_led_status(struct hda_codec *codec, int enabled) { struct sigmatel_spec *spec = codec->spec; - int i, num_ext_dacs, muted = 1; - unsigned int muted_lvl, notmtd_lvl; - hda_nid_t nid; + int muted = !enabled; if (!spec->gpio_led) - return 0; + return; + + /* LED state is inverted on these systems */ + if (spec->gpio_led_polarity) + muted = !muted; - for (i = 0; i < spec->multiout.num_dacs; i++) { - nid = spec->multiout.dac_nids[i]; - if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & - HDA_AMP_MUTE)) { - muted = 0; /* something heard */ - break; - } - } - if (muted && spec->multiout.hp_nid) - if (!(snd_hda_codec_amp_read(codec, - spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) & - HDA_AMP_MUTE)) { - muted = 0; /* HP is not muted */ - } - num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid); - for (i = 0; muted && i < num_ext_dacs; i++) { - nid = spec->multiout.extra_out_nid[i]; - if (nid == 0) - break; - if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & - HDA_AMP_MUTE)) { - muted = 0; /* extra output is not muted */ - } - } /*polarity defines *not* muted state level*/ if (!spec->vref_mute_led_nid) { if (muted) spec->gpio_data &= ~spec->gpio_led; /* orange */ else spec->gpio_data |= spec->gpio_led; /* white */ - - if (!spec->gpio_led_polarity) { - /* LED state is inverted on these systems */ - spec->gpio_data ^= spec->gpio_led; - } stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); } else { - notmtd_lvl = spec->gpio_led_polarity ? - AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; - muted_lvl = spec->gpio_led_polarity ? - AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50; - spec->vref_led = muted ? muted_lvl : notmtd_lvl; + spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; stac_vrefout_set(codec, spec->vref_mute_led_nid, spec->vref_led); } - return 0; } -/* - * use power check for controlling mute led of HP notebooks - */ -static int stac92xx_check_power_status(struct hda_codec *codec, - hda_nid_t nid) -{ - stac92xx_update_led_status(codec); - - return 0; -} -#endif /* CONFIG_SND_HDA_POWER_SAVE */ -#endif /* CONFIG_PM */ - static const struct hda_codec_ops stac92xx_patch_ops = { .build_controls = stac92xx_build_controls, .build_pcms = stac92xx_build_pcms, @@ -5627,8 +5593,6 @@ again: stac92xx_set_power_state; } codec->patch_ops.pre_resume = stac92xx_pre_resume; - codec->patch_ops.check_power_status = - stac92xx_check_power_status; } #endif @@ -5938,8 +5902,6 @@ again: stac92xx_set_power_state; } codec->patch_ops.pre_resume = stac92xx_pre_resume; - codec->patch_ops.check_power_status = - stac92xx_check_power_status; } #endif -- cgit v1.2.3 From 420b0febe54099ea9003bddad0a81e882a8472af Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Mar 2012 12:35:27 +0100 Subject: ALSA: hda - Rewrite the mute-LED control with vmaster hook for ALC269 We've had ugly static handling of the mute-LED with a powersave hook for ALC269 HP laptops just like done in patch_sigmatel.c. This is now rewritten with the new vmaster hook and a fixup code. For that, the new fixup action, ALC_FIXUP_ACT_BUILD, is introduced. It's called after build_controls is called. The reason of this new action is that vmaster hook must be added at this stage (not in init or probe). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 82 +++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 38 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1de0c1629bab..901547216c4e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -198,6 +198,7 @@ struct alc_spec { /* for virtual master */ hda_nid_t vmaster_nid; + struct snd_kcontrol *vmaster_sw_kctl; #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_loopback_check loopback; int num_loopbacks; @@ -1441,6 +1442,7 @@ enum { ALC_FIXUP_ACT_PRE_PROBE, ALC_FIXUP_ACT_PROBE, ALC_FIXUP_ACT_INIT, + ALC_FIXUP_ACT_BUILD, }; static void alc_apply_fixup(struct hda_codec *codec, int action) @@ -1955,9 +1957,10 @@ static int __alc_build_controls(struct hda_codec *codec) } if (!spec->no_analog && !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { - err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, alc_slave_pfxs, - "Playback Switch"); + err = __snd_hda_add_vmaster(codec, "Master Playback Switch", + NULL, alc_slave_pfxs, + "Playback Switch", + true, &spec->vmaster_sw_kctl); if (err < 0) return err; } @@ -2042,7 +2045,11 @@ static int alc_build_controls(struct hda_codec *codec) int err = __alc_build_controls(codec); if (err < 0) return err; - return snd_hda_jack_add_kctls(codec, &spec->autocfg); + err = snd_hda_jack_add_kctls(codec, &spec->autocfg); + if (err < 0) + return err; + alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); + return 0; } @@ -5721,35 +5728,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = { /* NID is set in alc_build_pcms */ }; -#ifdef CONFIG_SND_HDA_POWER_SAVE -static int alc269_mic2_for_mute_led(struct hda_codec *codec) -{ - switch (codec->subsystem_id) { - case 0x103c1586: - return 1; - } - return 0; -} - -static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) -{ - /* update mute-LED according to the speaker mute state */ - if (nid == 0x01 || nid == 0x14) { - int pinval; - if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) & - HDA_AMP_MUTE) - pinval = 0x24; - else - pinval = 0x20; - /* mic2 vref pin is used for mute LED control */ - snd_hda_codec_update_cache(codec, 0x19, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pinval); - } - return alc_check_power_status(codec, nid); -} -#endif /* CONFIG_SND_HDA_POWER_SAVE */ - /* different alc269-variants */ enum { ALC269_TYPE_ALC269VA, @@ -5900,6 +5878,33 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, spec->automute_hook = alc269_quanta_automute; } +/* update mute-LED according to the speaker mute state via mic2 VREF pin */ +static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled) +{ + struct hda_codec *codec = private_data; + unsigned int pinval = enabled ? 0x20 : 0x24; + snd_hda_codec_update_cache(codec, 0x19, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + pinval); +} + +static void alc269_fixup_mic2_mute(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + switch (action) { + case ALC_FIXUP_ACT_BUILD: + if (!spec->vmaster_sw_kctl) + return; + snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl, + alc269_fixup_mic2_mute_hook, codec); + /* fallthru */ + case ALC_FIXUP_ACT_INIT: + snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); + break; + } +} + enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -5917,6 +5922,7 @@ enum { ALC269_FIXUP_DMIC, ALC269VB_FIXUP_AMIC, ALC269VB_FIXUP_DMIC, + ALC269_FIXUP_MIC2_MUTE_LED, }; static const struct alc_fixup alc269_fixups[] = { @@ -6037,9 +6043,14 @@ static const struct alc_fixup alc269_fixups[] = { { } }, }, + [ALC269_FIXUP_MIC2_MUTE_LED] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc269_fixup_mic2_mute, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), @@ -6231,11 +6242,6 @@ static int patch_alc269(struct hda_codec *codec) #endif spec->shutup = alc269_shutup; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (alc269_mic2_for_mute_led(codec)) - codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps; -#endif - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); return 0; -- cgit v1.2.3 From 527c73bada6f02a35983ddb34db3a0fd4360c88c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Mar 2012 12:38:51 +0100 Subject: ALSA: hda - Add EAPD control to Conexnat auto-parser Added the vmaster hook for controlling EAPD dynamically to Conexant auto-parser. When the Master is muted, EAPDs are turned off as well. This will fix the missing mute-LED control on some machines in addition to the more power-saving in the auto-parser mode. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5a56fda83625..f1c9aed9fa69 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -70,6 +70,8 @@ struct conexant_spec { const struct snd_kcontrol_new *mixers[5]; int num_mixers; hda_nid_t vmaster_nid; + struct snd_kcontrol *vmaster_sw_kctl; + void (*vmaster_hook)(struct snd_kcontrol *, int); const struct hda_verb *init_verbs[5]; /* initialization verbs * don't forget NULL @@ -513,9 +515,10 @@ static int conexant_build_controls(struct hda_codec *codec) } if (spec->vmaster_nid && !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { - err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, slave_pfxs, - "Playback Switch"); + err = __snd_hda_add_vmaster(codec, "Master Playback Switch", + NULL, slave_pfxs, + "Playback Switch", true, + &spec->vmaster_sw_kctl); if (err < 0) return err; } @@ -3975,6 +3978,19 @@ static void clear_unsol_on_unused_pins(struct hda_codec *codec) } } +/* turn on/off EAPD according to Master switch */ +static void cx_auto_vmaster_hook(void *private_data, int enabled) +{ + struct hda_codec *codec = private_data; + struct conexant_spec *spec = codec->spec; + + if (enabled && spec->pin_eapd_ctrls) { + cx_auto_update_speakers(codec); + return; + } + cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled); +} + static void cx_auto_init_output(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; @@ -4079,11 +4095,13 @@ static void cx_auto_init_digital(struct hda_codec *codec) static int cx_auto_init(struct hda_codec *codec) { + struct conexant_spec *spec = codec->spec; /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ cx_auto_init_output(codec); cx_auto_init_input(codec); cx_auto_init_digital(codec); snd_hda_jack_report_sync(codec); + snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); return 0; } @@ -4329,6 +4347,11 @@ static int cx_auto_build_controls(struct hda_codec *codec) err = snd_hda_jack_add_kctls(codec, &spec->autocfg); if (err < 0) return err; + if (spec->vmaster_hook && spec->vmaster_sw_kctl) { + snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl, + spec->vmaster_hook, codec); + snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); + } return 0; } @@ -4353,7 +4376,6 @@ static int cx_auto_search_adcs(struct hda_codec *codec) return 0; } - static const struct hda_codec_ops cx_auto_patch_ops = { .build_controls = cx_auto_build_controls, .build_pcms = conexant_build_pcms, @@ -4455,6 +4477,12 @@ static int patch_conexant_auto(struct hda_codec *codec) apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); + /* add EAPD vmaster hook to all HP machines */ + /* NOTE: this should be applied via fixup once when the generic + * fixup code is merged to hda_codec.c + */ + spec->vmaster_hook = cx_auto_vmaster_hook; + err = cx_auto_search_adcs(codec); if (err < 0) return err; -- cgit v1.2.3 From d2f344b5e0a933b5b1d12f863406ee1d63e5bf8e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Mar 2012 16:59:58 +0100 Subject: ALSA: hda - Add "Mute-LED Mode" enum control Create snd_hda_add_vmaster_hook() and snd_hda_sync_vmaster_hook() helper functions to handle the mute-LED in vmaster hook more commonly. In the former function, a new enum control "Mute-LED Mode" is added. This provides user to choose whether the mute-LED should be turned on/off explicitly or to follow the master-mute status. Reviewed-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 94 ++++++++++++++++++++++++++++++++++++++++++ sound/pci/hda/hda_local.h | 21 ++++++++++ sound/pci/hda/patch_conexant.c | 17 ++++---- sound/pci/hda/patch_realtek.c | 12 +++--- sound/pci/hda/patch_sigmatel.c | 13 +++--- 5 files changed, 135 insertions(+), 22 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b79ee3444654..b981ea9c644c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2450,6 +2450,100 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, } EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster); +/* + * mute-LED control using vmaster + */ +static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static const char * const texts[] = { + "Off", "On", "Follow Master" + }; + unsigned int index; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 3; + index = uinfo->value.enumerated.item; + if (index >= 3) + index = 2; + strcpy(uinfo->value.enumerated.name, texts[index]); + return 0; +} + +static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); + ucontrol->value.enumerated.item[0] = hook->mute_mode; + return 0; +} + +static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); + unsigned int old_mode = hook->mute_mode; + + hook->mute_mode = ucontrol->value.enumerated.item[0]; + if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER) + hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; + if (old_mode == hook->mute_mode) + return 0; + snd_hda_sync_vmaster_hook(hook); + return 1; +} + +static struct snd_kcontrol_new vmaster_mute_mode = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mute-LED Mode", + .info = vmaster_mute_mode_info, + .get = vmaster_mute_mode_get, + .put = vmaster_mute_mode_put, +}; + +/* + * Add a mute-LED hook with the given vmaster switch kctl + * "Mute-LED Mode" control is automatically created and associated with + * the given hook. + */ +int snd_hda_add_vmaster_hook(struct hda_codec *codec, + struct hda_vmaster_mute_hook *hook) +{ + struct snd_kcontrol *kctl; + + if (!hook->hook || !hook->sw_kctl) + return 0; + snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); + hook->codec = codec; + hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; + kctl = snd_ctl_new1(&vmaster_mute_mode, hook); + if (!kctl) + return -ENOMEM; + return snd_hda_ctl_add(codec, 0, kctl); +} +EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook); + +/* + * Call the hook with the current value for synchronization + * Should be called in init callback + */ +void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) +{ + if (!hook->hook || !hook->codec) + return; + switch (hook->mute_mode) { + case HDA_VMUTE_FOLLOW_MASTER: + snd_ctl_sync_vmaster_hook(hook->sw_kctl); + break; + default: + hook->hook(hook->codec, hook->mute_mode); + break; + } +} +EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook); + + /** * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch * diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index c3ee4ede4482..3f82ab6a0587 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -147,6 +147,27 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL) int snd_hda_codec_reset(struct hda_codec *codec); +enum { + HDA_VMUTE_OFF, + HDA_VMUTE_ON, + HDA_VMUTE_FOLLOW_MASTER, +}; + +struct hda_vmaster_mute_hook { + /* below two fields must be filled by the caller of + * snd_hda_add_vmaster_hook() beforehand + */ + struct snd_kcontrol *sw_kctl; + void (*hook)(void *, int); + /* below are initialized automatically */ + unsigned int mute_mode; /* HDA_VMUTE_XXX */ + struct hda_codec *codec; +}; + +int snd_hda_add_vmaster_hook(struct hda_codec *codec, + struct hda_vmaster_mute_hook *hook); +void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); + /* amp value bits */ #define HDA_AMP_MUTE 0x80 #define HDA_AMP_UNMUTE 0x00 diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index f1c9aed9fa69..a21a485a413c 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -70,8 +70,7 @@ struct conexant_spec { const struct snd_kcontrol_new *mixers[5]; int num_mixers; hda_nid_t vmaster_nid; - struct snd_kcontrol *vmaster_sw_kctl; - void (*vmaster_hook)(struct snd_kcontrol *, int); + struct hda_vmaster_mute_hook vmaster_mute; const struct hda_verb *init_verbs[5]; /* initialization verbs * don't forget NULL @@ -518,7 +517,7 @@ static int conexant_build_controls(struct hda_codec *codec) err = __snd_hda_add_vmaster(codec, "Master Playback Switch", NULL, slave_pfxs, "Playback Switch", true, - &spec->vmaster_sw_kctl); + &spec->vmaster_mute.sw_kctl); if (err < 0) return err; } @@ -4101,7 +4100,7 @@ static int cx_auto_init(struct hda_codec *codec) cx_auto_init_input(codec); cx_auto_init_digital(codec); snd_hda_jack_report_sync(codec); - snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); return 0; } @@ -4347,10 +4346,10 @@ static int cx_auto_build_controls(struct hda_codec *codec) err = snd_hda_jack_add_kctls(codec, &spec->autocfg); if (err < 0) return err; - if (spec->vmaster_hook && spec->vmaster_sw_kctl) { - snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl, - spec->vmaster_hook, codec); - snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); + if (spec->vmaster_mute.hook && spec->vmaster_mute.sw_kctl) { + err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute); + if (err < 0) + return err; } return 0; } @@ -4481,7 +4480,7 @@ static int patch_conexant_auto(struct hda_codec *codec) /* NOTE: this should be applied via fixup once when the generic * fixup code is merged to hda_codec.c */ - spec->vmaster_hook = cx_auto_vmaster_hook; + spec->vmaster_mute.hook = cx_auto_vmaster_hook; err = cx_auto_search_adcs(codec); if (err < 0) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 901547216c4e..b69d2fe40297 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -198,7 +198,7 @@ struct alc_spec { /* for virtual master */ hda_nid_t vmaster_nid; - struct snd_kcontrol *vmaster_sw_kctl; + struct hda_vmaster_mute_hook vmaster_mute; #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_loopback_check loopback; int num_loopbacks; @@ -1960,7 +1960,7 @@ static int __alc_build_controls(struct hda_codec *codec) err = __snd_hda_add_vmaster(codec, "Master Playback Switch", NULL, alc_slave_pfxs, "Playback Switch", - true, &spec->vmaster_sw_kctl); + true, &spec->vmaster_mute.sw_kctl); if (err < 0) return err; } @@ -5894,13 +5894,11 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, struct alc_spec *spec = codec->spec; switch (action) { case ALC_FIXUP_ACT_BUILD: - if (!spec->vmaster_sw_kctl) - return; - snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl, - alc269_fixup_mic2_mute_hook, codec); + spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook; + snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute); /* fallthru */ case ALC_FIXUP_ACT_INIT: - snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); break; } } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6e926497b230..cd04e29e157b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -311,7 +311,7 @@ struct sigmatel_spec { unsigned auto_dmic_cnt; hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; - struct snd_kcontrol *vmaster_sw_kctl; + struct hda_vmaster_mute_hook vmaster_mute; }; static const hda_nid_t stac9200_adc_nids[1] = { @@ -1160,14 +1160,15 @@ static int stac92xx_build_controls(struct hda_codec *codec) err = __snd_hda_add_vmaster(codec, "Master Playback Switch", NULL, slave_pfxs, "Playback Switch", true, - &spec->vmaster_sw_kctl); + &spec->vmaster_mute.sw_kctl); if (err < 0) return err; if (spec->gpio_led) { - snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl, - stac92xx_vmaster_hook, codec); - snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); + spec->vmaster_mute.hook = stac92xx_vmaster_hook; + err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute); + if (err < 0) + return err; } if (spec->aloopback_ctl && @@ -4432,7 +4433,7 @@ static int stac92xx_init(struct hda_codec *codec) snd_hda_jack_report_sync(codec); /* sync mute LED */ - snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); if (spec->dac_list) stac92xx_power_down(codec); return 0; -- cgit v1.2.3 From f29735cbef4eb6072e5ae459b556f3a061efc47e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Mar 2012 07:55:10 +0100 Subject: ALSA: hda - Add expose_enum_ctl flag to snd_hda_add_vmaster_hook() Since it's not always safe to assume that the vmaster hook is purely the mute-LED control, add the flag indicating whether to expose the mute-LED enum control or not. Currently, conexant codec sets this off for non-HP laptops where EAPD may be used really as EAPD. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 5 ++++- sound/pci/hda/hda_local.h | 3 ++- sound/pci/hda/patch_conexant.c | 21 +++++++++++++++------ sound/pci/hda/patch_realtek.c | 2 +- sound/pci/hda/patch_sigmatel.c | 2 +- 5 files changed, 23 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b981ea9c644c..7a8fcc4c15f8 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2508,7 +2508,8 @@ static struct snd_kcontrol_new vmaster_mute_mode = { * the given hook. */ int snd_hda_add_vmaster_hook(struct hda_codec *codec, - struct hda_vmaster_mute_hook *hook) + struct hda_vmaster_mute_hook *hook, + bool expose_enum_ctl) { struct snd_kcontrol *kctl; @@ -2517,6 +2518,8 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec, snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); hook->codec = codec; hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; + if (!expose_enum_ctl) + return 0; kctl = snd_ctl_new1(&vmaster_mute_mode, hook); if (!kctl) return -ENOMEM; diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 3f82ab6a0587..0ec9248165bc 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -165,7 +165,8 @@ struct hda_vmaster_mute_hook { }; int snd_hda_add_vmaster_hook(struct hda_codec *codec, - struct hda_vmaster_mute_hook *hook); + struct hda_vmaster_mute_hook *hook, + bool expose_enum_ctl); void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); /* amp value bits */ diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a21a485a413c..e6eafb18c8f5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -71,6 +71,7 @@ struct conexant_spec { int num_mixers; hda_nid_t vmaster_nid; struct hda_vmaster_mute_hook vmaster_mute; + bool vmaster_mute_led; const struct hda_verb *init_verbs[5]; /* initialization verbs * don't forget NULL @@ -4346,8 +4347,10 @@ static int cx_auto_build_controls(struct hda_codec *codec) err = snd_hda_jack_add_kctls(codec, &spec->autocfg); if (err < 0) return err; - if (spec->vmaster_mute.hook && spec->vmaster_mute.sw_kctl) { - err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute); + if (spec->vmaster_mute.sw_kctl) { + spec->vmaster_mute.hook = cx_auto_vmaster_hook; + err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, + spec->vmaster_mute_led); if (err < 0) return err; } @@ -4476,11 +4479,17 @@ static int patch_conexant_auto(struct hda_codec *codec) apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); - /* add EAPD vmaster hook to all HP machines */ - /* NOTE: this should be applied via fixup once when the generic - * fixup code is merged to hda_codec.c + /* Show mute-led control only on HP laptops + * This is a sort of white-list: on HP laptops, EAPD corresponds + * only to the mute-LED without actualy amp function. Meanwhile, + * others may use EAPD really as an amp switch, so it might be + * not good to expose it blindly. */ - spec->vmaster_mute.hook = cx_auto_vmaster_hook; + switch (codec->subsystem_id >> 16) { + case 0x103c: + spec->vmaster_mute_led = 1; + break; + } err = cx_auto_search_adcs(codec); if (err < 0) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b69d2fe40297..8ea2fd654327 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5895,7 +5895,7 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, switch (action) { case ALC_FIXUP_ACT_BUILD: spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook; - snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute); + snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); /* fallthru */ case ALC_FIXUP_ACT_INIT: snd_hda_sync_vmaster_hook(&spec->vmaster_mute); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index cd04e29e157b..153b9ae46ba4 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1166,7 +1166,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) if (spec->gpio_led) { spec->vmaster_mute.hook = stac92xx_vmaster_hook; - err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute); + err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); if (err < 0) return err; } -- cgit v1.2.3 From 7907ae3e50613ae1c6d1a10f34fcd63f4123b93d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 14 Mar 2012 08:20:20 +0100 Subject: ALSA: hda - Fix build of patch_sigmatel.c without CONFIG_SND_HDA_POWER_SAVE Now the mute-LED is controlled without powersave hack, and the ifdefs must be removed. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 153b9ae46ba4..b064e595bb60 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -665,7 +665,6 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, return 0; } -#ifdef CONFIG_SND_HDA_POWER_SAVE static int stac_vrefout_set(struct hda_codec *codec, hda_nid_t nid, unsigned int new_vref) { @@ -689,7 +688,6 @@ static int stac_vrefout_set(struct hda_codec *codec, return 1; } -#endif static unsigned int stac92xx_vref_set(struct hda_codec *codec, hda_nid_t nid, unsigned int new_vref) @@ -5011,7 +5009,6 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) return 0; } -#ifdef CONFIG_SND_HDA_POWER_SAVE static int stac92xx_pre_resume(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -5046,7 +5043,6 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, afg_power_state); snd_hda_codec_set_power_to_all(codec, fg, power_state, true); } -#endif /* CONFIG_SND_HDA_POWER_SAVE */ #endif /* CONFIG_PM */ /* update mute-LED accoring to the master switch */ @@ -5583,7 +5579,6 @@ again: spec->gpio_led, spec->gpio_led_polarity); -#ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; @@ -5595,7 +5590,6 @@ again: } codec->patch_ops.pre_resume = stac92xx_pre_resume; } -#endif err = stac92xx_parse_auto_config(codec); if (!err) { @@ -5892,7 +5886,6 @@ again: spec->gpio_led, spec->gpio_led_polarity); -#ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; @@ -5904,7 +5897,6 @@ again: } codec->patch_ops.pre_resume = stac92xx_pre_resume; } -#endif spec->multiout.dac_nids = spec->dac_nids; -- cgit v1.2.3 From 350eba43fca735733a51185f26bdc30899c64a20 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 16 Mar 2012 16:09:03 +0100 Subject: ALSA: hda - Fix build with CONFIG_PM=n Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b064e595bb60..33a9946b492c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5043,6 +5043,11 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, afg_power_state); snd_hda_codec_set_power_to_all(codec, fg, power_state, true); } +#else +#define stac92xx_suspend NULL +#define stac92xx_resume NULL +#define stac92xx_pre_resume NULL +#define stac92xx_set_power_state NULL #endif /* CONFIG_PM */ /* update mute-LED accoring to the master switch */ @@ -5588,7 +5593,9 @@ again: codec->patch_ops.set_power_state = stac92xx_set_power_state; } +#ifdef CONFIG_PM codec->patch_ops.pre_resume = stac92xx_pre_resume; +#endif } err = stac92xx_parse_auto_config(codec); @@ -5895,7 +5902,9 @@ again: codec->patch_ops.set_power_state = stac92xx_set_power_state; } +#ifdef CONFIG_PM codec->patch_ops.pre_resume = stac92xx_pre_resume; +#endif } spec->multiout.dac_nids = spec->dac_nids; -- cgit v1.2.3