diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 76 |
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. */ |
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 | ||
@@ -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, | |||
2717 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); | 2731 | EXPORT_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 | */ | ||
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 | /** | ||
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 { |