diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-03-30 18:03:44 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-03-30 18:03:44 +0200 |
commit | a68d5a5419d2a15161488b20f740115068e7b666 (patch) | |
tree | 75249110bd358f068835ad87d1f47f99f4962038 /sound/pci/hda/hda_codec.c | |
parent | ad35879aa192e783db2d41c196f48f3fc059ce22 (diff) |
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>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 68 |
1 files changed, 56 insertions, 12 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d1424e7b9f3d..a3d638c8c1fd 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -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; } @@ -2722,6 +2731,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 * |