diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 17 | ||||
-rw-r--r-- | sound/pci/hda/Kconfig | 2 | ||||
-rw-r--r-- | sound/pci/hda/Makefile | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 150 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 5 | ||||
-rw-r--r-- | sound/pci/hda/hda_eld.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 60 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 66 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 14 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 31 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 106 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 14 | ||||
-rw-r--r-- | sound/pci/hda/patch_cmedia.c | 11 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 592 | ||||
-rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 1038 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1016 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 271 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 274 |
20 files changed, 2850 insertions, 831 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index d9266bae2849..1caf5e3c1f6a 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/Kconfig b/sound/pci/hda/Kconfig index 556cff937be7..567348b05b5a 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI | |||
157 | 157 | ||
158 | config SND_HDA_ELD | 158 | config SND_HDA_ELD |
159 | def_bool y | 159 | def_bool y |
160 | depends on SND_HDA_CODEC_INTELHDMI | 160 | depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI |
161 | 161 | ||
162 | config SND_HDA_CODEC_CIRRUS | 162 | config SND_HDA_CODEC_CIRRUS |
163 | bool "Build Cirrus Logic codec support" | 163 | bool "Build Cirrus Logic codec support" |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 315a1c4f8998..24bc195b02da 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o | |||
3 | snd-hda-codec-y := hda_codec.o | 3 | snd-hda-codec-y := hda_codec.o |
4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
6 | # snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o | 6 | snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o |
7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
9 | 9 | ||
@@ -18,7 +18,7 @@ snd-hda-codec-ca0110-objs := patch_ca0110.o | |||
18 | snd-hda-codec-conexant-objs := patch_conexant.o | 18 | snd-hda-codec-conexant-objs := patch_conexant.o |
19 | snd-hda-codec-via-objs := patch_via.o | 19 | snd-hda-codec-via-objs := patch_via.o |
20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o | 20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o |
21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o | 21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o |
22 | 22 | ||
23 | # common driver | 23 | # common driver |
24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o | 24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f98b47cd6cfb..5bd7cf45f3a5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -824,6 +824,9 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | |||
824 | struct hda_pincfg *pin; | 824 | struct hda_pincfg *pin; |
825 | unsigned int oldcfg; | 825 | unsigned int oldcfg; |
826 | 826 | ||
827 | if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) | ||
828 | return -EINVAL; | ||
829 | |||
827 | oldcfg = snd_hda_codec_get_pincfg(codec, nid); | 830 | oldcfg = snd_hda_codec_get_pincfg(codec, nid); |
828 | pin = look_up_pincfg(codec, list, nid); | 831 | pin = look_up_pincfg(codec, list, nid); |
829 | if (!pin) { | 832 | if (!pin) { |
@@ -899,6 +902,25 @@ static void restore_pincfgs(struct hda_codec *codec) | |||
899 | } | 902 | } |
900 | } | 903 | } |
901 | 904 | ||
905 | /** | ||
906 | * snd_hda_shutup_pins - Shut up all pins | ||
907 | * @codec: the HDA codec | ||
908 | * | ||
909 | * Clear all pin controls to shup up before suspend for avoiding click noise. | ||
910 | * The controls aren't cached so that they can be resumed properly. | ||
911 | */ | ||
912 | void snd_hda_shutup_pins(struct hda_codec *codec) | ||
913 | { | ||
914 | int i; | ||
915 | for (i = 0; i < codec->init_pins.used; i++) { | ||
916 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
917 | /* use read here for syncing after issuing each verb */ | ||
918 | snd_hda_codec_read(codec, pin->nid, 0, | ||
919 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
920 | } | ||
921 | } | ||
922 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); | ||
923 | |||
902 | static void init_hda_cache(struct hda_cache_rec *cache, | 924 | static void init_hda_cache(struct hda_cache_rec *cache, |
903 | unsigned int record_size); | 925 | unsigned int record_size); |
904 | static void free_hda_cache(struct hda_cache_rec *cache); | 926 | static void free_hda_cache(struct hda_cache_rec *cache); |
@@ -931,6 +953,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
931 | #endif | 953 | #endif |
932 | list_del(&codec->list); | 954 | list_del(&codec->list); |
933 | snd_array_free(&codec->mixers); | 955 | snd_array_free(&codec->mixers); |
956 | snd_array_free(&codec->nids); | ||
934 | codec->bus->caddr_tbl[codec->addr] = NULL; | 957 | codec->bus->caddr_tbl[codec->addr] = NULL; |
935 | if (codec->patch_ops.free) | 958 | if (codec->patch_ops.free) |
936 | codec->patch_ops.free(codec); | 959 | codec->patch_ops.free(codec); |
@@ -955,8 +978,9 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
955 | * | 978 | * |
956 | * Returns 0 if successful, or a negative error code. | 979 | * Returns 0 if successful, or a negative error code. |
957 | */ | 980 | */ |
958 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | 981 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, |
959 | struct hda_codec **codecp) | 982 | unsigned int codec_addr, |
983 | struct hda_codec **codecp) | ||
960 | { | 984 | { |
961 | struct hda_codec *codec; | 985 | struct hda_codec *codec; |
962 | char component[31]; | 986 | char component[31]; |
@@ -985,7 +1009,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
985 | mutex_init(&codec->control_mutex); | 1009 | mutex_init(&codec->control_mutex); |
986 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 1010 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
987 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 1011 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
988 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60); | 1012 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); |
1013 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); | ||
989 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | 1014 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); |
990 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | 1015 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); |
991 | if (codec->bus->modelname) { | 1016 | if (codec->bus->modelname) { |
@@ -1162,7 +1187,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | |||
1162 | */ | 1187 | */ |
1163 | 1188 | ||
1164 | /* FIXME: more better hash key? */ | 1189 | /* FIXME: more better hash key? */ |
1165 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | 1190 | #define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) |
1166 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) | 1191 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) |
1167 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) | 1192 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) |
1168 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) | 1193 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) |
@@ -1332,7 +1357,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) | |||
1332 | if (!codec->no_trigger_sense) { | 1357 | if (!codec->no_trigger_sense) { |
1333 | pincap = snd_hda_query_pin_caps(codec, nid); | 1358 | pincap = snd_hda_query_pin_caps(codec, nid); |
1334 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ | 1359 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ |
1335 | snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); | 1360 | snd_hda_codec_read(codec, nid, 0, |
1361 | AC_VERB_SET_PIN_SENSE, 0); | ||
1336 | } | 1362 | } |
1337 | return snd_hda_codec_read(codec, nid, 0, | 1363 | return snd_hda_codec_read(codec, nid, 0, |
1338 | AC_VERB_GET_PIN_SENSE, 0); | 1364 | AC_VERB_GET_PIN_SENSE, 0); |
@@ -1348,8 +1374,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense); | |||
1348 | */ | 1374 | */ |
1349 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) | 1375 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) |
1350 | { | 1376 | { |
1351 | u32 sense = snd_hda_pin_sense(codec, nid); | 1377 | u32 sense = snd_hda_pin_sense(codec, nid); |
1352 | return !!(sense & AC_PINSENSE_PRESENCE); | 1378 | return !!(sense & AC_PINSENSE_PRESENCE); |
1353 | } | 1379 | } |
1354 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); | 1380 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); |
1355 | 1381 | ||
@@ -1708,7 +1734,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1708 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | 1734 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); |
1709 | 1735 | ||
1710 | /** | 1736 | /** |
1711 | * snd_hda_ctl-add - Add a control element and assign to the codec | 1737 | * snd_hda_ctl_add - Add a control element and assign to the codec |
1712 | * @codec: HD-audio codec | 1738 | * @codec: HD-audio codec |
1713 | * @nid: corresponding NID (optional) | 1739 | * @nid: corresponding NID (optional) |
1714 | * @kctl: the control element to assign | 1740 | * @kctl: the control element to assign |
@@ -1723,19 +1749,25 @@ EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | |||
1723 | * | 1749 | * |
1724 | * snd_hda_ctl_add() checks the control subdev id field whether | 1750 | * snd_hda_ctl_add() checks the control subdev id field whether |
1725 | * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower | 1751 | * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower |
1726 | * bits value is taken as the NID to assign. | 1752 | * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit |
1753 | * specifies if kctl->private_value is a HDA amplifier value. | ||
1727 | */ | 1754 | */ |
1728 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | 1755 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, |
1729 | struct snd_kcontrol *kctl) | 1756 | struct snd_kcontrol *kctl) |
1730 | { | 1757 | { |
1731 | int err; | 1758 | int err; |
1759 | unsigned short flags = 0; | ||
1732 | struct hda_nid_item *item; | 1760 | struct hda_nid_item *item; |
1733 | 1761 | ||
1734 | if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) { | 1762 | if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) { |
1763 | flags |= HDA_NID_ITEM_AMP; | ||
1735 | if (nid == 0) | 1764 | if (nid == 0) |
1736 | nid = kctl->id.subdevice & 0xffff; | 1765 | nid = get_amp_nid_(kctl->private_value); |
1737 | kctl->id.subdevice = 0; | ||
1738 | } | 1766 | } |
1767 | if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0) | ||
1768 | nid = kctl->id.subdevice & 0xffff; | ||
1769 | if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG)) | ||
1770 | kctl->id.subdevice = 0; | ||
1739 | err = snd_ctl_add(codec->bus->card, kctl); | 1771 | err = snd_ctl_add(codec->bus->card, kctl); |
1740 | if (err < 0) | 1772 | if (err < 0) |
1741 | return err; | 1773 | return err; |
@@ -1744,11 +1776,41 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | |||
1744 | return -ENOMEM; | 1776 | return -ENOMEM; |
1745 | item->kctl = kctl; | 1777 | item->kctl = kctl; |
1746 | item->nid = nid; | 1778 | item->nid = nid; |
1779 | item->flags = flags; | ||
1747 | return 0; | 1780 | return 0; |
1748 | } | 1781 | } |
1749 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); | 1782 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); |
1750 | 1783 | ||
1751 | /** | 1784 | /** |
1785 | * snd_hda_add_nid - Assign a NID to a control element | ||
1786 | * @codec: HD-audio codec | ||
1787 | * @nid: corresponding NID (optional) | ||
1788 | * @kctl: the control element to assign | ||
1789 | * @index: index to kctl | ||
1790 | * | ||
1791 | * Add the given control element to an array inside the codec instance. | ||
1792 | * This function is used when #snd_hda_ctl_add cannot be used for 1:1 | ||
1793 | * NID:KCTL mapping - for example "Capture Source" selector. | ||
1794 | */ | ||
1795 | int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
1796 | unsigned int index, hda_nid_t nid) | ||
1797 | { | ||
1798 | struct hda_nid_item *item; | ||
1799 | |||
1800 | if (nid > 0) { | ||
1801 | item = snd_array_new(&codec->nids); | ||
1802 | if (!item) | ||
1803 | return -ENOMEM; | ||
1804 | item->kctl = kctl; | ||
1805 | item->index = index; | ||
1806 | item->nid = nid; | ||
1807 | return 0; | ||
1808 | } | ||
1809 | return -EINVAL; | ||
1810 | } | ||
1811 | EXPORT_SYMBOL_HDA(snd_hda_add_nid); | ||
1812 | |||
1813 | /** | ||
1752 | * snd_hda_ctls_clear - Clear all controls assigned to the given codec | 1814 | * snd_hda_ctls_clear - Clear all controls assigned to the given codec |
1753 | * @codec: HD-audio codec | 1815 | * @codec: HD-audio codec |
1754 | */ | 1816 | */ |
@@ -1759,6 +1821,7 @@ void snd_hda_ctls_clear(struct hda_codec *codec) | |||
1759 | for (i = 0; i < codec->mixers.used; i++) | 1821 | for (i = 0; i < codec->mixers.used; i++) |
1760 | snd_ctl_remove(codec->bus->card, items[i].kctl); | 1822 | snd_ctl_remove(codec->bus->card, items[i].kctl); |
1761 | snd_array_free(&codec->mixers); | 1823 | snd_array_free(&codec->mixers); |
1824 | snd_array_free(&codec->nids); | ||
1762 | } | 1825 | } |
1763 | 1826 | ||
1764 | /* pseudo device locking | 1827 | /* pseudo device locking |
@@ -1891,7 +1954,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1891 | err = snd_hda_ctl_add(codec, 0, kctl); | 1954 | err = snd_hda_ctl_add(codec, 0, kctl); |
1892 | if (err < 0) | 1955 | if (err < 0) |
1893 | return err; | 1956 | return err; |
1894 | 1957 | ||
1895 | for (s = slaves; *s; s++) { | 1958 | for (s = slaves; *s; s++) { |
1896 | struct snd_kcontrol *sctl; | 1959 | struct snd_kcontrol *sctl; |
1897 | int i = 0; | 1960 | int i = 0; |
@@ -2378,27 +2441,27 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
2378 | { | 2441 | { |
2379 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2442 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2380 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2443 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2381 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), | 2444 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), |
2382 | .info = snd_hda_spdif_mask_info, | 2445 | .info = snd_hda_spdif_mask_info, |
2383 | .get = snd_hda_spdif_cmask_get, | 2446 | .get = snd_hda_spdif_cmask_get, |
2384 | }, | 2447 | }, |
2385 | { | 2448 | { |
2386 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2449 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2387 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2450 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2388 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), | 2451 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), |
2389 | .info = snd_hda_spdif_mask_info, | 2452 | .info = snd_hda_spdif_mask_info, |
2390 | .get = snd_hda_spdif_pmask_get, | 2453 | .get = snd_hda_spdif_pmask_get, |
2391 | }, | 2454 | }, |
2392 | { | 2455 | { |
2393 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2456 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2394 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 2457 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), |
2395 | .info = snd_hda_spdif_mask_info, | 2458 | .info = snd_hda_spdif_mask_info, |
2396 | .get = snd_hda_spdif_default_get, | 2459 | .get = snd_hda_spdif_default_get, |
2397 | .put = snd_hda_spdif_default_put, | 2460 | .put = snd_hda_spdif_default_put, |
2398 | }, | 2461 | }, |
2399 | { | 2462 | { |
2400 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2463 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2401 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), | 2464 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), |
2402 | .info = snd_hda_spdif_out_switch_info, | 2465 | .info = snd_hda_spdif_out_switch_info, |
2403 | .get = snd_hda_spdif_out_switch_get, | 2466 | .get = snd_hda_spdif_out_switch_get, |
2404 | .put = snd_hda_spdif_out_switch_put, | 2467 | .put = snd_hda_spdif_out_switch_put, |
@@ -2549,7 +2612,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, | |||
2549 | static struct snd_kcontrol_new dig_in_ctls[] = { | 2612 | static struct snd_kcontrol_new dig_in_ctls[] = { |
2550 | { | 2613 | { |
2551 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2614 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2552 | .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), | 2615 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), |
2553 | .info = snd_hda_spdif_in_switch_info, | 2616 | .info = snd_hda_spdif_in_switch_info, |
2554 | .get = snd_hda_spdif_in_switch_get, | 2617 | .get = snd_hda_spdif_in_switch_get, |
2555 | .put = snd_hda_spdif_in_switch_put, | 2618 | .put = snd_hda_spdif_in_switch_put, |
@@ -2557,7 +2620,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { | |||
2557 | { | 2620 | { |
2558 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2621 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2559 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2622 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2560 | .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), | 2623 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), |
2561 | .info = snd_hda_spdif_mask_info, | 2624 | .info = snd_hda_spdif_mask_info, |
2562 | .get = snd_hda_spdif_in_status_get, | 2625 | .get = snd_hda_spdif_in_status_get, |
2563 | }, | 2626 | }, |
@@ -2706,7 +2769,8 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
2706 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 2769 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, |
2707 | power_state); | 2770 | power_state); |
2708 | /* partial workaround for "azx_get_response timeout" */ | 2771 | /* partial workaround for "azx_get_response timeout" */ |
2709 | if (power_state == AC_PWRST_D0) | 2772 | if (power_state == AC_PWRST_D0 && |
2773 | (codec->vendor_id & 0xffff0000) == 0x14f10000) | ||
2710 | msleep(10); | 2774 | msleep(10); |
2711 | 2775 | ||
2712 | nid = codec->start_nid; | 2776 | nid = codec->start_nid; |
@@ -2740,7 +2804,6 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
2740 | if (power_state == AC_PWRST_D0) { | 2804 | if (power_state == AC_PWRST_D0) { |
2741 | unsigned long end_time; | 2805 | unsigned long end_time; |
2742 | int state; | 2806 | int state; |
2743 | msleep(10); | ||
2744 | /* wait until the codec reachs to D0 */ | 2807 | /* wait until the codec reachs to D0 */ |
2745 | end_time = jiffies + msecs_to_jiffies(500); | 2808 | end_time = jiffies + msecs_to_jiffies(500); |
2746 | do { | 2809 | do { |
@@ -2822,7 +2885,7 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) | |||
2822 | int err = snd_hda_codec_build_controls(codec); | 2885 | int err = snd_hda_codec_build_controls(codec); |
2823 | if (err < 0) { | 2886 | if (err < 0) { |
2824 | printk(KERN_ERR "hda_codec: cannot build controls" | 2887 | printk(KERN_ERR "hda_codec: cannot build controls" |
2825 | "for #%d (error %d)\n", codec->addr, err); | 2888 | "for #%d (error %d)\n", codec->addr, err); |
2826 | err = snd_hda_codec_reset(codec); | 2889 | err = snd_hda_codec_reset(codec); |
2827 | if (err < 0) { | 2890 | if (err < 0) { |
2828 | printk(KERN_ERR | 2891 | printk(KERN_ERR |
@@ -2918,8 +2981,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
2918 | val |= channels - 1; | 2981 | val |= channels - 1; |
2919 | 2982 | ||
2920 | switch (snd_pcm_format_width(format)) { | 2983 | switch (snd_pcm_format_width(format)) { |
2921 | case 8: val |= 0x00; break; | 2984 | case 8: |
2922 | case 16: val |= 0x10; break; | 2985 | val |= 0x00; |
2986 | break; | ||
2987 | case 16: | ||
2988 | val |= 0x10; | ||
2989 | break; | ||
2923 | case 20: | 2990 | case 20: |
2924 | case 24: | 2991 | case 24: |
2925 | case 32: | 2992 | case 32: |
@@ -3214,6 +3281,8 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { | |||
3214 | 3281 | ||
3215 | /* | 3282 | /* |
3216 | * get the empty PCM device number to assign | 3283 | * get the empty PCM device number to assign |
3284 | * | ||
3285 | * note the max device number is limited by HDA_MAX_PCMS, currently 10 | ||
3217 | */ | 3286 | */ |
3218 | static int get_empty_pcm_device(struct hda_bus *bus, int type) | 3287 | static int get_empty_pcm_device(struct hda_bus *bus, int type) |
3219 | { | 3288 | { |
@@ -3235,7 +3304,8 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
3235 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) | 3304 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) |
3236 | return audio_idx[type][i]; | 3305 | return audio_idx[type][i]; |
3237 | 3306 | ||
3238 | snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]); | 3307 | snd_printk(KERN_WARNING "Too many %s devices\n", |
3308 | snd_hda_pcm_type_name[type]); | ||
3239 | return -EAGAIN; | 3309 | return -EAGAIN; |
3240 | } | 3310 | } |
3241 | 3311 | ||
@@ -3273,7 +3343,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
3273 | err = codec->patch_ops.build_pcms(codec); | 3343 | err = codec->patch_ops.build_pcms(codec); |
3274 | if (err < 0) { | 3344 | if (err < 0) { |
3275 | printk(KERN_ERR "hda_codec: cannot build PCMs" | 3345 | printk(KERN_ERR "hda_codec: cannot build PCMs" |
3276 | "for #%d (error %d)\n", codec->addr, err); | 3346 | "for #%d (error %d)\n", codec->addr, err); |
3277 | err = snd_hda_codec_reset(codec); | 3347 | err = snd_hda_codec_reset(codec); |
3278 | if (err < 0) { | 3348 | if (err < 0) { |
3279 | printk(KERN_ERR | 3349 | printk(KERN_ERR |
@@ -3403,8 +3473,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config); | |||
3403 | 3473 | ||
3404 | /** | 3474 | /** |
3405 | * snd_hda_check_board_codec_sid_config - compare the current codec | 3475 | * snd_hda_check_board_codec_sid_config - compare the current codec |
3406 | subsystem ID with the | 3476 | subsystem ID with the |
3407 | config table | 3477 | config table |
3408 | 3478 | ||
3409 | This is important for Gateway notebooks with SB450 HDA Audio | 3479 | This is important for Gateway notebooks with SB450 HDA Audio |
3410 | where the vendor ID of the PCI device is: | 3480 | where the vendor ID of the PCI device is: |
@@ -3478,6 +3548,8 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
3478 | 3548 | ||
3479 | for (; knew->name; knew++) { | 3549 | for (; knew->name; knew++) { |
3480 | struct snd_kcontrol *kctl; | 3550 | struct snd_kcontrol *kctl; |
3551 | if (knew->iface == -1) /* skip this codec private value */ | ||
3552 | continue; | ||
3481 | kctl = snd_ctl_new1(knew, codec); | 3553 | kctl = snd_ctl_new1(knew, codec); |
3482 | if (!kctl) | 3554 | if (!kctl) |
3483 | return -ENOMEM; | 3555 | return -ENOMEM; |
@@ -3542,7 +3614,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec) | |||
3542 | * | 3614 | * |
3543 | * Increment the power-up counter and power up the hardware really when | 3615 | * Increment the power-up counter and power up the hardware really when |
3544 | * not turned on yet. | 3616 | * not turned on yet. |
3545 | */ | 3617 | */ |
3546 | void snd_hda_power_up(struct hda_codec *codec) | 3618 | void snd_hda_power_up(struct hda_codec *codec) |
3547 | { | 3619 | { |
3548 | struct hda_bus *bus = codec->bus; | 3620 | struct hda_bus *bus = codec->bus; |
@@ -3571,7 +3643,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up); | |||
3571 | * | 3643 | * |
3572 | * Decrement the power-up counter and schedules the power-off work if | 3644 | * Decrement the power-up counter and schedules the power-off work if |
3573 | * the counter rearches to zero. | 3645 | * the counter rearches to zero. |
3574 | */ | 3646 | */ |
3575 | void snd_hda_power_down(struct hda_codec *codec) | 3647 | void snd_hda_power_down(struct hda_codec *codec) |
3576 | { | 3648 | { |
3577 | --codec->power_count; | 3649 | --codec->power_count; |
@@ -3597,7 +3669,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down); | |||
3597 | * | 3669 | * |
3598 | * This function is supposed to be set or called from the check_power_status | 3670 | * This function is supposed to be set or called from the check_power_status |
3599 | * patch ops. | 3671 | * patch ops. |
3600 | */ | 3672 | */ |
3601 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | 3673 | int snd_hda_check_amp_list_power(struct hda_codec *codec, |
3602 | struct hda_loopback_check *check, | 3674 | struct hda_loopback_check *check, |
3603 | hda_nid_t nid) | 3675 | hda_nid_t nid) |
@@ -3765,7 +3837,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, | |||
3765 | { | 3837 | { |
3766 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 3838 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
3767 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 3839 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) |
3768 | set_dig_out_convert(codec, nid, | 3840 | set_dig_out_convert(codec, nid, |
3769 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, | 3841 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, |
3770 | -1); | 3842 | -1); |
3771 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | 3843 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); |
@@ -4024,13 +4096,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
4024 | /* | 4096 | /* |
4025 | * Sort an associated group of pins according to their sequence numbers. | 4097 | * Sort an associated group of pins according to their sequence numbers. |
4026 | */ | 4098 | */ |
4027 | static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | 4099 | static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, |
4028 | int num_pins) | 4100 | int num_pins) |
4029 | { | 4101 | { |
4030 | int i, j; | 4102 | int i, j; |
4031 | short seq; | 4103 | short seq; |
4032 | hda_nid_t nid; | 4104 | hda_nid_t nid; |
4033 | 4105 | ||
4034 | for (i = 0; i < num_pins; i++) { | 4106 | for (i = 0; i < num_pins; i++) { |
4035 | for (j = i + 1; j < num_pins; j++) { | 4107 | for (j = i + 1; j < num_pins; j++) { |
4036 | if (sequences[i] > sequences[j]) { | 4108 | if (sequences[i] > sequences[j]) { |
@@ -4058,7 +4130,7 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | |||
4058 | * is detected, one of speaker of HP pins is assigned as the primary | 4130 | * is detected, one of speaker of HP pins is assigned as the primary |
4059 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 4131 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
4060 | * if any analog output exists. | 4132 | * if any analog output exists. |
4061 | * | 4133 | * |
4062 | * The analog input pins are assigned to input_pins array. | 4134 | * The analog input pins are assigned to input_pins array. |
4063 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 4135 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
4064 | * respectively. | 4136 | * respectively. |
@@ -4121,9 +4193,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4121 | case AC_JACK_SPEAKER: | 4193 | case AC_JACK_SPEAKER: |
4122 | seq = get_defcfg_sequence(def_conf); | 4194 | seq = get_defcfg_sequence(def_conf); |
4123 | assoc = get_defcfg_association(def_conf); | 4195 | assoc = get_defcfg_association(def_conf); |
4124 | if (! assoc) | 4196 | if (!assoc) |
4125 | continue; | 4197 | continue; |
4126 | if (! assoc_speaker) | 4198 | if (!assoc_speaker) |
4127 | assoc_speaker = assoc; | 4199 | assoc_speaker = assoc; |
4128 | else if (assoc_speaker != assoc) | 4200 | else if (assoc_speaker != assoc) |
4129 | continue; | 4201 | continue; |
@@ -4221,7 +4293,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4221 | cfg->speaker_outs); | 4293 | cfg->speaker_outs); |
4222 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | 4294 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, |
4223 | cfg->hp_outs); | 4295 | cfg->hp_outs); |
4224 | 4296 | ||
4225 | /* if we have only one mic, make it AUTO_PIN_MIC */ | 4297 | /* if we have only one mic, make it AUTO_PIN_MIC */ |
4226 | if (!cfg->input_pins[AUTO_PIN_MIC] && | 4298 | if (!cfg->input_pins[AUTO_PIN_MIC] && |
4227 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { | 4299 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { |
@@ -4371,7 +4443,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); | |||
4371 | /** | 4443 | /** |
4372 | * snd_array_new - get a new element from the given array | 4444 | * snd_array_new - get a new element from the given array |
4373 | * @array: the array object | 4445 | * @array: the array object |
4374 | * | 4446 | * |
4375 | * Get a new element from the given array. If it exceeds the | 4447 | * Get a new element from the given array. If it exceeds the |
4376 | * pre-allocated array size, re-allocate the array. | 4448 | * pre-allocated array size, re-allocate the array. |
4377 | * | 4449 | * |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 0a770a28e71f..b75da47571e6 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -527,6 +527,9 @@ enum { | |||
527 | /* max. codec address */ | 527 | /* max. codec address */ |
528 | #define HDA_MAX_CODEC_ADDRESS 0x0f | 528 | #define HDA_MAX_CODEC_ADDRESS 0x0f |
529 | 529 | ||
530 | /* max number of PCM devics per card */ | ||
531 | #define HDA_MAX_PCMS 10 | ||
532 | |||
530 | /* | 533 | /* |
531 | * generic arrays | 534 | * generic arrays |
532 | */ | 535 | */ |
@@ -789,6 +792,7 @@ struct hda_codec { | |||
789 | u32 *wcaps; | 792 | u32 *wcaps; |
790 | 793 | ||
791 | struct snd_array mixers; /* list of assigned mixer elements */ | 794 | struct snd_array mixers; /* list of assigned mixer elements */ |
795 | struct snd_array nids; /* list of mapped mixer elements */ | ||
792 | 796 | ||
793 | struct hda_cache_rec amp_cache; /* cache for amp access */ | 797 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
794 | struct hda_cache_rec cmd_cache; /* cache for other commands */ | 798 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
@@ -898,6 +902,7 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid, | |||
898 | unsigned int cfg); | 902 | unsigned int cfg); |
899 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | 903 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, |
900 | hda_nid_t nid, unsigned int cfg); /* for hwdep */ | 904 | hda_nid_t nid, unsigned int cfg); /* for hwdep */ |
905 | void snd_hda_shutup_pins(struct hda_codec *codec); | ||
901 | 906 | ||
902 | /* | 907 | /* |
903 | * Mixer | 908 | * Mixer |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 4228f2fe5956..dcd22446cfc7 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -331,6 +331,7 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) | |||
331 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | 331 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, |
332 | AC_DIPSIZE_ELD_BUF); | 332 | AC_DIPSIZE_ELD_BUF); |
333 | } | 333 | } |
334 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); | ||
334 | 335 | ||
335 | int snd_hdmi_get_eld(struct hdmi_eld *eld, | 336 | int snd_hdmi_get_eld(struct hdmi_eld *eld, |
336 | struct hda_codec *codec, hda_nid_t nid) | 337 | struct hda_codec *codec, hda_nid_t nid) |
@@ -366,6 +367,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, | |||
366 | kfree(buf); | 367 | kfree(buf); |
367 | return ret; | 368 | return ret; |
368 | } | 369 | } |
370 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); | ||
369 | 371 | ||
370 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 372 | static void hdmi_show_short_audio_desc(struct cea_sad *a) |
371 | { | 373 | { |
@@ -404,6 +406,7 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
404 | } | 406 | } |
405 | buf[j] = '\0'; /* necessary when j == 0 */ | 407 | buf[j] = '\0'; /* necessary when j == 0 */ |
406 | } | 408 | } |
409 | EXPORT_SYMBOL_HDA(snd_print_channel_allocation); | ||
407 | 410 | ||
408 | void snd_hdmi_show_eld(struct hdmi_eld *e) | 411 | void snd_hdmi_show_eld(struct hdmi_eld *e) |
409 | { | 412 | { |
@@ -422,6 +425,7 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) | |||
422 | for (i = 0; i < e->sad_count; i++) | 425 | for (i = 0; i < e->sad_count; i++) |
423 | hdmi_show_short_audio_desc(e->sad + i); | 426 | hdmi_show_short_audio_desc(e->sad + i); |
424 | } | 427 | } |
428 | EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); | ||
425 | 429 | ||
426 | #ifdef CONFIG_PROC_FS | 430 | #ifdef CONFIG_PROC_FS |
427 | 431 | ||
@@ -580,6 +584,7 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, | |||
580 | 584 | ||
581 | return 0; | 585 | return 0; |
582 | } | 586 | } |
587 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); | ||
583 | 588 | ||
584 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | 589 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) |
585 | { | 590 | { |
@@ -588,5 +593,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | |||
588 | eld->proc_entry = NULL; | 593 | eld->proc_entry = NULL; |
589 | } | 594 | } |
590 | } | 595 | } |
596 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); | ||
591 | 597 | ||
592 | #endif /* CONFIG_PROC_FS */ | 598 | #endif /* CONFIG_PROC_FS */ |
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_hwdep.c b/sound/pci/hda/hda_hwdep.c index 40ccb419b6e9..a1fc83753cc6 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -293,8 +293,11 @@ static ssize_t type##_store(struct device *dev, \ | |||
293 | { \ | 293 | { \ |
294 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | 294 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ |
295 | struct hda_codec *codec = hwdep->private_data; \ | 295 | struct hda_codec *codec = hwdep->private_data; \ |
296 | char *after; \ | 296 | unsigned long val; \ |
297 | codec->type = simple_strtoul(buf, &after, 0); \ | 297 | int err = strict_strtoul(buf, 0, &val); \ |
298 | if (err < 0) \ | ||
299 | return err; \ | ||
300 | codec->type = val; \ | ||
298 | return count; \ | 301 | return count; \ |
299 | } | 302 | } |
300 | 303 | ||
@@ -622,6 +625,10 @@ enum { | |||
622 | LINE_MODE_PINCFG, | 625 | LINE_MODE_PINCFG, |
623 | LINE_MODE_VERB, | 626 | LINE_MODE_VERB, |
624 | LINE_MODE_HINT, | 627 | LINE_MODE_HINT, |
628 | LINE_MODE_VENDOR_ID, | ||
629 | LINE_MODE_SUBSYSTEM_ID, | ||
630 | LINE_MODE_REVISION_ID, | ||
631 | LINE_MODE_CHIP_NAME, | ||
625 | NUM_LINE_MODES, | 632 | NUM_LINE_MODES, |
626 | }; | 633 | }; |
627 | 634 | ||
@@ -651,53 +658,71 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus, | |||
651 | } | 658 | } |
652 | 659 | ||
653 | /* parse the contents after the other command tags, [pincfg], [verb], | 660 | /* parse the contents after the other command tags, [pincfg], [verb], |
654 | * [hint] and [model] | 661 | * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model] |
655 | * just pass to the sysfs helper (only when any codec was specified) | 662 | * just pass to the sysfs helper (only when any codec was specified) |
656 | */ | 663 | */ |
657 | static void parse_pincfg_mode(char *buf, struct hda_bus *bus, | 664 | static void parse_pincfg_mode(char *buf, struct hda_bus *bus, |
658 | struct hda_codec **codecp) | 665 | struct hda_codec **codecp) |
659 | { | 666 | { |
660 | if (!*codecp) | ||
661 | return; | ||
662 | parse_user_pin_configs(*codecp, buf); | 667 | parse_user_pin_configs(*codecp, buf); |
663 | } | 668 | } |
664 | 669 | ||
665 | static void parse_verb_mode(char *buf, struct hda_bus *bus, | 670 | static void parse_verb_mode(char *buf, struct hda_bus *bus, |
666 | struct hda_codec **codecp) | 671 | struct hda_codec **codecp) |
667 | { | 672 | { |
668 | if (!*codecp) | ||
669 | return; | ||
670 | parse_init_verbs(*codecp, buf); | 673 | parse_init_verbs(*codecp, buf); |
671 | } | 674 | } |
672 | 675 | ||
673 | static void parse_hint_mode(char *buf, struct hda_bus *bus, | 676 | static void parse_hint_mode(char *buf, struct hda_bus *bus, |
674 | struct hda_codec **codecp) | 677 | struct hda_codec **codecp) |
675 | { | 678 | { |
676 | if (!*codecp) | ||
677 | return; | ||
678 | parse_hints(*codecp, buf); | 679 | parse_hints(*codecp, buf); |
679 | } | 680 | } |
680 | 681 | ||
681 | static void parse_model_mode(char *buf, struct hda_bus *bus, | 682 | static void parse_model_mode(char *buf, struct hda_bus *bus, |
682 | struct hda_codec **codecp) | 683 | struct hda_codec **codecp) |
683 | { | 684 | { |
684 | if (!*codecp) | ||
685 | return; | ||
686 | kfree((*codecp)->modelname); | 685 | kfree((*codecp)->modelname); |
687 | (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); | 686 | (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); |
688 | } | 687 | } |
689 | 688 | ||
689 | static void parse_chip_name_mode(char *buf, struct hda_bus *bus, | ||
690 | struct hda_codec **codecp) | ||
691 | { | ||
692 | kfree((*codecp)->chip_name); | ||
693 | (*codecp)->chip_name = kstrdup(buf, GFP_KERNEL); | ||
694 | } | ||
695 | |||
696 | #define DEFINE_PARSE_ID_MODE(name) \ | ||
697 | static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ | ||
698 | struct hda_codec **codecp) \ | ||
699 | { \ | ||
700 | unsigned long val; \ | ||
701 | if (!strict_strtoul(buf, 0, &val)) \ | ||
702 | (*codecp)->name = val; \ | ||
703 | } | ||
704 | |||
705 | DEFINE_PARSE_ID_MODE(vendor_id); | ||
706 | DEFINE_PARSE_ID_MODE(subsystem_id); | ||
707 | DEFINE_PARSE_ID_MODE(revision_id); | ||
708 | |||
709 | |||
690 | struct hda_patch_item { | 710 | struct hda_patch_item { |
691 | const char *tag; | 711 | const char *tag; |
692 | void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); | 712 | void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); |
713 | int need_codec; | ||
693 | }; | 714 | }; |
694 | 715 | ||
695 | static struct hda_patch_item patch_items[NUM_LINE_MODES] = { | 716 | static struct hda_patch_item patch_items[NUM_LINE_MODES] = { |
696 | [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode }, | 717 | [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 }, |
697 | [LINE_MODE_MODEL] = { "[model]", parse_model_mode }, | 718 | [LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 }, |
698 | [LINE_MODE_VERB] = { "[verb]", parse_verb_mode }, | 719 | [LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 }, |
699 | [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode }, | 720 | [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 }, |
700 | [LINE_MODE_HINT] = { "[hint]", parse_hint_mode }, | 721 | [LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 }, |
722 | [LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 }, | ||
723 | [LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 }, | ||
724 | [LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 }, | ||
725 | [LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 }, | ||
701 | }; | 726 | }; |
702 | 727 | ||
703 | /* check the line starting with '[' -- change the parser mode accodingly */ | 728 | /* check the line starting with '[' -- change the parser mode accodingly */ |
@@ -780,7 +805,8 @@ int snd_hda_load_patch(struct hda_bus *bus, const char *patch) | |||
780 | continue; | 805 | continue; |
781 | if (*buf == '[') | 806 | if (*buf == '[') |
782 | line_mode = parse_line_mode(buf, bus); | 807 | line_mode = parse_line_mode(buf, bus); |
783 | else if (patch_items[line_mode].parser) | 808 | else if (patch_items[line_mode].parser && |
809 | (codec || !patch_items[line_mode].need_codec)) | ||
784 | patch_items[line_mode].parser(buf, bus, &codec); | 810 | patch_items[line_mode].parser(buf, bus, &codec); |
785 | } | 811 | } |
786 | release_firmware(fw); | 812 | release_firmware(fw); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ff6da6f386d1..94b444e6fed3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -125,6 +125,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
125 | "{Intel, ICH9}," | 125 | "{Intel, ICH9}," |
126 | "{Intel, ICH10}," | 126 | "{Intel, ICH10}," |
127 | "{Intel, PCH}," | 127 | "{Intel, PCH}," |
128 | "{Intel, CPT}," | ||
128 | "{Intel, SCH}," | 129 | "{Intel, SCH}," |
129 | "{ATI, SB450}," | 130 | "{ATI, SB450}," |
130 | "{ATI, SB600}," | 131 | "{ATI, SB600}," |
@@ -259,8 +260,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
259 | #define AZX_MAX_FRAG 32 | 260 | #define AZX_MAX_FRAG 32 |
260 | /* max buffer size - no h/w limit, you can increase as you like */ | 261 | /* max buffer size - no h/w limit, you can increase as you like */ |
261 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) | 262 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) |
262 | /* max number of PCM devics per card */ | ||
263 | #define AZX_MAX_PCMS 8 | ||
264 | 263 | ||
265 | /* RIRB int mask: overrun[2], response[0] */ | 264 | /* RIRB int mask: overrun[2], response[0] */ |
266 | #define RIRB_INT_RESPONSE 0x01 | 265 | #define RIRB_INT_RESPONSE 0x01 |
@@ -268,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
268 | #define RIRB_INT_MASK 0x05 | 267 | #define RIRB_INT_MASK 0x05 |
269 | 268 | ||
270 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ | 269 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ |
271 | #define AZX_MAX_CODECS 4 | 270 | #define AZX_MAX_CODECS 8 |
271 | #define AZX_DEFAULT_CODECS 4 | ||
272 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) | 272 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) |
273 | 273 | ||
274 | /* SD_CTL bits */ | 274 | /* SD_CTL bits */ |
@@ -408,7 +408,7 @@ struct azx { | |||
408 | struct azx_dev *azx_dev; | 408 | struct azx_dev *azx_dev; |
409 | 409 | ||
410 | /* PCM */ | 410 | /* PCM */ |
411 | struct snd_pcm *pcm[AZX_MAX_PCMS]; | 411 | struct snd_pcm *pcm[HDA_MAX_PCMS]; |
412 | 412 | ||
413 | /* HD codec */ | 413 | /* HD codec */ |
414 | unsigned short codec_mask; | 414 | unsigned short codec_mask; |
@@ -449,6 +449,7 @@ struct azx { | |||
449 | /* driver types */ | 449 | /* driver types */ |
450 | enum { | 450 | enum { |
451 | AZX_DRIVER_ICH, | 451 | AZX_DRIVER_ICH, |
452 | AZX_DRIVER_PCH, | ||
452 | AZX_DRIVER_SCH, | 453 | AZX_DRIVER_SCH, |
453 | AZX_DRIVER_ATI, | 454 | AZX_DRIVER_ATI, |
454 | AZX_DRIVER_ATIHDMI, | 455 | AZX_DRIVER_ATIHDMI, |
@@ -463,6 +464,7 @@ enum { | |||
463 | 464 | ||
464 | static char *driver_short_names[] __devinitdata = { | 465 | static char *driver_short_names[] __devinitdata = { |
465 | [AZX_DRIVER_ICH] = "HDA Intel", | 466 | [AZX_DRIVER_ICH] = "HDA Intel", |
467 | [AZX_DRIVER_PCH] = "HDA Intel PCH", | ||
466 | [AZX_DRIVER_SCH] = "HDA Intel MID", | 468 | [AZX_DRIVER_SCH] = "HDA Intel MID", |
467 | [AZX_DRIVER_ATI] = "HDA ATI SB", | 469 | [AZX_DRIVER_ATI] = "HDA ATI SB", |
468 | [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", | 470 | [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", |
@@ -968,8 +970,8 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) | |||
968 | azx_dev->insufficient = 1; | 970 | azx_dev->insufficient = 1; |
969 | 971 | ||
970 | /* enable SIE */ | 972 | /* enable SIE */ |
971 | azx_writeb(chip, INTCTL, | 973 | azx_writel(chip, INTCTL, |
972 | azx_readb(chip, INTCTL) | (1 << azx_dev->index)); | 974 | azx_readl(chip, INTCTL) | (1 << azx_dev->index)); |
973 | /* set DMA start and interrupt mask */ | 975 | /* set DMA start and interrupt mask */ |
974 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | | 976 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | |
975 | SD_CTL_DMA_START | SD_INT_MASK); | 977 | SD_CTL_DMA_START | SD_INT_MASK); |
@@ -988,8 +990,8 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
988 | { | 990 | { |
989 | azx_stream_clear(chip, azx_dev); | 991 | azx_stream_clear(chip, azx_dev); |
990 | /* disable SIE */ | 992 | /* disable SIE */ |
991 | azx_writeb(chip, INTCTL, | 993 | azx_writel(chip, INTCTL, |
992 | azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); | 994 | azx_readl(chip, INTCTL) & ~(1 << azx_dev->index)); |
993 | } | 995 | } |
994 | 996 | ||
995 | 997 | ||
@@ -1065,6 +1067,7 @@ static void azx_init_pci(struct azx *chip) | |||
1065 | 0x01, NVIDIA_HDA_ENABLE_COHBIT); | 1067 | 0x01, NVIDIA_HDA_ENABLE_COHBIT); |
1066 | break; | 1068 | break; |
1067 | case AZX_DRIVER_SCH: | 1069 | case AZX_DRIVER_SCH: |
1070 | case AZX_DRIVER_PCH: | ||
1068 | pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); | 1071 | pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); |
1069 | if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) { | 1072 | if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) { |
1070 | pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, | 1073 | pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, |
@@ -1350,7 +1353,7 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1350 | if (chip->initialized) { | 1353 | if (chip->initialized) { |
1351 | int i; | 1354 | int i; |
1352 | 1355 | ||
1353 | for (i = 0; i < AZX_MAX_PCMS; i++) | 1356 | for (i = 0; i < HDA_MAX_PCMS; i++) |
1354 | snd_pcm_suspend_all(chip->pcm[i]); | 1357 | snd_pcm_suspend_all(chip->pcm[i]); |
1355 | snd_hda_suspend(chip->bus); | 1358 | snd_hda_suspend(chip->bus); |
1356 | snd_hda_resume(chip->bus); | 1359 | snd_hda_resume(chip->bus); |
@@ -1365,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1365 | 1368 | ||
1366 | /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ | 1369 | /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ |
1367 | static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | 1370 | static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { |
1371 | [AZX_DRIVER_NVIDIA] = 8, | ||
1368 | [AZX_DRIVER_TERA] = 1, | 1372 | [AZX_DRIVER_TERA] = 1, |
1369 | }; | 1373 | }; |
1370 | 1374 | ||
@@ -1397,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1397 | codecs = 0; | 1401 | codecs = 0; |
1398 | max_slots = azx_max_codecs[chip->driver_type]; | 1402 | max_slots = azx_max_codecs[chip->driver_type]; |
1399 | if (!max_slots) | 1403 | if (!max_slots) |
1400 | max_slots = AZX_MAX_CODECS; | 1404 | max_slots = AZX_DEFAULT_CODECS; |
1401 | 1405 | ||
1402 | /* First try to probe all given codec slots */ | 1406 | /* First try to probe all given codec slots */ |
1403 | for (c = 0; c < max_slots; c++) { | 1407 | for (c = 0; c < max_slots; c++) { |
@@ -1412,7 +1416,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1412 | chip->codec_mask &= ~(1 << c); | 1416 | chip->codec_mask &= ~(1 << c); |
1413 | /* More badly, accessing to a non-existing | 1417 | /* More badly, accessing to a non-existing |
1414 | * codec often screws up the controller chip, | 1418 | * codec often screws up the controller chip, |
1415 | * and distrubs the further communications. | 1419 | * and disturbs the further communications. |
1416 | * Thus if an error occurs during probing, | 1420 | * Thus if an error occurs during probing, |
1417 | * better to reset the controller chip to | 1421 | * better to reset the controller chip to |
1418 | * get back to the sanity state. | 1422 | * get back to the sanity state. |
@@ -1983,7 +1987,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
1983 | int pcm_dev = cpcm->device; | 1987 | int pcm_dev = cpcm->device; |
1984 | int s, err; | 1988 | int s, err; |
1985 | 1989 | ||
1986 | if (pcm_dev >= AZX_MAX_PCMS) { | 1990 | if (pcm_dev >= HDA_MAX_PCMS) { |
1987 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", | 1991 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", |
1988 | pcm_dev); | 1992 | pcm_dev); |
1989 | return -EINVAL; | 1993 | return -EINVAL; |
@@ -2139,7 +2143,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
2139 | 2143 | ||
2140 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2144 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2141 | azx_clear_irq_pending(chip); | 2145 | azx_clear_irq_pending(chip); |
2142 | for (i = 0; i < AZX_MAX_PCMS; i++) | 2146 | for (i = 0; i < HDA_MAX_PCMS; i++) |
2143 | snd_pcm_suspend_all(chip->pcm[i]); | 2147 | snd_pcm_suspend_all(chip->pcm[i]); |
2144 | if (chip->initialized) | 2148 | if (chip->initialized) |
2145 | snd_hda_suspend(chip->bus); | 2149 | snd_hda_suspend(chip->bus); |
@@ -2261,9 +2265,12 @@ static int azx_dev_free(struct snd_device *device) | |||
2261 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { | 2265 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { |
2262 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), | 2266 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), |
2263 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), | 2267 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), |
2268 | SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), | ||
2264 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), | 2269 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), |
2270 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), | ||
2265 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), | 2271 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), |
2266 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), | 2272 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), |
2273 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), | ||
2267 | {} | 2274 | {} |
2268 | }; | 2275 | }; |
2269 | 2276 | ||
@@ -2418,6 +2425,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2418 | if (bdl_pos_adj[dev] < 0) { | 2425 | if (bdl_pos_adj[dev] < 0) { |
2419 | switch (chip->driver_type) { | 2426 | switch (chip->driver_type) { |
2420 | case AZX_DRIVER_ICH: | 2427 | case AZX_DRIVER_ICH: |
2428 | case AZX_DRIVER_PCH: | ||
2421 | bdl_pos_adj[dev] = 1; | 2429 | bdl_pos_adj[dev] = 1; |
2422 | break; | 2430 | break; |
2423 | default: | 2431 | default: |
@@ -2696,6 +2704,8 @@ static struct pci_device_id azx_ids[] = { | |||
2696 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, | 2704 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, |
2697 | /* PCH */ | 2705 | /* PCH */ |
2698 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, | 2706 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, |
2707 | /* CPT */ | ||
2708 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, | ||
2699 | /* SCH */ | 2709 | /* SCH */ |
2700 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, | 2710 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, |
2701 | /* ATI SB 450/600 */ | 2711 | /* ATI SB 450/600 */ |
@@ -2723,32 +2733,10 @@ static struct pci_device_id azx_ids[] = { | |||
2723 | /* ULI M5461 */ | 2733 | /* ULI M5461 */ |
2724 | { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, | 2734 | { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, |
2725 | /* NVIDIA MCP */ | 2735 | /* NVIDIA MCP */ |
2726 | { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA }, | 2736 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), |
2727 | { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA }, | 2737 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
2728 | { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA }, | 2738 | .class_mask = 0xffffff, |
2729 | { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA }, | 2739 | .driver_data = AZX_DRIVER_NVIDIA }, |
2730 | { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2731 | { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2732 | { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2733 | { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2734 | { PCI_DEVICE(0x10de, 0x0590), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2735 | { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2736 | { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2737 | { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2738 | { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2739 | { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2740 | { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2741 | { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2742 | { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2743 | { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2744 | { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2745 | { PCI_DEVICE(0x10de, 0x0be2), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2746 | { PCI_DEVICE(0x10de, 0x0be3), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2747 | { PCI_DEVICE(0x10de, 0x0be4), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2748 | { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2749 | { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2750 | { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2751 | { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA }, | ||
2752 | /* Teradici */ | 2740 | /* Teradici */ |
2753 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, | 2741 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, |
2754 | /* Creative X-Fi (CA0110-IBG) */ | 2742 | /* Creative X-Fi (CA0110-IBG) */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 5778ae882b83..7cee364976ff 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, \ |
@@ -464,13 +465,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); | 465 | 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); | 466 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); |
466 | 467 | ||
468 | /* flags for hda_nid_item */ | ||
469 | #define HDA_NID_ITEM_AMP (1<<0) | ||
470 | |||
467 | struct hda_nid_item { | 471 | struct hda_nid_item { |
468 | struct snd_kcontrol *kctl; | 472 | struct snd_kcontrol *kctl; |
473 | unsigned int index; | ||
469 | hda_nid_t nid; | 474 | hda_nid_t nid; |
475 | unsigned short flags; | ||
470 | }; | 476 | }; |
471 | 477 | ||
472 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | 478 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, |
473 | struct snd_kcontrol *kctl); | 479 | struct snd_kcontrol *kctl); |
480 | int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
481 | unsigned int index, hda_nid_t nid); | ||
474 | void snd_hda_ctls_clear(struct hda_codec *codec); | 482 | void snd_hda_ctls_clear(struct hda_codec *codec); |
475 | 483 | ||
476 | /* | 484 | /* |
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 69a941c7b158..7832f363496f 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,27 @@ 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_nid(codec, kctl, i, spec->capsrc_nids[i]); | ||
248 | if (err < 0) | ||
249 | return err; | ||
250 | } | ||
251 | |||
252 | /* assign IEC958 enums to NID */ | ||
253 | kctl = snd_hda_find_mixer_ctl(codec, | ||
254 | SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source"); | ||
255 | if (kctl) { | ||
256 | err = snd_hda_add_nid(codec, kctl, 0, | ||
257 | spec->multiout.dig_out_nid); | ||
258 | if (err < 0) | ||
259 | return err; | ||
260 | } | ||
261 | |||
242 | return 0; | 262 | return 0; |
243 | } | 263 | } |
244 | 264 | ||
@@ -421,6 +441,11 @@ static int ad198x_build_pcms(struct hda_codec *codec) | |||
421 | return 0; | 441 | return 0; |
422 | } | 442 | } |
423 | 443 | ||
444 | static inline void ad198x_shutup(struct hda_codec *codec) | ||
445 | { | ||
446 | snd_hda_shutup_pins(codec); | ||
447 | } | ||
448 | |||
424 | static void ad198x_free_kctls(struct hda_codec *codec) | 449 | static void ad198x_free_kctls(struct hda_codec *codec) |
425 | { | 450 | { |
426 | struct ad198x_spec *spec = codec->spec; | 451 | struct ad198x_spec *spec = codec->spec; |
@@ -434,6 +459,46 @@ static void ad198x_free_kctls(struct hda_codec *codec) | |||
434 | snd_array_free(&spec->kctls); | 459 | snd_array_free(&spec->kctls); |
435 | } | 460 | } |
436 | 461 | ||
462 | static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, | ||
463 | hda_nid_t hp) | ||
464 | { | ||
465 | struct ad198x_spec *spec = codec->spec; | ||
466 | snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
467 | !spec->inv_eapd ? 0x00 : 0x02); | ||
468 | snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
469 | !spec->inv_eapd ? 0x00 : 0x02); | ||
470 | } | ||
471 | |||
472 | static void ad198x_power_eapd(struct hda_codec *codec) | ||
473 | { | ||
474 | /* We currently only handle front, HP */ | ||
475 | switch (codec->vendor_id) { | ||
476 | case 0x11d41882: | ||
477 | case 0x11d4882a: | ||
478 | case 0x11d41884: | ||
479 | case 0x11d41984: | ||
480 | case 0x11d41883: | ||
481 | case 0x11d4184a: | ||
482 | case 0x11d4194a: | ||
483 | case 0x11d4194b: | ||
484 | ad198x_power_eapd_write(codec, 0x12, 0x11); | ||
485 | break; | ||
486 | case 0x11d41981: | ||
487 | case 0x11d41983: | ||
488 | ad198x_power_eapd_write(codec, 0x05, 0x06); | ||
489 | break; | ||
490 | case 0x11d41986: | ||
491 | ad198x_power_eapd_write(codec, 0x1b, 0x1a); | ||
492 | break; | ||
493 | case 0x11d41988: | ||
494 | case 0x11d4198b: | ||
495 | case 0x11d4989a: | ||
496 | case 0x11d4989b: | ||
497 | ad198x_power_eapd_write(codec, 0x29, 0x22); | ||
498 | break; | ||
499 | } | ||
500 | } | ||
501 | |||
437 | static void ad198x_free(struct hda_codec *codec) | 502 | static void ad198x_free(struct hda_codec *codec) |
438 | { | 503 | { |
439 | struct ad198x_spec *spec = codec->spec; | 504 | struct ad198x_spec *spec = codec->spec; |
@@ -441,11 +506,29 @@ static void ad198x_free(struct hda_codec *codec) | |||
441 | if (!spec) | 506 | if (!spec) |
442 | return; | 507 | return; |
443 | 508 | ||
509 | ad198x_shutup(codec); | ||
444 | ad198x_free_kctls(codec); | 510 | ad198x_free_kctls(codec); |
445 | kfree(spec); | 511 | kfree(spec); |
446 | snd_hda_detach_beep_device(codec); | 512 | snd_hda_detach_beep_device(codec); |
447 | } | 513 | } |
448 | 514 | ||
515 | #ifdef SND_HDA_NEEDS_RESUME | ||
516 | static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) | ||
517 | { | ||
518 | ad198x_shutup(codec); | ||
519 | ad198x_power_eapd(codec); | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static int ad198x_resume(struct hda_codec *codec) | ||
524 | { | ||
525 | ad198x_init(codec); | ||
526 | snd_hda_codec_resume_amp(codec); | ||
527 | snd_hda_codec_resume_cache(codec); | ||
528 | return 0; | ||
529 | } | ||
530 | #endif | ||
531 | |||
449 | static struct hda_codec_ops ad198x_patch_ops = { | 532 | static struct hda_codec_ops ad198x_patch_ops = { |
450 | .build_controls = ad198x_build_controls, | 533 | .build_controls = ad198x_build_controls, |
451 | .build_pcms = ad198x_build_pcms, | 534 | .build_pcms = ad198x_build_pcms, |
@@ -454,6 +537,11 @@ static struct hda_codec_ops ad198x_patch_ops = { | |||
454 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 537 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
455 | .check_power_status = ad198x_check_power_status, | 538 | .check_power_status = ad198x_check_power_status, |
456 | #endif | 539 | #endif |
540 | #ifdef SND_HDA_NEEDS_RESUME | ||
541 | .suspend = ad198x_suspend, | ||
542 | .resume = ad198x_resume, | ||
543 | #endif | ||
544 | .reboot_notify = ad198x_shutup, | ||
457 | }; | 545 | }; |
458 | 546 | ||
459 | 547 | ||
@@ -701,6 +789,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
701 | { | 789 | { |
702 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 790 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
703 | .name = "External Amplifier", | 791 | .name = "External Amplifier", |
792 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, | ||
704 | .info = ad198x_eapd_info, | 793 | .info = ad198x_eapd_info, |
705 | .get = ad198x_eapd_get, | 794 | .get = ad198x_eapd_get, |
706 | .put = ad198x_eapd_put, | 795 | .put = ad198x_eapd_put, |
@@ -808,6 +897,7 @@ static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = { | |||
808 | { | 897 | { |
809 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 898 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
810 | .name = "Master Playback Switch", | 899 | .name = "Master Playback Switch", |
900 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
811 | .info = snd_hda_mixer_amp_switch_info, | 901 | .info = snd_hda_mixer_amp_switch_info, |
812 | .get = snd_hda_mixer_amp_switch_get, | 902 | .get = snd_hda_mixer_amp_switch_get, |
813 | .put = ad1986a_hp_master_sw_put, | 903 | .put = ad1986a_hp_master_sw_put, |
@@ -1008,7 +1098,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
1008 | SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK), | 1098 | SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK), |
1009 | SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK), | 1099 | SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK), |
1010 | SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK), | 1100 | SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK), |
1011 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), | 1101 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK), |
1012 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), | 1102 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), |
1013 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), | 1103 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), |
1014 | SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), | 1104 | SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), |
@@ -1612,6 +1702,7 @@ static struct snd_kcontrol_new ad1981_hp_mixers[] = { | |||
1612 | HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), | 1702 | HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), |
1613 | { | 1703 | { |
1614 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1704 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1705 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x05, | ||
1615 | .name = "Master Playback Switch", | 1706 | .name = "Master Playback Switch", |
1616 | .info = ad198x_eapd_info, | 1707 | .info = ad198x_eapd_info, |
1617 | .get = ad198x_eapd_get, | 1708 | .get = ad198x_eapd_get, |
@@ -2136,6 +2227,7 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { | |||
2136 | { | 2227 | { |
2137 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2228 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2138 | .name = "External Amplifier", | 2229 | .name = "External Amplifier", |
2230 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x12, | ||
2139 | .info = ad198x_eapd_info, | 2231 | .info = ad198x_eapd_info, |
2140 | .get = ad198x_eapd_get, | 2232 | .get = ad198x_eapd_get, |
2141 | .put = ad198x_eapd_put, | 2233 | .put = ad198x_eapd_put, |
@@ -2257,6 +2349,7 @@ static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = { | |||
2257 | { | 2349 | { |
2258 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2350 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2259 | .name = "IEC958 Playback Source", | 2351 | .name = "IEC958 Playback Source", |
2352 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, | ||
2260 | .info = ad1988_spdif_playback_source_info, | 2353 | .info = ad1988_spdif_playback_source_info, |
2261 | .get = ad1988_spdif_playback_source_get, | 2354 | .get = ad1988_spdif_playback_source_get, |
2262 | .put = ad1988_spdif_playback_source_put, | 2355 | .put = ad1988_spdif_playback_source_put, |
@@ -2589,7 +2682,7 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, | |||
2589 | if (! knew->name) | 2682 | if (! knew->name) |
2590 | return -ENOMEM; | 2683 | return -ENOMEM; |
2591 | if (get_amp_nid_(val)) | 2684 | if (get_amp_nid_(val)) |
2592 | knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); | 2685 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
2593 | knew->private_value = val; | 2686 | knew->private_value = val; |
2594 | return 0; | 2687 | return 0; |
2595 | } | 2688 | } |
@@ -3747,6 +3840,7 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | |||
3747 | { | 3840 | { |
3748 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 3841 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
3749 | .name = "Master Playback Switch", | 3842 | .name = "Master Playback Switch", |
3843 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
3750 | .info = snd_hda_mixer_amp_switch_info, | 3844 | .info = snd_hda_mixer_amp_switch_info, |
3751 | .get = snd_hda_mixer_amp_switch_get, | 3845 | .get = snd_hda_mixer_amp_switch_get, |
3752 | .put = ad1884a_mobile_master_sw_put, | 3846 | .put = ad1884a_mobile_master_sw_put, |
@@ -3775,6 +3869,7 @@ static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { | |||
3775 | { | 3869 | { |
3776 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 3870 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
3777 | .name = "Master Playback Switch", | 3871 | .name = "Master Playback Switch", |
3872 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
3778 | .info = snd_hda_mixer_amp_switch_info, | 3873 | .info = snd_hda_mixer_amp_switch_info, |
3779 | .get = snd_hda_mixer_amp_switch_get, | 3874 | .get = snd_hda_mixer_amp_switch_get, |
3780 | .put = ad1884a_mobile_master_sw_put, | 3875 | .put = ad1884a_mobile_master_sw_put, |
@@ -4116,6 +4211,7 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { | |||
4116 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ | 4211 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ |
4117 | { | 4212 | { |
4118 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 4213 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
4214 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
4119 | .name = "Master Playback Switch", | 4215 | .name = "Master Playback Switch", |
4120 | .info = snd_hda_mixer_amp_switch_info, | 4216 | .info = snd_hda_mixer_amp_switch_info, |
4121 | .get = snd_hda_mixer_amp_switch_get, | 4217 | .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..7de782a5b8f4 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) |
@@ -751,6 +753,7 @@ static int build_input(struct hda_codec *codec) | |||
751 | spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); | 753 | spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); |
752 | for (i = 0; i < 2; i++) { | 754 | for (i = 0; i < 2; i++) { |
753 | struct snd_kcontrol *kctl; | 755 | struct snd_kcontrol *kctl; |
756 | int n; | ||
754 | if (!spec->capture_bind[i]) | 757 | if (!spec->capture_bind[i]) |
755 | return -ENOMEM; | 758 | return -ENOMEM; |
756 | kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); | 759 | kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); |
@@ -760,6 +763,13 @@ static int build_input(struct hda_codec *codec) | |||
760 | err = snd_hda_ctl_add(codec, 0, kctl); | 763 | err = snd_hda_ctl_add(codec, 0, kctl); |
761 | if (err < 0) | 764 | if (err < 0) |
762 | return err; | 765 | return err; |
766 | for (n = 0; n < AUTO_PIN_LAST; n++) { | ||
767 | if (!spec->adc_nid[n]) | ||
768 | continue; | ||
769 | err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[i]); | ||
770 | if (err < 0) | ||
771 | return err; | ||
772 | } | ||
763 | } | 773 | } |
764 | 774 | ||
765 | if (spec->num_inputs > 1 && !spec->mic_detect) { | 775 | 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..ff60908f4554 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,14 @@ 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_nid(codec, kctl, i, spec->adc_nids[i]); | ||
349 | if (err < 0) | ||
350 | return err; | ||
351 | } | ||
343 | return 0; | 352 | return 0; |
344 | } | 353 | } |
345 | 354 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index c578c28f368e..194a28c54992 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -42,10 +42,12 @@ | |||
42 | 42 | ||
43 | /* Conexant 5051 specific */ | 43 | /* Conexant 5051 specific */ |
44 | 44 | ||
45 | #define CXT5051_SPDIF_OUT 0x1C | 45 | #define CXT5051_SPDIF_OUT 0x12 |
46 | #define CXT5051_PORTB_EVENT 0x38 | 46 | #define CXT5051_PORTB_EVENT 0x38 |
47 | #define CXT5051_PORTC_EVENT 0x39 | 47 | #define CXT5051_PORTC_EVENT 0x39 |
48 | 48 | ||
49 | #define AUTO_MIC_PORTB (1 << 1) | ||
50 | #define AUTO_MIC_PORTC (1 << 2) | ||
49 | 51 | ||
50 | struct conexant_jack { | 52 | struct conexant_jack { |
51 | 53 | ||
@@ -74,7 +76,7 @@ struct conexant_spec { | |||
74 | */ | 76 | */ |
75 | unsigned int cur_eapd; | 77 | unsigned int cur_eapd; |
76 | unsigned int hp_present; | 78 | unsigned int hp_present; |
77 | unsigned int no_auto_mic; | 79 | unsigned int auto_mic; |
78 | unsigned int need_dac_fix; | 80 | unsigned int need_dac_fix; |
79 | 81 | ||
80 | /* capture */ | 82 | /* capture */ |
@@ -111,8 +113,23 @@ struct conexant_spec { | |||
111 | 113 | ||
112 | unsigned int dell_automute; | 114 | unsigned int dell_automute; |
113 | unsigned int port_d_mode; | 115 | unsigned int port_d_mode; |
114 | unsigned char ext_mic_bias; | 116 | unsigned int dell_vostro:1; |
115 | unsigned int dell_vostro; | 117 | unsigned int ideapad:1; |
118 | |||
119 | unsigned int ext_mic_present; | ||
120 | unsigned int recording; | ||
121 | void (*capture_prepare)(struct hda_codec *codec); | ||
122 | void (*capture_cleanup)(struct hda_codec *codec); | ||
123 | |||
124 | /* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors) | ||
125 | * through the microphone jack. | ||
126 | * When the user enables this through a mixer switch, both internal and | ||
127 | * external microphones are disabled. Gain is fixed at 0dB. In this mode, | ||
128 | * we also allow the bias to be configured through a separate mixer | ||
129 | * control. */ | ||
130 | unsigned int dc_enable; | ||
131 | unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */ | ||
132 | unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ | ||
116 | }; | 133 | }; |
117 | 134 | ||
118 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, | 135 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, |
@@ -185,6 +202,8 @@ static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
185 | struct snd_pcm_substream *substream) | 202 | struct snd_pcm_substream *substream) |
186 | { | 203 | { |
187 | struct conexant_spec *spec = codec->spec; | 204 | struct conexant_spec *spec = codec->spec; |
205 | if (spec->capture_prepare) | ||
206 | spec->capture_prepare(codec); | ||
188 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | 207 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], |
189 | stream_tag, 0, format); | 208 | stream_tag, 0, format); |
190 | return 0; | 209 | return 0; |
@@ -196,6 +215,8 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
196 | { | 215 | { |
197 | struct conexant_spec *spec = codec->spec; | 216 | struct conexant_spec *spec = codec->spec; |
198 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | 217 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); |
218 | if (spec->capture_cleanup) | ||
219 | spec->capture_cleanup(codec); | ||
199 | return 0; | 220 | return 0; |
200 | } | 221 | } |
201 | 222 | ||
@@ -1585,6 +1606,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec) | |||
1585 | { | 1606 | { |
1586 | struct conexant_spec *spec = codec->spec; | 1607 | struct conexant_spec *spec = codec->spec; |
1587 | unsigned int pinctl; | 1608 | unsigned int pinctl; |
1609 | /* headphone pin */ | ||
1610 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; | ||
1611 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1612 | pinctl); | ||
1613 | /* speaker pin */ | ||
1588 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | 1614 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; |
1589 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 1615 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
1590 | pinctl); | 1616 | pinctl); |
@@ -1608,7 +1634,7 @@ static void cxt5051_portb_automic(struct hda_codec *codec) | |||
1608 | struct conexant_spec *spec = codec->spec; | 1634 | struct conexant_spec *spec = codec->spec; |
1609 | unsigned int present; | 1635 | unsigned int present; |
1610 | 1636 | ||
1611 | if (spec->no_auto_mic) | 1637 | if (!(spec->auto_mic & AUTO_MIC_PORTB)) |
1612 | return; | 1638 | return; |
1613 | present = snd_hda_jack_detect(codec, 0x17); | 1639 | present = snd_hda_jack_detect(codec, 0x17); |
1614 | snd_hda_codec_write(codec, 0x14, 0, | 1640 | snd_hda_codec_write(codec, 0x14, 0, |
@@ -1623,7 +1649,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec) | |||
1623 | unsigned int present; | 1649 | unsigned int present; |
1624 | hda_nid_t new_adc; | 1650 | hda_nid_t new_adc; |
1625 | 1651 | ||
1626 | if (spec->no_auto_mic) | 1652 | if (!(spec->auto_mic & AUTO_MIC_PORTC)) |
1627 | return; | 1653 | return; |
1628 | present = snd_hda_jack_detect(codec, 0x18); | 1654 | present = snd_hda_jack_detect(codec, 0x18); |
1629 | if (present) | 1655 | if (present) |
@@ -1669,13 +1695,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec, | |||
1669 | conexant_report_jack(codec, nid); | 1695 | conexant_report_jack(codec, nid); |
1670 | } | 1696 | } |
1671 | 1697 | ||
1672 | static struct snd_kcontrol_new cxt5051_mixers[] = { | 1698 | static struct snd_kcontrol_new cxt5051_playback_mixers[] = { |
1673 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1674 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1675 | HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1676 | HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1677 | HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1678 | HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1679 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | 1699 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), |
1680 | { | 1700 | { |
1681 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1701 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1685,7 +1705,16 @@ static struct snd_kcontrol_new cxt5051_mixers[] = { | |||
1685 | .put = cxt5051_hp_master_sw_put, | 1705 | .put = cxt5051_hp_master_sw_put, |
1686 | .private_value = 0x1a, | 1706 | .private_value = 0x1a, |
1687 | }, | 1707 | }, |
1708 | {} | ||
1709 | }; | ||
1688 | 1710 | ||
1711 | static struct snd_kcontrol_new cxt5051_capture_mixers[] = { | ||
1712 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1713 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1714 | HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1715 | HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1716 | HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1717 | HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1689 | {} | 1718 | {} |
1690 | }; | 1719 | }; |
1691 | 1720 | ||
@@ -1694,32 +1723,26 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = { | |||
1694 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | 1723 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), |
1695 | HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT), | 1724 | HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT), |
1696 | HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT), | 1725 | HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT), |
1697 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1698 | { | ||
1699 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1700 | .name = "Master Playback Switch", | ||
1701 | .info = cxt_eapd_info, | ||
1702 | .get = cxt_eapd_get, | ||
1703 | .put = cxt5051_hp_master_sw_put, | ||
1704 | .private_value = 0x1a, | ||
1705 | }, | ||
1706 | |||
1707 | {} | 1726 | {} |
1708 | }; | 1727 | }; |
1709 | 1728 | ||
1710 | static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | 1729 | static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { |
1711 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT), | 1730 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT), |
1712 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT), | 1731 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT), |
1713 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | 1732 | {} |
1714 | { | 1733 | }; |
1715 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1716 | .name = "Master Playback Switch", | ||
1717 | .info = cxt_eapd_info, | ||
1718 | .get = cxt_eapd_get, | ||
1719 | .put = cxt5051_hp_master_sw_put, | ||
1720 | .private_value = 0x1a, | ||
1721 | }, | ||
1722 | 1734 | ||
1735 | static struct snd_kcontrol_new cxt5051_f700_mixers[] = { | ||
1736 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT), | ||
1737 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT), | ||
1738 | {} | ||
1739 | }; | ||
1740 | |||
1741 | static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { | ||
1742 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1743 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1744 | HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1745 | HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1723 | {} | 1746 | {} |
1724 | }; | 1747 | }; |
1725 | 1748 | ||
@@ -1748,8 +1771,6 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
1748 | /* EAPD */ | 1771 | /* EAPD */ |
1749 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 1772 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
1750 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | 1773 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, |
1751 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1752 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT}, | ||
1753 | { } /* end */ | 1774 | { } /* end */ |
1754 | }; | 1775 | }; |
1755 | 1776 | ||
@@ -1775,7 +1796,6 @@ static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | |||
1775 | /* EAPD */ | 1796 | /* EAPD */ |
1776 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 1797 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
1777 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | 1798 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, |
1778 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1779 | { } /* end */ | 1799 | { } /* end */ |
1780 | }; | 1800 | }; |
1781 | 1801 | ||
@@ -1807,17 +1827,60 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | |||
1807 | /* EAPD */ | 1827 | /* EAPD */ |
1808 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 1828 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
1809 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | 1829 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, |
1810 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1811 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT}, | ||
1812 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | 1830 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, |
1813 | { } /* end */ | 1831 | { } /* end */ |
1814 | }; | 1832 | }; |
1815 | 1833 | ||
1834 | static struct hda_verb cxt5051_f700_init_verbs[] = { | ||
1835 | /* Line in, Mic */ | ||
1836 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1837 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1838 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1839 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1840 | /* SPK */ | ||
1841 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1842 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1843 | /* HP, Amp */ | ||
1844 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1845 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1846 | /* DAC1 */ | ||
1847 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1848 | /* Record selector: Int mic */ | ||
1849 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1850 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1851 | /* SPDIF route: PCM */ | ||
1852 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1853 | /* EAPD */ | ||
1854 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1855 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1856 | { } /* end */ | ||
1857 | }; | ||
1858 | |||
1859 | static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, | ||
1860 | unsigned int event) | ||
1861 | { | ||
1862 | snd_hda_codec_write(codec, nid, 0, | ||
1863 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1864 | AC_USRSP_EN | event); | ||
1865 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
1866 | conexant_add_jack(codec, nid, SND_JACK_MICROPHONE); | ||
1867 | conexant_report_jack(codec, nid); | ||
1868 | #endif | ||
1869 | } | ||
1870 | |||
1816 | /* initialize jack-sensing, too */ | 1871 | /* initialize jack-sensing, too */ |
1817 | static int cxt5051_init(struct hda_codec *codec) | 1872 | static int cxt5051_init(struct hda_codec *codec) |
1818 | { | 1873 | { |
1874 | struct conexant_spec *spec = codec->spec; | ||
1875 | |||
1819 | conexant_init(codec); | 1876 | conexant_init(codec); |
1820 | conexant_init_jacks(codec); | 1877 | conexant_init_jacks(codec); |
1878 | |||
1879 | if (spec->auto_mic & AUTO_MIC_PORTB) | ||
1880 | cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT); | ||
1881 | if (spec->auto_mic & AUTO_MIC_PORTC) | ||
1882 | cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT); | ||
1883 | |||
1821 | if (codec->patch_ops.unsol_event) { | 1884 | if (codec->patch_ops.unsol_event) { |
1822 | cxt5051_hp_automute(codec); | 1885 | cxt5051_hp_automute(codec); |
1823 | cxt5051_portb_automic(codec); | 1886 | cxt5051_portb_automic(codec); |
@@ -1832,6 +1895,8 @@ enum { | |||
1832 | CXT5051_HP, /* no docking */ | 1895 | CXT5051_HP, /* no docking */ |
1833 | CXT5051_HP_DV6736, /* HP without mic switch */ | 1896 | CXT5051_HP_DV6736, /* HP without mic switch */ |
1834 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ | 1897 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ |
1898 | CXT5051_F700, /* HP Compaq Presario F700 */ | ||
1899 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ | ||
1835 | CXT5051_MODELS | 1900 | CXT5051_MODELS |
1836 | }; | 1901 | }; |
1837 | 1902 | ||
@@ -1840,11 +1905,15 @@ static const char *cxt5051_models[CXT5051_MODELS] = { | |||
1840 | [CXT5051_HP] = "hp", | 1905 | [CXT5051_HP] = "hp", |
1841 | [CXT5051_HP_DV6736] = "hp-dv6736", | 1906 | [CXT5051_HP_DV6736] = "hp-dv6736", |
1842 | [CXT5051_LENOVO_X200] = "lenovo-x200", | 1907 | [CXT5051_LENOVO_X200] = "lenovo-x200", |
1908 | [CXT5051_F700] = "hp-700", | ||
1909 | [CXT5051_TOSHIBA] = "toshiba", | ||
1843 | }; | 1910 | }; |
1844 | 1911 | ||
1845 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | 1912 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { |
1846 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), | 1913 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), |
1847 | SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), | 1914 | SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), |
1915 | SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), | ||
1916 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA), | ||
1848 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | 1917 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", |
1849 | CXT5051_LAPTOP), | 1918 | CXT5051_LAPTOP), |
1850 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | 1919 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), |
@@ -1872,8 +1941,9 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1872 | spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; | 1941 | spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; |
1873 | spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ | 1942 | spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ |
1874 | spec->adc_nids = cxt5051_adc_nids; | 1943 | spec->adc_nids = cxt5051_adc_nids; |
1875 | spec->num_mixers = 1; | 1944 | spec->num_mixers = 2; |
1876 | spec->mixers[0] = cxt5051_mixers; | 1945 | spec->mixers[0] = cxt5051_capture_mixers; |
1946 | spec->mixers[1] = cxt5051_playback_mixers; | ||
1877 | spec->num_init_verbs = 1; | 1947 | spec->num_init_verbs = 1; |
1878 | spec->init_verbs[0] = cxt5051_init_verbs; | 1948 | spec->init_verbs[0] = cxt5051_init_verbs; |
1879 | spec->spdif_route = 0; | 1949 | spec->spdif_route = 0; |
@@ -1887,6 +1957,7 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1887 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, | 1957 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, |
1888 | cxt5051_models, | 1958 | cxt5051_models, |
1889 | cxt5051_cfg_tbl); | 1959 | cxt5051_cfg_tbl); |
1960 | spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC; | ||
1890 | switch (board_config) { | 1961 | switch (board_config) { |
1891 | case CXT5051_HP: | 1962 | case CXT5051_HP: |
1892 | spec->mixers[0] = cxt5051_hp_mixers; | 1963 | spec->mixers[0] = cxt5051_hp_mixers; |
@@ -1894,11 +1965,20 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1894 | case CXT5051_HP_DV6736: | 1965 | case CXT5051_HP_DV6736: |
1895 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; | 1966 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; |
1896 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; | 1967 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; |
1897 | spec->no_auto_mic = 1; | 1968 | spec->auto_mic = 0; |
1898 | break; | 1969 | break; |
1899 | case CXT5051_LENOVO_X200: | 1970 | case CXT5051_LENOVO_X200: |
1900 | spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; | 1971 | spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; |
1901 | break; | 1972 | break; |
1973 | case CXT5051_F700: | ||
1974 | spec->init_verbs[0] = cxt5051_f700_init_verbs; | ||
1975 | spec->mixers[0] = cxt5051_f700_mixers; | ||
1976 | spec->auto_mic = 0; | ||
1977 | break; | ||
1978 | case CXT5051_TOSHIBA: | ||
1979 | spec->mixers[0] = cxt5051_toshiba_mixers; | ||
1980 | spec->auto_mic = AUTO_MIC_PORTB; | ||
1981 | break; | ||
1902 | } | 1982 | } |
1903 | 1983 | ||
1904 | return 0; | 1984 | return 0; |
@@ -1966,33 +2046,117 @@ static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1966 | return 1; | 2046 | return 1; |
1967 | } | 2047 | } |
1968 | 2048 | ||
2049 | static const struct hda_input_mux cxt5066_olpc_dc_bias = { | ||
2050 | .num_items = 3, | ||
2051 | .items = { | ||
2052 | { "Off", PIN_IN }, | ||
2053 | { "50%", PIN_VREF50 }, | ||
2054 | { "80%", PIN_VREF80 }, | ||
2055 | }, | ||
2056 | }; | ||
2057 | |||
2058 | static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec) | ||
2059 | { | ||
2060 | struct conexant_spec *spec = codec->spec; | ||
2061 | /* Even though port F is the DC input, the bias is controlled on port B. | ||
2062 | * we also leave that port as an active input (but unselected) in DC mode | ||
2063 | * just in case that is necessary to make the bias setting take effect. */ | ||
2064 | return snd_hda_codec_write_cache(codec, 0x1a, 0, | ||
2065 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2066 | cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); | ||
2067 | } | ||
2068 | |||
2069 | /* OLPC defers mic widget control until when capture is started because the | ||
2070 | * microphone LED comes on as soon as these settings are put in place. if we | ||
2071 | * did this before recording, it would give the false indication that recording | ||
2072 | * is happening when it is not. */ | ||
2073 | static void cxt5066_olpc_select_mic(struct hda_codec *codec) | ||
2074 | { | ||
2075 | struct conexant_spec *spec = codec->spec; | ||
2076 | if (!spec->recording) | ||
2077 | return; | ||
2078 | |||
2079 | if (spec->dc_enable) { | ||
2080 | /* in DC mode we ignore presence detection and just use the jack | ||
2081 | * through our special DC port */ | ||
2082 | const struct hda_verb enable_dc_mode[] = { | ||
2083 | /* disble internal mic, port C */ | ||
2084 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2085 | |||
2086 | /* enable DC capture, port F */ | ||
2087 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2088 | {}, | ||
2089 | }; | ||
2090 | |||
2091 | snd_hda_sequence_write(codec, enable_dc_mode); | ||
2092 | /* port B input disabled (and bias set) through the following call */ | ||
2093 | cxt5066_set_olpc_dc_bias(codec); | ||
2094 | return; | ||
2095 | } | ||
2096 | |||
2097 | /* disable DC (port F) */ | ||
2098 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
2099 | |||
2100 | /* external mic, port B */ | ||
2101 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2102 | spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); | ||
2103 | |||
2104 | /* internal mic, port C */ | ||
2105 | snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2106 | spec->ext_mic_present ? 0 : PIN_VREF80); | ||
2107 | } | ||
2108 | |||
1969 | /* toggle input of built-in and mic jack appropriately */ | 2109 | /* toggle input of built-in and mic jack appropriately */ |
1970 | static void cxt5066_automic(struct hda_codec *codec) | 2110 | static void cxt5066_olpc_automic(struct hda_codec *codec) |
1971 | { | 2111 | { |
1972 | struct conexant_spec *spec = codec->spec; | 2112 | struct conexant_spec *spec = codec->spec; |
2113 | unsigned int present; | ||
2114 | |||
2115 | if (spec->dc_enable) /* don't do presence detection in DC mode */ | ||
2116 | return; | ||
2117 | |||
2118 | present = snd_hda_codec_read(codec, 0x1a, 0, | ||
2119 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
2120 | if (present) | ||
2121 | snd_printdd("CXT5066: external microphone detected\n"); | ||
2122 | else | ||
2123 | snd_printdd("CXT5066: external microphone absent\n"); | ||
2124 | |||
2125 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
2126 | present ? 0 : 1); | ||
2127 | spec->ext_mic_present = !!present; | ||
2128 | |||
2129 | cxt5066_olpc_select_mic(codec); | ||
2130 | } | ||
2131 | |||
2132 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
2133 | static void cxt5066_vostro_automic(struct hda_codec *codec) | ||
2134 | { | ||
2135 | unsigned int present; | ||
2136 | |||
1973 | struct hda_verb ext_mic_present[] = { | 2137 | struct hda_verb ext_mic_present[] = { |
1974 | /* enable external mic, port B */ | 2138 | /* enable external mic, port B */ |
1975 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias}, | 2139 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
1976 | 2140 | ||
1977 | /* switch to external mic input */ | 2141 | /* switch to external mic input */ |
1978 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | 2142 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, |
2143 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1979 | 2144 | ||
1980 | /* disable internal mic, port C */ | 2145 | /* disable internal digital mic */ |
1981 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2146 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
1982 | {} | 2147 | {} |
1983 | }; | 2148 | }; |
1984 | static struct hda_verb ext_mic_absent[] = { | 2149 | static struct hda_verb ext_mic_absent[] = { |
1985 | /* enable internal mic, port C */ | 2150 | /* enable internal mic, port C */ |
1986 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 2151 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1987 | 2152 | ||
1988 | /* switch to internal mic input */ | 2153 | /* switch to internal mic input */ |
1989 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, | 2154 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, |
1990 | 2155 | ||
1991 | /* disable external mic, port B */ | 2156 | /* disable external mic, port B */ |
1992 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2157 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
1993 | {} | 2158 | {} |
1994 | }; | 2159 | }; |
1995 | unsigned int present; | ||
1996 | 2160 | ||
1997 | present = snd_hda_jack_detect(codec, 0x1a); | 2161 | present = snd_hda_jack_detect(codec, 0x1a); |
1998 | if (present) { | 2162 | if (present) { |
@@ -2005,36 +2169,24 @@ static void cxt5066_automic(struct hda_codec *codec) | |||
2005 | } | 2169 | } |
2006 | 2170 | ||
2007 | /* toggle input of built-in digital mic and mic jack appropriately */ | 2171 | /* toggle input of built-in digital mic and mic jack appropriately */ |
2008 | static void cxt5066_vostro_automic(struct hda_codec *codec) | 2172 | static void cxt5066_ideapad_automic(struct hda_codec *codec) |
2009 | { | 2173 | { |
2010 | struct conexant_spec *spec = codec->spec; | ||
2011 | unsigned int present; | 2174 | unsigned int present; |
2012 | 2175 | ||
2013 | struct hda_verb ext_mic_present[] = { | 2176 | struct hda_verb ext_mic_present[] = { |
2014 | /* enable external mic, port B */ | ||
2015 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias}, | ||
2016 | |||
2017 | /* switch to external mic input */ | ||
2018 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2019 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | 2177 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, |
2020 | 2178 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | |
2021 | /* disable internal digital mic */ | ||
2022 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2179 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2023 | {} | 2180 | {} |
2024 | }; | 2181 | }; |
2025 | static struct hda_verb ext_mic_absent[] = { | 2182 | static struct hda_verb ext_mic_absent[] = { |
2026 | /* enable internal mic, port C */ | ||
2027 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2028 | |||
2029 | /* switch to internal mic input */ | ||
2030 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | 2183 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, |
2031 | 2184 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | |
2032 | /* disable external mic, port B */ | 2185 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2033 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2034 | {} | 2186 | {} |
2035 | }; | 2187 | }; |
2036 | 2188 | ||
2037 | present = snd_hda_jack_detect(codec, 0x1a); | 2189 | present = snd_hda_jack_detect(codec, 0x1b); |
2038 | if (present) { | 2190 | if (present) { |
2039 | snd_printdd("CXT5066: external microphone detected\n"); | 2191 | snd_printdd("CXT5066: external microphone detected\n"); |
2040 | snd_hda_sequence_write(codec, ext_mic_present); | 2192 | snd_hda_sequence_write(codec, ext_mic_present); |
@@ -2063,15 +2215,18 @@ static void cxt5066_hp_automute(struct hda_codec *codec) | |||
2063 | } | 2215 | } |
2064 | 2216 | ||
2065 | /* unsolicited event for jack sensing */ | 2217 | /* unsolicited event for jack sensing */ |
2066 | static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) | 2218 | static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) |
2067 | { | 2219 | { |
2220 | struct conexant_spec *spec = codec->spec; | ||
2068 | snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); | 2221 | snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); |
2069 | switch (res >> 26) { | 2222 | switch (res >> 26) { |
2070 | case CONEXANT_HP_EVENT: | 2223 | case CONEXANT_HP_EVENT: |
2071 | cxt5066_hp_automute(codec); | 2224 | cxt5066_hp_automute(codec); |
2072 | break; | 2225 | break; |
2073 | case CONEXANT_MIC_EVENT: | 2226 | case CONEXANT_MIC_EVENT: |
2074 | cxt5066_automic(codec); | 2227 | /* ignore mic events in DC mode; we're always using the jack */ |
2228 | if (!spec->dc_enable) | ||
2229 | cxt5066_olpc_automic(codec); | ||
2075 | break; | 2230 | break; |
2076 | } | 2231 | } |
2077 | } | 2232 | } |
@@ -2090,6 +2245,20 @@ static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res) | |||
2090 | } | 2245 | } |
2091 | } | 2246 | } |
2092 | 2247 | ||
2248 | /* unsolicited event for jack sensing */ | ||
2249 | static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res) | ||
2250 | { | ||
2251 | snd_printdd("CXT5066_ideapad: unsol event %x (%x)\n", res, res >> 26); | ||
2252 | switch (res >> 26) { | ||
2253 | case CONEXANT_HP_EVENT: | ||
2254 | cxt5066_hp_automute(codec); | ||
2255 | break; | ||
2256 | case CONEXANT_MIC_EVENT: | ||
2257 | cxt5066_ideapad_automic(codec); | ||
2258 | break; | ||
2259 | } | ||
2260 | } | ||
2261 | |||
2093 | static const struct hda_input_mux cxt5066_analog_mic_boost = { | 2262 | static const struct hda_input_mux cxt5066_analog_mic_boost = { |
2094 | .num_items = 5, | 2263 | .num_items = 5, |
2095 | .items = { | 2264 | .items = { |
@@ -2101,6 +2270,23 @@ static const struct hda_input_mux cxt5066_analog_mic_boost = { | |||
2101 | }, | 2270 | }, |
2102 | }; | 2271 | }; |
2103 | 2272 | ||
2273 | static void cxt5066_set_mic_boost(struct hda_codec *codec) | ||
2274 | { | ||
2275 | struct conexant_spec *spec = codec->spec; | ||
2276 | snd_hda_codec_write_cache(codec, 0x17, 0, | ||
2277 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2278 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | | ||
2279 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); | ||
2280 | if (spec->ideapad) { | ||
2281 | /* adjust the internal mic as well...it is not through 0x17 */ | ||
2282 | snd_hda_codec_write_cache(codec, 0x23, 0, | ||
2283 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2284 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT | | ||
2285 | cxt5066_analog_mic_boost. | ||
2286 | items[spec->mic_boost].index); | ||
2287 | } | ||
2288 | } | ||
2289 | |||
2104 | static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, | 2290 | static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, |
2105 | struct snd_ctl_elem_info *uinfo) | 2291 | struct snd_ctl_elem_info *uinfo) |
2106 | { | 2292 | { |
@@ -2111,15 +2297,8 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, | |||
2111 | struct snd_ctl_elem_value *ucontrol) | 2297 | struct snd_ctl_elem_value *ucontrol) |
2112 | { | 2298 | { |
2113 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2299 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2114 | int val; | 2300 | struct conexant_spec *spec = codec->spec; |
2115 | hda_nid_t nid = kcontrol->private_value & 0xff; | 2301 | ucontrol->value.enumerated.item[0] = spec->mic_boost; |
2116 | int inout = (kcontrol->private_value & 0x100) ? | ||
2117 | AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT; | ||
2118 | |||
2119 | val = snd_hda_codec_read(codec, nid, 0, | ||
2120 | AC_VERB_GET_AMP_GAIN_MUTE, inout); | ||
2121 | |||
2122 | ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN; | ||
2123 | return 0; | 2302 | return 0; |
2124 | } | 2303 | } |
2125 | 2304 | ||
@@ -2127,26 +2306,132 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
2127 | struct snd_ctl_elem_value *ucontrol) | 2306 | struct snd_ctl_elem_value *ucontrol) |
2128 | { | 2307 | { |
2129 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2308 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2309 | struct conexant_spec *spec = codec->spec; | ||
2130 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; | 2310 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; |
2131 | unsigned int idx; | 2311 | unsigned int idx; |
2132 | hda_nid_t nid = kcontrol->private_value & 0xff; | 2312 | idx = ucontrol->value.enumerated.item[0]; |
2133 | int inout = (kcontrol->private_value & 0x100) ? | 2313 | if (idx >= imux->num_items) |
2134 | AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT; | 2314 | idx = imux->num_items - 1; |
2315 | |||
2316 | spec->mic_boost = idx; | ||
2317 | if (!spec->dc_enable) | ||
2318 | cxt5066_set_mic_boost(codec); | ||
2319 | return 1; | ||
2320 | } | ||
2321 | |||
2322 | static void cxt5066_enable_dc(struct hda_codec *codec) | ||
2323 | { | ||
2324 | const struct hda_verb enable_dc_mode[] = { | ||
2325 | /* disable gain */ | ||
2326 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2327 | |||
2328 | /* switch to DC input */ | ||
2329 | {0x17, AC_VERB_SET_CONNECT_SEL, 3}, | ||
2330 | {} | ||
2331 | }; | ||
2332 | |||
2333 | /* configure as input source */ | ||
2334 | snd_hda_sequence_write(codec, enable_dc_mode); | ||
2335 | cxt5066_olpc_select_mic(codec); /* also sets configured bias */ | ||
2336 | } | ||
2337 | |||
2338 | static void cxt5066_disable_dc(struct hda_codec *codec) | ||
2339 | { | ||
2340 | /* reconfigure input source */ | ||
2341 | cxt5066_set_mic_boost(codec); | ||
2342 | /* automic also selects the right mic if we're recording */ | ||
2343 | cxt5066_olpc_automic(codec); | ||
2344 | } | ||
2345 | |||
2346 | static int cxt5066_olpc_dc_get(struct snd_kcontrol *kcontrol, | ||
2347 | struct snd_ctl_elem_value *ucontrol) | ||
2348 | { | ||
2349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2350 | struct conexant_spec *spec = codec->spec; | ||
2351 | ucontrol->value.integer.value[0] = spec->dc_enable; | ||
2352 | return 0; | ||
2353 | } | ||
2135 | 2354 | ||
2136 | if (!imux->num_items) | 2355 | static int cxt5066_olpc_dc_put(struct snd_kcontrol *kcontrol, |
2356 | struct snd_ctl_elem_value *ucontrol) | ||
2357 | { | ||
2358 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2359 | struct conexant_spec *spec = codec->spec; | ||
2360 | int dc_enable = !!ucontrol->value.integer.value[0]; | ||
2361 | |||
2362 | if (dc_enable == spec->dc_enable) | ||
2137 | return 0; | 2363 | return 0; |
2364 | |||
2365 | spec->dc_enable = dc_enable; | ||
2366 | if (dc_enable) | ||
2367 | cxt5066_enable_dc(codec); | ||
2368 | else | ||
2369 | cxt5066_disable_dc(codec); | ||
2370 | |||
2371 | return 1; | ||
2372 | } | ||
2373 | |||
2374 | static int cxt5066_olpc_dc_bias_enum_info(struct snd_kcontrol *kcontrol, | ||
2375 | struct snd_ctl_elem_info *uinfo) | ||
2376 | { | ||
2377 | return snd_hda_input_mux_info(&cxt5066_olpc_dc_bias, uinfo); | ||
2378 | } | ||
2379 | |||
2380 | static int cxt5066_olpc_dc_bias_enum_get(struct snd_kcontrol *kcontrol, | ||
2381 | struct snd_ctl_elem_value *ucontrol) | ||
2382 | { | ||
2383 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2384 | struct conexant_spec *spec = codec->spec; | ||
2385 | ucontrol->value.enumerated.item[0] = spec->dc_input_bias; | ||
2386 | return 0; | ||
2387 | } | ||
2388 | |||
2389 | static int cxt5066_olpc_dc_bias_enum_put(struct snd_kcontrol *kcontrol, | ||
2390 | struct snd_ctl_elem_value *ucontrol) | ||
2391 | { | ||
2392 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2393 | struct conexant_spec *spec = codec->spec; | ||
2394 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; | ||
2395 | unsigned int idx; | ||
2396 | |||
2138 | idx = ucontrol->value.enumerated.item[0]; | 2397 | idx = ucontrol->value.enumerated.item[0]; |
2139 | if (idx >= imux->num_items) | 2398 | if (idx >= imux->num_items) |
2140 | idx = imux->num_items - 1; | 2399 | idx = imux->num_items - 1; |
2141 | 2400 | ||
2142 | snd_hda_codec_write_cache(codec, nid, 0, | 2401 | spec->dc_input_bias = idx; |
2143 | AC_VERB_SET_AMP_GAIN_MUTE, | 2402 | if (spec->dc_enable) |
2144 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout | | 2403 | cxt5066_set_olpc_dc_bias(codec); |
2145 | imux->items[idx].index); | ||
2146 | |||
2147 | return 1; | 2404 | return 1; |
2148 | } | 2405 | } |
2149 | 2406 | ||
2407 | static void cxt5066_olpc_capture_prepare(struct hda_codec *codec) | ||
2408 | { | ||
2409 | struct conexant_spec *spec = codec->spec; | ||
2410 | /* mark as recording and configure the microphone widget so that the | ||
2411 | * recording LED comes on. */ | ||
2412 | spec->recording = 1; | ||
2413 | cxt5066_olpc_select_mic(codec); | ||
2414 | } | ||
2415 | |||
2416 | static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec) | ||
2417 | { | ||
2418 | struct conexant_spec *spec = codec->spec; | ||
2419 | const struct hda_verb disable_mics[] = { | ||
2420 | /* disable external mic, port B */ | ||
2421 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2422 | |||
2423 | /* disble internal mic, port C */ | ||
2424 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2425 | |||
2426 | /* disable DC capture, port F */ | ||
2427 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2428 | {}, | ||
2429 | }; | ||
2430 | |||
2431 | snd_hda_sequence_write(codec, disable_mics); | ||
2432 | spec->recording = 0; | ||
2433 | } | ||
2434 | |||
2150 | static struct hda_input_mux cxt5066_capture_source = { | 2435 | static struct hda_input_mux cxt5066_capture_source = { |
2151 | .num_items = 4, | 2436 | .num_items = 4, |
2152 | .items = { | 2437 | .items = { |
@@ -2187,6 +2472,7 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { | |||
2187 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 2472 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
2188 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 2473 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
2189 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | 2474 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, |
2475 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
2190 | .info = snd_hda_mixer_amp_volume_info, | 2476 | .info = snd_hda_mixer_amp_volume_info, |
2191 | .get = snd_hda_mixer_amp_volume_get, | 2477 | .get = snd_hda_mixer_amp_volume_get, |
2192 | .put = snd_hda_mixer_amp_volume_put, | 2478 | .put = snd_hda_mixer_amp_volume_put, |
@@ -2198,6 +2484,24 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { | |||
2198 | {} | 2484 | {} |
2199 | }; | 2485 | }; |
2200 | 2486 | ||
2487 | static struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = { | ||
2488 | { | ||
2489 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2490 | .name = "DC Mode Enable Switch", | ||
2491 | .info = snd_ctl_boolean_mono_info, | ||
2492 | .get = cxt5066_olpc_dc_get, | ||
2493 | .put = cxt5066_olpc_dc_put, | ||
2494 | }, | ||
2495 | { | ||
2496 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2497 | .name = "DC Input Bias Enum", | ||
2498 | .info = cxt5066_olpc_dc_bias_enum_info, | ||
2499 | .get = cxt5066_olpc_dc_bias_enum_get, | ||
2500 | .put = cxt5066_olpc_dc_bias_enum_put, | ||
2501 | }, | ||
2502 | {} | ||
2503 | }; | ||
2504 | |||
2201 | static struct snd_kcontrol_new cxt5066_mixers[] = { | 2505 | static struct snd_kcontrol_new cxt5066_mixers[] = { |
2202 | { | 2506 | { |
2203 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2507 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -2210,11 +2514,10 @@ static struct snd_kcontrol_new cxt5066_mixers[] = { | |||
2210 | 2514 | ||
2211 | { | 2515 | { |
2212 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2516 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2213 | .name = "Ext Mic Boost Capture Enum", | 2517 | .name = "Analog Mic Boost Capture Enum", |
2214 | .info = cxt5066_mic_boost_mux_enum_info, | 2518 | .info = cxt5066_mic_boost_mux_enum_info, |
2215 | .get = cxt5066_mic_boost_mux_enum_get, | 2519 | .get = cxt5066_mic_boost_mux_enum_get, |
2216 | .put = cxt5066_mic_boost_mux_enum_put, | 2520 | .put = cxt5066_mic_boost_mux_enum_put, |
2217 | .private_value = 0x17, | ||
2218 | }, | 2521 | }, |
2219 | 2522 | ||
2220 | HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), | 2523 | HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), |
@@ -2296,10 +2599,10 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = { | |||
2296 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | 2599 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ |
2297 | 2600 | ||
2298 | /* Port B: external microphone */ | 2601 | /* Port B: external microphone */ |
2299 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, CXT5066_OLPC_EXT_MIC_BIAS}, | 2602 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2300 | 2603 | ||
2301 | /* Port C: internal microphone */ | 2604 | /* Port C: internal microphone */ |
2302 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 2605 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2303 | 2606 | ||
2304 | /* Port D: unused */ | 2607 | /* Port D: unused */ |
2305 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2608 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
@@ -2308,7 +2611,7 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = { | |||
2308 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2611 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2309 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 2612 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
2310 | 2613 | ||
2311 | /* Port F: unused */ | 2614 | /* Port F: external DC input through microphone port */ |
2312 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2615 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2313 | 2616 | ||
2314 | /* Port G: internal speakers */ | 2617 | /* Port G: internal speakers */ |
@@ -2412,6 +2715,56 @@ static struct hda_verb cxt5066_init_verbs_vostro[] = { | |||
2412 | { } /* end */ | 2715 | { } /* end */ |
2413 | }; | 2716 | }; |
2414 | 2717 | ||
2718 | static struct hda_verb cxt5066_init_verbs_ideapad[] = { | ||
2719 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ | ||
2720 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ | ||
2721 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2722 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2723 | |||
2724 | /* Speakers */ | ||
2725 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2726 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2727 | |||
2728 | /* HP, Amp */ | ||
2729 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2730 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2731 | |||
2732 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2733 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2734 | |||
2735 | /* DAC1 */ | ||
2736 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2737 | |||
2738 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2739 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2740 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2741 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2742 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2743 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2744 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2745 | |||
2746 | /* Audio input selector */ | ||
2747 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2748 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2749 | |||
2750 | /* SPDIF route: PCM */ | ||
2751 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2752 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2753 | |||
2754 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2755 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2756 | |||
2757 | /* internal microphone */ | ||
2758 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */ | ||
2759 | |||
2760 | /* EAPD */ | ||
2761 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2762 | |||
2763 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2764 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2765 | { } /* end */ | ||
2766 | }; | ||
2767 | |||
2415 | static struct hda_verb cxt5066_init_verbs_portd_lo[] = { | 2768 | static struct hda_verb cxt5066_init_verbs_portd_lo[] = { |
2416 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 2769 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
2417 | { } /* end */ | 2770 | { } /* end */ |
@@ -2428,8 +2781,24 @@ static int cxt5066_init(struct hda_codec *codec) | |||
2428 | cxt5066_hp_automute(codec); | 2781 | cxt5066_hp_automute(codec); |
2429 | if (spec->dell_vostro) | 2782 | if (spec->dell_vostro) |
2430 | cxt5066_vostro_automic(codec); | 2783 | cxt5066_vostro_automic(codec); |
2431 | else | 2784 | else if (spec->ideapad) |
2432 | cxt5066_automic(codec); | 2785 | cxt5066_ideapad_automic(codec); |
2786 | } | ||
2787 | cxt5066_set_mic_boost(codec); | ||
2788 | return 0; | ||
2789 | } | ||
2790 | |||
2791 | static int cxt5066_olpc_init(struct hda_codec *codec) | ||
2792 | { | ||
2793 | struct conexant_spec *spec = codec->spec; | ||
2794 | snd_printdd("CXT5066: init\n"); | ||
2795 | conexant_init(codec); | ||
2796 | cxt5066_hp_automute(codec); | ||
2797 | if (!spec->dc_enable) { | ||
2798 | cxt5066_set_mic_boost(codec); | ||
2799 | cxt5066_olpc_automic(codec); | ||
2800 | } else { | ||
2801 | cxt5066_enable_dc(codec); | ||
2433 | } | 2802 | } |
2434 | return 0; | 2803 | return 0; |
2435 | } | 2804 | } |
@@ -2439,6 +2808,7 @@ enum { | |||
2439 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | 2808 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ |
2440 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ | 2809 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ |
2441 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ | 2810 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ |
2811 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | ||
2442 | CXT5066_MODELS | 2812 | CXT5066_MODELS |
2443 | }; | 2813 | }; |
2444 | 2814 | ||
@@ -2446,7 +2816,8 @@ static const char *cxt5066_models[CXT5066_MODELS] = { | |||
2446 | [CXT5066_LAPTOP] = "laptop", | 2816 | [CXT5066_LAPTOP] = "laptop", |
2447 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | 2817 | [CXT5066_DELL_LAPTOP] = "dell-laptop", |
2448 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", | 2818 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", |
2449 | [CXT5066_DELL_VOSTO] = "dell-vostro" | 2819 | [CXT5066_DELL_VOSTO] = "dell-vostro", |
2820 | [CXT5066_IDEAPAD] = "ideapad", | ||
2450 | }; | 2821 | }; |
2451 | 2822 | ||
2452 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | 2823 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { |
@@ -2456,6 +2827,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
2456 | CXT5066_DELL_LAPTOP), | 2827 | CXT5066_DELL_LAPTOP), |
2457 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), | 2828 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), |
2458 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), | 2829 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), |
2830 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), | ||
2459 | {} | 2831 | {} |
2460 | }; | 2832 | }; |
2461 | 2833 | ||
@@ -2470,7 +2842,7 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
2470 | codec->spec = spec; | 2842 | codec->spec = spec; |
2471 | 2843 | ||
2472 | codec->patch_ops = conexant_patch_ops; | 2844 | codec->patch_ops = conexant_patch_ops; |
2473 | codec->patch_ops.init = cxt5066_init; | 2845 | codec->patch_ops.init = conexant_init; |
2474 | 2846 | ||
2475 | spec->dell_automute = 0; | 2847 | spec->dell_automute = 0; |
2476 | spec->multiout.max_channels = 2; | 2848 | spec->multiout.max_channels = 2; |
@@ -2483,7 +2855,6 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
2483 | spec->input_mux = &cxt5066_capture_source; | 2855 | spec->input_mux = &cxt5066_capture_source; |
2484 | 2856 | ||
2485 | spec->port_d_mode = PIN_HP; | 2857 | spec->port_d_mode = PIN_HP; |
2486 | spec->ext_mic_bias = PIN_VREF80; | ||
2487 | 2858 | ||
2488 | spec->num_init_verbs = 1; | 2859 | spec->num_init_verbs = 1; |
2489 | spec->init_verbs[0] = cxt5066_init_verbs; | 2860 | spec->init_verbs[0] = cxt5066_init_verbs; |
@@ -2510,20 +2881,28 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
2510 | spec->dell_automute = 1; | 2881 | spec->dell_automute = 1; |
2511 | break; | 2882 | break; |
2512 | case CXT5066_OLPC_XO_1_5: | 2883 | case CXT5066_OLPC_XO_1_5: |
2513 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | 2884 | codec->patch_ops.init = cxt5066_olpc_init; |
2885 | codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; | ||
2514 | spec->init_verbs[0] = cxt5066_init_verbs_olpc; | 2886 | spec->init_verbs[0] = cxt5066_init_verbs_olpc; |
2515 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; | 2887 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; |
2888 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_olpc_dc; | ||
2516 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | 2889 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; |
2517 | spec->port_d_mode = 0; | 2890 | spec->port_d_mode = 0; |
2518 | spec->ext_mic_bias = CXT5066_OLPC_EXT_MIC_BIAS; | 2891 | spec->mic_boost = 3; /* default 30dB gain */ |
2519 | 2892 | ||
2520 | /* no S/PDIF out */ | 2893 | /* no S/PDIF out */ |
2521 | spec->multiout.dig_out_nid = 0; | 2894 | spec->multiout.dig_out_nid = 0; |
2522 | 2895 | ||
2523 | /* input source automatically selected */ | 2896 | /* input source automatically selected */ |
2524 | spec->input_mux = NULL; | 2897 | spec->input_mux = NULL; |
2898 | |||
2899 | /* our capture hooks which allow us to turn on the microphone LED | ||
2900 | * at the right time */ | ||
2901 | spec->capture_prepare = cxt5066_olpc_capture_prepare; | ||
2902 | spec->capture_cleanup = cxt5066_olpc_capture_cleanup; | ||
2525 | break; | 2903 | break; |
2526 | case CXT5066_DELL_VOSTO: | 2904 | case CXT5066_DELL_VOSTO: |
2905 | codec->patch_ops.init = cxt5066_init; | ||
2527 | codec->patch_ops.unsol_event = cxt5066_vostro_event; | 2906 | codec->patch_ops.unsol_event = cxt5066_vostro_event; |
2528 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; | 2907 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; |
2529 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; | 2908 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; |
@@ -2531,6 +2910,7 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
2531 | spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; | 2910 | spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; |
2532 | spec->port_d_mode = 0; | 2911 | spec->port_d_mode = 0; |
2533 | spec->dell_vostro = 1; | 2912 | spec->dell_vostro = 1; |
2913 | spec->mic_boost = 3; /* default 30dB gain */ | ||
2534 | snd_hda_attach_beep_device(codec, 0x13); | 2914 | snd_hda_attach_beep_device(codec, 0x13); |
2535 | 2915 | ||
2536 | /* no S/PDIF out */ | 2916 | /* no S/PDIF out */ |
@@ -2539,6 +2919,22 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
2539 | /* input source automatically selected */ | 2919 | /* input source automatically selected */ |
2540 | spec->input_mux = NULL; | 2920 | spec->input_mux = NULL; |
2541 | break; | 2921 | break; |
2922 | case CXT5066_IDEAPAD: | ||
2923 | codec->patch_ops.init = cxt5066_init; | ||
2924 | codec->patch_ops.unsol_event = cxt5066_ideapad_event; | ||
2925 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2926 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2927 | spec->init_verbs[0] = cxt5066_init_verbs_ideapad; | ||
2928 | spec->port_d_mode = 0; | ||
2929 | spec->ideapad = 1; | ||
2930 | spec->mic_boost = 2; /* default 20dB gain */ | ||
2931 | |||
2932 | /* no S/PDIF out */ | ||
2933 | spec->multiout.dig_out_nid = 0; | ||
2934 | |||
2935 | /* input source automatically selected */ | ||
2936 | spec->input_mux = NULL; | ||
2937 | break; | ||
2542 | } | 2938 | } |
2543 | 2939 | ||
2544 | return 0; | 2940 | return 0; |
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 6afdab09bab7..1c774f942407 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c | |||
@@ -32,10 +32,11 @@ | |||
32 | /* define below to restrict the supported rates and formats */ | 32 | /* define below to restrict the supported rates and formats */ |
33 | /* #define LIMITED_RATE_FMT_SUPPORT */ | 33 | /* #define LIMITED_RATE_FMT_SUPPORT */ |
34 | 34 | ||
35 | struct nvhdmi_spec { | 35 | enum HDACodec { |
36 | struct hda_multi_out multiout; | 36 | HDA_CODEC_NVIDIA_MCP7X, |
37 | 37 | HDA_CODEC_NVIDIA_MCP89, | |
38 | struct hda_pcm pcm_rec; | 38 | HDA_CODEC_NVIDIA_GT21X, |
39 | HDA_CODEC_INVALID | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | 42 | #define Nv_VERB_SET_Channel_Allocation 0xF79 |
@@ -43,15 +44,18 @@ struct nvhdmi_spec { | |||
43 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | 44 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 |
44 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | 45 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 |
45 | 46 | ||
46 | #define Nv_Master_Convert_nid 0x04 | 47 | #define nvhdmi_master_con_nid_7x 0x04 |
47 | #define Nv_Master_Pin_nid 0x05 | 48 | #define nvhdmi_master_pin_nid_7x 0x05 |
48 | 49 | ||
49 | static hda_nid_t nvhdmi_convert_nids[4] = { | 50 | #define nvhdmi_master_con_nid_89 0x04 |
51 | #define nvhdmi_master_pin_nid_89 0x05 | ||
52 | |||
53 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
50 | /*front, rear, clfe, rear_surr */ | 54 | /*front, rear, clfe, rear_surr */ |
51 | 0x6, 0x8, 0xa, 0xc, | 55 | 0x6, 0x8, 0xa, 0xc, |
52 | }; | 56 | }; |
53 | 57 | ||
54 | static struct hda_verb nvhdmi_basic_init[] = { | 58 | static struct hda_verb nvhdmi_basic_init_7x[] = { |
55 | /* set audio protect on */ | 59 | /* set audio protect on */ |
56 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 60 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
57 | /* enable digital output on pin widget */ | 61 | /* enable digital output on pin widget */ |
@@ -79,6 +83,796 @@ static struct hda_verb nvhdmi_basic_init[] = { | |||
79 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | 83 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
80 | #endif | 84 | #endif |
81 | 85 | ||
86 | #define NVIDIA_89_HDMI_CVTS 1 | ||
87 | #define NVIDIA_89_HDMI_PINS 1 | ||
88 | |||
89 | static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = { | ||
90 | "NVIDIA HDMI", | ||
91 | }; | ||
92 | |||
93 | struct nvhdmi_spec { | ||
94 | int num_cvts; | ||
95 | int num_pins; | ||
96 | hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1]; /* audio sources */ | ||
97 | hda_nid_t pin[NVIDIA_89_HDMI_PINS+1]; /* audio sinks */ | ||
98 | hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1]; | ||
99 | struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS]; | ||
100 | struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS]; | ||
101 | struct hda_multi_out multiout; | ||
102 | unsigned int codec_type; | ||
103 | }; | ||
104 | |||
105 | struct hdmi_audio_infoframe { | ||
106 | u8 type; /* 0x84 */ | ||
107 | u8 ver; /* 0x01 */ | ||
108 | u8 len; /* 0x0a */ | ||
109 | |||
110 | u8 checksum; /* PB0 */ | ||
111 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | ||
112 | u8 SS01_SF24; | ||
113 | u8 CXT04; | ||
114 | u8 CA; | ||
115 | u8 LFEPBL01_LSV36_DM_INH7; | ||
116 | }; | ||
117 | |||
118 | /* | ||
119 | * CEA speaker placement: | ||
120 | * | ||
121 | * FLH FCH FRH | ||
122 | * FLW FL FLC FC FRC FR FRW | ||
123 | * | ||
124 | * LFE | ||
125 | * TC | ||
126 | * | ||
127 | * RL RLC RC RRC RR | ||
128 | * | ||
129 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | ||
130 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | ||
131 | */ | ||
132 | enum cea_speaker_placement { | ||
133 | FL = (1 << 0), /* Front Left */ | ||
134 | FC = (1 << 1), /* Front Center */ | ||
135 | FR = (1 << 2), /* Front Right */ | ||
136 | FLC = (1 << 3), /* Front Left Center */ | ||
137 | FRC = (1 << 4), /* Front Right Center */ | ||
138 | RL = (1 << 5), /* Rear Left */ | ||
139 | RC = (1 << 6), /* Rear Center */ | ||
140 | RR = (1 << 7), /* Rear Right */ | ||
141 | RLC = (1 << 8), /* Rear Left Center */ | ||
142 | RRC = (1 << 9), /* Rear Right Center */ | ||
143 | LFE = (1 << 10), /* Low Frequency Effect */ | ||
144 | FLW = (1 << 11), /* Front Left Wide */ | ||
145 | FRW = (1 << 12), /* Front Right Wide */ | ||
146 | FLH = (1 << 13), /* Front Left High */ | ||
147 | FCH = (1 << 14), /* Front Center High */ | ||
148 | FRH = (1 << 15), /* Front Right High */ | ||
149 | TC = (1 << 16), /* Top Center */ | ||
150 | }; | ||
151 | |||
152 | /* | ||
153 | * ELD SA bits in the CEA Speaker Allocation data block | ||
154 | */ | ||
155 | static int eld_speaker_allocation_bits[] = { | ||
156 | [0] = FL | FR, | ||
157 | [1] = LFE, | ||
158 | [2] = FC, | ||
159 | [3] = RL | RR, | ||
160 | [4] = RC, | ||
161 | [5] = FLC | FRC, | ||
162 | [6] = RLC | RRC, | ||
163 | /* the following are not defined in ELD yet */ | ||
164 | [7] = FLW | FRW, | ||
165 | [8] = FLH | FRH, | ||
166 | [9] = TC, | ||
167 | [10] = FCH, | ||
168 | }; | ||
169 | |||
170 | struct cea_channel_speaker_allocation { | ||
171 | int ca_index; | ||
172 | int speakers[8]; | ||
173 | |||
174 | /* derived values, just for convenience */ | ||
175 | int channels; | ||
176 | int spk_mask; | ||
177 | }; | ||
178 | |||
179 | /* | ||
180 | * ALSA sequence is: | ||
181 | * | ||
182 | * surround40 surround41 surround50 surround51 surround71 | ||
183 | * ch0 front left = = = = | ||
184 | * ch1 front right = = = = | ||
185 | * ch2 rear left = = = = | ||
186 | * ch3 rear right = = = = | ||
187 | * ch4 LFE center center center | ||
188 | * ch5 LFE LFE | ||
189 | * ch6 side left | ||
190 | * ch7 side right | ||
191 | * | ||
192 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | ||
193 | */ | ||
194 | static int hdmi_channel_mapping[0x32][8] = { | ||
195 | /* stereo */ | ||
196 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
197 | /* 2.1 */ | ||
198 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
199 | /* Dolby Surround */ | ||
200 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
201 | /* surround40 */ | ||
202 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | ||
203 | /* 4ch */ | ||
204 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | ||
205 | /* surround41 */ | ||
206 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
207 | /* surround50 */ | ||
208 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
209 | /* surround51 */ | ||
210 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | ||
211 | /* 7.1 */ | ||
212 | [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 }, | ||
213 | }; | ||
214 | |||
215 | /* | ||
216 | * This is an ordered list! | ||
217 | * | ||
218 | * The preceding ones have better chances to be selected by | ||
219 | * hdmi_setup_channel_allocation(). | ||
220 | */ | ||
221 | static struct cea_channel_speaker_allocation channel_allocations[] = { | ||
222 | /* channel: 7 6 5 4 3 2 1 0 */ | ||
223 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | ||
224 | /* 2.1 */ | ||
225 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | ||
226 | /* Dolby Surround */ | ||
227 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | ||
228 | /* surround40 */ | ||
229 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
230 | /* surround41 */ | ||
231 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
232 | /* surround50 */ | ||
233 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
234 | /* surround51 */ | ||
235 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
236 | /* 6.1 */ | ||
237 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
238 | /* surround71 */ | ||
239 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
240 | |||
241 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | ||
242 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | ||
243 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | ||
244 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | ||
245 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | ||
246 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | ||
247 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | ||
248 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | ||
249 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | ||
250 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | ||
251 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | ||
252 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | ||
253 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | ||
254 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | ||
255 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | ||
256 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | ||
257 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | ||
258 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | ||
259 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | ||
260 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | ||
261 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | ||
262 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | ||
263 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | ||
264 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | ||
265 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
266 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | ||
267 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | ||
268 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | ||
269 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | ||
270 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | ||
271 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | ||
272 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | ||
273 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | ||
274 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | ||
275 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | ||
276 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | ||
277 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
278 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | ||
279 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | ||
280 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | ||
281 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | ||
282 | }; | ||
283 | |||
284 | /* | ||
285 | * HDA/HDMI auto parsing | ||
286 | */ | ||
287 | |||
288 | static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) | ||
289 | { | ||
290 | int i; | ||
291 | |||
292 | for (i = 0; nids[i]; i++) | ||
293 | if (nids[i] == nid) | ||
294 | return i; | ||
295 | |||
296 | snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); | ||
297 | return -EINVAL; | ||
298 | } | ||
299 | |||
300 | static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | ||
301 | { | ||
302 | struct nvhdmi_spec *spec = codec->spec; | ||
303 | hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; | ||
304 | int conn_len, curr; | ||
305 | int index; | ||
306 | |||
307 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | ||
308 | snd_printk(KERN_WARNING | ||
309 | "HDMI: pin %d wcaps %#x " | ||
310 | "does not support connection list\n", | ||
311 | pin_nid, get_wcaps(codec, pin_nid)); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, | ||
316 | HDA_MAX_CONNECTIONS); | ||
317 | if (conn_len > 1) | ||
318 | curr = snd_hda_codec_read(codec, pin_nid, 0, | ||
319 | AC_VERB_GET_CONNECT_SEL, 0); | ||
320 | else | ||
321 | curr = 0; | ||
322 | |||
323 | index = hda_node_index(spec->pin, pin_nid); | ||
324 | if (index < 0) | ||
325 | return -EINVAL; | ||
326 | |||
327 | spec->pin_cvt[index] = conn_list[curr]; | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, | ||
333 | struct hdmi_eld *eld) | ||
334 | { | ||
335 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | ||
336 | snd_hdmi_show_eld(eld); | ||
337 | } | ||
338 | |||
339 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | ||
340 | struct hdmi_eld *eld) | ||
341 | { | ||
342 | int present = snd_hda_pin_sense(codec, pin_nid); | ||
343 | |||
344 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | ||
345 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | ||
346 | |||
347 | if (present & AC_PINSENSE_ELDV) | ||
348 | hdmi_get_show_eld(codec, pin_nid, eld); | ||
349 | } | ||
350 | |||
351 | static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | ||
352 | { | ||
353 | struct nvhdmi_spec *spec = codec->spec; | ||
354 | |||
355 | if (spec->num_pins >= NVIDIA_89_HDMI_PINS) { | ||
356 | snd_printk(KERN_WARNING | ||
357 | "HDMI: no space for pin %d \n", pin_nid); | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); | ||
362 | |||
363 | spec->pin[spec->num_pins] = pin_nid; | ||
364 | spec->num_pins++; | ||
365 | |||
366 | /* | ||
367 | * It is assumed that converter nodes come first in the node list and | ||
368 | * hence have been registered and usable now. | ||
369 | */ | ||
370 | return nvhdmi_read_pin_conn(codec, pin_nid); | ||
371 | } | ||
372 | |||
373 | static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | ||
374 | { | ||
375 | struct nvhdmi_spec *spec = codec->spec; | ||
376 | |||
377 | if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) { | ||
378 | snd_printk(KERN_WARNING | ||
379 | "HDMI: no space for converter %d \n", nid); | ||
380 | return -EINVAL; | ||
381 | } | ||
382 | |||
383 | spec->cvt[spec->num_cvts] = nid; | ||
384 | spec->num_cvts++; | ||
385 | |||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | |||
390 | static int nvhdmi_parse_codec(struct hda_codec *codec) | ||
391 | { | ||
392 | hda_nid_t nid; | ||
393 | int i, nodes; | ||
394 | |||
395 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | ||
396 | if (!nid || nodes < 0) { | ||
397 | snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | |||
401 | for (i = 0; i < nodes; i++, nid++) { | ||
402 | unsigned int caps; | ||
403 | unsigned int type; | ||
404 | |||
405 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | ||
406 | type = get_wcaps_type(caps); | ||
407 | |||
408 | if (!(caps & AC_WCAP_DIGITAL)) | ||
409 | continue; | ||
410 | |||
411 | switch (type) { | ||
412 | case AC_WID_AUD_OUT: | ||
413 | if (nvhdmi_add_cvt(codec, nid) < 0) | ||
414 | return -EINVAL; | ||
415 | break; | ||
416 | case AC_WID_PIN: | ||
417 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
418 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | ||
419 | continue; | ||
420 | if (nvhdmi_add_pin(codec, nid) < 0) | ||
421 | return -EINVAL; | ||
422 | break; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | ||
428 | * can be lost and presence sense verb will become inaccurate if the | ||
429 | * HDA link is powered off at hot plug or hw initialization time. | ||
430 | */ | ||
431 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
432 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | ||
433 | AC_PWRST_EPSS)) | ||
434 | codec->bus->power_keep_link_on = 1; | ||
435 | #endif | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * HDMI routines | ||
442 | */ | ||
443 | |||
444 | #ifdef BE_PARANOID | ||
445 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
446 | int *packet_index, int *byte_index) | ||
447 | { | ||
448 | int val; | ||
449 | |||
450 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
451 | AC_VERB_GET_HDMI_DIP_INDEX, 0); | ||
452 | |||
453 | *packet_index = val >> 5; | ||
454 | *byte_index = val & 0x1f; | ||
455 | } | ||
456 | #endif | ||
457 | |||
458 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
459 | int packet_index, int byte_index) | ||
460 | { | ||
461 | int val; | ||
462 | |||
463 | val = (packet_index << 5) | (byte_index & 0x1f); | ||
464 | |||
465 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | ||
466 | } | ||
467 | |||
468 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, | ||
469 | unsigned char val) | ||
470 | { | ||
471 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | ||
472 | } | ||
473 | |||
474 | static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) | ||
475 | { | ||
476 | /* Unmute */ | ||
477 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) | ||
478 | snd_hda_codec_write(codec, pin_nid, 0, | ||
479 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
480 | /* Enable pin out */ | ||
481 | snd_hda_codec_write(codec, pin_nid, 0, | ||
482 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * Enable Audio InfoFrame Transmission | ||
487 | */ | ||
488 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, | ||
489 | hda_nid_t pin_nid) | ||
490 | { | ||
491 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
492 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
493 | AC_DIPXMIT_BEST); | ||
494 | } | ||
495 | |||
496 | /* | ||
497 | * Disable Audio InfoFrame Transmission | ||
498 | */ | ||
499 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, | ||
500 | hda_nid_t pin_nid) | ||
501 | { | ||
502 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
503 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
504 | AC_DIPXMIT_DISABLE); | ||
505 | } | ||
506 | |||
507 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) | ||
508 | { | ||
509 | return 1 + snd_hda_codec_read(codec, nid, 0, | ||
510 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | ||
511 | } | ||
512 | |||
513 | static void hdmi_set_channel_count(struct hda_codec *codec, | ||
514 | hda_nid_t nid, int chs) | ||
515 | { | ||
516 | if (chs != hdmi_get_channel_count(codec, nid)) | ||
517 | snd_hda_codec_write(codec, nid, 0, | ||
518 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | ||
519 | } | ||
520 | |||
521 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | ||
522 | hda_nid_t pin_nid) | ||
523 | { | ||
524 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
525 | int i; | ||
526 | int slot; | ||
527 | |||
528 | for (i = 0; i < 8; i++) { | ||
529 | slot = snd_hda_codec_read(codec, pin_nid, 0, | ||
530 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | ||
531 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | ||
532 | slot >> 4, slot & 0xf); | ||
533 | } | ||
534 | #endif | ||
535 | } | ||
536 | |||
537 | |||
538 | /* | ||
539 | * Audio InfoFrame routines | ||
540 | */ | ||
541 | |||
542 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) | ||
543 | { | ||
544 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
545 | int i; | ||
546 | int size; | ||
547 | |||
548 | size = snd_hdmi_get_eld_size(codec, pin_nid); | ||
549 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); | ||
550 | |||
551 | for (i = 0; i < 8; i++) { | ||
552 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
553 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
554 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); | ||
555 | } | ||
556 | #endif | ||
557 | } | ||
558 | |||
559 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | ||
560 | { | ||
561 | #ifdef BE_PARANOID | ||
562 | int i, j; | ||
563 | int size; | ||
564 | int pi, bi; | ||
565 | for (i = 0; i < 8; i++) { | ||
566 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
567 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
568 | if (size == 0) | ||
569 | continue; | ||
570 | |||
571 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); | ||
572 | for (j = 1; j < 1000; j++) { | ||
573 | hdmi_write_dip_byte(codec, pin_nid, 0x0); | ||
574 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); | ||
575 | if (pi != i) | ||
576 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | ||
577 | bi, pi, i); | ||
578 | if (bi == 0) /* byte index wrapped around */ | ||
579 | break; | ||
580 | } | ||
581 | snd_printd(KERN_INFO | ||
582 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | ||
583 | i, size, j); | ||
584 | } | ||
585 | #endif | ||
586 | } | ||
587 | |||
588 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | ||
589 | { | ||
590 | ai->checksum = 0; | ||
591 | } | ||
592 | |||
593 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | ||
594 | hda_nid_t pin_nid, | ||
595 | struct hdmi_audio_infoframe *ai) | ||
596 | { | ||
597 | u8 *bytes = (u8 *)ai; | ||
598 | int i; | ||
599 | |||
600 | hdmi_debug_dip_size(codec, pin_nid); | ||
601 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | ||
602 | |||
603 | hdmi_checksum_audio_infoframe(ai); | ||
604 | |||
605 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
606 | for (i = 0; i < sizeof(*ai); i++) | ||
607 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | ||
608 | } | ||
609 | |||
610 | /* | ||
611 | * Compute derived values in channel_allocations[]. | ||
612 | */ | ||
613 | static void init_channel_allocations(void) | ||
614 | { | ||
615 | int i, j; | ||
616 | struct cea_channel_speaker_allocation *p; | ||
617 | |||
618 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
619 | p = channel_allocations + i; | ||
620 | p->channels = 0; | ||
621 | p->spk_mask = 0; | ||
622 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | ||
623 | if (p->speakers[j]) { | ||
624 | p->channels++; | ||
625 | p->spk_mask |= p->speakers[j]; | ||
626 | } | ||
627 | } | ||
628 | } | ||
629 | |||
630 | /* | ||
631 | * The transformation takes two steps: | ||
632 | * | ||
633 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | ||
634 | * spk_mask => (channel_allocations[]) => ai->CA | ||
635 | * | ||
636 | * TODO: it could select the wrong CA from multiple candidates. | ||
637 | */ | ||
638 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | ||
639 | struct hdmi_audio_infoframe *ai) | ||
640 | { | ||
641 | struct nvhdmi_spec *spec = codec->spec; | ||
642 | struct hdmi_eld *eld; | ||
643 | int i; | ||
644 | int spk_mask = 0; | ||
645 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
646 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
647 | |||
648 | /* | ||
649 | * CA defaults to 0 for basic stereo audio | ||
650 | */ | ||
651 | if (channels <= 2) | ||
652 | return 0; | ||
653 | |||
654 | i = hda_node_index(spec->pin_cvt, nid); | ||
655 | if (i < 0) | ||
656 | return 0; | ||
657 | eld = &spec->sink_eld[i]; | ||
658 | |||
659 | /* | ||
660 | * HDMI sink's ELD info cannot always be retrieved for now, e.g. | ||
661 | * in console or for audio devices. Assume the highest speakers | ||
662 | * configuration, to _not_ prohibit multi-channel audio playback. | ||
663 | */ | ||
664 | if (!eld->spk_alloc) | ||
665 | eld->spk_alloc = 0xffff; | ||
666 | |||
667 | /* | ||
668 | * expand ELD's speaker allocation mask | ||
669 | * | ||
670 | * ELD tells the speaker mask in a compact(paired) form, | ||
671 | * expand ELD's notions to match the ones used by Audio InfoFrame. | ||
672 | */ | ||
673 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | ||
674 | if (eld->spk_alloc & (1 << i)) | ||
675 | spk_mask |= eld_speaker_allocation_bits[i]; | ||
676 | } | ||
677 | |||
678 | /* search for the first working match in the CA table */ | ||
679 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
680 | if (channels == channel_allocations[i].channels && | ||
681 | (spk_mask & channel_allocations[i].spk_mask) == | ||
682 | channel_allocations[i].spk_mask) { | ||
683 | ai->CA = channel_allocations[i].ca_index; | ||
684 | break; | ||
685 | } | ||
686 | } | ||
687 | |||
688 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | ||
689 | snd_printdd(KERN_INFO | ||
690 | "HDMI: select CA 0x%x for %d-channel allocation: %s\n", | ||
691 | ai->CA, channels, buf); | ||
692 | |||
693 | return ai->CA; | ||
694 | } | ||
695 | |||
696 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
697 | hda_nid_t pin_nid, | ||
698 | struct hdmi_audio_infoframe *ai) | ||
699 | { | ||
700 | int i; | ||
701 | int ca = ai->CA; | ||
702 | int err; | ||
703 | |||
704 | if (hdmi_channel_mapping[ca][1] == 0) { | ||
705 | for (i = 0; i < channel_allocations[ca].channels; i++) | ||
706 | hdmi_channel_mapping[ca][i] = i | (i << 4); | ||
707 | for (; i < 8; i++) | ||
708 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); | ||
709 | } | ||
710 | |||
711 | for (i = 0; i < 8; i++) { | ||
712 | err = snd_hda_codec_write(codec, pin_nid, 0, | ||
713 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
714 | hdmi_channel_mapping[ca][i]); | ||
715 | if (err) { | ||
716 | snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); | ||
717 | break; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | hdmi_debug_channel_mapping(codec, pin_nid); | ||
722 | } | ||
723 | |||
724 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | ||
725 | struct hdmi_audio_infoframe *ai) | ||
726 | { | ||
727 | u8 *bytes = (u8 *)ai; | ||
728 | u8 val; | ||
729 | int i; | ||
730 | |||
731 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) | ||
732 | != AC_DIPXMIT_BEST) | ||
733 | return false; | ||
734 | |||
735 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
736 | for (i = 0; i < sizeof(*ai); i++) { | ||
737 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
738 | AC_VERB_GET_HDMI_DIP_DATA, 0); | ||
739 | if (val != bytes[i]) | ||
740 | return false; | ||
741 | } | ||
742 | |||
743 | return true; | ||
744 | } | ||
745 | |||
746 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | ||
747 | struct snd_pcm_substream *substream) | ||
748 | { | ||
749 | struct nvhdmi_spec *spec = codec->spec; | ||
750 | hda_nid_t pin_nid; | ||
751 | int i; | ||
752 | struct hdmi_audio_infoframe ai = { | ||
753 | .type = 0x84, | ||
754 | .ver = 0x01, | ||
755 | .len = 0x0a, | ||
756 | .CC02_CT47 = substream->runtime->channels - 1, | ||
757 | }; | ||
758 | |||
759 | hdmi_setup_channel_allocation(codec, nid, &ai); | ||
760 | |||
761 | for (i = 0; i < spec->num_pins; i++) { | ||
762 | if (spec->pin_cvt[i] != nid) | ||
763 | continue; | ||
764 | if (!spec->sink_eld[i].monitor_present) | ||
765 | continue; | ||
766 | |||
767 | pin_nid = spec->pin[i]; | ||
768 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | ||
769 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | ||
770 | hdmi_stop_infoframe_trans(codec, pin_nid); | ||
771 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | ||
772 | hdmi_start_infoframe_trans(codec, pin_nid); | ||
773 | } | ||
774 | } | ||
775 | } | ||
776 | |||
777 | /* | ||
778 | * Unsolicited events | ||
779 | */ | ||
780 | |||
781 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
782 | { | ||
783 | struct nvhdmi_spec *spec = codec->spec; | ||
784 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
785 | int pind = !!(res & AC_UNSOL_RES_PD); | ||
786 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | ||
787 | int index; | ||
788 | |||
789 | printk(KERN_INFO | ||
790 | "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | ||
791 | tag, pind, eldv); | ||
792 | |||
793 | index = hda_node_index(spec->pin, tag); | ||
794 | if (index < 0) | ||
795 | return; | ||
796 | |||
797 | spec->sink_eld[index].monitor_present = pind; | ||
798 | spec->sink_eld[index].eld_valid = eldv; | ||
799 | |||
800 | if (eldv) { | ||
801 | spec->sink_eld[index].monitor_present = 1; | ||
802 | hdmi_get_show_eld(codec, spec->pin[index], | ||
803 | &spec->sink_eld[index]); | ||
804 | /* TODO: do real things about ELD */ | ||
805 | } | ||
806 | } | ||
807 | |||
808 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
809 | { | ||
810 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
811 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
812 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | ||
813 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | ||
814 | |||
815 | printk(KERN_INFO | ||
816 | "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | ||
817 | tag, | ||
818 | subtag, | ||
819 | cp_state, | ||
820 | cp_ready); | ||
821 | |||
822 | /* TODO */ | ||
823 | if (cp_state) | ||
824 | ; | ||
825 | if (cp_ready) | ||
826 | ; | ||
827 | } | ||
828 | |||
829 | static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res) | ||
830 | { | ||
831 | struct nvhdmi_spec *spec = codec->spec; | ||
832 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
833 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
834 | |||
835 | if (hda_node_index(spec->pin, tag) < 0) { | ||
836 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); | ||
837 | return; | ||
838 | } | ||
839 | |||
840 | if (subtag == 0) | ||
841 | hdmi_intrinsic_event(codec, res); | ||
842 | else | ||
843 | hdmi_non_intrinsic_event(codec, res); | ||
844 | } | ||
845 | |||
846 | /* | ||
847 | * Callbacks | ||
848 | */ | ||
849 | |||
850 | static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
851 | u32 stream_tag, int format) | ||
852 | { | ||
853 | int tag; | ||
854 | int fmt; | ||
855 | |||
856 | tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; | ||
857 | fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); | ||
858 | |||
859 | snd_printdd("hdmi_setup_stream: " | ||
860 | "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", | ||
861 | nid, | ||
862 | tag == stream_tag ? "" : "new-", | ||
863 | stream_tag, | ||
864 | fmt == format ? "" : "new-", | ||
865 | format); | ||
866 | |||
867 | if (tag != stream_tag) | ||
868 | snd_hda_codec_write(codec, nid, 0, | ||
869 | AC_VERB_SET_CHANNEL_STREAMID, | ||
870 | stream_tag << 4); | ||
871 | if (fmt != format) | ||
872 | snd_hda_codec_write(codec, nid, 0, | ||
873 | AC_VERB_SET_STREAM_FORMAT, format); | ||
874 | } | ||
875 | |||
82 | /* | 876 | /* |
83 | * Controls | 877 | * Controls |
84 | */ | 878 | */ |
@@ -86,20 +880,58 @@ static int nvhdmi_build_controls(struct hda_codec *codec) | |||
86 | { | 880 | { |
87 | struct nvhdmi_spec *spec = codec->spec; | 881 | struct nvhdmi_spec *spec = codec->spec; |
88 | int err; | 882 | int err; |
883 | int i; | ||
89 | 884 | ||
90 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 885 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) |
91 | if (err < 0) | 886 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { |
92 | return err; | 887 | for (i = 0; i < codec->num_pcms; i++) { |
888 | err = snd_hda_create_spdif_out_ctls(codec, | ||
889 | spec->cvt[i]); | ||
890 | if (err < 0) | ||
891 | return err; | ||
892 | } | ||
893 | } else { | ||
894 | err = snd_hda_create_spdif_out_ctls(codec, | ||
895 | spec->multiout.dig_out_nid); | ||
896 | if (err < 0) | ||
897 | return err; | ||
898 | } | ||
93 | 899 | ||
94 | return 0; | 900 | return 0; |
95 | } | 901 | } |
96 | 902 | ||
97 | static int nvhdmi_init(struct hda_codec *codec) | 903 | static int nvhdmi_init(struct hda_codec *codec) |
98 | { | 904 | { |
99 | snd_hda_sequence_write(codec, nvhdmi_basic_init); | 905 | struct nvhdmi_spec *spec = codec->spec; |
906 | int i; | ||
907 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
908 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
909 | for (i = 0; spec->pin[i]; i++) { | ||
910 | hdmi_enable_output(codec, spec->pin[i]); | ||
911 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
912 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
913 | AC_USRSP_EN | spec->pin[i]); | ||
914 | } | ||
915 | } else { | ||
916 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
917 | } | ||
100 | return 0; | 918 | return 0; |
101 | } | 919 | } |
102 | 920 | ||
921 | static void nvhdmi_free(struct hda_codec *codec) | ||
922 | { | ||
923 | struct nvhdmi_spec *spec = codec->spec; | ||
924 | int i; | ||
925 | |||
926 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
927 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
928 | for (i = 0; i < spec->num_pins; i++) | ||
929 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
930 | } | ||
931 | |||
932 | kfree(spec); | ||
933 | } | ||
934 | |||
103 | /* | 935 | /* |
104 | * Digital out | 936 | * Digital out |
105 | */ | 937 | */ |
@@ -111,21 +943,21 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
111 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 943 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
112 | } | 944 | } |
113 | 945 | ||
114 | static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, | 946 | static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, |
115 | struct hda_codec *codec, | 947 | struct hda_codec *codec, |
116 | struct snd_pcm_substream *substream) | 948 | struct snd_pcm_substream *substream) |
117 | { | 949 | { |
118 | struct nvhdmi_spec *spec = codec->spec; | 950 | struct nvhdmi_spec *spec = codec->spec; |
119 | int i; | 951 | int i; |
120 | 952 | ||
121 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, | 953 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, |
122 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 954 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
123 | for (i = 0; i < 4; i++) { | 955 | for (i = 0; i < 4; i++) { |
124 | /* set the stream id */ | 956 | /* set the stream id */ |
125 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 957 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
126 | AC_VERB_SET_CHANNEL_STREAMID, 0); | 958 | AC_VERB_SET_CHANNEL_STREAMID, 0); |
127 | /* set the stream format */ | 959 | /* set the stream format */ |
128 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 960 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
129 | AC_VERB_SET_STREAM_FORMAT, 0); | 961 | AC_VERB_SET_STREAM_FORMAT, 0); |
130 | } | 962 | } |
131 | 963 | ||
@@ -140,6 +972,21 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, | |||
140 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 972 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
141 | } | 973 | } |
142 | 974 | ||
975 | static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, | ||
976 | struct hda_codec *codec, | ||
977 | unsigned int stream_tag, | ||
978 | unsigned int format, | ||
979 | struct snd_pcm_substream *substream) | ||
980 | { | ||
981 | hdmi_set_channel_count(codec, hinfo->nid, | ||
982 | substream->runtime->channels); | ||
983 | |||
984 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
985 | |||
986 | hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
987 | return 0; | ||
988 | } | ||
989 | |||
143 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | 990 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, |
144 | struct hda_codec *codec, | 991 | struct hda_codec *codec, |
145 | unsigned int stream_tag, | 992 | unsigned int stream_tag, |
@@ -181,29 +1028,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
181 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 1028 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
182 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 1029 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) |
183 | snd_hda_codec_write(codec, | 1030 | snd_hda_codec_write(codec, |
184 | Nv_Master_Convert_nid, | 1031 | nvhdmi_master_con_nid_7x, |
185 | 0, | 1032 | 0, |
186 | AC_VERB_SET_DIGI_CONVERT_1, | 1033 | AC_VERB_SET_DIGI_CONVERT_1, |
187 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 1034 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
188 | 1035 | ||
189 | /* set the stream id */ | 1036 | /* set the stream id */ |
190 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 1037 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
191 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | 1038 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); |
192 | 1039 | ||
193 | /* set the stream format */ | 1040 | /* set the stream format */ |
194 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 1041 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
195 | AC_VERB_SET_STREAM_FORMAT, format); | 1042 | AC_VERB_SET_STREAM_FORMAT, format); |
196 | 1043 | ||
197 | /* turn on again (if needed) */ | 1044 | /* turn on again (if needed) */ |
198 | /* enable and set the channel status audio/data flag */ | 1045 | /* enable and set the channel status audio/data flag */ |
199 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 1046 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
200 | snd_hda_codec_write(codec, | 1047 | snd_hda_codec_write(codec, |
201 | Nv_Master_Convert_nid, | 1048 | nvhdmi_master_con_nid_7x, |
202 | 0, | 1049 | 0, |
203 | AC_VERB_SET_DIGI_CONVERT_1, | 1050 | AC_VERB_SET_DIGI_CONVERT_1, |
204 | codec->spdif_ctls & 0xff); | 1051 | codec->spdif_ctls & 0xff); |
205 | snd_hda_codec_write(codec, | 1052 | snd_hda_codec_write(codec, |
206 | Nv_Master_Convert_nid, | 1053 | nvhdmi_master_con_nid_7x, |
207 | 0, | 1054 | 0, |
208 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 1055 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
209 | } | 1056 | } |
@@ -220,19 +1067,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
220 | if (codec->spdif_status_reset && | 1067 | if (codec->spdif_status_reset && |
221 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | 1068 | (codec->spdif_ctls & AC_DIG1_ENABLE)) |
222 | snd_hda_codec_write(codec, | 1069 | snd_hda_codec_write(codec, |
223 | nvhdmi_convert_nids[i], | 1070 | nvhdmi_con_nids_7x[i], |
224 | 0, | 1071 | 0, |
225 | AC_VERB_SET_DIGI_CONVERT_1, | 1072 | AC_VERB_SET_DIGI_CONVERT_1, |
226 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 1073 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
227 | /* set the stream id */ | 1074 | /* set the stream id */ |
228 | snd_hda_codec_write(codec, | 1075 | snd_hda_codec_write(codec, |
229 | nvhdmi_convert_nids[i], | 1076 | nvhdmi_con_nids_7x[i], |
230 | 0, | 1077 | 0, |
231 | AC_VERB_SET_CHANNEL_STREAMID, | 1078 | AC_VERB_SET_CHANNEL_STREAMID, |
232 | (stream_tag << 4) | channel_id); | 1079 | (stream_tag << 4) | channel_id); |
233 | /* set the stream format */ | 1080 | /* set the stream format */ |
234 | snd_hda_codec_write(codec, | 1081 | snd_hda_codec_write(codec, |
235 | nvhdmi_convert_nids[i], | 1082 | nvhdmi_con_nids_7x[i], |
236 | 0, | 1083 | 0, |
237 | AC_VERB_SET_STREAM_FORMAT, | 1084 | AC_VERB_SET_STREAM_FORMAT, |
238 | format); | 1085 | format); |
@@ -241,12 +1088,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
241 | if (codec->spdif_status_reset && | 1088 | if (codec->spdif_status_reset && |
242 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 1089 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
243 | snd_hda_codec_write(codec, | 1090 | snd_hda_codec_write(codec, |
244 | nvhdmi_convert_nids[i], | 1091 | nvhdmi_con_nids_7x[i], |
245 | 0, | 1092 | 0, |
246 | AC_VERB_SET_DIGI_CONVERT_1, | 1093 | AC_VERB_SET_DIGI_CONVERT_1, |
247 | codec->spdif_ctls & 0xff); | 1094 | codec->spdif_ctls & 0xff); |
248 | snd_hda_codec_write(codec, | 1095 | snd_hda_codec_write(codec, |
249 | nvhdmi_convert_nids[i], | 1096 | nvhdmi_con_nids_7x[i], |
250 | 0, | 1097 | 0, |
251 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 1098 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
252 | } | 1099 | } |
@@ -261,6 +1108,13 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
261 | return 0; | 1108 | return 0; |
262 | } | 1109 | } |
263 | 1110 | ||
1111 | static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
1112 | struct hda_codec *codec, | ||
1113 | struct snd_pcm_substream *substream) | ||
1114 | { | ||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
264 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, | 1118 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, |
265 | struct hda_codec *codec, | 1119 | struct hda_codec *codec, |
266 | unsigned int stream_tag, | 1120 | unsigned int stream_tag, |
@@ -272,17 +1126,29 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, | |||
272 | format, substream); | 1126 | format, substream); |
273 | } | 1127 | } |
274 | 1128 | ||
275 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { | 1129 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { |
1130 | .substreams = 1, | ||
1131 | .channels_min = 2, | ||
1132 | .rates = SUPPORTED_RATES, | ||
1133 | .maxbps = SUPPORTED_MAXBPS, | ||
1134 | .formats = SUPPORTED_FORMATS, | ||
1135 | .ops = { | ||
1136 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, | ||
1137 | .cleanup = nvhdmi_playback_pcm_cleanup, | ||
1138 | }, | ||
1139 | }; | ||
1140 | |||
1141 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { | ||
276 | .substreams = 1, | 1142 | .substreams = 1, |
277 | .channels_min = 2, | 1143 | .channels_min = 2, |
278 | .channels_max = 8, | 1144 | .channels_max = 8, |
279 | .nid = Nv_Master_Convert_nid, | 1145 | .nid = nvhdmi_master_con_nid_7x, |
280 | .rates = SUPPORTED_RATES, | 1146 | .rates = SUPPORTED_RATES, |
281 | .maxbps = SUPPORTED_MAXBPS, | 1147 | .maxbps = SUPPORTED_MAXBPS, |
282 | .formats = SUPPORTED_FORMATS, | 1148 | .formats = SUPPORTED_FORMATS, |
283 | .ops = { | 1149 | .ops = { |
284 | .open = nvhdmi_dig_playback_pcm_open, | 1150 | .open = nvhdmi_dig_playback_pcm_open, |
285 | .close = nvhdmi_dig_playback_pcm_close_8ch, | 1151 | .close = nvhdmi_dig_playback_pcm_close_8ch_7x, |
286 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch | 1152 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch |
287 | }, | 1153 | }, |
288 | }; | 1154 | }; |
@@ -291,7 +1157,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
291 | .substreams = 1, | 1157 | .substreams = 1, |
292 | .channels_min = 2, | 1158 | .channels_min = 2, |
293 | .channels_max = 2, | 1159 | .channels_max = 2, |
294 | .nid = Nv_Master_Convert_nid, | 1160 | .nid = nvhdmi_master_con_nid_7x, |
295 | .rates = SUPPORTED_RATES, | 1161 | .rates = SUPPORTED_RATES, |
296 | .maxbps = SUPPORTED_MAXBPS, | 1162 | .maxbps = SUPPORTED_MAXBPS, |
297 | .formats = SUPPORTED_FORMATS, | 1163 | .formats = SUPPORTED_FORMATS, |
@@ -302,10 +1168,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
302 | }, | 1168 | }, |
303 | }; | 1169 | }; |
304 | 1170 | ||
305 | static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | 1171 | static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) |
1172 | { | ||
1173 | struct nvhdmi_spec *spec = codec->spec; | ||
1174 | struct hda_pcm *info = spec->pcm_rec; | ||
1175 | int i; | ||
1176 | |||
1177 | codec->num_pcms = spec->num_cvts; | ||
1178 | codec->pcm_info = info; | ||
1179 | |||
1180 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
1181 | unsigned int chans; | ||
1182 | |||
1183 | chans = get_wcaps(codec, spec->cvt[i]); | ||
1184 | chans = get_wcaps_channels(chans); | ||
1185 | |||
1186 | info->name = nvhdmi_pcm_names[i]; | ||
1187 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
1188 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
1189 | = nvhdmi_pcm_digital_playback_8ch_89; | ||
1190 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
1191 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
1192 | } | ||
1193 | |||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) | ||
306 | { | 1198 | { |
307 | struct nvhdmi_spec *spec = codec->spec; | 1199 | struct nvhdmi_spec *spec = codec->spec; |
308 | struct hda_pcm *info = &spec->pcm_rec; | 1200 | struct hda_pcm *info = spec->pcm_rec; |
309 | 1201 | ||
310 | codec->num_pcms = 1; | 1202 | codec->num_pcms = 1; |
311 | codec->pcm_info = info; | 1203 | codec->pcm_info = info; |
@@ -313,7 +1205,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | |||
313 | info->name = "NVIDIA HDMI"; | 1205 | info->name = "NVIDIA HDMI"; |
314 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1206 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
315 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | 1207 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] |
316 | = nvhdmi_pcm_digital_playback_8ch; | 1208 | = nvhdmi_pcm_digital_playback_8ch_7x; |
317 | 1209 | ||
318 | return 0; | 1210 | return 0; |
319 | } | 1211 | } |
@@ -321,7 +1213,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | |||
321 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | 1213 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) |
322 | { | 1214 | { |
323 | struct nvhdmi_spec *spec = codec->spec; | 1215 | struct nvhdmi_spec *spec = codec->spec; |
324 | struct hda_pcm *info = &spec->pcm_rec; | 1216 | struct hda_pcm *info = spec->pcm_rec; |
325 | 1217 | ||
326 | codec->num_pcms = 1; | 1218 | codec->num_pcms = 1; |
327 | codec->pcm_info = info; | 1219 | codec->pcm_info = info; |
@@ -334,14 +1226,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | |||
334 | return 0; | 1226 | return 0; |
335 | } | 1227 | } |
336 | 1228 | ||
337 | static void nvhdmi_free(struct hda_codec *codec) | 1229 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { |
338 | { | 1230 | .build_controls = nvhdmi_build_controls, |
339 | kfree(codec->spec); | 1231 | .build_pcms = nvhdmi_build_pcms_8ch_89, |
340 | } | 1232 | .init = nvhdmi_init, |
1233 | .free = nvhdmi_free, | ||
1234 | .unsol_event = nvhdmi_unsol_event, | ||
1235 | }; | ||
341 | 1236 | ||
342 | static struct hda_codec_ops nvhdmi_patch_ops_8ch = { | 1237 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { |
343 | .build_controls = nvhdmi_build_controls, | 1238 | .build_controls = nvhdmi_build_controls, |
344 | .build_pcms = nvhdmi_build_pcms_8ch, | 1239 | .build_pcms = nvhdmi_build_pcms_8ch_7x, |
345 | .init = nvhdmi_init, | 1240 | .init = nvhdmi_init, |
346 | .free = nvhdmi_free, | 1241 | .free = nvhdmi_free, |
347 | }; | 1242 | }; |
@@ -353,7 +1248,34 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | |||
353 | .free = nvhdmi_free, | 1248 | .free = nvhdmi_free, |
354 | }; | 1249 | }; |
355 | 1250 | ||
356 | static int patch_nvhdmi_8ch(struct hda_codec *codec) | 1251 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) |
1252 | { | ||
1253 | struct nvhdmi_spec *spec; | ||
1254 | int i; | ||
1255 | |||
1256 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1257 | if (spec == NULL) | ||
1258 | return -ENOMEM; | ||
1259 | |||
1260 | codec->spec = spec; | ||
1261 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; | ||
1262 | |||
1263 | if (nvhdmi_parse_codec(codec) < 0) { | ||
1264 | codec->spec = NULL; | ||
1265 | kfree(spec); | ||
1266 | return -EINVAL; | ||
1267 | } | ||
1268 | codec->patch_ops = nvhdmi_patch_ops_8ch_89; | ||
1269 | |||
1270 | for (i = 0; i < spec->num_pins; i++) | ||
1271 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
1272 | |||
1273 | init_channel_allocations(); | ||
1274 | |||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
357 | { | 1279 | { |
358 | struct nvhdmi_spec *spec; | 1280 | struct nvhdmi_spec *spec; |
359 | 1281 | ||
@@ -365,9 +1287,10 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec) | |||
365 | 1287 | ||
366 | spec->multiout.num_dacs = 0; /* no analog */ | 1288 | spec->multiout.num_dacs = 0; /* no analog */ |
367 | spec->multiout.max_channels = 8; | 1289 | spec->multiout.max_channels = 8; |
368 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 1290 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
1291 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
369 | 1292 | ||
370 | codec->patch_ops = nvhdmi_patch_ops_8ch; | 1293 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; |
371 | 1294 | ||
372 | return 0; | 1295 | return 0; |
373 | } | 1296 | } |
@@ -384,7 +1307,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
384 | 1307 | ||
385 | spec->multiout.num_dacs = 0; /* no analog */ | 1308 | spec->multiout.num_dacs = 0; /* no analog */ |
386 | spec->multiout.max_channels = 2; | 1309 | spec->multiout.max_channels = 2; |
387 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 1310 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
1311 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
388 | 1312 | ||
389 | codec->patch_ops = nvhdmi_patch_ops_2ch; | 1313 | codec->patch_ops = nvhdmi_patch_ops_2ch; |
390 | 1314 | ||
@@ -395,13 +1319,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
395 | * patch entries | 1319 | * patch entries |
396 | */ | 1320 | */ |
397 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | 1321 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { |
398 | { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
399 | { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
400 | { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
401 | { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
402 | { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch }, | ||
403 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 1322 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
404 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 1323 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
1324 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", | ||
1325 | .patch = patch_nvhdmi_8ch_7x }, | ||
1326 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", | ||
1327 | .patch = patch_nvhdmi_8ch_7x }, | ||
1328 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", | ||
1329 | .patch = patch_nvhdmi_8ch_7x }, | ||
1330 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", | ||
1331 | .patch = patch_nvhdmi_8ch_7x }, | ||
1332 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", | ||
1333 | .patch = patch_nvhdmi_8ch_7x }, | ||
1334 | { .id = 0x10de000c, .name = "MCP89 HDMI", | ||
1335 | .patch = patch_nvhdmi_8ch_89 }, | ||
1336 | { .id = 0x10de000b, .name = "GT21x HDMI", | ||
1337 | .patch = patch_nvhdmi_8ch_89 }, | ||
1338 | { .id = 0x10de000d, .name = "GT240 HDMI", | ||
1339 | .patch = patch_nvhdmi_8ch_89 }, | ||
405 | {} /* terminator */ | 1340 | {} /* terminator */ |
406 | }; | 1341 | }; |
407 | 1342 | ||
@@ -412,9 +1347,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"); | |||
412 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | 1347 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); |
413 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 1348 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
414 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 1349 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
1350 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
1351 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
1352 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
415 | 1353 | ||
416 | MODULE_LICENSE("GPL"); | 1354 | MODULE_LICENSE("GPL"); |
417 | MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); | 1355 | MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); |
418 | 1356 | ||
419 | static struct hda_codec_preset_list nvhdmi_list = { | 1357 | static struct hda_codec_preset_list nvhdmi_list = { |
420 | .preset = snd_hda_preset_nvhdmi, | 1358 | .preset = snd_hda_preset_nvhdmi, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index da34095c707f..5d2fbb87b871 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -131,8 +131,10 @@ enum { | |||
131 | enum { | 131 | enum { |
132 | ALC269_BASIC, | 132 | ALC269_BASIC, |
133 | ALC269_QUANTA_FL1, | 133 | ALC269_QUANTA_FL1, |
134 | ALC269_ASUS_AMIC, | 134 | ALC269_AMIC, |
135 | ALC269_ASUS_DMIC, | 135 | ALC269_DMIC, |
136 | ALC269VB_AMIC, | ||
137 | ALC269VB_DMIC, | ||
136 | ALC269_FUJITSU, | 138 | ALC269_FUJITSU, |
137 | ALC269_LIFEBOOK, | 139 | ALC269_LIFEBOOK, |
138 | ALC269_AUTO, | 140 | ALC269_AUTO, |
@@ -207,8 +209,10 @@ enum { | |||
207 | ALC882_ASUS_A7J, | 209 | ALC882_ASUS_A7J, |
208 | ALC882_ASUS_A7M, | 210 | ALC882_ASUS_A7M, |
209 | ALC885_MACPRO, | 211 | ALC885_MACPRO, |
212 | ALC885_MBA21, | ||
210 | ALC885_MBP3, | 213 | ALC885_MBP3, |
211 | ALC885_MB5, | 214 | ALC885_MB5, |
215 | ALC885_MACMINI3, | ||
212 | ALC885_IMAC24, | 216 | ALC885_IMAC24, |
213 | ALC885_IMAC91, | 217 | ALC885_IMAC91, |
214 | ALC883_3ST_2ch_DIG, | 218 | ALC883_3ST_2ch_DIG, |
@@ -338,7 +342,7 @@ struct alc_spec { | |||
338 | void (*init_hook)(struct hda_codec *codec); | 342 | void (*init_hook)(struct hda_codec *codec); |
339 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | 343 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); |
340 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 344 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
341 | void (*power_hook)(struct hda_codec *codec, int power); | 345 | void (*power_hook)(struct hda_codec *codec); |
342 | #endif | 346 | #endif |
343 | 347 | ||
344 | /* for pin sensing */ | 348 | /* for pin sensing */ |
@@ -391,7 +395,7 @@ struct alc_config_preset { | |||
391 | void (*init_hook)(struct hda_codec *); | 395 | void (*init_hook)(struct hda_codec *); |
392 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 396 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
393 | struct hda_amp_list *loopbacks; | 397 | struct hda_amp_list *loopbacks; |
394 | void (*power_hook)(struct hda_codec *codec, int power); | 398 | void (*power_hook)(struct hda_codec *codec); |
395 | #endif | 399 | #endif |
396 | }; | 400 | }; |
397 | 401 | ||
@@ -633,6 +637,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
633 | 637 | ||
634 | #define ALC_PIN_MODE(xname, nid, dir) \ | 638 | #define ALC_PIN_MODE(xname, nid, dir) \ |
635 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 639 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
640 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
636 | .info = alc_pin_mode_info, \ | 641 | .info = alc_pin_mode_info, \ |
637 | .get = alc_pin_mode_get, \ | 642 | .get = alc_pin_mode_get, \ |
638 | .put = alc_pin_mode_put, \ | 643 | .put = alc_pin_mode_put, \ |
@@ -684,6 +689,7 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | |||
684 | } | 689 | } |
685 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ | 690 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ |
686 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 691 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
692 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
687 | .info = alc_gpio_data_info, \ | 693 | .info = alc_gpio_data_info, \ |
688 | .get = alc_gpio_data_get, \ | 694 | .get = alc_gpio_data_get, \ |
689 | .put = alc_gpio_data_put, \ | 695 | .put = alc_gpio_data_put, \ |
@@ -738,6 +744,7 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | |||
738 | } | 744 | } |
739 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | 745 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ |
740 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 746 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
747 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
741 | .info = alc_spdif_ctrl_info, \ | 748 | .info = alc_spdif_ctrl_info, \ |
742 | .get = alc_spdif_ctrl_get, \ | 749 | .get = alc_spdif_ctrl_get, \ |
743 | .put = alc_spdif_ctrl_put, \ | 750 | .put = alc_spdif_ctrl_put, \ |
@@ -791,6 +798,7 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | |||
791 | 798 | ||
792 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ | 799 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ |
793 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 800 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
801 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
794 | .info = alc_eapd_ctrl_info, \ | 802 | .info = alc_eapd_ctrl_info, \ |
795 | .get = alc_eapd_ctrl_get, \ | 803 | .get = alc_eapd_ctrl_get, \ |
796 | .put = alc_eapd_ctrl_put, \ | 804 | .put = alc_eapd_ctrl_put, \ |
@@ -837,27 +845,6 @@ static void add_verb(struct alc_spec *spec, const struct hda_verb *verb) | |||
837 | spec->init_verbs[spec->num_init_verbs++] = verb; | 845 | spec->init_verbs[spec->num_init_verbs++] = verb; |
838 | } | 846 | } |
839 | 847 | ||
840 | #ifdef CONFIG_PROC_FS | ||
841 | /* | ||
842 | * hook for proc | ||
843 | */ | ||
844 | static void print_realtek_coef(struct snd_info_buffer *buffer, | ||
845 | struct hda_codec *codec, hda_nid_t nid) | ||
846 | { | ||
847 | int coeff; | ||
848 | |||
849 | if (nid != 0x20) | ||
850 | return; | ||
851 | coeff = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0); | ||
852 | snd_iprintf(buffer, " Processing Coefficient: 0x%02x\n", coeff); | ||
853 | coeff = snd_hda_codec_read(codec, nid, 0, | ||
854 | AC_VERB_GET_COEF_INDEX, 0); | ||
855 | snd_iprintf(buffer, " Coefficient Index: 0x%02x\n", coeff); | ||
856 | } | ||
857 | #else | ||
858 | #define print_realtek_coef NULL | ||
859 | #endif | ||
860 | |||
861 | /* | 848 | /* |
862 | * set up from the preset table | 849 | * set up from the preset table |
863 | */ | 850 | */ |
@@ -1162,6 +1149,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
1162 | case 0x10ec0888: | 1149 | case 0x10ec0888: |
1163 | alc888_coef_init(codec); | 1150 | alc888_coef_init(codec); |
1164 | break; | 1151 | break; |
1152 | #if 0 /* XXX: This may cause the silent output on speaker on some machines */ | ||
1165 | case 0x10ec0267: | 1153 | case 0x10ec0267: |
1166 | case 0x10ec0268: | 1154 | case 0x10ec0268: |
1167 | snd_hda_codec_write(codec, 0x20, 0, | 1155 | snd_hda_codec_write(codec, 0x20, 0, |
@@ -1174,6 +1162,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
1174 | AC_VERB_SET_PROC_COEF, | 1162 | AC_VERB_SET_PROC_COEF, |
1175 | tmp | 0x3000); | 1163 | tmp | 0x3000); |
1176 | break; | 1164 | break; |
1165 | #endif /* XXX */ | ||
1177 | } | 1166 | } |
1178 | break; | 1167 | break; |
1179 | } | 1168 | } |
@@ -1265,7 +1254,7 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1265 | */ | 1254 | */ |
1266 | static int alc_subsystem_id(struct hda_codec *codec, | 1255 | static int alc_subsystem_id(struct hda_codec *codec, |
1267 | hda_nid_t porta, hda_nid_t porte, | 1256 | hda_nid_t porta, hda_nid_t porte, |
1268 | hda_nid_t portd) | 1257 | hda_nid_t portd, hda_nid_t porti) |
1269 | { | 1258 | { |
1270 | unsigned int ass, tmp, i; | 1259 | unsigned int ass, tmp, i; |
1271 | unsigned nid; | 1260 | unsigned nid; |
@@ -1291,7 +1280,7 @@ static int alc_subsystem_id(struct hda_codec *codec, | |||
1291 | snd_printd("realtek: No valid SSID, " | 1280 | snd_printd("realtek: No valid SSID, " |
1292 | "checking pincfg 0x%08x for NID 0x%x\n", | 1281 | "checking pincfg 0x%08x for NID 0x%x\n", |
1293 | ass, nid); | 1282 | ass, nid); |
1294 | if (!(ass & 1) && !(ass & 0x100000)) | 1283 | if (!(ass & 1)) |
1295 | return 0; | 1284 | return 0; |
1296 | if ((ass >> 30) != 1) /* no physical connection */ | 1285 | if ((ass >> 30) != 1) /* no physical connection */ |
1297 | return 0; | 1286 | return 0; |
@@ -1351,6 +1340,8 @@ do_sku: | |||
1351 | nid = porte; | 1340 | nid = porte; |
1352 | else if (tmp == 2) | 1341 | else if (tmp == 2) |
1353 | nid = portd; | 1342 | nid = portd; |
1343 | else if (tmp == 3) | ||
1344 | nid = porti; | ||
1354 | else | 1345 | else |
1355 | return 1; | 1346 | return 1; |
1356 | for (i = 0; i < spec->autocfg.line_outs; i++) | 1347 | for (i = 0; i < spec->autocfg.line_outs; i++) |
@@ -1365,9 +1356,10 @@ do_sku: | |||
1365 | } | 1356 | } |
1366 | 1357 | ||
1367 | static void alc_ssid_check(struct hda_codec *codec, | 1358 | static void alc_ssid_check(struct hda_codec *codec, |
1368 | hda_nid_t porta, hda_nid_t porte, hda_nid_t portd) | 1359 | hda_nid_t porta, hda_nid_t porte, |
1360 | hda_nid_t portd, hda_nid_t porti) | ||
1369 | { | 1361 | { |
1370 | if (!alc_subsystem_id(codec, porta, porte, portd)) { | 1362 | if (!alc_subsystem_id(codec, porta, porte, portd, porti)) { |
1371 | struct alc_spec *spec = codec->spec; | 1363 | struct alc_spec *spec = codec->spec; |
1372 | snd_printd("realtek: " | 1364 | snd_printd("realtek: " |
1373 | "Enable default setup for auto mode as fallback\n"); | 1365 | "Enable default setup for auto mode as fallback\n"); |
@@ -1840,14 +1832,6 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec) | |||
1840 | spec->autocfg.speaker_pins[2] = 0x1b; | 1832 | spec->autocfg.speaker_pins[2] = 0x1b; |
1841 | } | 1833 | } |
1842 | 1834 | ||
1843 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1844 | static void alc889_power_eapd(struct hda_codec *codec, int power) | ||
1845 | { | ||
1846 | set_eapd(codec, 0x14, power); | ||
1847 | set_eapd(codec, 0x15, power); | ||
1848 | } | ||
1849 | #endif | ||
1850 | |||
1851 | /* | 1835 | /* |
1852 | * ALC880 3-stack model | 1836 | * ALC880 3-stack model |
1853 | * | 1837 | * |
@@ -2450,6 +2434,15 @@ static const char *alc_slave_sws[] = { | |||
2450 | * build control elements | 2434 | * build control elements |
2451 | */ | 2435 | */ |
2452 | 2436 | ||
2437 | #define NID_MAPPING (-1) | ||
2438 | |||
2439 | #define SUBDEV_SPEAKER_ (0 << 6) | ||
2440 | #define SUBDEV_HP_ (1 << 6) | ||
2441 | #define SUBDEV_LINE_ (2 << 6) | ||
2442 | #define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f)) | ||
2443 | #define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f)) | ||
2444 | #define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f)) | ||
2445 | |||
2453 | static void alc_free_kctls(struct hda_codec *codec); | 2446 | static void alc_free_kctls(struct hda_codec *codec); |
2454 | 2447 | ||
2455 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 2448 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
@@ -2464,8 +2457,11 @@ static struct snd_kcontrol_new alc_beep_mixer[] = { | |||
2464 | static int alc_build_controls(struct hda_codec *codec) | 2457 | static int alc_build_controls(struct hda_codec *codec) |
2465 | { | 2458 | { |
2466 | struct alc_spec *spec = codec->spec; | 2459 | struct alc_spec *spec = codec->spec; |
2467 | int err; | 2460 | struct snd_kcontrol *kctl; |
2468 | int i; | 2461 | struct snd_kcontrol_new *knew; |
2462 | int i, j, err; | ||
2463 | unsigned int u; | ||
2464 | hda_nid_t nid; | ||
2469 | 2465 | ||
2470 | for (i = 0; i < spec->num_mixers; i++) { | 2466 | for (i = 0; i < spec->num_mixers; i++) { |
2471 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | 2467 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); |
@@ -2506,8 +2502,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2506 | if (!kctl) | 2502 | if (!kctl) |
2507 | return -ENOMEM; | 2503 | return -ENOMEM; |
2508 | kctl->private_value = spec->beep_amp; | 2504 | kctl->private_value = spec->beep_amp; |
2509 | err = snd_hda_ctl_add(codec, | 2505 | err = snd_hda_ctl_add(codec, 0, kctl); |
2510 | get_amp_nid_(spec->beep_amp), kctl); | ||
2511 | if (err < 0) | 2506 | if (err < 0) |
2512 | return err; | 2507 | return err; |
2513 | } | 2508 | } |
@@ -2534,6 +2529,75 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2534 | } | 2529 | } |
2535 | 2530 | ||
2536 | alc_free_kctls(codec); /* no longer needed */ | 2531 | alc_free_kctls(codec); /* no longer needed */ |
2532 | |||
2533 | /* assign Capture Source enums to NID */ | ||
2534 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
2535 | if (!kctl) | ||
2536 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | ||
2537 | for (i = 0; kctl && i < kctl->count; i++) { | ||
2538 | hda_nid_t *nids = spec->capsrc_nids; | ||
2539 | if (!nids) | ||
2540 | nids = spec->adc_nids; | ||
2541 | err = snd_hda_add_nid(codec, kctl, i, nids[i]); | ||
2542 | if (err < 0) | ||
2543 | return err; | ||
2544 | } | ||
2545 | if (spec->cap_mixer) { | ||
2546 | const char *kname = kctl ? kctl->id.name : NULL; | ||
2547 | for (knew = spec->cap_mixer; knew->name; knew++) { | ||
2548 | if (kname && strcmp(knew->name, kname) == 0) | ||
2549 | continue; | ||
2550 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
2551 | for (i = 0; kctl && i < kctl->count; i++) { | ||
2552 | err = snd_hda_add_nid(codec, kctl, i, | ||
2553 | spec->adc_nids[i]); | ||
2554 | if (err < 0) | ||
2555 | return err; | ||
2556 | } | ||
2557 | } | ||
2558 | } | ||
2559 | |||
2560 | /* other nid->control mapping */ | ||
2561 | for (i = 0; i < spec->num_mixers; i++) { | ||
2562 | for (knew = spec->mixers[i]; knew->name; knew++) { | ||
2563 | if (knew->iface != NID_MAPPING) | ||
2564 | continue; | ||
2565 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
2566 | if (kctl == NULL) | ||
2567 | continue; | ||
2568 | u = knew->subdevice; | ||
2569 | for (j = 0; j < 4; j++, u >>= 8) { | ||
2570 | nid = u & 0x3f; | ||
2571 | if (nid == 0) | ||
2572 | continue; | ||
2573 | switch (u & 0xc0) { | ||
2574 | case SUBDEV_SPEAKER_: | ||
2575 | nid = spec->autocfg.speaker_pins[nid]; | ||
2576 | break; | ||
2577 | case SUBDEV_LINE_: | ||
2578 | nid = spec->autocfg.line_out_pins[nid]; | ||
2579 | break; | ||
2580 | case SUBDEV_HP_: | ||
2581 | nid = spec->autocfg.hp_pins[nid]; | ||
2582 | break; | ||
2583 | default: | ||
2584 | continue; | ||
2585 | } | ||
2586 | err = snd_hda_add_nid(codec, kctl, 0, nid); | ||
2587 | if (err < 0) | ||
2588 | return err; | ||
2589 | } | ||
2590 | u = knew->private_value; | ||
2591 | for (j = 0; j < 4; j++, u >>= 8) { | ||
2592 | nid = u & 0xff; | ||
2593 | if (nid == 0) | ||
2594 | continue; | ||
2595 | err = snd_hda_add_nid(codec, kctl, 0, nid); | ||
2596 | if (err < 0) | ||
2597 | return err; | ||
2598 | } | ||
2599 | } | ||
2600 | } | ||
2537 | return 0; | 2601 | return 0; |
2538 | } | 2602 | } |
2539 | 2603 | ||
@@ -3616,6 +3680,11 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3616 | return 0; | 3680 | return 0; |
3617 | } | 3681 | } |
3618 | 3682 | ||
3683 | static inline void alc_shutup(struct hda_codec *codec) | ||
3684 | { | ||
3685 | snd_hda_shutup_pins(codec); | ||
3686 | } | ||
3687 | |||
3619 | static void alc_free_kctls(struct hda_codec *codec) | 3688 | static void alc_free_kctls(struct hda_codec *codec) |
3620 | { | 3689 | { |
3621 | struct alc_spec *spec = codec->spec; | 3690 | struct alc_spec *spec = codec->spec; |
@@ -3636,17 +3705,44 @@ static void alc_free(struct hda_codec *codec) | |||
3636 | if (!spec) | 3705 | if (!spec) |
3637 | return; | 3706 | return; |
3638 | 3707 | ||
3708 | alc_shutup(codec); | ||
3639 | alc_free_kctls(codec); | 3709 | alc_free_kctls(codec); |
3640 | kfree(spec); | 3710 | kfree(spec); |
3641 | snd_hda_detach_beep_device(codec); | 3711 | snd_hda_detach_beep_device(codec); |
3642 | } | 3712 | } |
3643 | 3713 | ||
3644 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3714 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
3715 | static void alc_power_eapd(struct hda_codec *codec) | ||
3716 | { | ||
3717 | /* We currently only handle front, HP */ | ||
3718 | switch (codec->vendor_id) { | ||
3719 | case 0x10ec0260: | ||
3720 | set_eapd(codec, 0x0f, 0); | ||
3721 | set_eapd(codec, 0x10, 0); | ||
3722 | break; | ||
3723 | case 0x10ec0262: | ||
3724 | case 0x10ec0267: | ||
3725 | case 0x10ec0268: | ||
3726 | case 0x10ec0269: | ||
3727 | case 0x10ec0270: | ||
3728 | case 0x10ec0272: | ||
3729 | case 0x10ec0660: | ||
3730 | case 0x10ec0662: | ||
3731 | case 0x10ec0663: | ||
3732 | case 0x10ec0862: | ||
3733 | case 0x10ec0889: | ||
3734 | set_eapd(codec, 0x14, 0); | ||
3735 | set_eapd(codec, 0x15, 0); | ||
3736 | break; | ||
3737 | } | ||
3738 | } | ||
3739 | |||
3645 | static int alc_suspend(struct hda_codec *codec, pm_message_t state) | 3740 | static int alc_suspend(struct hda_codec *codec, pm_message_t state) |
3646 | { | 3741 | { |
3647 | struct alc_spec *spec = codec->spec; | 3742 | struct alc_spec *spec = codec->spec; |
3743 | alc_shutup(codec); | ||
3648 | if (spec && spec->power_hook) | 3744 | if (spec && spec->power_hook) |
3649 | spec->power_hook(codec, 0); | 3745 | spec->power_hook(codec); |
3650 | return 0; | 3746 | return 0; |
3651 | } | 3747 | } |
3652 | #endif | 3748 | #endif |
@@ -3654,16 +3750,9 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state) | |||
3654 | #ifdef SND_HDA_NEEDS_RESUME | 3750 | #ifdef SND_HDA_NEEDS_RESUME |
3655 | static int alc_resume(struct hda_codec *codec) | 3751 | static int alc_resume(struct hda_codec *codec) |
3656 | { | 3752 | { |
3657 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3658 | struct alc_spec *spec = codec->spec; | ||
3659 | #endif | ||
3660 | codec->patch_ops.init(codec); | 3753 | codec->patch_ops.init(codec); |
3661 | snd_hda_codec_resume_amp(codec); | 3754 | snd_hda_codec_resume_amp(codec); |
3662 | snd_hda_codec_resume_cache(codec); | 3755 | snd_hda_codec_resume_cache(codec); |
3663 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3664 | if (spec && spec->power_hook) | ||
3665 | spec->power_hook(codec, 1); | ||
3666 | #endif | ||
3667 | return 0; | 3756 | return 0; |
3668 | } | 3757 | } |
3669 | #endif | 3758 | #endif |
@@ -3683,6 +3772,7 @@ static struct hda_codec_ops alc_patch_ops = { | |||
3683 | .suspend = alc_suspend, | 3772 | .suspend = alc_suspend, |
3684 | .check_power_status = alc_check_power_status, | 3773 | .check_power_status = alc_check_power_status, |
3685 | #endif | 3774 | #endif |
3775 | .reboot_notify = alc_shutup, | ||
3686 | }; | 3776 | }; |
3687 | 3777 | ||
3688 | 3778 | ||
@@ -3839,6 +3929,7 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
3839 | #define PIN_CTL_TEST(xname,nid) { \ | 3929 | #define PIN_CTL_TEST(xname,nid) { \ |
3840 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3930 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3841 | .name = xname, \ | 3931 | .name = xname, \ |
3932 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
3842 | .info = alc_test_pin_ctl_info, \ | 3933 | .info = alc_test_pin_ctl_info, \ |
3843 | .get = alc_test_pin_ctl_get, \ | 3934 | .get = alc_test_pin_ctl_get, \ |
3844 | .put = alc_test_pin_ctl_put, \ | 3935 | .put = alc_test_pin_ctl_put, \ |
@@ -3848,6 +3939,7 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
3848 | #define PIN_SRC_TEST(xname,nid) { \ | 3939 | #define PIN_SRC_TEST(xname,nid) { \ |
3849 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3940 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
3850 | .name = xname, \ | 3941 | .name = xname, \ |
3942 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
3851 | .info = alc_test_pin_src_info, \ | 3943 | .info = alc_test_pin_src_info, \ |
3852 | .get = alc_test_pin_src_get, \ | 3944 | .get = alc_test_pin_src_get, \ |
3853 | .put = alc_test_pin_src_put, \ | 3945 | .put = alc_test_pin_src_put, \ |
@@ -4387,7 +4479,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
4387 | if (!knew->name) | 4479 | if (!knew->name) |
4388 | return -ENOMEM; | 4480 | return -ENOMEM; |
4389 | if (get_amp_nid_(val)) | 4481 | if (get_amp_nid_(val)) |
4390 | knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); | 4482 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
4391 | knew->private_value = val; | 4483 | knew->private_value = val; |
4392 | return 0; | 4484 | return 0; |
4393 | } | 4485 | } |
@@ -4770,7 +4862,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4770 | spec->num_mux_defs = 1; | 4862 | spec->num_mux_defs = 1; |
4771 | spec->input_mux = &spec->private_imux[0]; | 4863 | spec->input_mux = &spec->private_imux[0]; |
4772 | 4864 | ||
4773 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | 4865 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); |
4774 | 4866 | ||
4775 | return 1; | 4867 | return 1; |
4776 | } | 4868 | } |
@@ -4823,7 +4915,7 @@ static void fixup_automic_adc(struct hda_codec *codec) | |||
4823 | static void fixup_single_adc(struct hda_codec *codec) | 4915 | static void fixup_single_adc(struct hda_codec *codec) |
4824 | { | 4916 | { |
4825 | struct alc_spec *spec = codec->spec; | 4917 | struct alc_spec *spec = codec->spec; |
4826 | hda_nid_t pin; | 4918 | hda_nid_t pin = 0; |
4827 | int i; | 4919 | int i; |
4828 | 4920 | ||
4829 | /* search for the input pin; there must be only one */ | 4921 | /* search for the input pin; there must be only one */ |
@@ -4974,7 +5066,6 @@ static int patch_alc880(struct hda_codec *codec) | |||
4974 | if (!spec->loopback.amplist) | 5066 | if (!spec->loopback.amplist) |
4975 | spec->loopback.amplist = alc880_loopbacks; | 5067 | spec->loopback.amplist = alc880_loopbacks; |
4976 | #endif | 5068 | #endif |
4977 | codec->proc_widget_hook = print_realtek_coef; | ||
4978 | 5069 | ||
4979 | return 0; | 5070 | return 0; |
4980 | } | 5071 | } |
@@ -5182,6 +5273,7 @@ static struct snd_kcontrol_new alc260_hp_output_mixer[] = { | |||
5182 | { | 5273 | { |
5183 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5274 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5184 | .name = "Master Playback Switch", | 5275 | .name = "Master Playback Switch", |
5276 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, | ||
5185 | .info = snd_ctl_boolean_mono_info, | 5277 | .info = snd_ctl_boolean_mono_info, |
5186 | .get = alc260_hp_master_sw_get, | 5278 | .get = alc260_hp_master_sw_get, |
5187 | .put = alc260_hp_master_sw_put, | 5279 | .put = alc260_hp_master_sw_put, |
@@ -5220,6 +5312,7 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { | |||
5220 | { | 5312 | { |
5221 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5313 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5222 | .name = "Master Playback Switch", | 5314 | .name = "Master Playback Switch", |
5315 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x11, | ||
5223 | .info = snd_ctl_boolean_mono_info, | 5316 | .info = snd_ctl_boolean_mono_info, |
5224 | .get = alc260_hp_master_sw_get, | 5317 | .get = alc260_hp_master_sw_get, |
5225 | .put = alc260_hp_master_sw_put, | 5318 | .put = alc260_hp_master_sw_put, |
@@ -6303,7 +6396,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
6303 | spec->num_mux_defs = 1; | 6396 | spec->num_mux_defs = 1; |
6304 | spec->input_mux = &spec->private_imux[0]; | 6397 | spec->input_mux = &spec->private_imux[0]; |
6305 | 6398 | ||
6306 | alc_ssid_check(codec, 0x10, 0x15, 0x0f); | 6399 | alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0); |
6307 | 6400 | ||
6308 | return 1; | 6401 | return 1; |
6309 | } | 6402 | } |
@@ -6582,7 +6675,6 @@ static int patch_alc260(struct hda_codec *codec) | |||
6582 | if (!spec->loopback.amplist) | 6675 | if (!spec->loopback.amplist) |
6583 | spec->loopback.amplist = alc260_loopbacks; | 6676 | spec->loopback.amplist = alc260_loopbacks; |
6584 | #endif | 6677 | #endif |
6585 | codec->proc_widget_hook = print_realtek_coef; | ||
6586 | 6678 | ||
6587 | return 0; | 6679 | return 0; |
6588 | } | 6680 | } |
@@ -6664,6 +6756,14 @@ static struct hda_input_mux mb5_capture_source = { | |||
6664 | }, | 6756 | }, |
6665 | }; | 6757 | }; |
6666 | 6758 | ||
6759 | static struct hda_input_mux macmini3_capture_source = { | ||
6760 | .num_items = 2, | ||
6761 | .items = { | ||
6762 | { "Line", 0x2 }, | ||
6763 | { "CD", 0x4 }, | ||
6764 | }, | ||
6765 | }; | ||
6766 | |||
6667 | static struct hda_input_mux alc883_3stack_6ch_intel = { | 6767 | static struct hda_input_mux alc883_3stack_6ch_intel = { |
6668 | .num_items = 4, | 6768 | .num_items = 4, |
6669 | .items = { | 6769 | .items = { |
@@ -6852,6 +6952,13 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = { | |||
6852 | { 8, alc882_sixstack_ch8_init }, | 6952 | { 8, alc882_sixstack_ch8_init }, |
6853 | }; | 6953 | }; |
6854 | 6954 | ||
6955 | |||
6956 | /* Macbook Air 2,1 */ | ||
6957 | |||
6958 | static struct hda_channel_mode alc885_mba21_ch_modes[1] = { | ||
6959 | { 2, NULL }, | ||
6960 | }; | ||
6961 | |||
6855 | /* | 6962 | /* |
6856 | * macbook pro ALC885 can switch LineIn to LineOut without losing Mic | 6963 | * macbook pro ALC885 can switch LineIn to LineOut without losing Mic |
6857 | */ | 6964 | */ |
@@ -6912,6 +7019,7 @@ static struct hda_channel_mode alc885_mb5_6ch_modes[2] = { | |||
6912 | { 6, alc885_mb5_ch6_init }, | 7019 | { 6, alc885_mb5_ch6_init }, |
6913 | }; | 7020 | }; |
6914 | 7021 | ||
7022 | #define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes | ||
6915 | 7023 | ||
6916 | /* | 7024 | /* |
6917 | * 2ch mode | 7025 | * 2ch mode |
@@ -7123,6 +7231,15 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
7123 | { } /* end */ | 7231 | { } /* end */ |
7124 | }; | 7232 | }; |
7125 | 7233 | ||
7234 | /* Macbook Air 2,1 same control for HP and internal Speaker */ | ||
7235 | |||
7236 | static struct snd_kcontrol_new alc885_mba21_mixer[] = { | ||
7237 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
7238 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT), | ||
7239 | { } | ||
7240 | }; | ||
7241 | |||
7242 | |||
7126 | static struct snd_kcontrol_new alc885_mbp3_mixer[] = { | 7243 | static struct snd_kcontrol_new alc885_mbp3_mixer[] = { |
7127 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | 7244 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), |
7128 | HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), | 7245 | HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), |
@@ -7156,6 +7273,21 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = { | |||
7156 | { } /* end */ | 7273 | { } /* end */ |
7157 | }; | 7274 | }; |
7158 | 7275 | ||
7276 | static struct snd_kcontrol_new alc885_macmini3_mixer[] = { | ||
7277 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
7278 | HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
7279 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
7280 | HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), | ||
7281 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), | ||
7282 | HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), | ||
7283 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), | ||
7284 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), | ||
7285 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
7286 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
7287 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT), | ||
7288 | { } /* end */ | ||
7289 | }; | ||
7290 | |||
7159 | static struct snd_kcontrol_new alc885_imac91_mixer[] = { | 7291 | static struct snd_kcontrol_new alc885_imac91_mixer[] = { |
7160 | HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | 7292 | HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT), |
7161 | HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, HDA_INPUT), | 7293 | HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, HDA_INPUT), |
@@ -7247,29 +7379,18 @@ static struct snd_kcontrol_new alc882_chmode_mixer[] = { | |||
7247 | 7379 | ||
7248 | static struct hda_verb alc882_base_init_verbs[] = { | 7380 | static struct hda_verb alc882_base_init_verbs[] = { |
7249 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 7381 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
7250 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7251 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7382 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7252 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 7383 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7253 | /* Rear mixer */ | 7384 | /* Rear mixer */ |
7254 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7255 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7385 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7256 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 7386 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7257 | /* CLFE mixer */ | 7387 | /* CLFE mixer */ |
7258 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7259 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7388 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7260 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 7389 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7261 | /* Side mixer */ | 7390 | /* Side mixer */ |
7262 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7263 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7391 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7264 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 7392 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7265 | 7393 | ||
7266 | /* mute analog input loopbacks */ | ||
7267 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7268 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7269 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7270 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7271 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
7272 | |||
7273 | /* Front Pin: output 0 (0x0c) */ | 7394 | /* Front Pin: output 0 (0x0c) */ |
7274 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 7395 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
7275 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 7396 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -7306,14 +7427,8 @@ static struct hda_verb alc882_base_init_verbs[] = { | |||
7306 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | 7427 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ |
7307 | /* Input mixer2 */ | 7428 | /* Input mixer2 */ |
7308 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7429 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7309 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7310 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7311 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
7312 | /* Input mixer3 */ | 7430 | /* Input mixer3 */ |
7313 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7431 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7314 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7315 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7316 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
7317 | /* ADC2: mute amp left and right */ | 7432 | /* ADC2: mute amp left and right */ |
7318 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7433 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7319 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7434 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -7357,26 +7472,17 @@ static struct hda_verb alc_hp15_unsol_verbs[] = { | |||
7357 | 7472 | ||
7358 | static struct hda_verb alc885_init_verbs[] = { | 7473 | static struct hda_verb alc885_init_verbs[] = { |
7359 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 7474 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
7360 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 7475 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7361 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7476 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7362 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7363 | /* Rear mixer */ | 7477 | /* Rear mixer */ |
7364 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 7478 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7365 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7479 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7366 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7367 | /* CLFE mixer */ | 7480 | /* CLFE mixer */ |
7368 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 7481 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7369 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7482 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7370 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7371 | /* Side mixer */ | 7483 | /* Side mixer */ |
7372 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 7484 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7373 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7485 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7374 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7375 | |||
7376 | /* mute analog input loopbacks */ | ||
7377 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7378 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7379 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7380 | 7486 | ||
7381 | /* Front HP Pin: output 0 (0x0c) */ | 7487 | /* Front HP Pin: output 0 (0x0c) */ |
7382 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 7488 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
@@ -7410,17 +7516,11 @@ static struct hda_verb alc885_init_verbs[] = { | |||
7410 | 7516 | ||
7411 | /* Mixer elements: 0x18, , 0x1a, 0x1b */ | 7517 | /* Mixer elements: 0x18, , 0x1a, 0x1b */ |
7412 | /* Input mixer1 */ | 7518 | /* Input mixer1 */ |
7413 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7519 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7414 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7415 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7416 | /* Input mixer2 */ | 7520 | /* Input mixer2 */ |
7417 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7521 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7418 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7419 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7420 | /* Input mixer3 */ | 7522 | /* Input mixer3 */ |
7421 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7523 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7422 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7423 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7424 | /* ADC2: mute amp left and right */ | 7524 | /* ADC2: mute amp left and right */ |
7425 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 7525 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7426 | /* ADC3: mute amp left and right */ | 7526 | /* ADC3: mute amp left and right */ |
@@ -7562,6 +7662,76 @@ static struct hda_verb alc885_mb5_init_verbs[] = { | |||
7562 | { } | 7662 | { } |
7563 | }; | 7663 | }; |
7564 | 7664 | ||
7665 | /* Macmini 3,1 */ | ||
7666 | static struct hda_verb alc885_macmini3_init_verbs[] = { | ||
7667 | /* DACs */ | ||
7668 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7669 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7670 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7671 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7672 | /* Front mixer */ | ||
7673 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7674 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7675 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7676 | /* Surround mixer */ | ||
7677 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7678 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7679 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7680 | /* LFE mixer */ | ||
7681 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7682 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7683 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7684 | /* HP mixer */ | ||
7685 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7686 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7687 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7688 | /* Front Pin (0x0c) */ | ||
7689 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
7690 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7691 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7692 | /* LFE Pin (0x0e) */ | ||
7693 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
7694 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7695 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
7696 | /* HP Pin (0x0f) */ | ||
7697 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
7698 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7699 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
7700 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
7701 | /* Line In pin */ | ||
7702 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
7703 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
7704 | |||
7705 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
7706 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7707 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7708 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
7709 | { } | ||
7710 | }; | ||
7711 | |||
7712 | |||
7713 | static struct hda_verb alc885_mba21_init_verbs[] = { | ||
7714 | /*Internal and HP Speaker Mixer*/ | ||
7715 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
7716 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
7717 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
7718 | /*Internal Speaker Pin (0x0c)*/ | ||
7719 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, | ||
7720 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7721 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7722 | /* HP Pin: output 0 (0x0e) */ | ||
7723 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, | ||
7724 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7725 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7726 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)}, | ||
7727 | /* Line in (is hp when jack connected)*/ | ||
7728 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50}, | ||
7729 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
7730 | |||
7731 | { } | ||
7732 | }; | ||
7733 | |||
7734 | |||
7565 | /* Macbook Pro rev3 */ | 7735 | /* Macbook Pro rev3 */ |
7566 | static struct hda_verb alc885_mbp3_init_verbs[] = { | 7736 | static struct hda_verb alc885_mbp3_init_verbs[] = { |
7567 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 7737 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
@@ -7724,54 +7894,35 @@ static void alc885_imac24_setup(struct hda_codec *codec) | |||
7724 | spec->autocfg.speaker_pins[1] = 0x1a; | 7894 | spec->autocfg.speaker_pins[1] = 0x1a; |
7725 | } | 7895 | } |
7726 | 7896 | ||
7727 | static void alc885_mbp3_setup(struct hda_codec *codec) | 7897 | #define alc885_mb5_setup alc885_imac24_setup |
7728 | { | 7898 | #define alc885_macmini3_setup alc885_imac24_setup |
7729 | struct alc_spec *spec = codec->spec; | ||
7730 | |||
7731 | spec->autocfg.hp_pins[0] = 0x15; | ||
7732 | spec->autocfg.speaker_pins[0] = 0x14; | ||
7733 | } | ||
7734 | 7899 | ||
7735 | static void alc885_mb5_automute(struct hda_codec *codec) | 7900 | /* Macbook Air 2,1 */ |
7901 | static void alc885_mba21_setup(struct hda_codec *codec) | ||
7736 | { | 7902 | { |
7737 | unsigned int present; | 7903 | struct alc_spec *spec = codec->spec; |
7738 | |||
7739 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
7740 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
7741 | snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, | ||
7742 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7743 | snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0, | ||
7744 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7745 | 7904 | ||
7905 | spec->autocfg.hp_pins[0] = 0x14; | ||
7906 | spec->autocfg.speaker_pins[0] = 0x18; | ||
7746 | } | 7907 | } |
7747 | 7908 | ||
7748 | static void alc885_mb5_unsol_event(struct hda_codec *codec, | ||
7749 | unsigned int res) | ||
7750 | { | ||
7751 | /* Headphone insertion or removal. */ | ||
7752 | if ((res >> 26) == ALC880_HP_EVENT) | ||
7753 | alc885_mb5_automute(codec); | ||
7754 | } | ||
7755 | 7909 | ||
7756 | static void alc885_imac91_automute(struct hda_codec *codec) | ||
7757 | { | ||
7758 | unsigned int present; | ||
7759 | 7910 | ||
7760 | present = snd_hda_codec_read(codec, 0x14, 0, | 7911 | static void alc885_mbp3_setup(struct hda_codec *codec) |
7761 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 7912 | { |
7762 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | 7913 | struct alc_spec *spec = codec->spec; |
7763 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7764 | snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0, | ||
7765 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7766 | 7914 | ||
7915 | spec->autocfg.hp_pins[0] = 0x15; | ||
7916 | spec->autocfg.speaker_pins[0] = 0x14; | ||
7767 | } | 7917 | } |
7768 | 7918 | ||
7769 | static void alc885_imac91_unsol_event(struct hda_codec *codec, | 7919 | static void alc885_imac91_setup(struct hda_codec *codec) |
7770 | unsigned int res) | ||
7771 | { | 7920 | { |
7772 | /* Headphone insertion or removal. */ | 7921 | struct alc_spec *spec = codec->spec; |
7773 | if ((res >> 26) == ALC880_HP_EVENT) | 7922 | |
7774 | alc885_imac91_automute(codec); | 7923 | spec->autocfg.hp_pins[0] = 0x14; |
7924 | spec->autocfg.speaker_pins[0] = 0x15; | ||
7925 | spec->autocfg.speaker_pins[1] = 0x1a; | ||
7775 | } | 7926 | } |
7776 | 7927 | ||
7777 | static struct hda_verb alc882_targa_verbs[] = { | 7928 | static struct hda_verb alc882_targa_verbs[] = { |
@@ -7906,18 +8057,6 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
7906 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 8057 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7907 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8058 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7908 | 8059 | ||
7909 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
7910 | * mixer widget | ||
7911 | * Note: PASD motherboards uses the Line In 2 as the input for | ||
7912 | * front panel mic (mic 2) | ||
7913 | */ | ||
7914 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
7915 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
7916 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
7917 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
7918 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
7919 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
7920 | |||
7921 | /* | 8060 | /* |
7922 | * Set up output mixers (0x0c - 0x0f) | 8061 | * Set up output mixers (0x0c - 0x0f) |
7923 | */ | 8062 | */ |
@@ -7942,16 +8081,9 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
7942 | /* FIXME: use matrix-type input source selection */ | 8081 | /* FIXME: use matrix-type input source selection */ |
7943 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | 8082 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ |
7944 | /* Input mixer2 */ | 8083 | /* Input mixer2 */ |
7945 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 8084 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7946 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | ||
7947 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | ||
7948 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | ||
7949 | /* Input mixer3 */ | 8085 | /* Input mixer3 */ |
7950 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 8086 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7951 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | ||
7952 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | ||
7953 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | ||
7954 | |||
7955 | { } | 8087 | { } |
7956 | }; | 8088 | }; |
7957 | 8089 | ||
@@ -8938,6 +9070,8 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
8938 | [ALC882_ASUS_A7M] = "asus-a7m", | 9070 | [ALC882_ASUS_A7M] = "asus-a7m", |
8939 | [ALC885_MACPRO] = "macpro", | 9071 | [ALC885_MACPRO] = "macpro", |
8940 | [ALC885_MB5] = "mb5", | 9072 | [ALC885_MB5] = "mb5", |
9073 | [ALC885_MACMINI3] = "macmini3", | ||
9074 | [ALC885_MBA21] = "mba21", | ||
8941 | [ALC885_MBP3] = "mbp3", | 9075 | [ALC885_MBP3] = "mbp3", |
8942 | [ALC885_IMAC24] = "imac24", | 9076 | [ALC885_IMAC24] = "imac24", |
8943 | [ALC885_IMAC91] = "imac91", | 9077 | [ALC885_IMAC91] = "imac91", |
@@ -9121,6 +9255,7 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { | |||
9121 | */ | 9255 | */ |
9122 | SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5), | 9256 | SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5), |
9123 | SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5), | 9257 | SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5), |
9258 | SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3), | ||
9124 | {} /* terminator */ | 9259 | {} /* terminator */ |
9125 | }; | 9260 | }; |
9126 | 9261 | ||
@@ -9172,6 +9307,18 @@ static struct alc_config_preset alc882_presets[] = { | |||
9172 | .input_mux = &alc882_capture_source, | 9307 | .input_mux = &alc882_capture_source, |
9173 | .dig_out_nid = ALC882_DIGOUT_NID, | 9308 | .dig_out_nid = ALC882_DIGOUT_NID, |
9174 | }, | 9309 | }, |
9310 | [ALC885_MBA21] = { | ||
9311 | .mixers = { alc885_mba21_mixer }, | ||
9312 | .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs }, | ||
9313 | .num_dacs = 2, | ||
9314 | .dac_nids = alc882_dac_nids, | ||
9315 | .channel_mode = alc885_mba21_ch_modes, | ||
9316 | .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), | ||
9317 | .input_mux = &alc882_capture_source, | ||
9318 | .unsol_event = alc_automute_amp_unsol_event, | ||
9319 | .setup = alc885_mba21_setup, | ||
9320 | .init_hook = alc_automute_amp, | ||
9321 | }, | ||
9175 | [ALC885_MBP3] = { | 9322 | [ALC885_MBP3] = { |
9176 | .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, | 9323 | .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, |
9177 | .init_verbs = { alc885_mbp3_init_verbs, | 9324 | .init_verbs = { alc885_mbp3_init_verbs, |
@@ -9199,8 +9346,24 @@ static struct alc_config_preset alc882_presets[] = { | |||
9199 | .input_mux = &mb5_capture_source, | 9346 | .input_mux = &mb5_capture_source, |
9200 | .dig_out_nid = ALC882_DIGOUT_NID, | 9347 | .dig_out_nid = ALC882_DIGOUT_NID, |
9201 | .dig_in_nid = ALC882_DIGIN_NID, | 9348 | .dig_in_nid = ALC882_DIGIN_NID, |
9202 | .unsol_event = alc885_mb5_unsol_event, | 9349 | .unsol_event = alc_automute_amp_unsol_event, |
9203 | .init_hook = alc885_mb5_automute, | 9350 | .setup = alc885_mb5_setup, |
9351 | .init_hook = alc_automute_amp, | ||
9352 | }, | ||
9353 | [ALC885_MACMINI3] = { | ||
9354 | .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer }, | ||
9355 | .init_verbs = { alc885_macmini3_init_verbs, | ||
9356 | alc880_gpio1_init_verbs }, | ||
9357 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
9358 | .dac_nids = alc882_dac_nids, | ||
9359 | .channel_mode = alc885_macmini3_6ch_modes, | ||
9360 | .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes), | ||
9361 | .input_mux = &macmini3_capture_source, | ||
9362 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
9363 | .dig_in_nid = ALC882_DIGIN_NID, | ||
9364 | .unsol_event = alc_automute_amp_unsol_event, | ||
9365 | .setup = alc885_macmini3_setup, | ||
9366 | .init_hook = alc_automute_amp, | ||
9204 | }, | 9367 | }, |
9205 | [ALC885_MACPRO] = { | 9368 | [ALC885_MACPRO] = { |
9206 | .mixers = { alc882_macpro_mixer }, | 9369 | .mixers = { alc882_macpro_mixer }, |
@@ -9239,8 +9402,9 @@ static struct alc_config_preset alc882_presets[] = { | |||
9239 | .input_mux = &alc882_capture_source, | 9402 | .input_mux = &alc882_capture_source, |
9240 | .dig_out_nid = ALC882_DIGOUT_NID, | 9403 | .dig_out_nid = ALC882_DIGOUT_NID, |
9241 | .dig_in_nid = ALC882_DIGIN_NID, | 9404 | .dig_in_nid = ALC882_DIGIN_NID, |
9242 | .unsol_event = alc885_imac91_unsol_event, | 9405 | .unsol_event = alc_automute_amp_unsol_event, |
9243 | .init_hook = alc885_imac91_automute, | 9406 | .setup = alc885_imac91_setup, |
9407 | .init_hook = alc_automute_amp, | ||
9244 | }, | 9408 | }, |
9245 | [ALC882_TARGA] = { | 9409 | [ALC882_TARGA] = { |
9246 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer }, | 9410 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer }, |
@@ -9528,7 +9692,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
9528 | .setup = alc889_acer_aspire_8930g_setup, | 9692 | .setup = alc889_acer_aspire_8930g_setup, |
9529 | .init_hook = alc_automute_amp, | 9693 | .init_hook = alc_automute_amp, |
9530 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 9694 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
9531 | .power_hook = alc889_power_eapd, | 9695 | .power_hook = alc_power_eapd, |
9532 | #endif | 9696 | #endif |
9533 | }, | 9697 | }, |
9534 | [ALC888_ACER_ASPIRE_7730G] = { | 9698 | [ALC888_ACER_ASPIRE_7730G] = { |
@@ -10063,7 +10227,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
10063 | spec->num_mux_defs = 1; | 10227 | spec->num_mux_defs = 1; |
10064 | spec->input_mux = &spec->private_imux[0]; | 10228 | spec->input_mux = &spec->private_imux[0]; |
10065 | 10229 | ||
10066 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | 10230 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); |
10067 | 10231 | ||
10068 | err = alc_auto_add_mic_boost(codec); | 10232 | err = alc_auto_add_mic_boost(codec); |
10069 | if (err < 0) | 10233 | if (err < 0) |
@@ -10201,7 +10365,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
10201 | if (!spec->loopback.amplist) | 10365 | if (!spec->loopback.amplist) |
10202 | spec->loopback.amplist = alc882_loopbacks; | 10366 | spec->loopback.amplist = alc882_loopbacks; |
10203 | #endif | 10367 | #endif |
10204 | codec->proc_widget_hook = print_realtek_coef; | ||
10205 | 10368 | ||
10206 | return 0; | 10369 | return 0; |
10207 | } | 10370 | } |
@@ -10324,8 +10487,14 @@ static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
10324 | .info = snd_ctl_boolean_mono_info, \ | 10487 | .info = snd_ctl_boolean_mono_info, \ |
10325 | .get = alc262_hp_master_sw_get, \ | 10488 | .get = alc262_hp_master_sw_get, \ |
10326 | .put = alc262_hp_master_sw_put, \ | 10489 | .put = alc262_hp_master_sw_put, \ |
10490 | }, \ | ||
10491 | { \ | ||
10492 | .iface = NID_MAPPING, \ | ||
10493 | .name = "Master Playback Switch", \ | ||
10494 | .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \ | ||
10327 | } | 10495 | } |
10328 | 10496 | ||
10497 | |||
10329 | static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { | 10498 | static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { |
10330 | ALC262_HP_MASTER_SWITCH, | 10499 | ALC262_HP_MASTER_SWITCH, |
10331 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 10500 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -10483,6 +10652,12 @@ static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol, | |||
10483 | .info = snd_ctl_boolean_mono_info, \ | 10652 | .info = snd_ctl_boolean_mono_info, \ |
10484 | .get = alc262_hippo_master_sw_get, \ | 10653 | .get = alc262_hippo_master_sw_get, \ |
10485 | .put = alc262_hippo_master_sw_put, \ | 10654 | .put = alc262_hippo_master_sw_put, \ |
10655 | }, \ | ||
10656 | { \ | ||
10657 | .iface = NID_MAPPING, \ | ||
10658 | .name = "Master Playback Switch", \ | ||
10659 | .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \ | ||
10660 | (SUBDEV_SPEAKER(0) << 16), \ | ||
10486 | } | 10661 | } |
10487 | 10662 | ||
10488 | static struct snd_kcontrol_new alc262_hippo_mixer[] = { | 10663 | static struct snd_kcontrol_new alc262_hippo_mixer[] = { |
@@ -10963,11 +11138,17 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
10963 | { | 11138 | { |
10964 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 11139 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
10965 | .name = "Master Playback Switch", | 11140 | .name = "Master Playback Switch", |
11141 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
10966 | .info = snd_hda_mixer_amp_switch_info, | 11142 | .info = snd_hda_mixer_amp_switch_info, |
10967 | .get = snd_hda_mixer_amp_switch_get, | 11143 | .get = snd_hda_mixer_amp_switch_get, |
10968 | .put = alc262_fujitsu_master_sw_put, | 11144 | .put = alc262_fujitsu_master_sw_put, |
10969 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | 11145 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), |
10970 | }, | 11146 | }, |
11147 | { | ||
11148 | .iface = NID_MAPPING, | ||
11149 | .name = "Master Playback Switch", | ||
11150 | .private_value = 0x1b, | ||
11151 | }, | ||
10971 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 11152 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
10972 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 11153 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
10973 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11154 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
@@ -10998,6 +11179,7 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = { | |||
10998 | { | 11179 | { |
10999 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 11180 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
11000 | .name = "Master Playback Switch", | 11181 | .name = "Master Playback Switch", |
11182 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
11001 | .info = snd_hda_mixer_amp_switch_info, | 11183 | .info = snd_hda_mixer_amp_switch_info, |
11002 | .get = snd_hda_mixer_amp_switch_get, | 11184 | .get = snd_hda_mixer_amp_switch_get, |
11003 | .put = alc262_lenovo_3000_master_sw_put, | 11185 | .put = alc262_lenovo_3000_master_sw_put, |
@@ -11152,6 +11334,11 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = { | |||
11152 | .get = alc_mux_enum_get, | 11334 | .get = alc_mux_enum_get, |
11153 | .put = alc262_ultra_mux_enum_put, | 11335 | .put = alc262_ultra_mux_enum_put, |
11154 | }, | 11336 | }, |
11337 | { | ||
11338 | .iface = NID_MAPPING, | ||
11339 | .name = "Capture Source", | ||
11340 | .private_value = 0x15, | ||
11341 | }, | ||
11155 | { } /* end */ | 11342 | { } /* end */ |
11156 | }; | 11343 | }; |
11157 | 11344 | ||
@@ -11598,7 +11785,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
11598 | if (err < 0) | 11785 | if (err < 0) |
11599 | return err; | 11786 | return err; |
11600 | 11787 | ||
11601 | alc_ssid_check(codec, 0x15, 0x14, 0x1b); | 11788 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); |
11602 | 11789 | ||
11603 | return 1; | 11790 | return 1; |
11604 | } | 11791 | } |
@@ -12041,7 +12228,6 @@ static int patch_alc262(struct hda_codec *codec) | |||
12041 | if (!spec->loopback.amplist) | 12228 | if (!spec->loopback.amplist) |
12042 | spec->loopback.amplist = alc262_loopbacks; | 12229 | spec->loopback.amplist = alc262_loopbacks; |
12043 | #endif | 12230 | #endif |
12044 | codec->proc_widget_hook = print_realtek_coef; | ||
12045 | 12231 | ||
12046 | return 0; | 12232 | return 0; |
12047 | } | 12233 | } |
@@ -12170,6 +12356,7 @@ static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = { | |||
12170 | { | 12356 | { |
12171 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12357 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12172 | .name = "Master Playback Switch", | 12358 | .name = "Master Playback Switch", |
12359 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12173 | .info = snd_hda_mixer_amp_switch_info, | 12360 | .info = snd_hda_mixer_amp_switch_info, |
12174 | .get = snd_hda_mixer_amp_switch_get, | 12361 | .get = snd_hda_mixer_amp_switch_get, |
12175 | .put = alc268_acer_master_sw_put, | 12362 | .put = alc268_acer_master_sw_put, |
@@ -12185,6 +12372,7 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = { | |||
12185 | { | 12372 | { |
12186 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12373 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12187 | .name = "Master Playback Switch", | 12374 | .name = "Master Playback Switch", |
12375 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12188 | .info = snd_hda_mixer_amp_switch_info, | 12376 | .info = snd_hda_mixer_amp_switch_info, |
12189 | .get = snd_hda_mixer_amp_switch_get, | 12377 | .get = snd_hda_mixer_amp_switch_get, |
12190 | .put = alc268_acer_master_sw_put, | 12378 | .put = alc268_acer_master_sw_put, |
@@ -12202,6 +12390,7 @@ static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = { | |||
12202 | { | 12390 | { |
12203 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12391 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12204 | .name = "Master Playback Switch", | 12392 | .name = "Master Playback Switch", |
12393 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
12205 | .info = snd_hda_mixer_amp_switch_info, | 12394 | .info = snd_hda_mixer_amp_switch_info, |
12206 | .get = snd_hda_mixer_amp_switch_get, | 12395 | .get = snd_hda_mixer_amp_switch_get, |
12207 | .put = alc268_acer_master_sw_put, | 12396 | .put = alc268_acer_master_sw_put, |
@@ -12547,7 +12736,6 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | |||
12547 | dac = 0x02; | 12736 | dac = 0x02; |
12548 | break; | 12737 | break; |
12549 | case 0x15: | 12738 | case 0x15: |
12550 | case 0x21: | ||
12551 | dac = 0x03; | 12739 | dac = 0x03; |
12552 | break; | 12740 | break; |
12553 | default: | 12741 | default: |
@@ -12768,7 +12956,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
12768 | if (err < 0) | 12956 | if (err < 0) |
12769 | return err; | 12957 | return err; |
12770 | 12958 | ||
12771 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | 12959 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); |
12772 | 12960 | ||
12773 | return 1; | 12961 | return 1; |
12774 | } | 12962 | } |
@@ -13105,8 +13293,6 @@ static int patch_alc268(struct hda_codec *codec) | |||
13105 | if (board_config == ALC268_AUTO) | 13293 | if (board_config == ALC268_AUTO) |
13106 | spec->init_hook = alc268_auto_init; | 13294 | spec->init_hook = alc268_auto_init; |
13107 | 13295 | ||
13108 | codec->proc_widget_hook = print_realtek_coef; | ||
13109 | |||
13110 | return 0; | 13296 | return 0; |
13111 | } | 13297 | } |
13112 | 13298 | ||
@@ -13126,6 +13312,15 @@ static hda_nid_t alc269_capsrc_nids[1] = { | |||
13126 | 0x23, | 13312 | 0x23, |
13127 | }; | 13313 | }; |
13128 | 13314 | ||
13315 | static hda_nid_t alc269vb_adc_nids[1] = { | ||
13316 | /* ADC1 */ | ||
13317 | 0x09, | ||
13318 | }; | ||
13319 | |||
13320 | static hda_nid_t alc269vb_capsrc_nids[1] = { | ||
13321 | 0x22, | ||
13322 | }; | ||
13323 | |||
13129 | /* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24), | 13324 | /* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24), |
13130 | * not a mux! | 13325 | * not a mux! |
13131 | */ | 13326 | */ |
@@ -13155,6 +13350,7 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
13155 | { | 13350 | { |
13156 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 13351 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
13157 | .name = "Master Playback Switch", | 13352 | .name = "Master Playback Switch", |
13353 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
13158 | .info = snd_hda_mixer_amp_switch_info, | 13354 | .info = snd_hda_mixer_amp_switch_info, |
13159 | .get = snd_hda_mixer_amp_switch_get, | 13355 | .get = snd_hda_mixer_amp_switch_get, |
13160 | .put = alc268_acer_master_sw_put, | 13356 | .put = alc268_acer_master_sw_put, |
@@ -13175,6 +13371,7 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | |||
13175 | { | 13371 | { |
13176 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 13372 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
13177 | .name = "Master Playback Switch", | 13373 | .name = "Master Playback Switch", |
13374 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
13178 | .info = snd_hda_mixer_amp_switch_info, | 13375 | .info = snd_hda_mixer_amp_switch_info, |
13179 | .get = snd_hda_mixer_amp_switch_get, | 13376 | .get = snd_hda_mixer_amp_switch_get, |
13180 | .put = alc268_acer_master_sw_put, | 13377 | .put = alc268_acer_master_sw_put, |
@@ -13192,7 +13389,7 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | |||
13192 | { } | 13389 | { } |
13193 | }; | 13390 | }; |
13194 | 13391 | ||
13195 | static struct snd_kcontrol_new alc269_eeepc_mixer[] = { | 13392 | static struct snd_kcontrol_new alc269_laptop_mixer[] = { |
13196 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 13393 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
13197 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), | 13394 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), |
13198 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 13395 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
@@ -13200,16 +13397,47 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = { | |||
13200 | { } /* end */ | 13397 | { } /* end */ |
13201 | }; | 13398 | }; |
13202 | 13399 | ||
13400 | static struct snd_kcontrol_new alc269vb_laptop_mixer[] = { | ||
13401 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
13402 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
13403 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT), | ||
13404 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
13405 | { } /* end */ | ||
13406 | }; | ||
13407 | |||
13203 | /* capture mixer elements */ | 13408 | /* capture mixer elements */ |
13204 | static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { | 13409 | static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = { |
13410 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
13411 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
13412 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
13413 | HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT), | ||
13414 | { } /* end */ | ||
13415 | }; | ||
13416 | |||
13417 | static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = { | ||
13205 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 13418 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
13206 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 13419 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
13207 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 13420 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
13208 | { } /* end */ | 13421 | { } /* end */ |
13209 | }; | 13422 | }; |
13210 | 13423 | ||
13424 | static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = { | ||
13425 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
13426 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
13427 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
13428 | HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT), | ||
13429 | { } /* end */ | ||
13430 | }; | ||
13431 | |||
13432 | static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = { | ||
13433 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
13434 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
13435 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
13436 | { } /* end */ | ||
13437 | }; | ||
13438 | |||
13211 | /* FSC amilo */ | 13439 | /* FSC amilo */ |
13212 | #define alc269_fujitsu_mixer alc269_eeepc_mixer | 13440 | #define alc269_fujitsu_mixer alc269_laptop_mixer |
13213 | 13441 | ||
13214 | static struct hda_verb alc269_quanta_fl1_verbs[] = { | 13442 | static struct hda_verb alc269_quanta_fl1_verbs[] = { |
13215 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 13443 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
@@ -13333,6 +13561,8 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec, | |||
13333 | static void alc269_quanta_fl1_setup(struct hda_codec *codec) | 13561 | static void alc269_quanta_fl1_setup(struct hda_codec *codec) |
13334 | { | 13562 | { |
13335 | struct alc_spec *spec = codec->spec; | 13563 | struct alc_spec *spec = codec->spec; |
13564 | spec->autocfg.hp_pins[0] = 0x15; | ||
13565 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13336 | spec->ext_mic.pin = 0x18; | 13566 | spec->ext_mic.pin = 0x18; |
13337 | spec->ext_mic.mux_idx = 0; | 13567 | spec->ext_mic.mux_idx = 0; |
13338 | spec->int_mic.pin = 0x19; | 13568 | spec->int_mic.pin = 0x19; |
@@ -13352,7 +13582,7 @@ static void alc269_lifebook_init_hook(struct hda_codec *codec) | |||
13352 | alc269_lifebook_mic_autoswitch(codec); | 13582 | alc269_lifebook_mic_autoswitch(codec); |
13353 | } | 13583 | } |
13354 | 13584 | ||
13355 | static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { | 13585 | static struct hda_verb alc269_laptop_dmic_init_verbs[] = { |
13356 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 13586 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
13357 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, | 13587 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, |
13358 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | 13588 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, |
@@ -13363,7 +13593,7 @@ static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { | |||
13363 | {} | 13593 | {} |
13364 | }; | 13594 | }; |
13365 | 13595 | ||
13366 | static struct hda_verb alc269_eeepc_amic_init_verbs[] = { | 13596 | static struct hda_verb alc269_laptop_amic_init_verbs[] = { |
13367 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 13597 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
13368 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, | 13598 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, |
13369 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | 13599 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, |
@@ -13373,6 +13603,28 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = { | |||
13373 | {} | 13603 | {} |
13374 | }; | 13604 | }; |
13375 | 13605 | ||
13606 | static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = { | ||
13607 | {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
13608 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x06}, | ||
13609 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | ||
13610 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))}, | ||
13611 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13612 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
13613 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
13614 | {} | ||
13615 | }; | ||
13616 | |||
13617 | static struct hda_verb alc269vb_laptop_amic_init_verbs[] = { | ||
13618 | {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
13619 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
13620 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | ||
13621 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))}, | ||
13622 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13623 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
13624 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
13625 | {} | ||
13626 | }; | ||
13627 | |||
13376 | /* toggle speaker-output according to the hp-jack state */ | 13628 | /* toggle speaker-output according to the hp-jack state */ |
13377 | static void alc269_speaker_automute(struct hda_codec *codec) | 13629 | static void alc269_speaker_automute(struct hda_codec *codec) |
13378 | { | 13630 | { |
@@ -13390,7 +13642,7 @@ static void alc269_speaker_automute(struct hda_codec *codec) | |||
13390 | } | 13642 | } |
13391 | 13643 | ||
13392 | /* unsolicited event for HP jack sensing */ | 13644 | /* unsolicited event for HP jack sensing */ |
13393 | static void alc269_eeepc_unsol_event(struct hda_codec *codec, | 13645 | static void alc269_laptop_unsol_event(struct hda_codec *codec, |
13394 | unsigned int res) | 13646 | unsigned int res) |
13395 | { | 13647 | { |
13396 | switch (res >> 26) { | 13648 | switch (res >> 26) { |
@@ -13403,9 +13655,11 @@ static void alc269_eeepc_unsol_event(struct hda_codec *codec, | |||
13403 | } | 13655 | } |
13404 | } | 13656 | } |
13405 | 13657 | ||
13406 | static void alc269_eeepc_dmic_setup(struct hda_codec *codec) | 13658 | static void alc269_laptop_dmic_setup(struct hda_codec *codec) |
13407 | { | 13659 | { |
13408 | struct alc_spec *spec = codec->spec; | 13660 | struct alc_spec *spec = codec->spec; |
13661 | spec->autocfg.hp_pins[0] = 0x15; | ||
13662 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13409 | spec->ext_mic.pin = 0x18; | 13663 | spec->ext_mic.pin = 0x18; |
13410 | spec->ext_mic.mux_idx = 0; | 13664 | spec->ext_mic.mux_idx = 0; |
13411 | spec->int_mic.pin = 0x12; | 13665 | spec->int_mic.pin = 0x12; |
@@ -13413,9 +13667,23 @@ static void alc269_eeepc_dmic_setup(struct hda_codec *codec) | |||
13413 | spec->auto_mic = 1; | 13667 | spec->auto_mic = 1; |
13414 | } | 13668 | } |
13415 | 13669 | ||
13416 | static void alc269_eeepc_amic_setup(struct hda_codec *codec) | 13670 | static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) |
13417 | { | 13671 | { |
13418 | struct alc_spec *spec = codec->spec; | 13672 | struct alc_spec *spec = codec->spec; |
13673 | spec->autocfg.hp_pins[0] = 0x15; | ||
13674 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13675 | spec->ext_mic.pin = 0x18; | ||
13676 | spec->ext_mic.mux_idx = 0; | ||
13677 | spec->int_mic.pin = 0x12; | ||
13678 | spec->int_mic.mux_idx = 6; | ||
13679 | spec->auto_mic = 1; | ||
13680 | } | ||
13681 | |||
13682 | static void alc269_laptop_amic_setup(struct hda_codec *codec) | ||
13683 | { | ||
13684 | struct alc_spec *spec = codec->spec; | ||
13685 | spec->autocfg.hp_pins[0] = 0x15; | ||
13686 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13419 | spec->ext_mic.pin = 0x18; | 13687 | spec->ext_mic.pin = 0x18; |
13420 | spec->ext_mic.mux_idx = 0; | 13688 | spec->ext_mic.mux_idx = 0; |
13421 | spec->int_mic.pin = 0x19; | 13689 | spec->int_mic.pin = 0x19; |
@@ -13423,7 +13691,7 @@ static void alc269_eeepc_amic_setup(struct hda_codec *codec) | |||
13423 | spec->auto_mic = 1; | 13691 | spec->auto_mic = 1; |
13424 | } | 13692 | } |
13425 | 13693 | ||
13426 | static void alc269_eeepc_inithook(struct hda_codec *codec) | 13694 | static void alc269_laptop_inithook(struct hda_codec *codec) |
13427 | { | 13695 | { |
13428 | alc269_speaker_automute(codec); | 13696 | alc269_speaker_automute(codec); |
13429 | alc_mic_automute(codec); | 13697 | alc_mic_automute(codec); |
@@ -13436,22 +13704,10 @@ static struct hda_verb alc269_init_verbs[] = { | |||
13436 | /* | 13704 | /* |
13437 | * Unmute ADC0 and set the default input to mic-in | 13705 | * Unmute ADC0 and set the default input to mic-in |
13438 | */ | 13706 | */ |
13439 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 13707 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
13440 | |||
13441 | /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the | ||
13442 | * analog-loopback mixer widget | ||
13443 | * Note: PASD motherboards uses the Line In 2 as the input for | ||
13444 | * front panel mic (mic 2) | ||
13445 | */ | ||
13446 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
13447 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
13448 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
13449 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
13450 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
13451 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
13452 | 13708 | ||
13453 | /* | 13709 | /* |
13454 | * Set up output mixers (0x0c - 0x0e) | 13710 | * Set up output mixers (0x02 - 0x03) |
13455 | */ | 13711 | */ |
13456 | /* set vol=0 to output mixers */ | 13712 | /* set vol=0 to output mixers */ |
13457 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 13713 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
@@ -13476,26 +13732,57 @@ static struct hda_verb alc269_init_verbs[] = { | |||
13476 | 13732 | ||
13477 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 13733 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
13478 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 13734 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
13479 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
13480 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
13481 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
13482 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
13483 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
13484 | 13735 | ||
13485 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | 13736 | /* FIXME: use Mux-type input source selection */ |
13486 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | 13737 | /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */ |
13738 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
13739 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
13487 | 13740 | ||
13488 | /* FIXME: use matrix-type input source selection */ | 13741 | /* set EAPD */ |
13742 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
13743 | { } | ||
13744 | }; | ||
13745 | |||
13746 | static struct hda_verb alc269vb_init_verbs[] = { | ||
13747 | /* | ||
13748 | * Unmute ADC0 and set the default input to mic-in | ||
13749 | */ | ||
13750 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13751 | |||
13752 | /* | ||
13753 | * Set up output mixers (0x02 - 0x03) | ||
13754 | */ | ||
13755 | /* set vol=0 to output mixers */ | ||
13756 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
13757 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
13758 | |||
13759 | /* set up input amps for analog loopback */ | ||
13760 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
13761 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13762 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
13763 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13764 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
13765 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13766 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
13767 | |||
13768 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
13769 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
13770 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
13771 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
13772 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
13773 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13774 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13775 | |||
13776 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
13777 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
13778 | |||
13779 | /* FIXME: use Mux-type input source selection */ | ||
13489 | /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */ | 13780 | /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */ |
13490 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | 13781 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ |
13491 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 13782 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x00}, |
13492 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
13493 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
13494 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
13495 | 13783 | ||
13496 | /* set EAPD */ | 13784 | /* set EAPD */ |
13497 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | 13785 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, |
13498 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
13499 | { } | 13786 | { } |
13500 | }; | 13787 | }; |
13501 | 13788 | ||
@@ -13543,6 +13830,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13543 | struct alc_spec *spec = codec->spec; | 13830 | struct alc_spec *spec = codec->spec; |
13544 | int err; | 13831 | int err; |
13545 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; | 13832 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; |
13833 | hda_nid_t real_capsrc_nids; | ||
13546 | 13834 | ||
13547 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 13835 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
13548 | alc269_ignore); | 13836 | alc269_ignore); |
@@ -13564,11 +13852,20 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13564 | if (spec->kctls.list) | 13852 | if (spec->kctls.list) |
13565 | add_mixer(spec, spec->kctls.list); | 13853 | add_mixer(spec, spec->kctls.list); |
13566 | 13854 | ||
13567 | add_verb(spec, alc269_init_verbs); | 13855 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { |
13856 | add_verb(spec, alc269vb_init_verbs); | ||
13857 | real_capsrc_nids = alc269vb_capsrc_nids[0]; | ||
13858 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); | ||
13859 | } else { | ||
13860 | add_verb(spec, alc269_init_verbs); | ||
13861 | real_capsrc_nids = alc269_capsrc_nids[0]; | ||
13862 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); | ||
13863 | } | ||
13864 | |||
13568 | spec->num_mux_defs = 1; | 13865 | spec->num_mux_defs = 1; |
13569 | spec->input_mux = &spec->private_imux[0]; | 13866 | spec->input_mux = &spec->private_imux[0]; |
13570 | /* set default input source */ | 13867 | /* set default input source */ |
13571 | snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], | 13868 | snd_hda_codec_write_cache(codec, real_capsrc_nids, |
13572 | 0, AC_VERB_SET_CONNECT_SEL, | 13869 | 0, AC_VERB_SET_CONNECT_SEL, |
13573 | spec->input_mux->items[0].index); | 13870 | spec->input_mux->items[0].index); |
13574 | 13871 | ||
@@ -13579,8 +13876,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13579 | if (!spec->cap_mixer && !spec->no_analog) | 13876 | if (!spec->cap_mixer && !spec->no_analog) |
13580 | set_capture_mixer(codec); | 13877 | set_capture_mixer(codec); |
13581 | 13878 | ||
13582 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | ||
13583 | |||
13584 | return 1; | 13879 | return 1; |
13585 | } | 13880 | } |
13586 | 13881 | ||
@@ -13606,8 +13901,8 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
13606 | static const char *alc269_models[ALC269_MODEL_LAST] = { | 13901 | static const char *alc269_models[ALC269_MODEL_LAST] = { |
13607 | [ALC269_BASIC] = "basic", | 13902 | [ALC269_BASIC] = "basic", |
13608 | [ALC269_QUANTA_FL1] = "quanta", | 13903 | [ALC269_QUANTA_FL1] = "quanta", |
13609 | [ALC269_ASUS_AMIC] = "asus-amic", | 13904 | [ALC269_AMIC] = "laptop-amic", |
13610 | [ALC269_ASUS_DMIC] = "asus-dmic", | 13905 | [ALC269_DMIC] = "laptop-dmic", |
13611 | [ALC269_FUJITSU] = "fujitsu", | 13906 | [ALC269_FUJITSU] = "fujitsu", |
13612 | [ALC269_LIFEBOOK] = "lifebook", | 13907 | [ALC269_LIFEBOOK] = "lifebook", |
13613 | [ALC269_AUTO] = "auto", | 13908 | [ALC269_AUTO] = "auto", |
@@ -13616,43 +13911,57 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { | |||
13616 | static struct snd_pci_quirk alc269_cfg_tbl[] = { | 13911 | static struct snd_pci_quirk alc269_cfg_tbl[] = { |
13617 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), | 13912 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), |
13618 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", | 13913 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", |
13619 | ALC269_ASUS_AMIC), | 13914 | ALC269_AMIC), |
13620 | SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_ASUS_AMIC), | 13915 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC), |
13621 | SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80JT", ALC269_ASUS_AMIC), | 13916 | SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC), |
13622 | SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_ASUS_AMIC), | 13917 | SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC), |
13623 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_ASUS_AMIC), | 13918 | SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC), |
13624 | SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_ASUS_AMIC), | 13919 | SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC), |
13625 | SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_ASUS_AMIC), | 13920 | SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC), |
13626 | SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_ASUS_AMIC), | 13921 | SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC), |
13627 | SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_ASUS_AMIC), | 13922 | SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC), |
13628 | SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_ASUS_AMIC), | 13923 | SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC), |
13629 | SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_ASUS_AMIC), | 13924 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_AMIC), |
13630 | SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_ASUS_AMIC), | 13925 | SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC), |
13631 | SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_ASUS_AMIC), | 13926 | SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC), |
13632 | SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_ASUS_AMIC), | 13927 | SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC), |
13633 | SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_ASUS_AMIC), | 13928 | SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC), |
13634 | SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_ASUS_AMIC), | 13929 | SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC), |
13635 | SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_ASUS_AMIC), | 13930 | SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC), |
13636 | SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_ASUS_AMIC), | 13931 | SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC), |
13637 | SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_ASUS_AMIC), | 13932 | SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC), |
13638 | SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_ASUS_AMIC), | 13933 | SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC), |
13639 | SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_ASUS_AMIC), | 13934 | SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC), |
13640 | SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_AMIC), | 13935 | SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC), |
13641 | SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_ASUS_AMIC), | 13936 | SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC), |
13642 | SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_AMIC), | 13937 | SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC), |
13643 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_DMIC), | 13938 | SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC), |
13644 | SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_AMIC), | 13939 | SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC), |
13645 | SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_AMIC), | 13940 | SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC), |
13646 | SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_AMIC), | 13941 | SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC), |
13647 | SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_AMIC), | 13942 | SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC), |
13943 | SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC), | ||
13944 | SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC), | ||
13945 | SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC), | ||
13946 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC), | ||
13947 | SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC), | ||
13948 | SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC), | ||
13949 | SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC), | ||
13950 | SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC), | ||
13648 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", | 13951 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", |
13649 | ALC269_ASUS_DMIC), | 13952 | ALC269_DMIC), |
13650 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", | 13953 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", |
13651 | ALC269_ASUS_DMIC), | 13954 | ALC269_DMIC), |
13652 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_ASUS_DMIC), | 13955 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC), |
13653 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_ASUS_DMIC), | 13956 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC), |
13654 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), | 13957 | SND_PCI_QUIRK(0x104d, 0x9071, "SONY XTB", ALC269_DMIC), |
13655 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), | 13958 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), |
13959 | SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC), | ||
13960 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), | ||
13961 | SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC), | ||
13962 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC), | ||
13963 | SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC), | ||
13964 | SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC), | ||
13656 | {} | 13965 | {} |
13657 | }; | 13966 | }; |
13658 | 13967 | ||
@@ -13680,47 +13989,75 @@ static struct alc_config_preset alc269_presets[] = { | |||
13680 | .setup = alc269_quanta_fl1_setup, | 13989 | .setup = alc269_quanta_fl1_setup, |
13681 | .init_hook = alc269_quanta_fl1_init_hook, | 13990 | .init_hook = alc269_quanta_fl1_init_hook, |
13682 | }, | 13991 | }, |
13683 | [ALC269_ASUS_AMIC] = { | 13992 | [ALC269_AMIC] = { |
13684 | .mixers = { alc269_eeepc_mixer }, | 13993 | .mixers = { alc269_laptop_mixer }, |
13685 | .cap_mixer = alc269_epc_capture_mixer, | 13994 | .cap_mixer = alc269_laptop_analog_capture_mixer, |
13686 | .init_verbs = { alc269_init_verbs, | 13995 | .init_verbs = { alc269_init_verbs, |
13687 | alc269_eeepc_amic_init_verbs }, | 13996 | alc269_laptop_amic_init_verbs }, |
13688 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 13997 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
13689 | .dac_nids = alc269_dac_nids, | 13998 | .dac_nids = alc269_dac_nids, |
13690 | .hp_nid = 0x03, | 13999 | .hp_nid = 0x03, |
13691 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | 14000 | .num_channel_mode = ARRAY_SIZE(alc269_modes), |
13692 | .channel_mode = alc269_modes, | 14001 | .channel_mode = alc269_modes, |
13693 | .unsol_event = alc269_eeepc_unsol_event, | 14002 | .unsol_event = alc269_laptop_unsol_event, |
13694 | .setup = alc269_eeepc_amic_setup, | 14003 | .setup = alc269_laptop_amic_setup, |
13695 | .init_hook = alc269_eeepc_inithook, | 14004 | .init_hook = alc269_laptop_inithook, |
13696 | }, | 14005 | }, |
13697 | [ALC269_ASUS_DMIC] = { | 14006 | [ALC269_DMIC] = { |
13698 | .mixers = { alc269_eeepc_mixer }, | 14007 | .mixers = { alc269_laptop_mixer }, |
13699 | .cap_mixer = alc269_epc_capture_mixer, | 14008 | .cap_mixer = alc269_laptop_digital_capture_mixer, |
13700 | .init_verbs = { alc269_init_verbs, | 14009 | .init_verbs = { alc269_init_verbs, |
13701 | alc269_eeepc_dmic_init_verbs }, | 14010 | alc269_laptop_dmic_init_verbs }, |
14011 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
14012 | .dac_nids = alc269_dac_nids, | ||
14013 | .hp_nid = 0x03, | ||
14014 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
14015 | .channel_mode = alc269_modes, | ||
14016 | .unsol_event = alc269_laptop_unsol_event, | ||
14017 | .setup = alc269_laptop_dmic_setup, | ||
14018 | .init_hook = alc269_laptop_inithook, | ||
14019 | }, | ||
14020 | [ALC269VB_AMIC] = { | ||
14021 | .mixers = { alc269vb_laptop_mixer }, | ||
14022 | .cap_mixer = alc269vb_laptop_analog_capture_mixer, | ||
14023 | .init_verbs = { alc269vb_init_verbs, | ||
14024 | alc269vb_laptop_amic_init_verbs }, | ||
13702 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 14025 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
13703 | .dac_nids = alc269_dac_nids, | 14026 | .dac_nids = alc269_dac_nids, |
13704 | .hp_nid = 0x03, | 14027 | .hp_nid = 0x03, |
13705 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | 14028 | .num_channel_mode = ARRAY_SIZE(alc269_modes), |
13706 | .channel_mode = alc269_modes, | 14029 | .channel_mode = alc269_modes, |
13707 | .unsol_event = alc269_eeepc_unsol_event, | 14030 | .unsol_event = alc269_laptop_unsol_event, |
13708 | .setup = alc269_eeepc_dmic_setup, | 14031 | .setup = alc269_laptop_amic_setup, |
13709 | .init_hook = alc269_eeepc_inithook, | 14032 | .init_hook = alc269_laptop_inithook, |
14033 | }, | ||
14034 | [ALC269VB_DMIC] = { | ||
14035 | .mixers = { alc269vb_laptop_mixer }, | ||
14036 | .cap_mixer = alc269vb_laptop_digital_capture_mixer, | ||
14037 | .init_verbs = { alc269vb_init_verbs, | ||
14038 | alc269vb_laptop_dmic_init_verbs }, | ||
14039 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
14040 | .dac_nids = alc269_dac_nids, | ||
14041 | .hp_nid = 0x03, | ||
14042 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
14043 | .channel_mode = alc269_modes, | ||
14044 | .unsol_event = alc269_laptop_unsol_event, | ||
14045 | .setup = alc269vb_laptop_dmic_setup, | ||
14046 | .init_hook = alc269_laptop_inithook, | ||
13710 | }, | 14047 | }, |
13711 | [ALC269_FUJITSU] = { | 14048 | [ALC269_FUJITSU] = { |
13712 | .mixers = { alc269_fujitsu_mixer }, | 14049 | .mixers = { alc269_fujitsu_mixer }, |
13713 | .cap_mixer = alc269_epc_capture_mixer, | 14050 | .cap_mixer = alc269_laptop_digital_capture_mixer, |
13714 | .init_verbs = { alc269_init_verbs, | 14051 | .init_verbs = { alc269_init_verbs, |
13715 | alc269_eeepc_dmic_init_verbs }, | 14052 | alc269_laptop_dmic_init_verbs }, |
13716 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 14053 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
13717 | .dac_nids = alc269_dac_nids, | 14054 | .dac_nids = alc269_dac_nids, |
13718 | .hp_nid = 0x03, | 14055 | .hp_nid = 0x03, |
13719 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | 14056 | .num_channel_mode = ARRAY_SIZE(alc269_modes), |
13720 | .channel_mode = alc269_modes, | 14057 | .channel_mode = alc269_modes, |
13721 | .unsol_event = alc269_eeepc_unsol_event, | 14058 | .unsol_event = alc269_laptop_unsol_event, |
13722 | .setup = alc269_eeepc_dmic_setup, | 14059 | .setup = alc269_laptop_dmic_setup, |
13723 | .init_hook = alc269_eeepc_inithook, | 14060 | .init_hook = alc269_laptop_inithook, |
13724 | }, | 14061 | }, |
13725 | [ALC269_LIFEBOOK] = { | 14062 | [ALC269_LIFEBOOK] = { |
13726 | .mixers = { alc269_lifebook_mixer }, | 14063 | .mixers = { alc269_lifebook_mixer }, |
@@ -13741,6 +14078,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
13741 | struct alc_spec *spec; | 14078 | struct alc_spec *spec; |
13742 | int board_config; | 14079 | int board_config; |
13743 | int err; | 14080 | int err; |
14081 | int is_alc269vb = 0; | ||
13744 | 14082 | ||
13745 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 14083 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
13746 | if (spec == NULL) | 14084 | if (spec == NULL) |
@@ -13757,6 +14095,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
13757 | alc_free(codec); | 14095 | alc_free(codec); |
13758 | return -ENOMEM; | 14096 | return -ENOMEM; |
13759 | } | 14097 | } |
14098 | is_alc269vb = 1; | ||
13760 | } | 14099 | } |
13761 | 14100 | ||
13762 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, | 14101 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, |
@@ -13792,7 +14131,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
13792 | if (board_config != ALC269_AUTO) | 14131 | if (board_config != ALC269_AUTO) |
13793 | setup_preset(codec, &alc269_presets[board_config]); | 14132 | setup_preset(codec, &alc269_presets[board_config]); |
13794 | 14133 | ||
13795 | if (codec->subsystem_id == 0x17aa3bf8) { | 14134 | if (board_config == ALC269_QUANTA_FL1) { |
13796 | /* Due to a hardware problem on Lenovo Ideadpad, we need to | 14135 | /* Due to a hardware problem on Lenovo Ideadpad, we need to |
13797 | * fix the sample rate of analog I/O to 44.1kHz | 14136 | * fix the sample rate of analog I/O to 44.1kHz |
13798 | */ | 14137 | */ |
@@ -13805,9 +14144,16 @@ static int patch_alc269(struct hda_codec *codec) | |||
13805 | spec->stream_digital_playback = &alc269_pcm_digital_playback; | 14144 | spec->stream_digital_playback = &alc269_pcm_digital_playback; |
13806 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 14145 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
13807 | 14146 | ||
13808 | spec->adc_nids = alc269_adc_nids; | 14147 | if (!is_alc269vb) { |
13809 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 14148 | spec->adc_nids = alc269_adc_nids; |
13810 | spec->capsrc_nids = alc269_capsrc_nids; | 14149 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
14150 | spec->capsrc_nids = alc269_capsrc_nids; | ||
14151 | } else { | ||
14152 | spec->adc_nids = alc269vb_adc_nids; | ||
14153 | spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids); | ||
14154 | spec->capsrc_nids = alc269vb_capsrc_nids; | ||
14155 | } | ||
14156 | |||
13811 | if (!spec->cap_mixer) | 14157 | if (!spec->cap_mixer) |
13812 | set_capture_mixer(codec); | 14158 | set_capture_mixer(codec); |
13813 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 14159 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
@@ -13821,7 +14167,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
13821 | if (!spec->loopback.amplist) | 14167 | if (!spec->loopback.amplist) |
13822 | spec->loopback.amplist = alc269_loopbacks; | 14168 | spec->loopback.amplist = alc269_loopbacks; |
13823 | #endif | 14169 | #endif |
13824 | codec->proc_widget_hook = print_realtek_coef; | ||
13825 | 14170 | ||
13826 | return 0; | 14171 | return 0; |
13827 | } | 14172 | } |
@@ -14684,7 +15029,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
14684 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); | 15029 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); |
14685 | set_capture_mixer(codec); | 15030 | set_capture_mixer(codec); |
14686 | 15031 | ||
14687 | alc_ssid_check(codec, 0x0e, 0x0f, 0x0b); | 15032 | alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0); |
14688 | 15033 | ||
14689 | return 1; | 15034 | return 1; |
14690 | } | 15035 | } |
@@ -14939,13 +15284,16 @@ static int patch_alc861(struct hda_codec *codec) | |||
14939 | spec->vmaster_nid = 0x03; | 15284 | spec->vmaster_nid = 0x03; |
14940 | 15285 | ||
14941 | codec->patch_ops = alc_patch_ops; | 15286 | codec->patch_ops = alc_patch_ops; |
14942 | if (board_config == ALC861_AUTO) | 15287 | if (board_config == ALC861_AUTO) { |
14943 | spec->init_hook = alc861_auto_init; | 15288 | spec->init_hook = alc861_auto_init; |
14944 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 15289 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
15290 | spec->power_hook = alc_power_eapd; | ||
15291 | #endif | ||
15292 | } | ||
15293 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
14945 | if (!spec->loopback.amplist) | 15294 | if (!spec->loopback.amplist) |
14946 | spec->loopback.amplist = alc861_loopbacks; | 15295 | spec->loopback.amplist = alc861_loopbacks; |
14947 | #endif | 15296 | #endif |
14948 | codec->proc_widget_hook = print_realtek_coef; | ||
14949 | 15297 | ||
14950 | return 0; | 15298 | return 0; |
14951 | } | 15299 | } |
@@ -15572,7 +15920,7 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
15572 | static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, | 15920 | static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, |
15573 | const struct auto_pin_cfg *cfg) | 15921 | const struct auto_pin_cfg *cfg) |
15574 | { | 15922 | { |
15575 | return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x22, 0); | 15923 | return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0); |
15576 | } | 15924 | } |
15577 | 15925 | ||
15578 | 15926 | ||
@@ -15808,7 +16156,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
15808 | if (err < 0) | 16156 | if (err < 0) |
15809 | return err; | 16157 | return err; |
15810 | 16158 | ||
15811 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | 16159 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); |
15812 | 16160 | ||
15813 | return 1; | 16161 | return 1; |
15814 | } | 16162 | } |
@@ -15925,7 +16273,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
15925 | if (!spec->loopback.amplist) | 16273 | if (!spec->loopback.amplist) |
15926 | spec->loopback.amplist = alc861vd_loopbacks; | 16274 | spec->loopback.amplist = alc861vd_loopbacks; |
15927 | #endif | 16275 | #endif |
15928 | codec->proc_widget_hook = print_realtek_coef; | ||
15929 | 16276 | ||
15930 | return 0; | 16277 | return 0; |
15931 | } | 16278 | } |
@@ -16392,13 +16739,6 @@ static struct hda_verb alc662_init_verbs[] = { | |||
16392 | /* ADC: mute amp left and right */ | 16739 | /* ADC: mute amp left and right */ |
16393 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 16740 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
16394 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 16741 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
16395 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
16396 | |||
16397 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
16398 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
16399 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
16400 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
16401 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
16402 | 16742 | ||
16403 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 16743 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
16404 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 16744 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -16448,6 +16788,28 @@ static struct hda_verb alc662_init_verbs[] = { | |||
16448 | { } | 16788 | { } |
16449 | }; | 16789 | }; |
16450 | 16790 | ||
16791 | static struct hda_verb alc663_init_verbs[] = { | ||
16792 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16793 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16794 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16795 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16796 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16797 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16798 | { } | ||
16799 | }; | ||
16800 | |||
16801 | static struct hda_verb alc272_init_verbs[] = { | ||
16802 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
16803 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
16804 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16805 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16806 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16807 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16808 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16809 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16810 | { } | ||
16811 | }; | ||
16812 | |||
16451 | static struct hda_verb alc662_sue_init_verbs[] = { | 16813 | static struct hda_verb alc662_sue_init_verbs[] = { |
16452 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, | 16814 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, |
16453 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, | 16815 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, |
@@ -16467,61 +16829,6 @@ static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = { | |||
16467 | {} | 16829 | {} |
16468 | }; | 16830 | }; |
16469 | 16831 | ||
16470 | /* | ||
16471 | * generic initialization of ADC, input mixers and output mixers | ||
16472 | */ | ||
16473 | static struct hda_verb alc662_auto_init_verbs[] = { | ||
16474 | /* | ||
16475 | * Unmute ADC and set the default input to mic-in | ||
16476 | */ | ||
16477 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
16478 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16479 | |||
16480 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
16481 | * mixer widget | ||
16482 | * Note: PASD motherboards uses the Line In 2 as the input for front | ||
16483 | * panel mic (mic 2) | ||
16484 | */ | ||
16485 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
16486 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
16487 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
16488 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
16489 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
16490 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
16491 | |||
16492 | /* | ||
16493 | * Set up output mixers (0x0c - 0x0f) | ||
16494 | */ | ||
16495 | /* set vol=0 to output mixers */ | ||
16496 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
16497 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
16498 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
16499 | |||
16500 | /* set up input amps for analog loopback */ | ||
16501 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
16502 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16503 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16504 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16505 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16506 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16507 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16508 | |||
16509 | |||
16510 | /* FIXME: use matrix-type input source selection */ | ||
16511 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
16512 | /* Input mixer */ | ||
16513 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16514 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16515 | { } | ||
16516 | }; | ||
16517 | |||
16518 | /* additional verbs for ALC663 */ | ||
16519 | static struct hda_verb alc663_auto_init_verbs[] = { | ||
16520 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16521 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16522 | { } | ||
16523 | }; | ||
16524 | |||
16525 | static struct hda_verb alc663_m51va_init_verbs[] = { | 16832 | static struct hda_verb alc663_m51va_init_verbs[] = { |
16526 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 16833 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
16527 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 16834 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
@@ -17272,6 +17579,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
17272 | SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1), | 17579 | SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1), |
17273 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), | 17580 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), |
17274 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), | 17581 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), |
17582 | SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1), | ||
17275 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), | 17583 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), |
17276 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), | 17584 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), |
17277 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), | 17585 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), |
@@ -17307,6 +17615,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
17307 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), | 17615 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), |
17308 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), | 17616 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), |
17309 | SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1), | 17617 | SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1), |
17618 | SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1), | ||
17310 | SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1), | 17619 | SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1), |
17311 | SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1), | 17620 | SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1), |
17312 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), | 17621 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), |
@@ -17334,6 +17643,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
17334 | SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), | 17643 | SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), |
17335 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", | 17644 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", |
17336 | ALC662_3ST_6ch_DIG), | 17645 | ALC662_3ST_6ch_DIG), |
17646 | SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13), | ||
17337 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), | 17647 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), |
17338 | SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA), | 17648 | SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA), |
17339 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | 17649 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), |
@@ -17952,15 +18262,23 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
17952 | spec->num_mux_defs = 1; | 18262 | spec->num_mux_defs = 1; |
17953 | spec->input_mux = &spec->private_imux[0]; | 18263 | spec->input_mux = &spec->private_imux[0]; |
17954 | 18264 | ||
17955 | add_verb(spec, alc662_auto_init_verbs); | 18265 | add_verb(spec, alc662_init_verbs); |
17956 | if (codec->vendor_id == 0x10ec0663) | 18266 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || |
17957 | add_verb(spec, alc663_auto_init_verbs); | 18267 | codec->vendor_id == 0x10ec0665) |
18268 | add_verb(spec, alc663_init_verbs); | ||
18269 | |||
18270 | if (codec->vendor_id == 0x10ec0272) | ||
18271 | add_verb(spec, alc272_init_verbs); | ||
17958 | 18272 | ||
17959 | err = alc_auto_add_mic_boost(codec); | 18273 | err = alc_auto_add_mic_boost(codec); |
17960 | if (err < 0) | 18274 | if (err < 0) |
17961 | return err; | 18275 | return err; |
17962 | 18276 | ||
17963 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | 18277 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || |
18278 | codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670) | ||
18279 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21); | ||
18280 | else | ||
18281 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); | ||
17964 | 18282 | ||
17965 | return 1; | 18283 | return 1; |
17966 | } | 18284 | } |
@@ -18046,11 +18364,20 @@ static int patch_alc662(struct hda_codec *codec) | |||
18046 | 18364 | ||
18047 | if (!spec->cap_mixer) | 18365 | if (!spec->cap_mixer) |
18048 | set_capture_mixer(codec); | 18366 | set_capture_mixer(codec); |
18049 | if (codec->vendor_id == 0x10ec0662) | 18367 | |
18368 | switch (codec->vendor_id) { | ||
18369 | case 0x10ec0662: | ||
18050 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 18370 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
18051 | else | 18371 | break; |
18372 | case 0x10ec0272: | ||
18373 | case 0x10ec0663: | ||
18374 | case 0x10ec0665: | ||
18052 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 18375 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
18053 | 18376 | break; | |
18377 | case 0x10ec0273: | ||
18378 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); | ||
18379 | break; | ||
18380 | } | ||
18054 | spec->vmaster_nid = 0x02; | 18381 | spec->vmaster_nid = 0x02; |
18055 | 18382 | ||
18056 | codec->patch_ops = alc_patch_ops; | 18383 | codec->patch_ops = alc_patch_ops; |
@@ -18060,7 +18387,6 @@ static int patch_alc662(struct hda_codec *codec) | |||
18060 | if (!spec->loopback.amplist) | 18387 | if (!spec->loopback.amplist) |
18061 | spec->loopback.amplist = alc662_loopbacks; | 18388 | spec->loopback.amplist = alc662_loopbacks; |
18062 | #endif | 18389 | #endif |
18063 | codec->proc_widget_hook = print_realtek_coef; | ||
18064 | 18390 | ||
18065 | return 0; | 18391 | return 0; |
18066 | } | 18392 | } |
@@ -18101,6 +18427,8 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
18101 | { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", | 18427 | { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", |
18102 | .patch = patch_alc662 }, | 18428 | .patch = patch_alc662 }, |
18103 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, | 18429 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
18430 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, | ||
18431 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, | ||
18104 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 18432 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
18105 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 18433 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
18106 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, | 18434 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, |
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 799ba2570902..8c416bb18a57 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -568,6 +568,11 @@ static hda_nid_t stac92hd83xxx_pin_nids[10] = { | |||
568 | 0x0f, 0x10, 0x11, 0x1f, 0x20, | 568 | 0x0f, 0x10, 0x11, 0x1f, 0x20, |
569 | }; | 569 | }; |
570 | 570 | ||
571 | static hda_nid_t stac92hd88xxx_pin_nids[10] = { | ||
572 | 0x0a, 0x0b, 0x0c, 0x0d, | ||
573 | 0x0f, 0x11, 0x1f, 0x20, | ||
574 | }; | ||
575 | |||
571 | #define STAC92HD71BXX_NUM_PINS 13 | 576 | #define STAC92HD71BXX_NUM_PINS 13 |
572 | static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { | 577 | static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { |
573 | 0x0a, 0x0b, 0x0c, 0x0d, 0x00, | 578 | 0x0a, 0x0b, 0x0c, 0x0d, 0x00, |
@@ -2688,7 +2693,7 @@ static struct snd_kcontrol_new * | |||
2688 | stac_control_new(struct sigmatel_spec *spec, | 2693 | stac_control_new(struct sigmatel_spec *spec, |
2689 | struct snd_kcontrol_new *ktemp, | 2694 | struct snd_kcontrol_new *ktemp, |
2690 | const char *name, | 2695 | const char *name, |
2691 | hda_nid_t nid) | 2696 | unsigned int subdev) |
2692 | { | 2697 | { |
2693 | struct snd_kcontrol_new *knew; | 2698 | struct snd_kcontrol_new *knew; |
2694 | 2699 | ||
@@ -2704,8 +2709,7 @@ stac_control_new(struct sigmatel_spec *spec, | |||
2704 | spec->kctls.alloced--; | 2709 | spec->kctls.alloced--; |
2705 | return NULL; | 2710 | return NULL; |
2706 | } | 2711 | } |
2707 | if (nid) | 2712 | knew->subdevice = subdev; |
2708 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | ||
2709 | return knew; | 2713 | return knew; |
2710 | } | 2714 | } |
2711 | 2715 | ||
@@ -2715,7 +2719,7 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | |||
2715 | unsigned long val) | 2719 | unsigned long val) |
2716 | { | 2720 | { |
2717 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, | 2721 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, |
2718 | get_amp_nid_(val)); | 2722 | HDA_SUBDEV_AMP_FLAG); |
2719 | if (!knew) | 2723 | if (!knew) |
2720 | return -ENOMEM; | 2724 | return -ENOMEM; |
2721 | knew->index = idx; | 2725 | knew->index = idx; |
@@ -2874,6 +2878,13 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | |||
2874 | 2878 | ||
2875 | conn_len = snd_hda_get_connections(codec, nid, conn, | 2879 | conn_len = snd_hda_get_connections(codec, nid, conn, |
2876 | HDA_MAX_CONNECTIONS); | 2880 | HDA_MAX_CONNECTIONS); |
2881 | /* 92HD88: trace back up the link of nids to find the DAC */ | ||
2882 | while (conn_len == 1 && (get_wcaps_type(get_wcaps(codec, conn[0])) | ||
2883 | != AC_WID_AUD_OUT)) { | ||
2884 | nid = conn[0]; | ||
2885 | conn_len = snd_hda_get_connections(codec, nid, conn, | ||
2886 | HDA_MAX_CONNECTIONS); | ||
2887 | } | ||
2877 | for (j = 0; j < conn_len; j++) { | 2888 | for (j = 0; j < conn_len; j++) { |
2878 | wcaps = get_wcaps(codec, conn[j]); | 2889 | wcaps = get_wcaps(codec, conn[j]); |
2879 | wtype = get_wcaps_type(wcaps); | 2890 | wtype = get_wcaps_type(wcaps); |
@@ -4160,34 +4171,52 @@ static void stac92xx_power_down(struct hda_codec *codec) | |||
4160 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | 4171 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, |
4161 | int enable); | 4172 | int enable); |
4162 | 4173 | ||
4174 | static inline int get_int_hint(struct hda_codec *codec, const char *key, | ||
4175 | int *valp) | ||
4176 | { | ||
4177 | const char *p; | ||
4178 | p = snd_hda_get_hint(codec, key); | ||
4179 | if (p) { | ||
4180 | unsigned long val; | ||
4181 | if (!strict_strtoul(p, 0, &val)) { | ||
4182 | *valp = val; | ||
4183 | return 1; | ||
4184 | } | ||
4185 | } | ||
4186 | return 0; | ||
4187 | } | ||
4188 | |||
4163 | /* override some hints from the hwdep entry */ | 4189 | /* override some hints from the hwdep entry */ |
4164 | static void stac_store_hints(struct hda_codec *codec) | 4190 | static void stac_store_hints(struct hda_codec *codec) |
4165 | { | 4191 | { |
4166 | struct sigmatel_spec *spec = codec->spec; | 4192 | struct sigmatel_spec *spec = codec->spec; |
4167 | const char *p; | ||
4168 | int val; | 4193 | int val; |
4169 | 4194 | ||
4170 | val = snd_hda_get_bool_hint(codec, "hp_detect"); | 4195 | val = snd_hda_get_bool_hint(codec, "hp_detect"); |
4171 | if (val >= 0) | 4196 | if (val >= 0) |
4172 | spec->hp_detect = val; | 4197 | spec->hp_detect = val; |
4173 | p = snd_hda_get_hint(codec, "gpio_mask"); | 4198 | if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { |
4174 | if (p) { | ||
4175 | spec->gpio_mask = simple_strtoul(p, NULL, 0); | ||
4176 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = | 4199 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = |
4177 | spec->gpio_mask; | 4200 | spec->gpio_mask; |
4178 | } | 4201 | } |
4179 | p = snd_hda_get_hint(codec, "gpio_dir"); | 4202 | if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) |
4180 | if (p) | 4203 | spec->gpio_mask &= spec->gpio_mask; |
4181 | spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | 4204 | if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) |
4182 | p = snd_hda_get_hint(codec, "gpio_data"); | 4205 | spec->gpio_dir &= spec->gpio_mask; |
4183 | if (p) | 4206 | if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) |
4184 | spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | 4207 | spec->eapd_mask &= spec->gpio_mask; |
4185 | p = snd_hda_get_hint(codec, "eapd_mask"); | 4208 | if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) |
4186 | if (p) | 4209 | spec->gpio_mute &= spec->gpio_mask; |
4187 | spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
4188 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | 4210 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); |
4189 | if (val >= 0) | 4211 | if (val >= 0) |
4190 | spec->eapd_switch = val; | 4212 | spec->eapd_switch = val; |
4213 | get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); | ||
4214 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | ||
4215 | spec->gpio_mask |= spec->gpio_led; | ||
4216 | spec->gpio_dir |= spec->gpio_led; | ||
4217 | if (spec->gpio_led_polarity) | ||
4218 | spec->gpio_data |= spec->gpio_led; | ||
4219 | } | ||
4191 | } | 4220 | } |
4192 | 4221 | ||
4193 | static int stac92xx_init(struct hda_codec *codec) | 4222 | static int stac92xx_init(struct hda_codec *codec) |
@@ -4334,6 +4363,12 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4334 | if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) | 4363 | if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) |
4335 | stac_issue_unsol_event(codec, nid); | 4364 | stac_issue_unsol_event(codec, nid); |
4336 | } | 4365 | } |
4366 | |||
4367 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4368 | /* sync mute LED */ | ||
4369 | if (spec->gpio_led && codec->patch_ops.check_power_status) | ||
4370 | codec->patch_ops.check_power_status(codec, 0x01); | ||
4371 | #endif | ||
4337 | if (spec->dac_list) | 4372 | if (spec->dac_list) |
4338 | stac92xx_power_down(codec); | 4373 | stac92xx_power_down(codec); |
4339 | return 0; | 4374 | return 0; |
@@ -4372,18 +4407,8 @@ static void stac92xx_free_kctls(struct hda_codec *codec) | |||
4372 | static void stac92xx_shutup(struct hda_codec *codec) | 4407 | static void stac92xx_shutup(struct hda_codec *codec) |
4373 | { | 4408 | { |
4374 | struct sigmatel_spec *spec = codec->spec; | 4409 | struct sigmatel_spec *spec = codec->spec; |
4375 | int i; | ||
4376 | hda_nid_t nid; | ||
4377 | 4410 | ||
4378 | /* reset each pin before powering down DAC/ADC to avoid click noise */ | 4411 | snd_hda_shutup_pins(codec); |
4379 | nid = codec->start_nid; | ||
4380 | for (i = 0; i < codec->num_nodes; i++, nid++) { | ||
4381 | unsigned int wcaps = get_wcaps(codec, nid); | ||
4382 | unsigned int wid_type = get_wcaps_type(wcaps); | ||
4383 | if (wid_type == AC_WID_PIN) | ||
4384 | snd_hda_codec_read(codec, nid, 0, | ||
4385 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
4386 | } | ||
4387 | 4412 | ||
4388 | if (spec->eapd_mask) | 4413 | if (spec->eapd_mask) |
4389 | stac_gpio_set(codec, spec->gpio_mask, | 4414 | stac_gpio_set(codec, spec->gpio_mask, |
@@ -4735,19 +4760,14 @@ static int hp_blike_system(u32 subsystem_id); | |||
4735 | static void set_hp_led_gpio(struct hda_codec *codec) | 4760 | static void set_hp_led_gpio(struct hda_codec *codec) |
4736 | { | 4761 | { |
4737 | struct sigmatel_spec *spec = codec->spec; | 4762 | struct sigmatel_spec *spec = codec->spec; |
4738 | switch (codec->vendor_id) { | 4763 | unsigned int gpio; |
4739 | case 0x111d7608: | 4764 | |
4740 | /* GPIO 0 */ | 4765 | gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); |
4741 | spec->gpio_led = 0x01; | 4766 | gpio &= AC_GPIO_IO_COUNT; |
4742 | break; | 4767 | if (gpio > 3) |
4743 | case 0x111d7600: | 4768 | spec->gpio_led = 0x08; /* GPIO 3 */ |
4744 | case 0x111d7601: | 4769 | else |
4745 | case 0x111d7602: | 4770 | spec->gpio_led = 0x01; /* GPIO 0 */ |
4746 | case 0x111d7603: | ||
4747 | /* GPIO 3 */ | ||
4748 | spec->gpio_led = 0x08; | ||
4749 | break; | ||
4750 | } | ||
4751 | } | 4771 | } |
4752 | 4772 | ||
4753 | /* | 4773 | /* |
@@ -4770,7 +4790,7 @@ static void set_hp_led_gpio(struct hda_codec *codec) | |||
4770 | * Need more information on whether it is true across the entire series. | 4790 | * Need more information on whether it is true across the entire series. |
4771 | * -- kunal | 4791 | * -- kunal |
4772 | */ | 4792 | */ |
4773 | static int find_mute_led_gpio(struct hda_codec *codec) | 4793 | static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) |
4774 | { | 4794 | { |
4775 | struct sigmatel_spec *spec = codec->spec; | 4795 | struct sigmatel_spec *spec = codec->spec; |
4776 | const struct dmi_device *dev = NULL; | 4796 | const struct dmi_device *dev = NULL; |
@@ -4797,7 +4817,7 @@ static int find_mute_led_gpio(struct hda_codec *codec) | |||
4797 | */ | 4817 | */ |
4798 | if (!hp_blike_system(codec->subsystem_id)) { | 4818 | if (!hp_blike_system(codec->subsystem_id)) { |
4799 | set_hp_led_gpio(codec); | 4819 | set_hp_led_gpio(codec); |
4800 | spec->gpio_led_polarity = 1; | 4820 | spec->gpio_led_polarity = default_polarity; |
4801 | return 1; | 4821 | return 1; |
4802 | } | 4822 | } |
4803 | } | 4823 | } |
@@ -4895,6 +4915,11 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4895 | stac_issue_unsol_event(codec, | 4915 | stac_issue_unsol_event(codec, |
4896 | spec->autocfg.line_out_pins[0]); | 4916 | spec->autocfg.line_out_pins[0]); |
4897 | } | 4917 | } |
4918 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4919 | /* sync mute LED */ | ||
4920 | if (spec->gpio_led && codec->patch_ops.check_power_status) | ||
4921 | codec->patch_ops.check_power_status(codec, 0x01); | ||
4922 | #endif | ||
4898 | return 0; | 4923 | return 0; |
4899 | } | 4924 | } |
4900 | 4925 | ||
@@ -4914,43 +4939,29 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, | |||
4914 | hda_nid_t nid) | 4939 | hda_nid_t nid) |
4915 | { | 4940 | { |
4916 | struct sigmatel_spec *spec = codec->spec; | 4941 | struct sigmatel_spec *spec = codec->spec; |
4942 | int i, muted = 1; | ||
4917 | 4943 | ||
4918 | if (nid == 0x10) { | 4944 | for (i = 0; i < spec->multiout.num_dacs; i++) { |
4919 | if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | 4945 | nid = spec->multiout.dac_nids[i]; |
4920 | HDA_AMP_MUTE) | 4946 | if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & |
4921 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | 4947 | HDA_AMP_MUTE)) { |
4922 | else | 4948 | muted = 0; /* something heard */ |
4923 | spec->gpio_data |= spec->gpio_led; /* white */ | 4949 | break; |
4924 | |||
4925 | if (!spec->gpio_led_polarity) { | ||
4926 | /* LED state is inverted on these systems */ | ||
4927 | spec->gpio_data ^= spec->gpio_led; | ||
4928 | } | 4950 | } |
4929 | |||
4930 | stac_gpio_set(codec, spec->gpio_mask, | ||
4931 | spec->gpio_dir, | ||
4932 | spec->gpio_data); | ||
4933 | } | 4951 | } |
4952 | if (muted) | ||
4953 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | ||
4954 | else | ||
4955 | spec->gpio_data |= spec->gpio_led; /* white */ | ||
4934 | 4956 | ||
4935 | return 0; | 4957 | if (!spec->gpio_led_polarity) { |
4936 | } | 4958 | /* LED state is inverted on these systems */ |
4937 | 4959 | spec->gpio_data ^= spec->gpio_led; | |
4938 | static int idt92hd83xxx_hp_check_power_status(struct hda_codec *codec, | 4960 | } |
4939 | hda_nid_t nid) | ||
4940 | { | ||
4941 | struct sigmatel_spec *spec = codec->spec; | ||
4942 | 4961 | ||
4943 | if (nid != 0x13) | ||
4944 | return 0; | ||
4945 | if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE) | ||
4946 | spec->gpio_data |= spec->gpio_led; /* mute LED on */ | ||
4947 | else | ||
4948 | spec->gpio_data &= ~spec->gpio_led; /* mute LED off */ | ||
4949 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | 4962 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); |
4950 | |||
4951 | return 0; | 4963 | return 0; |
4952 | } | 4964 | } |
4953 | |||
4954 | #endif | 4965 | #endif |
4955 | 4966 | ||
4956 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | 4967 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) |
@@ -5272,7 +5283,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
5272 | hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; | 5283 | hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; |
5273 | int err; | 5284 | int err; |
5274 | int num_dacs; | 5285 | int num_dacs; |
5275 | hda_nid_t nid; | ||
5276 | 5286 | ||
5277 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5287 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
5278 | if (spec == NULL) | 5288 | if (spec == NULL) |
@@ -5311,7 +5321,18 @@ again: | |||
5311 | stac92hd83xxx_brd_tbl[spec->board_config]); | 5321 | stac92hd83xxx_brd_tbl[spec->board_config]); |
5312 | 5322 | ||
5313 | switch (codec->vendor_id) { | 5323 | switch (codec->vendor_id) { |
5324 | case 0x111d7666: | ||
5325 | case 0x111d7667: | ||
5326 | case 0x111d7668: | ||
5327 | case 0x111d7669: | ||
5328 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); | ||
5329 | spec->pin_nids = stac92hd88xxx_pin_nids; | ||
5330 | spec->mono_nid = 0; | ||
5331 | spec->digbeep_nid = 0; | ||
5332 | spec->num_pwrs = 0; | ||
5333 | break; | ||
5314 | case 0x111d7604: | 5334 | case 0x111d7604: |
5335 | case 0x111d76d4: | ||
5315 | case 0x111d7605: | 5336 | case 0x111d7605: |
5316 | case 0x111d76d5: | 5337 | case 0x111d76d5: |
5317 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) | 5338 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) |
@@ -5322,8 +5343,10 @@ again: | |||
5322 | 5343 | ||
5323 | codec->patch_ops = stac92xx_patch_ops; | 5344 | codec->patch_ops = stac92xx_patch_ops; |
5324 | 5345 | ||
5325 | if (spec->board_config == STAC_92HD83XXX_HP) | 5346 | if (find_mute_led_gpio(codec, 0)) |
5326 | spec->gpio_led = 0x01; | 5347 | snd_printd("mute LED gpio %d polarity %d\n", |
5348 | spec->gpio_led, | ||
5349 | spec->gpio_led_polarity); | ||
5327 | 5350 | ||
5328 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5351 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5329 | if (spec->gpio_led) { | 5352 | if (spec->gpio_led) { |
@@ -5332,7 +5355,7 @@ again: | |||
5332 | spec->gpio_data |= spec->gpio_led; | 5355 | spec->gpio_data |= spec->gpio_led; |
5333 | /* register check_power_status callback. */ | 5356 | /* register check_power_status callback. */ |
5334 | codec->patch_ops.check_power_status = | 5357 | codec->patch_ops.check_power_status = |
5335 | idt92hd83xxx_hp_check_power_status; | 5358 | stac92xx_hp_check_power_status; |
5336 | } | 5359 | } |
5337 | #endif | 5360 | #endif |
5338 | 5361 | ||
@@ -5352,24 +5375,21 @@ again: | |||
5352 | return err; | 5375 | return err; |
5353 | } | 5376 | } |
5354 | 5377 | ||
5355 | switch (spec->board_config) { | 5378 | /* docking output support */ |
5356 | case STAC_DELL_S14: | 5379 | num_dacs = snd_hda_get_connections(codec, 0xF, |
5357 | nid = 0xf; | ||
5358 | break; | ||
5359 | default: | ||
5360 | nid = 0xe; | ||
5361 | break; | ||
5362 | } | ||
5363 | |||
5364 | num_dacs = snd_hda_get_connections(codec, nid, | ||
5365 | conn, STAC92HD83_DAC_COUNT + 1) - 1; | 5380 | conn, STAC92HD83_DAC_COUNT + 1) - 1; |
5366 | if (num_dacs < 0) | 5381 | /* skip non-DAC connections */ |
5367 | num_dacs = STAC92HD83_DAC_COUNT; | 5382 | while (num_dacs >= 0 && |
5368 | 5383 | (get_wcaps_type(get_wcaps(codec, conn[num_dacs])) | |
5369 | /* set port X to select the last DAC | 5384 | != AC_WID_AUD_OUT)) |
5370 | */ | 5385 | num_dacs--; |
5371 | snd_hda_codec_write_cache(codec, nid, 0, | 5386 | /* set port E and F to select the last DAC */ |
5387 | if (num_dacs >= 0) { | ||
5388 | snd_hda_codec_write_cache(codec, 0xE, 0, | ||
5389 | AC_VERB_SET_CONNECT_SEL, num_dacs); | ||
5390 | snd_hda_codec_write_cache(codec, 0xF, 0, | ||
5372 | AC_VERB_SET_CONNECT_SEL, num_dacs); | 5391 | AC_VERB_SET_CONNECT_SEL, num_dacs); |
5392 | } | ||
5373 | 5393 | ||
5374 | codec->proc_widget_hook = stac92hd_proc_hook; | 5394 | codec->proc_widget_hook = stac92hd_proc_hook; |
5375 | 5395 | ||
@@ -5431,6 +5451,54 @@ static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | |||
5431 | return 0; | 5451 | return 0; |
5432 | } | 5452 | } |
5433 | 5453 | ||
5454 | /* HP dv7 bass switch - GPIO5 */ | ||
5455 | #define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info | ||
5456 | static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, | ||
5457 | struct snd_ctl_elem_value *ucontrol) | ||
5458 | { | ||
5459 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5460 | struct sigmatel_spec *spec = codec->spec; | ||
5461 | ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); | ||
5462 | return 0; | ||
5463 | } | ||
5464 | |||
5465 | static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, | ||
5466 | struct snd_ctl_elem_value *ucontrol) | ||
5467 | { | ||
5468 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5469 | struct sigmatel_spec *spec = codec->spec; | ||
5470 | unsigned int gpio_data; | ||
5471 | |||
5472 | gpio_data = (spec->gpio_data & ~0x20) | | ||
5473 | (ucontrol->value.integer.value[0] ? 0x20 : 0); | ||
5474 | if (gpio_data == spec->gpio_data) | ||
5475 | return 0; | ||
5476 | spec->gpio_data = gpio_data; | ||
5477 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | ||
5478 | return 1; | ||
5479 | } | ||
5480 | |||
5481 | static struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { | ||
5482 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
5483 | .info = stac_hp_bass_gpio_info, | ||
5484 | .get = stac_hp_bass_gpio_get, | ||
5485 | .put = stac_hp_bass_gpio_put, | ||
5486 | }; | ||
5487 | |||
5488 | static int stac_add_hp_bass_switch(struct hda_codec *codec) | ||
5489 | { | ||
5490 | struct sigmatel_spec *spec = codec->spec; | ||
5491 | |||
5492 | if (!stac_control_new(spec, &stac_hp_bass_sw_ctrl, | ||
5493 | "Bass Speaker Playback Switch", 0)) | ||
5494 | return -ENOMEM; | ||
5495 | |||
5496 | spec->gpio_mask |= 0x20; | ||
5497 | spec->gpio_dir |= 0x20; | ||
5498 | spec->gpio_data |= 0x20; | ||
5499 | return 0; | ||
5500 | } | ||
5501 | |||
5434 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 5502 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
5435 | { | 5503 | { |
5436 | struct sigmatel_spec *spec; | 5504 | struct sigmatel_spec *spec; |
@@ -5602,7 +5670,6 @@ again: | |||
5602 | */ | 5670 | */ |
5603 | spec->num_smuxes = 1; | 5671 | spec->num_smuxes = 1; |
5604 | spec->num_dmuxes = 1; | 5672 | spec->num_dmuxes = 1; |
5605 | spec->gpio_led = 0x01; | ||
5606 | /* fallthrough */ | 5673 | /* fallthrough */ |
5607 | case STAC_HP_DV5: | 5674 | case STAC_HP_DV5: |
5608 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); | 5675 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); |
@@ -5617,8 +5684,6 @@ again: | |||
5617 | spec->num_dmics = 1; | 5684 | spec->num_dmics = 1; |
5618 | spec->num_dmuxes = 1; | 5685 | spec->num_dmuxes = 1; |
5619 | spec->num_smuxes = 1; | 5686 | spec->num_smuxes = 1; |
5620 | /* orange/white mute led on GPIO3, orange=0, white=1 */ | ||
5621 | spec->gpio_led = 0x08; | ||
5622 | break; | 5687 | break; |
5623 | } | 5688 | } |
5624 | 5689 | ||
@@ -5640,7 +5705,7 @@ again: | |||
5640 | } | 5705 | } |
5641 | } | 5706 | } |
5642 | 5707 | ||
5643 | if (find_mute_led_gpio(codec)) | 5708 | if (find_mute_led_gpio(codec, 1)) |
5644 | snd_printd("mute LED gpio %d polarity %d\n", | 5709 | snd_printd("mute LED gpio %d polarity %d\n", |
5645 | spec->gpio_led, | 5710 | spec->gpio_led, |
5646 | spec->gpio_led_polarity); | 5711 | spec->gpio_led_polarity); |
@@ -5674,6 +5739,15 @@ again: | |||
5674 | return err; | 5739 | return err; |
5675 | } | 5740 | } |
5676 | 5741 | ||
5742 | /* enable bass on HP dv7 */ | ||
5743 | if (spec->board_config == STAC_HP_DV5) { | ||
5744 | unsigned int cap; | ||
5745 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); | ||
5746 | cap &= AC_GPIO_IO_COUNT; | ||
5747 | if (cap >= 6) | ||
5748 | stac_add_hp_bass_switch(codec); | ||
5749 | } | ||
5750 | |||
5677 | codec->proc_widget_hook = stac92hd7x_proc_hook; | 5751 | codec->proc_widget_hook = stac92hd7x_proc_hook; |
5678 | 5752 | ||
5679 | return 0; | 5753 | return 0; |
@@ -6172,8 +6246,13 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
6172 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, | 6246 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, |
6173 | { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, | 6247 | { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, |
6174 | { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, | 6248 | { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, |
6249 | { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, | ||
6175 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, | 6250 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, |
6176 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, | 6251 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, |
6252 | { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, | ||
6253 | { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, | ||
6254 | { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, | ||
6255 | { .id = 0x111d7669, .name = "92HD88B4", .patch = patch_stac92hd83xxx}, | ||
6177 | { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, | 6256 | { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, |
6178 | { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, | 6257 | { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, |
6179 | { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, | 6258 | { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index b70e26ad263f..9ddc37300f6b 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,27 @@ 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_nid(codec, kctl, i, spec->mux_nids[i]); | ||
1911 | if (err < 0) | ||
1912 | return err; | ||
1913 | } | ||
1914 | |||
1915 | /* other nid->control mapping */ | ||
1916 | for (i = 0; i < spec->num_mixers; i++) { | ||
1917 | for (knew = spec->mixers[i]; knew->name; knew++) { | ||
1918 | if (knew->iface != NID_MAPPING) | ||
1919 | continue; | ||
1920 | kctl = snd_hda_find_mixer_ctl(codec, knew->name); | ||
1921 | if (kctl == NULL) | ||
1922 | continue; | ||
1923 | err = snd_hda_add_nid(codec, kctl, 0, | ||
1924 | knew->subdevice); | ||
1925 | } | ||
1926 | } | ||
1927 | |||
1848 | /* init power states */ | 1928 | /* init power states */ |
1849 | set_jack_power_state(codec); | 1929 | set_jack_power_state(codec); |
1850 | analog_low_current_mode(codec, 1); | 1930 | analog_low_current_mode(codec, 1); |
@@ -2481,9 +2561,9 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
2481 | spec->input_mux = &spec->private_imux[0]; | 2561 | spec->input_mux = &spec->private_imux[0]; |
2482 | 2562 | ||
2483 | if (spec->hp_mux) | 2563 | if (spec->hp_mux) |
2484 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 2564 | via_hp_build(spec); |
2485 | 2565 | ||
2486 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 2566 | via_smart51_build(spec); |
2487 | return 1; | 2567 | return 1; |
2488 | } | 2568 | } |
2489 | 2569 | ||
@@ -2554,12 +2634,10 @@ static int patch_vt1708(struct hda_codec *codec) | |||
2554 | int err; | 2634 | int err; |
2555 | 2635 | ||
2556 | /* create a codec specific record */ | 2636 | /* create a codec specific record */ |
2557 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2637 | spec = via_new_spec(codec); |
2558 | if (spec == NULL) | 2638 | if (spec == NULL) |
2559 | return -ENOMEM; | 2639 | return -ENOMEM; |
2560 | 2640 | ||
2561 | codec->spec = spec; | ||
2562 | |||
2563 | /* automatic parse from the BIOS config */ | 2641 | /* automatic parse from the BIOS config */ |
2564 | err = vt1708_parse_auto_config(codec); | 2642 | err = vt1708_parse_auto_config(codec); |
2565 | if (err < 0) { | 2643 | if (err < 0) { |
@@ -2597,7 +2675,6 @@ static int patch_vt1708(struct hda_codec *codec) | |||
2597 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2675 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2598 | spec->loopback.amplist = vt1708_loopbacks; | 2676 | spec->loopback.amplist = vt1708_loopbacks; |
2599 | #endif | 2677 | #endif |
2600 | spec->codec = codec; | ||
2601 | INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state); | 2678 | INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state); |
2602 | return 0; | 2679 | return 0; |
2603 | } | 2680 | } |
@@ -3010,9 +3087,9 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
3010 | spec->input_mux = &spec->private_imux[0]; | 3087 | spec->input_mux = &spec->private_imux[0]; |
3011 | 3088 | ||
3012 | if (spec->hp_mux) | 3089 | if (spec->hp_mux) |
3013 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 3090 | via_hp_build(spec); |
3014 | 3091 | ||
3015 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 3092 | via_smart51_build(spec); |
3016 | return 1; | 3093 | return 1; |
3017 | } | 3094 | } |
3018 | 3095 | ||
@@ -3032,12 +3109,10 @@ static int patch_vt1709_10ch(struct hda_codec *codec) | |||
3032 | int err; | 3109 | int err; |
3033 | 3110 | ||
3034 | /* create a codec specific record */ | 3111 | /* create a codec specific record */ |
3035 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3112 | spec = via_new_spec(codec); |
3036 | if (spec == NULL) | 3113 | if (spec == NULL) |
3037 | return -ENOMEM; | 3114 | return -ENOMEM; |
3038 | 3115 | ||
3039 | codec->spec = spec; | ||
3040 | |||
3041 | err = vt1709_parse_auto_config(codec); | 3116 | err = vt1709_parse_auto_config(codec); |
3042 | if (err < 0) { | 3117 | if (err < 0) { |
3043 | via_free(codec); | 3118 | via_free(codec); |
@@ -3126,12 +3201,10 @@ static int patch_vt1709_6ch(struct hda_codec *codec) | |||
3126 | int err; | 3201 | int err; |
3127 | 3202 | ||
3128 | /* create a codec specific record */ | 3203 | /* create a codec specific record */ |
3129 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3204 | spec = via_new_spec(codec); |
3130 | if (spec == NULL) | 3205 | if (spec == NULL) |
3131 | return -ENOMEM; | 3206 | return -ENOMEM; |
3132 | 3207 | ||
3133 | codec->spec = spec; | ||
3134 | |||
3135 | err = vt1709_parse_auto_config(codec); | 3208 | err = vt1709_parse_auto_config(codec); |
3136 | if (err < 0) { | 3209 | if (err < 0) { |
3137 | via_free(codec); | 3210 | via_free(codec); |
@@ -3581,9 +3654,9 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
3581 | spec->input_mux = &spec->private_imux[0]; | 3654 | spec->input_mux = &spec->private_imux[0]; |
3582 | 3655 | ||
3583 | if (spec->hp_mux) | 3656 | if (spec->hp_mux) |
3584 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 3657 | via_hp_build(spec); |
3585 | 3658 | ||
3586 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 3659 | via_smart51_build(spec); |
3587 | return 1; | 3660 | return 1; |
3588 | } | 3661 | } |
3589 | 3662 | ||
@@ -3605,12 +3678,10 @@ static int patch_vt1708B_8ch(struct hda_codec *codec) | |||
3605 | if (get_codec_type(codec) == VT1708BCE) | 3678 | if (get_codec_type(codec) == VT1708BCE) |
3606 | return patch_vt1708S(codec); | 3679 | return patch_vt1708S(codec); |
3607 | /* create a codec specific record */ | 3680 | /* create a codec specific record */ |
3608 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3681 | spec = via_new_spec(codec); |
3609 | if (spec == NULL) | 3682 | if (spec == NULL) |
3610 | return -ENOMEM; | 3683 | return -ENOMEM; |
3611 | 3684 | ||
3612 | codec->spec = spec; | ||
3613 | |||
3614 | /* automatic parse from the BIOS config */ | 3685 | /* automatic parse from the BIOS config */ |
3615 | err = vt1708B_parse_auto_config(codec); | 3686 | err = vt1708B_parse_auto_config(codec); |
3616 | if (err < 0) { | 3687 | if (err < 0) { |
@@ -3657,12 +3728,10 @@ static int patch_vt1708B_4ch(struct hda_codec *codec) | |||
3657 | int err; | 3728 | int err; |
3658 | 3729 | ||
3659 | /* create a codec specific record */ | 3730 | /* create a codec specific record */ |
3660 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 3731 | spec = via_new_spec(codec); |
3661 | if (spec == NULL) | 3732 | if (spec == NULL) |
3662 | return -ENOMEM; | 3733 | return -ENOMEM; |
3663 | 3734 | ||
3664 | codec->spec = spec; | ||
3665 | |||
3666 | /* automatic parse from the BIOS config */ | 3735 | /* automatic parse from the BIOS config */ |
3667 | err = vt1708B_parse_auto_config(codec); | 3736 | err = vt1708B_parse_auto_config(codec); |
3668 | if (err < 0) { | 3737 | if (err < 0) { |
@@ -4071,9 +4140,9 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
4071 | spec->input_mux = &spec->private_imux[0]; | 4140 | spec->input_mux = &spec->private_imux[0]; |
4072 | 4141 | ||
4073 | if (spec->hp_mux) | 4142 | if (spec->hp_mux) |
4074 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 4143 | via_hp_build(spec); |
4075 | 4144 | ||
4076 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 4145 | via_smart51_build(spec); |
4077 | return 1; | 4146 | return 1; |
4078 | } | 4147 | } |
4079 | 4148 | ||
@@ -4103,12 +4172,10 @@ static int patch_vt1708S(struct hda_codec *codec) | |||
4103 | int err; | 4172 | int err; |
4104 | 4173 | ||
4105 | /* create a codec specific record */ | 4174 | /* create a codec specific record */ |
4106 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4175 | spec = via_new_spec(codec); |
4107 | if (spec == NULL) | 4176 | if (spec == NULL) |
4108 | return -ENOMEM; | 4177 | return -ENOMEM; |
4109 | 4178 | ||
4110 | codec->spec = spec; | ||
4111 | |||
4112 | /* automatic parse from the BIOS config */ | 4179 | /* automatic parse from the BIOS config */ |
4113 | err = vt1708S_parse_auto_config(codec); | 4180 | err = vt1708S_parse_auto_config(codec); |
4114 | if (err < 0) { | 4181 | if (err < 0) { |
@@ -4443,7 +4510,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
4443 | spec->input_mux = &spec->private_imux[0]; | 4510 | spec->input_mux = &spec->private_imux[0]; |
4444 | 4511 | ||
4445 | if (spec->hp_mux) | 4512 | if (spec->hp_mux) |
4446 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 4513 | via_hp_build(spec); |
4447 | 4514 | ||
4448 | return 1; | 4515 | return 1; |
4449 | } | 4516 | } |
@@ -4464,12 +4531,10 @@ static int patch_vt1702(struct hda_codec *codec) | |||
4464 | int err; | 4531 | int err; |
4465 | 4532 | ||
4466 | /* create a codec specific record */ | 4533 | /* create a codec specific record */ |
4467 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4534 | spec = via_new_spec(codec); |
4468 | if (spec == NULL) | 4535 | if (spec == NULL) |
4469 | return -ENOMEM; | 4536 | return -ENOMEM; |
4470 | 4537 | ||
4471 | codec->spec = spec; | ||
4472 | |||
4473 | /* automatic parse from the BIOS config */ | 4538 | /* automatic parse from the BIOS config */ |
4474 | err = vt1702_parse_auto_config(codec); | 4539 | err = vt1702_parse_auto_config(codec); |
4475 | if (err < 0) { | 4540 | if (err < 0) { |
@@ -4865,9 +4930,9 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) | |||
4865 | spec->input_mux = &spec->private_imux[0]; | 4930 | spec->input_mux = &spec->private_imux[0]; |
4866 | 4931 | ||
4867 | if (spec->hp_mux) | 4932 | if (spec->hp_mux) |
4868 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 4933 | via_hp_build(spec); |
4869 | 4934 | ||
4870 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 4935 | via_smart51_build(spec); |
4871 | 4936 | ||
4872 | return 1; | 4937 | return 1; |
4873 | } | 4938 | } |
@@ -4888,12 +4953,10 @@ static int patch_vt1718S(struct hda_codec *codec) | |||
4888 | int err; | 4953 | int err; |
4889 | 4954 | ||
4890 | /* create a codec specific record */ | 4955 | /* create a codec specific record */ |
4891 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4956 | spec = via_new_spec(codec); |
4892 | if (spec == NULL) | 4957 | if (spec == NULL) |
4893 | return -ENOMEM; | 4958 | return -ENOMEM; |
4894 | 4959 | ||
4895 | codec->spec = spec; | ||
4896 | |||
4897 | /* automatic parse from the BIOS config */ | 4960 | /* automatic parse from the BIOS config */ |
4898 | err = vt1718S_parse_auto_config(codec); | 4961 | err = vt1718S_parse_auto_config(codec); |
4899 | if (err < 0) { | 4962 | if (err < 0) { |
@@ -5014,6 +5077,7 @@ static struct snd_kcontrol_new vt1716s_dmic_mixer[] = { | |||
5014 | { | 5077 | { |
5015 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 5078 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
5016 | .name = "Digital Mic Capture Switch", | 5079 | .name = "Digital Mic Capture Switch", |
5080 | .subdevice = HDA_SUBDEV_NID_FLAG | 0x26, | ||
5017 | .count = 1, | 5081 | .count = 1, |
5018 | .info = vt1716s_dmic_info, | 5082 | .info = vt1716s_dmic_info, |
5019 | .get = vt1716s_dmic_get, | 5083 | .get = vt1716s_dmic_get, |
@@ -5361,9 +5425,9 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) | |||
5361 | spec->input_mux = &spec->private_imux[0]; | 5425 | spec->input_mux = &spec->private_imux[0]; |
5362 | 5426 | ||
5363 | if (spec->hp_mux) | 5427 | if (spec->hp_mux) |
5364 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 5428 | via_hp_build(spec); |
5365 | 5429 | ||
5366 | spec->mixers[spec->num_mixers++] = via_smart51_mixer; | 5430 | via_smart51_build(spec); |
5367 | 5431 | ||
5368 | return 1; | 5432 | return 1; |
5369 | } | 5433 | } |
@@ -5384,12 +5448,10 @@ static int patch_vt1716S(struct hda_codec *codec) | |||
5384 | int err; | 5448 | int err; |
5385 | 5449 | ||
5386 | /* create a codec specific record */ | 5450 | /* create a codec specific record */ |
5387 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5451 | spec = via_new_spec(codec); |
5388 | if (spec == NULL) | 5452 | if (spec == NULL) |
5389 | return -ENOMEM; | 5453 | return -ENOMEM; |
5390 | 5454 | ||
5391 | codec->spec = spec; | ||
5392 | |||
5393 | /* automatic parse from the BIOS config */ | 5455 | /* automatic parse from the BIOS config */ |
5394 | err = vt1716S_parse_auto_config(codec); | 5456 | err = vt1716S_parse_auto_config(codec); |
5395 | if (err < 0) { | 5457 | if (err < 0) { |
@@ -5719,7 +5781,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) | |||
5719 | spec->input_mux = &spec->private_imux[0]; | 5781 | spec->input_mux = &spec->private_imux[0]; |
5720 | 5782 | ||
5721 | if (spec->hp_mux) | 5783 | if (spec->hp_mux) |
5722 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 5784 | via_hp_build(spec); |
5723 | 5785 | ||
5724 | return 1; | 5786 | return 1; |
5725 | } | 5787 | } |
@@ -5741,12 +5803,10 @@ static int patch_vt2002P(struct hda_codec *codec) | |||
5741 | int err; | 5803 | int err; |
5742 | 5804 | ||
5743 | /* create a codec specific record */ | 5805 | /* create a codec specific record */ |
5744 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5806 | spec = via_new_spec(codec); |
5745 | if (spec == NULL) | 5807 | if (spec == NULL) |
5746 | return -ENOMEM; | 5808 | return -ENOMEM; |
5747 | 5809 | ||
5748 | codec->spec = spec; | ||
5749 | |||
5750 | /* automatic parse from the BIOS config */ | 5810 | /* automatic parse from the BIOS config */ |
5751 | err = vt2002P_parse_auto_config(codec); | 5811 | err = vt2002P_parse_auto_config(codec); |
5752 | if (err < 0) { | 5812 | if (err < 0) { |
@@ -6070,7 +6130,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) | |||
6070 | spec->input_mux = &spec->private_imux[0]; | 6130 | spec->input_mux = &spec->private_imux[0]; |
6071 | 6131 | ||
6072 | if (spec->hp_mux) | 6132 | if (spec->hp_mux) |
6073 | spec->mixers[spec->num_mixers++] = via_hp_mixer; | 6133 | via_hp_build(spec); |
6074 | 6134 | ||
6075 | return 1; | 6135 | return 1; |
6076 | } | 6136 | } |
@@ -6092,12 +6152,10 @@ static int patch_vt1812(struct hda_codec *codec) | |||
6092 | int err; | 6152 | int err; |
6093 | 6153 | ||
6094 | /* create a codec specific record */ | 6154 | /* create a codec specific record */ |
6095 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 6155 | spec = via_new_spec(codec); |
6096 | if (spec == NULL) | 6156 | if (spec == NULL) |
6097 | return -ENOMEM; | 6157 | return -ENOMEM; |
6098 | 6158 | ||
6099 | codec->spec = spec; | ||
6100 | |||
6101 | /* automatic parse from the BIOS config */ | 6159 | /* automatic parse from the BIOS config */ |
6102 | err = vt1812_parse_auto_config(codec); | 6160 | err = vt1812_parse_auto_config(codec); |
6103 | if (err < 0) { | 6161 | if (err < 0) { |