diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-03-30 12:03:44 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-03-30 12:03:44 -0400 |
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) | |||
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | /* query the hash. allocate an entry if not found. */ | 1211 | /* query the hash. allocate an entry if not found. */ |
1212 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | 1212 | static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key) |
1213 | u32 key) | ||
1214 | { | 1213 | { |
1215 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | 1214 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
1216 | u16 cur = cache->hash[idx]; | 1215 | u16 cur = cache->hash[idx]; |
@@ -1222,17 +1221,27 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
1222 | return info; | 1221 | return info; |
1223 | cur = info->next; | 1222 | cur = info->next; |
1224 | } | 1223 | } |
1224 | return NULL; | ||
1225 | } | ||
1225 | 1226 | ||
1226 | /* add a new hash entry */ | 1227 | /* query the hash. allocate an entry if not found. */ |
1227 | info = snd_array_new(&cache->buf); | 1228 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, |
1228 | if (!info) | 1229 | u32 key) |
1229 | return NULL; | 1230 | { |
1230 | cur = snd_array_index(&cache->buf, info); | 1231 | struct hda_cache_head *info = get_hash(cache, key); |
1231 | info->key = key; | 1232 | if (!info) { |
1232 | info->val = 0; | 1233 | u16 idx, cur; |
1233 | info->next = cache->hash[idx]; | 1234 | /* add a new hash entry */ |
1234 | cache->hash[idx] = cur; | 1235 | info = snd_array_new(&cache->buf); |
1235 | 1236 | if (!info) | |
1237 | return NULL; | ||
1238 | cur = snd_array_index(&cache->buf, info); | ||
1239 | info->key = key; | ||
1240 | info->val = 0; | ||
1241 | idx = key % (u16)ARRAY_SIZE(cache->hash); | ||
1242 | info->next = cache->hash[idx]; | ||
1243 | cache->hash[idx] = cur; | ||
1244 | } | ||
1236 | return info; | 1245 | return info; |
1237 | } | 1246 | } |
1238 | 1247 | ||
@@ -2722,6 +2731,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
2722 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); | 2731 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); |
2723 | 2732 | ||
2724 | /** | 2733 | /** |
2734 | * snd_hda_codec_update_cache - check cache and write the cmd only when needed | ||
2735 | * @codec: the HDA codec | ||
2736 | * @nid: NID to send the command | ||
2737 | * @direct: direct flag | ||
2738 | * @verb: the verb to send | ||
2739 | * @parm: the parameter for the verb | ||
2740 | * | ||
2741 | * This function works like snd_hda_codec_write_cache(), but it doesn't send | ||
2742 | * command if the parameter is already identical with the cached value. | ||
2743 | * If not, it sends the command and refreshes the cache. | ||
2744 | * | ||
2745 | * Returns 0 if successful, or a negative error code. | ||
2746 | */ | ||
2747 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | ||
2748 | int direct, unsigned int verb, unsigned int parm) | ||
2749 | { | ||
2750 | struct hda_cache_head *c; | ||
2751 | u32 key; | ||
2752 | |||
2753 | /* parm may contain the verb stuff for get/set amp */ | ||
2754 | verb = verb | (parm >> 8); | ||
2755 | parm &= 0xff; | ||
2756 | key = build_cmd_cache_key(nid, verb); | ||
2757 | mutex_lock(&codec->bus->cmd_mutex); | ||
2758 | c = get_hash(&codec->cmd_cache, key); | ||
2759 | if (c && c->val == parm) { | ||
2760 | mutex_unlock(&codec->bus->cmd_mutex); | ||
2761 | return 0; | ||
2762 | } | ||
2763 | mutex_unlock(&codec->bus->cmd_mutex); | ||
2764 | return snd_hda_codec_write_cache(codec, nid, direct, verb, parm); | ||
2765 | } | ||
2766 | EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache); | ||
2767 | |||
2768 | /** | ||
2725 | * snd_hda_codec_resume_cache - Resume the all commands from the cache | 2769 | * snd_hda_codec_resume_cache - Resume the all commands from the cache |
2726 | * @codec: HD-audio codec | 2770 | * @codec: HD-audio codec |
2727 | * | 2771 | * |