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 | |
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>
-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 |