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/pci/hda/hda_codec.c | |
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/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 77 |
1 files changed, 74 insertions, 3 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 | ||