diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-01-07 11:25:08 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-12 02:44:11 -0500 |
commit | 3ca529d339f1904b68c6251172522302fca77b28 (patch) | |
tree | a56c0a41db62e26cdec6bce9d284edcb0af5304d /sound/pci/hda/hda_generic.c | |
parent | c697b716859c6c8c4e9f102304638c83ff2e61aa (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.c | 102 |
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 */ | ||
91 | static 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 */ | ||
101 | static 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 | |||
90 | static struct nid_path *get_nid_path(struct hda_codec *codec, | 106 | static 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, | |||
114 | struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec, | 131 | struct 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 | } |
119 | EXPORT_SYMBOL_HDA(snd_hda_get_nid_path); | 136 | EXPORT_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 */ |
214 | static bool __parse_nid_path(struct hda_codec *codec, | 231 | static 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 | */ |
276 | bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid, | 290 | bool 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 | */ |
293 | struct nid_path * | 307 | struct nid_path * |
294 | snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid, | 308 | snd_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 */ |
1111 | static int check_aamix_out_path(struct hda_codec *codec, int path_idx) | 1127 | static 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 */ | ||
2975 | static 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 */ |
2985 | static bool auto_mic_check_imux(struct hda_codec *codec) | 2993 | static bool auto_mic_check_imux(struct hda_codec *codec) |
2986 | { | 2994 | { |