Commit a68d5a54 authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent ad35879a
...@@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache) ...@@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache)
} }
/* query the hash. allocate an entry if not found. */ /* query the hash. allocate an entry if not found. */
static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key)
u32 key)
{ {
u16 idx = key % (u16)ARRAY_SIZE(cache->hash); u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
u16 cur = cache->hash[idx]; u16 cur = cache->hash[idx];
...@@ -1222,17 +1221,27 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, ...@@ -1222,17 +1221,27 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
return info; return info;
cur = info->next; cur = info->next;
} }
return NULL;
}
/* add a new hash entry */ /* query the hash. allocate an entry if not found. */
info = snd_array_new(&cache->buf); static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
if (!info) u32 key)
return NULL; {
cur = snd_array_index(&cache->buf, info); struct hda_cache_head *info = get_hash(cache, key);
info->key = key; if (!info) {
info->val = 0; u16 idx, cur;
info->next = cache->hash[idx]; /* add a new hash entry */
cache->hash[idx] = cur; 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; return info;
} }
...@@ -2721,6 +2730,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, ...@@ -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); 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 * snd_hda_codec_resume_cache - Resume the all commands from the cache
* @codec: HD-audio codec * @codec: HD-audio codec
......
...@@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, ...@@ -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); int direct, unsigned int verb, unsigned int parm);
void snd_hda_sequence_write_cache(struct hda_codec *codec, void snd_hda_sequence_write_cache(struct hda_codec *codec,
const struct hda_verb *seq); 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); void snd_hda_codec_resume_cache(struct hda_codec *codec);
#else #else
#define snd_hda_codec_write_cache snd_hda_codec_write #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 #define snd_hda_sequence_write_cache snd_hda_sequence_write
#endif #endif
......
...@@ -14012,8 +14012,9 @@ static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) ...@@ -14012,8 +14012,9 @@ static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
else else
pinval = 0x20; pinval = 0x20;
/* mic2 vref pin is used for mute LED control */ /* mic2 vref pin is used for mute LED control */
snd_hda_codec_write(codec, 0x19, 0, snd_hda_codec_update_cache(codec, 0x19, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, pinval); AC_VERB_SET_PIN_WIDGET_CONTROL,
pinval);
} }
return alc_check_power_status(codec, nid); return alc_check_power_status(codec, nid);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment