aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_codec.c215
-rw-r--r--sound/pci/hda/hda_local.h10
-rw-r--r--sound/pci/hda/patch_hdmi.c2
-rw-r--r--sound/pci/hda/patch_realtek.c4
4 files changed, 32 insertions, 199 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 39b5660653f0..52962f697825 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1543,139 +1543,6 @@ int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
1543} 1543}
1544EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps); 1544EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps);
1545 1545
1546/* read or sync the hash value with the current value;
1547 * call within hash_mutex
1548 */
1549static struct hda_amp_info *
1550update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
1551 int direction, int index, bool init_only)
1552{
1553 struct hda_amp_info *info;
1554 unsigned int parm, val = 0;
1555 bool val_read = false;
1556
1557 retry:
1558 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
1559 if (!info)
1560 return NULL;
1561 if (!(info->head.val & INFO_AMP_VOL(ch))) {
1562 if (!val_read) {
1563 mutex_unlock(&codec->hash_mutex);
1564 parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
1565 parm |= direction == HDA_OUTPUT ?
1566 AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
1567 parm |= index;
1568 val = snd_hda_codec_read(codec, nid, 0,
1569 AC_VERB_GET_AMP_GAIN_MUTE, parm);
1570 val &= 0xff;
1571 val_read = true;
1572 mutex_lock(&codec->hash_mutex);
1573 goto retry;
1574 }
1575 info->vol[ch] = val;
1576 info->head.val |= INFO_AMP_VOL(ch);
1577 } else if (init_only)
1578 return NULL;
1579 return info;
1580}
1581
1582/*
1583 * write the current volume in info to the h/w
1584 */
1585static void put_vol_mute(struct hda_codec *codec, unsigned int amp_caps,
1586 hda_nid_t nid, int ch, int direction, int index,
1587 int val)
1588{
1589 u32 parm;
1590
1591 parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
1592 parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
1593 parm |= index << AC_AMP_SET_INDEX_SHIFT;
1594 if ((val & HDA_AMP_MUTE) && !(amp_caps & AC_AMPCAP_MUTE) &&
1595 (amp_caps & AC_AMPCAP_MIN_MUTE))
1596 ; /* set the zero value as a fake mute */
1597 else
1598 parm |= val;
1599 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
1600}
1601
1602/**
1603 * snd_hda_codec_amp_read - Read AMP value
1604 * @codec: HD-audio codec
1605 * @nid: NID to read the AMP value
1606 * @ch: channel (left=0 or right=1)
1607 * @direction: #HDA_INPUT or #HDA_OUTPUT
1608 * @index: the index value (only for input direction)
1609 *
1610 * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
1611 */
1612int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
1613 int direction, int index)
1614{
1615 struct hda_amp_info *info;
1616 unsigned int val = 0;
1617
1618 mutex_lock(&codec->hash_mutex);
1619 info = update_amp_hash(codec, nid, ch, direction, index, false);
1620 if (info)
1621 val = info->vol[ch];
1622 mutex_unlock(&codec->hash_mutex);
1623 return val;
1624}
1625EXPORT_SYMBOL_GPL(snd_hda_codec_amp_read);
1626
1627static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1628 int direction, int idx, int mask, int val,
1629 bool init_only, bool cache_only)
1630{
1631 struct hda_amp_info *info;
1632 unsigned int caps;
1633
1634 if (snd_BUG_ON(mask & ~0xff))
1635 mask &= 0xff;
1636 val &= mask;
1637
1638 mutex_lock(&codec->hash_mutex);
1639 info = update_amp_hash(codec, nid, ch, direction, idx, init_only);
1640 if (!info) {
1641 mutex_unlock(&codec->hash_mutex);
1642 return 0;
1643 }
1644 val |= info->vol[ch] & ~mask;
1645 if (info->vol[ch] == val) {
1646 mutex_unlock(&codec->hash_mutex);
1647 return 0;
1648 }
1649 info->vol[ch] = val;
1650 info->head.dirty |= cache_only;
1651 caps = info->amp_caps;
1652 mutex_unlock(&codec->hash_mutex);
1653 if (!cache_only)
1654 put_vol_mute(codec, caps, nid, ch, direction, idx, val);
1655 return 1;
1656}
1657
1658/**
1659 * snd_hda_codec_amp_update - update the AMP value
1660 * @codec: HD-audio codec
1661 * @nid: NID to read the AMP value
1662 * @ch: channel (left=0 or right=1)
1663 * @direction: #HDA_INPUT or #HDA_OUTPUT
1664 * @idx: the index value (only for input direction)
1665 * @mask: bit mask to set
1666 * @val: the bits value to set
1667 *
1668 * Update the AMP value with a bit mask.
1669 * Returns 0 if the value is unchanged, 1 if changed.
1670 */
1671int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1672 int direction, int idx, int mask, int val)
1673{
1674 return codec_amp_update(codec, nid, ch, direction, idx, mask, val,
1675 false, codec->cached_write);
1676}
1677EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
1678
1679/** 1546/**
1680 * snd_hda_codec_amp_stereo - update the AMP stereo values 1547 * snd_hda_codec_amp_stereo - update the AMP stereo values
1681 * @codec: HD-audio codec 1548 * @codec: HD-audio codec
@@ -1719,8 +1586,16 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
1719int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, 1586int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
1720 int dir, int idx, int mask, int val) 1587 int dir, int idx, int mask, int val)
1721{ 1588{
1722 return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true, 1589 int orig;
1723 codec->cached_write); 1590
1591 if (!codec->core.regmap)
1592 return -EINVAL;
1593 regcache_cache_only(codec->core.regmap, true);
1594 orig = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1595 regcache_cache_only(codec->core.regmap, false);
1596 if (orig >= 0)
1597 return 0;
1598 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val);
1724} 1599}
1725EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init); 1600EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
1726 1601
@@ -1749,49 +1624,6 @@ int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
1749} 1624}
1750EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo); 1625EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo);
1751 1626
1752/**
1753 * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
1754 * @codec: HD-audio codec
1755 *
1756 * Resume the all amp commands from the cache.
1757 */
1758void snd_hda_codec_resume_amp(struct hda_codec *codec)
1759{
1760 int i;
1761
1762 mutex_lock(&codec->hash_mutex);
1763 codec->cached_write = 0;
1764 for (i = 0; i < codec->amp_cache.buf.used; i++) {
1765 struct hda_amp_info *buffer;
1766 u32 key;
1767 hda_nid_t nid;
1768 unsigned int idx, dir, ch;
1769 struct hda_amp_info info;
1770
1771 buffer = snd_array_elem(&codec->amp_cache.buf, i);
1772 if (!buffer->head.dirty)
1773 continue;
1774 buffer->head.dirty = 0;
1775 info = *buffer;
1776 key = info.head.key;
1777 if (!key)
1778 continue;
1779 nid = key & 0xff;
1780 idx = (key >> 16) & 0xff;
1781 dir = (key >> 24) & 0xff;
1782 for (ch = 0; ch < 2; ch++) {
1783 if (!(info.head.val & INFO_AMP_VOL(ch)))
1784 continue;
1785 mutex_unlock(&codec->hash_mutex);
1786 put_vol_mute(codec, info.amp_caps, nid, ch, dir, idx,
1787 info.vol[ch]);
1788 mutex_lock(&codec->hash_mutex);
1789 }
1790 }
1791 mutex_unlock(&codec->hash_mutex);
1792}
1793EXPORT_SYMBOL_GPL(snd_hda_codec_resume_amp);
1794
1795static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, 1627static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
1796 unsigned int ofs) 1628 unsigned int ofs)
1797{ 1629{
@@ -1862,8 +1694,8 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1862 maxval = get_amp_max_value(codec, nid, dir, 0); 1694 maxval = get_amp_max_value(codec, nid, dir, 0);
1863 if (val > maxval) 1695 if (val > maxval)
1864 val = maxval; 1696 val = maxval;
1865 return codec_amp_update(codec, nid, ch, dir, idx, HDA_AMP_VOLMASK, val, 1697 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1866 false, !hda_codec_is_power_on(codec)); 1698 HDA_AMP_VOLMASK, val);
1867} 1699}
1868 1700
1869/** 1701/**
@@ -2546,17 +2378,15 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
2546 int change = 0; 2378 int change = 0;
2547 2379
2548 if (chs & 1) { 2380 if (chs & 1) {
2549 change = codec_amp_update(codec, nid, 0, dir, idx, 2381 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
2550 HDA_AMP_MUTE, 2382 HDA_AMP_MUTE,
2551 *valp ? 0 : HDA_AMP_MUTE, false, 2383 *valp ? 0 : HDA_AMP_MUTE);
2552 !hda_codec_is_power_on(codec));
2553 valp++; 2384 valp++;
2554 } 2385 }
2555 if (chs & 2) 2386 if (chs & 2)
2556 change |= codec_amp_update(codec, nid, 1, dir, idx, 2387 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
2557 HDA_AMP_MUTE, 2388 HDA_AMP_MUTE,
2558 *valp ? 0 : HDA_AMP_MUTE, false, 2389 *valp ? 0 : HDA_AMP_MUTE);
2559 !hda_codec_is_power_on(codec));
2560 hda_call_check_power_status(codec, nid); 2390 hda_call_check_power_status(codec, nid);
2561 return change; 2391 return change;
2562} 2392}
@@ -3417,7 +3247,8 @@ EXPORT_SYMBOL_GPL(snd_hda_sequence_write_cache);
3417 */ 3247 */
3418void snd_hda_codec_flush_cache(struct hda_codec *codec) 3248void snd_hda_codec_flush_cache(struct hda_codec *codec)
3419{ 3249{
3420 snd_hda_codec_resume_amp(codec); 3250 if (codec->core.regmap)
3251 regcache_sync(codec->core.regmap);
3421 snd_hda_codec_resume_cache(codec); 3252 snd_hda_codec_resume_cache(codec);
3422} 3253}
3423EXPORT_SYMBOL_GPL(snd_hda_codec_flush_cache); 3254EXPORT_SYMBOL_GPL(snd_hda_codec_flush_cache);
@@ -3645,6 +3476,9 @@ static void hda_call_codec_resume(struct hda_codec *codec)
3645{ 3476{
3646 atomic_inc(&codec->core.in_pm); 3477 atomic_inc(&codec->core.in_pm);
3647 3478
3479 if (codec->core.regmap)
3480 regcache_mark_dirty(codec->core.regmap);
3481
3648 hda_mark_cmd_cache_dirty(codec); 3482 hda_mark_cmd_cache_dirty(codec);
3649 3483
3650 codec->power_jiffies = jiffies; 3484 codec->power_jiffies = jiffies;
@@ -3658,7 +3492,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
3658 else { 3492 else {
3659 if (codec->patch_ops.init) 3493 if (codec->patch_ops.init)
3660 codec->patch_ops.init(codec); 3494 codec->patch_ops.init(codec);
3661 snd_hda_codec_resume_amp(codec); 3495 if (codec->core.regmap)
3496 regcache_sync(codec->core.regmap);
3662 snd_hda_codec_resume_cache(codec); 3497 snd_hda_codec_resume_cache(codec);
3663 } 3498 }
3664 3499
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 8a83775e0e27..7023eeee8b9d 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -127,18 +127,16 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
127 struct snd_ctl_elem_value *ucontrol); 127 struct snd_ctl_elem_value *ucontrol);
128#endif 128#endif
129/* lowlevel accessor with caching; use carefully */ 129/* lowlevel accessor with caching; use carefully */
130int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, 130#define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \
131 int direction, int index); 131 snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx)
132int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, 132#define snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val) \
133 int direction, int idx, int mask, int val); 133 snd_hdac_regmap_update_amp(&(codec)->core, nid, ch, dir, idx, mask, val)
134int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, 134int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
135 int dir, int idx, int mask, int val); 135 int dir, int idx, int mask, int val);
136int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, 136int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
137 int direction, int idx, int mask, int val); 137 int direction, int idx, int mask, int val);
138int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid, 138int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
139 int dir, int idx, int mask, int val); 139 int dir, int idx, int mask, int val);
140void snd_hda_codec_resume_amp(struct hda_codec *codec);
141
142void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, 140void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
143 unsigned int *tlv); 141 unsigned int *tlv);
144struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, 142struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 35d92a8a99ce..04c5ab20eb76 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -2211,7 +2211,7 @@ static int generic_hdmi_resume(struct hda_codec *codec)
2211 int pin_idx; 2211 int pin_idx;
2212 2212
2213 codec->patch_ops.init(codec); 2213 codec->patch_ops.init(codec);
2214 snd_hda_codec_resume_amp(codec); 2214 regcache_sync(codec->core.regmap);
2215 snd_hda_codec_resume_cache(codec); 2215 snd_hda_codec_resume_cache(codec);
2216 2216
2217 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { 2217 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index eee4532ab5f6..a440e539230f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -799,7 +799,7 @@ static int alc_resume(struct hda_codec *codec)
799 if (!spec->no_depop_delay) 799 if (!spec->no_depop_delay)
800 msleep(150); /* to avoid pop noise */ 800 msleep(150); /* to avoid pop noise */
801 codec->patch_ops.init(codec); 801 codec->patch_ops.init(codec);
802 snd_hda_codec_resume_amp(codec); 802 regcache_sync(codec->core.regmap);
803 snd_hda_codec_resume_cache(codec); 803 snd_hda_codec_resume_cache(codec);
804 hda_call_check_power_status(codec, 0x01); 804 hda_call_check_power_status(codec, 0x01);
805 return 0; 805 return 0;
@@ -3058,7 +3058,7 @@ static int alc269_resume(struct hda_codec *codec)
3058 msleep(200); 3058 msleep(200);
3059 } 3059 }
3060 3060
3061 snd_hda_codec_resume_amp(codec); 3061 regcache_sync(codec->core.regmap);
3062 snd_hda_codec_resume_cache(codec); 3062 snd_hda_codec_resume_cache(codec);
3063 hda_call_check_power_status(codec, 0x01); 3063 hda_call_check_power_status(codec, 0x01);
3064 3064