diff options
-rw-r--r-- | sound/pci/Kconfig | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 239 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 32 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 55 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 158 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 25 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 91 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 307 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 68 |
11 files changed, 800 insertions, 192 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index ff7a689c229..9554140f0b0 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -581,6 +581,14 @@ config SND_HDA_GENERIC | |||
581 | Say Y here to enable the generic HD-audio codec parser | 581 | Say Y here to enable the generic HD-audio codec parser |
582 | in snd-hda-intel driver. | 582 | in snd-hda-intel driver. |
583 | 583 | ||
584 | config SND_HDA_POWER_SAVE | ||
585 | bool "Aggressive power-saving on HD-audio" | ||
586 | depends on SND_HDA_INTEL && EXPERIMENTAL | ||
587 | help | ||
588 | Say Y here to enable more aggressive power-saving mode on | ||
589 | HD-audio driver. The power-saving timeout can be configured | ||
590 | via power_save option or over sysfs on-the-fly. | ||
591 | |||
584 | config SND_HDSP | 592 | config SND_HDSP |
585 | tristate "RME Hammerfall DSP Audio" | 593 | tristate "RME Hammerfall DSP Audio" |
586 | depends on SND | 594 | depends on SND |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 04352930867..9a3b72824f8 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -33,6 +33,13 @@ | |||
33 | #include "hda_local.h" | 33 | #include "hda_local.h" |
34 | #include <sound/hda_hwdep.h> | 34 | #include <sound/hda_hwdep.h> |
35 | 35 | ||
36 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
37 | /* define this option here to hide as static */ | ||
38 | static int power_save = 10; | ||
39 | module_param(power_save, int, 0644); | ||
40 | MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " | ||
41 | "(in second, 0 = disable)."); | ||
42 | #endif | ||
36 | 43 | ||
37 | /* | 44 | /* |
38 | * vendor / preset table | 45 | * vendor / preset table |
@@ -60,6 +67,13 @@ static struct hda_vendor_id hda_vendor_ids[] = { | |||
60 | #include "hda_patch.h" | 67 | #include "hda_patch.h" |
61 | 68 | ||
62 | 69 | ||
70 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
71 | static void hda_power_work(struct work_struct *work); | ||
72 | static void hda_keep_power_on(struct hda_codec *codec); | ||
73 | #else | ||
74 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | ||
75 | #endif | ||
76 | |||
63 | /** | 77 | /** |
64 | * snd_hda_codec_read - send a command and get the response | 78 | * snd_hda_codec_read - send a command and get the response |
65 | * @codec: the HDA codec | 79 | * @codec: the HDA codec |
@@ -77,12 +91,14 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
77 | unsigned int verb, unsigned int parm) | 91 | unsigned int verb, unsigned int parm) |
78 | { | 92 | { |
79 | unsigned int res; | 93 | unsigned int res; |
94 | snd_hda_power_up(codec); | ||
80 | mutex_lock(&codec->bus->cmd_mutex); | 95 | mutex_lock(&codec->bus->cmd_mutex); |
81 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) | 96 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) |
82 | res = codec->bus->ops.get_response(codec); | 97 | res = codec->bus->ops.get_response(codec); |
83 | else | 98 | else |
84 | res = (unsigned int)-1; | 99 | res = (unsigned int)-1; |
85 | mutex_unlock(&codec->bus->cmd_mutex); | 100 | mutex_unlock(&codec->bus->cmd_mutex); |
101 | snd_hda_power_down(codec); | ||
86 | return res; | 102 | return res; |
87 | } | 103 | } |
88 | 104 | ||
@@ -102,9 +118,11 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
102 | unsigned int verb, unsigned int parm) | 118 | unsigned int verb, unsigned int parm) |
103 | { | 119 | { |
104 | int err; | 120 | int err; |
121 | snd_hda_power_up(codec); | ||
105 | mutex_lock(&codec->bus->cmd_mutex); | 122 | mutex_lock(&codec->bus->cmd_mutex); |
106 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | 123 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); |
107 | mutex_unlock(&codec->bus->cmd_mutex); | 124 | mutex_unlock(&codec->bus->cmd_mutex); |
125 | snd_hda_power_down(codec); | ||
108 | return err; | 126 | return err; |
109 | } | 127 | } |
110 | 128 | ||
@@ -505,6 +523,9 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
505 | { | 523 | { |
506 | if (!codec) | 524 | if (!codec) |
507 | return; | 525 | return; |
526 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
527 | cancel_delayed_work(&codec->power_work); | ||
528 | #endif | ||
508 | list_del(&codec->list); | 529 | list_del(&codec->list); |
509 | codec->bus->caddr_tbl[codec->addr] = NULL; | 530 | codec->bus->caddr_tbl[codec->addr] = NULL; |
510 | if (codec->patch_ops.free) | 531 | if (codec->patch_ops.free) |
@@ -551,6 +572,15 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
551 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 572 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
552 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 573 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
553 | 574 | ||
575 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
576 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | ||
577 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. | ||
578 | * the caller has to power down appropriatley after initialization | ||
579 | * phase. | ||
580 | */ | ||
581 | hda_keep_power_on(codec); | ||
582 | #endif | ||
583 | |||
554 | list_add_tail(&codec->list, &bus->codec_list); | 584 | list_add_tail(&codec->list, &bus->codec_list); |
555 | bus->caddr_tbl[codec_addr] = codec; | 585 | bus->caddr_tbl[codec_addr] = codec; |
556 | 586 | ||
@@ -855,7 +885,7 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
855 | return ret; | 885 | return ret; |
856 | } | 886 | } |
857 | 887 | ||
858 | #ifdef CONFIG_PM | 888 | #ifdef SND_HDA_NEEDS_RESUME |
859 | /* resume the all amp commands from the cache */ | 889 | /* resume the all amp commands from the cache */ |
860 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | 890 | void snd_hda_codec_resume_amp(struct hda_codec *codec) |
861 | { | 891 | { |
@@ -879,7 +909,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec) | |||
879 | } | 909 | } |
880 | } | 910 | } |
881 | } | 911 | } |
882 | #endif /* CONFIG_PM */ | 912 | #endif /* SND_HDA_NEEDS_RESUME */ |
883 | 913 | ||
884 | /* | 914 | /* |
885 | * AMP control callbacks | 915 | * AMP control callbacks |
@@ -945,6 +975,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
945 | long *valp = ucontrol->value.integer.value; | 975 | long *valp = ucontrol->value.integer.value; |
946 | int change = 0; | 976 | int change = 0; |
947 | 977 | ||
978 | snd_hda_power_up(codec); | ||
948 | if (chs & 1) { | 979 | if (chs & 1) { |
949 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 980 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
950 | 0x7f, *valp); | 981 | 0x7f, *valp); |
@@ -953,6 +984,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
953 | if (chs & 2) | 984 | if (chs & 2) |
954 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 985 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
955 | 0x7f, *valp); | 986 | 0x7f, *valp); |
987 | snd_hda_power_down(codec); | ||
956 | return change; | 988 | return change; |
957 | } | 989 | } |
958 | 990 | ||
@@ -1025,6 +1057,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
1025 | long *valp = ucontrol->value.integer.value; | 1057 | long *valp = ucontrol->value.integer.value; |
1026 | int change = 0; | 1058 | int change = 0; |
1027 | 1059 | ||
1060 | snd_hda_power_up(codec); | ||
1028 | if (chs & 1) { | 1061 | if (chs & 1) { |
1029 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 1062 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
1030 | HDA_AMP_MUTE, | 1063 | HDA_AMP_MUTE, |
@@ -1035,7 +1068,11 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
1035 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 1068 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
1036 | HDA_AMP_MUTE, | 1069 | HDA_AMP_MUTE, |
1037 | *valp ? 0 : HDA_AMP_MUTE); | 1070 | *valp ? 0 : HDA_AMP_MUTE); |
1038 | 1071 | #ifdef CONFIG_SND_HDA_POWER_SAVE | |
1072 | if (codec->patch_ops.check_power_status) | ||
1073 | codec->patch_ops.check_power_status(codec, nid); | ||
1074 | #endif | ||
1075 | snd_hda_power_down(codec); | ||
1039 | return change; | 1076 | return change; |
1040 | } | 1077 | } |
1041 | 1078 | ||
@@ -1502,7 +1539,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1502 | return 0; | 1539 | return 0; |
1503 | } | 1540 | } |
1504 | 1541 | ||
1505 | #ifdef CONFIG_PM | 1542 | #ifdef SND_HDA_NEEDS_RESUME |
1506 | /* | 1543 | /* |
1507 | * command cache | 1544 | * command cache |
1508 | */ | 1545 | */ |
@@ -1528,6 +1565,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
1528 | int direct, unsigned int verb, unsigned int parm) | 1565 | int direct, unsigned int verb, unsigned int parm) |
1529 | { | 1566 | { |
1530 | int err; | 1567 | int err; |
1568 | snd_hda_power_up(codec); | ||
1531 | mutex_lock(&codec->bus->cmd_mutex); | 1569 | mutex_lock(&codec->bus->cmd_mutex); |
1532 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | 1570 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); |
1533 | if (!err) { | 1571 | if (!err) { |
@@ -1538,6 +1576,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
1538 | c->val = parm; | 1576 | c->val = parm; |
1539 | } | 1577 | } |
1540 | mutex_unlock(&codec->bus->cmd_mutex); | 1578 | mutex_unlock(&codec->bus->cmd_mutex); |
1579 | snd_hda_power_down(codec); | ||
1541 | return err; | 1580 | return err; |
1542 | } | 1581 | } |
1543 | 1582 | ||
@@ -1572,7 +1611,7 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec, | |||
1572 | snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb, | 1611 | snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb, |
1573 | seq->param); | 1612 | seq->param); |
1574 | } | 1613 | } |
1575 | #endif /* CONFIG_PM */ | 1614 | #endif /* SND_HDA_NEEDS_RESUME */ |
1576 | 1615 | ||
1577 | /* | 1616 | /* |
1578 | * set power state of the codec | 1617 | * set power state of the codec |
@@ -1580,24 +1619,70 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec, | |||
1580 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 1619 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
1581 | unsigned int power_state) | 1620 | unsigned int power_state) |
1582 | { | 1621 | { |
1583 | hda_nid_t nid, nid_start; | 1622 | hda_nid_t nid; |
1584 | int nodes; | 1623 | int i; |
1585 | 1624 | ||
1586 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 1625 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, |
1587 | power_state); | 1626 | power_state); |
1588 | 1627 | ||
1589 | nodes = snd_hda_get_sub_nodes(codec, fg, &nid_start); | 1628 | nid = codec->start_nid; |
1590 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | 1629 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
1591 | if (get_wcaps(codec, nid) & AC_WCAP_POWER) | 1630 | if (get_wcaps(codec, nid) & AC_WCAP_POWER) |
1592 | snd_hda_codec_write(codec, nid, 0, | 1631 | snd_hda_codec_write(codec, nid, 0, |
1593 | AC_VERB_SET_POWER_STATE, | 1632 | AC_VERB_SET_POWER_STATE, |
1594 | power_state); | 1633 | power_state); |
1595 | } | 1634 | } |
1596 | 1635 | ||
1597 | if (power_state == AC_PWRST_D0) | 1636 | if (power_state == AC_PWRST_D0) { |
1637 | unsigned long end_time; | ||
1638 | int state; | ||
1598 | msleep(10); | 1639 | msleep(10); |
1640 | /* wait until the codec reachs to D0 */ | ||
1641 | end_time = jiffies + msecs_to_jiffies(500); | ||
1642 | do { | ||
1643 | state = snd_hda_codec_read(codec, fg, 0, | ||
1644 | AC_VERB_GET_POWER_STATE, 0); | ||
1645 | if (state == power_state) | ||
1646 | break; | ||
1647 | msleep(1); | ||
1648 | } while (time_after_eq(end_time, jiffies)); | ||
1649 | } | ||
1650 | } | ||
1651 | |||
1652 | #ifdef SND_HDA_NEEDS_RESUME | ||
1653 | /* | ||
1654 | * call suspend and power-down; used both from PM and power-save | ||
1655 | */ | ||
1656 | static void hda_call_codec_suspend(struct hda_codec *codec) | ||
1657 | { | ||
1658 | if (codec->patch_ops.suspend) | ||
1659 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); | ||
1660 | hda_set_power_state(codec, | ||
1661 | codec->afg ? codec->afg : codec->mfg, | ||
1662 | AC_PWRST_D3); | ||
1663 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1664 | cancel_delayed_work(&codec->power_work); | ||
1665 | #endif | ||
1599 | } | 1666 | } |
1600 | 1667 | ||
1668 | /* | ||
1669 | * kick up codec; used both from PM and power-save | ||
1670 | */ | ||
1671 | static void hda_call_codec_resume(struct hda_codec *codec) | ||
1672 | { | ||
1673 | hda_set_power_state(codec, | ||
1674 | codec->afg ? codec->afg : codec->mfg, | ||
1675 | AC_PWRST_D0); | ||
1676 | if (codec->patch_ops.resume) | ||
1677 | codec->patch_ops.resume(codec); | ||
1678 | else { | ||
1679 | codec->patch_ops.init(codec); | ||
1680 | snd_hda_codec_resume_amp(codec); | ||
1681 | snd_hda_codec_resume_cache(codec); | ||
1682 | } | ||
1683 | } | ||
1684 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
1685 | |||
1601 | 1686 | ||
1602 | /** | 1687 | /** |
1603 | * snd_hda_build_controls - build mixer controls | 1688 | * snd_hda_build_controls - build mixer controls |
@@ -1611,28 +1696,24 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus) | |||
1611 | { | 1696 | { |
1612 | struct hda_codec *codec; | 1697 | struct hda_codec *codec; |
1613 | 1698 | ||
1614 | /* build controls */ | ||
1615 | list_for_each_entry(codec, &bus->codec_list, list) { | 1699 | list_for_each_entry(codec, &bus->codec_list, list) { |
1616 | int err; | 1700 | int err = 0; |
1617 | if (!codec->patch_ops.build_controls) | 1701 | /* fake as if already powered-on */ |
1618 | continue; | 1702 | hda_keep_power_on(codec); |
1619 | err = codec->patch_ops.build_controls(codec); | 1703 | /* then fire up */ |
1620 | if (err < 0) | ||
1621 | return err; | ||
1622 | } | ||
1623 | |||
1624 | /* initialize */ | ||
1625 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
1626 | int err; | ||
1627 | hda_set_power_state(codec, | 1704 | hda_set_power_state(codec, |
1628 | codec->afg ? codec->afg : codec->mfg, | 1705 | codec->afg ? codec->afg : codec->mfg, |
1629 | AC_PWRST_D0); | 1706 | AC_PWRST_D0); |
1630 | if (!codec->patch_ops.init) | 1707 | /* continue to initialize... */ |
1631 | continue; | 1708 | if (codec->patch_ops.init) |
1632 | err = codec->patch_ops.init(codec); | 1709 | err = codec->patch_ops.init(codec); |
1710 | if (!err && codec->patch_ops.build_controls) | ||
1711 | err = codec->patch_ops.build_controls(codec); | ||
1712 | snd_hda_power_down(codec); | ||
1633 | if (err < 0) | 1713 | if (err < 0) |
1634 | return err; | 1714 | return err; |
1635 | } | 1715 | } |
1716 | |||
1636 | return 0; | 1717 | return 0; |
1637 | } | 1718 | } |
1638 | 1719 | ||
@@ -2078,7 +2159,7 @@ int snd_hda_check_board_config(struct hda_codec *codec, | |||
2078 | */ | 2159 | */ |
2079 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | 2160 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) |
2080 | { | 2161 | { |
2081 | int err; | 2162 | int err; |
2082 | 2163 | ||
2083 | for (; knew->name; knew++) { | 2164 | for (; knew->name; knew++) { |
2084 | struct snd_kcontrol *kctl; | 2165 | struct snd_kcontrol *kctl; |
@@ -2101,6 +2182,89 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2101 | return 0; | 2182 | return 0; |
2102 | } | 2183 | } |
2103 | 2184 | ||
2185 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2186 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
2187 | unsigned int power_state); | ||
2188 | |||
2189 | static void hda_power_work(struct work_struct *work) | ||
2190 | { | ||
2191 | struct hda_codec *codec = | ||
2192 | container_of(work, struct hda_codec, power_work.work); | ||
2193 | |||
2194 | if (!codec->power_on || codec->power_count) | ||
2195 | return; | ||
2196 | |||
2197 | hda_call_codec_suspend(codec); | ||
2198 | codec->power_on = 0; | ||
2199 | if (codec->bus->ops.pm_notify) | ||
2200 | codec->bus->ops.pm_notify(codec); | ||
2201 | } | ||
2202 | |||
2203 | static void hda_keep_power_on(struct hda_codec *codec) | ||
2204 | { | ||
2205 | codec->power_count++; | ||
2206 | codec->power_on = 1; | ||
2207 | } | ||
2208 | |||
2209 | void snd_hda_power_up(struct hda_codec *codec) | ||
2210 | { | ||
2211 | codec->power_count++; | ||
2212 | if (codec->power_on) | ||
2213 | return; | ||
2214 | |||
2215 | codec->power_on = 1; | ||
2216 | if (codec->bus->ops.pm_notify) | ||
2217 | codec->bus->ops.pm_notify(codec); | ||
2218 | hda_call_codec_resume(codec); | ||
2219 | cancel_delayed_work(&codec->power_work); | ||
2220 | } | ||
2221 | |||
2222 | void snd_hda_power_down(struct hda_codec *codec) | ||
2223 | { | ||
2224 | --codec->power_count; | ||
2225 | if (!codec->power_on) | ||
2226 | return; | ||
2227 | if (power_save) | ||
2228 | schedule_delayed_work(&codec->power_work, | ||
2229 | msecs_to_jiffies(power_save * 1000)); | ||
2230 | } | ||
2231 | |||
2232 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | ||
2233 | struct hda_loopback_check *check, | ||
2234 | hda_nid_t nid) | ||
2235 | { | ||
2236 | struct hda_amp_list *p; | ||
2237 | int ch, v; | ||
2238 | |||
2239 | if (!check->amplist) | ||
2240 | return 0; | ||
2241 | for (p = check->amplist; p->nid; p++) { | ||
2242 | if (p->nid == nid) | ||
2243 | break; | ||
2244 | } | ||
2245 | if (!p->nid) | ||
2246 | return 0; /* nothing changed */ | ||
2247 | |||
2248 | for (p = check->amplist; p->nid; p++) { | ||
2249 | for (ch = 0; ch < 2; ch++) { | ||
2250 | v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir, | ||
2251 | p->idx); | ||
2252 | if (!(v & HDA_AMP_MUTE) && v > 0) { | ||
2253 | if (!check->power_on) { | ||
2254 | check->power_on = 1; | ||
2255 | snd_hda_power_up(codec); | ||
2256 | } | ||
2257 | return 1; | ||
2258 | } | ||
2259 | } | ||
2260 | } | ||
2261 | if (check->power_on) { | ||
2262 | check->power_on = 0; | ||
2263 | snd_hda_power_down(codec); | ||
2264 | } | ||
2265 | return 0; | ||
2266 | } | ||
2267 | #endif | ||
2104 | 2268 | ||
2105 | /* | 2269 | /* |
2106 | * Channel mode helper | 2270 | * Channel mode helper |
@@ -2605,41 +2769,32 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | |||
2605 | { | 2769 | { |
2606 | struct hda_codec *codec; | 2770 | struct hda_codec *codec; |
2607 | 2771 | ||
2608 | /* FIXME: should handle power widget capabilities */ | ||
2609 | list_for_each_entry(codec, &bus->codec_list, list) { | 2772 | list_for_each_entry(codec, &bus->codec_list, list) { |
2610 | if (codec->patch_ops.suspend) | 2773 | hda_call_codec_suspend(codec); |
2611 | codec->patch_ops.suspend(codec, state); | ||
2612 | hda_set_power_state(codec, | ||
2613 | codec->afg ? codec->afg : codec->mfg, | ||
2614 | AC_PWRST_D3); | ||
2615 | } | 2774 | } |
2616 | return 0; | 2775 | return 0; |
2617 | } | 2776 | } |
2618 | 2777 | ||
2778 | #ifndef CONFIG_SND_HDA_POWER_SAVE | ||
2619 | /** | 2779 | /** |
2620 | * snd_hda_resume - resume the codecs | 2780 | * snd_hda_resume - resume the codecs |
2621 | * @bus: the HDA bus | 2781 | * @bus: the HDA bus |
2622 | * @state: resume state | 2782 | * @state: resume state |
2623 | * | 2783 | * |
2624 | * Returns 0 if successful. | 2784 | * Returns 0 if successful. |
2785 | * | ||
2786 | * This fucntion is defined only when POWER_SAVE isn't set. | ||
2787 | * In the power-save mode, the codec is resumed dynamically. | ||
2625 | */ | 2788 | */ |
2626 | int snd_hda_resume(struct hda_bus *bus) | 2789 | int snd_hda_resume(struct hda_bus *bus) |
2627 | { | 2790 | { |
2628 | struct hda_codec *codec; | 2791 | struct hda_codec *codec; |
2629 | 2792 | ||
2630 | list_for_each_entry(codec, &bus->codec_list, list) { | 2793 | list_for_each_entry(codec, &bus->codec_list, list) { |
2631 | hda_set_power_state(codec, | 2794 | hda_call_codec_resume(codec); |
2632 | codec->afg ? codec->afg : codec->mfg, | ||
2633 | AC_PWRST_D0); | ||
2634 | if (codec->patch_ops.resume) | ||
2635 | codec->patch_ops.resume(codec); | ||
2636 | else { | ||
2637 | codec->patch_ops.init(codec); | ||
2638 | snd_hda_codec_resume_amp(codec); | ||
2639 | snd_hda_codec_resume_cache(codec); | ||
2640 | } | ||
2641 | } | 2795 | } |
2642 | return 0; | 2796 | return 0; |
2643 | } | 2797 | } |
2798 | #endif /* !CONFIG_SND_HDA_POWER_SAVE */ | ||
2644 | 2799 | ||
2645 | #endif | 2800 | #endif |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 92938d2a52e..1ffffaa3a30 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -26,6 +26,10 @@ | |||
26 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
27 | #include <sound/hwdep.h> | 27 | #include <sound/hwdep.h> |
28 | 28 | ||
29 | #if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE) | ||
30 | #define SND_HDA_NEEDS_RESUME /* resume control code is required */ | ||
31 | #endif | ||
32 | |||
29 | /* | 33 | /* |
30 | * nodes | 34 | * nodes |
31 | */ | 35 | */ |
@@ -412,6 +416,10 @@ struct hda_bus_ops { | |||
412 | unsigned int (*get_response)(struct hda_codec *codec); | 416 | unsigned int (*get_response)(struct hda_codec *codec); |
413 | /* free the private data */ | 417 | /* free the private data */ |
414 | void (*private_free)(struct hda_bus *); | 418 | void (*private_free)(struct hda_bus *); |
419 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
420 | /* notify power-up/down from codec to contoller */ | ||
421 | void (*pm_notify)(struct hda_codec *codec); | ||
422 | #endif | ||
415 | }; | 423 | }; |
416 | 424 | ||
417 | /* template to pass to the bus constructor */ | 425 | /* template to pass to the bus constructor */ |
@@ -473,10 +481,13 @@ struct hda_codec_ops { | |||
473 | int (*init)(struct hda_codec *codec); | 481 | int (*init)(struct hda_codec *codec); |
474 | void (*free)(struct hda_codec *codec); | 482 | void (*free)(struct hda_codec *codec); |
475 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | 483 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); |
476 | #ifdef CONFIG_PM | 484 | #ifdef SND_HDA_NEEDS_RESUME |
477 | int (*suspend)(struct hda_codec *codec, pm_message_t state); | 485 | int (*suspend)(struct hda_codec *codec, pm_message_t state); |
478 | int (*resume)(struct hda_codec *codec); | 486 | int (*resume)(struct hda_codec *codec); |
479 | #endif | 487 | #endif |
488 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
489 | int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); | ||
490 | #endif | ||
480 | }; | 491 | }; |
481 | 492 | ||
482 | /* record for amp information cache */ | 493 | /* record for amp information cache */ |
@@ -573,6 +584,12 @@ struct hda_codec { | |||
573 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 584 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
574 | 585 | ||
575 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 586 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
587 | |||
588 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
589 | int power_on; /* current (global) power-state */ | ||
590 | int power_count; /* current (global) power refcount */ | ||
591 | struct delayed_work power_work; /* delayed task for powerdown */ | ||
592 | #endif | ||
576 | }; | 593 | }; |
577 | 594 | ||
578 | /* direction */ | 595 | /* direction */ |
@@ -617,7 +634,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, | |||
617 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); | 634 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); |
618 | 635 | ||
619 | /* cached write */ | 636 | /* cached write */ |
620 | #ifdef CONFIG_PM | 637 | #ifdef SND_HDA_NEEDS_RESUME |
621 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | 638 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, |
622 | int direct, unsigned int verb, unsigned int parm); | 639 | int direct, unsigned int verb, unsigned int parm); |
623 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | 640 | void snd_hda_sequence_write_cache(struct hda_codec *codec, |
@@ -662,4 +679,15 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); | |||
662 | int snd_hda_resume(struct hda_bus *bus); | 679 | int snd_hda_resume(struct hda_bus *bus); |
663 | #endif | 680 | #endif |
664 | 681 | ||
682 | /* | ||
683 | * power saving | ||
684 | */ | ||
685 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
686 | void snd_hda_power_up(struct hda_codec *codec); | ||
687 | void snd_hda_power_down(struct hda_codec *codec); | ||
688 | #else | ||
689 | static inline void snd_hda_power_up(struct hda_codec *codec) {} | ||
690 | static inline void snd_hda_power_down(struct hda_codec *codec) {} | ||
691 | #endif | ||
692 | |||
665 | #endif /* __SOUND_HDA_CODEC_H */ | 693 | #endif /* __SOUND_HDA_CODEC_H */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 91cd9b9ea5d..819c804a579 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -70,6 +70,13 @@ struct hda_gspec { | |||
70 | struct hda_pcm pcm_rec; /* PCM information */ | 70 | struct hda_pcm pcm_rec; /* PCM information */ |
71 | 71 | ||
72 | struct list_head nid_list; /* list of widgets */ | 72 | struct list_head nid_list; /* list of widgets */ |
73 | |||
74 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
75 | #define MAX_LOOPBACK_AMPS 7 | ||
76 | struct hda_loopback_check loopback; | ||
77 | int num_loopbacks; | ||
78 | struct hda_amp_list loopback_list[MAX_LOOPBACK_AMPS + 1]; | ||
79 | #endif | ||
73 | }; | 80 | }; |
74 | 81 | ||
75 | /* | 82 | /* |
@@ -682,11 +689,33 @@ static int parse_input(struct hda_codec *codec) | |||
682 | return 0; | 689 | return 0; |
683 | } | 690 | } |
684 | 691 | ||
692 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
693 | static void add_input_loopback(struct hda_codec *codec, hda_nid_t nid, | ||
694 | int dir, int idx) | ||
695 | { | ||
696 | struct hda_gspec *spec = codec->spec; | ||
697 | struct hda_amp_list *p; | ||
698 | |||
699 | if (spec->num_loopbacks >= MAX_LOOPBACK_AMPS) { | ||
700 | snd_printk(KERN_ERR "hda_generic: Too many loopback ctls\n"); | ||
701 | return; | ||
702 | } | ||
703 | p = &spec->loopback_list[spec->num_loopbacks++]; | ||
704 | p->nid = nid; | ||
705 | p->dir = dir; | ||
706 | p->idx = idx; | ||
707 | spec->loopback.amplist = spec->loopback_list; | ||
708 | } | ||
709 | #else | ||
710 | #define add_input_loopback(codec,nid,dir,idx) | ||
711 | #endif | ||
712 | |||
685 | /* | 713 | /* |
686 | * create mixer controls if possible | 714 | * create mixer controls if possible |
687 | */ | 715 | */ |
688 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | 716 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, |
689 | unsigned int index, const char *type, const char *dir_sfx) | 717 | unsigned int index, const char *type, |
718 | const char *dir_sfx, int is_loopback) | ||
690 | { | 719 | { |
691 | char name[32]; | 720 | char name[32]; |
692 | int err; | 721 | int err; |
@@ -700,6 +729,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
700 | if ((node->wid_caps & AC_WCAP_IN_AMP) && | 729 | if ((node->wid_caps & AC_WCAP_IN_AMP) && |
701 | (node->amp_in_caps & AC_AMPCAP_MUTE)) { | 730 | (node->amp_in_caps & AC_AMPCAP_MUTE)) { |
702 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); | 731 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); |
732 | if (is_loopback) | ||
733 | add_input_loopback(codec, node->nid, HDA_INPUT, index); | ||
703 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 734 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
704 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 735 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) |
705 | return err; | 736 | return err; |
@@ -707,6 +738,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
707 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 738 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
708 | (node->amp_out_caps & AC_AMPCAP_MUTE)) { | 739 | (node->amp_out_caps & AC_AMPCAP_MUTE)) { |
709 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); | 740 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); |
741 | if (is_loopback) | ||
742 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); | ||
710 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 743 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
711 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 744 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) |
712 | return err; | 745 | return err; |
@@ -765,7 +798,7 @@ static int create_output_mixers(struct hda_codec *codec, const char **names) | |||
765 | for (i = 0; i < spec->pcm_vol_nodes; i++) { | 798 | for (i = 0; i < spec->pcm_vol_nodes; i++) { |
766 | err = create_mixer(codec, spec->pcm_vol[i].node, | 799 | err = create_mixer(codec, spec->pcm_vol[i].node, |
767 | spec->pcm_vol[i].index, | 800 | spec->pcm_vol[i].index, |
768 | names[i], "Playback"); | 801 | names[i], "Playback", 0); |
769 | if (err < 0) | 802 | if (err < 0) |
770 | return err; | 803 | return err; |
771 | } | 804 | } |
@@ -782,7 +815,7 @@ static int build_output_controls(struct hda_codec *codec) | |||
782 | case 1: | 815 | case 1: |
783 | return create_mixer(codec, spec->pcm_vol[0].node, | 816 | return create_mixer(codec, spec->pcm_vol[0].node, |
784 | spec->pcm_vol[0].index, | 817 | spec->pcm_vol[0].index, |
785 | "Master", "Playback"); | 818 | "Master", "Playback", 0); |
786 | case 2: | 819 | case 2: |
787 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) | 820 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) |
788 | return create_output_mixers(codec, types_speaker); | 821 | return create_output_mixers(codec, types_speaker); |
@@ -818,7 +851,7 @@ static int build_input_controls(struct hda_codec *codec) | |||
818 | if (spec->input_mux.num_items == 1) { | 851 | if (spec->input_mux.num_items == 1) { |
819 | err = create_mixer(codec, adc_node, | 852 | err = create_mixer(codec, adc_node, |
820 | spec->input_mux.items[0].index, | 853 | spec->input_mux.items[0].index, |
821 | NULL, "Capture"); | 854 | NULL, "Capture", 0); |
822 | if (err < 0) | 855 | if (err < 0) |
823 | return err; | 856 | return err; |
824 | return 0; | 857 | return 0; |
@@ -884,7 +917,8 @@ static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
884 | return err; | 917 | return err; |
885 | else if (err >= 1) { | 918 | else if (err >= 1) { |
886 | if (err == 1) { | 919 | if (err == 1) { |
887 | err = create_mixer(codec, node, i, type, "Playback"); | 920 | err = create_mixer(codec, node, i, type, |
921 | "Playback", 1); | ||
888 | if (err < 0) | 922 | if (err < 0) |
889 | return err; | 923 | return err; |
890 | if (err > 0) | 924 | if (err > 0) |
@@ -1020,6 +1054,14 @@ static int build_generic_pcms(struct hda_codec *codec) | |||
1020 | return 0; | 1054 | return 0; |
1021 | } | 1055 | } |
1022 | 1056 | ||
1057 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1058 | static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
1059 | { | ||
1060 | struct hda_gspec *spec = codec->spec; | ||
1061 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
1062 | } | ||
1063 | #endif | ||
1064 | |||
1023 | 1065 | ||
1024 | /* | 1066 | /* |
1025 | */ | 1067 | */ |
@@ -1027,6 +1069,9 @@ static struct hda_codec_ops generic_patch_ops = { | |||
1027 | .build_controls = build_generic_controls, | 1069 | .build_controls = build_generic_controls, |
1028 | .build_pcms = build_generic_pcms, | 1070 | .build_pcms = build_generic_pcms, |
1029 | .free = snd_hda_generic_free, | 1071 | .free = snd_hda_generic_free, |
1072 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1073 | .check_power_status = generic_check_power_status, | ||
1074 | #endif | ||
1030 | }; | 1075 | }; |
1031 | 1076 | ||
1032 | /* | 1077 | /* |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ebb442dcc02..7be3a9b5533 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -75,6 +75,7 @@ MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " | |||
75 | module_param(enable_msi, int, 0); | 75 | module_param(enable_msi, int, 0); |
76 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); | 76 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); |
77 | 77 | ||
78 | /* power_save option is defined in hda_codec.c */ | ||
78 | 79 | ||
79 | /* just for backward compatibility */ | 80 | /* just for backward compatibility */ |
80 | static int enable; | 81 | static int enable; |
@@ -102,6 +103,18 @@ MODULE_DESCRIPTION("Intel HDA driver"); | |||
102 | #define SFX "hda-intel: " | 103 | #define SFX "hda-intel: " |
103 | 104 | ||
104 | /* | 105 | /* |
106 | * build flags | ||
107 | */ | ||
108 | |||
109 | /* | ||
110 | * reset the HD-audio controller in power save mode. | ||
111 | * this may give more power-saving, but will take longer time to | ||
112 | * wake up. | ||
113 | */ | ||
114 | #define HDA_POWER_SAVE_RESET_CONTROLLER | ||
115 | |||
116 | |||
117 | /* | ||
105 | * registers | 118 | * registers |
106 | */ | 119 | */ |
107 | #define ICH6_REG_GCAP 0x00 | 120 | #define ICH6_REG_GCAP 0x00 |
@@ -345,6 +358,7 @@ struct azx { | |||
345 | 358 | ||
346 | /* flags */ | 359 | /* flags */ |
347 | int position_fix; | 360 | int position_fix; |
361 | unsigned int running :1; | ||
348 | unsigned int initialized :1; | 362 | unsigned int initialized :1; |
349 | unsigned int single_cmd :1; | 363 | unsigned int single_cmd :1; |
350 | unsigned int polling_mode :1; | 364 | unsigned int polling_mode :1; |
@@ -665,6 +679,9 @@ static unsigned int azx_get_response(struct hda_codec *codec) | |||
665 | return azx_rirb_get_response(codec); | 679 | return azx_rirb_get_response(codec); |
666 | } | 680 | } |
667 | 681 | ||
682 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
683 | static void azx_power_notify(struct hda_codec *codec); | ||
684 | #endif | ||
668 | 685 | ||
669 | /* reset codec link */ | 686 | /* reset codec link */ |
670 | static int azx_reset(struct azx *chip) | 687 | static int azx_reset(struct azx *chip) |
@@ -790,19 +807,12 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
790 | 807 | ||
791 | 808 | ||
792 | /* | 809 | /* |
793 | * initialize the chip | 810 | * reset and start the controller registers |
794 | */ | 811 | */ |
795 | static void azx_init_chip(struct azx *chip) | 812 | static void azx_init_chip(struct azx *chip) |
796 | { | 813 | { |
797 | unsigned char reg; | 814 | if (chip->initialized) |
798 | 815 | return; | |
799 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | ||
800 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | ||
801 | * Ensuring these bits are 0 clears playback static on some HD Audio | ||
802 | * codecs | ||
803 | */ | ||
804 | pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, ®); | ||
805 | pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, reg & 0xf8); | ||
806 | 816 | ||
807 | /* reset controller */ | 817 | /* reset controller */ |
808 | azx_reset(chip); | 818 | azx_reset(chip); |
@@ -819,22 +829,45 @@ static void azx_init_chip(struct azx *chip) | |||
819 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | 829 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); |
820 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); | 830 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); |
821 | 831 | ||
832 | chip->initialized = 1; | ||
833 | } | ||
834 | |||
835 | /* | ||
836 | * initialize the PCI registers | ||
837 | */ | ||
838 | /* update bits in a PCI register byte */ | ||
839 | static void update_pci_byte(struct pci_dev *pci, unsigned int reg, | ||
840 | unsigned char mask, unsigned char val) | ||
841 | { | ||
842 | unsigned char data; | ||
843 | |||
844 | pci_read_config_byte(pci, reg, &data); | ||
845 | data &= ~mask; | ||
846 | data |= (val & mask); | ||
847 | pci_write_config_byte(pci, reg, data); | ||
848 | } | ||
849 | |||
850 | static void azx_init_pci(struct azx *chip) | ||
851 | { | ||
852 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | ||
853 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | ||
854 | * Ensuring these bits are 0 clears playback static on some HD Audio | ||
855 | * codecs | ||
856 | */ | ||
857 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | ||
858 | |||
822 | switch (chip->driver_type) { | 859 | switch (chip->driver_type) { |
823 | case AZX_DRIVER_ATI: | 860 | case AZX_DRIVER_ATI: |
824 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ | 861 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ |
825 | pci_read_config_byte(chip->pci, | 862 | update_pci_byte(chip->pci, |
826 | ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | 863 | ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, |
827 | ®); | 864 | 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP); |
828 | pci_write_config_byte(chip->pci, | ||
829 | ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | ||
830 | (reg & 0xf8) | | ||
831 | ATI_SB450_HDAUDIO_ENABLE_SNOOP); | ||
832 | break; | 865 | break; |
833 | case AZX_DRIVER_NVIDIA: | 866 | case AZX_DRIVER_NVIDIA: |
834 | /* For NVIDIA HDA, enable snoop */ | 867 | /* For NVIDIA HDA, enable snoop */ |
835 | pci_read_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, ®); | 868 | update_pci_byte(chip->pci, |
836 | pci_write_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, | 869 | NVIDIA_HDA_TRANSREG_ADDR, |
837 | (reg & 0xf0) | NVIDIA_HDA_ENABLE_COHBITS); | 870 | 0x0f, NVIDIA_HDA_ENABLE_COHBITS); |
838 | break; | 871 | break; |
839 | } | 872 | } |
840 | } | 873 | } |
@@ -1007,6 +1040,9 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1007 | bus_temp.pci = chip->pci; | 1040 | bus_temp.pci = chip->pci; |
1008 | bus_temp.ops.command = azx_send_cmd; | 1041 | bus_temp.ops.command = azx_send_cmd; |
1009 | bus_temp.ops.get_response = azx_get_response; | 1042 | bus_temp.ops.get_response = azx_get_response; |
1043 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1044 | bus_temp.ops.pm_notify = azx_power_notify; | ||
1045 | #endif | ||
1010 | 1046 | ||
1011 | err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); | 1047 | err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); |
1012 | if (err < 0) | 1048 | if (err < 0) |
@@ -1128,9 +1164,11 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1128 | 128); | 1164 | 128); |
1129 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | 1165 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, |
1130 | 128); | 1166 | 128); |
1167 | snd_hda_power_up(apcm->codec); | ||
1131 | err = hinfo->ops.open(hinfo, apcm->codec, substream); | 1168 | err = hinfo->ops.open(hinfo, apcm->codec, substream); |
1132 | if (err < 0) { | 1169 | if (err < 0) { |
1133 | azx_release_device(azx_dev); | 1170 | azx_release_device(azx_dev); |
1171 | snd_hda_power_down(apcm->codec); | ||
1134 | mutex_unlock(&chip->open_mutex); | 1172 | mutex_unlock(&chip->open_mutex); |
1135 | return err; | 1173 | return err; |
1136 | } | 1174 | } |
@@ -1159,6 +1197,7 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
1159 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1197 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1160 | azx_release_device(azx_dev); | 1198 | azx_release_device(azx_dev); |
1161 | hinfo->ops.close(hinfo, apcm->codec, substream); | 1199 | hinfo->ops.close(hinfo, apcm->codec, substream); |
1200 | snd_hda_power_down(apcm->codec); | ||
1162 | mutex_unlock(&chip->open_mutex); | 1201 | mutex_unlock(&chip->open_mutex); |
1163 | return 0; | 1202 | return 0; |
1164 | } | 1203 | } |
@@ -1459,6 +1498,48 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
1459 | } | 1498 | } |
1460 | 1499 | ||
1461 | 1500 | ||
1501 | static void azx_stop_chip(struct azx *chip) | ||
1502 | { | ||
1503 | if (chip->initialized) | ||
1504 | return; | ||
1505 | |||
1506 | /* disable interrupts */ | ||
1507 | azx_int_disable(chip); | ||
1508 | azx_int_clear(chip); | ||
1509 | |||
1510 | /* disable CORB/RIRB */ | ||
1511 | azx_free_cmd_io(chip); | ||
1512 | |||
1513 | /* disable position buffer */ | ||
1514 | azx_writel(chip, DPLBASE, 0); | ||
1515 | azx_writel(chip, DPUBASE, 0); | ||
1516 | |||
1517 | chip->initialized = 0; | ||
1518 | } | ||
1519 | |||
1520 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1521 | /* power-up/down the controller */ | ||
1522 | static void azx_power_notify(struct hda_codec *codec) | ||
1523 | { | ||
1524 | struct azx *chip = codec->bus->private_data; | ||
1525 | struct hda_codec *c; | ||
1526 | int power_on = 0; | ||
1527 | |||
1528 | list_for_each_entry(c, &codec->bus->codec_list, list) { | ||
1529 | if (c->power_on) { | ||
1530 | power_on = 1; | ||
1531 | break; | ||
1532 | } | ||
1533 | } | ||
1534 | if (power_on) | ||
1535 | azx_init_chip(chip); | ||
1536 | #ifdef HDA_POWER_SAVE_RESET_CONTROLLER | ||
1537 | else if (chip->running) | ||
1538 | azx_stop_chip(chip); | ||
1539 | #endif | ||
1540 | } | ||
1541 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
1542 | |||
1462 | #ifdef CONFIG_PM | 1543 | #ifdef CONFIG_PM |
1463 | /* | 1544 | /* |
1464 | * power management | 1545 | * power management |
@@ -1473,7 +1554,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1473 | for (i = 0; i < chip->pcm_devs; i++) | 1554 | for (i = 0; i < chip->pcm_devs; i++) |
1474 | snd_pcm_suspend_all(chip->pcm[i]); | 1555 | snd_pcm_suspend_all(chip->pcm[i]); |
1475 | snd_hda_suspend(chip->bus, state); | 1556 | snd_hda_suspend(chip->bus, state); |
1476 | azx_free_cmd_io(chip); | 1557 | azx_stop_chip(chip); |
1477 | if (chip->irq >= 0) { | 1558 | if (chip->irq >= 0) { |
1478 | synchronize_irq(chip->irq); | 1559 | synchronize_irq(chip->irq); |
1479 | free_irq(chip->irq, chip); | 1560 | free_irq(chip->irq, chip); |
@@ -1506,8 +1587,12 @@ static int azx_resume(struct pci_dev *pci) | |||
1506 | chip->msi = 0; | 1587 | chip->msi = 0; |
1507 | if (azx_acquire_irq(chip, 1) < 0) | 1588 | if (azx_acquire_irq(chip, 1) < 0) |
1508 | return -EIO; | 1589 | return -EIO; |
1590 | azx_init_pci(chip); | ||
1591 | #ifndef CONFIG_SND_HDA_POWER_SAVE | ||
1592 | /* the explicit resume is needed only when POWER_SAVE isn't set */ | ||
1509 | azx_init_chip(chip); | 1593 | azx_init_chip(chip); |
1510 | snd_hda_resume(chip->bus); | 1594 | snd_hda_resume(chip->bus); |
1595 | #endif | ||
1511 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1596 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1512 | return 0; | 1597 | return 0; |
1513 | } | 1598 | } |
@@ -1521,20 +1606,9 @@ static int azx_free(struct azx *chip) | |||
1521 | { | 1606 | { |
1522 | if (chip->initialized) { | 1607 | if (chip->initialized) { |
1523 | int i; | 1608 | int i; |
1524 | |||
1525 | for (i = 0; i < chip->num_streams; i++) | 1609 | for (i = 0; i < chip->num_streams; i++) |
1526 | azx_stream_stop(chip, &chip->azx_dev[i]); | 1610 | azx_stream_stop(chip, &chip->azx_dev[i]); |
1527 | 1611 | azx_stop_chip(chip); | |
1528 | /* disable interrupts */ | ||
1529 | azx_int_disable(chip); | ||
1530 | azx_int_clear(chip); | ||
1531 | |||
1532 | /* disable CORB/RIRB */ | ||
1533 | azx_free_cmd_io(chip); | ||
1534 | |||
1535 | /* disable position buffer */ | ||
1536 | azx_writel(chip, DPLBASE, 0); | ||
1537 | azx_writel(chip, DPUBASE, 0); | ||
1538 | } | 1612 | } |
1539 | 1613 | ||
1540 | if (chip->irq >= 0) { | 1614 | if (chip->irq >= 0) { |
@@ -1720,10 +1794,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1720 | azx_init_stream(chip); | 1794 | azx_init_stream(chip); |
1721 | 1795 | ||
1722 | /* initialize chip */ | 1796 | /* initialize chip */ |
1797 | azx_init_pci(chip); | ||
1723 | azx_init_chip(chip); | 1798 | azx_init_chip(chip); |
1724 | 1799 | ||
1725 | chip->initialized = 1; | ||
1726 | |||
1727 | /* codec detection */ | 1800 | /* codec detection */ |
1728 | if (!chip->codec_mask) { | 1801 | if (!chip->codec_mask) { |
1729 | snd_printk(KERN_ERR SFX "no codecs found!\n"); | 1802 | snd_printk(KERN_ERR SFX "no codecs found!\n"); |
@@ -1750,6 +1823,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1750 | return err; | 1823 | return err; |
1751 | } | 1824 | } |
1752 | 1825 | ||
1826 | static void power_down_all_codecs(struct azx *chip) | ||
1827 | { | ||
1828 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1829 | /* The codecs were powered up in snd_hda_codec_new(). | ||
1830 | * Now all initialization done, so turn them down if possible | ||
1831 | */ | ||
1832 | struct hda_codec *codec; | ||
1833 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | ||
1834 | snd_hda_power_down(codec); | ||
1835 | } | ||
1836 | #endif | ||
1837 | } | ||
1838 | |||
1753 | static int __devinit azx_probe(struct pci_dev *pci, | 1839 | static int __devinit azx_probe(struct pci_dev *pci, |
1754 | const struct pci_device_id *pci_id) | 1840 | const struct pci_device_id *pci_id) |
1755 | { | 1841 | { |
@@ -1800,6 +1886,8 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
1800 | } | 1886 | } |
1801 | 1887 | ||
1802 | pci_set_drvdata(pci, card); | 1888 | pci_set_drvdata(pci, card); |
1889 | chip->running = 1; | ||
1890 | power_down_all_codecs(chip); | ||
1803 | 1891 | ||
1804 | return err; | 1892 | return err; |
1805 | } | 1893 | } |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 35ea0cf37a2..a79d0ed5469 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -86,7 +86,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
86 | int direction, int idx, int mask, int val); | 86 | int direction, int idx, int mask, int val); |
87 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | 87 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, |
88 | int dir, int idx, int mask, int val); | 88 | int dir, int idx, int mask, int val); |
89 | #ifdef CONFIG_PM | 89 | #ifdef SND_HDA_NEEDS_RESUME |
90 | void snd_hda_codec_resume_amp(struct hda_codec *codec); | 90 | void snd_hda_codec_resume_amp(struct hda_codec *codec); |
91 | #endif | 91 | #endif |
92 | 92 | ||
@@ -366,4 +366,27 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
366 | */ | 366 | */ |
367 | int snd_hda_create_hwdep(struct hda_codec *codec); | 367 | int snd_hda_create_hwdep(struct hda_codec *codec); |
368 | 368 | ||
369 | /* | ||
370 | * power-management | ||
371 | */ | ||
372 | |||
373 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
374 | void snd_hda_schedule_power_save(struct hda_codec *codec); | ||
375 | |||
376 | struct hda_amp_list { | ||
377 | hda_nid_t nid; | ||
378 | unsigned char dir; | ||
379 | unsigned char idx; | ||
380 | }; | ||
381 | |||
382 | struct hda_loopback_check { | ||
383 | struct hda_amp_list *amplist; | ||
384 | int power_on; | ||
385 | }; | ||
386 | |||
387 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | ||
388 | struct hda_loopback_check *check, | ||
389 | hda_nid_t nid); | ||
390 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
391 | |||
369 | #endif /* __SOUND_HDA_LOCAL_H */ | 392 | #endif /* __SOUND_HDA_LOCAL_H */ |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index ccd19180e54..e94944f34ff 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -262,6 +262,7 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
262 | 262 | ||
263 | if (! codec->afg) | 263 | if (! codec->afg) |
264 | return; | 264 | return; |
265 | snd_hda_power_up(codec); | ||
265 | snd_iprintf(buffer, "Default PCM:\n"); | 266 | snd_iprintf(buffer, "Default PCM:\n"); |
266 | print_pcm_caps(buffer, codec, codec->afg); | 267 | print_pcm_caps(buffer, codec, codec->afg); |
267 | snd_iprintf(buffer, "Default Amp-In caps: "); | 268 | snd_iprintf(buffer, "Default Amp-In caps: "); |
@@ -272,6 +273,7 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
272 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | 273 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); |
273 | if (! nid || nodes < 0) { | 274 | if (! nid || nodes < 0) { |
274 | snd_iprintf(buffer, "Invalid AFG subtree\n"); | 275 | snd_iprintf(buffer, "Invalid AFG subtree\n"); |
276 | snd_hda_power_down(codec); | ||
275 | return; | 277 | return; |
276 | } | 278 | } |
277 | for (i = 0; i < nodes; i++, nid++) { | 279 | for (i = 0; i < nodes; i++, nid++) { |
@@ -359,6 +361,7 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
359 | snd_iprintf(buffer, "\n"); | 361 | snd_iprintf(buffer, "\n"); |
360 | } | 362 | } |
361 | } | 363 | } |
364 | snd_hda_power_down(codec); | ||
362 | } | 365 | } |
363 | 366 | ||
364 | /* | 367 | /* |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index f9390a544ea..53cfa0da496 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -73,6 +73,10 @@ struct ad198x_spec { | |||
73 | struct snd_kcontrol_new *kctl_alloc; | 73 | struct snd_kcontrol_new *kctl_alloc; |
74 | struct hda_input_mux private_imux; | 74 | struct hda_input_mux private_imux; |
75 | hda_nid_t private_dac_nids[4]; | 75 | hda_nid_t private_dac_nids[4]; |
76 | |||
77 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
78 | struct hda_loopback_check loopback; | ||
79 | #endif | ||
76 | }; | 80 | }; |
77 | 81 | ||
78 | /* | 82 | /* |
@@ -144,6 +148,14 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
144 | return 0; | 148 | return 0; |
145 | } | 149 | } |
146 | 150 | ||
151 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
152 | static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
153 | { | ||
154 | struct ad198x_spec *spec = codec->spec; | ||
155 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
156 | } | ||
157 | #endif | ||
158 | |||
147 | /* | 159 | /* |
148 | * Analog playback callbacks | 160 | * Analog playback callbacks |
149 | */ | 161 | */ |
@@ -323,6 +335,9 @@ static struct hda_codec_ops ad198x_patch_ops = { | |||
323 | .build_pcms = ad198x_build_pcms, | 335 | .build_pcms = ad198x_build_pcms, |
324 | .init = ad198x_init, | 336 | .init = ad198x_init, |
325 | .free = ad198x_free, | 337 | .free = ad198x_free, |
338 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
339 | .check_power_status = ad198x_check_power_status, | ||
340 | #endif | ||
326 | }; | 341 | }; |
327 | 342 | ||
328 | 343 | ||
@@ -736,6 +751,17 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
736 | {} | 751 | {} |
737 | }; | 752 | }; |
738 | 753 | ||
754 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
755 | static struct hda_amp_list ad1986a_loopbacks[] = { | ||
756 | { 0x13, HDA_OUTPUT, 0 }, /* Mic */ | ||
757 | { 0x14, HDA_OUTPUT, 0 }, /* Phone */ | ||
758 | { 0x15, HDA_OUTPUT, 0 }, /* CD */ | ||
759 | { 0x16, HDA_OUTPUT, 0 }, /* Aux */ | ||
760 | { 0x17, HDA_OUTPUT, 0 }, /* Line */ | ||
761 | { } /* end */ | ||
762 | }; | ||
763 | #endif | ||
764 | |||
739 | static int patch_ad1986a(struct hda_codec *codec) | 765 | static int patch_ad1986a(struct hda_codec *codec) |
740 | { | 766 | { |
741 | struct ad198x_spec *spec; | 767 | struct ad198x_spec *spec; |
@@ -759,6 +785,9 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
759 | spec->mixers[0] = ad1986a_mixers; | 785 | spec->mixers[0] = ad1986a_mixers; |
760 | spec->num_init_verbs = 1; | 786 | spec->num_init_verbs = 1; |
761 | spec->init_verbs[0] = ad1986a_init_verbs; | 787 | spec->init_verbs[0] = ad1986a_init_verbs; |
788 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
789 | spec->loopback.amplist = ad1986a_loopbacks; | ||
790 | #endif | ||
762 | 791 | ||
763 | codec->patch_ops = ad198x_patch_ops; | 792 | codec->patch_ops = ad198x_patch_ops; |
764 | 793 | ||
@@ -944,6 +973,13 @@ static struct hda_verb ad1983_init_verbs[] = { | |||
944 | { } /* end */ | 973 | { } /* end */ |
945 | }; | 974 | }; |
946 | 975 | ||
976 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
977 | static struct hda_amp_list ad1983_loopbacks[] = { | ||
978 | { 0x12, HDA_OUTPUT, 0 }, /* Mic */ | ||
979 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | ||
980 | { } /* end */ | ||
981 | }; | ||
982 | #endif | ||
947 | 983 | ||
948 | static int patch_ad1983(struct hda_codec *codec) | 984 | static int patch_ad1983(struct hda_codec *codec) |
949 | { | 985 | { |
@@ -968,6 +1004,9 @@ static int patch_ad1983(struct hda_codec *codec) | |||
968 | spec->num_init_verbs = 1; | 1004 | spec->num_init_verbs = 1; |
969 | spec->init_verbs[0] = ad1983_init_verbs; | 1005 | spec->init_verbs[0] = ad1983_init_verbs; |
970 | spec->spdif_route = 0; | 1006 | spec->spdif_route = 0; |
1007 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1008 | spec->loopback.amplist = ad1983_loopbacks; | ||
1009 | #endif | ||
971 | 1010 | ||
972 | codec->patch_ops = ad198x_patch_ops; | 1011 | codec->patch_ops = ad198x_patch_ops; |
973 | 1012 | ||
@@ -1091,6 +1130,17 @@ static struct hda_verb ad1981_init_verbs[] = { | |||
1091 | { } /* end */ | 1130 | { } /* end */ |
1092 | }; | 1131 | }; |
1093 | 1132 | ||
1133 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1134 | static struct hda_amp_list ad1981_loopbacks[] = { | ||
1135 | { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ | ||
1136 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | ||
1137 | { 0x1b, HDA_OUTPUT, 0 }, /* Aux */ | ||
1138 | { 0x1c, HDA_OUTPUT, 0 }, /* Mic */ | ||
1139 | { 0x1d, HDA_OUTPUT, 0 }, /* CD */ | ||
1140 | { } /* end */ | ||
1141 | }; | ||
1142 | #endif | ||
1143 | |||
1094 | /* | 1144 | /* |
1095 | * Patch for HP nx6320 | 1145 | * Patch for HP nx6320 |
1096 | * | 1146 | * |
@@ -1350,6 +1400,9 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1350 | spec->num_init_verbs = 1; | 1400 | spec->num_init_verbs = 1; |
1351 | spec->init_verbs[0] = ad1981_init_verbs; | 1401 | spec->init_verbs[0] = ad1981_init_verbs; |
1352 | spec->spdif_route = 0; | 1402 | spec->spdif_route = 0; |
1403 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1404 | spec->loopback.amplist = ad1981_loopbacks; | ||
1405 | #endif | ||
1353 | 1406 | ||
1354 | codec->patch_ops = ad198x_patch_ops; | 1407 | codec->patch_ops = ad198x_patch_ops; |
1355 | 1408 | ||
@@ -2103,6 +2156,15 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2103 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); | 2156 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); |
2104 | } | 2157 | } |
2105 | 2158 | ||
2159 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2160 | static struct hda_amp_list ad1988_loopbacks[] = { | ||
2161 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
2162 | { 0x20, HDA_INPUT, 1 }, /* Line */ | ||
2163 | { 0x20, HDA_INPUT, 4 }, /* Mic */ | ||
2164 | { 0x20, HDA_INPUT, 6 }, /* CD */ | ||
2165 | { } /* end */ | ||
2166 | }; | ||
2167 | #endif | ||
2106 | 2168 | ||
2107 | /* | 2169 | /* |
2108 | * Automatic parse of I/O pins from the BIOS configuration | 2170 | * Automatic parse of I/O pins from the BIOS configuration |
@@ -2647,6 +2709,9 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2647 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; | 2709 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; |
2648 | break; | 2710 | break; |
2649 | } | 2711 | } |
2712 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2713 | spec->loopback.amplist = ad1988_loopbacks; | ||
2714 | #endif | ||
2650 | 2715 | ||
2651 | return 0; | 2716 | return 0; |
2652 | } | 2717 | } |
@@ -2803,6 +2868,16 @@ static struct hda_verb ad1884_init_verbs[] = { | |||
2803 | { } /* end */ | 2868 | { } /* end */ |
2804 | }; | 2869 | }; |
2805 | 2870 | ||
2871 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2872 | static struct hda_amp_list ad1884_loopbacks[] = { | ||
2873 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
2874 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | ||
2875 | { 0x20, HDA_INPUT, 2 }, /* CD */ | ||
2876 | { 0x20, HDA_INPUT, 4 }, /* Docking */ | ||
2877 | { } /* end */ | ||
2878 | }; | ||
2879 | #endif | ||
2880 | |||
2806 | static int patch_ad1884(struct hda_codec *codec) | 2881 | static int patch_ad1884(struct hda_codec *codec) |
2807 | { | 2882 | { |
2808 | struct ad198x_spec *spec; | 2883 | struct ad198x_spec *spec; |
@@ -2827,6 +2902,9 @@ static int patch_ad1884(struct hda_codec *codec) | |||
2827 | spec->num_init_verbs = 1; | 2902 | spec->num_init_verbs = 1; |
2828 | spec->init_verbs[0] = ad1884_init_verbs; | 2903 | spec->init_verbs[0] = ad1884_init_verbs; |
2829 | spec->spdif_route = 0; | 2904 | spec->spdif_route = 0; |
2905 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2906 | spec->loopback.amplist = ad1884_loopbacks; | ||
2907 | #endif | ||
2830 | 2908 | ||
2831 | codec->patch_ops = ad198x_patch_ops; | 2909 | codec->patch_ops = ad198x_patch_ops; |
2832 | 2910 | ||
@@ -3208,6 +3286,16 @@ static struct hda_verb ad1882_init_verbs[] = { | |||
3208 | { } /* end */ | 3286 | { } /* end */ |
3209 | }; | 3287 | }; |
3210 | 3288 | ||
3289 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3290 | static struct hda_amp_list ad1882_loopbacks[] = { | ||
3291 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
3292 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | ||
3293 | { 0x20, HDA_INPUT, 4 }, /* Line */ | ||
3294 | { 0x20, HDA_INPUT, 6 }, /* CD */ | ||
3295 | { } /* end */ | ||
3296 | }; | ||
3297 | #endif | ||
3298 | |||
3211 | /* models */ | 3299 | /* models */ |
3212 | enum { | 3300 | enum { |
3213 | AD1882_3STACK, | 3301 | AD1882_3STACK, |
@@ -3246,6 +3334,9 @@ static int patch_ad1882(struct hda_codec *codec) | |||
3246 | spec->num_init_verbs = 1; | 3334 | spec->num_init_verbs = 1; |
3247 | spec->init_verbs[0] = ad1882_init_verbs; | 3335 | spec->init_verbs[0] = ad1882_init_verbs; |
3248 | spec->spdif_route = 0; | 3336 | spec->spdif_route = 0; |
3337 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3338 | spec->loopback.amplist = ad1882_loopbacks; | ||
3339 | #endif | ||
3249 | 3340 | ||
3250 | codec->patch_ops = ad198x_patch_ops; | 3341 | codec->patch_ops = ad198x_patch_ops; |
3251 | 3342 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ebbabeb3293..b3d3916c8ec 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -240,6 +240,10 @@ struct alc_spec { | |||
240 | /* for pin sensing */ | 240 | /* for pin sensing */ |
241 | unsigned int sense_updated: 1; | 241 | unsigned int sense_updated: 1; |
242 | unsigned int jack_present: 1; | 242 | unsigned int jack_present: 1; |
243 | |||
244 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
245 | struct hda_loopback_check loopback; | ||
246 | #endif | ||
243 | }; | 247 | }; |
244 | 248 | ||
245 | /* | 249 | /* |
@@ -264,6 +268,9 @@ struct alc_config_preset { | |||
264 | const struct hda_input_mux *input_mux; | 268 | const struct hda_input_mux *input_mux; |
265 | void (*unsol_event)(struct hda_codec *, unsigned int); | 269 | void (*unsol_event)(struct hda_codec *, unsigned int); |
266 | void (*init_hook)(struct hda_codec *); | 270 | void (*init_hook)(struct hda_codec *); |
271 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
272 | struct hda_amp_list *loopbacks; | ||
273 | #endif | ||
267 | }; | 274 | }; |
268 | 275 | ||
269 | 276 | ||
@@ -621,6 +628,9 @@ static void setup_preset(struct alc_spec *spec, | |||
621 | 628 | ||
622 | spec->unsol_event = preset->unsol_event; | 629 | spec->unsol_event = preset->unsol_event; |
623 | spec->init_hook = preset->init_hook; | 630 | spec->init_hook = preset->init_hook; |
631 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
632 | spec->loopback.amplist = preset->loopbacks; | ||
633 | #endif | ||
624 | } | 634 | } |
625 | 635 | ||
626 | /* Enable GPIO mask and set output */ | 636 | /* Enable GPIO mask and set output */ |
@@ -1287,11 +1297,13 @@ static struct hda_verb alc880_volume_init_verbs[] = { | |||
1287 | * panel mic (mic 2) | 1297 | * panel mic (mic 2) |
1288 | */ | 1298 | */ |
1289 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 1299 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
1290 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1300 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1291 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 1301 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1292 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 1302 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1293 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 1303 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1294 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 1304 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1305 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
1306 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
1295 | 1307 | ||
1296 | /* | 1308 | /* |
1297 | * Set up output mixers (0x0c - 0x0f) | 1309 | * Set up output mixers (0x0c - 0x0f) |
@@ -1836,8 +1848,8 @@ static struct hda_verb alc880_lg_init_verbs[] = { | |||
1836 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 1848 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
1837 | /* mute all amp mixer inputs */ | 1849 | /* mute all amp mixer inputs */ |
1838 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 1850 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, |
1839 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 1851 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
1840 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 1852 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
1841 | /* line-in to input */ | 1853 | /* line-in to input */ |
1842 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 1854 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1843 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1855 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -1939,7 +1951,7 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = { | |||
1939 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1951 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1940 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1952 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1941 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1953 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1942 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 1954 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
1943 | /* speaker-out */ | 1955 | /* speaker-out */ |
1944 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 1956 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1945 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1957 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -1979,6 +1991,24 @@ static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1979 | alc880_lg_lw_automute(codec); | 1991 | alc880_lg_lw_automute(codec); |
1980 | } | 1992 | } |
1981 | 1993 | ||
1994 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1995 | static struct hda_amp_list alc880_loopbacks[] = { | ||
1996 | { 0x0b, HDA_INPUT, 0 }, | ||
1997 | { 0x0b, HDA_INPUT, 1 }, | ||
1998 | { 0x0b, HDA_INPUT, 2 }, | ||
1999 | { 0x0b, HDA_INPUT, 3 }, | ||
2000 | { 0x0b, HDA_INPUT, 4 }, | ||
2001 | { } /* end */ | ||
2002 | }; | ||
2003 | |||
2004 | static struct hda_amp_list alc880_lg_loopbacks[] = { | ||
2005 | { 0x0b, HDA_INPUT, 1 }, | ||
2006 | { 0x0b, HDA_INPUT, 6 }, | ||
2007 | { 0x0b, HDA_INPUT, 7 }, | ||
2008 | { } /* end */ | ||
2009 | }; | ||
2010 | #endif | ||
2011 | |||
1982 | /* | 2012 | /* |
1983 | * Common callbacks | 2013 | * Common callbacks |
1984 | */ | 2014 | */ |
@@ -2005,6 +2035,14 @@ static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2005 | spec->unsol_event(codec, res); | 2035 | spec->unsol_event(codec, res); |
2006 | } | 2036 | } |
2007 | 2037 | ||
2038 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2039 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
2040 | { | ||
2041 | struct alc_spec *spec = codec->spec; | ||
2042 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
2043 | } | ||
2044 | #endif | ||
2045 | |||
2008 | /* | 2046 | /* |
2009 | * Analog playback callbacks | 2047 | * Analog playback callbacks |
2010 | */ | 2048 | */ |
@@ -2236,6 +2274,9 @@ static struct hda_codec_ops alc_patch_ops = { | |||
2236 | .init = alc_init, | 2274 | .init = alc_init, |
2237 | .free = alc_free, | 2275 | .free = alc_free, |
2238 | .unsol_event = alc_unsol_event, | 2276 | .unsol_event = alc_unsol_event, |
2277 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2278 | .check_power_status = alc_check_power_status, | ||
2279 | #endif | ||
2239 | }; | 2280 | }; |
2240 | 2281 | ||
2241 | 2282 | ||
@@ -2860,6 +2901,9 @@ static struct alc_config_preset alc880_presets[] = { | |||
2860 | .input_mux = &alc880_lg_capture_source, | 2901 | .input_mux = &alc880_lg_capture_source, |
2861 | .unsol_event = alc880_lg_unsol_event, | 2902 | .unsol_event = alc880_lg_unsol_event, |
2862 | .init_hook = alc880_lg_automute, | 2903 | .init_hook = alc880_lg_automute, |
2904 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2905 | .loopbacks = alc880_lg_loopbacks, | ||
2906 | #endif | ||
2863 | }, | 2907 | }, |
2864 | [ALC880_LG_LW] = { | 2908 | [ALC880_LG_LW] = { |
2865 | .mixers = { alc880_lg_lw_mixer }, | 2909 | .mixers = { alc880_lg_lw_mixer }, |
@@ -3343,6 +3387,10 @@ static int patch_alc880(struct hda_codec *codec) | |||
3343 | codec->patch_ops = alc_patch_ops; | 3387 | codec->patch_ops = alc_patch_ops; |
3344 | if (board_config == ALC880_AUTO) | 3388 | if (board_config == ALC880_AUTO) |
3345 | spec->init_hook = alc880_auto_init; | 3389 | spec->init_hook = alc880_auto_init; |
3390 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3391 | if (!spec->loopback.amplist) | ||
3392 | spec->loopback.amplist = alc880_loopbacks; | ||
3393 | #endif | ||
3346 | 3394 | ||
3347 | return 0; | 3395 | return 0; |
3348 | } | 3396 | } |
@@ -3691,12 +3739,12 @@ static struct hda_verb alc260_init_verbs[] = { | |||
3691 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3739 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3692 | * Line In 2 = 0x03 | 3740 | * Line In 2 = 0x03 |
3693 | */ | 3741 | */ |
3694 | /* mute CD */ | 3742 | /* mute analog inputs */ |
3695 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 3743 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3696 | /* mute Line In */ | 3744 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3697 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 3745 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3698 | /* mute Mic */ | 3746 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3699 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 3747 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3700 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3748 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3701 | /* mute Front out path */ | 3749 | /* mute Front out path */ |
3702 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3750 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
@@ -3741,12 +3789,12 @@ static struct hda_verb alc260_hp_init_verbs[] = { | |||
3741 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3789 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3742 | * Line In 2 = 0x03 | 3790 | * Line In 2 = 0x03 |
3743 | */ | 3791 | */ |
3744 | /* unmute CD */ | 3792 | /* mute analog inputs */ |
3745 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3793 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3746 | /* unmute Line In */ | 3794 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3747 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 3795 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3748 | /* unmute Mic */ | 3796 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3749 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3797 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3750 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3798 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3751 | /* Unmute Front out path */ | 3799 | /* Unmute Front out path */ |
3752 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3800 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, |
@@ -3791,12 +3839,12 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = { | |||
3791 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3839 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3792 | * Line In 2 = 0x03 | 3840 | * Line In 2 = 0x03 |
3793 | */ | 3841 | */ |
3794 | /* unmute CD */ | 3842 | /* mute analog inputs */ |
3795 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3843 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3796 | /* unmute Line In */ | 3844 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3797 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 3845 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3798 | /* unmute Mic */ | 3846 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3799 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3847 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3800 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3848 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3801 | /* Unmute Front out path */ | 3849 | /* Unmute Front out path */ |
3802 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3850 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, |
@@ -4418,11 +4466,12 @@ static struct hda_verb alc260_volume_init_verbs[] = { | |||
4418 | * front panel mic (mic 2) | 4466 | * front panel mic (mic 2) |
4419 | */ | 4467 | */ |
4420 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 4468 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
4421 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4469 | /* mute analog inputs */ |
4422 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 4470 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
4423 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 4471 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
4424 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 4472 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
4425 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 4473 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
4474 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
4426 | 4475 | ||
4427 | /* | 4476 | /* |
4428 | * Set up output mixers (0x08 - 0x0a) | 4477 | * Set up output mixers (0x08 - 0x0a) |
@@ -4499,6 +4548,17 @@ static void alc260_auto_init(struct hda_codec *codec) | |||
4499 | alc260_auto_init_analog_input(codec); | 4548 | alc260_auto_init_analog_input(codec); |
4500 | } | 4549 | } |
4501 | 4550 | ||
4551 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4552 | static struct hda_amp_list alc260_loopbacks[] = { | ||
4553 | { 0x07, HDA_INPUT, 0 }, | ||
4554 | { 0x07, HDA_INPUT, 1 }, | ||
4555 | { 0x07, HDA_INPUT, 2 }, | ||
4556 | { 0x07, HDA_INPUT, 3 }, | ||
4557 | { 0x07, HDA_INPUT, 4 }, | ||
4558 | { } /* end */ | ||
4559 | }; | ||
4560 | #endif | ||
4561 | |||
4502 | /* | 4562 | /* |
4503 | * ALC260 configurations | 4563 | * ALC260 configurations |
4504 | */ | 4564 | */ |
@@ -4698,6 +4758,10 @@ static int patch_alc260(struct hda_codec *codec) | |||
4698 | codec->patch_ops = alc_patch_ops; | 4758 | codec->patch_ops = alc_patch_ops; |
4699 | if (board_config == ALC260_AUTO) | 4759 | if (board_config == ALC260_AUTO) |
4700 | spec->init_hook = alc260_auto_init; | 4760 | spec->init_hook = alc260_auto_init; |
4761 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4762 | if (!spec->loopback.amplist) | ||
4763 | spec->loopback.amplist = alc260_loopbacks; | ||
4764 | #endif | ||
4701 | 4765 | ||
4702 | return 0; | 4766 | return 0; |
4703 | } | 4767 | } |
@@ -5223,17 +5287,17 @@ static struct hda_verb alc882_auto_init_verbs[] = { | |||
5223 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 5287 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
5224 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5288 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5225 | 5289 | ||
5226 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 5290 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
5227 | * mixer widget | 5291 | * mixer widget |
5228 | * Note: PASD motherboards uses the Line In 2 as the input for | 5292 | * Note: PASD motherboards uses the Line In 2 as the input for |
5229 | * front panel mic (mic 2) | 5293 | * front panel mic (mic 2) |
5230 | */ | 5294 | */ |
5231 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 5295 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
5232 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5296 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
5233 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 5297 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
5234 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 5298 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
5235 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 5299 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
5236 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 5300 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
5237 | 5301 | ||
5238 | /* | 5302 | /* |
5239 | * Set up output mixers (0x0c - 0x0f) | 5303 | * Set up output mixers (0x0c - 0x0f) |
@@ -5322,6 +5386,10 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = { | |||
5322 | { } /* end */ | 5386 | { } /* end */ |
5323 | }; | 5387 | }; |
5324 | 5388 | ||
5389 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5390 | #define alc882_loopbacks alc880_loopbacks | ||
5391 | #endif | ||
5392 | |||
5325 | /* pcm configuration: identiacal with ALC880 */ | 5393 | /* pcm configuration: identiacal with ALC880 */ |
5326 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback | 5394 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback |
5327 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture | 5395 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture |
@@ -5659,6 +5727,10 @@ static int patch_alc882(struct hda_codec *codec) | |||
5659 | codec->patch_ops = alc_patch_ops; | 5727 | codec->patch_ops = alc_patch_ops; |
5660 | if (board_config == ALC882_AUTO) | 5728 | if (board_config == ALC882_AUTO) |
5661 | spec->init_hook = alc882_auto_init; | 5729 | spec->init_hook = alc882_auto_init; |
5730 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5731 | if (!spec->loopback.amplist) | ||
5732 | spec->loopback.amplist = alc882_loopbacks; | ||
5733 | #endif | ||
5662 | 5734 | ||
5663 | return 0; | 5735 | return 0; |
5664 | } | 5736 | } |
@@ -6242,11 +6314,12 @@ static struct hda_verb alc883_init_verbs[] = { | |||
6242 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 6314 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6243 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 6315 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6244 | 6316 | ||
6245 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6317 | /* mute analog input loopbacks */ |
6246 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 6318 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6247 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6319 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6248 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 6320 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
6249 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 6321 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
6322 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
6250 | 6323 | ||
6251 | /* Front Pin: output 0 (0x0c) */ | 6324 | /* Front Pin: output 0 (0x0c) */ |
6252 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 6325 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
@@ -6515,17 +6588,17 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
6515 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 6588 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
6516 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6589 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
6517 | 6590 | ||
6518 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 6591 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
6519 | * mixer widget | 6592 | * mixer widget |
6520 | * Note: PASD motherboards uses the Line In 2 as the input for | 6593 | * Note: PASD motherboards uses the Line In 2 as the input for |
6521 | * front panel mic (mic 2) | 6594 | * front panel mic (mic 2) |
6522 | */ | 6595 | */ |
6523 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 6596 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
6524 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6597 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6525 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 6598 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6526 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6599 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
6527 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 6600 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
6528 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 6601 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
6529 | 6602 | ||
6530 | /* | 6603 | /* |
6531 | * Set up output mixers (0x0c - 0x0f) | 6604 | * Set up output mixers (0x0c - 0x0f) |
@@ -6588,6 +6661,10 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = { | |||
6588 | { } /* end */ | 6661 | { } /* end */ |
6589 | }; | 6662 | }; |
6590 | 6663 | ||
6664 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
6665 | #define alc883_loopbacks alc880_loopbacks | ||
6666 | #endif | ||
6667 | |||
6591 | /* pcm configuration: identiacal with ALC880 */ | 6668 | /* pcm configuration: identiacal with ALC880 */ |
6592 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback | 6669 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback |
6593 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture | 6670 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture |
@@ -7029,6 +7106,10 @@ static int patch_alc883(struct hda_codec *codec) | |||
7029 | codec->patch_ops = alc_patch_ops; | 7106 | codec->patch_ops = alc_patch_ops; |
7030 | if (board_config == ALC883_AUTO) | 7107 | if (board_config == ALC883_AUTO) |
7031 | spec->init_hook = alc883_auto_init; | 7108 | spec->init_hook = alc883_auto_init; |
7109 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
7110 | if (!spec->loopback.amplist) | ||
7111 | spec->loopback.amplist = alc883_loopbacks; | ||
7112 | #endif | ||
7032 | 7113 | ||
7033 | return 0; | 7114 | return 0; |
7034 | } | 7115 | } |
@@ -7186,17 +7267,17 @@ static struct hda_verb alc262_init_verbs[] = { | |||
7186 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7267 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7187 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7268 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7188 | 7269 | ||
7189 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7270 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7190 | * mixer widget | 7271 | * mixer widget |
7191 | * Note: PASD motherboards uses the Line In 2 as the input for | 7272 | * Note: PASD motherboards uses the Line In 2 as the input for |
7192 | * front panel mic (mic 2) | 7273 | * front panel mic (mic 2) |
7193 | */ | 7274 | */ |
7194 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7275 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7195 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7276 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7196 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7277 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7197 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7278 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7198 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7279 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7199 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7280 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7200 | 7281 | ||
7201 | /* | 7282 | /* |
7202 | * Set up output mixers (0x0c - 0x0e) | 7283 | * Set up output mixers (0x0c - 0x0e) |
@@ -7565,17 +7646,17 @@ static struct hda_verb alc262_volume_init_verbs[] = { | |||
7565 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7646 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7566 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7647 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7567 | 7648 | ||
7568 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7649 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7569 | * mixer widget | 7650 | * mixer widget |
7570 | * Note: PASD motherboards uses the Line In 2 as the input for | 7651 | * Note: PASD motherboards uses the Line In 2 as the input for |
7571 | * front panel mic (mic 2) | 7652 | * front panel mic (mic 2) |
7572 | */ | 7653 | */ |
7573 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7654 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7574 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7655 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7575 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7656 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7576 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7657 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7577 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7658 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7578 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7659 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7579 | 7660 | ||
7580 | /* | 7661 | /* |
7581 | * Set up output mixers (0x0c - 0x0f) | 7662 | * Set up output mixers (0x0c - 0x0f) |
@@ -7626,19 +7707,19 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = { | |||
7626 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7707 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7627 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7708 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7628 | 7709 | ||
7629 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7710 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7630 | * mixer widget | 7711 | * mixer widget |
7631 | * Note: PASD motherboards uses the Line In 2 as the input for | 7712 | * Note: PASD motherboards uses the Line In 2 as the input for |
7632 | * front panel mic (mic 2) | 7713 | * front panel mic (mic 2) |
7633 | */ | 7714 | */ |
7634 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7715 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7635 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7716 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7636 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7717 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7637 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7718 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7638 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7719 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7639 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7720 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7640 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 7721 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, |
7641 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 7722 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
7642 | 7723 | ||
7643 | /* | 7724 | /* |
7644 | * Set up output mixers (0x0c - 0x0e) | 7725 | * Set up output mixers (0x0c - 0x0e) |
@@ -7713,20 +7794,20 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { | |||
7713 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7794 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7714 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7795 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7715 | 7796 | ||
7716 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7797 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7717 | * mixer widget | 7798 | * mixer widget |
7718 | * Note: PASD motherboards uses the Line In 2 as the input for front | 7799 | * Note: PASD motherboards uses the Line In 2 as the input for front |
7719 | * panel mic (mic 2) | 7800 | * panel mic (mic 2) |
7720 | */ | 7801 | */ |
7721 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7802 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7722 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7803 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7723 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7804 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7724 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7805 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7725 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7806 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7726 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7807 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7727 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 7808 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, |
7728 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 7809 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
7729 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 7810 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
7730 | /* | 7811 | /* |
7731 | * Set up output mixers (0x0c - 0x0e) | 7812 | * Set up output mixers (0x0c - 0x0e) |
7732 | */ | 7813 | */ |
@@ -7796,6 +7877,10 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { | |||
7796 | { } | 7877 | { } |
7797 | }; | 7878 | }; |
7798 | 7879 | ||
7880 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
7881 | #define alc262_loopbacks alc880_loopbacks | ||
7882 | #endif | ||
7883 | |||
7799 | /* pcm configuration: identiacal with ALC880 */ | 7884 | /* pcm configuration: identiacal with ALC880 */ |
7800 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback | 7885 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback |
7801 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture | 7886 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture |
@@ -8098,6 +8183,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
8098 | codec->patch_ops = alc_patch_ops; | 8183 | codec->patch_ops = alc_patch_ops; |
8099 | if (board_config == ALC262_AUTO) | 8184 | if (board_config == ALC262_AUTO) |
8100 | spec->init_hook = alc262_auto_init; | 8185 | spec->init_hook = alc262_auto_init; |
8186 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
8187 | if (!spec->loopback.amplist) | ||
8188 | spec->loopback.amplist = alc262_loopbacks; | ||
8189 | #endif | ||
8101 | 8190 | ||
8102 | return 0; | 8191 | return 0; |
8103 | } | 8192 | } |
@@ -8507,6 +8596,10 @@ static void alc268_auto_init(struct hda_codec *codec) | |||
8507 | alc268_auto_init_analog_input(codec); | 8596 | alc268_auto_init_analog_input(codec); |
8508 | } | 8597 | } |
8509 | 8598 | ||
8599 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
8600 | #define alc883_loopbacks alc880_loopbacks | ||
8601 | #endif | ||
8602 | |||
8510 | /* | 8603 | /* |
8511 | * configuration and preset | 8604 | * configuration and preset |
8512 | */ | 8605 | */ |
@@ -9556,6 +9649,16 @@ static void alc861_auto_init(struct hda_codec *codec) | |||
9556 | alc861_auto_init_analog_input(codec); | 9649 | alc861_auto_init_analog_input(codec); |
9557 | } | 9650 | } |
9558 | 9651 | ||
9652 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
9653 | static struct hda_amp_list alc861_loopbacks[] = { | ||
9654 | { 0x15, HDA_INPUT, 0 }, | ||
9655 | { 0x15, HDA_INPUT, 1 }, | ||
9656 | { 0x15, HDA_INPUT, 2 }, | ||
9657 | { 0x15, HDA_INPUT, 3 }, | ||
9658 | { } /* end */ | ||
9659 | }; | ||
9660 | #endif | ||
9661 | |||
9559 | 9662 | ||
9560 | /* | 9663 | /* |
9561 | * configuration and preset | 9664 | * configuration and preset |
@@ -9753,6 +9856,10 @@ static int patch_alc861(struct hda_codec *codec) | |||
9753 | codec->patch_ops = alc_patch_ops; | 9856 | codec->patch_ops = alc_patch_ops; |
9754 | if (board_config == ALC861_AUTO) | 9857 | if (board_config == ALC861_AUTO) |
9755 | spec->init_hook = alc861_auto_init; | 9858 | spec->init_hook = alc861_auto_init; |
9859 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
9860 | if (!spec->loopback.amplist) | ||
9861 | spec->loopback.amplist = alc861_loopbacks; | ||
9862 | #endif | ||
9756 | 9863 | ||
9757 | return 0; | 9864 | return 0; |
9758 | } | 9865 | } |
@@ -10035,11 +10142,11 @@ static struct hda_verb alc861vd_volume_init_verbs[] = { | |||
10035 | * the analog-loopback mixer widget | 10142 | * the analog-loopback mixer widget |
10036 | */ | 10143 | */ |
10037 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 10144 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
10038 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 10145 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
10039 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 10146 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
10040 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 10147 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
10041 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 10148 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
10042 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 10149 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
10043 | 10150 | ||
10044 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ | 10151 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ |
10045 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 10152 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -10266,6 +10373,10 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
10266 | alc861vd_dallas_automute(codec); | 10373 | alc861vd_dallas_automute(codec); |
10267 | } | 10374 | } |
10268 | 10375 | ||
10376 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
10377 | #define alc861vd_loopbacks alc880_loopbacks | ||
10378 | #endif | ||
10379 | |||
10269 | /* pcm configuration: identiacal with ALC880 */ | 10380 | /* pcm configuration: identiacal with ALC880 */ |
10270 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback | 10381 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback |
10271 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture | 10382 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture |
@@ -10688,6 +10799,10 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
10688 | 10799 | ||
10689 | if (board_config == ALC861VD_AUTO) | 10800 | if (board_config == ALC861VD_AUTO) |
10690 | spec->init_hook = alc861vd_auto_init; | 10801 | spec->init_hook = alc861vd_auto_init; |
10802 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
10803 | if (!spec->loopback.amplist) | ||
10804 | spec->loopback.amplist = alc861vd_loopbacks; | ||
10805 | #endif | ||
10691 | 10806 | ||
10692 | return 0; | 10807 | return 0; |
10693 | } | 10808 | } |
@@ -10968,11 +11083,11 @@ static struct hda_verb alc662_init_verbs[] = { | |||
10968 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 11083 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
10969 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 11084 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
10970 | 11085 | ||
10971 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11086 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
10972 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11087 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
10973 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11088 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
10974 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 11089 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
10975 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11090 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
10976 | 11091 | ||
10977 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11092 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
10978 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11093 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -11041,11 +11156,11 @@ static struct hda_verb alc662_auto_init_verbs[] = { | |||
11041 | * panel mic (mic 2) | 11156 | * panel mic (mic 2) |
11042 | */ | 11157 | */ |
11043 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 11158 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
11044 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11159 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
11045 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11160 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
11046 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11161 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
11047 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 11162 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
11048 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11163 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
11049 | 11164 | ||
11050 | /* | 11165 | /* |
11051 | * Set up output mixers (0x0c - 0x0f) | 11166 | * Set up output mixers (0x0c - 0x0f) |
@@ -11132,6 +11247,10 @@ static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, | |||
11132 | alc662_lenovo_101e_ispeaker_automute(codec); | 11247 | alc662_lenovo_101e_ispeaker_automute(codec); |
11133 | } | 11248 | } |
11134 | 11249 | ||
11250 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
11251 | #define alc662_loopbacks alc880_loopbacks | ||
11252 | #endif | ||
11253 | |||
11135 | 11254 | ||
11136 | /* pcm configuration: identiacal with ALC880 */ | 11255 | /* pcm configuration: identiacal with ALC880 */ |
11137 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback | 11256 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback |
@@ -11534,6 +11653,10 @@ static int patch_alc662(struct hda_codec *codec) | |||
11534 | codec->patch_ops = alc_patch_ops; | 11653 | codec->patch_ops = alc_patch_ops; |
11535 | if (board_config == ALC662_AUTO) | 11654 | if (board_config == ALC662_AUTO) |
11536 | spec->init_hook = alc662_auto_init; | 11655 | spec->init_hook = alc662_auto_init; |
11656 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
11657 | if (!spec->loopback.amplist) | ||
11658 | spec->loopback.amplist = alc662_loopbacks; | ||
11659 | #endif | ||
11537 | 11660 | ||
11538 | return 0; | 11661 | return 0; |
11539 | } | 11662 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index bf5d91b63d1..4a981399abd 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -1946,7 +1946,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1946 | } | 1946 | } |
1947 | } | 1947 | } |
1948 | 1948 | ||
1949 | #ifdef CONFIG_PM | 1949 | #ifdef SND_HDA_NEEDS_RESUME |
1950 | static int stac92xx_resume(struct hda_codec *codec) | 1950 | static int stac92xx_resume(struct hda_codec *codec) |
1951 | { | 1951 | { |
1952 | stac92xx_set_config_regs(codec); | 1952 | stac92xx_set_config_regs(codec); |
@@ -1963,7 +1963,7 @@ static struct hda_codec_ops stac92xx_patch_ops = { | |||
1963 | .init = stac92xx_init, | 1963 | .init = stac92xx_init, |
1964 | .free = stac92xx_free, | 1964 | .free = stac92xx_free, |
1965 | .unsol_event = stac92xx_unsol_event, | 1965 | .unsol_event = stac92xx_unsol_event, |
1966 | #ifdef CONFIG_PM | 1966 | #ifdef SND_HDA_NEEDS_RESUME |
1967 | .resume = stac92xx_resume, | 1967 | .resume = stac92xx_resume, |
1968 | #endif | 1968 | #endif |
1969 | }; | 1969 | }; |
@@ -2460,7 +2460,7 @@ static struct hda_codec_ops stac9872_patch_ops = { | |||
2460 | .build_pcms = stac92xx_build_pcms, | 2460 | .build_pcms = stac92xx_build_pcms, |
2461 | .init = stac92xx_init, | 2461 | .init = stac92xx_init, |
2462 | .free = stac92xx_free, | 2462 | .free = stac92xx_free, |
2463 | #ifdef CONFIG_PM | 2463 | #ifdef SND_HDA_NEEDS_RESUME |
2464 | .resume = stac92xx_resume, | 2464 | .resume = stac92xx_resume, |
2465 | #endif | 2465 | #endif |
2466 | }; | 2466 | }; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 6c734f07e5b..33b5e1ffa81 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -115,6 +115,10 @@ struct via_spec { | |||
115 | struct snd_kcontrol_new *kctl_alloc; | 115 | struct snd_kcontrol_new *kctl_alloc; |
116 | struct hda_input_mux private_imux; | 116 | struct hda_input_mux private_imux; |
117 | hda_nid_t private_dac_nids[4]; | 117 | hda_nid_t private_dac_nids[4]; |
118 | |||
119 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
120 | struct hda_loopback_check loopback; | ||
121 | #endif | ||
118 | }; | 122 | }; |
119 | 123 | ||
120 | static hda_nid_t vt1708_adc_nids[2] = { | 124 | static hda_nid_t vt1708_adc_nids[2] = { |
@@ -305,15 +309,15 @@ static struct hda_verb vt1708_volume_init_verbs[] = { | |||
305 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 309 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
306 | 310 | ||
307 | 311 | ||
308 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 312 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
309 | * mixer widget | 313 | * mixer widget |
310 | */ | 314 | */ |
311 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 315 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
312 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 316 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* master */ |
313 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 317 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
314 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 318 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
315 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 319 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
316 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 320 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
317 | 321 | ||
318 | /* | 322 | /* |
319 | * Set up output mixers (0x19 - 0x1b) | 323 | * Set up output mixers (0x19 - 0x1b) |
@@ -543,6 +547,14 @@ static int via_init(struct hda_codec *codec) | |||
543 | return 0; | 547 | return 0; |
544 | } | 548 | } |
545 | 549 | ||
550 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
551 | static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
552 | { | ||
553 | struct via_spec *spec = codec->spec; | ||
554 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
555 | } | ||
556 | #endif | ||
557 | |||
546 | /* | 558 | /* |
547 | */ | 559 | */ |
548 | static struct hda_codec_ops via_patch_ops = { | 560 | static struct hda_codec_ops via_patch_ops = { |
@@ -550,6 +562,9 @@ static struct hda_codec_ops via_patch_ops = { | |||
550 | .build_pcms = via_build_pcms, | 562 | .build_pcms = via_build_pcms, |
551 | .init = via_init, | 563 | .init = via_init, |
552 | .free = via_free, | 564 | .free = via_free, |
565 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
566 | .check_power_status = via_check_power_status, | ||
567 | #endif | ||
553 | }; | 568 | }; |
554 | 569 | ||
555 | /* fill in the dac_nids table from the parsed pin configuration */ | 570 | /* fill in the dac_nids table from the parsed pin configuration */ |
@@ -738,6 +753,16 @@ static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, | |||
738 | return 0; | 753 | return 0; |
739 | } | 754 | } |
740 | 755 | ||
756 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
757 | static struct hda_amp_list vt1708_loopbacks[] = { | ||
758 | { 0x17, HDA_INPUT, 1 }, | ||
759 | { 0x17, HDA_INPUT, 2 }, | ||
760 | { 0x17, HDA_INPUT, 3 }, | ||
761 | { 0x17, HDA_INPUT, 4 }, | ||
762 | { } /* end */ | ||
763 | }; | ||
764 | #endif | ||
765 | |||
741 | static int vt1708_parse_auto_config(struct hda_codec *codec) | 766 | static int vt1708_parse_auto_config(struct hda_codec *codec) |
742 | { | 767 | { |
743 | struct via_spec *spec = codec->spec; | 768 | struct via_spec *spec = codec->spec; |
@@ -831,6 +856,9 @@ static int patch_vt1708(struct hda_codec *codec) | |||
831 | codec->patch_ops = via_patch_ops; | 856 | codec->patch_ops = via_patch_ops; |
832 | 857 | ||
833 | codec->patch_ops.init = via_auto_init; | 858 | codec->patch_ops.init = via_auto_init; |
859 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
860 | spec->loopback.amplist = vt1708_loopbacks; | ||
861 | #endif | ||
834 | 862 | ||
835 | return 0; | 863 | return 0; |
836 | } | 864 | } |
@@ -871,15 +899,15 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = { | |||
871 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 899 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
872 | 900 | ||
873 | 901 | ||
874 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 902 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
875 | * mixer widget | 903 | * mixer widget |
876 | */ | 904 | */ |
877 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 905 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
878 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 906 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* unmute master */ |
879 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 907 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
880 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 908 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
881 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 909 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
882 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 910 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
883 | 911 | ||
884 | /* | 912 | /* |
885 | * Set up output selector (0x1a, 0x1b, 0x29) | 913 | * Set up output selector (0x1a, 0x1b, 0x29) |
@@ -1227,6 +1255,16 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1227 | return 1; | 1255 | return 1; |
1228 | } | 1256 | } |
1229 | 1257 | ||
1258 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1259 | static struct hda_amp_list vt1709_loopbacks[] = { | ||
1260 | { 0x18, HDA_INPUT, 1 }, | ||
1261 | { 0x18, HDA_INPUT, 2 }, | ||
1262 | { 0x18, HDA_INPUT, 3 }, | ||
1263 | { 0x18, HDA_INPUT, 4 }, | ||
1264 | { } /* end */ | ||
1265 | }; | ||
1266 | #endif | ||
1267 | |||
1230 | static int patch_vt1709_10ch(struct hda_codec *codec) | 1268 | static int patch_vt1709_10ch(struct hda_codec *codec) |
1231 | { | 1269 | { |
1232 | struct via_spec *spec; | 1270 | struct via_spec *spec; |
@@ -1269,6 +1307,9 @@ static int patch_vt1709_10ch(struct hda_codec *codec) | |||
1269 | codec->patch_ops = via_patch_ops; | 1307 | codec->patch_ops = via_patch_ops; |
1270 | 1308 | ||
1271 | codec->patch_ops.init = via_auto_init; | 1309 | codec->patch_ops.init = via_auto_init; |
1310 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1311 | spec->loopback.amplist = vt1709_loopbacks; | ||
1312 | #endif | ||
1272 | 1313 | ||
1273 | return 0; | 1314 | return 0; |
1274 | } | 1315 | } |
@@ -1359,6 +1400,9 @@ static int patch_vt1709_6ch(struct hda_codec *codec) | |||
1359 | codec->patch_ops = via_patch_ops; | 1400 | codec->patch_ops = via_patch_ops; |
1360 | 1401 | ||
1361 | codec->patch_ops.init = via_auto_init; | 1402 | codec->patch_ops.init = via_auto_init; |
1403 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1404 | spec->loopback.amplist = vt1709_loopbacks; | ||
1405 | #endif | ||
1362 | 1406 | ||
1363 | return 0; | 1407 | return 0; |
1364 | } | 1408 | } |