diff options
| author | Takashi Iwai <tiwai@suse.de> | 2010-07-30 04:48:14 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2010-07-30 04:48:14 -0400 |
| commit | 757899aceebc33d9f86bbc481be7b7bf861e89ac (patch) | |
| tree | ba07222b92186c8092a228fd0c2ce1630f917765 | |
| parent | ce503f38bdb59c9175a9076215a3ba579fad4e64 (diff) | |
ALSA: hda - Share digital I/O parser in patch_realtek.c
Make a helper function to parse the digital I/Os of all Realtek codecs
to simplify the code and to ensure the setups.
Also, initialize digital I/O pins properly in init callbacks. Some BIOS
seem to leave pins uninitialized.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 140 |
1 files changed, 78 insertions, 62 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cf9f20805173..442adef38c5b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -1541,6 +1541,63 @@ static int alc_read_coef_idx(struct hda_codec *codec, | |||
| 1541 | return val; | 1541 | return val; |
| 1542 | } | 1542 | } |
| 1543 | 1543 | ||
| 1544 | /* set right pin controls for digital I/O */ | ||
| 1545 | static void alc_auto_init_digital(struct hda_codec *codec) | ||
| 1546 | { | ||
| 1547 | struct alc_spec *spec = codec->spec; | ||
| 1548 | int i; | ||
| 1549 | hda_nid_t pin; | ||
| 1550 | |||
| 1551 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
| 1552 | pin = spec->autocfg.dig_out_pins[i]; | ||
| 1553 | if (pin) { | ||
| 1554 | snd_hda_codec_write(codec, pin, 0, | ||
| 1555 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 1556 | PIN_OUT); | ||
| 1557 | } | ||
| 1558 | } | ||
| 1559 | pin = spec->autocfg.dig_in_pin; | ||
| 1560 | if (pin) | ||
| 1561 | snd_hda_codec_write(codec, pin, 0, | ||
| 1562 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 1563 | PIN_IN); | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | /* parse digital I/Os and set up NIDs in BIOS auto-parse mode */ | ||
| 1567 | static void alc_auto_parse_digital(struct hda_codec *codec) | ||
| 1568 | { | ||
| 1569 | struct alc_spec *spec = codec->spec; | ||
| 1570 | int i, err; | ||
| 1571 | hda_nid_t dig_nid; | ||
| 1572 | |||
| 1573 | /* support multiple SPDIFs; the secondary is set up as a slave */ | ||
| 1574 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
| 1575 | err = snd_hda_get_connections(codec, | ||
| 1576 | spec->autocfg.dig_out_pins[i], | ||
| 1577 | &dig_nid, 1); | ||
| 1578 | if (err < 0) | ||
| 1579 | continue; | ||
| 1580 | if (!i) { | ||
| 1581 | spec->multiout.dig_out_nid = dig_nid; | ||
| 1582 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
| 1583 | } else { | ||
| 1584 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
| 1585 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
| 1586 | break; | ||
| 1587 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
| 1588 | } | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | if (spec->autocfg.dig_in_pin) { | ||
| 1592 | hda_nid_t dig_nid; | ||
| 1593 | err = snd_hda_get_connections(codec, | ||
| 1594 | spec->autocfg.dig_in_pin, | ||
| 1595 | &dig_nid, 1); | ||
| 1596 | if (err > 0) | ||
| 1597 | spec->dig_in_nid = dig_nid; | ||
| 1598 | } | ||
| 1599 | } | ||
| 1600 | |||
| 1544 | /* | 1601 | /* |
| 1545 | * ALC888 | 1602 | * ALC888 |
| 1546 | */ | 1603 | */ |
| @@ -5013,7 +5070,7 @@ static void alc880_auto_init_input_src(struct hda_codec *codec) | |||
| 5013 | static int alc880_parse_auto_config(struct hda_codec *codec) | 5070 | static int alc880_parse_auto_config(struct hda_codec *codec) |
| 5014 | { | 5071 | { |
| 5015 | struct alc_spec *spec = codec->spec; | 5072 | struct alc_spec *spec = codec->spec; |
| 5016 | int i, err; | 5073 | int err; |
| 5017 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; | 5074 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; |
| 5018 | 5075 | ||
| 5019 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 5076 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
| @@ -5044,25 +5101,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
| 5044 | 5101 | ||
| 5045 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 5102 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| 5046 | 5103 | ||
| 5047 | /* check multiple SPDIF-out (for recent codecs) */ | 5104 | alc_auto_parse_digital(codec); |
| 5048 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
| 5049 | hda_nid_t dig_nid; | ||
| 5050 | err = snd_hda_get_connections(codec, | ||
| 5051 | spec->autocfg.dig_out_pins[i], | ||
| 5052 | &dig_nid, 1); | ||
| 5053 | if (err < 0) | ||
| 5054 | continue; | ||
| 5055 | if (!i) | ||
| 5056 | spec->multiout.dig_out_nid = dig_nid; | ||
| 5057 | else { | ||
| 5058 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
| 5059 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
| 5060 | break; | ||
| 5061 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
| 5062 | } | ||
| 5063 | } | ||
| 5064 | if (spec->autocfg.dig_in_pin) | ||
| 5065 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
| 5066 | 5105 | ||
| 5067 | if (spec->kctls.list) | 5106 | if (spec->kctls.list) |
| 5068 | add_mixer(spec, spec->kctls.list); | 5107 | add_mixer(spec, spec->kctls.list); |
| @@ -5085,6 +5124,7 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
| 5085 | alc880_auto_init_extra_out(codec); | 5124 | alc880_auto_init_extra_out(codec); |
| 5086 | alc880_auto_init_analog_input(codec); | 5125 | alc880_auto_init_analog_input(codec); |
| 5087 | alc880_auto_init_input_src(codec); | 5126 | alc880_auto_init_input_src(codec); |
| 5127 | alc_auto_init_digital(codec); | ||
| 5088 | if (spec->unsol_event) | 5128 | if (spec->unsol_event) |
| 5089 | alc_inithook(codec); | 5129 | alc_inithook(codec); |
| 5090 | } | 5130 | } |
| @@ -6724,6 +6764,7 @@ static void alc260_auto_init(struct hda_codec *codec) | |||
| 6724 | alc260_auto_init_multi_out(codec); | 6764 | alc260_auto_init_multi_out(codec); |
| 6725 | alc260_auto_init_analog_input(codec); | 6765 | alc260_auto_init_analog_input(codec); |
| 6726 | alc260_auto_init_input_src(codec); | 6766 | alc260_auto_init_input_src(codec); |
| 6767 | alc_auto_init_digital(codec); | ||
| 6727 | if (spec->unsol_event) | 6768 | if (spec->unsol_event) |
| 6728 | alc_inithook(codec); | 6769 | alc_inithook(codec); |
| 6729 | } | 6770 | } |
| @@ -10546,7 +10587,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
| 10546 | { | 10587 | { |
| 10547 | struct alc_spec *spec = codec->spec; | 10588 | struct alc_spec *spec = codec->spec; |
| 10548 | static hda_nid_t alc882_ignore[] = { 0x1d, 0 }; | 10589 | static hda_nid_t alc882_ignore[] = { 0x1d, 0 }; |
| 10549 | int i, err; | 10590 | int err; |
| 10550 | 10591 | ||
| 10551 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 10592 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
| 10552 | alc882_ignore); | 10593 | alc882_ignore); |
| @@ -10576,25 +10617,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
| 10576 | 10617 | ||
| 10577 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 10618 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| 10578 | 10619 | ||
| 10579 | /* check multiple SPDIF-out (for recent codecs) */ | 10620 | alc_auto_parse_digital(codec); |
| 10580 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
| 10581 | hda_nid_t dig_nid; | ||
| 10582 | err = snd_hda_get_connections(codec, | ||
| 10583 | spec->autocfg.dig_out_pins[i], | ||
| 10584 | &dig_nid, 1); | ||
| 10585 | if (err < 0) | ||
| 10586 | continue; | ||
| 10587 | if (!i) | ||
| 10588 | spec->multiout.dig_out_nid = dig_nid; | ||
| 10589 | else { | ||
| 10590 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
| 10591 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
| 10592 | break; | ||
| 10593 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
| 10594 | } | ||
| 10595 | } | ||
| 10596 | if (spec->autocfg.dig_in_pin) | ||
| 10597 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
| 10598 | 10621 | ||
| 10599 | if (spec->kctls.list) | 10622 | if (spec->kctls.list) |
| 10600 | add_mixer(spec, spec->kctls.list); | 10623 | add_mixer(spec, spec->kctls.list); |
| @@ -10624,6 +10647,7 @@ static void alc882_auto_init(struct hda_codec *codec) | |||
| 10624 | alc882_auto_init_hp_out(codec); | 10647 | alc882_auto_init_hp_out(codec); |
| 10625 | alc882_auto_init_analog_input(codec); | 10648 | alc882_auto_init_analog_input(codec); |
| 10626 | alc882_auto_init_input_src(codec); | 10649 | alc882_auto_init_input_src(codec); |
| 10650 | alc_auto_init_digital(codec); | ||
| 10627 | if (spec->unsol_event) | 10651 | if (spec->unsol_event) |
| 10628 | alc_inithook(codec); | 10652 | alc_inithook(codec); |
| 10629 | } | 10653 | } |
| @@ -12154,12 +12178,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
| 12154 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 12178 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| 12155 | 12179 | ||
| 12156 | dig_only: | 12180 | dig_only: |
| 12157 | if (spec->autocfg.dig_outs) { | 12181 | alc_auto_parse_digital(codec); |
| 12158 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; | ||
| 12159 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
| 12160 | } | ||
| 12161 | if (spec->autocfg.dig_in_pin) | ||
| 12162 | spec->dig_in_nid = ALC262_DIGIN_NID; | ||
| 12163 | 12182 | ||
| 12164 | if (spec->kctls.list) | 12183 | if (spec->kctls.list) |
| 12165 | add_mixer(spec, spec->kctls.list); | 12184 | add_mixer(spec, spec->kctls.list); |
| @@ -12191,6 +12210,7 @@ static void alc262_auto_init(struct hda_codec *codec) | |||
| 12191 | alc262_auto_init_hp_out(codec); | 12210 | alc262_auto_init_hp_out(codec); |
| 12192 | alc262_auto_init_analog_input(codec); | 12211 | alc262_auto_init_analog_input(codec); |
| 12193 | alc262_auto_init_input_src(codec); | 12212 | alc262_auto_init_input_src(codec); |
| 12213 | alc_auto_init_digital(codec); | ||
| 12194 | if (spec->unsol_event) | 12214 | if (spec->unsol_event) |
| 12195 | alc_inithook(codec); | 12215 | alc_inithook(codec); |
| 12196 | } | 12216 | } |
| @@ -13327,10 +13347,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
| 13327 | 13347 | ||
| 13328 | dig_only: | 13348 | dig_only: |
| 13329 | /* digital only support output */ | 13349 | /* digital only support output */ |
| 13330 | if (spec->autocfg.dig_outs) { | 13350 | alc_auto_parse_digital(codec); |
| 13331 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | ||
| 13332 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
| 13333 | } | ||
| 13334 | if (spec->kctls.list) | 13351 | if (spec->kctls.list) |
| 13335 | add_mixer(spec, spec->kctls.list); | 13352 | add_mixer(spec, spec->kctls.list); |
| 13336 | 13353 | ||
| @@ -13360,6 +13377,7 @@ static void alc268_auto_init(struct hda_codec *codec) | |||
| 13360 | alc268_auto_init_hp_out(codec); | 13377 | alc268_auto_init_hp_out(codec); |
| 13361 | alc268_auto_init_mono_speaker_out(codec); | 13378 | alc268_auto_init_mono_speaker_out(codec); |
| 13362 | alc268_auto_init_analog_input(codec); | 13379 | alc268_auto_init_analog_input(codec); |
| 13380 | alc_auto_init_digital(codec); | ||
| 13363 | if (spec->unsol_event) | 13381 | if (spec->unsol_event) |
| 13364 | alc_inithook(codec); | 13382 | alc_inithook(codec); |
| 13365 | } | 13383 | } |
| @@ -14305,8 +14323,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
| 14305 | 14323 | ||
| 14306 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 14324 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| 14307 | 14325 | ||
| 14308 | if (spec->autocfg.dig_outs) | 14326 | alc_auto_parse_digital(codec); |
| 14309 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | ||
| 14310 | 14327 | ||
| 14311 | if (spec->kctls.list) | 14328 | if (spec->kctls.list) |
| 14312 | add_mixer(spec, spec->kctls.list); | 14329 | add_mixer(spec, spec->kctls.list); |
| @@ -14354,6 +14371,7 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
| 14354 | alc269_auto_init_multi_out(codec); | 14371 | alc269_auto_init_multi_out(codec); |
| 14355 | alc269_auto_init_hp_out(codec); | 14372 | alc269_auto_init_hp_out(codec); |
| 14356 | alc269_auto_init_analog_input(codec); | 14373 | alc269_auto_init_analog_input(codec); |
| 14374 | alc_auto_init_digital(codec); | ||
| 14357 | if (spec->unsol_event) | 14375 | if (spec->unsol_event) |
| 14358 | alc_inithook(codec); | 14376 | alc_inithook(codec); |
| 14359 | } | 14377 | } |
| @@ -15515,8 +15533,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
| 15515 | 15533 | ||
| 15516 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 15534 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| 15517 | 15535 | ||
| 15518 | if (spec->autocfg.dig_outs) | 15536 | alc_auto_parse_digital(codec); |
| 15519 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | ||
| 15520 | 15537 | ||
| 15521 | if (spec->kctls.list) | 15538 | if (spec->kctls.list) |
| 15522 | add_mixer(spec, spec->kctls.list); | 15539 | add_mixer(spec, spec->kctls.list); |
| @@ -15542,6 +15559,7 @@ static void alc861_auto_init(struct hda_codec *codec) | |||
| 15542 | alc861_auto_init_multi_out(codec); | 15559 | alc861_auto_init_multi_out(codec); |
| 15543 | alc861_auto_init_hp_out(codec); | 15560 | alc861_auto_init_hp_out(codec); |
| 15544 | alc861_auto_init_analog_input(codec); | 15561 | alc861_auto_init_analog_input(codec); |
| 15562 | alc_auto_init_digital(codec); | ||
| 15545 | if (spec->unsol_event) | 15563 | if (spec->unsol_event) |
| 15546 | alc_inithook(codec); | 15564 | alc_inithook(codec); |
| 15547 | } | 15565 | } |
| @@ -16646,8 +16664,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
| 16646 | 16664 | ||
| 16647 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 16665 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| 16648 | 16666 | ||
| 16649 | if (spec->autocfg.dig_outs) | 16667 | alc_auto_parse_digital(codec); |
| 16650 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | ||
| 16651 | 16668 | ||
| 16652 | if (spec->kctls.list) | 16669 | if (spec->kctls.list) |
| 16653 | add_mixer(spec, spec->kctls.list); | 16670 | add_mixer(spec, spec->kctls.list); |
| @@ -16674,6 +16691,7 @@ static void alc861vd_auto_init(struct hda_codec *codec) | |||
| 16674 | alc861vd_auto_init_hp_out(codec); | 16691 | alc861vd_auto_init_hp_out(codec); |
| 16675 | alc861vd_auto_init_analog_input(codec); | 16692 | alc861vd_auto_init_analog_input(codec); |
| 16676 | alc861vd_auto_init_input_src(codec); | 16693 | alc861vd_auto_init_input_src(codec); |
| 16694 | alc_auto_init_digital(codec); | ||
| 16677 | if (spec->unsol_event) | 16695 | if (spec->unsol_event) |
| 16678 | alc_inithook(codec); | 16696 | alc_inithook(codec); |
| 16679 | } | 16697 | } |
| @@ -18761,8 +18779,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
| 18761 | 18779 | ||
| 18762 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 18780 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| 18763 | 18781 | ||
| 18764 | if (spec->autocfg.dig_outs) | 18782 | alc_auto_parse_digital(codec); |
| 18765 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
| 18766 | 18783 | ||
| 18767 | if (spec->kctls.list) | 18784 | if (spec->kctls.list) |
| 18768 | add_mixer(spec, spec->kctls.list); | 18785 | add_mixer(spec, spec->kctls.list); |
| @@ -18799,6 +18816,7 @@ static void alc662_auto_init(struct hda_codec *codec) | |||
| 18799 | alc662_auto_init_hp_out(codec); | 18816 | alc662_auto_init_hp_out(codec); |
| 18800 | alc662_auto_init_analog_input(codec); | 18817 | alc662_auto_init_analog_input(codec); |
| 18801 | alc662_auto_init_input_src(codec); | 18818 | alc662_auto_init_input_src(codec); |
| 18819 | alc_auto_init_digital(codec); | ||
| 18802 | if (spec->unsol_event) | 18820 | if (spec->unsol_event) |
| 18803 | alc_inithook(codec); | 18821 | alc_inithook(codec); |
| 18804 | } | 18822 | } |
| @@ -19124,10 +19142,7 @@ static int alc680_parse_auto_config(struct hda_codec *codec) | |||
| 19124 | 19142 | ||
| 19125 | dig_only: | 19143 | dig_only: |
| 19126 | /* digital only support output */ | 19144 | /* digital only support output */ |
| 19127 | if (spec->autocfg.dig_outs) { | 19145 | alc_auto_parse_digital(codec); |
| 19128 | spec->multiout.dig_out_nid = ALC680_DIGOUT_NID; | ||
| 19129 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
| 19130 | } | ||
| 19131 | if (spec->kctls.list) | 19146 | if (spec->kctls.list) |
| 19132 | add_mixer(spec, spec->kctls.list); | 19147 | add_mixer(spec, spec->kctls.list); |
| 19133 | 19148 | ||
| @@ -19151,6 +19166,7 @@ static void alc680_auto_init(struct hda_codec *codec) | |||
| 19151 | alc680_auto_init_multi_out(codec); | 19166 | alc680_auto_init_multi_out(codec); |
| 19152 | alc680_auto_init_hp_out(codec); | 19167 | alc680_auto_init_hp_out(codec); |
| 19153 | alc680_auto_init_analog_input(codec); | 19168 | alc680_auto_init_analog_input(codec); |
| 19169 | alc_auto_init_digital(codec); | ||
| 19154 | if (spec->unsol_event) | 19170 | if (spec->unsol_event) |
| 19155 | alc_inithook(codec); | 19171 | alc_inithook(codec); |
| 19156 | } | 19172 | } |
