diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 17 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 79 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 16 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 31 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 37 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 10 | ||||
-rw-r--r-- | sound/pci/hda/patch_cmedia.c | 12 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 125 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 7 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 275 |
14 files changed, 456 insertions, 159 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 139cf3b2b9d7..e288a5595f34 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -544,25 +544,10 @@ static int patch_wolfson04(struct snd_ac97 * ac97) | |||
544 | return 0; | 544 | return 0; |
545 | } | 545 | } |
546 | 546 | ||
547 | static int patch_wolfson_wm9705_specific(struct snd_ac97 * ac97) | ||
548 | { | ||
549 | int err, i; | ||
550 | for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) { | ||
551 | if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0) | ||
552 | return err; | ||
553 | } | ||
554 | snd_ac97_write_cache(ac97, 0x72, 0x0808); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = { | ||
559 | .build_specific = patch_wolfson_wm9705_specific, | ||
560 | }; | ||
561 | |||
562 | static int patch_wolfson05(struct snd_ac97 * ac97) | 547 | static int patch_wolfson05(struct snd_ac97 * ac97) |
563 | { | 548 | { |
564 | /* WM9705, WM9710 */ | 549 | /* WM9705, WM9710 */ |
565 | ac97->build_ops = &patch_wolfson_wm9705_ops; | 550 | ac97->build_ops = &patch_wolfson_wm9703_ops; |
566 | #ifdef CONFIG_TOUCHSCREEN_WM9705 | 551 | #ifdef CONFIG_TOUCHSCREEN_WM9705 |
567 | /* WM9705 touchscreen uses AUX and VIDEO for touch */ | 552 | /* WM9705 touchscreen uses AUX and VIDEO for touch */ |
568 | ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; | 553 | ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 950ee5cfcacf..d2f10b1c3a8a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -931,6 +931,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
931 | #endif | 931 | #endif |
932 | list_del(&codec->list); | 932 | list_del(&codec->list); |
933 | snd_array_free(&codec->mixers); | 933 | snd_array_free(&codec->mixers); |
934 | snd_array_free(&codec->nids); | ||
934 | codec->bus->caddr_tbl[codec->addr] = NULL; | 935 | codec->bus->caddr_tbl[codec->addr] = NULL; |
935 | if (codec->patch_ops.free) | 936 | if (codec->patch_ops.free) |
936 | codec->patch_ops.free(codec); | 937 | codec->patch_ops.free(codec); |
@@ -985,7 +986,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
985 | mutex_init(&codec->control_mutex); | 986 | mutex_init(&codec->control_mutex); |
986 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 987 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
987 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 988 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
988 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60); | 989 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); |
990 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); | ||
989 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | 991 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); |
990 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | 992 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); |
991 | if (codec->bus->modelname) { | 993 | if (codec->bus->modelname) { |
@@ -1706,7 +1708,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1706 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | 1708 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); |
1707 | 1709 | ||
1708 | /** | 1710 | /** |
1709 | * snd_hda_ctl-add - Add a control element and assign to the codec | 1711 | * snd_hda_ctl_add - Add a control element and assign to the codec |
1710 | * @codec: HD-audio codec | 1712 | * @codec: HD-audio codec |
1711 | * @nid: corresponding NID (optional) | 1713 | * @nid: corresponding NID (optional) |
1712 | * @kctl: the control element to assign | 1714 | * @kctl: the control element to assign |
@@ -1721,19 +1723,25 @@ EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | |||
1721 | * | 1723 | * |
1722 | * snd_hda_ctl_add() checks the control subdev id field whether | 1724 | * snd_hda_ctl_add() checks the control subdev id field whether |
1723 | * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower | 1725 | * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower |
1724 | * bits value is taken as the NID to assign. | 1726 | * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit |
1727 | * specifies if kctl->private_value is a HDA amplifier value. | ||
1725 | */ | 1728 | */ |
1726 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | 1729 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, |
1727 | struct snd_kcontrol *kctl) | 1730 | struct snd_kcontrol *kctl) |
1728 | { | 1731 | { |
1729 | int err; | 1732 | int err; |
1733 | unsigned short flags = 0; | ||
1730 | struct hda_nid_item *item; | 1734 | struct hda_nid_item *item; |
1731 | 1735 | ||
1732 | if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) { | 1736 | if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) { |
1737 | flags |= HDA_NID_ITEM_AMP; | ||
1733 | if (nid == 0) | 1738 | if (nid == 0) |
1734 | nid = kctl->id.subdevice & 0xffff; | 1739 | nid = get_amp_nid_(kctl->private_value); |
1735 | kctl->id.subdevice = 0; | ||
1736 | } | 1740 | } |
1741 | if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0) | ||
1742 | nid = kctl->id.subdevice & 0xffff; | ||
1743 | if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG)) | ||
1744 | kctl->id.subdevice = 0; | ||
1737 | err = snd_ctl_add(codec->bus->card, kctl); | 1745 | err = snd_ctl_add(codec->bus->card, kctl); |
1738 | if (err < 0) | 1746 | if (err < 0) |
1739 | return err; | 1747 | return err; |
@@ -1742,11 +1750,41 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | |||
1742 | return -ENOMEM; | 1750 | return -ENOMEM; |
1743 | item->kctl = kctl; | 1751 | item->kctl = kctl; |
1744 | item->nid = nid; | 1752 | item->nid = nid; |
1753 | item->flags = flags; | ||
1745 | return 0; | 1754 | return 0; |
1746 | } | 1755 | } |
1747 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); | 1756 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); |
1748 | 1757 | ||
1749 | /** | 1758 | /** |
1759 | * snd_hda_add_nid - Assign a NID to a control element | ||
1760 | * @codec: HD-audio codec | ||
1761 | * @nid: corresponding NID (optional) | ||
1762 | * @kctl: the control element to assign | ||
1763 | * @index: index to kctl | ||
1764 | * | ||
1765 | * Add the given control element to an array inside the codec instance. | ||
1766 | * This function is used when #snd_hda_ctl_add cannot be used for 1:1 | ||
1767 | * NID:KCTL mapping - for example "Capture Source" selector. | ||
1768 | */ | ||
1769 | int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
1770 | unsigned int index, hda_nid_t nid) | ||
1771 | { | ||
1772 | struct hda_nid_item *item; | ||
1773 | |||
1774 | if (nid > 0) { | ||
1775 | item = snd_array_new(&codec->nids); | ||
1776 | if (!item) | ||
1777 | return -ENOMEM; | ||
1778 | item->kctl = kctl; | ||
1779 | item->index = index; | ||
1780 | item->nid = nid; | ||
1781 | return 0; | ||
1782 | } | ||
1783 | return -EINVAL; | ||
1784 | } | ||
1785 | EXPORT_SYMBOL_HDA(snd_hda_add_nid); | ||
1786 | |||
1787 | /** | ||
1750 | * snd_hda_ctls_clear - Clear all controls assigned to the given codec | 1788 | * snd_hda_ctls_clear - Clear all controls assigned to the given codec |
1751 | * @codec: HD-audio codec | 1789 | * @codec: HD-audio codec |
1752 | */ | 1790 | */ |
@@ -1757,6 +1795,7 @@ void snd_hda_ctls_clear(struct hda_codec *codec) | |||
1757 | for (i = 0; i < codec->mixers.used; i++) | 1795 | for (i = 0; i < codec->mixers.used; i++) |
1758 | snd_ctl_remove(codec->bus->card, items[i].kctl); | 1796 | snd_ctl_remove(codec->bus->card, items[i].kctl); |
1759 | snd_array_free(&codec->mixers); | 1797 | snd_array_free(&codec->mixers); |
1798 | snd_array_free(&codec->nids); | ||
1760 | } | 1799 | } |
1761 | 1800 | ||
1762 | /* pseudo device locking | 1801 | /* pseudo device locking |
@@ -3476,6 +3515,8 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
3476 | 3515 | ||
3477 | for (; knew->name; knew++) { | 3516 | for (; knew->name; knew++) { |
3478 | struct snd_kcontrol *kctl; | 3517 | struct snd_kcontrol *kctl; |
3518 | if (knew->iface == -1) /* skip this codec private value */ | ||
3519 | continue; | ||
3479 | kctl = snd_ctl_new1(knew, codec); | 3520 | kctl = snd_ctl_new1(knew, codec); |
3480 | if (!kctl) | 3521 | if (!kctl) |
3481 | return -ENOMEM; | 3522 | return -ENOMEM; |
@@ -3496,6 +3537,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
3496 | } | 3537 | } |
3497 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); | 3538 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); |
3498 | 3539 | ||
3540 | /** | ||
3541 | * snd_hda_add_nids - assign nids to controls from the array | ||
3542 | * @codec: the HDA codec | ||
3543 | * @kctl: struct snd_kcontrol | ||
3544 | * @index: index to kctl | ||
3545 | * @nids: the array of hda_nid_t | ||
3546 | * @size: count of hda_nid_t items | ||
3547 | * | ||
3548 | * This helper function assigns NIDs in the given array to a control element. | ||
3549 | * | ||
3550 | * Returns 0 if successful, or a negative error code. | ||
3551 | */ | ||
3552 | int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
3553 | unsigned int index, hda_nid_t *nids, unsigned int size) | ||
3554 | { | ||
3555 | int err; | ||
3556 | |||
3557 | for ( ; size > 0; size--, nids++) { | ||
3558 | err = snd_hda_add_nid(codec, kctl, index, *nids); | ||
3559 | if (err < 0) | ||
3560 | return err; | ||
3561 | } | ||
3562 | return 0; | ||
3563 | } | ||
3564 | EXPORT_SYMBOL_HDA(snd_hda_add_nids); | ||
3565 | |||
3499 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3566 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
3500 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 3567 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
3501 | unsigned int power_state); | 3568 | unsigned int power_state); |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 1d541b7f5547..0d08ad5bd898 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -789,6 +789,7 @@ struct hda_codec { | |||
789 | u32 *wcaps; | 789 | u32 *wcaps; |
790 | 790 | ||
791 | struct snd_array mixers; /* list of assigned mixer elements */ | 791 | struct snd_array mixers; /* list of assigned mixer elements */ |
792 | struct snd_array nids; /* list of mapped mixer elements */ | ||
792 | 793 | ||
793 | struct hda_cache_rec amp_cache; /* cache for amp access */ | 794 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
794 | struct hda_cache_rec cmd_cache; /* cache for other commands */ | 795 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 092c6a7c2ff3..5ea21285ee1f 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -861,7 +861,8 @@ static int build_input_controls(struct hda_codec *codec) | |||
861 | } | 861 | } |
862 | 862 | ||
863 | /* create input MUX if multiple sources are available */ | 863 | /* create input MUX if multiple sources are available */ |
864 | err = snd_hda_ctl_add(codec, 0, snd_ctl_new1(&cap_sel, codec)); | 864 | err = snd_hda_ctl_add(codec, spec->adc_node->nid, |
865 | snd_ctl_new1(&cap_sel, codec)); | ||
865 | if (err < 0) | 866 | if (err < 0) |
866 | return err; | 867 | return err; |
867 | 868 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 5778ae882b83..d505d052972e 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -31,6 +31,7 @@ | |||
31 | * in snd_hda_ctl_add(), so that this value won't appear in the outside. | 31 | * in snd_hda_ctl_add(), so that this value won't appear in the outside. |
32 | */ | 32 | */ |
33 | #define HDA_SUBDEV_NID_FLAG (1U << 31) | 33 | #define HDA_SUBDEV_NID_FLAG (1U << 31) |
34 | #define HDA_SUBDEV_AMP_FLAG (1U << 30) | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * for mixer controls | 37 | * for mixer controls |
@@ -42,7 +43,7 @@ | |||
42 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 43 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
43 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 44 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
44 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 45 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
45 | .subdevice = HDA_SUBDEV_NID_FLAG | (nid), \ | 46 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ |
46 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | 47 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ |
47 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | 48 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ |
48 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | 49 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ |
@@ -63,7 +64,7 @@ | |||
63 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ | 64 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ |
64 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 65 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
65 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 66 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
66 | .subdevice = HDA_SUBDEV_NID_FLAG | (nid), \ | 67 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ |
67 | .info = snd_hda_mixer_amp_switch_info, \ | 68 | .info = snd_hda_mixer_amp_switch_info, \ |
68 | .get = snd_hda_mixer_amp_switch_get, \ | 69 | .get = snd_hda_mixer_amp_switch_get, \ |
69 | .put = snd_hda_mixer_amp_switch_put, \ | 70 | .put = snd_hda_mixer_amp_switch_put, \ |
@@ -81,7 +82,7 @@ | |||
81 | /* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */ | 82 | /* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */ |
82 | #define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 83 | #define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
83 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 84 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
84 | .subdevice = HDA_SUBDEV_NID_FLAG | (nid), \ | 85 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ |
85 | .info = snd_hda_mixer_amp_switch_info, \ | 86 | .info = snd_hda_mixer_amp_switch_info, \ |
86 | .get = snd_hda_mixer_amp_switch_get, \ | 87 | .get = snd_hda_mixer_amp_switch_get, \ |
87 | .put = snd_hda_mixer_amp_switch_put_beep, \ | 88 | .put = snd_hda_mixer_amp_switch_put_beep, \ |
@@ -342,6 +343,8 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, | |||
342 | const struct snd_pci_quirk *tbl); | 343 | const struct snd_pci_quirk *tbl); |
343 | int snd_hda_add_new_ctls(struct hda_codec *codec, | 344 | int snd_hda_add_new_ctls(struct hda_codec *codec, |
344 | struct snd_kcontrol_new *knew); | 345 | struct snd_kcontrol_new *knew); |
346 | int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
347 | unsigned int index, hda_nid_t *nids, unsigned int size); | ||
345 | 348 | ||
346 | /* | 349 | /* |
347 | * unsolicited event handler | 350 | * unsolicited event handler |
@@ -464,13 +467,20 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); | |||
464 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); | 467 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); |
465 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); | 468 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); |
466 | 469 | ||
470 | /* flags for hda_nid_item */ | ||
471 | #define HDA_NID_ITEM_AMP (1<<0) | ||
472 | |||
467 | struct hda_nid_item { | 473 | struct hda_nid_item { |
468 | struct snd_kcontrol *kctl; | 474 | struct snd_kcontrol *kctl; |
475 | unsigned int index; | ||
469 | hda_nid_t nid; | 476 | hda_nid_t nid; |
477 | unsigned short flags; | ||
470 | }; | 478 | }; |
471 | 479 | ||
472 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | 480 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, |
473 | struct snd_kcontrol *kctl); | 481 | struct snd_kcontrol *kctl); |
482 | int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
483 | unsigned int index, hda_nid_t nid); | ||
474 | void snd_hda_ctls_clear(struct hda_codec *codec); | 484 | void snd_hda_ctls_clear(struct hda_codec *codec); |
475 | 485 | ||
476 | /* | 486 | /* |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index c9afc04adac8..f97d35de66c4 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -61,18 +61,29 @@ static const char *get_wid_type_name(unsigned int wid_value) | |||
61 | return "UNKNOWN Widget"; | 61 | return "UNKNOWN Widget"; |
62 | } | 62 | } |
63 | 63 | ||
64 | static void print_nid_mixers(struct snd_info_buffer *buffer, | 64 | static void print_nid_array(struct snd_info_buffer *buffer, |
65 | struct hda_codec *codec, hda_nid_t nid) | 65 | struct hda_codec *codec, hda_nid_t nid, |
66 | struct snd_array *array) | ||
66 | { | 67 | { |
67 | int i; | 68 | int i; |
68 | struct hda_nid_item *items = codec->mixers.list; | 69 | struct hda_nid_item *items = array->list, *item; |
69 | struct snd_kcontrol *kctl; | 70 | struct snd_kcontrol *kctl; |
70 | for (i = 0; i < codec->mixers.used; i++) { | 71 | for (i = 0; i < array->used; i++) { |
71 | if (items[i].nid == nid) { | 72 | item = &items[i]; |
72 | kctl = items[i].kctl; | 73 | if (item->nid == nid) { |
74 | kctl = item->kctl; | ||
73 | snd_iprintf(buffer, | 75 | snd_iprintf(buffer, |
74 | " Control: name=\"%s\", index=%i, device=%i\n", | 76 | " Control: name=\"%s\", index=%i, device=%i\n", |
75 | kctl->id.name, kctl->id.index, kctl->id.device); | 77 | kctl->id.name, kctl->id.index + item->index, |
78 | kctl->id.device); | ||
79 | if (item->flags & HDA_NID_ITEM_AMP) | ||
80 | snd_iprintf(buffer, | ||
81 | " ControlAmp: chs=%lu, dir=%s, " | ||
82 | "idx=%lu, ofs=%lu\n", | ||
83 | get_amp_channels(kctl), | ||
84 | get_amp_direction(kctl) ? "Out" : "In", | ||
85 | get_amp_index(kctl), | ||
86 | get_amp_offset(kctl)); | ||
76 | } | 87 | } |
77 | } | 88 | } |
78 | } | 89 | } |
@@ -528,7 +539,8 @@ static void print_gpio(struct snd_info_buffer *buffer, | |||
528 | (data & (1<<i)) ? 1 : 0, | 539 | (data & (1<<i)) ? 1 : 0, |
529 | (unsol & (1<<i)) ? 1 : 0); | 540 | (unsol & (1<<i)) ? 1 : 0); |
530 | /* FIXME: add GPO and GPI pin information */ | 541 | /* FIXME: add GPO and GPI pin information */ |
531 | print_nid_mixers(buffer, codec, nid); | 542 | print_nid_array(buffer, codec, nid, &codec->mixers); |
543 | print_nid_array(buffer, codec, nid, &codec->nids); | ||
532 | } | 544 | } |
533 | 545 | ||
534 | static void print_codec_info(struct snd_info_entry *entry, | 546 | static void print_codec_info(struct snd_info_entry *entry, |
@@ -608,7 +620,8 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
608 | snd_iprintf(buffer, " CP"); | 620 | snd_iprintf(buffer, " CP"); |
609 | snd_iprintf(buffer, "\n"); | 621 | snd_iprintf(buffer, "\n"); |
610 | 622 | ||
611 | print_nid_mixers(buffer, codec, nid); | 623 | print_nid_array(buffer, codec, nid, &codec->mixers); |
624 | print_nid_array(buffer, codec, nid, &codec->nids); | ||
612 | print_nid_pcms(buffer, codec, nid); | 625 | print_nid_pcms(buffer, codec, nid); |
613 | 626 | ||
614 | /* volume knob is a special widget that always have connection | 627 | /* volume knob is a special widget that always have connection |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 1a36137e13ec..92b72d4f3984 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -174,6 +174,7 @@ static struct snd_kcontrol_new ad_beep_mixer[] = { | |||
174 | static int ad198x_build_controls(struct hda_codec *codec) | 174 | static int ad198x_build_controls(struct hda_codec *codec) |
175 | { | 175 | { |
176 | struct ad198x_spec *spec = codec->spec; | 176 | struct ad198x_spec *spec = codec->spec; |
177 | struct snd_kcontrol *kctl; | ||
177 | unsigned int i; | 178 | unsigned int i; |
178 | int err; | 179 | int err; |
179 | 180 | ||
@@ -208,9 +209,7 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
208 | if (!kctl) | 209 | if (!kctl) |
209 | return -ENOMEM; | 210 | return -ENOMEM; |
210 | kctl->private_value = spec->beep_amp; | 211 | kctl->private_value = spec->beep_amp; |
211 | err = snd_hda_ctl_add(codec, | 212 | err = snd_hda_ctl_add(codec, 0, kctl); |
212 | get_amp_nid_(spec->beep_amp), | ||
213 | kctl); | ||
214 | if (err < 0) | 213 | if (err < 0) |
215 | return err; | 214 | return err; |
216 | } | 215 | } |
@@ -239,6 +238,28 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
239 | } | 238 | } |
240 | 239 | ||
241 | ad198x_free_kctls(codec); /* no longer needed */ | 240 | ad198x_free_kctls(codec); /* no longer needed */ |
241 | |||
242 | /* assign Capture Source enums to NID */ | ||
243 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
244 | if (!kctl) | ||
245 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | ||
246 | for (i = 0; kctl && i < kctl->count; i++) { | ||
247 | err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids, | ||
248 | spec->input_mux->num_items); | ||
249 | if (err < 0) | ||
250 | return err; | ||
251 | } | ||
252 | |||
253 | /* assign IEC958 enums to NID */ | ||
254 | kctl = snd_hda_find_mixer_ctl(codec, | ||
255 | SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source"); | ||
256 | if (kctl) { | ||
257 | err = snd_hda_add_nid(codec, kctl, 0, | ||
258 | spec->multiout.dig_out_nid); | ||
259 | if (err < 0) | ||
260 | return err; | ||
261 | } | ||
262 | |||
242 | return 0; | 263 | return 0; |
243 | } | 264 | } |
244 | 265 | ||
@@ -701,6 +722,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
701 | { | 722 | { |
702 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 723 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
703 | .name = "External Amplifier", | 724 | .name = "External Amplifier", |
725 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, | ||
704 | .info = ad198x_eapd_info, | 726 | .info = ad198x_eapd_info, |
705 | .get = ad198x_eapd_get, | 727 | .get = ad198x_eapd_get, |
706 | .put = ad198x_eapd_put, | 728 | .put = ad198x_eapd_put, |
@@ -808,6 +830,7 @@ static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = { | |||
808 | { | 830 | { |
809 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 831 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
810 | .name = "Master Playback Switch", | 832 | .name = "Master Playback Switch", |
833 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
811 | .info = snd_hda_mixer_amp_switch_info, | 834 | .info = snd_hda_mixer_amp_switch_info, |
812 | .get = snd_hda_mixer_amp_switch_get, | 835 | .get = snd_hda_mixer_amp_switch_get, |
813 | .put = ad1986a_hp_master_sw_put, | 836 | .put = ad1986a_hp_master_sw_put, |
@@ -1608,6 +1631,7 @@ static struct snd_kcontrol_new ad1981_hp_mixers[] = { | |||
1608 | HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), | 1631 | HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), |
1609 | { | 1632 | { |
1610 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1633 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1634 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x05, | ||
1611 | .name = "Master Playback Switch", | 1635 | .name = "Master Playback Switch", |
1612 | .info = ad198x_eapd_info, | 1636 | .info = ad198x_eapd_info, |
1613 | .get = ad198x_eapd_get, | 1637 | .get = ad198x_eapd_get, |
@@ -2129,6 +2153,7 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { | |||
2129 | { | 2153 | { |
2130 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2154 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2131 | .name = "External Amplifier", | 2155 | .name = "External Amplifier", |
2156 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x12, | ||
2132 | .info = ad198x_eapd_info, | 2157 | .info = ad198x_eapd_info, |
2133 | .get = ad198x_eapd_get, | 2158 | .get = ad198x_eapd_get, |
2134 | .put = ad198x_eapd_put, | 2159 | .put = ad198x_eapd_put, |
@@ -2250,6 +2275,7 @@ static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = { | |||
2250 | { | 2275 | { |
2251 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2276 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2252 | .name = "IEC958 Playback Source", | 2277 | .name = "IEC958 Playback Source", |
2278 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, | ||
2253 | .info = ad1988_spdif_playback_source_info, | 2279 | .info = ad1988_spdif_playback_source_info, |
2254 | .get = ad1988_spdif_playback_source_get, | 2280 | .get = ad1988_spdif_playback_source_get, |
2255 | .put = ad1988_spdif_playback_source_put, | 2281 | .put = ad1988_spdif_playback_source_put, |
@@ -2582,7 +2608,7 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, | |||
2582 | if (! knew->name) | 2608 | if (! knew->name) |
2583 | return -ENOMEM; | 2609 | return -ENOMEM; |
2584 | if (get_amp_nid_(val)) | 2610 | if (get_amp_nid_(val)) |
2585 | knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); | 2611 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
2586 | knew->private_value = val; | 2612 | knew->private_value = val; |
2587 | return 0; | 2613 | return 0; |
2588 | } | 2614 | } |
@@ -3736,6 +3762,7 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | |||
3736 | { | 3762 | { |
3737 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 3763 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
3738 | .name = "Master Playback Switch", | 3764 | .name = "Master Playback Switch", |
3765 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
3739 | .info = snd_hda_mixer_amp_switch_info, | 3766 | .info = snd_hda_mixer_amp_switch_info, |
3740 | .get = snd_hda_mixer_amp_switch_get, | 3767 | .get = snd_hda_mixer_amp_switch_get, |
3741 | .put = ad1884a_mobile_master_sw_put, | 3768 | .put = ad1884a_mobile_master_sw_put, |
@@ -3764,6 +3791,7 @@ static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { | |||
3764 | { | 3791 | { |
3765 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 3792 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
3766 | .name = "Master Playback Switch", | 3793 | .name = "Master Playback Switch", |
3794 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
3767 | .info = snd_hda_mixer_amp_switch_info, | 3795 | .info = snd_hda_mixer_amp_switch_info, |
3768 | .get = snd_hda_mixer_amp_switch_get, | 3796 | .get = snd_hda_mixer_amp_switch_get, |
3769 | .put = ad1884a_mobile_master_sw_put, | 3797 | .put = ad1884a_mobile_master_sw_put, |
@@ -4105,6 +4133,7 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { | |||
4105 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ | 4133 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ |
4106 | { | 4134 | { |
4107 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 4135 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
4136 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
4108 | .name = "Master Playback Switch", | 4137 | .name = "Master Playback Switch", |
4109 | .info = snd_hda_mixer_amp_switch_info, | 4138 | .info = snd_hda_mixer_amp_switch_info, |
4110 | .get = snd_hda_mixer_amp_switch_get, | 4139 | .get = snd_hda_mixer_amp_switch_get, |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index fe0423c39598..093cfbb55e9e 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -501,7 +501,8 @@ static int add_mute(struct hda_codec *codec, const char *name, int index, | |||
501 | knew.private_value = pval; | 501 | knew.private_value = pval; |
502 | snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); | 502 | snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); |
503 | *kctlp = snd_ctl_new1(&knew, codec); | 503 | *kctlp = snd_ctl_new1(&knew, codec); |
504 | return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp); | 504 | (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; |
505 | return snd_hda_ctl_add(codec, 0, *kctlp); | ||
505 | } | 506 | } |
506 | 507 | ||
507 | static int add_volume(struct hda_codec *codec, const char *name, | 508 | static int add_volume(struct hda_codec *codec, const char *name, |
@@ -514,7 +515,8 @@ static int add_volume(struct hda_codec *codec, const char *name, | |||
514 | knew.private_value = pval; | 515 | knew.private_value = pval; |
515 | snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); | 516 | snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); |
516 | *kctlp = snd_ctl_new1(&knew, codec); | 517 | *kctlp = snd_ctl_new1(&knew, codec); |
517 | return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp); | 518 | (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; |
519 | return snd_hda_ctl_add(codec, 0, *kctlp); | ||
518 | } | 520 | } |
519 | 521 | ||
520 | static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) | 522 | static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) |
@@ -760,6 +762,10 @@ static int build_input(struct hda_codec *codec) | |||
760 | err = snd_hda_ctl_add(codec, 0, kctl); | 762 | err = snd_hda_ctl_add(codec, 0, kctl); |
761 | if (err < 0) | 763 | if (err < 0) |
762 | return err; | 764 | return err; |
765 | err = snd_hda_add_nids(codec, kctl, 0, spec->adc_nid, | ||
766 | spec->num_inputs); | ||
767 | if (err < 0) | ||
768 | return err; | ||
763 | } | 769 | } |
764 | 770 | ||
765 | if (spec->num_inputs > 1 && !spec->mic_detect) { | 771 | if (spec->num_inputs > 1 && !spec->mic_detect) { |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index a45c1169762b..cc1c22370a60 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -315,7 +315,8 @@ static struct hda_verb cmi9880_allout_init[] = { | |||
315 | static int cmi9880_build_controls(struct hda_codec *codec) | 315 | static int cmi9880_build_controls(struct hda_codec *codec) |
316 | { | 316 | { |
317 | struct cmi_spec *spec = codec->spec; | 317 | struct cmi_spec *spec = codec->spec; |
318 | int err; | 318 | struct snd_kcontrol *kctl; |
319 | int i, err; | ||
319 | 320 | ||
320 | err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); | 321 | err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); |
321 | if (err < 0) | 322 | if (err < 0) |
@@ -340,6 +341,15 @@ static int cmi9880_build_controls(struct hda_codec *codec) | |||
340 | if (err < 0) | 341 | if (err < 0) |
341 | return err; | 342 | return err; |
342 | } | 343 | } |
344 | |||
345 | /* assign Capture Source enums to NID */ | ||
346 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
347 | for (i = 0; kctl && i < kctl->count; i++) { | ||
348 | err = snd_hda_add_nids(codec, kctl, i, spec->adc_nids, | ||
349 | spec->input_mux->num_items); | ||
350 | if (err < 0) | ||
351 | return err; | ||
352 | } | ||
343 | return 0; | 353 | return 0; |
344 | } | 354 | } |
345 | 355 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index c578c28f368e..947785f43b28 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -2187,6 +2187,7 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { | |||
2187 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 2187 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
2188 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 2188 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
2189 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | 2189 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, |
2190 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
2190 | .info = snd_hda_mixer_amp_volume_info, | 2191 | .info = snd_hda_mixer_amp_volume_info, |
2191 | .get = snd_hda_mixer_amp_volume_get, | 2192 | .get = snd_hda_mixer_amp_volume_get, |
2192 | .put = snd_hda_mixer_amp_volume_put, | 2193 | .put = snd_hda_mixer_amp_volume_put, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c7465053d6bb..aeb23ef6afe5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -633,6 +633,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
633 | 633 | ||
634 | #define ALC_PIN_MODE(xname, nid, dir) \ | 634 | #define ALC_PIN_MODE(xname, nid, dir) \ |
635 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 635 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
636 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
636 | .info = alc_pin_mode_info, \ | 637 | .info = alc_pin_mode_info, \ |
637 | .get = alc_pin_mode_get, \ | 638 | .get = alc_pin_mode_get, \ |
638 | .put = alc_pin_mode_put, \ | 639 | .put = alc_pin_mode_put, \ |
@@ -684,6 +685,7 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | |||
684 | } | 685 | } |
685 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ | 686 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ |
686 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 687 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
688 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
687 | .info = alc_gpio_data_info, \ | 689 | .info = alc_gpio_data_info, \ |
688 | .get = alc_gpio_data_get, \ | 690 | .get = alc_gpio_data_get, \ |
689 | .put = alc_gpio_data_put, \ | 691 | .put = alc_gpio_data_put, \ |
@@ -738,6 +740,7 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | |||
738 | } | 740 | } |
739 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | 741 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ |
740 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 742 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
743 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
741 | .info = alc_spdif_ctrl_info, \ | 744 | .info = alc_spdif_ctrl_info, \ |
742 | .get = alc_spdif_ctrl_get, \ | 745 | .get = alc_spdif_ctrl_get, \ |
743 | .put = alc_spdif_ctrl_put, \ | 746 | .put = alc_spdif_ctrl_put, \ |
@@ -791,6 +794,7 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | |||
791 | 794 | ||
792 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ | 795 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ |
793 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 796 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
797 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
794 | .info = alc_eapd_ctrl_info, \ | 798 | .info = alc_eapd_ctrl_info, \ |
795 | .get = alc_eapd_ctrl_get, \ | 799 | .get = alc_eapd_ctrl_get, \ |
796 | .put = alc_eapd_ctrl_put, \ | 800 | .put = alc_eapd_ctrl_put, \ |
@@ -2443,6 +2447,15 @@ static const char *alc_slave_sws[] = { | |||
2443 | * build control elements | 2447 | * build control elements |
2444 | */ | 2448 | */ |
2445 | 2449 | ||
2450 | #define NID_MAPPING (-1) | ||
2451 | |||
2452 | #define SUBDEV_SPEAKER_ (0 << 6) | ||
2453 | #define SUBDEV_HP_ (1 << 6) | ||
2454 | #define SUBDEV_LINE_ (2 << 6) | ||
2455 | #define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f)) | ||
2456 | #define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f)) | ||
2457 | #define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f)) | ||
2458 | |||
2446 | static void alc_free_kctls(struct hda_codec *codec); | 2459 | static void alc_free_kctls(struct hda_codec *codec); |
2447 | 2460 | ||
2448 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 2461 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
@@ -2457,8 +2470,11 @@ static struct snd_kcontrol_new alc_beep_mixer[] = { | |||
2457 | static int alc_build_controls(struct hda_codec *codec) | 2470 | static int alc_build_controls(struct hda_codec *codec) |
2458 | { | 2471 | { |
2459 | struct alc_spec *spec = codec->spec; | 2472 | struct alc_spec *spec = codec->spec; |
2460 | int err; | 2473 | struct snd_kcontrol *kctl; |
2461 | int i; | 2474 | struct snd_kcontrol_new *knew; |
2475 | int i, j, err; | ||
2476 | unsigned int u; | ||
2477 | hda_nid_t nid; | ||
2462 | 2478 | ||
2463 | for (i = 0; i < spec->num_mixers; i++) { | 2479 | for (i = 0; i < spec->num_mixers; i++) { |
2464 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | 2480 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); |
@@ -2499,8 +2515,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2499 | if (!kctl) | 2515 | if (!kctl) |
2500 | return -ENOMEM; | 2516 | return -ENOMEM; |
2501 | kctl->private_value = spec->beep_amp; | 2517 | kctl->private_value = spec->beep_amp; |
2502 | err = snd_hda_ctl_add(codec, | 2518 | err = snd_hda_ctl_add(codec, 0, kctl); |
2503 | get_amp_nid_(spec->beep_amp), kctl); | ||
2504 | if (err < 0) | 2519 | if (err < 0) |
2505 | return err; | 2520 | return err; |
2506 | } | 2521 | } |
@@ -2527,6 +2542,73 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2527 | } | 2542 | } |
2528 | 2543 | ||
2529 | alc_free_kctls(codec); /* no longer needed */ | 2544 | alc_free_kctls(codec); /* no longer needed */ |
2545 | |||
2546 | /* assign Capture Source enums to NID */ | ||
2547 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
2548 | if (!kctl) | ||
2549 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | ||
2550 | for (i = 0; kctl && i < kctl->count; i++) { | ||
2551 | err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids, | ||
2552 | spec->input_mux->num_items); | ||
2553 | if (err < 0) | ||
2554 | return err; | ||
2555 | } | ||
2556 | if (spec->cap_mixer) { | ||
2557 | const char *kname = kctl ? kctl->id.name : NULL; | ||
2558 | for (knew = spec->cap_mixer; knew->name; knew++) { | ||
2559 | if (kname && strcmp(knew->name, kname) == 0) | ||
2560 | continue; | ||
2561 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
2562 | for (i = 0; kctl && i < kctl->count; i++) { | ||
2563 | err = snd_hda_add_nid(codec, kctl, i, | ||
2564 | spec->adc_nids[i]); | ||
2565 | if (err < 0) | ||
2566 | return err; | ||
2567 | } | ||
2568 | } | ||
2569 | } | ||
2570 | |||
2571 | /* other nid->control mapping */ | ||
2572 | for (i = 0; i < spec->num_mixers; i++) { | ||
2573 | for (knew = spec->mixers[i]; knew->name; knew++) { | ||
2574 | if (knew->iface != NID_MAPPING) | ||
2575 | continue; | ||
2576 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
2577 | if (kctl == NULL) | ||
2578 | continue; | ||
2579 | u = knew->subdevice; | ||
2580 | for (j = 0; j < 4; j++, u >>= 8) { | ||
2581 | nid = u & 0x3f; | ||
2582 | if (nid == 0) | ||
2583 | continue; | ||
2584 | switch (u & 0xc0) { | ||
2585 | case SUBDEV_SPEAKER_: | ||
2586 | nid = spec->autocfg.speaker_pins[nid]; | ||
2587 | break; | ||
2588 | case SUBDEV_LINE_: | ||
2589 | nid = spec->autocfg.line_out_pins[nid]; | ||
2590 | break; | ||
2591 | case SUBDEV_HP_: | ||
2592 | nid = spec->autocfg.hp_pins[nid]; | ||
2593 | break; | ||
2594 | default: | ||
2595 | continue; | ||
2596 | } | ||
2597 | err = snd_hda_add_nid(codec, kctl, 0, nid); | ||
2598 | if (err < 0) | ||
2599 | return err; | ||
2600 | } | ||
2601 | u = knew->private_value; | ||
2602 | for (j = 0; j < 4; j++, u >>= 8) { | ||
2603 | nid = u & 0xff; | ||
2604 | if (nid == 0) | ||
2605 | continue; | ||
2606 | err = snd_hda_add_nid(codec, kctl, 0, nid); | ||
2607 | if (err < 0) | ||
2608 | return err; | ||
2609 | } | ||
2610 | } | ||
2611 | } | ||
2530 | return 0; | 2612 | return 0; |
2531 | } | 2613 | } |
2532 | 2614 | ||
@@ -3832,6 +3914,7 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
3832 | #define PIN_CTL_TEST(xname,nid) { \ | 3914 | #define PIN_CTL_TEST(xname,nid) { \ |
3833 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3915 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3834 | .name = xname, \ | 3916 | .name = xname, \ |
3917 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
3835 | .info = alc_test_pin_ctl_info, \ | 3918 | .info = alc_test_pin_ctl_info, \ |
3836 | .get = alc_test_pin_ctl_get, \ | 3919 | .get = alc_test_pin_ctl_get, \ |
3837 | .put = alc_test_pin_ctl_put, \ | 3920 | .put = alc_test_pin_ctl_put, \ |
@@ -3841,6 +3924,7 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
3841 | #define PIN_SRC_TEST(xname,nid) { \ | 3924 | #define PIN_SRC_TEST(xname,nid) { \ |
3842 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3925 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3843 | .name = xname, \ | 3926 | .name = xname, \ |
3927 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
3844 | .info = alc_test_pin_src_info, \ | 3928 | .info = alc_test_pin_src_info, \ |
3845 | .get = alc_test_pin_src_get, \ | 3929 | .get = alc_test_pin_src_get, \ |
3846 | .put = alc_test_pin_src_put, \ | 3930 | .put = alc_test_pin_src_put, \ |
@@ -4380,7 +4464,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
4380 | if (!knew->name) | 4464 | if (!knew->name) |
4381 | return -ENOMEM; | 4465 | return -ENOMEM; |
4382 | if (get_amp_nid_(val)) | 4466 | if (get_amp_nid_(val)) |
4383 | knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); | 4467 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
4384 | knew->private_value = val; | 4468 | knew->private_value = val; |
4385 | return 0; | 4469 | return 0; |
4386 | } | 4470 | } |
@@ -5131,6 +5215,7 @@ static struct snd_kcontrol_new alc260_hp_output_mixer[] = { | |||
5131 | { | 5215 | { |
5132 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5216 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5133 | .name = "Master Playback Switch", | 5217 | .name = "Master Playback Switch", |
5218 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, | ||
5134 | .info = snd_ctl_boolean_mono_info, | 5219 | .info = snd_ctl_boolean_mono_info, |
5135 | .get = alc260_hp_master_sw_get, | 5220 | .get = alc260_hp_master_sw_get, |
5136 | .put = alc260_hp_master_sw_put, | 5221 | .put = alc260_hp_master_sw_put, |
@@ -5169,6 +5254,7 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { | |||
5169 | { | 5254 | { |
5170 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5255 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5171 | .name = "Master Playback Switch", | 5256 | .name = "Master Playback Switch", |
5257 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, | ||
5172 | .info = snd_ctl_boolean_mono_info, | 5258 | .info = snd_ctl_boolean_mono_info, |
5173 | .get = alc260_hp_master_sw_get, | 5259 | .get = alc260_hp_master_sw_get, |
5174 | .put = alc260_hp_master_sw_put, | 5260 | .put = alc260_hp_master_sw_put, |
@@ -10248,8 +10334,14 @@ static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
10248 | .info = snd_ctl_boolean_mono_info, \ | 10334 | .info = snd_ctl_boolean_mono_info, \ |
10249 | .get = alc262_hp_master_sw_get, \ | 10335 | .get = alc262_hp_master_sw_get, \ |
10250 | .put = alc262_hp_master_sw_put, \ | 10336 | .put = alc262_hp_master_sw_put, \ |
10337 | }, \ | ||
10338 | { \ | ||
10339 | .iface = NID_MAPPING, \ | ||
10340 | .name = "Master Playback Switch", \ | ||
10341 | .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \ | ||
10251 | } | 10342 | } |
10252 | 10343 | ||
10344 | |||
10253 | static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { | 10345 | static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { |
10254 | ALC262_HP_MASTER_SWITCH, | 10346 | ALC262_HP_MASTER_SWITCH, |
10255 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 10347 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -10407,6 +10499,12 @@ static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol, | |||
10407 | .info = snd_ctl_boolean_mono_info, \ | 10499 | .info = snd_ctl_boolean_mono_info, \ |
10408 | .get = alc262_hippo_master_sw_get, \ | 10500 | .get = alc262_hippo_master_sw_get, \ |
10409 | .put = alc262_hippo_master_sw_put, \ | 10501 | .put = alc262_hippo_master_sw_put, \ |
10502 | }, \ | ||
10503 | { \ | ||
10504 | .iface = NID_MAPPING, \ | ||
10505 | .name = "Master Playback Switch", \ | ||
10506 | .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \ | ||
10507 | (SUBDEV_SPEAKER(0) << 16), \ | ||
10410 | } | 10508 | } |
10411 | 10509 | ||
10412 | static struct snd_kcontrol_new alc262_hippo_mixer[] = { | 10510 | static struct snd_kcontrol_new alc262_hippo_mixer[] = { |
@@ -10887,11 +10985,17 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
10887 | { | 10985 | { |
10888 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 10986 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
10889 | .name = "Master Playback Switch", | 10987 | .name = "Master Playback Switch", |
10988 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
10890 | .info = snd_hda_mixer_amp_switch_info, | 10989 | .info = snd_hda_mixer_amp_switch_info, |
10891 | .get = snd_hda_mixer_amp_switch_get, | 10990 | .get = snd_hda_mixer_amp_switch_get, |
10892 | .put = alc262_fujitsu_master_sw_put, | 10991 | .put = alc262_fujitsu_master_sw_put, |
10893 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | 10992 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), |
10894 | }, | 10993 | }, |
10994 | { | ||
10995 | .iface = NID_MAPPING, | ||
10996 | .name = "Master Playback Switch", | ||
10997 | .private_value = 0x1b, | ||
10998 | }, | ||
10895 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 10999 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
10896 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 11000 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
10897 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11001 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
@@ -10922,6 +11026,7 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = { | |||
10922 | { | 11026 | { |
10923 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 11027 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
10924 | .name = "Master Playback Switch", | 11028 | .name = "Master Playback Switch", |
11029 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
10925 | .info = snd_hda_mixer_amp_switch_info, | 11030 | .info = snd_hda_mixer_amp_switch_info, |
10926 | .get = snd_hda_mixer_amp_switch_get, | 11031 | .get = snd_hda_mixer_amp_switch_get, |
10927 | .put = alc262_lenovo_3000_master_sw_put, | 11032 | .put = alc262_lenovo_3000_master_sw_put, |
@@ -11076,6 +11181,11 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = { | |||
11076 | .get = alc_mux_enum_get, | 11181 | .get = alc_mux_enum_get, |
11077 | .put = alc262_ultra_mux_enum_put, | 11182 | .put = alc262_ultra_mux_enum_put, |
11078 | }, | 11183 | }, |
11184 | { | ||
11185 | .iface = NID_MAPPING, | ||
11186 | .name = "Capture Source", | ||
11187 | .private_value = 0x15, | ||
11188 | }, | ||
11079 | { } /* end */ | 11189 | { } /* end */ |
11080 | }; | 11190 | }; |
11081 | 11191 | ||
@@ -12094,6 +12204,7 @@ static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = { | |||
12094 | { | 12204 | { |
12095 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12205 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12096 | .name = "Master Playback Switch", | 12206 | .name = "Master Playback Switch", |
12207 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12097 | .info = snd_hda_mixer_amp_switch_info, | 12208 | .info = snd_hda_mixer_amp_switch_info, |
12098 | .get = snd_hda_mixer_amp_switch_get, | 12209 | .get = snd_hda_mixer_amp_switch_get, |
12099 | .put = alc268_acer_master_sw_put, | 12210 | .put = alc268_acer_master_sw_put, |
@@ -12109,6 +12220,7 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = { | |||
12109 | { | 12220 | { |
12110 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12221 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12111 | .name = "Master Playback Switch", | 12222 | .name = "Master Playback Switch", |
12223 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12112 | .info = snd_hda_mixer_amp_switch_info, | 12224 | .info = snd_hda_mixer_amp_switch_info, |
12113 | .get = snd_hda_mixer_amp_switch_get, | 12225 | .get = snd_hda_mixer_amp_switch_get, |
12114 | .put = alc268_acer_master_sw_put, | 12226 | .put = alc268_acer_master_sw_put, |
@@ -12126,6 +12238,7 @@ static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = { | |||
12126 | { | 12238 | { |
12127 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12239 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12128 | .name = "Master Playback Switch", | 12240 | .name = "Master Playback Switch", |
12241 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12129 | .info = snd_hda_mixer_amp_switch_info, | 12242 | .info = snd_hda_mixer_amp_switch_info, |
12130 | .get = snd_hda_mixer_amp_switch_get, | 12243 | .get = snd_hda_mixer_amp_switch_get, |
12131 | .put = alc268_acer_master_sw_put, | 12244 | .put = alc268_acer_master_sw_put, |
@@ -13078,6 +13191,7 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
13078 | { | 13191 | { |
13079 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 13192 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
13080 | .name = "Master Playback Switch", | 13193 | .name = "Master Playback Switch", |
13194 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
13081 | .info = snd_hda_mixer_amp_switch_info, | 13195 | .info = snd_hda_mixer_amp_switch_info, |
13082 | .get = snd_hda_mixer_amp_switch_get, | 13196 | .get = snd_hda_mixer_amp_switch_get, |
13083 | .put = alc268_acer_master_sw_put, | 13197 | .put = alc268_acer_master_sw_put, |
@@ -13098,6 +13212,7 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | |||
13098 | { | 13212 | { |
13099 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 13213 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
13100 | .name = "Master Playback Switch", | 13214 | .name = "Master Playback Switch", |
13215 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
13101 | .info = snd_hda_mixer_amp_switch_info, | 13216 | .info = snd_hda_mixer_amp_switch_info, |
13102 | .get = snd_hda_mixer_amp_switch_get, | 13217 | .get = snd_hda_mixer_amp_switch_get, |
13103 | .put = alc268_acer_master_sw_put, | 13218 | .put = alc268_acer_master_sw_put, |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 43b436c5d01b..f419ee8d75f0 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -122,6 +122,7 @@ static int si3054_switch_put(struct snd_kcontrol *kcontrol, | |||
122 | #define SI3054_KCONTROL(kname,reg,mask) { \ | 122 | #define SI3054_KCONTROL(kname,reg,mask) { \ |
123 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 123 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
124 | .name = kname, \ | 124 | .name = kname, \ |
125 | .subdevice = HDA_SUBDEV_NID_FLAG | reg, \ | ||
125 | .info = si3054_switch_info, \ | 126 | .info = si3054_switch_info, \ |
126 | .get = si3054_switch_get, \ | 127 | .get = si3054_switch_get, \ |
127 | .put = si3054_switch_put, \ | 128 | .put = si3054_switch_put, \ |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index eeda7beeb57a..74d5d333ed6c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -2688,7 +2688,7 @@ static struct snd_kcontrol_new * | |||
2688 | stac_control_new(struct sigmatel_spec *spec, | 2688 | stac_control_new(struct sigmatel_spec *spec, |
2689 | struct snd_kcontrol_new *ktemp, | 2689 | struct snd_kcontrol_new *ktemp, |
2690 | const char *name, | 2690 | const char *name, |
2691 | hda_nid_t nid) | 2691 | unsigned int subdev) |
2692 | { | 2692 | { |
2693 | struct snd_kcontrol_new *knew; | 2693 | struct snd_kcontrol_new *knew; |
2694 | 2694 | ||
@@ -2704,8 +2704,7 @@ stac_control_new(struct sigmatel_spec *spec, | |||
2704 | spec->kctls.alloced--; | 2704 | spec->kctls.alloced--; |
2705 | return NULL; | 2705 | return NULL; |
2706 | } | 2706 | } |
2707 | if (nid) | 2707 | knew->subdevice = subdev; |
2708 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | ||
2709 | return knew; | 2708 | return knew; |
2710 | } | 2709 | } |
2711 | 2710 | ||
@@ -2715,7 +2714,7 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | |||
2715 | unsigned long val) | 2714 | unsigned long val) |
2716 | { | 2715 | { |
2717 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, | 2716 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, |
2718 | get_amp_nid_(val)); | 2717 | HDA_SUBDEV_AMP_FLAG); |
2719 | if (!knew) | 2718 | if (!knew) |
2720 | return -ENOMEM; | 2719 | return -ENOMEM; |
2721 | knew->index = idx; | 2720 | knew->index = idx; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index b70e26ad263f..de4839e46762 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -54,6 +54,8 @@ | |||
54 | #include "hda_codec.h" | 54 | #include "hda_codec.h" |
55 | #include "hda_local.h" | 55 | #include "hda_local.h" |
56 | 56 | ||
57 | #define NID_MAPPING (-1) | ||
58 | |||
57 | /* amp values */ | 59 | /* amp values */ |
58 | #define AMP_VAL_IDX_SHIFT 19 | 60 | #define AMP_VAL_IDX_SHIFT 19 |
59 | #define AMP_VAL_IDX_MASK (0x0f<<19) | 61 | #define AMP_VAL_IDX_MASK (0x0f<<19) |
@@ -157,6 +159,19 @@ struct via_spec { | |||
157 | #endif | 159 | #endif |
158 | }; | 160 | }; |
159 | 161 | ||
162 | static struct via_spec * via_new_spec(struct hda_codec *codec) | ||
163 | { | ||
164 | struct via_spec *spec; | ||
165 | |||
166 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
167 | if (spec == NULL) | ||
168 | return NULL; | ||
169 | |||
170 | codec->spec = spec; | ||
171 | spec->codec = codec; | ||
172 | return spec; | ||
173 | } | ||
174 | |||
160 | static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec) | 175 | static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec) |
161 | { | 176 | { |
162 | u32 vendor_id = codec->vendor_id; | 177 | u32 vendor_id = codec->vendor_id; |
@@ -443,11 +458,27 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, | |||
443 | if (!knew->name) | 458 | if (!knew->name) |
444 | return -ENOMEM; | 459 | return -ENOMEM; |
445 | if (get_amp_nid_(val)) | 460 | if (get_amp_nid_(val)) |
446 | knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); | 461 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
447 | knew->private_value = val; | 462 | knew->private_value = val; |
448 | return 0; | 463 | return 0; |
449 | } | 464 | } |
450 | 465 | ||
466 | static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, | ||
467 | struct snd_kcontrol_new *tmpl) | ||
468 | { | ||
469 | struct snd_kcontrol_new *knew; | ||
470 | |||
471 | snd_array_init(&spec->kctls, sizeof(*knew), 32); | ||
472 | knew = snd_array_new(&spec->kctls); | ||
473 | if (!knew) | ||
474 | return NULL; | ||
475 | *knew = *tmpl; | ||
476 | knew->name = kstrdup(tmpl->name, GFP_KERNEL); | ||
477 | if (!knew->name) | ||
478 | return NULL; | ||
479 | return 0; | ||
480 | } | ||
481 | |||
451 | static void via_free_kctls(struct hda_codec *codec) | 482 | static void via_free_kctls(struct hda_codec *codec) |
452 | { | 483 | { |
453 | struct via_spec *spec = codec->spec; | 484 | struct via_spec *spec = codec->spec; |
@@ -1088,24 +1119,9 @@ static int via_independent_hp_get(struct snd_kcontrol *kcontrol, | |||
1088 | struct snd_ctl_elem_value *ucontrol) | 1119 | struct snd_ctl_elem_value *ucontrol) |
1089 | { | 1120 | { |
1090 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1121 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1091 | struct via_spec *spec = codec->spec; | 1122 | hda_nid_t nid = kcontrol->private_value; |
1092 | hda_nid_t nid; | ||
1093 | unsigned int pinsel; | 1123 | unsigned int pinsel; |
1094 | 1124 | ||
1095 | switch (spec->codec_type) { | ||
1096 | case VT1718S: | ||
1097 | nid = 0x34; | ||
1098 | break; | ||
1099 | case VT2002P: | ||
1100 | nid = 0x35; | ||
1101 | break; | ||
1102 | case VT1812: | ||
1103 | nid = 0x3d; | ||
1104 | break; | ||
1105 | default: | ||
1106 | nid = spec->autocfg.hp_pins[0]; | ||
1107 | break; | ||
1108 | } | ||
1109 | /* use !! to translate conn sel 2 for VT1718S */ | 1125 | /* use !! to translate conn sel 2 for VT1718S */ |
1110 | pinsel = !!snd_hda_codec_read(codec, nid, 0, | 1126 | pinsel = !!snd_hda_codec_read(codec, nid, 0, |
1111 | AC_VERB_GET_CONNECT_SEL, | 1127 | AC_VERB_GET_CONNECT_SEL, |
@@ -1127,29 +1143,24 @@ static void activate_ctl(struct hda_codec *codec, const char *name, int active) | |||
1127 | } | 1143 | } |
1128 | } | 1144 | } |
1129 | 1145 | ||
1146 | static hda_nid_t side_mute_channel(struct via_spec *spec) | ||
1147 | { | ||
1148 | switch (spec->codec_type) { | ||
1149 | case VT1708: return 0x1b; | ||
1150 | case VT1709_10CH: return 0x29; | ||
1151 | case VT1708B_8CH: /* fall thru */ | ||
1152 | case VT1708S: return 0x27; | ||
1153 | default: return 0; | ||
1154 | } | ||
1155 | } | ||
1156 | |||
1130 | static int update_side_mute_status(struct hda_codec *codec) | 1157 | static int update_side_mute_status(struct hda_codec *codec) |
1131 | { | 1158 | { |
1132 | /* mute side channel */ | 1159 | /* mute side channel */ |
1133 | struct via_spec *spec = codec->spec; | 1160 | struct via_spec *spec = codec->spec; |
1134 | unsigned int parm = spec->hp_independent_mode | 1161 | unsigned int parm = spec->hp_independent_mode |
1135 | ? AMP_OUT_MUTE : AMP_OUT_UNMUTE; | 1162 | ? AMP_OUT_MUTE : AMP_OUT_UNMUTE; |
1136 | hda_nid_t sw3; | 1163 | hda_nid_t sw3 = side_mute_channel(spec); |
1137 | |||
1138 | switch (spec->codec_type) { | ||
1139 | case VT1708: | ||
1140 | sw3 = 0x1b; | ||
1141 | break; | ||
1142 | case VT1709_10CH: | ||
1143 | sw3 = 0x29; | ||
1144 | break; | ||
1145 | case VT1708B_8CH: | ||
1146 | case VT1708S: | ||
1147 | sw3 = 0x27; | ||
1148 | break; | ||
1149 | default: | ||
1150 | sw3 = 0; | ||
1151 | break; | ||
1152 | } | ||
1153 | 1164 | ||
1154 | if (sw3) | 1165 | if (sw3) |
1155 | snd_hda_codec_write(codec, sw3, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 1166 | snd_hda_codec_write(codec, sw3, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -1162,28 +1173,11 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol, | |||
1162 | { | 1173 | { |
1163 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1174 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1164 | struct via_spec *spec = codec->spec; | 1175 | struct via_spec *spec = codec->spec; |
1165 | hda_nid_t nid = spec->autocfg.hp_pins[0]; | 1176 | hda_nid_t nid = kcontrol->private_value; |
1166 | unsigned int pinsel = ucontrol->value.enumerated.item[0]; | 1177 | unsigned int pinsel = ucontrol->value.enumerated.item[0]; |
1167 | /* Get Independent Mode index of headphone pin widget */ | 1178 | /* Get Independent Mode index of headphone pin widget */ |
1168 | spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel | 1179 | spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel |
1169 | ? 1 : 0; | 1180 | ? 1 : 0; |
1170 | |||
1171 | switch (spec->codec_type) { | ||
1172 | case VT1718S: | ||
1173 | nid = 0x34; | ||
1174 | pinsel = pinsel ? 2 : 0; /* indep HP use AOW4 (index 2) */ | ||
1175 | spec->multiout.num_dacs = 4; | ||
1176 | break; | ||
1177 | case VT2002P: | ||
1178 | nid = 0x35; | ||
1179 | break; | ||
1180 | case VT1812: | ||
1181 | nid = 0x3d; | ||
1182 | break; | ||
1183 | default: | ||
1184 | nid = spec->autocfg.hp_pins[0]; | ||
1185 | break; | ||
1186 | } | ||
1187 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel); | 1181 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel); |
1188 | 1182 | ||
1189 | if (spec->multiout.hp_nid && spec->multiout.hp_nid | 1183 | if (spec->multiout.hp_nid && spec->multiout.hp_nid |
@@ -1207,18 +1201,55 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol, | |||
1207 | return 0; | 1201 | return 0; |
1208 | } | 1202 | } |
1209 | 1203 | ||
1210 | static struct snd_kcontrol_new via_hp_mixer[] = { | 1204 | static struct snd_kcontrol_new via_hp_mixer[2] = { |
1211 | { | 1205 | { |
1212 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1206 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1213 | .name = "Independent HP", | 1207 | .name = "Independent HP", |
1214 | .count = 1, | ||
1215 | .info = via_independent_hp_info, | 1208 | .info = via_independent_hp_info, |
1216 | .get = via_independent_hp_get, | 1209 | .get = via_independent_hp_get, |
1217 | .put = via_independent_hp_put, | 1210 | .put = via_independent_hp_put, |
1218 | }, | 1211 | }, |
1219 | { } /* end */ | 1212 | { |
1213 | .iface = NID_MAPPING, | ||
1214 | .name = "Independent HP", | ||
1215 | }, | ||
1220 | }; | 1216 | }; |
1221 | 1217 | ||
1218 | static int via_hp_build(struct via_spec *spec) | ||
1219 | { | ||
1220 | struct snd_kcontrol_new *knew; | ||
1221 | hda_nid_t nid; | ||
1222 | |||
1223 | knew = via_clone_control(spec, &via_hp_mixer[0]); | ||
1224 | if (knew == NULL) | ||
1225 | return -ENOMEM; | ||
1226 | |||
1227 | switch (spec->codec_type) { | ||
1228 | case VT1718S: | ||
1229 | nid = 0x34; | ||
1230 | break; | ||
1231 | case VT2002P: | ||
1232 | nid = 0x35; | ||
1233 | break; | ||
1234 | case VT1812: | ||
1235 | nid = 0x3d; | ||
1236 | break; | ||
1237 | default: | ||
1238 | nid = spec->autocfg.hp_pins[0]; | ||
1239 | break; | ||
1240 | } | ||
1241 | |||
1242 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | ||
1243 | knew->private_value = nid; | ||
1244 | |||
1245 | knew = via_clone_control(spec, &via_hp_mixer[1]); | ||
1246 | if (knew == NULL) | ||
1247 | return -ENOMEM; | ||
1248 | knew->subdevice = side_mute_channel(spec); | ||
1249 | |||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1222 | static void notify_aa_path_ctls(struct hda_codec *codec) | 1253 | static void notify_aa_path_ctls(struct hda_codec *codec) |
1223 | { | 1254 | { |
1224 | int i; | 1255 | int i; |
@@ -1376,7 +1407,7 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, | |||
1376 | return 1; | 1407 | return 1; |
1377 | } | 1408 | } |
1378 | 1409 | ||
1379 | static struct snd_kcontrol_new via_smart51_mixer[] = { | 1410 | static struct snd_kcontrol_new via_smart51_mixer[2] = { |
1380 | { | 1411 | { |
1381 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1412 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1382 | .name = "Smart 5.1", | 1413 | .name = "Smart 5.1", |
@@ -1385,9 +1416,36 @@ static struct snd_kcontrol_new via_smart51_mixer[] = { | |||
1385 | .get = via_smart51_get, | 1416 | .get = via_smart51_get, |
1386 | .put = via_smart51_put, | 1417 | .put = via_smart51_put, |
1387 | }, | 1418 | }, |
1388 | {} /* end */ | 1419 | { |
1420 | .iface = NID_MAPPING, | ||
1421 | .name = "Smart 5.1", | ||
1422 | } | ||
1389 | }; | 1423 | }; |
1390 | 1424 | ||
1425 | static int via_smart51_build(struct via_spec *spec) | ||
1426 | { | ||
1427 | struct snd_kcontrol_new *knew; | ||
1428 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | ||
1429 | hda_nid_t nid; | ||
1430 | int i; | ||
1431 | |||
1432 | knew = via_clone_control(spec, &via_smart51_mixer[0]); | ||
1433 | if (knew == NULL) | ||
1434 | return -ENOMEM; | ||
1435 | |||
1436 | for (i = 0; i < ARRAY_SIZE(index); i++) { | ||
1437 | nid = spec->autocfg.input_pins[index[i]]; | ||
1438 | if (nid) { | ||
1439 | knew = via_clone_control(spec, &via_smart51_mixer[1]); | ||
1440 | if (knew == NULL) | ||
1441 | return -ENOMEM; | ||
1442 | knew->subdevice = nid; | ||
1443 | } | ||
1444 | } | ||
1445 | |||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1391 | /* capture mixer elements */ | 1449 | /* capture mixer elements */ |
1392 | static struct snd_kcontrol_new vt1708_capture_mixer[] = { | 1450 | static struct snd_kcontrol_new vt1708_capture_mixer[] = { |
1393 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT), | 1451 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT), |
@@ -1819,8 +1877,9 @@ static struct hda_pcm_stream vt1708_pcm_digital_capture = { | |||
1819 | static int via_build_controls(struct hda_codec *codec) | 1877 | static int via_build_controls(struct hda_codec *codec) |
1820 | { | 1878 | { |
1821 | struct via_spec *spec = codec->spec; | 1879 | struct via_spec *spec = codec->spec; |
1822 | int err; | 1880 | struct snd_kcontrol *kctl; |
1823 | int i; | 1881 | struct snd_kcontrol_new *knew; |
1882 | int err, i; | ||
1824 | 1883 | ||
1825 | for (i = 0; i < spec->num_mixers; i++) { | 1884 | for (i = 0; i < spec->num_mixers; i++) { |
1826 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | 1885 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); |
@@ -1845,6 +1904,28 @@ static int via_build_controls(struct hda_codec *codec) | |||
1845 | return err; | 1904 | return err; |
1846 | } | 1905 | } |
1847 | 1906 | ||
1907 | /* assign Capture Source enums to NID */ | ||
1908 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | ||
1909 | for (i = 0; kctl && i < kctl->count; i++) { | ||
1910 | err = snd_hda_add_nids(codec, kctl, i, spec->mux_nids, | ||
1911 | spec->input_mux->num_items); | ||
1912 | if (err < 0) | ||
1913 | return err; | ||
1914 | } | ||
1915 | |||
1916 | /* other nid->control mapping */ | ||
1917 | for (i = 0; i < spec->num_mixers; i++) { | ||
1918 | for (knew = spec->mixers[i]; knew->name; knew++) { | ||
1919 | if (knew->iface != NID_MAPPING) | ||
1920 | continue; | ||
1921 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
1922 | if (kctl == NULL) | ||
1923 | continue; | ||
1924 | err = snd_hda_add_nid(codec, kctl, 0, | ||
1925 | knew->subdevice); | ||
1926 | } | ||
1927 | } | ||
1928 | |||
1848 | /* init power states */ | 1929 | /* init power states */ |
1849 | set_jack_power_state(codec); | 1930 | set_jack_power_state(codec); |
1850 | analog_low_current_mode(codec, 1); | 1931 | analog_low_current_mode(codec, 1); |
@@ -2481,9 +2562,9 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
2481 | spec->input_mux = &spec->private_imux[0]; | 2562 | spec->input_mux = &spec->private_imux[0]; |
2482 | 2563 | ||
2483 | if (spec->hp_mux) | 2564 | if (spec->hp_mux) |
2484 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 2565 | via_hp_build(spec); |
2485 | 2566 | ||
2486 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 2567 | via_smart51_build(spec); |
2487 | return 1; | 2568 | return 1; |
2488 | } | 2569 | } |
2489 | 2570 | ||
@@ -2554,12 +2635,10 @@ static int patch_vt1708(struct hda_codec *codec) | |||
2554 | int err; | 2635 | int err; |
2555 | 2636 | ||
2556 | /* create a codec specific record */ | 2637 | /* create a codec specific record */ |
2557 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2638 | spec = via_new_spec(codec); |
2558 | if (spec == NULL) | 2639 | if (spec == NULL) |
2559 | return -ENOMEM; | 2640 | return -ENOMEM; |
2560 | 2641 | ||
2561 | codec->spec = spec; | ||
2562 | |||
2563 | /* automatic parse from the BIOS config */ | 2642 | /* automatic parse from the BIOS config */ |
2564 | err = vt1708_parse_auto_config(codec); | 2643 | err = vt1708_parse_auto_config(codec); |
2565 | if (err < 0) { | 2644 | if (err < 0) { |
@@ -2597,7 +2676,6 @@ static int patch_vt1708(struct hda_codec *codec) | |||
2597 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2676 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2598 | spec->loopback.amplist = vt1708_loopbacks; | 2677 | spec->loopback.amplist = vt1708_loopbacks; |
2599 | #endif | 2678 | #endif |
2600 | spec->codec = codec; | ||
2601 | INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state); | 2679 | INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state); |
2602 | return 0; | 2680 | return 0; |
2603 | } | 2681 | } |
@@ -3010,9 +3088,9 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
3010 | spec->input_mux = &spec->private_imux[0]; | 3088 | spec->input_mux = &spec->private_imux[0]; |
3011 | 3089 | ||
3012 | if (spec->hp_mux) | 3090 | if (spec->hp_mux) |
3013 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 3091 | via_hp_build(spec); |
3014 | 3092 | ||
3015 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 3093 | via_smart51_build(spec); |
3016 | return 1; | 3094 | return 1; |
3017 | } | 3095 | } |
3018 | 3096 | ||
@@ -3032,12 +3110,10 @@ static int patch_vt1709_10ch(struct hda_codec *codec) | |||
3032 | int err; | 3110 | int err; |
3033 | 3111 | ||
3034 | /* create a codec specific record */ | 3112 | /* create a codec specific record */ |
3035 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3113 | spec = via_new_spec(codec); |
3036 | if (spec == NULL) | 3114 | if (spec == NULL) |
3037 | return -ENOMEM; | 3115 | return -ENOMEM; |
3038 | 3116 | ||
3039 | codec->spec = spec; | ||
3040 | |||
3041 | err = vt1709_parse_auto_config(codec); | 3117 | err = vt1709_parse_auto_config(codec); |
3042 | if (err < 0) { | 3118 | if (err < 0) { |
3043 | via_free(codec); | 3119 | via_free(codec); |
@@ -3126,12 +3202,10 @@ static int patch_vt1709_6ch(struct hda_codec *codec) | |||
3126 | int err; | 3202 | int err; |
3127 | 3203 | ||
3128 | /* create a codec specific record */ | 3204 | /* create a codec specific record */ |
3129 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3205 | spec = via_new_spec(codec); |
3130 | if (spec == NULL) | 3206 | if (spec == NULL) |
3131 | return -ENOMEM; | 3207 | return -ENOMEM; |
3132 | 3208 | ||
3133 | codec->spec = spec; | ||
3134 | |||
3135 | err = vt1709_parse_auto_config(codec); | 3209 | err = vt1709_parse_auto_config(codec); |
3136 | if (err < 0) { | 3210 | if (err < 0) { |
3137 | via_free(codec); | 3211 | via_free(codec); |
@@ -3581,9 +3655,9 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
3581 | spec->input_mux = &spec->private_imux[0]; | 3655 | spec->input_mux = &spec->private_imux[0]; |
3582 | 3656 | ||
3583 | if (spec->hp_mux) | 3657 | if (spec->hp_mux) |
3584 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 3658 | via_hp_build(spec); |
3585 | 3659 | ||
3586 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 3660 | via_smart51_build(spec); |
3587 | return 1; | 3661 | return 1; |
3588 | } | 3662 | } |
3589 | 3663 | ||
@@ -3605,12 +3679,10 @@ static int patch_vt1708B_8ch(struct hda_codec *codec) | |||
3605 | if (get_codec_type(codec) == VT1708BCE) | 3679 | if (get_codec_type(codec) == VT1708BCE) |
3606 | return patch_vt1708S(codec); | 3680 | return patch_vt1708S(codec); |
3607 | /* create a codec specific record */ | 3681 | /* create a codec specific record */ |
3608 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3682 | spec = via_new_spec(codec); |
3609 | if (spec == NULL) | 3683 | if (spec == NULL) |
3610 | return -ENOMEM; | 3684 | return -ENOMEM; |
3611 | 3685 | ||
3612 | codec->spec = spec; | ||
3613 | |||
3614 | /* automatic parse from the BIOS config */ | 3686 | /* automatic parse from the BIOS config */ |
3615 | err = vt1708B_parse_auto_config(codec); | 3687 | err = vt1708B_parse_auto_config(codec); |
3616 | if (err < 0) { | 3688 | if (err < 0) { |
@@ -3657,12 +3729,10 @@ static int patch_vt1708B_4ch(struct hda_codec *codec) | |||
3657 | int err; | 3729 | int err; |
3658 | 3730 | ||
3659 | /* create a codec specific record */ | 3731 | /* create a codec specific record */ |
3660 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3732 | spec = via_new_spec(codec); |
3661 | if (spec == NULL) | 3733 | if (spec == NULL) |
3662 | return -ENOMEM; | 3734 | return -ENOMEM; |
3663 | 3735 | ||
3664 | codec->spec = spec; | ||
3665 | |||
3666 | /* automatic parse from the BIOS config */ | 3736 | /* automatic parse from the BIOS config */ |
3667 | err = vt1708B_parse_auto_config(codec); | 3737 | err = vt1708B_parse_auto_config(codec); |
3668 | if (err < 0) { | 3738 | if (err < 0) { |
@@ -4071,9 +4141,9 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
4071 | spec->input_mux = &spec->private_imux[0]; | 4141 | spec->input_mux = &spec->private_imux[0]; |
4072 | 4142 | ||
4073 | if (spec->hp_mux) | 4143 | if (spec->hp_mux) |
4074 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 4144 | via_hp_build(spec); |
4075 | 4145 | ||
4076 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 4146 | via_smart51_build(spec); |
4077 | return 1; | 4147 | return 1; |
4078 | } | 4148 | } |
4079 | 4149 | ||
@@ -4103,12 +4173,10 @@ static int patch_vt1708S(struct hda_codec *codec) | |||
4103 | int err; | 4173 | int err; |
4104 | 4174 | ||
4105 | /* create a codec specific record */ | 4175 | /* create a codec specific record */ |
4106 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4176 | spec = via_new_spec(codec); |
4107 | if (spec == NULL) | 4177 | if (spec == NULL) |
4108 | return -ENOMEM; | 4178 | return -ENOMEM; |
4109 | 4179 | ||
4110 | codec->spec = spec; | ||
4111 | |||
4112 | /* automatic parse from the BIOS config */ | 4180 | /* automatic parse from the BIOS config */ |
4113 | err = vt1708S_parse_auto_config(codec); | 4181 | err = vt1708S_parse_auto_config(codec); |
4114 | if (err < 0) { | 4182 | if (err < 0) { |
@@ -4443,7 +4511,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
4443 | spec->input_mux = &spec->private_imux[0]; | 4511 | spec->input_mux = &spec->private_imux[0]; |
4444 | 4512 | ||
4445 | if (spec->hp_mux) | 4513 | if (spec->hp_mux) |
4446 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 4514 | via_hp_build(spec); |
4447 | 4515 | ||
4448 | return 1; | 4516 | return 1; |
4449 | } | 4517 | } |
@@ -4464,12 +4532,10 @@ static int patch_vt1702(struct hda_codec *codec) | |||
4464 | int err; | 4532 | int err; |
4465 | 4533 | ||
4466 | /* create a codec specific record */ | 4534 | /* create a codec specific record */ |
4467 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4535 | spec = via_new_spec(codec); |
4468 | if (spec == NULL) | 4536 | if (spec == NULL) |
4469 | return -ENOMEM; | 4537 | return -ENOMEM; |
4470 | 4538 | ||
4471 | codec->spec = spec; | ||
4472 | |||
4473 | /* automatic parse from the BIOS config */ | 4539 | /* automatic parse from the BIOS config */ |
4474 | err = vt1702_parse_auto_config(codec); | 4540 | err = vt1702_parse_auto_config(codec); |
4475 | if (err < 0) { | 4541 | if (err < 0) { |
@@ -4865,9 +4931,9 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) | |||
4865 | spec->input_mux = &spec->private_imux[0]; | 4931 | spec->input_mux = &spec->private_imux[0]; |
4866 | 4932 | ||
4867 | if (spec->hp_mux) | 4933 | if (spec->hp_mux) |
4868 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 4934 | via_hp_build(spec); |
4869 | 4935 | ||
4870 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 4936 | via_smart51_build(spec); |
4871 | 4937 | ||
4872 | return 1; | 4938 | return 1; |
4873 | } | 4939 | } |
@@ -4888,12 +4954,10 @@ static int patch_vt1718S(struct hda_codec *codec) | |||
4888 | int err; | 4954 | int err; |
4889 | 4955 | ||
4890 | /* create a codec specific record */ | 4956 | /* create a codec specific record */ |
4891 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4957 | spec = via_new_spec(codec); |
4892 | if (spec == NULL) | 4958 | if (spec == NULL) |
4893 | return -ENOMEM; | 4959 | return -ENOMEM; |
4894 | 4960 | ||
4895 | codec->spec = spec; | ||
4896 | |||
4897 | /* automatic parse from the BIOS config */ | 4961 | /* automatic parse from the BIOS config */ |
4898 | err = vt1718S_parse_auto_config(codec); | 4962 | err = vt1718S_parse_auto_config(codec); |
4899 | if (err < 0) { | 4963 | if (err < 0) { |
@@ -5014,6 +5078,7 @@ static struct snd_kcontrol_new vt1716s_dmic_mixer[] = { | |||
5014 | { | 5078 | { |
5015 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5079 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5016 | .name = "Digital Mic Capture Switch", | 5080 | .name = "Digital Mic Capture Switch", |
5081 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x26, | ||
5017 | .count = 1, | 5082 | .count = 1, |
5018 | .info = vt1716s_dmic_info, | 5083 | .info = vt1716s_dmic_info, |
5019 | .get = vt1716s_dmic_get, | 5084 | .get = vt1716s_dmic_get, |
@@ -5361,9 +5426,9 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) | |||
5361 | spec->input_mux = &spec->private_imux[0]; | 5426 | spec->input_mux = &spec->private_imux[0]; |
5362 | 5427 | ||
5363 | if (spec->hp_mux) | 5428 | if (spec->hp_mux) |
5364 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 5429 | via_hp_build(spec); |
5365 | 5430 | ||
5366 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 5431 | via_smart51_build(spec); |
5367 | 5432 | ||
5368 | return 1; | 5433 | return 1; |
5369 | } | 5434 | } |
@@ -5384,12 +5449,10 @@ static int patch_vt1716S(struct hda_codec *codec) | |||
5384 | int err; | 5449 | int err; |
5385 | 5450 | ||
5386 | /* create a codec specific record */ | 5451 | /* create a codec specific record */ |
5387 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5452 | spec = via_new_spec(codec); |
5388 | if (spec == NULL) | 5453 | if (spec == NULL) |
5389 | return -ENOMEM; | 5454 | return -ENOMEM; |
5390 | 5455 | ||
5391 | codec->spec = spec; | ||
5392 | |||
5393 | /* automatic parse from the BIOS config */ | 5456 | /* automatic parse from the BIOS config */ |
5394 | err = vt1716S_parse_auto_config(codec); | 5457 | err = vt1716S_parse_auto_config(codec); |
5395 | if (err < 0) { | 5458 | if (err < 0) { |
@@ -5719,7 +5782,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) | |||
5719 | spec->input_mux = &spec->private_imux[0]; | 5782 | spec->input_mux = &spec->private_imux[0]; |
5720 | 5783 | ||
5721 | if (spec->hp_mux) | 5784 | if (spec->hp_mux) |
5722 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 5785 | via_hp_build(spec); |
5723 | 5786 | ||
5724 | return 1; | 5787 | return 1; |
5725 | } | 5788 | } |
@@ -5741,12 +5804,10 @@ static int patch_vt2002P(struct hda_codec *codec) | |||
5741 | int err; | 5804 | int err; |
5742 | 5805 | ||
5743 | /* create a codec specific record */ | 5806 | /* create a codec specific record */ |
5744 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5807 | spec = via_new_spec(codec); |
5745 | if (spec == NULL) | 5808 | if (spec == NULL) |
5746 | return -ENOMEM; | 5809 | return -ENOMEM; |
5747 | 5810 | ||
5748 | codec->spec = spec; | ||
5749 | |||
5750 | /* automatic parse from the BIOS config */ | 5811 | /* automatic parse from the BIOS config */ |
5751 | err = vt2002P_parse_auto_config(codec); | 5812 | err = vt2002P_parse_auto_config(codec); |
5752 | if (err < 0) { | 5813 | if (err < 0) { |
@@ -6070,7 +6131,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) | |||
6070 | spec->input_mux = &spec->private_imux[0]; | 6131 | spec->input_mux = &spec->private_imux[0]; |
6071 | 6132 | ||
6072 | if (spec->hp_mux) | 6133 | if (spec->hp_mux) |
6073 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 6134 | via_hp_build(spec); |
6074 | 6135 | ||
6075 | return 1; | 6136 | return 1; |
6076 | } | 6137 | } |
@@ -6092,12 +6153,10 @@ static int patch_vt1812(struct hda_codec *codec) | |||
6092 | int err; | 6153 | int err; |
6093 | 6154 | ||
6094 | /* create a codec specific record */ | 6155 | /* create a codec specific record */ |
6095 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 6156 | spec = via_new_spec(codec); |
6096 | if (spec == NULL) | 6157 | if (spec == NULL) |
6097 | return -ENOMEM; | 6158 | return -ENOMEM; |
6098 | 6159 | ||
6099 | codec->spec = spec; | ||
6100 | |||
6101 | /* automatic parse from the BIOS config */ | 6160 | /* automatic parse from the BIOS config */ |
6102 | err = vt1812_parse_auto_config(codec); | 6161 | err = vt1812_parse_auto_config(codec); |
6103 | if (err < 0) { | 6162 | if (err < 0) { |