diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-04-01 10:04:28 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-04-01 10:04:28 -0400 |
commit | c125ba3becb3cb93b2207cf06656aead6506de3d (patch) | |
tree | 246579764bac6a32701f087171a6f2caec56b399 /sound/pci/hda | |
parent | 7a2e38a555f2b1a20aaaf30f3d8ecad8faa97ea7 (diff) | |
parent | a68d5a5419d2a15161488b20f740115068e7b666 (diff) |
Merge branch 'topic/hda-alc-mute' into topic/hda
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 68 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 39 |
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. */ |
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 | * |
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); |
886 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | 886 | void snd_hda_sequence_write_cache(struct hda_codec *codec, |
887 | const struct hda_verb *seq); | 887 | const struct hda_verb *seq); |
888 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | ||
889 | int direct, unsigned int verb, unsigned int parm); | ||
888 | void snd_hda_codec_resume_cache(struct hda_codec *codec); | 890 | void 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 | ||
13995 | static 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 | |||
14004 | static 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; |