|
@@ -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
|