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