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: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2012-12-14 10:32:21 +01:00
parent c370dd6e9f
commit 280e57d544
2 changed files with 64 additions and 27 deletions

View file

@ -1765,7 +1765,7 @@ EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
*/
static struct hda_amp_info *
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;
unsigned int parm, val = 0;
@ -1791,7 +1791,8 @@ update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
}
info->vol[ch] = val;
info->head.val |= INFO_AMP_VOL(ch);
}
} else if (init_only)
return NULL;
return info;
}
@ -1832,7 +1833,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
unsigned int val = 0;
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)
val = info->vol[ch];
mutex_unlock(&codec->hash_mutex);
@ -1840,6 +1841,36 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
}
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val,
bool init_only)
{
struct hda_amp_info *info;
if (snd_BUG_ON(mask & ~0xff))
mask &= 0xff;
val &= mask;
mutex_lock(&codec->hash_mutex);
info = update_amp_hash(codec, nid, ch, direction, idx, init_only);
if (!info) {
mutex_unlock(&codec->hash_mutex);
return 0;
}
val |= info->vol[ch] & ~mask;
if (info->vol[ch] == val) {
mutex_unlock(&codec->hash_mutex);
return 0;
}
info->vol[ch] = val;
if (codec->cached_write)
info->head.dirty = 1;
mutex_unlock(&codec->hash_mutex);
if (!codec->cached_write)
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
/**
* snd_hda_codec_amp_update - update the AMP value
* @codec: HD-audio codec
@ -1856,30 +1887,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
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;
if (snd_BUG_ON(mask & ~0xff))
mask &= 0xff;
val &= mask;
mutex_lock(&codec->hash_mutex);
info = update_amp_hash(codec, nid, ch, direction, idx);
if (!info) {
mutex_unlock(&codec->hash_mutex);
return 0;
}
val |= info->vol[ch] & ~mask;
if (info->vol[ch] == val) {
mutex_unlock(&codec->hash_mutex);
return 0;
}
info->vol[ch] = val;
if (codec->cached_write)
info->head.dirty = 1;
mutex_unlock(&codec->hash_mutex);
if (!codec->cached_write)
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
return codec_amp_update(codec, nid, ch, direction, idx, mask, val, false);
}
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,
}
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
* @codec: HD-audio codec

View file

@ -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 snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
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_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,