aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-08-10 11:21:45 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:58:46 -0400
commitcb53c626e1145edf1d619bc4953f6293d3a77ace (patch)
tree715c2ef3d56a5ac7c79498800e888f562c1aa961 /sound
parentcca3b3718ca96dca51daf1129ac03003bcede751 (diff)
[ALSA] hda-intel - Add POWER_SAVE option
Added CONFIG_SND_HDA_POWER_SAVE kconfig. It's an experimental option to achieve an aggressive power-saving. With this option, the driver will turn on/off the power of each codec and controller chip dynamically on demand. The patch introduces a new module option 'power_save'. It specifies the second of time-out for automatic power-down. As default, it's 10 seconds. Setting 0 means to suppress the power-saving feature. The codec may have analog-input loopbacks, which are usually represented by mixer elements such as 'Mic Playback Switch' or 'CD Playback Switch'. When these are on, we cannot turn off the mixer and the codec chip has to be kept on. For bookkeeping these states, a new codec-callback is introduced. For the bus-controller side, a new callback pm_notify is introduced, which can be used to turn on/off the contoller appropriately. Note that this power-saving might cause slight click-noise at power-on/off. Also, it might take some time to wake up the codec, and might even drop some tones at the very beginning. This seems to be the side-effect of turning off the controller chip. This turn-off of the controller can be disabled by undefining HDA_POWER_SAVE_RESET_CONTOLLER in hda_intel.c. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/Kconfig8
-rw-r--r--sound/pci/hda/hda_codec.c239
-rw-r--r--sound/pci/hda/hda_codec.h32
-rw-r--r--sound/pci/hda/hda_generic.c55
-rw-r--r--sound/pci/hda/hda_intel.c158
-rw-r--r--sound/pci/hda/hda_local.h25
-rw-r--r--sound/pci/hda/hda_proc.c3
-rw-r--r--sound/pci/hda/patch_analog.c91
-rw-r--r--sound/pci/hda/patch_realtek.c307
-rw-r--r--sound/pci/hda/patch_sigmatel.c6
-rw-r--r--sound/pci/hda/patch_via.c68
11 files changed, 800 insertions, 192 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index ff7a689c229e..9554140f0b04 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
584config 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
584config SND_HDSP 592config 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 043529308676..9a3b72824f87 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 */
38static int power_save = 10;
39module_param(power_save, int, 0644);
40MODULE_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
71static void hda_power_work(struct work_struct *work);
72static void hda_keep_power_on(struct hda_codec *codec);
73#else
74static 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 */
860void snd_hda_codec_resume_amp(struct hda_codec *codec) 890void 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,
1580static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, 1619static 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 */
1656static 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 */
1671static 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 */
2079int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) 2160int 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
2186static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2187 unsigned int power_state);
2188
2189static 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
2203static void hda_keep_power_on(struct hda_codec *codec)
2204{
2205 codec->power_count++;
2206 codec->power_on = 1;
2207}
2208
2209void 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
2222void 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
2232int 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 */
2626int snd_hda_resume(struct hda_bus *bus) 2789int 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 92938d2a52e2..1ffffaa3a30d 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,
617int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); 634int 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
621int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, 638int 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);
623void snd_hda_sequence_write_cache(struct hda_codec *codec, 640void 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);
662int snd_hda_resume(struct hda_bus *bus); 679int 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
686void snd_hda_power_up(struct hda_codec *codec);
687void snd_hda_power_down(struct hda_codec *codec);
688#else
689static inline void snd_hda_power_up(struct hda_codec *codec) {}
690static 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 91cd9b9ea5d1..819c804a579f 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
693static 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 */
688static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, 716static 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
1058static 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 ebb442dcc027..7be3a9b55330 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 "
75module_param(enable_msi, int, 0); 75module_param(enable_msi, int, 0);
76MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); 76MODULE_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 */
80static int enable; 81static 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
683static void azx_power_notify(struct hda_codec *codec);
684#endif
668 685
669/* reset codec link */ 686/* reset codec link */
670static int azx_reset(struct azx *chip) 687static 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 */
795static void azx_init_chip(struct azx *chip) 812static 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, &reg);
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 */
839static 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
850static 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 &reg); 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, &reg); 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
1501static 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 */
1522static 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
1826static 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
1753static int __devinit azx_probe(struct pci_dev *pci, 1839static 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 35ea0cf37a27..a79d0ed5469c 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);
87int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, 87int 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
90void snd_hda_codec_resume_amp(struct hda_codec *codec); 90void 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 */
367int snd_hda_create_hwdep(struct hda_codec *codec); 367int snd_hda_create_hwdep(struct hda_codec *codec);
368 368
369/*
370 * power-management
371 */
372
373#ifdef CONFIG_SND_HDA_POWER_SAVE
374void snd_hda_schedule_power_save(struct hda_codec *codec);
375
376struct hda_amp_list {
377 hda_nid_t nid;
378 unsigned char dir;
379 unsigned char idx;
380};
381
382struct hda_loopback_check {
383 struct hda_amp_list *amplist;
384 int power_on;
385};
386
387int 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 ccd19180e541..e94944f34ffd 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 f9390a544ea4..53cfa0da4964 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
152static 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
755static 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
739static int patch_ad1986a(struct hda_codec *codec) 765static 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
977static 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
948static int patch_ad1983(struct hda_codec *codec) 984static 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
1134static 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
2160static 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
2872static 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
2806static int patch_ad1884(struct hda_codec *codec) 2881static 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
3290static 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 */
3212enum { 3300enum {
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 ebbabeb32930..b3d3916c8eca 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
1995static 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
2004static 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
2039static 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
4552static 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
9653static 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 bf5d91b63d15..4a981399abde 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
1950static int stac92xx_resume(struct hda_codec *codec) 1950static 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 6c734f07e5b5..33b5e1ffa817 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
120static hda_nid_t vt1708_adc_nids[2] = { 124static 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
551static 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 */
548static struct hda_codec_ops via_patch_ops = { 560static 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
757static 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
741static int vt1708_parse_auto_config(struct hda_codec *codec) 766static 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
1259static 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
1230static int patch_vt1709_10ch(struct hda_codec *codec) 1268static 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}