aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c76
1 files changed, 63 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 0e76ac2b2ace..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. */
1212static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, 1212static 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); 1228static 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
@@ -1461,6 +1470,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1461 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); 1470 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1462 if (!info) 1471 if (!info)
1463 return 0; 1472 return 0;
1473 if (snd_BUG_ON(mask & ~0xff))
1474 mask &= 0xff;
1464 val &= mask; 1475 val &= mask;
1465 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; 1476 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
1466 if (info->vol[ch] == val) 1477 if (info->vol[ch] == val)
@@ -1486,6 +1497,9 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1486 int direction, int idx, int mask, int val) 1497 int direction, int idx, int mask, int val)
1487{ 1498{
1488 int ch, ret = 0; 1499 int ch, ret = 0;
1500
1501 if (snd_BUG_ON(mask & ~0xff))
1502 mask &= 0xff;
1489 for (ch = 0; ch < 2; ch++) 1503 for (ch = 0; ch < 2; ch++)
1490 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, 1504 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1491 idx, mask, val); 1505 idx, mask, val);
@@ -2717,6 +2731,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2717EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); 2731EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
2718 2732
2719/** 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 */
2747int 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}
2766EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
2767
2768/**
2720 * 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
2721 * @codec: HD-audio codec 2770 * @codec: HD-audio codec
2722 * 2771 *
@@ -4218,7 +4267,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4218 break; 4267 break;
4219 case AC_JACK_MIC_IN: { 4268 case AC_JACK_MIC_IN: {
4220 int preferred, alt; 4269 int preferred, alt;
4221 if (loc == AC_JACK_LOC_FRONT) { 4270 if (loc == AC_JACK_LOC_FRONT ||
4271 (loc & 0x30) == AC_JACK_LOC_INTERNAL) {
4222 preferred = AUTO_PIN_FRONT_MIC; 4272 preferred = AUTO_PIN_FRONT_MIC;
4223 alt = AUTO_PIN_MIC; 4273 alt = AUTO_PIN_MIC;
4224 } else { 4274 } else {