diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-10-03 12:31:33 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-10-03 12:31:33 -0400 |
commit | 7fa9742bf7f918293c0b3ffd84167fccbdd42765 (patch) | |
tree | 5625c42c045972417a33217cc0f84b7f51a9c182 | |
parent | a1cb9cd69750d6d62251393738efc02d252b67d3 (diff) | |
parent | 7085ec12a62ec2e990bc7d984bee7ba28e5c1dec (diff) |
Merge branch 'fix/hda' into for-linus
-rw-r--r-- | Documentation/sound/alsa/HD-Audio-Models.txt | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 139 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 12 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 244 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 20 |
6 files changed, 323 insertions, 94 deletions
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 97eebd63bedc..a2643cfe7938 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt | |||
@@ -209,6 +209,7 @@ AD1884A / AD1883 / AD1984A / AD1984B | |||
209 | laptop laptop with HP jack sensing | 209 | laptop laptop with HP jack sensing |
210 | mobile mobile devices with HP jack sensing | 210 | mobile mobile devices with HP jack sensing |
211 | thinkpad Lenovo Thinkpad X300 | 211 | thinkpad Lenovo Thinkpad X300 |
212 | touchsmart HP Touchsmart | ||
212 | 213 | ||
213 | AD1884 | 214 | AD1884 |
214 | ====== | 215 | ====== |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 20a66f85f0a4..c9ad182e1b4b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -2303,6 +2303,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) | |||
2303 | * white-list for enable_msi | 2303 | * white-list for enable_msi |
2304 | */ | 2304 | */ |
2305 | static struct snd_pci_quirk msi_white_list[] __devinitdata = { | 2305 | static struct snd_pci_quirk msi_white_list[] __devinitdata = { |
2306 | SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1), | ||
2306 | SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1), | 2307 | SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1), |
2307 | {} | 2308 | {} |
2308 | }; | 2309 | }; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 215e72a87113..2d603f6aba63 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -4032,6 +4032,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec) | |||
4032 | } | 4032 | } |
4033 | 4033 | ||
4034 | /* | 4034 | /* |
4035 | * HP Touchsmart | ||
4036 | * port-A (0x11) - front hp-out | ||
4037 | * port-B (0x14) - unused | ||
4038 | * port-C (0x15) - unused | ||
4039 | * port-D (0x12) - rear line out | ||
4040 | * port-E (0x1c) - front mic-in | ||
4041 | * port-F (0x16) - Internal speakers | ||
4042 | * digital-mic (0x17) - Internal mic | ||
4043 | */ | ||
4044 | |||
4045 | static struct hda_verb ad1984a_touchsmart_verbs[] = { | ||
4046 | /* DACs; unmute as default */ | ||
4047 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ | ||
4048 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ | ||
4049 | /* Port-A (HP) mixer - route only from analog mixer */ | ||
4050 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4051 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4052 | /* Port-A pin */ | ||
4053 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
4054 | /* Port-A (HP) pin - always unmuted */ | ||
4055 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4056 | /* Port-E (int speaker) mixer - route only from analog mixer */ | ||
4057 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, | ||
4058 | /* Port-E pin */ | ||
4059 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
4060 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4061 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
4062 | /* Port-F (int speaker) mixer - route only from analog mixer */ | ||
4063 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4064 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4065 | /* Port-F pin */ | ||
4066 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
4067 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4068 | /* Analog mixer; mute as default */ | ||
4069 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4070 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
4071 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
4072 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
4073 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
4074 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, | ||
4075 | /* Analog Mix output amp */ | ||
4076 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4077 | /* capture sources */ | ||
4078 | /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ | ||
4079 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4080 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
4081 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4082 | /* unsolicited event for pin-sense */ | ||
4083 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, | ||
4084 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, | ||
4085 | /* allow to touch GPIO1 (for mute control) */ | ||
4086 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
4087 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
4088 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ | ||
4089 | /* internal mic - dmic */ | ||
4090 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
4091 | /* set magic COEFs for dmic */ | ||
4092 | {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, | ||
4093 | {0x01, AC_VERB_SET_PROC_COEF, 0x08}, | ||
4094 | { } /* end */ | ||
4095 | }; | ||
4096 | |||
4097 | static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { | ||
4098 | HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), | ||
4099 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ | ||
4100 | { | ||
4101 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4102 | .name = "Master Playback Switch", | ||
4103 | .info = snd_hda_mixer_amp_switch_info, | ||
4104 | .get = snd_hda_mixer_amp_switch_get, | ||
4105 | .put = ad1884a_mobile_master_sw_put, | ||
4106 | .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), | ||
4107 | }, | ||
4108 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), | ||
4109 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | ||
4110 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
4111 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | ||
4112 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), | ||
4113 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), | ||
4114 | { } /* end */ | ||
4115 | }; | ||
4116 | |||
4117 | /* switch to external mic if plugged */ | ||
4118 | static void ad1984a_touchsmart_automic(struct hda_codec *codec) | ||
4119 | { | ||
4120 | if (snd_hda_codec_read(codec, 0x1c, 0, | ||
4121 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) { | ||
4122 | snd_hda_codec_write(codec, 0x0c, 0, | ||
4123 | AC_VERB_SET_CONNECT_SEL, 0x4); | ||
4124 | } else { | ||
4125 | snd_hda_codec_write(codec, 0x0c, 0, | ||
4126 | AC_VERB_SET_CONNECT_SEL, 0x5); | ||
4127 | } | ||
4128 | } | ||
4129 | |||
4130 | |||
4131 | /* unsolicited event for HP jack sensing */ | ||
4132 | static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, | ||
4133 | unsigned int res) | ||
4134 | { | ||
4135 | switch (res >> 26) { | ||
4136 | case AD1884A_HP_EVENT: | ||
4137 | ad1884a_hp_automute(codec); | ||
4138 | break; | ||
4139 | case AD1884A_MIC_EVENT: | ||
4140 | ad1984a_touchsmart_automic(codec); | ||
4141 | break; | ||
4142 | } | ||
4143 | } | ||
4144 | |||
4145 | /* initialize jack-sensing, too */ | ||
4146 | static int ad1984a_touchsmart_init(struct hda_codec *codec) | ||
4147 | { | ||
4148 | ad198x_init(codec); | ||
4149 | ad1884a_hp_automute(codec); | ||
4150 | ad1984a_touchsmart_automic(codec); | ||
4151 | return 0; | ||
4152 | } | ||
4153 | |||
4154 | |||
4155 | /* | ||
4035 | */ | 4156 | */ |
4036 | 4157 | ||
4037 | enum { | 4158 | enum { |
@@ -4039,6 +4160,7 @@ enum { | |||
4039 | AD1884A_LAPTOP, | 4160 | AD1884A_LAPTOP, |
4040 | AD1884A_MOBILE, | 4161 | AD1884A_MOBILE, |
4041 | AD1884A_THINKPAD, | 4162 | AD1884A_THINKPAD, |
4163 | AD1984A_TOUCHSMART, | ||
4042 | AD1884A_MODELS | 4164 | AD1884A_MODELS |
4043 | }; | 4165 | }; |
4044 | 4166 | ||
@@ -4047,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = { | |||
4047 | [AD1884A_LAPTOP] = "laptop", | 4169 | [AD1884A_LAPTOP] = "laptop", |
4048 | [AD1884A_MOBILE] = "mobile", | 4170 | [AD1884A_MOBILE] = "mobile", |
4049 | [AD1884A_THINKPAD] = "thinkpad", | 4171 | [AD1884A_THINKPAD] = "thinkpad", |
4172 | [AD1984A_TOUCHSMART] = "touchsmart", | ||
4050 | }; | 4173 | }; |
4051 | 4174 | ||
4052 | static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | 4175 | static struct snd_pci_quirk ad1884a_cfg_tbl[] = { |
@@ -4059,6 +4182,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | |||
4059 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), | 4182 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), |
4060 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), | 4183 | SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), |
4061 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), | 4184 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), |
4185 | SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), | ||
4062 | {} | 4186 | {} |
4063 | }; | 4187 | }; |
4064 | 4188 | ||
@@ -4142,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
4142 | codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; | 4266 | codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; |
4143 | codec->patch_ops.init = ad1984a_thinkpad_init; | 4267 | codec->patch_ops.init = ad1984a_thinkpad_init; |
4144 | break; | 4268 | break; |
4269 | case AD1984A_TOUCHSMART: | ||
4270 | spec->mixers[0] = ad1984a_touchsmart_mixers; | ||
4271 | spec->init_verbs[0] = ad1984a_touchsmart_verbs; | ||
4272 | spec->multiout.dig_out_nid = 0; | ||
4273 | codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; | ||
4274 | codec->patch_ops.init = ad1984a_touchsmart_init; | ||
4275 | /* set the upper-limit for mixer amp to 0dB for avoiding the | ||
4276 | * possible damage by overloading | ||
4277 | */ | ||
4278 | snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, | ||
4279 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
4280 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
4281 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
4282 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
4283 | break; | ||
4145 | } | 4284 | } |
4146 | 4285 | ||
4147 | return 0; | 4286 | return 0; |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 9d899eda44d7..3fbbc8c01e70 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -682,11 +682,13 @@ static struct hda_input_mux cxt5045_capture_source = { | |||
682 | }; | 682 | }; |
683 | 683 | ||
684 | static struct hda_input_mux cxt5045_capture_source_benq = { | 684 | static struct hda_input_mux cxt5045_capture_source_benq = { |
685 | .num_items = 3, | 685 | .num_items = 5, |
686 | .items = { | 686 | .items = { |
687 | { "IntMic", 0x1 }, | 687 | { "IntMic", 0x1 }, |
688 | { "ExtMic", 0x2 }, | 688 | { "ExtMic", 0x2 }, |
689 | { "LineIn", 0x3 }, | 689 | { "LineIn", 0x3 }, |
690 | { "CD", 0x4 }, | ||
691 | { "Mixer", 0x0 }, | ||
690 | } | 692 | } |
691 | }; | 693 | }; |
692 | 694 | ||
@@ -811,11 +813,19 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
811 | }; | 813 | }; |
812 | 814 | ||
813 | static struct snd_kcontrol_new cxt5045_benq_mixers[] = { | 815 | static struct snd_kcontrol_new cxt5045_benq_mixers[] = { |
816 | HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT), | ||
817 | HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT), | ||
818 | HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT), | ||
819 | HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT), | ||
820 | |||
814 | HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT), | 821 | HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT), |
815 | HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT), | 822 | HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT), |
816 | HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT), | 823 | HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT), |
817 | HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT), | 824 | HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT), |
818 | 825 | ||
826 | HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT), | ||
827 | HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
828 | |||
819 | {} | 829 | {} |
820 | }; | 830 | }; |
821 | 831 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 129605819560..7810d3dcad83 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -12660,7 +12660,7 @@ static struct alc_config_preset alc268_presets[] = { | |||
12660 | .init_hook = alc268_toshiba_automute, | 12660 | .init_hook = alc268_toshiba_automute, |
12661 | }, | 12661 | }, |
12662 | [ALC268_ACER] = { | 12662 | [ALC268_ACER] = { |
12663 | .mixers = { alc268_acer_mixer, alc268_capture_nosrc_mixer, | 12663 | .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer, |
12664 | alc268_beep_mixer }, | 12664 | alc268_beep_mixer }, |
12665 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 12665 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
12666 | alc268_acer_verbs }, | 12666 | alc268_acer_verbs }, |
@@ -16852,6 +16852,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
16852 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), | 16852 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), |
16853 | SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", | 16853 | SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", |
16854 | ALC662_3ST_6ch_DIG), | 16854 | ALC662_3ST_6ch_DIG), |
16855 | SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4), | ||
16855 | SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), | 16856 | SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), |
16856 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", | 16857 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", |
16857 | ALC662_3ST_6ch_DIG), | 16858 | ALC662_3ST_6ch_DIG), |
@@ -17145,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = { | |||
17145 | * BIOS auto configuration | 17146 | * BIOS auto configuration |
17146 | */ | 17147 | */ |
17147 | 17148 | ||
17149 | /* convert from MIX nid to DAC */ | ||
17150 | static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) | ||
17151 | { | ||
17152 | if (nid == 0x0f) | ||
17153 | return 0x02; | ||
17154 | else if (nid >= 0x0c && nid <= 0x0e) | ||
17155 | return nid - 0x0c + 0x02; | ||
17156 | else | ||
17157 | return 0; | ||
17158 | } | ||
17159 | |||
17160 | /* get MIX nid connected to the given pin targeted to DAC */ | ||
17161 | static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin, | ||
17162 | hda_nid_t dac) | ||
17163 | { | ||
17164 | hda_nid_t mix[4]; | ||
17165 | int i, num; | ||
17166 | |||
17167 | num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); | ||
17168 | for (i = 0; i < num; i++) { | ||
17169 | if (alc662_mix_to_dac(mix[i]) == dac) | ||
17170 | return mix[i]; | ||
17171 | } | ||
17172 | return 0; | ||
17173 | } | ||
17174 | |||
17175 | /* look for an empty DAC slot */ | ||
17176 | static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | ||
17177 | { | ||
17178 | struct alc_spec *spec = codec->spec; | ||
17179 | hda_nid_t srcs[5]; | ||
17180 | int i, j, num; | ||
17181 | |||
17182 | num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); | ||
17183 | if (num < 0) | ||
17184 | return 0; | ||
17185 | for (i = 0; i < num; i++) { | ||
17186 | hda_nid_t nid = alc662_mix_to_dac(srcs[i]); | ||
17187 | if (!nid) | ||
17188 | continue; | ||
17189 | for (j = 0; j < spec->multiout.num_dacs; j++) | ||
17190 | if (spec->multiout.dac_nids[j] == nid) | ||
17191 | break; | ||
17192 | if (j >= spec->multiout.num_dacs) | ||
17193 | return nid; | ||
17194 | } | ||
17195 | return 0; | ||
17196 | } | ||
17197 | |||
17198 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
17199 | static int alc662_auto_fill_dac_nids(struct hda_codec *codec, | ||
17200 | const struct auto_pin_cfg *cfg) | ||
17201 | { | ||
17202 | struct alc_spec *spec = codec->spec; | ||
17203 | int i; | ||
17204 | hda_nid_t dac; | ||
17205 | |||
17206 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
17207 | for (i = 0; i < cfg->line_outs; i++) { | ||
17208 | dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]); | ||
17209 | if (!dac) | ||
17210 | continue; | ||
17211 | spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; | ||
17212 | } | ||
17213 | return 0; | ||
17214 | } | ||
17215 | |||
17216 | static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, | ||
17217 | hda_nid_t nid, unsigned int chs) | ||
17218 | { | ||
17219 | char name[32]; | ||
17220 | sprintf(name, "%s Playback Volume", pfx); | ||
17221 | return add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
17222 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
17223 | } | ||
17224 | |||
17225 | static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, | ||
17226 | hda_nid_t nid, unsigned int chs) | ||
17227 | { | ||
17228 | char name[32]; | ||
17229 | sprintf(name, "%s Playback Switch", pfx); | ||
17230 | return add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
17231 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); | ||
17232 | } | ||
17233 | |||
17234 | #define alc662_add_stereo_vol(spec, pfx, nid) \ | ||
17235 | alc662_add_vol_ctl(spec, pfx, nid, 3) | ||
17236 | #define alc662_add_stereo_sw(spec, pfx, nid) \ | ||
17237 | alc662_add_sw_ctl(spec, pfx, nid, 3) | ||
17238 | |||
17148 | /* add playback controls from the parsed DAC table */ | 17239 | /* add playback controls from the parsed DAC table */ |
17149 | static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, | 17240 | static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, |
17150 | const struct auto_pin_cfg *cfg) | 17241 | const struct auto_pin_cfg *cfg) |
17151 | { | 17242 | { |
17152 | char name[32]; | 17243 | struct alc_spec *spec = codec->spec; |
17153 | static const char *chname[4] = { | 17244 | static const char *chname[4] = { |
17154 | "Front", "Surround", NULL /*CLFE*/, "Side" | 17245 | "Front", "Surround", NULL /*CLFE*/, "Side" |
17155 | }; | 17246 | }; |
17156 | hda_nid_t nid; | 17247 | hda_nid_t nid, mix; |
17157 | int i, err; | 17248 | int i, err; |
17158 | 17249 | ||
17159 | for (i = 0; i < cfg->line_outs; i++) { | 17250 | for (i = 0; i < cfg->line_outs; i++) { |
17160 | if (!spec->multiout.dac_nids[i]) | 17251 | nid = spec->multiout.dac_nids[i]; |
17252 | if (!nid) | ||
17253 | continue; | ||
17254 | mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); | ||
17255 | if (!mix) | ||
17161 | continue; | 17256 | continue; |
17162 | nid = alc880_idx_to_dac(i); | ||
17163 | if (i == 2) { | 17257 | if (i == 2) { |
17164 | /* Center/LFE */ | 17258 | /* Center/LFE */ |
17165 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 17259 | err = alc662_add_vol_ctl(spec, "Center", nid, 1); |
17166 | "Center Playback Volume", | ||
17167 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, | ||
17168 | HDA_OUTPUT)); | ||
17169 | if (err < 0) | 17260 | if (err < 0) |
17170 | return err; | 17261 | return err; |
17171 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 17262 | err = alc662_add_vol_ctl(spec, "LFE", nid, 2); |
17172 | "LFE Playback Volume", | ||
17173 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
17174 | HDA_OUTPUT)); | ||
17175 | if (err < 0) | 17263 | if (err < 0) |
17176 | return err; | 17264 | return err; |
17177 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, | 17265 | err = alc662_add_sw_ctl(spec, "Center", mix, 1); |
17178 | "Center Playback Switch", | ||
17179 | HDA_COMPOSE_AMP_VAL(0x0e, 1, 0, | ||
17180 | HDA_INPUT)); | ||
17181 | if (err < 0) | 17266 | if (err < 0) |
17182 | return err; | 17267 | return err; |
17183 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, | 17268 | err = alc662_add_sw_ctl(spec, "LFE", mix, 2); |
17184 | "LFE Playback Switch", | ||
17185 | HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, | ||
17186 | HDA_INPUT)); | ||
17187 | if (err < 0) | 17269 | if (err < 0) |
17188 | return err; | 17270 | return err; |
17189 | } else { | 17271 | } else { |
17190 | const char *pfx; | 17272 | const char *pfx; |
17191 | if (cfg->line_outs == 1 && | 17273 | if (cfg->line_outs == 1 && |
17192 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | 17274 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { |
17193 | if (!cfg->hp_pins) | 17275 | if (cfg->hp_outs) |
17194 | pfx = "Speaker"; | 17276 | pfx = "Speaker"; |
17195 | else | 17277 | else |
17196 | pfx = "PCM"; | 17278 | pfx = "PCM"; |
17197 | } else | 17279 | } else |
17198 | pfx = chname[i]; | 17280 | pfx = chname[i]; |
17199 | sprintf(name, "%s Playback Volume", pfx); | 17281 | err = alc662_add_vol_ctl(spec, pfx, nid, 3); |
17200 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
17201 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
17202 | HDA_OUTPUT)); | ||
17203 | if (err < 0) | 17282 | if (err < 0) |
17204 | return err; | 17283 | return err; |
17205 | if (cfg->line_outs == 1 && | 17284 | if (cfg->line_outs == 1 && |
17206 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 17285 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) |
17207 | pfx = "Speaker"; | 17286 | pfx = "Speaker"; |
17208 | sprintf(name, "%s Playback Switch", pfx); | 17287 | err = alc662_add_sw_ctl(spec, pfx, mix, 3); |
17209 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
17210 | HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i), | ||
17211 | 3, 0, HDA_INPUT)); | ||
17212 | if (err < 0) | 17288 | if (err < 0) |
17213 | return err; | 17289 | return err; |
17214 | } | 17290 | } |
@@ -17217,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
17217 | } | 17293 | } |
17218 | 17294 | ||
17219 | /* add playback controls for speaker and HP outputs */ | 17295 | /* add playback controls for speaker and HP outputs */ |
17220 | static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | 17296 | /* return DAC nid if any new DAC is assigned */ |
17297 | static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | ||
17221 | const char *pfx) | 17298 | const char *pfx) |
17222 | { | 17299 | { |
17223 | hda_nid_t nid; | 17300 | struct alc_spec *spec = codec->spec; |
17301 | hda_nid_t nid, mix; | ||
17224 | int err; | 17302 | int err; |
17225 | char name[32]; | ||
17226 | 17303 | ||
17227 | if (!pin) | 17304 | if (!pin) |
17228 | return 0; | 17305 | return 0; |
17229 | 17306 | nid = alc662_look_for_dac(codec, pin); | |
17230 | if (pin == 0x17) { | 17307 | if (!nid) { |
17231 | /* ALC663 has a mono output pin on 0x17 */ | 17308 | char name[32]; |
17309 | /* the corresponding DAC is already occupied */ | ||
17310 | if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) | ||
17311 | return 0; /* no way */ | ||
17312 | /* create a switch only */ | ||
17232 | sprintf(name, "%s Playback Switch", pfx); | 17313 | sprintf(name, "%s Playback Switch", pfx); |
17233 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | 17314 | return add_control(spec, ALC_CTL_WIDGET_MUTE, name, |
17234 | HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT)); | 17315 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); |
17235 | return err; | ||
17236 | } | 17316 | } |
17237 | 17317 | ||
17238 | if (alc880_is_fixed_pin(pin)) { | 17318 | mix = alc662_dac_to_mix(codec, pin, nid); |
17239 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 17319 | if (!mix) |
17240 | /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ | 17320 | return 0; |
17241 | /* specify the DAC as the extra output */ | 17321 | err = alc662_add_vol_ctl(spec, pfx, nid, 3); |
17242 | if (!spec->multiout.hp_nid) | 17322 | if (err < 0) |
17243 | spec->multiout.hp_nid = nid; | 17323 | return err; |
17244 | else | 17324 | err = alc662_add_sw_ctl(spec, pfx, mix, 3); |
17245 | spec->multiout.extra_out_nid[0] = nid; | 17325 | if (err < 0) |
17246 | /* control HP volume/switch on the output mixer amp */ | 17326 | return err; |
17247 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 17327 | return nid; |
17248 | sprintf(name, "%s Playback Volume", pfx); | ||
17249 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
17250 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | ||
17251 | if (err < 0) | ||
17252 | return err; | ||
17253 | sprintf(name, "%s Playback Switch", pfx); | ||
17254 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, | ||
17255 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); | ||
17256 | if (err < 0) | ||
17257 | return err; | ||
17258 | } else if (alc880_is_multi_pin(pin)) { | ||
17259 | /* set manual connection */ | ||
17260 | /* we have only a switch on HP-out PIN */ | ||
17261 | sprintf(name, "%s Playback Switch", pfx); | ||
17262 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
17263 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); | ||
17264 | if (err < 0) | ||
17265 | return err; | ||
17266 | } | ||
17267 | return 0; | ||
17268 | } | 17328 | } |
17269 | 17329 | ||
17270 | /* create playback/capture controls for input pins */ | 17330 | /* create playback/capture controls for input pins */ |
@@ -17273,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
17273 | 17333 | ||
17274 | static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, | 17334 | static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, |
17275 | hda_nid_t nid, int pin_type, | 17335 | hda_nid_t nid, int pin_type, |
17276 | int dac_idx) | 17336 | hda_nid_t dac) |
17277 | { | 17337 | { |
17338 | int i, num; | ||
17339 | hda_nid_t srcs[4]; | ||
17340 | |||
17278 | alc_set_pin_output(codec, nid, pin_type); | 17341 | alc_set_pin_output(codec, nid, pin_type); |
17279 | /* need the manual connection? */ | 17342 | /* need the manual connection? */ |
17280 | if (alc880_is_multi_pin(nid)) { | 17343 | num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs)); |
17281 | struct alc_spec *spec = codec->spec; | 17344 | if (num <= 1) |
17282 | int idx = alc880_multi_pin_idx(nid); | 17345 | return; |
17283 | snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, | 17346 | for (i = 0; i < num; i++) { |
17284 | AC_VERB_SET_CONNECT_SEL, | 17347 | if (alc662_mix_to_dac(srcs[i]) != dac) |
17285 | alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); | 17348 | continue; |
17349 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i); | ||
17350 | return; | ||
17286 | } | 17351 | } |
17287 | } | 17352 | } |
17288 | 17353 | ||
17289 | static void alc662_auto_init_multi_out(struct hda_codec *codec) | 17354 | static void alc662_auto_init_multi_out(struct hda_codec *codec) |
17290 | { | 17355 | { |
17291 | struct alc_spec *spec = codec->spec; | 17356 | struct alc_spec *spec = codec->spec; |
17357 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
17292 | int i; | 17358 | int i; |
17293 | 17359 | ||
17294 | for (i = 0; i <= HDA_SIDE; i++) { | 17360 | for (i = 0; i <= HDA_SIDE; i++) { |
17295 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 17361 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; |
17296 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
17297 | if (nid) | 17362 | if (nid) |
17298 | alc662_auto_set_output_and_unmute(codec, nid, pin_type, | 17363 | alc662_auto_set_output_and_unmute(codec, nid, pin_type, |
17299 | i); | 17364 | spec->multiout.dac_nids[i]); |
17300 | } | 17365 | } |
17301 | } | 17366 | } |
17302 | 17367 | ||
@@ -17306,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) | |||
17306 | hda_nid_t pin; | 17371 | hda_nid_t pin; |
17307 | 17372 | ||
17308 | pin = spec->autocfg.hp_pins[0]; | 17373 | pin = spec->autocfg.hp_pins[0]; |
17309 | if (pin) /* connect to front */ | 17374 | if (pin) |
17310 | /* use dac 0 */ | 17375 | alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, |
17311 | alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 17376 | spec->multiout.hp_nid); |
17312 | pin = spec->autocfg.speaker_pins[0]; | 17377 | pin = spec->autocfg.speaker_pins[0]; |
17313 | if (pin) | 17378 | if (pin) |
17314 | alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 17379 | alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, |
17380 | spec->multiout.extra_out_nid[0]); | ||
17315 | } | 17381 | } |
17316 | 17382 | ||
17317 | #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID | 17383 | #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID |
@@ -17349,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
17349 | if (!spec->autocfg.line_outs) | 17415 | if (!spec->autocfg.line_outs) |
17350 | return 0; /* can't find valid BIOS pin config */ | 17416 | return 0; /* can't find valid BIOS pin config */ |
17351 | 17417 | ||
17352 | err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); | 17418 | err = alc662_auto_fill_dac_nids(codec, &spec->autocfg); |
17353 | if (err < 0) | 17419 | if (err < 0) |
17354 | return err; | 17420 | return err; |
17355 | err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); | 17421 | err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg); |
17356 | if (err < 0) | 17422 | if (err < 0) |
17357 | return err; | 17423 | return err; |
17358 | err = alc662_auto_create_extra_out(spec, | 17424 | err = alc662_auto_create_extra_out(codec, |
17359 | spec->autocfg.speaker_pins[0], | 17425 | spec->autocfg.speaker_pins[0], |
17360 | "Speaker"); | 17426 | "Speaker"); |
17361 | if (err < 0) | 17427 | if (err < 0) |
17362 | return err; | 17428 | return err; |
17363 | err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | 17429 | if (err) |
17430 | spec->multiout.extra_out_nid[0] = err; | ||
17431 | err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], | ||
17364 | "Headphone"); | 17432 | "Headphone"); |
17365 | if (err < 0) | 17433 | if (err < 0) |
17366 | return err; | 17434 | return err; |
17435 | if (err) | ||
17436 | spec->multiout.hp_nid = err; | ||
17367 | err = alc662_auto_create_input_ctls(codec, &spec->autocfg); | 17437 | err = alc662_auto_create_input_ctls(codec, &spec->autocfg); |
17368 | if (err < 0) | 17438 | if (err < 0) |
17369 | return err; | 17439 | return err; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 826137ec3002..a9b26828a651 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -182,8 +182,8 @@ struct sigmatel_jack { | |||
182 | 182 | ||
183 | struct sigmatel_mic_route { | 183 | struct sigmatel_mic_route { |
184 | hda_nid_t pin; | 184 | hda_nid_t pin; |
185 | unsigned char mux_idx; | 185 | signed char mux_idx; |
186 | unsigned char dmux_idx; | 186 | signed char dmux_idx; |
187 | }; | 187 | }; |
188 | 188 | ||
189 | struct sigmatel_spec { | 189 | struct sigmatel_spec { |
@@ -3469,18 +3469,26 @@ static int set_mic_route(struct hda_codec *codec, | |||
3469 | break; | 3469 | break; |
3470 | if (i <= AUTO_PIN_FRONT_MIC) { | 3470 | if (i <= AUTO_PIN_FRONT_MIC) { |
3471 | /* analog pin */ | 3471 | /* analog pin */ |
3472 | mic->dmux_idx = 0; | ||
3473 | i = get_connection_index(codec, spec->mux_nids[0], pin); | 3472 | i = get_connection_index(codec, spec->mux_nids[0], pin); |
3474 | if (i < 0) | 3473 | if (i < 0) |
3475 | return -1; | 3474 | return -1; |
3476 | mic->mux_idx = i; | 3475 | mic->mux_idx = i; |
3476 | mic->dmux_idx = -1; | ||
3477 | if (spec->dmux_nids) | ||
3478 | mic->dmux_idx = get_connection_index(codec, | ||
3479 | spec->dmux_nids[0], | ||
3480 | spec->mux_nids[0]); | ||
3477 | } else if (spec->dmux_nids) { | 3481 | } else if (spec->dmux_nids) { |
3478 | /* digital pin */ | 3482 | /* digital pin */ |
3479 | mic->mux_idx = 0; | ||
3480 | i = get_connection_index(codec, spec->dmux_nids[0], pin); | 3483 | i = get_connection_index(codec, spec->dmux_nids[0], pin); |
3481 | if (i < 0) | 3484 | if (i < 0) |
3482 | return -1; | 3485 | return -1; |
3483 | mic->dmux_idx = i; | 3486 | mic->dmux_idx = i; |
3487 | mic->mux_idx = -1; | ||
3488 | if (spec->mux_nids) | ||
3489 | mic->mux_idx = get_connection_index(codec, | ||
3490 | spec->mux_nids[0], | ||
3491 | spec->dmux_nids[0]); | ||
3484 | } | 3492 | } |
3485 | return 0; | 3493 | return 0; |
3486 | } | 3494 | } |
@@ -4557,11 +4565,11 @@ static void stac92xx_mic_detect(struct hda_codec *codec) | |||
4557 | mic = &spec->ext_mic; | 4565 | mic = &spec->ext_mic; |
4558 | else | 4566 | else |
4559 | mic = &spec->int_mic; | 4567 | mic = &spec->int_mic; |
4560 | if (mic->dmux_idx) | 4568 | if (mic->dmux_idx >= 0) |
4561 | snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, | 4569 | snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, |
4562 | AC_VERB_SET_CONNECT_SEL, | 4570 | AC_VERB_SET_CONNECT_SEL, |
4563 | mic->dmux_idx); | 4571 | mic->dmux_idx); |
4564 | else | 4572 | if (mic->mux_idx >= 0) |
4565 | snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, | 4573 | snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, |
4566 | AC_VERB_SET_CONNECT_SEL, | 4574 | AC_VERB_SET_CONNECT_SEL, |
4567 | mic->mux_idx); | 4575 | mic->mux_idx); |