aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_generic.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-07 11:25:08 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-12 02:44:11 -0500
commit3ca529d339f1904b68c6251172522302fca77b28 (patch)
treea56c0a41db62e26cdec6bce9d284edcb0af5304d /sound/pci/hda/hda_generic.c
parentc697b716859c6c8c4e9f102304638c83ff2e61aa (diff)
ALSA: hda - Re-define snd_hda_parse_nid_path()
This commit modifies the definition of snd_hda_parse_nid_path() slightly, now with_aa_mix argument is changed to anchor_nid, so that it can handle any NID generically as an anchor point to include or exclude. The with_aa_mix field in struct nid_path is removed again by this change. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r--sound/pci/hda/hda_generic.c102
1 files changed, 55 insertions, 47 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 7861c3af6ae0..8e7ce7d2c138 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -87,9 +87,25 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
87 * parsing paths 87 * parsing paths
88 */ 88 */
89 89
90/* return the position of NID in the list, or -1 if not found */
91static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
92{
93 int i;
94 for (i = 0; i < nums; i++)
95 if (list[i] == nid)
96 return i;
97 return -1;
98}
99
100/* return true if the given NID is contained in the path */
101static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
102{
103 return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
104}
105
90static struct nid_path *get_nid_path(struct hda_codec *codec, 106static struct nid_path *get_nid_path(struct hda_codec *codec,
91 hda_nid_t from_nid, hda_nid_t to_nid, 107 hda_nid_t from_nid, hda_nid_t to_nid,
92 int with_aa_mix) 108 int anchor_nid)
93{ 109{
94 struct hda_gen_spec *spec = codec->spec; 110 struct hda_gen_spec *spec = codec->spec;
95 int i; 111 int i;
@@ -100,8 +116,9 @@ static struct nid_path *get_nid_path(struct hda_codec *codec,
100 continue; 116 continue;
101 if ((!from_nid || path->path[0] == from_nid) && 117 if ((!from_nid || path->path[0] == from_nid) &&
102 (!to_nid || path->path[path->depth - 1] == to_nid)) { 118 (!to_nid || path->path[path->depth - 1] == to_nid)) {
103 if (with_aa_mix == HDA_PARSE_ALL || 119 if (!anchor_nid ||
104 path->with_aa_mix == with_aa_mix) 120 (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
121 (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
105 return path; 122 return path;
106 } 123 }
107 } 124 }
@@ -114,7 +131,7 @@ static struct nid_path *get_nid_path(struct hda_codec *codec,
114struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec, 131struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
115 hda_nid_t from_nid, hda_nid_t to_nid) 132 hda_nid_t from_nid, hda_nid_t to_nid)
116{ 133{
117 return get_nid_path(codec, from_nid, to_nid, HDA_PARSE_ALL); 134 return get_nid_path(codec, from_nid, to_nid, 0);
118} 135}
119EXPORT_SYMBOL_HDA(snd_hda_get_nid_path); 136EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
120 137
@@ -213,17 +230,16 @@ static void print_nid_path(const char *pfx, struct nid_path *path)
213/* called recursively */ 230/* called recursively */
214static bool __parse_nid_path(struct hda_codec *codec, 231static bool __parse_nid_path(struct hda_codec *codec,
215 hda_nid_t from_nid, hda_nid_t to_nid, 232 hda_nid_t from_nid, hda_nid_t to_nid,
216 int with_aa_mix, struct nid_path *path, int depth) 233 int anchor_nid, struct nid_path *path,
234 int depth)
217{ 235{
218 struct hda_gen_spec *spec = codec->spec;
219 const hda_nid_t *conn; 236 const hda_nid_t *conn;
220 int i, nums; 237 int i, nums;
221 238
222 if (to_nid == spec->mixer_nid) { 239 if (to_nid == anchor_nid)
223 if (with_aa_mix == HDA_PARSE_NO_AAMIX) 240 anchor_nid = 0; /* anchor passed */
224 return false; 241 else if (to_nid == (hda_nid_t)(-anchor_nid))
225 with_aa_mix = HDA_PARSE_ALL; /* mark aa-mix is included */ 242 return false; /* hit the exclusive nid */
226 }
227 243
228 nums = snd_hda_get_conn_list(codec, to_nid, &conn); 244 nums = snd_hda_get_conn_list(codec, to_nid, &conn);
229 for (i = 0; i < nums; i++) { 245 for (i = 0; i < nums; i++) {
@@ -236,8 +252,8 @@ static bool __parse_nid_path(struct hda_codec *codec,
236 is_dac_already_used(codec, conn[i])) 252 is_dac_already_used(codec, conn[i]))
237 continue; 253 continue;
238 } 254 }
239 /* aa-mix is requested but not included? */ 255 /* anchor is not requested or already passed? */
240 if (!(spec->mixer_nid && with_aa_mix == HDA_PARSE_ONLY_AAMIX)) 256 if (anchor_nid <= 0)
241 goto found; 257 goto found;
242 } 258 }
243 if (depth >= MAX_NID_PATH_DEPTH) 259 if (depth >= MAX_NID_PATH_DEPTH)
@@ -249,15 +265,13 @@ static bool __parse_nid_path(struct hda_codec *codec,
249 type == AC_WID_PIN) 265 type == AC_WID_PIN)
250 continue; 266 continue;
251 if (__parse_nid_path(codec, from_nid, conn[i], 267 if (__parse_nid_path(codec, from_nid, conn[i],
252 with_aa_mix, path, depth + 1)) 268 anchor_nid, path, depth + 1))
253 goto found; 269 goto found;
254 } 270 }
255 return false; 271 return false;
256 272
257 found: 273 found:
258 path->path[path->depth] = conn[i]; 274 path->path[path->depth] = conn[i];
259 if (conn[i] == spec->mixer_nid)
260 path->with_aa_mix = true;
261 path->idx[path->depth + 1] = i; 275 path->idx[path->depth + 1] = i;
262 if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX) 276 if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
263 path->multi[path->depth + 1] = 1; 277 path->multi[path->depth + 1] = 1;
@@ -267,17 +281,17 @@ static bool __parse_nid_path(struct hda_codec *codec,
267 281
268/* parse the widget path from the given nid to the target nid; 282/* parse the widget path from the given nid to the target nid;
269 * when @from_nid is 0, try to find an empty DAC; 283 * when @from_nid is 0, try to find an empty DAC;
270 * when @with_aa_mix is HDA_PARSE_NO_AAMIX, paths with spec->mixer_nid are 284 * when @anchor_nid is set to a positive value, only paths through the widget
271 * excluded, only the paths that don't go through the mixer will be chosen. 285 * with the given value are evaluated.
272 * when @with_aa_mix is HDA_PARSE_ONLY_AAMIX, only the paths going through 286 * when @anchor_nid is set to a negative value, paths through the widget
273 * spec->mixer_nid will be chosen. 287 * with the negative of given value are excluded, only other paths are chosen.
274 * when @with_aa_mix is HDA_PARSE_ALL, no special handling about mixer widget. 288 * when @anchor_nid is zero, no special handling about path selection.
275 */ 289 */
276bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid, 290bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
277 hda_nid_t to_nid, int with_aa_mix, 291 hda_nid_t to_nid, int anchor_nid,
278 struct nid_path *path) 292 struct nid_path *path)
279{ 293{
280 if (__parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path, 1)) { 294 if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
281 path->path[path->depth] = to_nid; 295 path->path[path->depth] = to_nid;
282 path->depth++; 296 path->depth++;
283 return true; 297 return true;
@@ -292,7 +306,7 @@ EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
292 */ 306 */
293struct nid_path * 307struct nid_path *
294snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid, 308snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
295 hda_nid_t to_nid, int with_aa_mix) 309 hda_nid_t to_nid, int anchor_nid)
296{ 310{
297 struct hda_gen_spec *spec = codec->spec; 311 struct hda_gen_spec *spec = codec->spec;
298 struct nid_path *path; 312 struct nid_path *path;
@@ -301,7 +315,7 @@ snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
301 return NULL; 315 return NULL;
302 316
303 /* check whether the path has been already added */ 317 /* check whether the path has been already added */
304 path = get_nid_path(codec, from_nid, to_nid, with_aa_mix); 318 path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
305 if (path) 319 if (path)
306 return path; 320 return path;
307 321
@@ -309,7 +323,7 @@ snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
309 if (!path) 323 if (!path)
310 return NULL; 324 return NULL;
311 memset(path, 0, sizeof(*path)); 325 memset(path, 0, sizeof(*path));
312 if (snd_hda_parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path)) 326 if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
313 return path; 327 return path;
314 /* push back */ 328 /* push back */
315 spec->paths.used--; 329 spec->paths.used--;
@@ -909,10 +923,10 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
909 else 923 else
910 badness += bad->no_dac; 924 badness += bad->no_dac;
911 } 925 }
912 path = snd_hda_add_new_path(codec, dac, pin, HDA_PARSE_NO_AAMIX); 926 path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
913 if (!path && !i && spec->mixer_nid) { 927 if (!path && !i && spec->mixer_nid) {
914 /* try with aamix */ 928 /* try with aamix */
915 path = snd_hda_add_new_path(codec, dac, pin, HDA_PARSE_ALL); 929 path = snd_hda_add_new_path(codec, dac, pin, 0);
916 } 930 }
917 if (!path) 931 if (!path)
918 dac = dacs[i] = 0; 932 dac = dacs[i] = 0;
@@ -1038,7 +1052,8 @@ static int fill_multi_ios(struct hda_codec *codec,
1038 badness++; 1052 badness++;
1039 continue; 1053 continue;
1040 } 1054 }
1041 path = snd_hda_add_new_path(codec, dac, nid, HDA_PARSE_NO_AAMIX); 1055 path = snd_hda_add_new_path(codec, dac, nid,
1056 -spec->mixer_nid);
1042 if (!path) { 1057 if (!path) {
1043 badness++; 1058 badness++;
1044 continue; 1059 continue;
@@ -1093,9 +1108,10 @@ static bool map_singles(struct hda_codec *codec, int outs,
1093 dac = get_dac_if_single(codec, pins[i]); 1108 dac = get_dac_if_single(codec, pins[i]);
1094 if (!dac) 1109 if (!dac)
1095 continue; 1110 continue;
1096 path = snd_hda_add_new_path(codec, dac, pins[i], HDA_PARSE_NO_AAMIX); 1111 path = snd_hda_add_new_path(codec, dac, pins[i],
1112 -spec->mixer_nid);
1097 if (!path && !i && spec->mixer_nid) 1113 if (!path && !i && spec->mixer_nid)
1098 path = snd_hda_add_new_path(codec, dac, pins[i], HDA_PARSE_ALL); 1114 path = snd_hda_add_new_path(codec, dac, pins[i], 0);
1099 if (path) { 1115 if (path) {
1100 dacs[i] = dac; 1116 dacs[i] = dac;
1101 found = true; 1117 found = true;
@@ -1110,14 +1126,16 @@ static bool map_singles(struct hda_codec *codec, int outs,
1110/* create a new path including aamix if available, and return its index */ 1126/* create a new path including aamix if available, and return its index */
1111static int check_aamix_out_path(struct hda_codec *codec, int path_idx) 1127static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1112{ 1128{
1129 struct hda_gen_spec *spec = codec->spec;
1113 struct nid_path *path; 1130 struct nid_path *path;
1114 1131
1115 path = snd_hda_get_path_from_idx(codec, path_idx); 1132 path = snd_hda_get_path_from_idx(codec, path_idx);
1116 if (!path || !path->depth || path->with_aa_mix) 1133 if (!path || !path->depth ||
1134 is_nid_contained(path, spec->mixer_nid))
1117 return 0; 1135 return 0;
1118 path = snd_hda_add_new_path(codec, path->path[0], 1136 path = snd_hda_add_new_path(codec, path->path[0],
1119 path->path[path->depth - 1], 1137 path->path[path->depth - 1],
1120 HDA_PARSE_ONLY_AAMIX); 1138 spec->mixer_nid);
1121 if (!path) 1139 if (!path)
1122 return 0; 1140 return 0;
1123 print_nid_path("output-aamix", path); 1141 print_nid_path("output-aamix", path);
@@ -1919,7 +1937,7 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
1919 !nid_has_mute(codec, mix_nid, HDA_INPUT)) 1937 !nid_has_mute(codec, mix_nid, HDA_INPUT))
1920 return 0; /* no need for analog loopback */ 1938 return 0; /* no need for analog loopback */
1921 1939
1922 path = snd_hda_add_new_path(codec, pin, mix_nid, HDA_PARSE_ALL); 1940 path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
1923 if (!path) 1941 if (!path)
1924 return -EINVAL; 1942 return -EINVAL;
1925 print_nid_path("loopback", path); 1943 print_nid_path("loopback", path);
@@ -2092,7 +2110,7 @@ static int create_input_ctls(struct hda_codec *codec)
2092 2110
2093 if (!is_reachable_path(codec, pin, adc)) 2111 if (!is_reachable_path(codec, pin, adc))
2094 continue; 2112 continue;
2095 path = snd_hda_add_new_path(codec, pin, adc, HDA_PARSE_ALL); 2113 path = snd_hda_add_new_path(codec, pin, adc, 0);
2096 if (!path) { 2114 if (!path) {
2097 snd_printd(KERN_ERR 2115 snd_printd(KERN_ERR
2098 "invalid input path 0x%x -> 0x%x\n", 2116 "invalid input path 0x%x -> 0x%x\n",
@@ -2567,7 +2585,7 @@ static void parse_digital(struct hda_codec *codec)
2567 dig_nid = look_for_dac(codec, pin, true); 2585 dig_nid = look_for_dac(codec, pin, true);
2568 if (!dig_nid) 2586 if (!dig_nid)
2569 continue; 2587 continue;
2570 path = snd_hda_add_new_path(codec, dig_nid, pin, HDA_PARSE_ALL); 2588 path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
2571 if (!path) 2589 if (!path)
2572 continue; 2590 continue;
2573 print_nid_path("digout", path); 2591 print_nid_path("digout", path);
@@ -2595,7 +2613,7 @@ static void parse_digital(struct hda_codec *codec)
2595 continue; 2613 continue;
2596 path = snd_hda_add_new_path(codec, 2614 path = snd_hda_add_new_path(codec,
2597 spec->autocfg.dig_in_pin, 2615 spec->autocfg.dig_in_pin,
2598 dig_nid, HDA_PARSE_ALL); 2616 dig_nid, 0);
2599 if (path) { 2617 if (path) {
2600 print_nid_path("digin", path); 2618 print_nid_path("digin", path);
2601 path->active = true; 2619 path->active = true;
@@ -2971,16 +2989,6 @@ static int check_auto_mute_availability(struct hda_codec *codec)
2971 return 0; 2989 return 0;
2972} 2990}
2973 2991
2974/* return the position of NID in the list, or -1 if not found */
2975static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2976{
2977 int i;
2978 for (i = 0; i < nums; i++)
2979 if (list[i] == nid)
2980 return i;
2981 return -1;
2982}
2983
2984/* check whether all auto-mic pins are valid; setup indices if OK */ 2992/* check whether all auto-mic pins are valid; setup indices if OK */
2985static bool auto_mic_check_imux(struct hda_codec *codec) 2993static bool auto_mic_check_imux(struct hda_codec *codec)
2986{ 2994{