aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_codec.c106
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 */
2119static 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