ALSA: hda - introduce snd_hda_codec_update_cache()
Add a new helper, snd_hda_codec_update_cache(), for reducing the unneeded verbs. This function checks the cached value and skips if it's identical with the given one. Otherwise it works like snd_hda_codec_write_cache(). The alc269 code uses this function as an example. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
ad35879aa1
commit
a68d5a5419
3 changed files with 62 additions and 14 deletions
sound/pci/hda
|
@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache)
|
|||
}
|
||||
|
||||
/* query the hash. allocate an entry if not found. */
|
||||
static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
|
||||
u32 key)
|
||||
static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key)
|
||||
{
|
||||
u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
|
||||
u16 cur = cache->hash[idx];
|
||||
|
@ -1222,17 +1221,27 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
|
|||
return info;
|
||||
cur = info->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add a new hash entry */
|
||||
info = snd_array_new(&cache->buf);
|
||||
if (!info)
|
||||
return NULL;
|
||||
cur = snd_array_index(&cache->buf, info);
|
||||
info->key = key;
|
||||
info->val = 0;
|
||||
info->next = cache->hash[idx];
|
||||
cache->hash[idx] = cur;
|
||||
|
||||
/* query the hash. allocate an entry if not found. */
|
||||
static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
|
||||
u32 key)
|
||||
{
|
||||
struct hda_cache_head *info = get_hash(cache, key);
|
||||
if (!info) {
|
||||
u16 idx, cur;
|
||||
/* add a new hash entry */
|
||||
info = snd_array_new(&cache->buf);
|
||||
if (!info)
|
||||
return NULL;
|
||||
cur = snd_array_index(&cache->buf, info);
|
||||
info->key = key;
|
||||
info->val = 0;
|
||||
idx = key % (u16)ARRAY_SIZE(cache->hash);
|
||||
info->next = cache->hash[idx];
|
||||
cache->hash[idx] = cur;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -2721,6 +2730,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
|
|||
}
|
||||
EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
|
||||
|
||||
/**
|
||||
* snd_hda_codec_update_cache - check cache and write the cmd only when needed
|
||||
* @codec: the HDA codec
|
||||
* @nid: NID to send the command
|
||||
* @direct: direct flag
|
||||
* @verb: the verb to send
|
||||
* @parm: the parameter for the verb
|
||||
*
|
||||
* This function works like snd_hda_codec_write_cache(), but it doesn't send
|
||||
* command if the parameter is already identical with the cached value.
|
||||
* If not, it sends the command and refreshes the cache.
|
||||
*
|
||||
* Returns 0 if successful, or a negative error code.
|
||||
*/
|
||||
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
|
||||
int direct, unsigned int verb, unsigned int parm)
|
||||
{
|
||||
struct hda_cache_head *c;
|
||||
u32 key;
|
||||
|
||||
/* parm may contain the verb stuff for get/set amp */
|
||||
verb = verb | (parm >> 8);
|
||||
parm &= 0xff;
|
||||
key = build_cmd_cache_key(nid, verb);
|
||||
mutex_lock(&codec->bus->cmd_mutex);
|
||||
c = get_hash(&codec->cmd_cache, key);
|
||||
if (c && c->val == parm) {
|
||||
mutex_unlock(&codec->bus->cmd_mutex);
|
||||
return 0;
|
||||
}
|
||||
mutex_unlock(&codec->bus->cmd_mutex);
|
||||
return snd_hda_codec_write_cache(codec, nid, direct, verb, parm);
|
||||
}
|
||||
EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
|
||||
|
||||
/**
|
||||
* snd_hda_codec_resume_cache - Resume the all commands from the cache
|
||||
* @codec: HD-audio codec
|
||||
|
|
|
@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
|
|||
int direct, unsigned int verb, unsigned int parm);
|
||||
void snd_hda_sequence_write_cache(struct hda_codec *codec,
|
||||
const struct hda_verb *seq);
|
||||
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
|
||||
int direct, unsigned int verb, unsigned int parm);
|
||||
void snd_hda_codec_resume_cache(struct hda_codec *codec);
|
||||
#else
|
||||
#define snd_hda_codec_write_cache snd_hda_codec_write
|
||||
#define snd_hda_codec_update_cache snd_hda_codec_write
|
||||
#define snd_hda_sequence_write_cache snd_hda_sequence_write
|
||||
#endif
|
||||
|
||||
|
|
|
@ -14012,8 +14012,9 @@ static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
|
|||
else
|
||||
pinval = 0x20;
|
||||
/* mic2 vref pin is used for mute LED control */
|
||||
snd_hda_codec_write(codec, 0x19, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, pinval);
|
||||
snd_hda_codec_update_cache(codec, 0x19, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL,
|
||||
pinval);
|
||||
}
|
||||
return alc_check_power_status(codec, nid);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue