}
/* 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];
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;
}
}
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
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