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:
Takashi Iwai 2010-03-30 18:03:44 +02:00
parent ad35879aa1
commit a68d5a5419
3 changed files with 62 additions and 14 deletions

View File

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

View File

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

View File

@ -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);
}