diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 916a1863af73..4562e9de6a1a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2331,6 +2331,39 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2331 | return 0; | 2331 | return 0; |
2332 | } | 2332 | } |
2333 | 2333 | ||
2334 | typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); | ||
2335 | |||
2336 | /* apply the function to all matching slave ctls in the mixer list */ | ||
2337 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, | ||
2338 | map_slave_func_t func, void *data) | ||
2339 | { | ||
2340 | struct hda_nid_item *items; | ||
2341 | const char * const *s; | ||
2342 | int i, err; | ||
2343 | |||
2344 | items = codec->mixers.list; | ||
2345 | for (i = 0; i < codec->mixers.used; i++) { | ||
2346 | struct snd_kcontrol *sctl = items[i].kctl; | ||
2347 | if (!sctl || !sctl->id.name || | ||
2348 | sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) | ||
2349 | continue; | ||
2350 | for (s = slaves; *s; s++) { | ||
2351 | if (!strcmp(sctl->id.name, *s)) { | ||
2352 | err = func(data, sctl); | ||
2353 | if (err) | ||
2354 | return err; | ||
2355 | break; | ||
2356 | } | ||
2357 | } | ||
2358 | } | ||
2359 | return 0; | ||
2360 | } | ||
2361 | |||
2362 | static int check_slave_present(void *data, struct snd_kcontrol *sctl) | ||
2363 | { | ||
2364 | return 1; | ||
2365 | } | ||
2366 | |||
2334 | /** | 2367 | /** |
2335 | * snd_hda_add_vmaster - create a virtual master control and add slaves | 2368 | * snd_hda_add_vmaster - create a virtual master control and add slaves |
2336 | * @codec: HD-audio codec | 2369 | * @codec: HD-audio codec |
@@ -2351,12 +2384,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2351 | unsigned int *tlv, const char * const *slaves) | 2384 | unsigned int *tlv, const char * const *slaves) |
2352 | { | 2385 | { |
2353 | struct snd_kcontrol *kctl; | 2386 | struct snd_kcontrol *kctl; |
2354 | const char * const *s; | ||
2355 | int err; | 2387 | int err; |
2356 | 2388 | ||
2357 | for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++) | 2389 | err = map_slaves(codec, slaves, check_slave_present, NULL); |
2358 | ; | 2390 | if (err != 1) { |
2359 | if (!*s) { | ||
2360 | snd_printdd("No slave found for %s\n", name); | 2391 | snd_printdd("No slave found for %s\n", name); |
2361 | return 0; | 2392 | return 0; |
2362 | } | 2393 | } |
@@ -2367,23 +2398,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2367 | if (err < 0) | 2398 | if (err < 0) |
2368 | return err; | 2399 | return err; |
2369 | 2400 | ||
2370 | for (s = slaves; *s; s++) { | 2401 | err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, |
2371 | struct snd_kcontrol *sctl; | 2402 | kctl); |
2372 | int i = 0; | 2403 | if (err < 0) |
2373 | for (;;) { | 2404 | return err; |
2374 | sctl = _snd_hda_find_mixer_ctl(codec, *s, i); | ||
2375 | if (!sctl) { | ||
2376 | if (!i) | ||
2377 | snd_printdd("Cannot find slave %s, " | ||
2378 | "skipped\n", *s); | ||
2379 | break; | ||
2380 | } | ||
2381 | err = snd_ctl_add_slave(kctl, sctl); | ||
2382 | if (err < 0) | ||
2383 | return err; | ||
2384 | i++; | ||
2385 | } | ||
2386 | } | ||
2387 | return 0; | 2405 | return 0; |
2388 | } | 2406 | } |
2389 | EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); | 2407 | EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); |
@@ -4028,9 +4046,9 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, | |||
4028 | 4046 | ||
4029 | /* Search for codec ID */ | 4047 | /* Search for codec ID */ |
4030 | for (q = tbl; q->subvendor; q++) { | 4048 | for (q = tbl; q->subvendor; q++) { |
4031 | unsigned long vendorid = (q->subdevice) | (q->subvendor << 16); | 4049 | unsigned int mask = 0xffff0000 | q->subdevice_mask; |
4032 | 4050 | unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask; | |
4033 | if (vendorid == codec->subsystem_id) | 4051 | if ((codec->subsystem_id & mask) == id) |
4034 | break; | 4052 | break; |
4035 | } | 4053 | } |
4036 | 4054 | ||
@@ -4752,6 +4770,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
4752 | memset(sequences_hp, 0, sizeof(sequences_hp)); | 4770 | memset(sequences_hp, 0, sizeof(sequences_hp)); |
4753 | assoc_line_out = 0; | 4771 | assoc_line_out = 0; |
4754 | 4772 | ||
4773 | codec->ignore_misc_bit = true; | ||
4755 | end_nid = codec->start_nid + codec->num_nodes; | 4774 | end_nid = codec->start_nid + codec->num_nodes; |
4756 | for (nid = codec->start_nid; nid < end_nid; nid++) { | 4775 | for (nid = codec->start_nid; nid < end_nid; nid++) { |
4757 | unsigned int wid_caps = get_wcaps(codec, nid); | 4776 | unsigned int wid_caps = get_wcaps(codec, nid); |
@@ -4767,6 +4786,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
4767 | continue; | 4786 | continue; |
4768 | 4787 | ||
4769 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 4788 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
4789 | if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
4790 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
4791 | codec->ignore_misc_bit = false; | ||
4770 | conn = get_defcfg_connect(def_conf); | 4792 | conn = get_defcfg_connect(def_conf); |
4771 | if (conn == AC_JACK_PORT_NONE) | 4793 | if (conn == AC_JACK_PORT_NONE) |
4772 | continue; | 4794 | continue; |