diff options
| author | Takashi Iwai <tiwai@suse.de> | 2011-07-08 09:16:55 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2011-07-08 09:16:55 -0400 |
| commit | 72dcd8e76bd2b5d9846c3103ec020e1b550cdaac (patch) | |
| tree | f376ace699ad0d90ec6d01f3a3b6c68fa1d02c82 /sound | |
| parent | 44c0240052892911d9ebcb2bbc2a5cfc3176077c (diff) | |
ALSA: hda - Merge ALC861 auto-parser code
Merge more auto-parser code in patch_realtek.c, now for ALC861.
The topology of this codec is pretty simple, and can be parsed well
by the current starndard parser.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 195 |
1 files changed, 8 insertions, 187 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index db9df5759103..b9e0c73cbd76 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -5364,176 +5364,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 5364 | * ALC861 | 5364 | * ALC861 |
| 5365 | */ | 5365 | */ |
| 5366 | 5366 | ||
| 5367 | static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | ||
| 5368 | { | ||
| 5369 | struct alc_spec *spec = codec->spec; | ||
| 5370 | hda_nid_t mix, srcs[5]; | ||
| 5371 | int i, num; | ||
| 5372 | |||
| 5373 | if (snd_hda_get_connections(codec, pin, &mix, 1) != 1) | ||
| 5374 | return 0; | ||
| 5375 | num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs)); | ||
| 5376 | if (num < 0) | ||
| 5377 | return 0; | ||
| 5378 | for (i = 0; i < num; i++) { | ||
| 5379 | unsigned int type; | ||
| 5380 | type = get_wcaps_type(get_wcaps(codec, srcs[i])); | ||
| 5381 | if (type != AC_WID_AUD_OUT) | ||
| 5382 | continue; | ||
| 5383 | if (!found_in_nid_list(srcs[i], spec->multiout.dac_nids, | ||
| 5384 | spec->multiout.num_dacs)) | ||
| 5385 | return srcs[i]; | ||
| 5386 | } | ||
| 5387 | return 0; | ||
| 5388 | } | ||
| 5389 | |||
| 5390 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
| 5391 | static int alc861_auto_fill_dac_nids(struct hda_codec *codec) | ||
| 5392 | { | ||
| 5393 | struct alc_spec *spec = codec->spec; | ||
| 5394 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 5395 | int i; | ||
| 5396 | hda_nid_t nid, dac; | ||
| 5397 | |||
| 5398 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
| 5399 | for (i = 0; i < cfg->line_outs; i++) { | ||
| 5400 | nid = cfg->line_out_pins[i]; | ||
| 5401 | dac = alc861_look_for_dac(codec, nid); | ||
| 5402 | if (!dac) | ||
| 5403 | continue; | ||
| 5404 | spec->private_dac_nids[spec->multiout.num_dacs++] = dac; | ||
| 5405 | } | ||
| 5406 | return 0; | ||
| 5407 | } | ||
| 5408 | |||
| 5409 | static int __alc861_create_out_sw(struct hda_codec *codec, const char *pfx, | ||
| 5410 | hda_nid_t nid, int idx, unsigned int chs) | ||
| 5411 | { | ||
| 5412 | return __add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, idx, | ||
| 5413 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
| 5414 | } | ||
| 5415 | |||
| 5416 | #define alc861_create_out_sw(codec, pfx, nid, chs) \ | ||
| 5417 | __alc861_create_out_sw(codec, pfx, nid, 0, chs) | ||
| 5418 | |||
| 5419 | /* add playback controls from the parsed DAC table */ | ||
| 5420 | static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
| 5421 | const struct auto_pin_cfg *cfg) | ||
| 5422 | { | ||
| 5423 | struct alc_spec *spec = codec->spec; | ||
| 5424 | hda_nid_t nid; | ||
| 5425 | int i, err, noutputs; | ||
| 5426 | |||
| 5427 | noutputs = cfg->line_outs; | ||
| 5428 | if (spec->multi_ios > 0) | ||
| 5429 | noutputs += spec->multi_ios; | ||
| 5430 | |||
| 5431 | for (i = 0; i < noutputs; i++) { | ||
| 5432 | const char *name; | ||
| 5433 | int index; | ||
| 5434 | nid = spec->multiout.dac_nids[i]; | ||
| 5435 | if (!nid) | ||
| 5436 | continue; | ||
| 5437 | name = alc_get_line_out_pfx(spec, i, true, &index); | ||
| 5438 | if (!name) { | ||
| 5439 | /* Center/LFE */ | ||
| 5440 | err = alc861_create_out_sw(codec, "Center", nid, 1); | ||
| 5441 | if (err < 0) | ||
| 5442 | return err; | ||
| 5443 | err = alc861_create_out_sw(codec, "LFE", nid, 2); | ||
| 5444 | if (err < 0) | ||
| 5445 | return err; | ||
| 5446 | } else { | ||
| 5447 | err = __alc861_create_out_sw(codec, name, nid, index, 3); | ||
| 5448 | if (err < 0) | ||
| 5449 | return err; | ||
| 5450 | } | ||
| 5451 | } | ||
| 5452 | return 0; | ||
| 5453 | } | ||
| 5454 | |||
| 5455 | static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin) | ||
| 5456 | { | ||
| 5457 | struct alc_spec *spec = codec->spec; | ||
| 5458 | int err; | ||
| 5459 | hda_nid_t nid; | ||
| 5460 | |||
| 5461 | if (!pin) | ||
| 5462 | return 0; | ||
| 5463 | |||
| 5464 | if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { | ||
| 5465 | nid = alc861_look_for_dac(codec, pin); | ||
| 5466 | if (nid) { | ||
| 5467 | err = alc861_create_out_sw(codec, "Headphone", nid, 3); | ||
| 5468 | if (err < 0) | ||
| 5469 | return err; | ||
| 5470 | spec->multiout.hp_nid = nid; | ||
| 5471 | } | ||
| 5472 | } | ||
| 5473 | return 0; | ||
| 5474 | } | ||
| 5475 | |||
| 5476 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, | ||
| 5477 | hda_nid_t nid, | ||
| 5478 | int pin_type, hda_nid_t dac) | ||
| 5479 | { | ||
| 5480 | hda_nid_t mix, srcs[5]; | ||
| 5481 | int i, num; | ||
| 5482 | |||
| 5483 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 5484 | pin_type); | ||
| 5485 | snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
| 5486 | AMP_OUT_UNMUTE); | ||
| 5487 | if (snd_hda_get_connections(codec, nid, &mix, 1) != 1) | ||
| 5488 | return; | ||
| 5489 | num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs)); | ||
| 5490 | if (num < 0) | ||
| 5491 | return; | ||
| 5492 | for (i = 0; i < num; i++) { | ||
| 5493 | unsigned int mute; | ||
| 5494 | if (srcs[i] == dac || srcs[i] == 0x15) | ||
| 5495 | mute = AMP_IN_UNMUTE(i); | ||
| 5496 | else | ||
| 5497 | mute = AMP_IN_MUTE(i); | ||
| 5498 | snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
| 5499 | mute); | ||
| 5500 | } | ||
| 5501 | } | ||
| 5502 | |||
| 5503 | static void alc861_auto_init_multi_out(struct hda_codec *codec) | ||
| 5504 | { | ||
| 5505 | struct alc_spec *spec = codec->spec; | ||
| 5506 | int i; | ||
| 5507 | |||
| 5508 | for (i = 0; i < spec->autocfg.line_outs + spec->multi_ios; i++) { | ||
| 5509 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
| 5510 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
| 5511 | if (nid) | ||
| 5512 | alc861_auto_set_output_and_unmute(codec, nid, pin_type, | ||
| 5513 | spec->multiout.dac_nids[i]); | ||
| 5514 | } | ||
| 5515 | } | ||
| 5516 | |||
| 5517 | static void alc861_auto_init_hp_out(struct hda_codec *codec) | ||
| 5518 | { | ||
| 5519 | struct alc_spec *spec = codec->spec; | ||
| 5520 | |||
| 5521 | if (spec->autocfg.hp_outs) | ||
| 5522 | alc861_auto_set_output_and_unmute(codec, | ||
| 5523 | spec->autocfg.hp_pins[0], | ||
| 5524 | PIN_HP, | ||
| 5525 | spec->multiout.hp_nid); | ||
| 5526 | if (spec->autocfg.speaker_outs) | ||
| 5527 | alc861_auto_set_output_and_unmute(codec, | ||
| 5528 | spec->autocfg.speaker_pins[0], | ||
| 5529 | PIN_OUT, | ||
| 5530 | spec->multiout.dac_nids[0]); | ||
| 5531 | } | ||
| 5532 | |||
| 5533 | /* parse the BIOS configuration and set up the alc_spec */ | ||
| 5534 | /* return 1 if successful, 0 if the proper config is not found, | ||
| 5535 | * or a negative error code | ||
| 5536 | */ | ||
| 5537 | static int alc861_parse_auto_config(struct hda_codec *codec) | 5367 | static int alc861_parse_auto_config(struct hda_codec *codec) |
| 5538 | { | 5368 | { |
| 5539 | struct alc_spec *spec = codec->spec; | 5369 | struct alc_spec *spec = codec->spec; |
| @@ -5547,16 +5377,19 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
| 5547 | if (!spec->autocfg.line_outs) | 5377 | if (!spec->autocfg.line_outs) |
| 5548 | return 0; /* can't find valid BIOS pin config */ | 5378 | return 0; /* can't find valid BIOS pin config */ |
| 5549 | 5379 | ||
| 5550 | err = alc861_auto_fill_dac_nids(codec); | 5380 | err = alc_auto_fill_dac_nids(codec); |
| 5551 | if (err < 0) | 5381 | if (err < 0) |
| 5552 | return err; | 5382 | return err; |
| 5553 | err = alc_auto_add_multi_channel_mode(codec, alc861_auto_fill_dac_nids); | 5383 | err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids); |
| 5384 | if (err < 0) | ||
| 5385 | return err; | ||
| 5386 | err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg); | ||
| 5554 | if (err < 0) | 5387 | if (err < 0) |
| 5555 | return err; | 5388 | return err; |
| 5556 | err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg); | 5389 | err = alc_auto_create_hp_out(codec); |
| 5557 | if (err < 0) | 5390 | if (err < 0) |
| 5558 | return err; | 5391 | return err; |
| 5559 | err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]); | 5392 | err = alc_auto_create_speaker_out(codec); |
| 5560 | if (err < 0) | 5393 | if (err < 0) |
| 5561 | return err; | 5394 | return err; |
| 5562 | err = alc_auto_create_input_ctls(codec); | 5395 | err = alc_auto_create_input_ctls(codec); |
| @@ -5580,18 +5413,6 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
| 5580 | return 1; | 5413 | return 1; |
| 5581 | } | 5414 | } |
| 5582 | 5415 | ||
| 5583 | /* additional initialization for auto-configuration model */ | ||
| 5584 | static void alc861_auto_init(struct hda_codec *codec) | ||
| 5585 | { | ||
| 5586 | struct alc_spec *spec = codec->spec; | ||
| 5587 | alc861_auto_init_multi_out(codec); | ||
| 5588 | alc861_auto_init_hp_out(codec); | ||
| 5589 | alc_auto_init_analog_input(codec); | ||
| 5590 | alc_auto_init_digital(codec); | ||
| 5591 | if (spec->unsol_event) | ||
| 5592 | alc_inithook(codec); | ||
| 5593 | } | ||
| 5594 | |||
| 5595 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5416 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 5596 | static const struct hda_amp_list alc861_loopbacks[] = { | 5417 | static const struct hda_amp_list alc861_loopbacks[] = { |
| 5597 | { 0x15, HDA_INPUT, 0 }, | 5418 | { 0x15, HDA_INPUT, 0 }, |
| @@ -5700,7 +5521,7 @@ static int patch_alc861(struct hda_codec *codec) | |||
| 5700 | 5521 | ||
| 5701 | codec->patch_ops = alc_patch_ops; | 5522 | codec->patch_ops = alc_patch_ops; |
| 5702 | if (board_config == ALC_MODEL_AUTO) { | 5523 | if (board_config == ALC_MODEL_AUTO) { |
| 5703 | spec->init_hook = alc861_auto_init; | 5524 | spec->init_hook = alc_auto_init_std; |
| 5704 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5525 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 5705 | spec->power_hook = alc_power_eapd; | 5526 | spec->power_hook = alc_power_eapd; |
| 5706 | #endif | 5527 | #endif |
