Commit 280e57d5 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Introduce snd_hda_codec_amp_init*()

The new function snd_hda_codec_amp_init() (and the stereo variant)
initializes the amp value only once at the first access.  If the amp
was already initialized or updated, this won't do anything more.

It's useful for initializing the input amps that are in the part of
the path but never used.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c370dd6e
...@@ -1765,7 +1765,7 @@ EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps); ...@@ -1765,7 +1765,7 @@ EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
*/ */
static struct hda_amp_info * static struct hda_amp_info *
update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch, update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int index) int direction, int index, bool init_only)
{ {
struct hda_amp_info *info; struct hda_amp_info *info;
unsigned int parm, val = 0; unsigned int parm, val = 0;
...@@ -1791,7 +1791,8 @@ update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch, ...@@ -1791,7 +1791,8 @@ update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
} }
info->vol[ch] = val; info->vol[ch] = val;
info->head.val |= INFO_AMP_VOL(ch); info->head.val |= INFO_AMP_VOL(ch);
} } else if (init_only)
return NULL;
return info; return info;
} }
...@@ -1832,7 +1833,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, ...@@ -1832,7 +1833,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
unsigned int val = 0; unsigned int val = 0;
mutex_lock(&codec->hash_mutex); mutex_lock(&codec->hash_mutex);
info = update_amp_hash(codec, nid, ch, direction, index); info = update_amp_hash(codec, nid, ch, direction, index, false);
if (info) if (info)
val = info->vol[ch]; val = info->vol[ch];
mutex_unlock(&codec->hash_mutex); mutex_unlock(&codec->hash_mutex);
...@@ -1840,21 +1841,9 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, ...@@ -1840,21 +1841,9 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
} }
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read); EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
/** static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
* snd_hda_codec_amp_update - update the AMP value int direction, int idx, int mask, int val,
* @codec: HD-audio codec bool init_only)
* @nid: NID to read the AMP value
* @ch: channel (left=0 or right=1)
* @direction: #HDA_INPUT or #HDA_OUTPUT
* @idx: the index value (only for input direction)
* @mask: bit mask to set
* @val: the bits value to set
*
* Update the AMP value with a bit mask.
* Returns 0 if the value is unchanged, 1 if changed.
*/
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val)
{ {
struct hda_amp_info *info; struct hda_amp_info *info;
...@@ -1863,7 +1852,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, ...@@ -1863,7 +1852,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
val &= mask; val &= mask;
mutex_lock(&codec->hash_mutex); mutex_lock(&codec->hash_mutex);
info = update_amp_hash(codec, nid, ch, direction, idx); info = update_amp_hash(codec, nid, ch, direction, idx, init_only);
if (!info) { if (!info) {
mutex_unlock(&codec->hash_mutex); mutex_unlock(&codec->hash_mutex);
return 0; return 0;
...@@ -1881,6 +1870,25 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, ...@@ -1881,6 +1870,25 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
put_vol_mute(codec, info, nid, ch, direction, idx, val); put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1; return 1;
} }
/**
* snd_hda_codec_amp_update - update the AMP value
* @codec: HD-audio codec
* @nid: NID to read the AMP value
* @ch: channel (left=0 or right=1)
* @direction: #HDA_INPUT or #HDA_OUTPUT
* @idx: the index value (only for input direction)
* @mask: bit mask to set
* @val: the bits value to set
*
* Update the AMP value with a bit mask.
* Returns 0 if the value is unchanged, 1 if changed.
*/
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val)
{
return codec_amp_update(codec, nid, ch, direction, idx, mask, val, false);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update); EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
/** /**
...@@ -1909,6 +1917,31 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, ...@@ -1909,6 +1917,31 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
} }
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo); EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
/* Works like snd_hda_codec_amp_update() but it writes the value only at
* the first access. If the amp was already initialized / updated beforehand,
* this does nothing.
*/
int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
int dir, int idx, int mask, int val)
{
return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init);
int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, int mask, int val)
{
int ch, ret = 0;
if (snd_BUG_ON(mask & ~0xff))
mask &= 0xff;
for (ch = 0; ch < 2; ch++)
ret |= snd_hda_codec_amp_init(codec, nid, ch, dir,
idx, mask, val);
return ret;
}
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo);
/** /**
* snd_hda_codec_resume_amp - Resume all AMP commands from the cache * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
* @codec: HD-audio codec * @codec: HD-audio codec
......
...@@ -133,6 +133,10 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, ...@@ -133,6 +133,10 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val); int direction, int idx, int mask, int val);
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, int mask, int val); int dir, int idx, int mask, int val);
int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val);
int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, int mask, int val);
void snd_hda_codec_resume_amp(struct hda_codec *codec); void snd_hda_codec_resume_amp(struct hda_codec *codec);
void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment