diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-03-21 05:24:42 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-03-22 04:40:14 -0500 |
commit | 82bc955f6379135e6ce35ff90c7ac411fd412c4c (patch) | |
tree | 314610afb5a469ac6a5a9f4d5e947436bb2c0538 /sound | |
parent | 19739fef0203d2f3eecc9c4b1ef25b57d85f2b30 (diff) |
[ALSA] hda-codec - Fix BIOS auto-configuration
Modules: HDA Codec driver,HDA generic driver
- Fix autoconfig speaker/hp detection
Now it allows multiple speaker pins (e.g. Dell laptops have such config)
- Use speaker or hp pins if no line-outs are available
This fixes the silence output on recent Dell laptops with STAC9200
(ALSA bug#1843)
- Fix analog/realtek/sigmatel autoconfig parser
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 77 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 23 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 47 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 84 |
5 files changed, 160 insertions, 75 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fc91256e42eb..b42dff7ceed0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1899,6 +1899,13 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1899 | if (mout->hp_nid) | 1899 | if (mout->hp_nid) |
1900 | /* headphone out will just decode front left/right (stereo) */ | 1900 | /* headphone out will just decode front left/right (stereo) */ |
1901 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | 1901 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); |
1902 | /* extra outputs copied from front */ | ||
1903 | for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) | ||
1904 | if (mout->extra_out_nid[i]) | ||
1905 | snd_hda_codec_setup_stream(codec, | ||
1906 | mout->extra_out_nid[i], | ||
1907 | stream_tag, 0, format); | ||
1908 | |||
1902 | /* surrounds */ | 1909 | /* surrounds */ |
1903 | for (i = 1; i < mout->num_dacs; i++) { | 1910 | for (i = 1; i < mout->num_dacs; i++) { |
1904 | if (chs >= (i + 1) * 2) /* independent out */ | 1911 | if (chs >= (i + 1) * 2) /* independent out */ |
@@ -1923,6 +1930,11 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o | |||
1923 | snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); | 1930 | snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); |
1924 | if (mout->hp_nid) | 1931 | if (mout->hp_nid) |
1925 | snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); | 1932 | snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); |
1933 | for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) | ||
1934 | if (mout->extra_out_nid[i]) | ||
1935 | snd_hda_codec_setup_stream(codec, | ||
1936 | mout->extra_out_nid[i], | ||
1937 | 0, 0, 0); | ||
1926 | mutex_lock(&codec->spdif_mutex); | 1938 | mutex_lock(&codec->spdif_mutex); |
1927 | if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { | 1939 | if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { |
1928 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); | 1940 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); |
@@ -1944,13 +1956,29 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
1944 | return 0; | 1956 | return 0; |
1945 | } | 1957 | } |
1946 | 1958 | ||
1947 | /* parse all pin widgets and store the useful pin nids to cfg */ | 1959 | /* |
1960 | * Parse all pin widgets and store the useful pin nids to cfg | ||
1961 | * | ||
1962 | * The number of line-outs or any primary output is stored in line_outs, | ||
1963 | * and the corresponding output pins are assigned to line_out_pins[], | ||
1964 | * in the order of front, rear, CLFE, side, ... | ||
1965 | * | ||
1966 | * If more extra outputs (speaker and headphone) are found, the pins are | ||
1967 | * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack | ||
1968 | * is detected, one of speaker of HP pins is assigned as the primary | ||
1969 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | ||
1970 | * if any analog output exists. | ||
1971 | * | ||
1972 | * The analog input pins are assigned to input_pins array. | ||
1973 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | ||
1974 | * respectively. | ||
1975 | */ | ||
1948 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, | 1976 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, |
1949 | hda_nid_t *ignore_nids) | 1977 | hda_nid_t *ignore_nids) |
1950 | { | 1978 | { |
1951 | hda_nid_t nid, nid_start; | 1979 | hda_nid_t nid, nid_start; |
1952 | int i, j, nodes; | 1980 | int i, j, nodes; |
1953 | short seq, sequences[4], assoc_line_out; | 1981 | short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)]; |
1954 | 1982 | ||
1955 | memset(cfg, 0, sizeof(*cfg)); | 1983 | memset(cfg, 0, sizeof(*cfg)); |
1956 | 1984 | ||
@@ -1992,7 +2020,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
1992 | cfg->line_outs++; | 2020 | cfg->line_outs++; |
1993 | break; | 2021 | break; |
1994 | case AC_JACK_SPEAKER: | 2022 | case AC_JACK_SPEAKER: |
1995 | cfg->speaker_pin = nid; | 2023 | if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) |
2024 | continue; | ||
2025 | cfg->speaker_pins[cfg->speaker_outs] = nid; | ||
2026 | cfg->speaker_outs++; | ||
1996 | break; | 2027 | break; |
1997 | case AC_JACK_HP_OUT: | 2028 | case AC_JACK_HP_OUT: |
1998 | cfg->hp_pin = nid; | 2029 | cfg->hp_pin = nid; |
@@ -2057,6 +2088,46 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2057 | break; | 2088 | break; |
2058 | } | 2089 | } |
2059 | 2090 | ||
2091 | /* | ||
2092 | * debug prints of the parsed results | ||
2093 | */ | ||
2094 | snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | ||
2095 | cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], | ||
2096 | cfg->line_out_pins[2], cfg->line_out_pins[3], | ||
2097 | cfg->line_out_pins[4]); | ||
2098 | snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | ||
2099 | cfg->speaker_outs, cfg->speaker_pins[0], | ||
2100 | cfg->speaker_pins[1], cfg->speaker_pins[2], | ||
2101 | cfg->speaker_pins[3], cfg->speaker_pins[4]); | ||
2102 | snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", | ||
2103 | cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); | ||
2104 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | ||
2105 | " cd=0x%x, aux=0x%x\n", | ||
2106 | cfg->input_pins[AUTO_PIN_MIC], | ||
2107 | cfg->input_pins[AUTO_PIN_FRONT_MIC], | ||
2108 | cfg->input_pins[AUTO_PIN_LINE], | ||
2109 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | ||
2110 | cfg->input_pins[AUTO_PIN_CD], | ||
2111 | cfg->input_pins[AUTO_PIN_AUX]); | ||
2112 | |||
2113 | /* | ||
2114 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | ||
2115 | * as a primary output | ||
2116 | */ | ||
2117 | if (! cfg->line_outs) { | ||
2118 | if (cfg->speaker_outs) { | ||
2119 | cfg->line_outs = cfg->speaker_outs; | ||
2120 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
2121 | sizeof(cfg->speaker_pins)); | ||
2122 | cfg->speaker_outs = 0; | ||
2123 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
2124 | } else if (cfg->hp_pin) { | ||
2125 | cfg->line_outs = 1; | ||
2126 | cfg->line_out_pins[0] = cfg->hp_pin; | ||
2127 | cfg->hp_pin = 0; | ||
2128 | } | ||
2129 | } | ||
2130 | |||
2060 | return 0; | 2131 | return 0; |
2061 | } | 2132 | } |
2062 | 2133 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 548a8b698487..14e8aa2806ed 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -135,6 +135,7 @@ struct hda_multi_out { | |||
135 | int num_dacs; /* # of DACs, must be more than 1 */ | 135 | int num_dacs; /* # of DACs, must be more than 1 */ |
136 | hda_nid_t *dac_nids; /* DAC list */ | 136 | hda_nid_t *dac_nids; /* DAC list */ |
137 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ | 137 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ |
138 | hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ | ||
138 | hda_nid_t dig_out_nid; /* digital out audio widget */ | 139 | hda_nid_t dig_out_nid; /* digital out audio widget */ |
139 | int max_channels; /* currently supported analog channels */ | 140 | int max_channels; /* currently supported analog channels */ |
140 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ | 141 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ |
@@ -221,7 +222,8 @@ extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | |||
221 | struct auto_pin_cfg { | 222 | struct auto_pin_cfg { |
222 | int line_outs; | 223 | int line_outs; |
223 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ | 224 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ |
224 | hda_nid_t speaker_pin; | 225 | int speaker_outs; |
226 | hda_nid_t speaker_pins[5]; | ||
225 | hda_nid_t hp_pin; | 227 | hda_nid_t hp_pin; |
226 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 228 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
227 | hda_nid_t dig_out_pin; | 229 | hda_nid_t dig_out_pin; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2b14fa74a8fd..7fbe71e69cfc 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -786,6 +786,8 @@ enum { AD1986A_6STACK, AD1986A_3STACK, AD1986A_LAPTOP, AD1986A_LAPTOP_EAPD }; | |||
786 | static struct hda_board_config ad1986a_cfg_tbl[] = { | 786 | static struct hda_board_config ad1986a_cfg_tbl[] = { |
787 | { .modelname = "6stack", .config = AD1986A_6STACK }, | 787 | { .modelname = "6stack", .config = AD1986A_6STACK }, |
788 | { .modelname = "3stack", .config = AD1986A_3STACK }, | 788 | { .modelname = "3stack", .config = AD1986A_3STACK }, |
789 | { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, | ||
790 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ | ||
789 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, | 791 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, |
790 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, | 792 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, |
791 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ | 793 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ |
@@ -2253,14 +2255,11 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
2253 | 2255 | ||
2254 | idx = ad1988_pin_idx(pin); | 2256 | idx = ad1988_pin_idx(pin); |
2255 | nid = ad1988_idx_to_dac(codec, idx); | 2257 | nid = ad1988_idx_to_dac(codec, idx); |
2256 | if (! spec->multiout.dac_nids[0]) { | 2258 | /* specify the DAC as the extra output */ |
2257 | /* use this as the primary output */ | 2259 | if (! spec->multiout.hp_nid) |
2258 | spec->multiout.dac_nids[0] = nid; | ||
2259 | if (! spec->multiout.num_dacs) | ||
2260 | spec->multiout.num_dacs = 1; | ||
2261 | } else | ||
2262 | /* specify the DAC as the extra output */ | ||
2263 | spec->multiout.hp_nid = nid; | 2260 | spec->multiout.hp_nid = nid; |
2261 | else | ||
2262 | spec->multiout.extra_out_nid[0] = nid; | ||
2264 | /* control HP volume/switch on the output mixer amp */ | 2263 | /* control HP volume/switch on the output mixer amp */ |
2265 | sprintf(name, "%s Playback Volume", pfx); | 2264 | sprintf(name, "%s Playback Volume", pfx); |
2266 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, | 2265 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, |
@@ -2379,7 +2378,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
2379 | struct ad198x_spec *spec = codec->spec; | 2378 | struct ad198x_spec *spec = codec->spec; |
2380 | hda_nid_t pin; | 2379 | hda_nid_t pin; |
2381 | 2380 | ||
2382 | pin = spec->autocfg.speaker_pin; | 2381 | pin = spec->autocfg.speaker_pins[0]; |
2383 | if (pin) /* connect to front */ | 2382 | if (pin) /* connect to front */ |
2384 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2383 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2385 | pin = spec->autocfg.hp_pin; | 2384 | pin = spec->autocfg.hp_pin; |
@@ -2428,13 +2427,13 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2428 | return err; | 2427 | return err; |
2429 | if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 2428 | if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
2430 | return err; | 2429 | return err; |
2431 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 2430 | if (! spec->autocfg.line_outs) |
2432 | ! spec->autocfg.hp_pin) | ||
2433 | return 0; /* can't find valid BIOS pin config */ | 2431 | return 0; /* can't find valid BIOS pin config */ |
2434 | if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 2432 | if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
2435 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, | 2433 | (err = ad1988_auto_create_extra_out(codec, |
2434 | spec->autocfg.speaker_pins[0], | ||
2436 | "Speaker")) < 0 || | 2435 | "Speaker")) < 0 || |
2437 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, | 2436 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, |
2438 | "Headphone")) < 0 || | 2437 | "Headphone")) < 0 || |
2439 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2438 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2440 | return err; | 2439 | return err; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1607a1fab568..de145d102d9f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2431,14 +2431,11 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
2431 | 2431 | ||
2432 | if (alc880_is_fixed_pin(pin)) { | 2432 | if (alc880_is_fixed_pin(pin)) { |
2433 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 2433 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); |
2434 | if (! spec->multiout.dac_nids[0]) { | 2434 | /* specify the DAC as the extra output */ |
2435 | /* use this as the primary output */ | 2435 | if (! spec->multiout.hp_nid) |
2436 | spec->multiout.dac_nids[0] = nid; | ||
2437 | if (! spec->multiout.num_dacs) | ||
2438 | spec->multiout.num_dacs = 1; | ||
2439 | } else | ||
2440 | /* specify the DAC as the extra output */ | ||
2441 | spec->multiout.hp_nid = nid; | 2436 | spec->multiout.hp_nid = nid; |
2437 | else | ||
2438 | spec->multiout.extra_out_nid[0] = nid; | ||
2442 | /* control HP volume/switch on the output mixer amp */ | 2439 | /* control HP volume/switch on the output mixer amp */ |
2443 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); | 2440 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); |
2444 | sprintf(name, "%s Playback Volume", pfx); | 2441 | sprintf(name, "%s Playback Volume", pfx); |
@@ -2451,12 +2448,6 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
2451 | return err; | 2448 | return err; |
2452 | } else if (alc880_is_multi_pin(pin)) { | 2449 | } else if (alc880_is_multi_pin(pin)) { |
2453 | /* set manual connection */ | 2450 | /* set manual connection */ |
2454 | if (! spec->multiout.dac_nids[0]) { | ||
2455 | /* use this as the primary output */ | ||
2456 | spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin)); | ||
2457 | if (! spec->multiout.num_dacs) | ||
2458 | spec->multiout.num_dacs = 1; | ||
2459 | } | ||
2460 | /* we have only a switch on HP-out PIN */ | 2451 | /* we have only a switch on HP-out PIN */ |
2461 | sprintf(name, "%s Playback Switch", pfx); | 2452 | sprintf(name, "%s Playback Switch", pfx); |
2462 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | 2453 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, |
@@ -2540,7 +2531,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
2540 | struct alc_spec *spec = codec->spec; | 2531 | struct alc_spec *spec = codec->spec; |
2541 | hda_nid_t pin; | 2532 | hda_nid_t pin; |
2542 | 2533 | ||
2543 | pin = spec->autocfg.speaker_pin; | 2534 | pin = spec->autocfg.speaker_pins[0]; |
2544 | if (pin) /* connect to front */ | 2535 | if (pin) /* connect to front */ |
2545 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2536 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2546 | pin = spec->autocfg.hp_pin; | 2537 | pin = spec->autocfg.hp_pin; |
@@ -2576,15 +2567,15 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2576 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 2567 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
2577 | alc880_ignore)) < 0) | 2568 | alc880_ignore)) < 0) |
2578 | return err; | 2569 | return err; |
2579 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 2570 | if (! spec->autocfg.line_outs) |
2580 | ! spec->autocfg.hp_pin) | ||
2581 | return 0; /* can't find valid BIOS pin config */ | 2571 | return 0; /* can't find valid BIOS pin config */ |
2582 | 2572 | ||
2583 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 2573 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || |
2584 | (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 2574 | (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
2585 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, | 2575 | (err = alc880_auto_create_extra_out(spec, |
2576 | spec->autocfg.speaker_pins[0], | ||
2586 | "Speaker")) < 0 || | 2577 | "Speaker")) < 0 || |
2587 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, | 2578 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, |
2588 | "Headphone")) < 0 || | 2579 | "Headphone")) < 0 || |
2589 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2580 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2590 | return err; | 2581 | return err; |
@@ -3445,7 +3436,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
3445 | return err; | 3436 | return err; |
3446 | } | 3437 | } |
3447 | 3438 | ||
3448 | nid = cfg->speaker_pin; | 3439 | nid = cfg->speaker_pins[0]; |
3449 | if (nid) { | 3440 | if (nid) { |
3450 | err = alc260_add_playback_controls(spec, nid, "Speaker"); | 3441 | err = alc260_add_playback_controls(spec, nid, "Speaker"); |
3451 | if (err < 0) | 3442 | if (err < 0) |
@@ -3518,7 +3509,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
3518 | if (nid) | 3509 | if (nid) |
3519 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3510 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3520 | 3511 | ||
3521 | nid = spec->autocfg.speaker_pin; | 3512 | nid = spec->autocfg.speaker_pins[0]; |
3522 | if (nid) | 3513 | if (nid) |
3523 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3514 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3524 | 3515 | ||
@@ -4602,7 +4593,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
4602 | return err; | 4593 | return err; |
4603 | } | 4594 | } |
4604 | 4595 | ||
4605 | nid = cfg->speaker_pin; | 4596 | nid = cfg->speaker_pins[0]; |
4606 | if (nid) { | 4597 | if (nid) { |
4607 | if (nid == 0x16) { | 4598 | if (nid == 0x16) { |
4608 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", | 4599 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", |
@@ -4612,10 +4603,6 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
4612 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 4603 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) |
4613 | return err; | 4604 | return err; |
4614 | } else { | 4605 | } else { |
4615 | if (! cfg->line_out_pins[0]) | ||
4616 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", | ||
4617 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) | ||
4618 | return err; | ||
4619 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", | 4606 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", |
4620 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 4607 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) |
4621 | return err; | 4608 | return err; |
@@ -4632,10 +4619,6 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
4632 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 4619 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) |
4633 | return err; | 4620 | return err; |
4634 | } else { | 4621 | } else { |
4635 | if (! cfg->line_out_pins[0]) | ||
4636 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", | ||
4637 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) | ||
4638 | return err; | ||
4639 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 4622 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", |
4640 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 4623 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) |
4641 | return err; | 4624 | return err; |
@@ -4729,8 +4712,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
4729 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 4712 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
4730 | alc262_ignore)) < 0) | 4713 | alc262_ignore)) < 0) |
4731 | return err; | 4714 | return err; |
4732 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 4715 | if (! spec->autocfg.line_outs) |
4733 | ! spec->autocfg.hp_pin) | ||
4734 | return 0; /* can't find valid BIOS pin config */ | 4716 | return 0; /* can't find valid BIOS pin config */ |
4735 | if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 4717 | if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
4736 | (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 4718 | (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
@@ -5404,8 +5386,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
5404 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 5386 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
5405 | alc861_ignore)) < 0) | 5387 | alc861_ignore)) < 0) |
5406 | return err; | 5388 | return err; |
5407 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 5389 | if (! spec->autocfg.line_outs) |
5408 | ! spec->autocfg.hp_pin) | ||
5409 | return 0; /* can't find valid BIOS pin config */ | 5390 | return 0; /* can't find valid BIOS pin config */ |
5410 | 5391 | ||
5411 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 5392 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 240958df26ce..b56ca4019392 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -51,6 +51,7 @@ struct sigmatel_spec { | |||
51 | unsigned int line_switch: 1; | 51 | unsigned int line_switch: 1; |
52 | unsigned int mic_switch: 1; | 52 | unsigned int mic_switch: 1; |
53 | unsigned int alt_switch: 1; | 53 | unsigned int alt_switch: 1; |
54 | unsigned int hp_detect: 1; | ||
54 | 55 | ||
55 | /* playback */ | 56 | /* playback */ |
56 | struct hda_multi_out multiout; | 57 | struct hda_multi_out multiout; |
@@ -697,13 +698,7 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct aut | |||
697 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 698 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
698 | } | 699 | } |
699 | 700 | ||
700 | if (cfg->line_outs) | 701 | spec->multiout.num_dacs = cfg->line_outs; |
701 | spec->multiout.num_dacs = cfg->line_outs; | ||
702 | else if (cfg->hp_pin) { | ||
703 | spec->multiout.dac_nids[0] = snd_hda_codec_read(codec, cfg->hp_pin, 0, | ||
704 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
705 | spec->multiout.num_dacs = 1; | ||
706 | } | ||
707 | 702 | ||
708 | return 0; | 703 | return 0; |
709 | } | 704 | } |
@@ -772,11 +767,13 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin | |||
772 | return 0; | 767 | return 0; |
773 | 768 | ||
774 | wid_caps = get_wcaps(codec, pin); | 769 | wid_caps = get_wcaps(codec, pin); |
775 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 770 | if (wid_caps & AC_WCAP_UNSOL_CAP) { |
776 | /* Enable unsolicited responses on the HP widget */ | 771 | /* Enable unsolicited responses on the HP widget */ |
777 | snd_hda_codec_write(codec, pin, 0, | 772 | snd_hda_codec_write(codec, pin, 0, |
778 | AC_VERB_SET_UNSOLICITED_ENABLE, | 773 | AC_VERB_SET_UNSOLICITED_ENABLE, |
779 | STAC_UNSOL_ENABLE); | 774 | STAC_UNSOL_ENABLE); |
775 | spec->hp_detect = 1; | ||
776 | } | ||
780 | 777 | ||
781 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 778 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
782 | for (i = 0; i < cfg->line_outs; i++) { | 779 | for (i = 0; i < cfg->line_outs; i++) { |
@@ -810,9 +807,6 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
810 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 807 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
811 | int index = -1; | 808 | int index = -1; |
812 | if (cfg->input_pins[i]) { | 809 | if (cfg->input_pins[i]) { |
813 | /* Enable active pin widget as an input */ | ||
814 | stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], AC_PINCTL_IN_EN); | ||
815 | |||
816 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 810 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; |
817 | 811 | ||
818 | for (j=0; j<spec->num_muxes; j++) { | 812 | for (j=0; j<spec->num_muxes; j++) { |
@@ -861,10 +855,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
861 | 855 | ||
862 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) | 856 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) |
863 | return err; | 857 | return err; |
864 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | 858 | if (! spec->autocfg.line_outs) |
865 | return 0; /* can't find valid pin config */ | 859 | return 0; /* can't find valid pin config */ |
866 | stac92xx_auto_init_multi_out(codec); | ||
867 | stac92xx_auto_init_hp_out(codec); | ||
868 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) | 860 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) |
869 | return err; | 861 | return err; |
870 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 862 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
@@ -879,14 +871,10 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
879 | if (spec->multiout.max_channels > 2) | 871 | if (spec->multiout.max_channels > 2) |
880 | spec->surr_switch = 1; | 872 | spec->surr_switch = 1; |
881 | 873 | ||
882 | if (spec->autocfg.dig_out_pin) { | 874 | if (spec->autocfg.dig_out_pin) |
883 | spec->multiout.dig_out_nid = dig_out; | 875 | spec->multiout.dig_out_nid = dig_out; |
884 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | 876 | if (spec->autocfg.dig_in_pin) |
885 | } | ||
886 | if (spec->autocfg.dig_in_pin) { | ||
887 | spec->dig_in_nid = dig_in; | 877 | spec->dig_in_nid = dig_in; |
888 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
889 | } | ||
890 | 878 | ||
891 | if (spec->kctl_alloc) | 879 | if (spec->kctl_alloc) |
892 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 880 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
@@ -896,6 +884,29 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
896 | return 1; | 884 | return 1; |
897 | } | 885 | } |
898 | 886 | ||
887 | /* add playback controls for HP output */ | ||
888 | static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | ||
889 | struct auto_pin_cfg *cfg) | ||
890 | { | ||
891 | struct sigmatel_spec *spec = codec->spec; | ||
892 | hda_nid_t pin = cfg->hp_pin; | ||
893 | unsigned int wid_caps; | ||
894 | |||
895 | if (! pin) | ||
896 | return 0; | ||
897 | |||
898 | wid_caps = get_wcaps(codec, pin); | ||
899 | if (wid_caps & AC_WCAP_UNSOL_CAP) { | ||
900 | /* Enable unsolicited responses on the HP widget */ | ||
901 | snd_hda_codec_write(codec, pin, 0, | ||
902 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
903 | STAC_UNSOL_ENABLE); | ||
904 | spec->hp_detect = 1; | ||
905 | } | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | |||
899 | static int stac9200_parse_auto_config(struct hda_codec *codec) | 910 | static int stac9200_parse_auto_config(struct hda_codec *codec) |
900 | { | 911 | { |
901 | struct sigmatel_spec *spec = codec->spec; | 912 | struct sigmatel_spec *spec = codec->spec; |
@@ -907,14 +918,13 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
907 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | 918 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) |
908 | return err; | 919 | return err; |
909 | 920 | ||
910 | if (spec->autocfg.dig_out_pin) { | 921 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) |
922 | return err; | ||
923 | |||
924 | if (spec->autocfg.dig_out_pin) | ||
911 | spec->multiout.dig_out_nid = 0x05; | 925 | spec->multiout.dig_out_nid = 0x05; |
912 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | 926 | if (spec->autocfg.dig_in_pin) |
913 | } | ||
914 | if (spec->autocfg.dig_in_pin) { | ||
915 | spec->dig_in_nid = 0x04; | 927 | spec->dig_in_nid = 0x04; |
916 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
917 | } | ||
918 | 928 | ||
919 | if (spec->kctl_alloc) | 929 | if (spec->kctl_alloc) |
920 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 930 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
@@ -927,9 +937,31 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
927 | static int stac92xx_init(struct hda_codec *codec) | 937 | static int stac92xx_init(struct hda_codec *codec) |
928 | { | 938 | { |
929 | struct sigmatel_spec *spec = codec->spec; | 939 | struct sigmatel_spec *spec = codec->spec; |
940 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
941 | int i; | ||
930 | 942 | ||
931 | snd_hda_sequence_write(codec, spec->init); | 943 | snd_hda_sequence_write(codec, spec->init); |
932 | 944 | ||
945 | /* set up pins */ | ||
946 | if (spec->hp_detect) { | ||
947 | /* fake event to set up pins */ | ||
948 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
949 | } else { | ||
950 | stac92xx_auto_init_multi_out(codec); | ||
951 | stac92xx_auto_init_hp_out(codec); | ||
952 | } | ||
953 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
954 | if (cfg->input_pins[i]) | ||
955 | stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], | ||
956 | AC_PINCTL_IN_EN); | ||
957 | } | ||
958 | if (cfg->dig_out_pin) | ||
959 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | ||
960 | AC_PINCTL_OUT_EN); | ||
961 | if (cfg->dig_in_pin) | ||
962 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | ||
963 | AC_PINCTL_IN_EN); | ||
964 | |||
933 | return 0; | 965 | return 0; |
934 | } | 966 | } |
935 | 967 | ||