aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-04-01 10:04:28 -0400
committerTakashi Iwai <tiwai@suse.de>2010-04-01 10:04:28 -0400
commitc125ba3becb3cb93b2207cf06656aead6506de3d (patch)
tree246579764bac6a32701f087171a6f2caec56b399 /sound/pci/hda
parent7a2e38a555f2b1a20aaaf30f3d8ecad8faa97ea7 (diff)
parenta68d5a5419d2a15161488b20f740115068e7b666 (diff)
Merge branch 'topic/hda-alc-mute' into topic/hda
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_codec.c68
-rw-r--r--sound/pci/hda/hda_codec.h3
-rw-r--r--sound/pci/hda/patch_realtek.c39
3 files changed, 98 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. */
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
@@ -2722,6 +2731,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2722EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); 2731EXPORT_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 */
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/**
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 *
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index b75da47571e6..49e939e7e5cd 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
885 int direct, unsigned int verb, unsigned int parm); 885 int direct, unsigned int verb, unsigned int parm);
886void snd_hda_sequence_write_cache(struct hda_codec *codec, 886void snd_hda_sequence_write_cache(struct hda_codec *codec,
887 const struct hda_verb *seq); 887 const struct hda_verb *seq);
888int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
889 int direct, unsigned int verb, unsigned int parm);
888void snd_hda_codec_resume_cache(struct hda_codec *codec); 890void snd_hda_codec_resume_cache(struct hda_codec *codec);
889#else 891#else
890#define snd_hda_codec_write_cache snd_hda_codec_write 892#define snd_hda_codec_write_cache snd_hda_codec_write
893#define snd_hda_codec_update_cache snd_hda_codec_write
891#define snd_hda_sequence_write_cache snd_hda_sequence_write 894#define snd_hda_sequence_write_cache snd_hda_sequence_write
892#endif 895#endif
893 896
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 1694f60631a1..8ae48061e8c7 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3467,6 +3467,10 @@ static int alc_init(struct hda_codec *codec)
3467 if (spec->init_hook) 3467 if (spec->init_hook)
3468 spec->init_hook(codec); 3468 spec->init_hook(codec);
3469 3469
3470#ifdef CONFIG_SND_HDA_POWER_SAVE
3471 if (codec->patch_ops.check_power_status)
3472 codec->patch_ops.check_power_status(codec, 0x01);
3473#endif
3470 return 0; 3474 return 0;
3471} 3475}
3472 3476
@@ -3827,6 +3831,10 @@ static int alc_resume(struct hda_codec *codec)
3827 codec->patch_ops.init(codec); 3831 codec->patch_ops.init(codec);
3828 snd_hda_codec_resume_amp(codec); 3832 snd_hda_codec_resume_amp(codec);
3829 snd_hda_codec_resume_cache(codec); 3833 snd_hda_codec_resume_cache(codec);
3834#ifdef CONFIG_SND_HDA_POWER_SAVE
3835 if (codec->patch_ops.check_power_status)
3836 codec->patch_ops.check_power_status(codec, 0x01);
3837#endif
3830 return 0; 3838 return 0;
3831} 3839}
3832#endif 3840#endif
@@ -13983,6 +13991,35 @@ static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
13983 /* NID is set in alc_build_pcms */ 13991 /* NID is set in alc_build_pcms */
13984}; 13992};
13985 13993
13994#ifdef CONFIG_SND_HDA_POWER_SAVE
13995static int alc269_mic2_for_mute_led(struct hda_codec *codec)
13996{
13997 switch (codec->subsystem_id) {
13998 case 0x103c1586:
13999 return 1;
14000 }
14001 return 0;
14002}
14003
14004static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
14005{
14006 /* update mute-LED according to the speaker mute state */
14007 if (nid == 0x01 || nid == 0x14) {
14008 int pinval;
14009 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
14010 HDA_AMP_MUTE)
14011 pinval = 0x24;
14012 else
14013 pinval = 0x20;
14014 /* mic2 vref pin is used for mute LED control */
14015 snd_hda_codec_update_cache(codec, 0x19, 0,
14016 AC_VERB_SET_PIN_WIDGET_CONTROL,
14017 pinval);
14018 }
14019 return alc_check_power_status(codec, nid);
14020}
14021#endif /* CONFIG_SND_HDA_POWER_SAVE */
14022
13986/* 14023/*
13987 * BIOS auto configuration 14024 * BIOS auto configuration
13988 */ 14025 */
@@ -14330,6 +14367,8 @@ static int patch_alc269(struct hda_codec *codec)
14330#ifdef CONFIG_SND_HDA_POWER_SAVE 14367#ifdef CONFIG_SND_HDA_POWER_SAVE
14331 if (!spec->loopback.amplist) 14368 if (!spec->loopback.amplist)
14332 spec->loopback.amplist = alc269_loopbacks; 14369 spec->loopback.amplist = alc269_loopbacks;
14370 if (alc269_mic2_for_mute_led(codec))
14371 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
14333#endif 14372#endif
14334 14373
14335 return 0; 14374 return 0;