diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-12-15 04:45:10 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-12-15 04:45:10 -0500 |
commit | 709350506567029021b8a38ee7e65bc246fceabc (patch) | |
tree | 94e3865d62b9b964e2272d0844629ec88808cb42 | |
parent | a9e060571a057c132240753b7f815f4a1e0320a3 (diff) | |
parent | 5e26dfd0615868872cb44842f1e1428c7b414ab0 (diff) |
Merge remote branch 'alsa/devel' into topic/hda
-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 |
13 files changed, 455 insertions, 143 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 9cfdb771928c..c848ec0f085e 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 4b200da1bd18..eeb91f6a06c2 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -500,7 +500,8 @@ static int add_mute(struct hda_codec *codec, const char *name, int index, | |||
500 | knew.private_value = pval; | 500 | knew.private_value = pval; |
501 | snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); | 501 | snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); |
502 | *kctlp = snd_ctl_new1(&knew, codec); | 502 | *kctlp = snd_ctl_new1(&knew, codec); |
503 | return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp); | 503 | (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; |
504 | return snd_hda_ctl_add(codec, 0, *kctlp); | ||
504 | } | 505 | } |
505 | 506 | ||
506 | static int add_volume(struct hda_codec *codec, const char *name, | 507 | static int add_volume(struct hda_codec *codec, const char *name, |
@@ -513,7 +514,8 @@ static int add_volume(struct hda_codec *codec, const char *name, | |||
513 | knew.private_value = pval; | 514 | knew.private_value = pval; |
514 | snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); | 515 | snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); |
515 | *kctlp = snd_ctl_new1(&knew, codec); | 516 | *kctlp = snd_ctl_new1(&knew, codec); |
516 | return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp); | 517 | (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; |
518 | return snd_hda_ctl_add(codec, 0, *kctlp); | ||
517 | } | 519 | } |
518 | 520 | ||
519 | static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) | 521 | static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) |
@@ -759,6 +761,10 @@ static int build_input(struct hda_codec *codec) | |||
759 | err = snd_hda_ctl_add(codec, 0, kctl); | 761 | err = snd_hda_ctl_add(codec, 0, kctl); |
760 | if (err < 0) | 762 | if (err < 0) |
761 | return err; | 763 | return err; |
764 | err = snd_hda_add_nids(codec, kctl, 0, spec->adc_nid, | ||
765 | spec->num_inputs); | ||
766 | if (err < 0) | ||
767 | return err; | ||
762 | } | 768 | } |
763 | 769 | ||
764 | if (spec->num_inputs > 1 && !spec->mic_detect) { | 770 | 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 a09c03c3f62b..1ab2958a290b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -2178,6 +2178,7 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { | |||
2178 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 2178 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
2179 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 2179 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
2180 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | 2180 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, |
2181 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
2181 | .info = snd_hda_mixer_amp_volume_info, | 2182 | .info = snd_hda_mixer_amp_volume_info, |
2182 | .get = snd_hda_mixer_amp_volume_get, | 2183 | .get = snd_hda_mixer_amp_volume_get, |
2183 | .put = snd_hda_mixer_amp_volume_put, | 2184 | .put = snd_hda_mixer_amp_volume_put, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index aeed4cc5aa79..f88577897e46 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -627,6 +627,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
627 | 627 | ||
628 | #define ALC_PIN_MODE(xname, nid, dir) \ | 628 | #define ALC_PIN_MODE(xname, nid, dir) \ |
629 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 629 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
630 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
630 | .info = alc_pin_mode_info, \ | 631 | .info = alc_pin_mode_info, \ |
631 | .get = alc_pin_mode_get, \ | 632 | .get = alc_pin_mode_get, \ |
632 | .put = alc_pin_mode_put, \ | 633 | .put = alc_pin_mode_put, \ |
@@ -678,6 +679,7 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | |||
678 | } | 679 | } |
679 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ | 680 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ |
680 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 681 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
682 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
681 | .info = alc_gpio_data_info, \ | 683 | .info = alc_gpio_data_info, \ |
682 | .get = alc_gpio_data_get, \ | 684 | .get = alc_gpio_data_get, \ |
683 | .put = alc_gpio_data_put, \ | 685 | .put = alc_gpio_data_put, \ |
@@ -732,6 +734,7 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | |||
732 | } | 734 | } |
733 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | 735 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ |
734 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 736 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
737 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
735 | .info = alc_spdif_ctrl_info, \ | 738 | .info = alc_spdif_ctrl_info, \ |
736 | .get = alc_spdif_ctrl_get, \ | 739 | .get = alc_spdif_ctrl_get, \ |
737 | .put = alc_spdif_ctrl_put, \ | 740 | .put = alc_spdif_ctrl_put, \ |
@@ -785,6 +788,7 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | |||
785 | 788 | ||
786 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ | 789 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ |
787 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 790 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
791 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
788 | .info = alc_eapd_ctrl_info, \ | 792 | .info = alc_eapd_ctrl_info, \ |
789 | .get = alc_eapd_ctrl_get, \ | 793 | .get = alc_eapd_ctrl_get, \ |
790 | .put = alc_eapd_ctrl_put, \ | 794 | .put = alc_eapd_ctrl_put, \ |
@@ -2410,6 +2414,15 @@ static const char *alc_slave_sws[] = { | |||
2410 | * build control elements | 2414 | * build control elements |
2411 | */ | 2415 | */ |
2412 | 2416 | ||
2417 | #define NID_MAPPING (-1) | ||
2418 | |||
2419 | #define SUBDEV_SPEAKER_ (0 << 6) | ||
2420 | #define SUBDEV_HP_ (1 << 6) | ||
2421 | #define SUBDEV_LINE_ (2 << 6) | ||
2422 | #define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f)) | ||
2423 | #define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f)) | ||
2424 | #define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f)) | ||
2425 | |||
2413 | static void alc_free_kctls(struct hda_codec *codec); | 2426 | static void alc_free_kctls(struct hda_codec *codec); |
2414 | 2427 | ||
2415 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 2428 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
@@ -2424,8 +2437,11 @@ static struct snd_kcontrol_new alc_beep_mixer[] = { | |||
2424 | static int alc_build_controls(struct hda_codec *codec) | 2437 | static int alc_build_controls(struct hda_codec *codec) |
2425 | { | 2438 | { |
2426 | struct alc_spec *spec = codec->spec; | 2439 | struct alc_spec *spec = codec->spec; |
2427 | int err; | 2440 | struct snd_kcontrol *kctl; |
2428 | int i; | 2441 | struct snd_kcontrol_new *knew; |
2442 | int i, j, err; | ||
2443 | unsigned int u; | ||
2444 | hda_nid_t nid; | ||
2429 | 2445 | ||
2430 | for (i = 0; i < spec->num_mixers; i++) { | 2446 | for (i = 0; i < spec->num_mixers; i++) { |
2431 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | 2447 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); |
@@ -2466,8 +2482,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2466 | if (!kctl) | 2482 | if (!kctl) |
2467 | return -ENOMEM; | 2483 | return -ENOMEM; |
2468 | kctl->private_value = spec->beep_amp; | 2484 | kctl->private_value = spec->beep_amp; |
2469 | err = snd_hda_ctl_add(codec, | 2485 | err = snd_hda_ctl_add(codec, 0, kctl); |
2470 | get_amp_nid_(spec->beep_amp), kctl); | ||
2471 | if (err < 0) | 2486 | if (err < 0) |
2472 | return err; | 2487 | return err; |
2473 | } | 2488 | } |
@@ -2494,6 +2509,73 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2494 | } | 2509 | } |
2495 | 2510 | ||
2496 | alc_free_kctls(codec); /* no longer needed */ | 2511 | alc_free_kctls(codec); /* no longer needed */ |
2512 | |||
2513 | /* assign Capture Source enums to NID */ | ||
2514 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
2515 | if (!kctl) | ||
2516 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | ||
2517 | for (i = 0; kctl && i < kctl->count; i++) { | ||
2518 | err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids, | ||
2519 | spec->input_mux->num_items); | ||
2520 | if (err < 0) | ||
2521 | return err; | ||
2522 | } | ||
2523 | if (spec->cap_mixer) { | ||
2524 | const char *kname = kctl ? kctl->id.name : NULL; | ||
2525 | for (knew = spec->cap_mixer; knew->name; knew++) { | ||
2526 | if (kname && strcmp(knew->name, kname) == 0) | ||
2527 | continue; | ||
2528 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
2529 | for (i = 0; kctl && i < kctl->count; i++) { | ||
2530 | err = snd_hda_add_nid(codec, kctl, i, | ||
2531 | spec->adc_nids[i]); | ||
2532 | if (err < 0) | ||
2533 | return err; | ||
2534 | } | ||
2535 | } | ||
2536 | } | ||
2537 | |||
2538 | /* other nid->control mapping */ | ||
2539 | for (i = 0; i < spec->num_mixers; i++) { | ||
2540 | for (knew = spec->mixers[i]; knew->name; knew++) { | ||
2541 | if (knew->iface != NID_MAPPING) | ||
2542 | continue; | ||
2543 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
2544 | if (kctl == NULL) | ||
2545 | continue; | ||
2546 | u = knew->subdevice; | ||
2547 | for (j = 0; j < 4; j++, u >>= 8) { | ||
2548 | nid = u & 0x3f; | ||
2549 | if (nid == 0) | ||
2550 | continue; | ||
2551 | switch (u & 0xc0) { | ||
2552 | case SUBDEV_SPEAKER_: | ||
2553 | nid = spec->autocfg.speaker_pins[nid]; | ||
2554 | break; | ||
2555 | case SUBDEV_LINE_: | ||
2556 | nid = spec->autocfg.line_out_pins[nid]; | ||
2557 | break; | ||
2558 | case SUBDEV_HP_: | ||
2559 | nid = spec->autocfg.hp_pins[nid]; | ||
2560 | break; | ||
2561 | default: | ||
2562 | continue; | ||
2563 | } | ||
2564 | err = snd_hda_add_nid(codec, kctl, 0, nid); | ||
2565 | if (err < 0) | ||
2566 | return err; | ||
2567 | } | ||
2568 | u = knew->private_value; | ||
2569 | for (j = 0; j < 4; j++, u >>= 8) { | ||
2570 | nid = u & 0xff; | ||
2571 | if (nid == 0) | ||
2572 | continue; | ||
2573 | err = snd_hda_add_nid(codec, kctl, 0, nid); | ||
2574 | if (err < 0) | ||
2575 | return err; | ||
2576 | } | ||
2577 | } | ||
2578 | } | ||
2497 | return 0; | 2579 | return 0; |
2498 | } | 2580 | } |
2499 | 2581 | ||
@@ -3781,6 +3863,7 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
3781 | #define PIN_CTL_TEST(xname,nid) { \ | 3863 | #define PIN_CTL_TEST(xname,nid) { \ |
3782 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3864 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3783 | .name = xname, \ | 3865 | .name = xname, \ |
3866 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
3784 | .info = alc_test_pin_ctl_info, \ | 3867 | .info = alc_test_pin_ctl_info, \ |
3785 | .get = alc_test_pin_ctl_get, \ | 3868 | .get = alc_test_pin_ctl_get, \ |
3786 | .put = alc_test_pin_ctl_put, \ | 3869 | .put = alc_test_pin_ctl_put, \ |
@@ -3790,6 +3873,7 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
3790 | #define PIN_SRC_TEST(xname,nid) { \ | 3873 | #define PIN_SRC_TEST(xname,nid) { \ |
3791 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3874 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3792 | .name = xname, \ | 3875 | .name = xname, \ |
3876 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
3793 | .info = alc_test_pin_src_info, \ | 3877 | .info = alc_test_pin_src_info, \ |
3794 | .get = alc_test_pin_src_get, \ | 3878 | .get = alc_test_pin_src_get, \ |
3795 | .put = alc_test_pin_src_put, \ | 3879 | .put = alc_test_pin_src_put, \ |
@@ -4329,7 +4413,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
4329 | if (!knew->name) | 4413 | if (!knew->name) |
4330 | return -ENOMEM; | 4414 | return -ENOMEM; |
4331 | if (get_amp_nid_(val)) | 4415 | if (get_amp_nid_(val)) |
4332 | knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); | 4416 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
4333 | knew->private_value = val; | 4417 | knew->private_value = val; |
4334 | return 0; | 4418 | return 0; |
4335 | } | 4419 | } |
@@ -5080,6 +5164,7 @@ static struct snd_kcontrol_new alc260_hp_output_mixer[] = { | |||
5080 | { | 5164 | { |
5081 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5165 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5082 | .name = "Master Playback Switch", | 5166 | .name = "Master Playback Switch", |
5167 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, | ||
5083 | .info = snd_ctl_boolean_mono_info, | 5168 | .info = snd_ctl_boolean_mono_info, |
5084 | .get = alc260_hp_master_sw_get, | 5169 | .get = alc260_hp_master_sw_get, |
5085 | .put = alc260_hp_master_sw_put, | 5170 | .put = alc260_hp_master_sw_put, |
@@ -5118,6 +5203,7 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { | |||
5118 | { | 5203 | { |
5119 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5204 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5120 | .name = "Master Playback Switch", | 5205 | .name = "Master Playback Switch", |
5206 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, | ||
5121 | .info = snd_ctl_boolean_mono_info, | 5207 | .info = snd_ctl_boolean_mono_info, |
5122 | .get = alc260_hp_master_sw_get, | 5208 | .get = alc260_hp_master_sw_get, |
5123 | .put = alc260_hp_master_sw_put, | 5209 | .put = alc260_hp_master_sw_put, |
@@ -10189,8 +10275,14 @@ static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
10189 | .info = snd_ctl_boolean_mono_info, \ | 10275 | .info = snd_ctl_boolean_mono_info, \ |
10190 | .get = alc262_hp_master_sw_get, \ | 10276 | .get = alc262_hp_master_sw_get, \ |
10191 | .put = alc262_hp_master_sw_put, \ | 10277 | .put = alc262_hp_master_sw_put, \ |
10278 | }, \ | ||
10279 | { \ | ||
10280 | .iface = NID_MAPPING, \ | ||
10281 | .name = "Master Playback Switch", \ | ||
10282 | .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \ | ||
10192 | } | 10283 | } |
10193 | 10284 | ||
10285 | |||
10194 | static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { | 10286 | static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { |
10195 | ALC262_HP_MASTER_SWITCH, | 10287 | ALC262_HP_MASTER_SWITCH, |
10196 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 10288 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -10348,6 +10440,12 @@ static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol, | |||
10348 | .info = snd_ctl_boolean_mono_info, \ | 10440 | .info = snd_ctl_boolean_mono_info, \ |
10349 | .get = alc262_hippo_master_sw_get, \ | 10441 | .get = alc262_hippo_master_sw_get, \ |
10350 | .put = alc262_hippo_master_sw_put, \ | 10442 | .put = alc262_hippo_master_sw_put, \ |
10443 | }, \ | ||
10444 | { \ | ||
10445 | .iface = NID_MAPPING, \ | ||
10446 | .name = "Master Playback Switch", \ | ||
10447 | .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \ | ||
10448 | (SUBDEV_SPEAKER(0) << 16), \ | ||
10351 | } | 10449 | } |
10352 | 10450 | ||
10353 | static struct snd_kcontrol_new alc262_hippo_mixer[] = { | 10451 | static struct snd_kcontrol_new alc262_hippo_mixer[] = { |
@@ -10821,11 +10919,17 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
10821 | { | 10919 | { |
10822 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 10920 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
10823 | .name = "Master Playback Switch", | 10921 | .name = "Master Playback Switch", |
10922 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
10824 | .info = snd_hda_mixer_amp_switch_info, | 10923 | .info = snd_hda_mixer_amp_switch_info, |
10825 | .get = snd_hda_mixer_amp_switch_get, | 10924 | .get = snd_hda_mixer_amp_switch_get, |
10826 | .put = alc262_fujitsu_master_sw_put, | 10925 | .put = alc262_fujitsu_master_sw_put, |
10827 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | 10926 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), |
10828 | }, | 10927 | }, |
10928 | { | ||
10929 | .iface = NID_MAPPING, | ||
10930 | .name = "Master Playback Switch", | ||
10931 | .private_value = 0x1b, | ||
10932 | }, | ||
10829 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 10933 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
10830 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 10934 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
10831 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 10935 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
@@ -10856,6 +10960,7 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = { | |||
10856 | { | 10960 | { |
10857 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 10961 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
10858 | .name = "Master Playback Switch", | 10962 | .name = "Master Playback Switch", |
10963 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
10859 | .info = snd_hda_mixer_amp_switch_info, | 10964 | .info = snd_hda_mixer_amp_switch_info, |
10860 | .get = snd_hda_mixer_amp_switch_get, | 10965 | .get = snd_hda_mixer_amp_switch_get, |
10861 | .put = alc262_lenovo_3000_master_sw_put, | 10966 | .put = alc262_lenovo_3000_master_sw_put, |
@@ -11010,6 +11115,11 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = { | |||
11010 | .get = alc_mux_enum_get, | 11115 | .get = alc_mux_enum_get, |
11011 | .put = alc262_ultra_mux_enum_put, | 11116 | .put = alc262_ultra_mux_enum_put, |
11012 | }, | 11117 | }, |
11118 | { | ||
11119 | .iface = NID_MAPPING, | ||
11120 | .name = "Capture Source", | ||
11121 | .private_value = 0x15, | ||
11122 | }, | ||
11013 | { } /* end */ | 11123 | { } /* end */ |
11014 | }; | 11124 | }; |
11015 | 11125 | ||
@@ -12027,6 +12137,7 @@ static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = { | |||
12027 | { | 12137 | { |
12028 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12138 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12029 | .name = "Master Playback Switch", | 12139 | .name = "Master Playback Switch", |
12140 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12030 | .info = snd_hda_mixer_amp_switch_info, | 12141 | .info = snd_hda_mixer_amp_switch_info, |
12031 | .get = snd_hda_mixer_amp_switch_get, | 12142 | .get = snd_hda_mixer_amp_switch_get, |
12032 | .put = alc268_acer_master_sw_put, | 12143 | .put = alc268_acer_master_sw_put, |
@@ -12042,6 +12153,7 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = { | |||
12042 | { | 12153 | { |
12043 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12154 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12044 | .name = "Master Playback Switch", | 12155 | .name = "Master Playback Switch", |
12156 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12045 | .info = snd_hda_mixer_amp_switch_info, | 12157 | .info = snd_hda_mixer_amp_switch_info, |
12046 | .get = snd_hda_mixer_amp_switch_get, | 12158 | .get = snd_hda_mixer_amp_switch_get, |
12047 | .put = alc268_acer_master_sw_put, | 12159 | .put = alc268_acer_master_sw_put, |
@@ -12059,6 +12171,7 @@ static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = { | |||
12059 | { | 12171 | { |
12060 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12172 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12061 | .name = "Master Playback Switch", | 12173 | .name = "Master Playback Switch", |
12174 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12062 | .info = snd_hda_mixer_amp_switch_info, | 12175 | .info = snd_hda_mixer_amp_switch_info, |
12063 | .get = snd_hda_mixer_amp_switch_get, | 12176 | .get = snd_hda_mixer_amp_switch_get, |
12064 | .put = alc268_acer_master_sw_put, | 12177 | .put = alc268_acer_master_sw_put, |
@@ -13011,6 +13124,7 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
13011 | { | 13124 | { |
13012 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 13125 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
13013 | .name = "Master Playback Switch", | 13126 | .name = "Master Playback Switch", |
13127 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
13014 | .info = snd_hda_mixer_amp_switch_info, | 13128 | .info = snd_hda_mixer_amp_switch_info, |
13015 | .get = snd_hda_mixer_amp_switch_get, | 13129 | .get = snd_hda_mixer_amp_switch_get, |
13016 | .put = alc268_acer_master_sw_put, | 13130 | .put = alc268_acer_master_sw_put, |
@@ -13031,6 +13145,7 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | |||
13031 | { | 13145 | { |
13032 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 13146 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
13033 | .name = "Master Playback Switch", | 13147 | .name = "Master Playback Switch", |
13148 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
13034 | .info = snd_hda_mixer_amp_switch_info, | 13149 | .info = snd_hda_mixer_amp_switch_info, |
13035 | .get = snd_hda_mixer_amp_switch_get, | 13150 | .get = snd_hda_mixer_amp_switch_get, |
13036 | .put = alc268_acer_master_sw_put, | 13151 | .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 3d59f8325848..0bafea9d5106 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -2685,7 +2685,7 @@ static struct snd_kcontrol_new * | |||
2685 | stac_control_new(struct sigmatel_spec *spec, | 2685 | stac_control_new(struct sigmatel_spec *spec, |
2686 | struct snd_kcontrol_new *ktemp, | 2686 | struct snd_kcontrol_new *ktemp, |
2687 | const char *name, | 2687 | const char *name, |
2688 | hda_nid_t nid) | 2688 | unsigned int subdev) |
2689 | { | 2689 | { |
2690 | struct snd_kcontrol_new *knew; | 2690 | struct snd_kcontrol_new *knew; |
2691 | 2691 | ||
@@ -2701,8 +2701,7 @@ stac_control_new(struct sigmatel_spec *spec, | |||
2701 | spec->kctls.alloced--; | 2701 | spec->kctls.alloced--; |
2702 | return NULL; | 2702 | return NULL; |
2703 | } | 2703 | } |
2704 | if (nid) | 2704 | knew->subdevice = subdev; |
2705 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | ||
2706 | return knew; | 2705 | return knew; |
2707 | } | 2706 | } |
2708 | 2707 | ||
@@ -2712,7 +2711,7 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | |||
2712 | unsigned long val) | 2711 | unsigned long val) |
2713 | { | 2712 | { |
2714 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, | 2713 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, |
2715 | get_amp_nid_(val)); | 2714 | HDA_SUBDEV_AMP_FLAG); |
2716 | if (!knew) | 2715 | if (!knew) |
2717 | return -ENOMEM; | 2716 | return -ENOMEM; |
2718 | knew->index = idx; | 2717 | 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) { |