aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c241
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 */
17150static 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 */
17161static 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 */
17176static 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 */
17199static 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
17216static 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
17225static 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 */
17150static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, 17240static 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),
17212 3, 0, HDA_INPUT));
17213 if (err < 0) 17288 if (err < 0)
17214 return err; 17289 return err;
17215 } 17290 }
@@ -17218,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
17218} 17293}
17219 17294
17220/* add playback controls for speaker and HP outputs */ 17295/* add playback controls for speaker and HP outputs */
17221static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 17296/* return DAC nid if any new DAC is assigned */
17297static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
17222 const char *pfx) 17298 const char *pfx)
17223{ 17299{
17224 hda_nid_t nid; 17300 struct alc_spec *spec = codec->spec;
17301 hda_nid_t nid, mix;
17225 int err; 17302 int err;
17226 char name[32];
17227 17303
17228 if (!pin) 17304 if (!pin)
17229 return 0; 17305 return 0;
17230 17306 nid = alc662_look_for_dac(codec, pin);
17231 if (pin == 0x17) { 17307 if (!nid) {
17232 /* 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 */
17233 sprintf(name, "%s Playback Switch", pfx); 17313 sprintf(name, "%s Playback Switch", pfx);
17234 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 17314 return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17235 HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT)); 17315 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
17236 return err;
17237 } 17316 }
17238 17317
17239 if (alc880_is_fixed_pin(pin)) { 17318 mix = alc662_dac_to_mix(codec, pin, nid);
17240 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 17319 if (!mix)
17241 /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ 17320 return 0;
17242 /* specify the DAC as the extra output */ 17321 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
17243 if (!spec->multiout.hp_nid) 17322 if (err < 0)
17244 spec->multiout.hp_nid = nid; 17323 return err;
17245 else 17324 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
17246 spec->multiout.extra_out_nid[0] = nid; 17325 if (err < 0)
17247 /* control HP volume/switch on the output mixer amp */ 17326 return err;
17248 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 17327 return nid;
17249 sprintf(name, "%s Playback Volume", pfx);
17250 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
17251 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
17252 if (err < 0)
17253 return err;
17254 sprintf(name, "%s Playback Switch", pfx);
17255 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
17256 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
17257 if (err < 0)
17258 return err;
17259 } else if (alc880_is_multi_pin(pin)) {
17260 /* set manual connection */
17261 /* we have only a switch on HP-out PIN */
17262 sprintf(name, "%s Playback Switch", pfx);
17263 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17264 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
17265 if (err < 0)
17266 return err;
17267 }
17268 return 0;
17269} 17328}
17270 17329
17271/* create playback/capture controls for input pins */ 17330/* create playback/capture controls for input pins */
@@ -17274,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
17274 17333
17275static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, 17334static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
17276 hda_nid_t nid, int pin_type, 17335 hda_nid_t nid, int pin_type,
17277 int dac_idx) 17336 hda_nid_t dac)
17278{ 17337{
17338 int i, num;
17339 hda_nid_t srcs[4];
17340
17279 alc_set_pin_output(codec, nid, pin_type); 17341 alc_set_pin_output(codec, nid, pin_type);
17280 /* need the manual connection? */ 17342 /* need the manual connection? */
17281 if (alc880_is_multi_pin(nid)) { 17343 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
17282 struct alc_spec *spec = codec->spec; 17344 if (num <= 1)
17283 int idx = alc880_multi_pin_idx(nid); 17345 return;
17284 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 17346 for (i = 0; i < num; i++) {
17285 AC_VERB_SET_CONNECT_SEL, 17347 if (alc662_mix_to_dac(srcs[i]) != dac)
17286 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;
17287 } 17351 }
17288} 17352}
17289 17353
17290static void alc662_auto_init_multi_out(struct hda_codec *codec) 17354static void alc662_auto_init_multi_out(struct hda_codec *codec)
17291{ 17355{
17292 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);
17293 int i; 17358 int i;
17294 17359
17295 for (i = 0; i <= HDA_SIDE; i++) { 17360 for (i = 0; i <= HDA_SIDE; i++) {
17296 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 17361 hda_nid_t nid = spec->autocfg.line_out_pins[i];
17297 int pin_type = get_pin_type(spec->autocfg.line_out_type);
17298 if (nid) 17362 if (nid)
17299 alc662_auto_set_output_and_unmute(codec, nid, pin_type, 17363 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
17300 i); 17364 spec->multiout.dac_nids[i]);
17301 } 17365 }
17302} 17366}
17303 17367
@@ -17307,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
17307 hda_nid_t pin; 17371 hda_nid_t pin;
17308 17372
17309 pin = spec->autocfg.hp_pins[0]; 17373 pin = spec->autocfg.hp_pins[0];
17310 if (pin) /* connect to front */ 17374 if (pin)
17311 /* use dac 0 */ 17375 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
17312 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 17376 spec->multiout.hp_nid);
17313 pin = spec->autocfg.speaker_pins[0]; 17377 pin = spec->autocfg.speaker_pins[0];
17314 if (pin) 17378 if (pin)
17315 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]);
17316} 17381}
17317 17382
17318#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID 17383#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
@@ -17350,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
17350 if (!spec->autocfg.line_outs) 17415 if (!spec->autocfg.line_outs)
17351 return 0; /* can't find valid BIOS pin config */ 17416 return 0; /* can't find valid BIOS pin config */
17352 17417
17353 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 17418 err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
17354 if (err < 0) 17419 if (err < 0)
17355 return err; 17420 return err;
17356 err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); 17421 err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
17357 if (err < 0) 17422 if (err < 0)
17358 return err; 17423 return err;
17359 err = alc662_auto_create_extra_out(spec, 17424 err = alc662_auto_create_extra_out(codec,
17360 spec->autocfg.speaker_pins[0], 17425 spec->autocfg.speaker_pins[0],
17361 "Speaker"); 17426 "Speaker");
17362 if (err < 0) 17427 if (err < 0)
17363 return err; 17428 return err;
17364 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],
17365 "Headphone"); 17432 "Headphone");
17366 if (err < 0) 17433 if (err < 0)
17367 return err; 17434 return err;
17435 if (err)
17436 spec->multiout.hp_nid = err;
17368 err = alc662_auto_create_input_ctls(codec, &spec->autocfg); 17437 err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
17369 if (err < 0) 17438 if (err < 0)
17370 return err; 17439 return err;