diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-12-14 10:54:44 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-12 02:30:10 -0500 |
commit | fef7fbbc5d6643513b27a706ed02ed4c46a0eef2 (patch) | |
tree | 52f9567d63fe8b32f83888ccfc34d6d921a7ebfb | |
parent | c9967f1cbadd3a6af2be54a5baed2cc0dcef50e6 (diff) |
ALSA: hda/realtek - Use path-based parser for digital outputs
Similar like analog output paths, use the path list for parsing and
initializing digital outputs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9a38107cf0f5..e25b13a09e58 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -1424,6 +1424,14 @@ static unsigned int alc_get_coef0(struct hda_codec *codec) | |||
1424 | return spec->coef0; | 1424 | return spec->coef0; |
1425 | } | 1425 | } |
1426 | 1426 | ||
1427 | static void alc_auto_set_output_and_unmute(struct hda_codec *codec, | ||
1428 | hda_nid_t pin, int pin_type, | ||
1429 | hda_nid_t dac); | ||
1430 | static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin, | ||
1431 | bool is_digital); | ||
1432 | static bool add_new_out_path(struct hda_codec *codec, hda_nid_t pin, | ||
1433 | hda_nid_t dac); | ||
1434 | |||
1427 | /* | 1435 | /* |
1428 | * Digital I/O handling | 1436 | * Digital I/O handling |
1429 | */ | 1437 | */ |
@@ -1433,22 +1441,13 @@ static void alc_auto_init_digital(struct hda_codec *codec) | |||
1433 | { | 1441 | { |
1434 | struct alc_spec *spec = codec->spec; | 1442 | struct alc_spec *spec = codec->spec; |
1435 | int i; | 1443 | int i; |
1436 | hda_nid_t pin, dac; | 1444 | hda_nid_t pin; |
1437 | 1445 | ||
1438 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | 1446 | for (i = 0; i < spec->autocfg.dig_outs; i++) { |
1439 | pin = spec->autocfg.dig_out_pins[i]; | 1447 | pin = spec->autocfg.dig_out_pins[i]; |
1440 | if (!pin) | 1448 | if (!pin) |
1441 | continue; | 1449 | continue; |
1442 | snd_hda_set_pin_ctl(codec, pin, PIN_OUT); | 1450 | alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
1443 | if (!i) | ||
1444 | dac = spec->multiout.dig_out_nid; | ||
1445 | else | ||
1446 | dac = spec->slave_dig_outs[i - 1]; | ||
1447 | if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP)) | ||
1448 | continue; | ||
1449 | snd_hda_codec_write(codec, dac, 0, | ||
1450 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1451 | AMP_OUT_UNMUTE); | ||
1452 | } | 1451 | } |
1453 | pin = spec->autocfg.dig_in_pin; | 1452 | pin = spec->autocfg.dig_in_pin; |
1454 | if (pin) | 1453 | if (pin) |
@@ -1465,13 +1464,10 @@ static void alc_auto_parse_digital(struct hda_codec *codec) | |||
1465 | /* support multiple SPDIFs; the secondary is set up as a slave */ | 1464 | /* support multiple SPDIFs; the secondary is set up as a slave */ |
1466 | nums = 0; | 1465 | nums = 0; |
1467 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | 1466 | for (i = 0; i < spec->autocfg.dig_outs; i++) { |
1468 | hda_nid_t conn[4]; | 1467 | hda_nid_t pin = spec->autocfg.dig_out_pins[i]; |
1469 | err = snd_hda_get_connections(codec, | 1468 | dig_nid = alc_auto_look_for_dac(codec, pin, true); |
1470 | spec->autocfg.dig_out_pins[i], | 1469 | if (!dig_nid) |
1471 | conn, ARRAY_SIZE(conn)); | ||
1472 | if (err <= 0) | ||
1473 | continue; | 1470 | continue; |
1474 | dig_nid = conn[0]; /* assume the first element is audio-out */ | ||
1475 | if (!nums) { | 1471 | if (!nums) { |
1476 | spec->multiout.dig_out_nid = dig_nid; | 1472 | spec->multiout.dig_out_nid = dig_nid; |
1477 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | 1473 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; |
@@ -1481,6 +1477,7 @@ static void alc_auto_parse_digital(struct hda_codec *codec) | |||
1481 | break; | 1477 | break; |
1482 | spec->slave_dig_outs[nums - 1] = dig_nid; | 1478 | spec->slave_dig_outs[nums - 1] = dig_nid; |
1483 | } | 1479 | } |
1480 | add_new_out_path(codec, pin, dig_nid); | ||
1484 | nums++; | 1481 | nums++; |
1485 | } | 1482 | } |
1486 | 1483 | ||
@@ -2895,15 +2892,20 @@ static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) | |||
2895 | } | 2892 | } |
2896 | 2893 | ||
2897 | /* look for an empty DAC slot */ | 2894 | /* look for an empty DAC slot */ |
2898 | static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | 2895 | static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin, |
2896 | bool is_digital) | ||
2899 | { | 2897 | { |
2900 | struct alc_spec *spec = codec->spec; | 2898 | struct alc_spec *spec = codec->spec; |
2899 | bool cap_digital; | ||
2901 | int i; | 2900 | int i; |
2902 | 2901 | ||
2903 | for (i = 0; i < spec->num_all_dacs; i++) { | 2902 | for (i = 0; i < spec->num_all_dacs; i++) { |
2904 | hda_nid_t nid = spec->all_dacs[i]; | 2903 | hda_nid_t nid = spec->all_dacs[i]; |
2905 | if (!nid || alc_is_dac_already_used(codec, nid)) | 2904 | if (!nid || alc_is_dac_already_used(codec, nid)) |
2906 | continue; | 2905 | continue; |
2906 | cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL); | ||
2907 | if (is_digital != cap_digital) | ||
2908 | continue; | ||
2907 | if (is_reachable_path(codec, nid, pin)) | 2909 | if (is_reachable_path(codec, nid, pin)) |
2908 | return nid; | 2910 | return nid; |
2909 | } | 2911 | } |
@@ -3169,7 +3171,7 @@ static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs, | |||
3169 | for (i = 0; i < num_outs; i++) { | 3171 | for (i = 0; i < num_outs; i++) { |
3170 | hda_nid_t pin = pins[i]; | 3172 | hda_nid_t pin = pins[i]; |
3171 | if (!dacs[i]) | 3173 | if (!dacs[i]) |
3172 | dacs[i] = alc_auto_look_for_dac(codec, pin); | 3174 | dacs[i] = alc_auto_look_for_dac(codec, pin, false); |
3173 | if (!dacs[i] && !i) { | 3175 | if (!dacs[i] && !i) { |
3174 | for (j = 1; j < num_outs; j++) { | 3176 | for (j = 1; j < num_outs; j++) { |
3175 | if (is_reachable_path(codec, dacs[j], pin)) { | 3177 | if (is_reachable_path(codec, dacs[j], pin)) { |
@@ -4110,7 +4112,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, | |||
4110 | if (hardwired) | 4112 | if (hardwired) |
4111 | dac = get_dac_if_single(codec, nid); | 4113 | dac = get_dac_if_single(codec, nid); |
4112 | else if (!dac) | 4114 | else if (!dac) |
4113 | dac = alc_auto_look_for_dac(codec, nid); | 4115 | dac = alc_auto_look_for_dac(codec, nid, false); |
4114 | if (!dac) { | 4116 | if (!dac) { |
4115 | badness++; | 4117 | badness++; |
4116 | continue; | 4118 | continue; |