aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 ff7a689c229..9554140f0b0 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -581,6 +581,14 @@ config SND_HDA_GENERIC
581 Say Y here to enable the generic HD-audio codec parser 581 Say Y here to enable the generic HD-audio codec parser
582 in snd-hda-intel driver. 582 in snd-hda-intel driver.
583 583
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 04352930867..9a3b72824f8 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -33,6 +33,13 @@
33#include "hda_local.h" 33#include "hda_local.h"
34#include <sound/hda_hwdep.h> 34#include <sound/hda_hwdep.h>
35 35
36#ifdef CONFIG_SND_HDA_POWER_SAVE
37/* define this option here to hide as static */
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 92938d2a52e..1ffffaa3a30 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -26,6 +26,10 @@
26#include <sound/pcm.h> 26#include <sound/pcm.h>
27#include <sound/hwdep.h> 27#include <sound/hwdep.h>
28 28
29#if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE)
30#define SND_HDA_NEEDS_RESUME /* resume control code is required */
31#endif
32
29/* 33/*
30 * nodes 34 * nodes
31 */ 35 */
@@ -412,6 +416,10 @@ struct hda_bus_ops {
412 unsigned int (*get_response)(struct hda_codec *codec); 416 unsigned int (*get_response)(struct hda_codec *codec);
413 /* free the private data */ 417 /* free the private data */
414 void (*private_free)(struct hda_bus *); 418 void (*private_free)(struct hda_bus *);
419#ifdef CONFIG_SND_HDA_POWER_SAVE
420 /* notify power-up/down from codec to contoller */
421 void (*pm_notify)(struct hda_codec *codec);
422#endif
415}; 423};
416 424
417/* template to pass to the bus constructor */ 425/* template to pass to the bus constructor */
@@ -473,10 +481,13 @@ struct hda_codec_ops {
473 int (*init)(struct hda_codec *codec); 481 int (*init)(struct hda_codec *codec);
474 void (*free)(struct hda_codec *codec); 482 void (*free)(struct hda_codec *codec);
475 void (*unsol_event)(struct hda_codec *codec, unsigned int res); 483 void (*unsol_event)(struct hda_codec *codec, unsigned int res);
476#ifdef CONFIG_PM 484#ifdef SND_HDA_NEEDS_RESUME
477 int (*suspend)(struct hda_codec *codec, pm_message_t state); 485 int (*suspend)(struct hda_codec *codec, pm_message_t state);
478 int (*resume)(struct hda_codec *codec); 486 int (*resume)(struct hda_codec *codec);
479#endif 487#endif
488#ifdef CONFIG_SND_HDA_POWER_SAVE
489 int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
490#endif
480}; 491};
481 492
482/* record for amp information cache */ 493/* record for amp information cache */
@@ -573,6 +584,12 @@ struct hda_codec {
573 unsigned int spdif_in_enable; /* SPDIF input enable? */ 584 unsigned int spdif_in_enable; /* SPDIF input enable? */
574 585
575 struct snd_hwdep *hwdep; /* assigned hwdep device */ 586 struct snd_hwdep *hwdep; /* assigned hwdep device */
587
588#ifdef CONFIG_SND_HDA_POWER_SAVE
589 int power_on; /* current (global) power-state */
590 int power_count; /* current (global) power refcount */
591 struct delayed_work power_work; /* delayed task for powerdown */
592#endif
576}; 593};
577 594
578/* direction */ 595/* direction */
@@ -617,7 +634,7 @@ void snd_hda_sequence_write(struct hda_codec *codec,
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 91cd9b9ea5d..819c804a579 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -70,6 +70,13 @@ struct hda_gspec {
70 struct hda_pcm pcm_rec; /* PCM information */ 70 struct hda_pcm pcm_rec; /* PCM information */
71 71
72 struct list_head nid_list; /* list of widgets */ 72 struct list_head nid_list; /* list of widgets */
73
74#ifdef CONFIG_SND_HDA_POWER_SAVE
75#define MAX_LOOPBACK_AMPS 7
76 struct hda_loopback_check loopback;
77 int num_loopbacks;
78 struct hda_amp_list loopback_list[MAX_LOOPBACK_AMPS + 1];
79#endif
73}; 80};
74 81
75/* 82/*
@@ -682,11 +689,33 @@ static int parse_input(struct hda_codec *codec)
682 return 0; 689 return 0;
683} 690}
684 691
692#ifdef CONFIG_SND_HDA_POWER_SAVE
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 ebb442dcc02..7be3a9b5533 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -75,6 +75,7 @@ MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
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 35ea0cf37a2..a79d0ed5469 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -86,7 +86,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
86 int direction, int idx, int mask, int val); 86 int direction, int idx, int mask, int val);
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 ccd19180e54..e94944f34ff 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -262,6 +262,7 @@ static void print_codec_info(struct snd_info_entry *entry,
262 262
263 if (! codec->afg) 263 if (! codec->afg)
264 return; 264 return;
265 snd_hda_power_up(codec);
265 snd_iprintf(buffer, "Default PCM:\n"); 266 snd_iprintf(buffer, "Default PCM:\n");
266 print_pcm_caps(buffer, codec, codec->afg); 267 print_pcm_caps(buffer, codec, codec->afg);
267 snd_iprintf(buffer, "Default Amp-In caps: "); 268 snd_iprintf(buffer, "Default Amp-In caps: ");
@@ -272,6 +273,7 @@ static void print_codec_info(struct snd_info_entry *entry,
272 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); 273 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
273 if (! nid || nodes < 0) { 274 if (! nid || nodes < 0) {
274 snd_iprintf(buffer, "Invalid AFG subtree\n"); 275 snd_iprintf(buffer, "Invalid AFG subtree\n");
276 snd_hda_power_down(codec);
275 return; 277 return;
276 } 278 }
277 for (i = 0; i < nodes; i++, nid++) { 279 for (i = 0; i < nodes; i++, nid++) {
@@ -359,6 +361,7 @@ static void print_codec_info(struct snd_info_entry *entry,
359 snd_iprintf(buffer, "\n"); 361 snd_iprintf(buffer, "\n");
360 } 362 }
361 } 363 }
364 snd_hda_power_down(codec);
362} 365}
363 366
364/* 367/*
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index f9390a544ea..53cfa0da496 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -73,6 +73,10 @@ struct ad198x_spec {
73 struct snd_kcontrol_new *kctl_alloc; 73 struct snd_kcontrol_new *kctl_alloc;
74 struct hda_input_mux private_imux; 74 struct hda_input_mux private_imux;
75 hda_nid_t private_dac_nids[4]; 75 hda_nid_t private_dac_nids[4];
76
77#ifdef CONFIG_SND_HDA_POWER_SAVE
78 struct hda_loopback_check loopback;
79#endif
76}; 80};
77 81
78/* 82/*
@@ -144,6 +148,14 @@ static int ad198x_build_controls(struct hda_codec *codec)
144 return 0; 148 return 0;
145} 149}
146 150
151#ifdef CONFIG_SND_HDA_POWER_SAVE
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 ebbabeb3293..b3d3916c8ec 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -240,6 +240,10 @@ struct alc_spec {
240 /* for pin sensing */ 240 /* for pin sensing */
241 unsigned int sense_updated: 1; 241 unsigned int sense_updated: 1;
242 unsigned int jack_present: 1; 242 unsigned int jack_present: 1;
243
244#ifdef CONFIG_SND_HDA_POWER_SAVE
245 struct hda_loopback_check loopback;
246#endif
243}; 247};
244 248
245/* 249/*
@@ -264,6 +268,9 @@ struct alc_config_preset {
264 const struct hda_input_mux *input_mux; 268 const struct hda_input_mux *input_mux;
265 void (*unsol_event)(struct hda_codec *, unsigned int); 269 void (*unsol_event)(struct hda_codec *, unsigned int);
266 void (*init_hook)(struct hda_codec *); 270 void (*init_hook)(struct hda_codec *);
271#ifdef CONFIG_SND_HDA_POWER_SAVE
272 struct hda_amp_list *loopbacks;
273#endif
267}; 274};
268 275
269 276
@@ -621,6 +628,9 @@ static void setup_preset(struct alc_spec *spec,
621 628
622 spec->unsol_event = preset->unsol_event; 629 spec->unsol_event = preset->unsol_event;
623 spec->init_hook = preset->init_hook; 630 spec->init_hook = preset->init_hook;
631#ifdef CONFIG_SND_HDA_POWER_SAVE
632 spec->loopback.amplist = preset->loopbacks;
633#endif
624} 634}
625 635
626/* Enable GPIO mask and set output */ 636/* Enable GPIO mask and set output */
@@ -1287,11 +1297,13 @@ static struct hda_verb alc880_volume_init_verbs[] = {
1287 * panel mic (mic 2) 1297 * panel mic (mic 2)
1288 */ 1298 */
1289 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ 1299 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
1290 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1300 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1291 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1301 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1292 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 1302 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1293 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 1303 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1294 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 1304 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1305 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1306 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1295 1307
1296 /* 1308 /*
1297 * Set up output mixers (0x0c - 0x0f) 1309 * Set up output mixers (0x0c - 0x0f)
@@ -1836,8 +1848,8 @@ static struct hda_verb alc880_lg_init_verbs[] = {
1836 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 1848 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1837 /* mute all amp mixer inputs */ 1849 /* mute all amp mixer inputs */
1838 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, 1850 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
1839 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, 1851 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1840 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 1852 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1841 /* line-in to input */ 1853 /* line-in to input */
1842 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 1854 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1843 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1855 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -1939,7 +1951,7 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = {
1939 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1951 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1940 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1952 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1941 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 1953 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1942 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, 1954 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1943 /* speaker-out */ 1955 /* speaker-out */
1944 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 1956 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1945 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1957 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -1979,6 +1991,24 @@ static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
1979 alc880_lg_lw_automute(codec); 1991 alc880_lg_lw_automute(codec);
1980} 1992}
1981 1993
1994#ifdef CONFIG_SND_HDA_POWER_SAVE
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 bf5d91b63d1..4a981399abd 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1946,7 +1946,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
1946 } 1946 }
1947} 1947}
1948 1948
1949#ifdef CONFIG_PM 1949#ifdef SND_HDA_NEEDS_RESUME
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 6c734f07e5b..33b5e1ffa81 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -115,6 +115,10 @@ struct via_spec {
115 struct snd_kcontrol_new *kctl_alloc; 115 struct snd_kcontrol_new *kctl_alloc;
116 struct hda_input_mux private_imux; 116 struct hda_input_mux private_imux;
117 hda_nid_t private_dac_nids[4]; 117 hda_nid_t private_dac_nids[4];
118
119#ifdef CONFIG_SND_HDA_POWER_SAVE
120 struct hda_loopback_check loopback;
121#endif
118}; 122};
119 123
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}