diff options
author | Steve Longerbeam <stevel@embeddedalley.com> | 2007-05-08 09:33:03 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-05-11 10:56:18 -0400 |
commit | 81937d3bac582ea2249dc2c8891d3371635e8b64 (patch) | |
tree | 2aa6a1787815e04a1684b048c9c0673922c8808d /sound | |
parent | bdd148a307e230517bf891c108e0eec68ba5d10f (diff) |
[ALSA] Add speaker pin sequencing to hda_codec.c:snd_hda_parse_pin_def_config()
Some verb tables (such as an Asus VT sent by IDT) contain only speaker
outs in the default pin configs, and no line-outs. In such a case the
speaker sequence numbers have to be used to order the speaker out
pins, just as is being done for line-out pins. Then, when speaker-outs
are copied to line-outs, the line-outs will be ordered properly.
Signed-off-by: Steve Longerbeam <stevel@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 106 |
1 files changed, 69 insertions, 37 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ff12de474d2c..14649d54b493 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2112,6 +2112,32 @@ static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
2112 | return 0; | 2112 | return 0; |
2113 | } | 2113 | } |
2114 | 2114 | ||
2115 | |||
2116 | /* | ||
2117 | * Sort an associated group of pins according to their sequence numbers. | ||
2118 | */ | ||
2119 | static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | ||
2120 | int num_pins) | ||
2121 | { | ||
2122 | int i, j; | ||
2123 | short seq; | ||
2124 | hda_nid_t nid; | ||
2125 | |||
2126 | for (i = 0; i < num_pins; i++) { | ||
2127 | for (j = i + 1; j < num_pins; j++) { | ||
2128 | if (sequences[i] > sequences[j]) { | ||
2129 | seq = sequences[i]; | ||
2130 | sequences[i] = sequences[j]; | ||
2131 | sequences[j] = seq; | ||
2132 | nid = pins[i]; | ||
2133 | pins[i] = pins[j]; | ||
2134 | pins[j] = nid; | ||
2135 | } | ||
2136 | } | ||
2137 | } | ||
2138 | } | ||
2139 | |||
2140 | |||
2115 | /* | 2141 | /* |
2116 | * Parse all pin widgets and store the useful pin nids to cfg | 2142 | * Parse all pin widgets and store the useful pin nids to cfg |
2117 | * | 2143 | * |
@@ -2134,13 +2160,16 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2134 | hda_nid_t *ignore_nids) | 2160 | hda_nid_t *ignore_nids) |
2135 | { | 2161 | { |
2136 | hda_nid_t nid, nid_start; | 2162 | hda_nid_t nid, nid_start; |
2137 | int i, j, nodes; | 2163 | int nodes; |
2138 | short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)]; | 2164 | short seq, assoc_line_out, assoc_speaker; |
2165 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; | ||
2166 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; | ||
2139 | 2167 | ||
2140 | memset(cfg, 0, sizeof(*cfg)); | 2168 | memset(cfg, 0, sizeof(*cfg)); |
2141 | 2169 | ||
2142 | memset(sequences, 0, sizeof(sequences)); | 2170 | memset(sequences_line_out, 0, sizeof(sequences_line_out)); |
2143 | assoc_line_out = 0; | 2171 | memset(sequences_speaker, 0, sizeof(sequences_speaker)); |
2172 | assoc_line_out = assoc_speaker = 0; | ||
2144 | 2173 | ||
2145 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | 2174 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); |
2146 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | 2175 | for (nid = nid_start; nid < nodes + nid_start; nid++) { |
@@ -2175,13 +2204,22 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2175 | if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) | 2204 | if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) |
2176 | continue; | 2205 | continue; |
2177 | cfg->line_out_pins[cfg->line_outs] = nid; | 2206 | cfg->line_out_pins[cfg->line_outs] = nid; |
2178 | sequences[cfg->line_outs] = seq; | 2207 | sequences_line_out[cfg->line_outs] = seq; |
2179 | cfg->line_outs++; | 2208 | cfg->line_outs++; |
2180 | break; | 2209 | break; |
2181 | case AC_JACK_SPEAKER: | 2210 | case AC_JACK_SPEAKER: |
2211 | seq = get_defcfg_sequence(def_conf); | ||
2212 | assoc = get_defcfg_association(def_conf); | ||
2213 | if (! assoc) | ||
2214 | continue; | ||
2215 | if (! assoc_speaker) | ||
2216 | assoc_speaker = assoc; | ||
2217 | else if (assoc_speaker != assoc) | ||
2218 | continue; | ||
2182 | if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) | 2219 | if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) |
2183 | continue; | 2220 | continue; |
2184 | cfg->speaker_pins[cfg->speaker_outs] = nid; | 2221 | cfg->speaker_pins[cfg->speaker_outs] = nid; |
2222 | sequences_speaker[cfg->speaker_outs] = seq; | ||
2185 | cfg->speaker_outs++; | 2223 | cfg->speaker_outs++; |
2186 | break; | 2224 | break; |
2187 | case AC_JACK_HP_OUT: | 2225 | case AC_JACK_HP_OUT: |
@@ -2227,16 +2265,32 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2227 | } | 2265 | } |
2228 | 2266 | ||
2229 | /* sort by sequence */ | 2267 | /* sort by sequence */ |
2230 | for (i = 0; i < cfg->line_outs; i++) | 2268 | sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out, |
2231 | for (j = i + 1; j < cfg->line_outs; j++) | 2269 | cfg->line_outs); |
2232 | if (sequences[i] > sequences[j]) { | 2270 | sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker, |
2233 | seq = sequences[i]; | 2271 | cfg->speaker_outs); |
2234 | sequences[i] = sequences[j]; | 2272 | |
2235 | sequences[j] = seq; | 2273 | /* |
2236 | nid = cfg->line_out_pins[i]; | 2274 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin |
2237 | cfg->line_out_pins[i] = cfg->line_out_pins[j]; | 2275 | * as a primary output |
2238 | cfg->line_out_pins[j] = nid; | 2276 | */ |
2239 | } | 2277 | if (!cfg->line_outs) { |
2278 | if (cfg->speaker_outs) { | ||
2279 | cfg->line_outs = cfg->speaker_outs; | ||
2280 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
2281 | sizeof(cfg->speaker_pins)); | ||
2282 | cfg->speaker_outs = 0; | ||
2283 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
2284 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; | ||
2285 | } else if (cfg->hp_outs) { | ||
2286 | cfg->line_outs = cfg->hp_outs; | ||
2287 | memcpy(cfg->line_out_pins, cfg->hp_pins, | ||
2288 | sizeof(cfg->hp_pins)); | ||
2289 | cfg->hp_outs = 0; | ||
2290 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2291 | cfg->line_out_type = AUTO_PIN_HP_OUT; | ||
2292 | } | ||
2293 | } | ||
2240 | 2294 | ||
2241 | /* Reorder the surround channels | 2295 | /* Reorder the surround channels |
2242 | * ALSA sequence is front/surr/clfe/side | 2296 | * ALSA sequence is front/surr/clfe/side |
@@ -2278,28 +2332,6 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
2278 | cfg->input_pins[AUTO_PIN_CD], | 2332 | cfg->input_pins[AUTO_PIN_CD], |
2279 | cfg->input_pins[AUTO_PIN_AUX]); | 2333 | cfg->input_pins[AUTO_PIN_AUX]); |
2280 | 2334 | ||
2281 | /* | ||
2282 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | ||
2283 | * as a primary output | ||
2284 | */ | ||
2285 | if (!cfg->line_outs) { | ||
2286 | if (cfg->speaker_outs) { | ||
2287 | cfg->line_outs = cfg->speaker_outs; | ||
2288 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
2289 | sizeof(cfg->speaker_pins)); | ||
2290 | cfg->speaker_outs = 0; | ||
2291 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
2292 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; | ||
2293 | } else if (cfg->hp_outs) { | ||
2294 | cfg->line_outs = cfg->hp_outs; | ||
2295 | memcpy(cfg->line_out_pins, cfg->hp_pins, | ||
2296 | sizeof(cfg->hp_pins)); | ||
2297 | cfg->hp_outs = 0; | ||
2298 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2299 | cfg->line_out_type = AUTO_PIN_HP_OUT; | ||
2300 | } | ||
2301 | } | ||
2302 | |||
2303 | return 0; | 2335 | return 0; |
2304 | } | 2336 | } |
2305 | 2337 | ||