diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 81 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 5 | ||||
-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 | 60 | ||||
-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 | 117 | ||||
-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_realtek.c | 1006 | ||||
-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 |
15 files changed, 1810 insertions, 730 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f98b47cd6cfb..76d3c4c049db 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); |
@@ -985,7 +1008,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
985 | mutex_init(&codec->control_mutex); | 1008 | mutex_init(&codec->control_mutex); |
986 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 1009 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
987 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 1010 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
988 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60); | 1011 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); |
1012 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); | ||
989 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | 1013 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); |
990 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | 1014 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); |
991 | if (codec->bus->modelname) { | 1015 | if (codec->bus->modelname) { |
@@ -1708,7 +1732,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1708 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | 1732 | EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); |
1709 | 1733 | ||
1710 | /** | 1734 | /** |
1711 | * snd_hda_ctl-add - Add a control element and assign to the codec | 1735 | * snd_hda_ctl_add - Add a control element and assign to the codec |
1712 | * @codec: HD-audio codec | 1736 | * @codec: HD-audio codec |
1713 | * @nid: corresponding NID (optional) | 1737 | * @nid: corresponding NID (optional) |
1714 | * @kctl: the control element to assign | 1738 | * @kctl: the control element to assign |
@@ -1723,19 +1747,25 @@ EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); | |||
1723 | * | 1747 | * |
1724 | * snd_hda_ctl_add() checks the control subdev id field whether | 1748 | * 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 | 1749 | * #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. | 1750 | * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit |
1751 | * specifies if kctl->private_value is a HDA amplifier value. | ||
1727 | */ | 1752 | */ |
1728 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | 1753 | int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, |
1729 | struct snd_kcontrol *kctl) | 1754 | struct snd_kcontrol *kctl) |
1730 | { | 1755 | { |
1731 | int err; | 1756 | int err; |
1757 | unsigned short flags = 0; | ||
1732 | struct hda_nid_item *item; | 1758 | struct hda_nid_item *item; |
1733 | 1759 | ||
1734 | if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) { | 1760 | if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) { |
1761 | flags |= HDA_NID_ITEM_AMP; | ||
1735 | if (nid == 0) | 1762 | if (nid == 0) |
1736 | nid = kctl->id.subdevice & 0xffff; | 1763 | nid = get_amp_nid_(kctl->private_value); |
1737 | kctl->id.subdevice = 0; | ||
1738 | } | 1764 | } |
1765 | if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0) | ||
1766 | nid = kctl->id.subdevice & 0xffff; | ||
1767 | if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG)) | ||
1768 | kctl->id.subdevice = 0; | ||
1739 | err = snd_ctl_add(codec->bus->card, kctl); | 1769 | err = snd_ctl_add(codec->bus->card, kctl); |
1740 | if (err < 0) | 1770 | if (err < 0) |
1741 | return err; | 1771 | return err; |
@@ -1744,11 +1774,41 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, | |||
1744 | return -ENOMEM; | 1774 | return -ENOMEM; |
1745 | item->kctl = kctl; | 1775 | item->kctl = kctl; |
1746 | item->nid = nid; | 1776 | item->nid = nid; |
1777 | item->flags = flags; | ||
1747 | return 0; | 1778 | return 0; |
1748 | } | 1779 | } |
1749 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); | 1780 | EXPORT_SYMBOL_HDA(snd_hda_ctl_add); |
1750 | 1781 | ||
1751 | /** | 1782 | /** |
1783 | * snd_hda_add_nid - Assign a NID to a control element | ||
1784 | * @codec: HD-audio codec | ||
1785 | * @nid: corresponding NID (optional) | ||
1786 | * @kctl: the control element to assign | ||
1787 | * @index: index to kctl | ||
1788 | * | ||
1789 | * Add the given control element to an array inside the codec instance. | ||
1790 | * This function is used when #snd_hda_ctl_add cannot be used for 1:1 | ||
1791 | * NID:KCTL mapping - for example "Capture Source" selector. | ||
1792 | */ | ||
1793 | int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
1794 | unsigned int index, hda_nid_t nid) | ||
1795 | { | ||
1796 | struct hda_nid_item *item; | ||
1797 | |||
1798 | if (nid > 0) { | ||
1799 | item = snd_array_new(&codec->nids); | ||
1800 | if (!item) | ||
1801 | return -ENOMEM; | ||
1802 | item->kctl = kctl; | ||
1803 | item->index = index; | ||
1804 | item->nid = nid; | ||
1805 | return 0; | ||
1806 | } | ||
1807 | return -EINVAL; | ||
1808 | } | ||
1809 | EXPORT_SYMBOL_HDA(snd_hda_add_nid); | ||
1810 | |||
1811 | /** | ||
1752 | * snd_hda_ctls_clear - Clear all controls assigned to the given codec | 1812 | * snd_hda_ctls_clear - Clear all controls assigned to the given codec |
1753 | * @codec: HD-audio codec | 1813 | * @codec: HD-audio codec |
1754 | */ | 1814 | */ |
@@ -1759,6 +1819,7 @@ void snd_hda_ctls_clear(struct hda_codec *codec) | |||
1759 | for (i = 0; i < codec->mixers.used; i++) | 1819 | for (i = 0; i < codec->mixers.used; i++) |
1760 | snd_ctl_remove(codec->bus->card, items[i].kctl); | 1820 | snd_ctl_remove(codec->bus->card, items[i].kctl); |
1761 | snd_array_free(&codec->mixers); | 1821 | snd_array_free(&codec->mixers); |
1822 | snd_array_free(&codec->nids); | ||
1762 | } | 1823 | } |
1763 | 1824 | ||
1764 | /* pseudo device locking | 1825 | /* pseudo device locking |
@@ -2706,7 +2767,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, | 2767 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, |
2707 | power_state); | 2768 | power_state); |
2708 | /* partial workaround for "azx_get_response timeout" */ | 2769 | /* partial workaround for "azx_get_response timeout" */ |
2709 | if (power_state == AC_PWRST_D0) | 2770 | if (power_state == AC_PWRST_D0 && |
2771 | (codec->vendor_id & 0xffff0000) == 0x14f10000) | ||
2710 | msleep(10); | 2772 | msleep(10); |
2711 | 2773 | ||
2712 | nid = codec->start_nid; | 2774 | nid = codec->start_nid; |
@@ -2740,7 +2802,6 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
2740 | if (power_state == AC_PWRST_D0) { | 2802 | if (power_state == AC_PWRST_D0) { |
2741 | unsigned long end_time; | 2803 | unsigned long end_time; |
2742 | int state; | 2804 | int state; |
2743 | msleep(10); | ||
2744 | /* wait until the codec reachs to D0 */ | 2805 | /* wait until the codec reachs to D0 */ |
2745 | end_time = jiffies + msecs_to_jiffies(500); | 2806 | end_time = jiffies + msecs_to_jiffies(500); |
2746 | do { | 2807 | do { |
@@ -3214,6 +3275,8 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { | |||
3214 | 3275 | ||
3215 | /* | 3276 | /* |
3216 | * get the empty PCM device number to assign | 3277 | * get the empty PCM device number to assign |
3278 | * | ||
3279 | * note the max device number is limited by HDA_MAX_PCMS, currently 10 | ||
3217 | */ | 3280 | */ |
3218 | static int get_empty_pcm_device(struct hda_bus *bus, int type) | 3281 | static int get_empty_pcm_device(struct hda_bus *bus, int type) |
3219 | { | 3282 | { |
@@ -3478,6 +3541,8 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
3478 | 3541 | ||
3479 | for (; knew->name; knew++) { | 3542 | for (; knew->name; knew++) { |
3480 | struct snd_kcontrol *kctl; | 3543 | struct snd_kcontrol *kctl; |
3544 | if (knew->iface == -1) /* skip this codec private value */ | ||
3545 | continue; | ||
3481 | kctl = snd_ctl_new1(knew, codec); | 3546 | kctl = snd_ctl_new1(knew, codec); |
3482 | if (!kctl) | 3547 | if (!kctl) |
3483 | return -ENOMEM; | 3548 | return -ENOMEM; |
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_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..d5c93ad852ee 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 |
@@ -408,7 +407,7 @@ struct azx { | |||
408 | struct azx_dev *azx_dev; | 407 | struct azx_dev *azx_dev; |
409 | 408 | ||
410 | /* PCM */ | 409 | /* PCM */ |
411 | struct snd_pcm *pcm[AZX_MAX_PCMS]; | 410 | struct snd_pcm *pcm[HDA_MAX_PCMS]; |
412 | 411 | ||
413 | /* HD codec */ | 412 | /* HD codec */ |
414 | unsigned short codec_mask; | 413 | unsigned short codec_mask; |
@@ -449,6 +448,7 @@ struct azx { | |||
449 | /* driver types */ | 448 | /* driver types */ |
450 | enum { | 449 | enum { |
451 | AZX_DRIVER_ICH, | 450 | AZX_DRIVER_ICH, |
451 | AZX_DRIVER_PCH, | ||
452 | AZX_DRIVER_SCH, | 452 | AZX_DRIVER_SCH, |
453 | AZX_DRIVER_ATI, | 453 | AZX_DRIVER_ATI, |
454 | AZX_DRIVER_ATIHDMI, | 454 | AZX_DRIVER_ATIHDMI, |
@@ -463,6 +463,7 @@ enum { | |||
463 | 463 | ||
464 | static char *driver_short_names[] __devinitdata = { | 464 | static char *driver_short_names[] __devinitdata = { |
465 | [AZX_DRIVER_ICH] = "HDA Intel", | 465 | [AZX_DRIVER_ICH] = "HDA Intel", |
466 | [AZX_DRIVER_PCH] = "HDA Intel PCH", | ||
466 | [AZX_DRIVER_SCH] = "HDA Intel MID", | 467 | [AZX_DRIVER_SCH] = "HDA Intel MID", |
467 | [AZX_DRIVER_ATI] = "HDA ATI SB", | 468 | [AZX_DRIVER_ATI] = "HDA ATI SB", |
468 | [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", | 469 | [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", |
@@ -968,8 +969,8 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) | |||
968 | azx_dev->insufficient = 1; | 969 | azx_dev->insufficient = 1; |
969 | 970 | ||
970 | /* enable SIE */ | 971 | /* enable SIE */ |
971 | azx_writeb(chip, INTCTL, | 972 | azx_writel(chip, INTCTL, |
972 | azx_readb(chip, INTCTL) | (1 << azx_dev->index)); | 973 | azx_readl(chip, INTCTL) | (1 << azx_dev->index)); |
973 | /* set DMA start and interrupt mask */ | 974 | /* set DMA start and interrupt mask */ |
974 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | | 975 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | |
975 | SD_CTL_DMA_START | SD_INT_MASK); | 976 | SD_CTL_DMA_START | SD_INT_MASK); |
@@ -988,8 +989,8 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
988 | { | 989 | { |
989 | azx_stream_clear(chip, azx_dev); | 990 | azx_stream_clear(chip, azx_dev); |
990 | /* disable SIE */ | 991 | /* disable SIE */ |
991 | azx_writeb(chip, INTCTL, | 992 | azx_writel(chip, INTCTL, |
992 | azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); | 993 | azx_readl(chip, INTCTL) & ~(1 << azx_dev->index)); |
993 | } | 994 | } |
994 | 995 | ||
995 | 996 | ||
@@ -1065,6 +1066,7 @@ static void azx_init_pci(struct azx *chip) | |||
1065 | 0x01, NVIDIA_HDA_ENABLE_COHBIT); | 1066 | 0x01, NVIDIA_HDA_ENABLE_COHBIT); |
1066 | break; | 1067 | break; |
1067 | case AZX_DRIVER_SCH: | 1068 | case AZX_DRIVER_SCH: |
1069 | case AZX_DRIVER_PCH: | ||
1068 | pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); | 1070 | pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); |
1069 | if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) { | 1071 | if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) { |
1070 | pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, | 1072 | pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, |
@@ -1350,7 +1352,7 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1350 | if (chip->initialized) { | 1352 | if (chip->initialized) { |
1351 | int i; | 1353 | int i; |
1352 | 1354 | ||
1353 | for (i = 0; i < AZX_MAX_PCMS; i++) | 1355 | for (i = 0; i < HDA_MAX_PCMS; i++) |
1354 | snd_pcm_suspend_all(chip->pcm[i]); | 1356 | snd_pcm_suspend_all(chip->pcm[i]); |
1355 | snd_hda_suspend(chip->bus); | 1357 | snd_hda_suspend(chip->bus); |
1356 | snd_hda_resume(chip->bus); | 1358 | snd_hda_resume(chip->bus); |
@@ -1412,7 +1414,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1412 | chip->codec_mask &= ~(1 << c); | 1414 | chip->codec_mask &= ~(1 << c); |
1413 | /* More badly, accessing to a non-existing | 1415 | /* More badly, accessing to a non-existing |
1414 | * codec often screws up the controller chip, | 1416 | * codec often screws up the controller chip, |
1415 | * and distrubs the further communications. | 1417 | * and disturbs the further communications. |
1416 | * Thus if an error occurs during probing, | 1418 | * Thus if an error occurs during probing, |
1417 | * better to reset the controller chip to | 1419 | * better to reset the controller chip to |
1418 | * get back to the sanity state. | 1420 | * get back to the sanity state. |
@@ -1983,7 +1985,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
1983 | int pcm_dev = cpcm->device; | 1985 | int pcm_dev = cpcm->device; |
1984 | int s, err; | 1986 | int s, err; |
1985 | 1987 | ||
1986 | if (pcm_dev >= AZX_MAX_PCMS) { | 1988 | if (pcm_dev >= HDA_MAX_PCMS) { |
1987 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", | 1989 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", |
1988 | pcm_dev); | 1990 | pcm_dev); |
1989 | return -EINVAL; | 1991 | return -EINVAL; |
@@ -2139,7 +2141,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
2139 | 2141 | ||
2140 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2142 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2141 | azx_clear_irq_pending(chip); | 2143 | azx_clear_irq_pending(chip); |
2142 | for (i = 0; i < AZX_MAX_PCMS; i++) | 2144 | for (i = 0; i < HDA_MAX_PCMS; i++) |
2143 | snd_pcm_suspend_all(chip->pcm[i]); | 2145 | snd_pcm_suspend_all(chip->pcm[i]); |
2144 | if (chip->initialized) | 2146 | if (chip->initialized) |
2145 | snd_hda_suspend(chip->bus); | 2147 | snd_hda_suspend(chip->bus); |
@@ -2262,6 +2264,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { | |||
2262 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), | 2264 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), |
2263 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), | 2265 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), |
2264 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), | 2266 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), |
2267 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), | ||
2265 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), | 2268 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), |
2266 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), | 2269 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), |
2267 | {} | 2270 | {} |
@@ -2418,6 +2421,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2418 | if (bdl_pos_adj[dev] < 0) { | 2421 | if (bdl_pos_adj[dev] < 0) { |
2419 | switch (chip->driver_type) { | 2422 | switch (chip->driver_type) { |
2420 | case AZX_DRIVER_ICH: | 2423 | case AZX_DRIVER_ICH: |
2424 | case AZX_DRIVER_PCH: | ||
2421 | bdl_pos_adj[dev] = 1; | 2425 | bdl_pos_adj[dev] = 1; |
2422 | break; | 2426 | break; |
2423 | default: | 2427 | default: |
@@ -2683,7 +2687,7 @@ static void __devexit azx_remove(struct pci_dev *pci) | |||
2683 | } | 2687 | } |
2684 | 2688 | ||
2685 | /* PCI IDs */ | 2689 | /* PCI IDs */ |
2686 | static struct pci_device_id azx_ids[] = { | 2690 | static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { |
2687 | /* ICH 6..10 */ | 2691 | /* ICH 6..10 */ |
2688 | { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH }, | 2692 | { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH }, |
2689 | { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH }, | 2693 | { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH }, |
@@ -2696,6 +2700,8 @@ static struct pci_device_id azx_ids[] = { | |||
2696 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, | 2700 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, |
2697 | /* PCH */ | 2701 | /* PCH */ |
2698 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, | 2702 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, |
2703 | /* CPT */ | ||
2704 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, | ||
2699 | /* SCH */ | 2705 | /* SCH */ |
2700 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, | 2706 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, |
2701 | /* ATI SB 450/600 */ | 2707 | /* ATI SB 450/600 */ |
@@ -2723,32 +2729,10 @@ static struct pci_device_id azx_ids[] = { | |||
2723 | /* ULI M5461 */ | 2729 | /* ULI M5461 */ |
2724 | { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, | 2730 | { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, |
2725 | /* NVIDIA MCP */ | 2731 | /* NVIDIA MCP */ |
2726 | { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA }, | 2732 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), |
2727 | { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA }, | 2733 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
2728 | { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA }, | 2734 | .class_mask = 0xffffff, |
2729 | { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA }, | 2735 | .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 */ | 2736 | /* Teradici */ |
2753 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, | 2737 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, |
2754 | /* Creative X-Fi (CA0110-IBG) */ | 2738 | /* 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..e6d1bdff1b6e 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, |
@@ -2372,6 +2465,12 @@ static struct hda_verb ad1988_spdif_init_verbs[] = { | |||
2372 | { } | 2465 | { } |
2373 | }; | 2466 | }; |
2374 | 2467 | ||
2468 | static struct hda_verb ad1988_spdif_in_init_verbs[] = { | ||
2469 | /* unmute SPDIF input pin */ | ||
2470 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
2471 | { } | ||
2472 | }; | ||
2473 | |||
2375 | /* AD1989 has no ADC -> SPDIF route */ | 2474 | /* AD1989 has no ADC -> SPDIF route */ |
2376 | static struct hda_verb ad1989_spdif_init_verbs[] = { | 2475 | static struct hda_verb ad1989_spdif_init_verbs[] = { |
2377 | /* SPDIF-1 out pin */ | 2476 | /* SPDIF-1 out pin */ |
@@ -2589,7 +2688,7 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, | |||
2589 | if (! knew->name) | 2688 | if (! knew->name) |
2590 | return -ENOMEM; | 2689 | return -ENOMEM; |
2591 | if (get_amp_nid_(val)) | 2690 | if (get_amp_nid_(val)) |
2592 | knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val); | 2691 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
2593 | knew->private_value = val; | 2692 | knew->private_value = val; |
2594 | return 0; | 2693 | return 0; |
2595 | } | 2694 | } |
@@ -3107,8 +3206,11 @@ static int patch_ad1988(struct hda_codec *codec) | |||
3107 | ad1988_spdif_init_verbs; | 3206 | ad1988_spdif_init_verbs; |
3108 | } | 3207 | } |
3109 | } | 3208 | } |
3110 | if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) | 3209 | if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) { |
3111 | spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; | 3210 | spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; |
3211 | spec->init_verbs[spec->num_init_verbs++] = | ||
3212 | ad1988_spdif_in_init_verbs; | ||
3213 | } | ||
3112 | 3214 | ||
3113 | codec->patch_ops = ad198x_patch_ops; | 3215 | codec->patch_ops = ad198x_patch_ops; |
3114 | switch (board_config) { | 3216 | switch (board_config) { |
@@ -3747,6 +3849,7 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | |||
3747 | { | 3849 | { |
3748 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 3850 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
3749 | .name = "Master Playback Switch", | 3851 | .name = "Master Playback Switch", |
3852 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
3750 | .info = snd_hda_mixer_amp_switch_info, | 3853 | .info = snd_hda_mixer_amp_switch_info, |
3751 | .get = snd_hda_mixer_amp_switch_get, | 3854 | .get = snd_hda_mixer_amp_switch_get, |
3752 | .put = ad1884a_mobile_master_sw_put, | 3855 | .put = ad1884a_mobile_master_sw_put, |
@@ -3775,6 +3878,7 @@ static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { | |||
3775 | { | 3878 | { |
3776 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 3879 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
3777 | .name = "Master Playback Switch", | 3880 | .name = "Master Playback Switch", |
3881 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
3778 | .info = snd_hda_mixer_amp_switch_info, | 3882 | .info = snd_hda_mixer_amp_switch_info, |
3779 | .get = snd_hda_mixer_amp_switch_get, | 3883 | .get = snd_hda_mixer_amp_switch_get, |
3780 | .put = ad1884a_mobile_master_sw_put, | 3884 | .put = ad1884a_mobile_master_sw_put, |
@@ -4116,6 +4220,7 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { | |||
4116 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ | 4220 | /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ |
4117 | { | 4221 | { |
4118 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 4222 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
4223 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
4119 | .name = "Master Playback Switch", | 4224 | .name = "Master Playback Switch", |
4120 | .info = snd_hda_mixer_amp_switch_info, | 4225 | .info = snd_hda_mixer_amp_switch_info, |
4121 | .get = snd_hda_mixer_amp_switch_get, | 4226 | .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_realtek.c b/sound/pci/hda/patch_realtek.c index da34095c707f..e8cbe216e912 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 | } |
@@ -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}, |
@@ -13352,7 +13580,7 @@ static void alc269_lifebook_init_hook(struct hda_codec *codec) | |||
13352 | alc269_lifebook_mic_autoswitch(codec); | 13580 | alc269_lifebook_mic_autoswitch(codec); |
13353 | } | 13581 | } |
13354 | 13582 | ||
13355 | static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { | 13583 | static struct hda_verb alc269_laptop_dmic_init_verbs[] = { |
13356 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 13584 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
13357 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, | 13585 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, |
13358 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | 13586 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, |
@@ -13363,7 +13591,7 @@ static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { | |||
13363 | {} | 13591 | {} |
13364 | }; | 13592 | }; |
13365 | 13593 | ||
13366 | static struct hda_verb alc269_eeepc_amic_init_verbs[] = { | 13594 | static struct hda_verb alc269_laptop_amic_init_verbs[] = { |
13367 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 13595 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
13368 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, | 13596 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, |
13369 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | 13597 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, |
@@ -13373,6 +13601,28 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = { | |||
13373 | {} | 13601 | {} |
13374 | }; | 13602 | }; |
13375 | 13603 | ||
13604 | static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = { | ||
13605 | {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
13606 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x06}, | ||
13607 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | ||
13608 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))}, | ||
13609 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13610 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
13611 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
13612 | {} | ||
13613 | }; | ||
13614 | |||
13615 | static struct hda_verb alc269vb_laptop_amic_init_verbs[] = { | ||
13616 | {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
13617 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
13618 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | ||
13619 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))}, | ||
13620 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13621 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
13622 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
13623 | {} | ||
13624 | }; | ||
13625 | |||
13376 | /* toggle speaker-output according to the hp-jack state */ | 13626 | /* toggle speaker-output according to the hp-jack state */ |
13377 | static void alc269_speaker_automute(struct hda_codec *codec) | 13627 | static void alc269_speaker_automute(struct hda_codec *codec) |
13378 | { | 13628 | { |
@@ -13390,7 +13640,7 @@ static void alc269_speaker_automute(struct hda_codec *codec) | |||
13390 | } | 13640 | } |
13391 | 13641 | ||
13392 | /* unsolicited event for HP jack sensing */ | 13642 | /* unsolicited event for HP jack sensing */ |
13393 | static void alc269_eeepc_unsol_event(struct hda_codec *codec, | 13643 | static void alc269_laptop_unsol_event(struct hda_codec *codec, |
13394 | unsigned int res) | 13644 | unsigned int res) |
13395 | { | 13645 | { |
13396 | switch (res >> 26) { | 13646 | switch (res >> 26) { |
@@ -13403,7 +13653,7 @@ static void alc269_eeepc_unsol_event(struct hda_codec *codec, | |||
13403 | } | 13653 | } |
13404 | } | 13654 | } |
13405 | 13655 | ||
13406 | static void alc269_eeepc_dmic_setup(struct hda_codec *codec) | 13656 | static void alc269_laptop_dmic_setup(struct hda_codec *codec) |
13407 | { | 13657 | { |
13408 | struct alc_spec *spec = codec->spec; | 13658 | struct alc_spec *spec = codec->spec; |
13409 | spec->ext_mic.pin = 0x18; | 13659 | spec->ext_mic.pin = 0x18; |
@@ -13413,7 +13663,17 @@ static void alc269_eeepc_dmic_setup(struct hda_codec *codec) | |||
13413 | spec->auto_mic = 1; | 13663 | spec->auto_mic = 1; |
13414 | } | 13664 | } |
13415 | 13665 | ||
13416 | static void alc269_eeepc_amic_setup(struct hda_codec *codec) | 13666 | static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) |
13667 | { | ||
13668 | struct alc_spec *spec = codec->spec; | ||
13669 | spec->ext_mic.pin = 0x18; | ||
13670 | spec->ext_mic.mux_idx = 0; | ||
13671 | spec->int_mic.pin = 0x12; | ||
13672 | spec->int_mic.mux_idx = 6; | ||
13673 | spec->auto_mic = 1; | ||
13674 | } | ||
13675 | |||
13676 | static void alc269_laptop_amic_setup(struct hda_codec *codec) | ||
13417 | { | 13677 | { |
13418 | struct alc_spec *spec = codec->spec; | 13678 | struct alc_spec *spec = codec->spec; |
13419 | spec->ext_mic.pin = 0x18; | 13679 | spec->ext_mic.pin = 0x18; |
@@ -13423,7 +13683,7 @@ static void alc269_eeepc_amic_setup(struct hda_codec *codec) | |||
13423 | spec->auto_mic = 1; | 13683 | spec->auto_mic = 1; |
13424 | } | 13684 | } |
13425 | 13685 | ||
13426 | static void alc269_eeepc_inithook(struct hda_codec *codec) | 13686 | static void alc269_laptop_inithook(struct hda_codec *codec) |
13427 | { | 13687 | { |
13428 | alc269_speaker_automute(codec); | 13688 | alc269_speaker_automute(codec); |
13429 | alc_mic_automute(codec); | 13689 | alc_mic_automute(codec); |
@@ -13436,22 +13696,10 @@ static struct hda_verb alc269_init_verbs[] = { | |||
13436 | /* | 13696 | /* |
13437 | * Unmute ADC0 and set the default input to mic-in | 13697 | * Unmute ADC0 and set the default input to mic-in |
13438 | */ | 13698 | */ |
13439 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 13699 | {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 | 13700 | ||
13453 | /* | 13701 | /* |
13454 | * Set up output mixers (0x0c - 0x0e) | 13702 | * Set up output mixers (0x02 - 0x03) |
13455 | */ | 13703 | */ |
13456 | /* set vol=0 to output mixers */ | 13704 | /* set vol=0 to output mixers */ |
13457 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 13705 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
@@ -13476,26 +13724,57 @@ static struct hda_verb alc269_init_verbs[] = { | |||
13476 | 13724 | ||
13477 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 13725 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
13478 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 13726 | {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 | 13727 | ||
13485 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | 13728 | /* FIXME: use Mux-type input source selection */ |
13486 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | 13729 | /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */ |
13730 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
13731 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
13487 | 13732 | ||
13488 | /* FIXME: use matrix-type input source selection */ | 13733 | /* set EAPD */ |
13734 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
13735 | { } | ||
13736 | }; | ||
13737 | |||
13738 | static struct hda_verb alc269vb_init_verbs[] = { | ||
13739 | /* | ||
13740 | * Unmute ADC0 and set the default input to mic-in | ||
13741 | */ | ||
13742 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13743 | |||
13744 | /* | ||
13745 | * Set up output mixers (0x02 - 0x03) | ||
13746 | */ | ||
13747 | /* set vol=0 to output mixers */ | ||
13748 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
13749 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
13750 | |||
13751 | /* set up input amps for analog loopback */ | ||
13752 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
13753 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13754 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
13755 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13756 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
13757 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
13758 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
13759 | |||
13760 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
13761 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
13762 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
13763 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
13764 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
13765 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13766 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
13767 | |||
13768 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
13769 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
13770 | |||
13771 | /* FIXME: use Mux-type input source selection */ | ||
13489 | /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */ | 13772 | /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */ |
13490 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | 13773 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ |
13491 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 13774 | {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 | 13775 | ||
13496 | /* set EAPD */ | 13776 | /* set EAPD */ |
13497 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | 13777 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, |
13498 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
13499 | { } | 13778 | { } |
13500 | }; | 13779 | }; |
13501 | 13780 | ||
@@ -13543,6 +13822,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13543 | struct alc_spec *spec = codec->spec; | 13822 | struct alc_spec *spec = codec->spec; |
13544 | int err; | 13823 | int err; |
13545 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; | 13824 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; |
13825 | hda_nid_t real_capsrc_nids; | ||
13546 | 13826 | ||
13547 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 13827 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
13548 | alc269_ignore); | 13828 | alc269_ignore); |
@@ -13564,11 +13844,20 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13564 | if (spec->kctls.list) | 13844 | if (spec->kctls.list) |
13565 | add_mixer(spec, spec->kctls.list); | 13845 | add_mixer(spec, spec->kctls.list); |
13566 | 13846 | ||
13567 | add_verb(spec, alc269_init_verbs); | 13847 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { |
13848 | add_verb(spec, alc269vb_init_verbs); | ||
13849 | real_capsrc_nids = alc269vb_capsrc_nids[0]; | ||
13850 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); | ||
13851 | } else { | ||
13852 | add_verb(spec, alc269_init_verbs); | ||
13853 | real_capsrc_nids = alc269_capsrc_nids[0]; | ||
13854 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); | ||
13855 | } | ||
13856 | |||
13568 | spec->num_mux_defs = 1; | 13857 | spec->num_mux_defs = 1; |
13569 | spec->input_mux = &spec->private_imux[0]; | 13858 | spec->input_mux = &spec->private_imux[0]; |
13570 | /* set default input source */ | 13859 | /* set default input source */ |
13571 | snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], | 13860 | snd_hda_codec_write_cache(codec, real_capsrc_nids, |
13572 | 0, AC_VERB_SET_CONNECT_SEL, | 13861 | 0, AC_VERB_SET_CONNECT_SEL, |
13573 | spec->input_mux->items[0].index); | 13862 | spec->input_mux->items[0].index); |
13574 | 13863 | ||
@@ -13579,8 +13868,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13579 | if (!spec->cap_mixer && !spec->no_analog) | 13868 | if (!spec->cap_mixer && !spec->no_analog) |
13580 | set_capture_mixer(codec); | 13869 | set_capture_mixer(codec); |
13581 | 13870 | ||
13582 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | ||
13583 | |||
13584 | return 1; | 13871 | return 1; |
13585 | } | 13872 | } |
13586 | 13873 | ||
@@ -13606,8 +13893,8 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
13606 | static const char *alc269_models[ALC269_MODEL_LAST] = { | 13893 | static const char *alc269_models[ALC269_MODEL_LAST] = { |
13607 | [ALC269_BASIC] = "basic", | 13894 | [ALC269_BASIC] = "basic", |
13608 | [ALC269_QUANTA_FL1] = "quanta", | 13895 | [ALC269_QUANTA_FL1] = "quanta", |
13609 | [ALC269_ASUS_AMIC] = "asus-amic", | 13896 | [ALC269_AMIC] = "laptop-amic", |
13610 | [ALC269_ASUS_DMIC] = "asus-dmic", | 13897 | [ALC269_DMIC] = "laptop-dmic", |
13611 | [ALC269_FUJITSU] = "fujitsu", | 13898 | [ALC269_FUJITSU] = "fujitsu", |
13612 | [ALC269_LIFEBOOK] = "lifebook", | 13899 | [ALC269_LIFEBOOK] = "lifebook", |
13613 | [ALC269_AUTO] = "auto", | 13900 | [ALC269_AUTO] = "auto", |
@@ -13616,43 +13903,57 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { | |||
13616 | static struct snd_pci_quirk alc269_cfg_tbl[] = { | 13903 | static struct snd_pci_quirk alc269_cfg_tbl[] = { |
13617 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), | 13904 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), |
13618 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", | 13905 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", |
13619 | ALC269_ASUS_AMIC), | 13906 | ALC269_AMIC), |
13620 | SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_ASUS_AMIC), | 13907 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC), |
13621 | SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80JT", ALC269_ASUS_AMIC), | 13908 | SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC), |
13622 | SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_ASUS_AMIC), | 13909 | SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC), |
13623 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_ASUS_AMIC), | 13910 | SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC), |
13624 | SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_ASUS_AMIC), | 13911 | SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC), |
13625 | SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_ASUS_AMIC), | 13912 | SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC), |
13626 | SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_ASUS_AMIC), | 13913 | SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC), |
13627 | SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_ASUS_AMIC), | 13914 | SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC), |
13628 | SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_ASUS_AMIC), | 13915 | SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC), |
13629 | SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_ASUS_AMIC), | 13916 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_AMIC), |
13630 | SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_ASUS_AMIC), | 13917 | SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC), |
13631 | SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_ASUS_AMIC), | 13918 | SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC), |
13632 | SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_ASUS_AMIC), | 13919 | SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC), |
13633 | SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_ASUS_AMIC), | 13920 | SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC), |
13634 | SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_ASUS_AMIC), | 13921 | SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC), |
13635 | SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_ASUS_AMIC), | 13922 | SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC), |
13636 | SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_ASUS_AMIC), | 13923 | SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC), |
13637 | SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_ASUS_AMIC), | 13924 | SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC), |
13638 | SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_ASUS_AMIC), | 13925 | SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC), |
13639 | SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_ASUS_AMIC), | 13926 | SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC), |
13640 | SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_AMIC), | 13927 | SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC), |
13641 | SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_ASUS_AMIC), | 13928 | SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC), |
13642 | SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_AMIC), | 13929 | SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC), |
13643 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_DMIC), | 13930 | SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC), |
13644 | SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_AMIC), | 13931 | SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC), |
13645 | SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_AMIC), | 13932 | SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC), |
13646 | SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_AMIC), | 13933 | SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC), |
13647 | SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_AMIC), | 13934 | SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC), |
13935 | SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC), | ||
13936 | SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC), | ||
13937 | SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC), | ||
13938 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC), | ||
13939 | SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC), | ||
13940 | SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC), | ||
13941 | SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC), | ||
13942 | SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC), | ||
13648 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", | 13943 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", |
13649 | ALC269_ASUS_DMIC), | 13944 | ALC269_DMIC), |
13650 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", | 13945 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", |
13651 | ALC269_ASUS_DMIC), | 13946 | ALC269_DMIC), |
13652 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_ASUS_DMIC), | 13947 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC), |
13653 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_ASUS_DMIC), | 13948 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC), |
13654 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), | 13949 | SND_PCI_QUIRK(0x104d, 0x9071, "SONY XTB", ALC269_DMIC), |
13655 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), | 13950 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), |
13951 | SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC), | ||
13952 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), | ||
13953 | SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC), | ||
13954 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC), | ||
13955 | SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC), | ||
13956 | SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC), | ||
13656 | {} | 13957 | {} |
13657 | }; | 13958 | }; |
13658 | 13959 | ||
@@ -13680,47 +13981,75 @@ static struct alc_config_preset alc269_presets[] = { | |||
13680 | .setup = alc269_quanta_fl1_setup, | 13981 | .setup = alc269_quanta_fl1_setup, |
13681 | .init_hook = alc269_quanta_fl1_init_hook, | 13982 | .init_hook = alc269_quanta_fl1_init_hook, |
13682 | }, | 13983 | }, |
13683 | [ALC269_ASUS_AMIC] = { | 13984 | [ALC269_AMIC] = { |
13684 | .mixers = { alc269_eeepc_mixer }, | 13985 | .mixers = { alc269_laptop_mixer }, |
13685 | .cap_mixer = alc269_epc_capture_mixer, | 13986 | .cap_mixer = alc269_laptop_analog_capture_mixer, |
13686 | .init_verbs = { alc269_init_verbs, | 13987 | .init_verbs = { alc269_init_verbs, |
13687 | alc269_eeepc_amic_init_verbs }, | 13988 | alc269_laptop_amic_init_verbs }, |
13688 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 13989 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
13689 | .dac_nids = alc269_dac_nids, | 13990 | .dac_nids = alc269_dac_nids, |
13690 | .hp_nid = 0x03, | 13991 | .hp_nid = 0x03, |
13691 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | 13992 | .num_channel_mode = ARRAY_SIZE(alc269_modes), |
13692 | .channel_mode = alc269_modes, | 13993 | .channel_mode = alc269_modes, |
13693 | .unsol_event = alc269_eeepc_unsol_event, | 13994 | .unsol_event = alc269_laptop_unsol_event, |
13694 | .setup = alc269_eeepc_amic_setup, | 13995 | .setup = alc269_laptop_amic_setup, |
13695 | .init_hook = alc269_eeepc_inithook, | 13996 | .init_hook = alc269_laptop_inithook, |
13696 | }, | 13997 | }, |
13697 | [ALC269_ASUS_DMIC] = { | 13998 | [ALC269_DMIC] = { |
13698 | .mixers = { alc269_eeepc_mixer }, | 13999 | .mixers = { alc269_laptop_mixer }, |
13699 | .cap_mixer = alc269_epc_capture_mixer, | 14000 | .cap_mixer = alc269_laptop_digital_capture_mixer, |
13700 | .init_verbs = { alc269_init_verbs, | 14001 | .init_verbs = { alc269_init_verbs, |
13701 | alc269_eeepc_dmic_init_verbs }, | 14002 | alc269_laptop_dmic_init_verbs }, |
14003 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
14004 | .dac_nids = alc269_dac_nids, | ||
14005 | .hp_nid = 0x03, | ||
14006 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
14007 | .channel_mode = alc269_modes, | ||
14008 | .unsol_event = alc269_laptop_unsol_event, | ||
14009 | .setup = alc269_laptop_dmic_setup, | ||
14010 | .init_hook = alc269_laptop_inithook, | ||
14011 | }, | ||
14012 | [ALC269VB_AMIC] = { | ||
14013 | .mixers = { alc269vb_laptop_mixer }, | ||
14014 | .cap_mixer = alc269vb_laptop_analog_capture_mixer, | ||
14015 | .init_verbs = { alc269vb_init_verbs, | ||
14016 | alc269vb_laptop_amic_init_verbs }, | ||
14017 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
14018 | .dac_nids = alc269_dac_nids, | ||
14019 | .hp_nid = 0x03, | ||
14020 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
14021 | .channel_mode = alc269_modes, | ||
14022 | .unsol_event = alc269_laptop_unsol_event, | ||
14023 | .setup = alc269_laptop_amic_setup, | ||
14024 | .init_hook = alc269_laptop_inithook, | ||
14025 | }, | ||
14026 | [ALC269VB_DMIC] = { | ||
14027 | .mixers = { alc269vb_laptop_mixer }, | ||
14028 | .cap_mixer = alc269vb_laptop_digital_capture_mixer, | ||
14029 | .init_verbs = { alc269vb_init_verbs, | ||
14030 | alc269vb_laptop_dmic_init_verbs }, | ||
13702 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 14031 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
13703 | .dac_nids = alc269_dac_nids, | 14032 | .dac_nids = alc269_dac_nids, |
13704 | .hp_nid = 0x03, | 14033 | .hp_nid = 0x03, |
13705 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | 14034 | .num_channel_mode = ARRAY_SIZE(alc269_modes), |
13706 | .channel_mode = alc269_modes, | 14035 | .channel_mode = alc269_modes, |
13707 | .unsol_event = alc269_eeepc_unsol_event, | 14036 | .unsol_event = alc269_laptop_unsol_event, |
13708 | .setup = alc269_eeepc_dmic_setup, | 14037 | .setup = alc269vb_laptop_dmic_setup, |
13709 | .init_hook = alc269_eeepc_inithook, | 14038 | .init_hook = alc269_laptop_inithook, |
13710 | }, | 14039 | }, |
13711 | [ALC269_FUJITSU] = { | 14040 | [ALC269_FUJITSU] = { |
13712 | .mixers = { alc269_fujitsu_mixer }, | 14041 | .mixers = { alc269_fujitsu_mixer }, |
13713 | .cap_mixer = alc269_epc_capture_mixer, | 14042 | .cap_mixer = alc269_laptop_digital_capture_mixer, |
13714 | .init_verbs = { alc269_init_verbs, | 14043 | .init_verbs = { alc269_init_verbs, |
13715 | alc269_eeepc_dmic_init_verbs }, | 14044 | alc269_laptop_dmic_init_verbs }, |
13716 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 14045 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
13717 | .dac_nids = alc269_dac_nids, | 14046 | .dac_nids = alc269_dac_nids, |
13718 | .hp_nid = 0x03, | 14047 | .hp_nid = 0x03, |
13719 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | 14048 | .num_channel_mode = ARRAY_SIZE(alc269_modes), |
13720 | .channel_mode = alc269_modes, | 14049 | .channel_mode = alc269_modes, |
13721 | .unsol_event = alc269_eeepc_unsol_event, | 14050 | .unsol_event = alc269_laptop_unsol_event, |
13722 | .setup = alc269_eeepc_dmic_setup, | 14051 | .setup = alc269_laptop_dmic_setup, |
13723 | .init_hook = alc269_eeepc_inithook, | 14052 | .init_hook = alc269_laptop_inithook, |
13724 | }, | 14053 | }, |
13725 | [ALC269_LIFEBOOK] = { | 14054 | [ALC269_LIFEBOOK] = { |
13726 | .mixers = { alc269_lifebook_mixer }, | 14055 | .mixers = { alc269_lifebook_mixer }, |
@@ -13741,6 +14070,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
13741 | struct alc_spec *spec; | 14070 | struct alc_spec *spec; |
13742 | int board_config; | 14071 | int board_config; |
13743 | int err; | 14072 | int err; |
14073 | int is_alc269vb = 0; | ||
13744 | 14074 | ||
13745 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 14075 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
13746 | if (spec == NULL) | 14076 | if (spec == NULL) |
@@ -13757,6 +14087,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
13757 | alc_free(codec); | 14087 | alc_free(codec); |
13758 | return -ENOMEM; | 14088 | return -ENOMEM; |
13759 | } | 14089 | } |
14090 | is_alc269vb = 1; | ||
13760 | } | 14091 | } |
13761 | 14092 | ||
13762 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, | 14093 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, |
@@ -13792,7 +14123,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
13792 | if (board_config != ALC269_AUTO) | 14123 | if (board_config != ALC269_AUTO) |
13793 | setup_preset(codec, &alc269_presets[board_config]); | 14124 | setup_preset(codec, &alc269_presets[board_config]); |
13794 | 14125 | ||
13795 | if (codec->subsystem_id == 0x17aa3bf8) { | 14126 | if (board_config == ALC269_QUANTA_FL1) { |
13796 | /* Due to a hardware problem on Lenovo Ideadpad, we need to | 14127 | /* Due to a hardware problem on Lenovo Ideadpad, we need to |
13797 | * fix the sample rate of analog I/O to 44.1kHz | 14128 | * fix the sample rate of analog I/O to 44.1kHz |
13798 | */ | 14129 | */ |
@@ -13805,9 +14136,16 @@ static int patch_alc269(struct hda_codec *codec) | |||
13805 | spec->stream_digital_playback = &alc269_pcm_digital_playback; | 14136 | spec->stream_digital_playback = &alc269_pcm_digital_playback; |
13806 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 14137 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
13807 | 14138 | ||
13808 | spec->adc_nids = alc269_adc_nids; | 14139 | if (!is_alc269vb) { |
13809 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 14140 | spec->adc_nids = alc269_adc_nids; |
13810 | spec->capsrc_nids = alc269_capsrc_nids; | 14141 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
14142 | spec->capsrc_nids = alc269_capsrc_nids; | ||
14143 | } else { | ||
14144 | spec->adc_nids = alc269vb_adc_nids; | ||
14145 | spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids); | ||
14146 | spec->capsrc_nids = alc269vb_capsrc_nids; | ||
14147 | } | ||
14148 | |||
13811 | if (!spec->cap_mixer) | 14149 | if (!spec->cap_mixer) |
13812 | set_capture_mixer(codec); | 14150 | set_capture_mixer(codec); |
13813 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 14151 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
@@ -13821,7 +14159,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
13821 | if (!spec->loopback.amplist) | 14159 | if (!spec->loopback.amplist) |
13822 | spec->loopback.amplist = alc269_loopbacks; | 14160 | spec->loopback.amplist = alc269_loopbacks; |
13823 | #endif | 14161 | #endif |
13824 | codec->proc_widget_hook = print_realtek_coef; | ||
13825 | 14162 | ||
13826 | return 0; | 14163 | return 0; |
13827 | } | 14164 | } |
@@ -14684,7 +15021,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
14684 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); | 15021 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); |
14685 | set_capture_mixer(codec); | 15022 | set_capture_mixer(codec); |
14686 | 15023 | ||
14687 | alc_ssid_check(codec, 0x0e, 0x0f, 0x0b); | 15024 | alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0); |
14688 | 15025 | ||
14689 | return 1; | 15026 | return 1; |
14690 | } | 15027 | } |
@@ -14939,13 +15276,16 @@ static int patch_alc861(struct hda_codec *codec) | |||
14939 | spec->vmaster_nid = 0x03; | 15276 | spec->vmaster_nid = 0x03; |
14940 | 15277 | ||
14941 | codec->patch_ops = alc_patch_ops; | 15278 | codec->patch_ops = alc_patch_ops; |
14942 | if (board_config == ALC861_AUTO) | 15279 | if (board_config == ALC861_AUTO) { |
14943 | spec->init_hook = alc861_auto_init; | 15280 | spec->init_hook = alc861_auto_init; |
14944 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 15281 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
15282 | spec->power_hook = alc_power_eapd; | ||
15283 | #endif | ||
15284 | } | ||
15285 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
14945 | if (!spec->loopback.amplist) | 15286 | if (!spec->loopback.amplist) |
14946 | spec->loopback.amplist = alc861_loopbacks; | 15287 | spec->loopback.amplist = alc861_loopbacks; |
14947 | #endif | 15288 | #endif |
14948 | codec->proc_widget_hook = print_realtek_coef; | ||
14949 | 15289 | ||
14950 | return 0; | 15290 | return 0; |
14951 | } | 15291 | } |
@@ -15572,7 +15912,7 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
15572 | static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, | 15912 | static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, |
15573 | const struct auto_pin_cfg *cfg) | 15913 | const struct auto_pin_cfg *cfg) |
15574 | { | 15914 | { |
15575 | return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x22, 0); | 15915 | return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0); |
15576 | } | 15916 | } |
15577 | 15917 | ||
15578 | 15918 | ||
@@ -15808,7 +16148,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
15808 | if (err < 0) | 16148 | if (err < 0) |
15809 | return err; | 16149 | return err; |
15810 | 16150 | ||
15811 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | 16151 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); |
15812 | 16152 | ||
15813 | return 1; | 16153 | return 1; |
15814 | } | 16154 | } |
@@ -15925,7 +16265,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
15925 | if (!spec->loopback.amplist) | 16265 | if (!spec->loopback.amplist) |
15926 | spec->loopback.amplist = alc861vd_loopbacks; | 16266 | spec->loopback.amplist = alc861vd_loopbacks; |
15927 | #endif | 16267 | #endif |
15928 | codec->proc_widget_hook = print_realtek_coef; | ||
15929 | 16268 | ||
15930 | return 0; | 16269 | return 0; |
15931 | } | 16270 | } |
@@ -16392,13 +16731,6 @@ static struct hda_verb alc662_init_verbs[] = { | |||
16392 | /* ADC: mute amp left and right */ | 16731 | /* ADC: mute amp left and right */ |
16393 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 16732 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
16394 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 16733 | {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 | 16734 | ||
16403 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 16735 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
16404 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 16736 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -16448,6 +16780,28 @@ static struct hda_verb alc662_init_verbs[] = { | |||
16448 | { } | 16780 | { } |
16449 | }; | 16781 | }; |
16450 | 16782 | ||
16783 | static struct hda_verb alc663_init_verbs[] = { | ||
16784 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16785 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16786 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16787 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16788 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16789 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16790 | { } | ||
16791 | }; | ||
16792 | |||
16793 | static struct hda_verb alc272_init_verbs[] = { | ||
16794 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
16795 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
16796 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16797 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16798 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
16799 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
16800 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
16801 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
16802 | { } | ||
16803 | }; | ||
16804 | |||
16451 | static struct hda_verb alc662_sue_init_verbs[] = { | 16805 | static struct hda_verb alc662_sue_init_verbs[] = { |
16452 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, | 16806 | {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}, | 16807 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, |
@@ -16467,61 +16821,6 @@ static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = { | |||
16467 | {} | 16821 | {} |
16468 | }; | 16822 | }; |
16469 | 16823 | ||
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[] = { | 16824 | static struct hda_verb alc663_m51va_init_verbs[] = { |
16526 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 16825 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
16527 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 16826 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
@@ -17272,6 +17571,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
17272 | SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1), | 17571 | SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1), |
17273 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), | 17572 | SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), |
17274 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), | 17573 | SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), |
17574 | SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1), | ||
17275 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), | 17575 | SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), |
17276 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), | 17576 | SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), |
17277 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), | 17577 | SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), |
@@ -17307,6 +17607,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
17307 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), | 17607 | SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), |
17308 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), | 17608 | SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), |
17309 | SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1), | 17609 | SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1), |
17610 | SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1), | ||
17310 | SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1), | 17611 | SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1), |
17311 | SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1), | 17612 | SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1), |
17312 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), | 17613 | SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), |
@@ -17334,6 +17635,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
17334 | SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), | 17635 | SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), |
17335 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", | 17636 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", |
17336 | ALC662_3ST_6ch_DIG), | 17637 | ALC662_3ST_6ch_DIG), |
17638 | SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13), | ||
17337 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), | 17639 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), |
17338 | SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA), | 17640 | SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA), |
17339 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | 17641 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), |
@@ -17952,15 +18254,23 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
17952 | spec->num_mux_defs = 1; | 18254 | spec->num_mux_defs = 1; |
17953 | spec->input_mux = &spec->private_imux[0]; | 18255 | spec->input_mux = &spec->private_imux[0]; |
17954 | 18256 | ||
17955 | add_verb(spec, alc662_auto_init_verbs); | 18257 | add_verb(spec, alc662_init_verbs); |
17956 | if (codec->vendor_id == 0x10ec0663) | 18258 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || |
17957 | add_verb(spec, alc663_auto_init_verbs); | 18259 | codec->vendor_id == 0x10ec0665) |
18260 | add_verb(spec, alc663_init_verbs); | ||
18261 | |||
18262 | if (codec->vendor_id == 0x10ec0272) | ||
18263 | add_verb(spec, alc272_init_verbs); | ||
17958 | 18264 | ||
17959 | err = alc_auto_add_mic_boost(codec); | 18265 | err = alc_auto_add_mic_boost(codec); |
17960 | if (err < 0) | 18266 | if (err < 0) |
17961 | return err; | 18267 | return err; |
17962 | 18268 | ||
17963 | alc_ssid_check(codec, 0x15, 0x1b, 0x14); | 18269 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || |
18270 | codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670) | ||
18271 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21); | ||
18272 | else | ||
18273 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); | ||
17964 | 18274 | ||
17965 | return 1; | 18275 | return 1; |
17966 | } | 18276 | } |
@@ -18046,11 +18356,20 @@ static int patch_alc662(struct hda_codec *codec) | |||
18046 | 18356 | ||
18047 | if (!spec->cap_mixer) | 18357 | if (!spec->cap_mixer) |
18048 | set_capture_mixer(codec); | 18358 | set_capture_mixer(codec); |
18049 | if (codec->vendor_id == 0x10ec0662) | 18359 | |
18360 | switch (codec->vendor_id) { | ||
18361 | case 0x10ec0662: | ||
18050 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 18362 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
18051 | else | 18363 | break; |
18364 | case 0x10ec0272: | ||
18365 | case 0x10ec0663: | ||
18366 | case 0x10ec0665: | ||
18052 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 18367 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
18053 | 18368 | break; | |
18369 | case 0x10ec0273: | ||
18370 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); | ||
18371 | break; | ||
18372 | } | ||
18054 | spec->vmaster_nid = 0x02; | 18373 | spec->vmaster_nid = 0x02; |
18055 | 18374 | ||
18056 | codec->patch_ops = alc_patch_ops; | 18375 | codec->patch_ops = alc_patch_ops; |
@@ -18060,7 +18379,6 @@ static int patch_alc662(struct hda_codec *codec) | |||
18060 | if (!spec->loopback.amplist) | 18379 | if (!spec->loopback.amplist) |
18061 | spec->loopback.amplist = alc662_loopbacks; | 18380 | spec->loopback.amplist = alc662_loopbacks; |
18062 | #endif | 18381 | #endif |
18063 | codec->proc_widget_hook = print_realtek_coef; | ||
18064 | 18382 | ||
18065 | return 0; | 18383 | return 0; |
18066 | } | 18384 | } |
@@ -18101,6 +18419,8 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
18101 | { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", | 18419 | { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", |
18102 | .patch = patch_alc662 }, | 18420 | .patch = patch_alc662 }, |
18103 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, | 18421 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
18422 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, | ||
18423 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, | ||
18104 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 18424 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
18105 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 18425 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
18106 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, | 18426 | { .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) { |