diff options
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 241 |
1 files changed, 155 insertions, 86 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 87da5e805c8e..7810d3dcad83 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -17146,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = { | |||
| 17146 | * BIOS auto configuration | 17146 | * BIOS auto configuration |
| 17147 | */ | 17147 | */ |
| 17148 | 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 | |||
| 17149 | /* add playback controls from the parsed DAC table */ | 17239 | /* add playback controls from the parsed DAC table */ |
| 17150 | 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, |
| 17151 | const struct auto_pin_cfg *cfg) | 17241 | const struct auto_pin_cfg *cfg) |
| 17152 | { | 17242 | { |
| 17153 | char name[32]; | 17243 | struct alc_spec *spec = codec->spec; |
| 17154 | static const char *chname[4] = { | 17244 | static const char *chname[4] = { |
| 17155 | "Front", "Surround", NULL /*CLFE*/, "Side" | 17245 | "Front", "Surround", NULL /*CLFE*/, "Side" |
| 17156 | }; | 17246 | }; |
| 17157 | hda_nid_t nid; | 17247 | hda_nid_t nid, mix; |
| 17158 | int i, err; | 17248 | int i, err; |
| 17159 | 17249 | ||
| 17160 | for (i = 0; i < cfg->line_outs; i++) { | 17250 | for (i = 0; i < cfg->line_outs; i++) { |
| 17161 | 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) | ||
| 17162 | continue; | 17256 | continue; |
| 17163 | nid = alc880_idx_to_dac(i); | ||
| 17164 | if (i == 2) { | 17257 | if (i == 2) { |
| 17165 | /* Center/LFE */ | 17258 | /* Center/LFE */ |
| 17166 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 17259 | err = alc662_add_vol_ctl(spec, "Center", nid, 1); |
| 17167 | "Center Playback Volume", | ||
| 17168 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, | ||
| 17169 | HDA_OUTPUT)); | ||
| 17170 | if (err < 0) | 17260 | if (err < 0) |
| 17171 | return err; | 17261 | return err; |
| 17172 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 17262 | err = alc662_add_vol_ctl(spec, "LFE", nid, 2); |
| 17173 | "LFE Playback Volume", | ||
| 17174 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
| 17175 | HDA_OUTPUT)); | ||
| 17176 | if (err < 0) | 17263 | if (err < 0) |
| 17177 | return err; | 17264 | return err; |
| 17178 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, | 17265 | err = alc662_add_sw_ctl(spec, "Center", mix, 1); |
| 17179 | "Center Playback Switch", | ||
| 17180 | HDA_COMPOSE_AMP_VAL(0x0e, 1, 0, | ||
| 17181 | HDA_INPUT)); | ||
| 17182 | if (err < 0) | 17266 | if (err < 0) |
| 17183 | return err; | 17267 | return err; |
| 17184 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, | 17268 | err = alc662_add_sw_ctl(spec, "LFE", mix, 2); |
| 17185 | "LFE Playback Switch", | ||
| 17186 | HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, | ||
| 17187 | HDA_INPUT)); | ||
| 17188 | if (err < 0) | 17269 | if (err < 0) |
| 17189 | return err; | 17270 | return err; |
| 17190 | } else { | 17271 | } else { |
| 17191 | const char *pfx; | 17272 | const char *pfx; |
| 17192 | if (cfg->line_outs == 1 && | 17273 | if (cfg->line_outs == 1 && |
| 17193 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | 17274 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { |
| 17194 | if (!cfg->hp_pins) | 17275 | if (cfg->hp_outs) |
| 17195 | pfx = "Speaker"; | 17276 | pfx = "Speaker"; |
| 17196 | else | 17277 | else |
| 17197 | pfx = "PCM"; | 17278 | pfx = "PCM"; |
| 17198 | } else | 17279 | } else |
| 17199 | pfx = chname[i]; | 17280 | pfx = chname[i]; |
| 17200 | sprintf(name, "%s Playback Volume", pfx); | 17281 | err = alc662_add_vol_ctl(spec, pfx, nid, 3); |
| 17201 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
| 17202 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
| 17203 | HDA_OUTPUT)); | ||
| 17204 | if (err < 0) | 17282 | if (err < 0) |
| 17205 | return err; | 17283 | return err; |
| 17206 | if (cfg->line_outs == 1 && | 17284 | if (cfg->line_outs == 1 && |
| 17207 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 17285 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) |
| 17208 | pfx = "Speaker"; | 17286 | pfx = "Speaker"; |
| 17209 | sprintf(name, "%s Playback Switch", pfx); | 17287 | err = alc662_add_sw_ctl(spec, pfx, mix, 3); |
| 17210 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
| 17211 | HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i), | ||
