diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-27 12:25:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-27 12:25:15 -0400 |
commit | 75623437167d9d1ef14acaf6b3fb4ccd38fcbc84 (patch) | |
tree | b7136121995cc6c2b5211a5393b1ad7c179a2f3b /sound | |
parent | 70a3eff5768350c0313a9ae70a15da113171d0ab (diff) | |
parent | 636f78581dbd5529a52057973fe2bdfc1c2f528e (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (22 commits)
ALSA: hda - Cirrus Logic CS421x support
ALSA: Make pcm.h self-contained
ALSA: hda - Allow codec-specific set_power_state ops
ALSA: hda - Add post_suspend patch ops
ALSA: hda - Make CONFIG_SND_HDA_POWER_SAVE depending on CONFIG_PM
ALSA: hda - Make sure mute led reflects master mute state
ALSA: hda - Fix invalid mute led state on resume of IDT codecs
ASoC: Revert "ASoC: SAMSUNG: Add I2S0 internal dma driver"
ALSA: hda - Add support of the 4 internal speakers on certain HP laptops
ALSA: Make snd_pcm_debug_name usable outside pcm_lib
ALSA: hda - Fix DAC filling for multi-connection pins in Realtek parser
ASoC: dapm - Add methods to retrieve snd_card and soc_card from dapm context.
ASoC: SAMSUNG: Add I2S0 internal dma driver
ASoC: SAMSUNG: Modify I2S driver to support idma
ASoC: davinci: add missing break statement
ASoC: davinci: fix codec start and stop functions
ASoC: dapm - add DAPM macro for external enum widgets
ASoC: Acknowledge WM8962 interrupts before acting on them
ASoC: sgtl5000: guide user when regulator support is needed
ASoC: sgtl5000: refactor registering internal ldo
...
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/pcm_lib.c | 13 | ||||
-rw-r--r-- | sound/pci/asihpi/asihpi.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/Kconfig | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 114 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 15 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 743 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 14 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 15 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 122 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.c | 70 | ||||
-rw-r--r-- | sound/soc/codecs/wm8962.c | 6 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-vcif.c | 9 | ||||
-rw-r--r-- | sound/soc/samsung/i2s.c | 7 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 5 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 30 |
18 files changed, 990 insertions, 205 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index f1341308beda..86d0caf91b35 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -128,7 +128,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram | |||
128 | } | 128 | } |
129 | } | 129 | } |
130 | 130 | ||
131 | static void pcm_debug_name(struct snd_pcm_substream *substream, | 131 | #ifdef CONFIG_SND_DEBUG |
132 | void snd_pcm_debug_name(struct snd_pcm_substream *substream, | ||
132 | char *name, size_t len) | 133 | char *name, size_t len) |
133 | { | 134 | { |
134 | snprintf(name, len, "pcmC%dD%d%c:%d", | 135 | snprintf(name, len, "pcmC%dD%d%c:%d", |
@@ -137,6 +138,8 @@ static void pcm_debug_name(struct snd_pcm_substream *substream, | |||
137 | substream->stream ? 'c' : 'p', | 138 | substream->stream ? 'c' : 'p', |
138 | substream->number); | 139 | substream->number); |
139 | } | 140 | } |
141 | EXPORT_SYMBOL(snd_pcm_debug_name); | ||
142 | #endif | ||
140 | 143 | ||
141 | #define XRUN_DEBUG_BASIC (1<<0) | 144 | #define XRUN_DEBUG_BASIC (1<<0) |
142 | #define XRUN_DEBUG_STACK (1<<1) /* dump also stack */ | 145 | #define XRUN_DEBUG_STACK (1<<1) /* dump also stack */ |
@@ -168,7 +171,7 @@ static void xrun(struct snd_pcm_substream *substream) | |||
168 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | 171 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); |
169 | if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { | 172 | if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { |
170 | char name[16]; | 173 | char name[16]; |
171 | pcm_debug_name(substream, name, sizeof(name)); | 174 | snd_pcm_debug_name(substream, name, sizeof(name)); |
172 | snd_printd(KERN_DEBUG "XRUN: %s\n", name); | 175 | snd_printd(KERN_DEBUG "XRUN: %s\n", name); |
173 | dump_stack_on_xrun(substream); | 176 | dump_stack_on_xrun(substream); |
174 | } | 177 | } |
@@ -243,7 +246,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream) | |||
243 | return; | 246 | return; |
244 | if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit) | 247 | if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit) |
245 | return; | 248 | return; |
246 | pcm_debug_name(substream, name, sizeof(name)); | 249 | snd_pcm_debug_name(substream, name, sizeof(name)); |
247 | for (cnt = 0, idx = log->idx; cnt < XRUN_LOG_CNT; cnt++) { | 250 | for (cnt = 0, idx = log->idx; cnt < XRUN_LOG_CNT; cnt++) { |
248 | entry = &log->entries[idx]; | 251 | entry = &log->entries[idx]; |
249 | if (entry->period_size == 0) | 252 | if (entry->period_size == 0) |
@@ -319,7 +322,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
319 | if (pos >= runtime->buffer_size) { | 322 | if (pos >= runtime->buffer_size) { |
320 | if (printk_ratelimit()) { | 323 | if (printk_ratelimit()) { |
321 | char name[16]; | 324 | char name[16]; |
322 | pcm_debug_name(substream, name, sizeof(name)); | 325 | snd_pcm_debug_name(substream, name, sizeof(name)); |
323 | xrun_log_show(substream); | 326 | xrun_log_show(substream); |
324 | snd_printd(KERN_ERR "BUG: %s, pos = %ld, " | 327 | snd_printd(KERN_ERR "BUG: %s, pos = %ld, " |
325 | "buffer size = %ld, period size = %ld\n", | 328 | "buffer size = %ld, period size = %ld\n", |
@@ -364,7 +367,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
364 | if (xrun_debug(substream, in_interrupt ? | 367 | if (xrun_debug(substream, in_interrupt ? |
365 | XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) { | 368 | XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) { |
366 | char name[16]; | 369 | char name[16]; |
367 | pcm_debug_name(substream, name, sizeof(name)); | 370 | snd_pcm_debug_name(substream, name, sizeof(name)); |
368 | snd_printd("%s_update: %s: pos=%u/%u/%u, " | 371 | snd_printd("%s_update: %s: pos=%u/%u/%u, " |
369 | "hwptr=%ld/%ld/%ld/%ld\n", | 372 | "hwptr=%ld/%ld/%ld/%ld\n", |
370 | in_interrupt ? "period" : "hwptr", | 373 | in_interrupt ? "period" : "hwptr", |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index b941d2541dda..eae62ebbd295 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -41,31 +41,10 @@ | |||
41 | #include <sound/tlv.h> | 41 | #include <sound/tlv.h> |
42 | #include <sound/hwdep.h> | 42 | #include <sound/hwdep.h> |
43 | 43 | ||
44 | |||
45 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
46 | MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); | 45 | MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); |
47 | MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); | 46 | MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); |
48 | 47 | ||
49 | #if defined CONFIG_SND_DEBUG | ||
50 | /* copied from pcm_lib.c, hope later patch will make that version public | ||
51 | and this copy can be removed */ | ||
52 | static inline void | ||
53 | snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size) | ||
54 | { | ||
55 | snprintf(buf, size, "pcmC%dD%d%c:%d", | ||
56 | substream->pcm->card->number, | ||
57 | substream->pcm->device, | ||
58 | substream->stream ? 'c' : 'p', | ||
59 | substream->number); | ||
60 | } | ||
61 | #else | ||
62 | static inline void | ||
63 | snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size) | ||
64 | { | ||
65 | *buf = 0; | ||
66 | } | ||
67 | #endif | ||
68 | |||
69 | #if defined CONFIG_SND_DEBUG_VERBOSE | 48 | #if defined CONFIG_SND_DEBUG_VERBOSE |
70 | /** | 49 | /** |
71 | * snd_printddd - very verbose debug printk | 50 | * snd_printddd - very verbose debug printk |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 7489b4608551..bb7e102d6726 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -243,6 +243,7 @@ config SND_HDA_GENERIC | |||
243 | 243 | ||
244 | config SND_HDA_POWER_SAVE | 244 | config SND_HDA_POWER_SAVE |
245 | bool "Aggressive power-saving on HD-audio" | 245 | bool "Aggressive power-saving on HD-audio" |
246 | depends on PM | ||
246 | help | 247 | help |
247 | Say Y here to enable more aggressive power-saving mode on | 248 | Say Y here to enable more aggressive power-saving mode on |
248 | HD-audio driver. The power-saving timeout can be configured | 249 | HD-audio driver. The power-saving timeout can be configured |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 9c27a3a4c4d5..3e7850c238c3 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -91,8 +91,10 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); | |||
91 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 91 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
92 | static void hda_power_work(struct work_struct *work); | 92 | static void hda_power_work(struct work_struct *work); |
93 | static void hda_keep_power_on(struct hda_codec *codec); | 93 | static void hda_keep_power_on(struct hda_codec *codec); |
94 | #define hda_codec_is_power_on(codec) ((codec)->power_on) | ||
94 | #else | 95 | #else |
95 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | 96 | static inline void hda_keep_power_on(struct hda_codec *codec) {} |
97 | #define hda_codec_is_power_on(codec) 1 | ||
96 | #endif | 98 | #endif |
97 | 99 | ||
98 | /** | 100 | /** |
@@ -1101,7 +1103,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec) | |||
1101 | } | 1103 | } |
1102 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); | 1104 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); |
1103 | 1105 | ||
1104 | #ifdef SND_HDA_NEEDS_RESUME | 1106 | #ifdef CONFIG_PM |
1105 | /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ | 1107 | /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ |
1106 | static void restore_shutup_pins(struct hda_codec *codec) | 1108 | static void restore_shutup_pins(struct hda_codec *codec) |
1107 | { | 1109 | { |
@@ -1499,7 +1501,7 @@ static void purify_inactive_streams(struct hda_codec *codec) | |||
1499 | } | 1501 | } |
1500 | } | 1502 | } |
1501 | 1503 | ||
1502 | #ifdef SND_HDA_NEEDS_RESUME | 1504 | #ifdef CONFIG_PM |
1503 | /* clean up all streams; called from suspend */ | 1505 | /* clean up all streams; called from suspend */ |
1504 | static void hda_cleanup_all_streams(struct hda_codec *codec) | 1506 | static void hda_cleanup_all_streams(struct hda_codec *codec) |
1505 | { | 1507 | { |
@@ -1838,7 +1840,7 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
1838 | } | 1840 | } |
1839 | EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo); | 1841 | EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo); |
1840 | 1842 | ||
1841 | #ifdef SND_HDA_NEEDS_RESUME | 1843 | #ifdef CONFIG_PM |
1842 | /** | 1844 | /** |
1843 | * snd_hda_codec_resume_amp - Resume all AMP commands from the cache | 1845 | * snd_hda_codec_resume_amp - Resume all AMP commands from the cache |
1844 | * @codec: HD-audio codec | 1846 | * @codec: HD-audio codec |
@@ -1868,7 +1870,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec) | |||
1868 | } | 1870 | } |
1869 | } | 1871 | } |
1870 | EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); | 1872 | EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); |
1871 | #endif /* SND_HDA_NEEDS_RESUME */ | 1873 | #endif /* CONFIG_PM */ |
1872 | 1874 | ||
1873 | static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, | 1875 | static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, |
1874 | unsigned int ofs) | 1876 | unsigned int ofs) |
@@ -3082,7 +3084,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
3082 | } | 3084 | } |
3083 | EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls); | 3085 | EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls); |
3084 | 3086 | ||
3085 | #ifdef SND_HDA_NEEDS_RESUME | 3087 | #ifdef CONFIG_PM |
3086 | /* | 3088 | /* |
3087 | * command cache | 3089 | * command cache |
3088 | */ | 3090 | */ |
@@ -3199,53 +3201,32 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec, | |||
3199 | seq->param); | 3201 | seq->param); |
3200 | } | 3202 | } |
3201 | EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache); | 3203 | EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache); |
3202 | #endif /* SND_HDA_NEEDS_RESUME */ | 3204 | #endif /* CONFIG_PM */ |
3203 | 3205 | ||
3204 | /* | 3206 | void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, |
3205 | * set power state of the codec | 3207 | unsigned int power_state, |
3206 | */ | 3208 | bool eapd_workaround) |
3207 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
3208 | unsigned int power_state) | ||
3209 | { | 3209 | { |
3210 | hda_nid_t nid; | 3210 | hda_nid_t nid = codec->start_nid; |
3211 | int i; | 3211 | int i; |
3212 | 3212 | ||
3213 | /* this delay seems necessary to avoid click noise at power-down */ | ||
3214 | if (power_state == AC_PWRST_D3) | ||
3215 | msleep(100); | ||
3216 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
3217 | power_state); | ||
3218 | /* partial workaround for "azx_get_response timeout" */ | ||
3219 | if (power_state == AC_PWRST_D0 && | ||
3220 | (codec->vendor_id & 0xffff0000) == 0x14f10000) | ||
3221 | msleep(10); | ||
3222 | |||
3223 | nid = codec->start_nid; | ||
3224 | for (i = 0; i < codec->num_nodes; i++, nid++) { | 3213 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
3225 | unsigned int wcaps = get_wcaps(codec, nid); | 3214 | unsigned int wcaps = get_wcaps(codec, nid); |
3226 | if (wcaps & AC_WCAP_POWER) { | 3215 | if (!(wcaps & AC_WCAP_POWER)) |
3227 | unsigned int wid_type = get_wcaps_type(wcaps); | 3216 | continue; |
3228 | if (power_state == AC_PWRST_D3 && | 3217 | /* don't power down the widget if it controls eapd and |
3229 | wid_type == AC_WID_PIN) { | 3218 | * EAPD_BTLENABLE is set. |
3230 | unsigned int pincap; | 3219 | */ |
3231 | /* | 3220 | if (eapd_workaround && power_state == AC_PWRST_D3 && |
3232 | * don't power down the widget if it controls | 3221 | get_wcaps_type(wcaps) == AC_WID_PIN && |
3233 | * eapd and EAPD_BTLENABLE is set. | 3222 | (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) { |
3234 | */ | 3223 | int eapd = snd_hda_codec_read(codec, nid, 0, |
3235 | pincap = snd_hda_query_pin_caps(codec, nid); | ||
3236 | if (pincap & AC_PINCAP_EAPD) { | ||
3237 | int eapd = snd_hda_codec_read(codec, | ||
3238 | nid, 0, | ||
3239 | AC_VERB_GET_EAPD_BTLENABLE, 0); | 3224 | AC_VERB_GET_EAPD_BTLENABLE, 0); |
3240 | eapd &= 0x02; | 3225 | if (eapd & 0x02) |
3241 | if (eapd) | 3226 | continue; |
3242 | continue; | ||
3243 | } | ||
3244 | } | ||
3245 | snd_hda_codec_write(codec, nid, 0, | ||
3246 | AC_VERB_SET_POWER_STATE, | ||
3247 | power_state); | ||
3248 | } | 3227 | } |
3228 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, | ||
3229 | power_state); | ||
3249 | } | 3230 | } |
3250 | 3231 | ||
3251 | if (power_state == AC_PWRST_D0) { | 3232 | if (power_state == AC_PWRST_D0) { |
@@ -3262,6 +3243,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
3262 | } while (time_after_eq(end_time, jiffies)); | 3243 | } while (time_after_eq(end_time, jiffies)); |
3263 | } | 3244 | } |
3264 | } | 3245 | } |
3246 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); | ||
3247 | |||
3248 | /* | ||
3249 | * set power state of the codec | ||
3250 | */ | ||
3251 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
3252 | unsigned int power_state) | ||
3253 | { | ||
3254 | if (codec->patch_ops.set_power_state) { | ||
3255 | codec->patch_ops.set_power_state(codec, fg, power_state); | ||
3256 | return; | ||
3257 | } | ||
3258 | |||
3259 | /* this delay seems necessary to avoid click noise at power-down */ | ||
3260 | if (power_state == AC_PWRST_D3) | ||
3261 | msleep(100); | ||
3262 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
3263 | power_state); | ||
3264 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | ||
3265 | } | ||
3265 | 3266 | ||
3266 | #ifdef CONFIG_SND_HDA_HWDEP | 3267 | #ifdef CONFIG_SND_HDA_HWDEP |
3267 | /* execute additional init verbs */ | 3268 | /* execute additional init verbs */ |
@@ -3274,7 +3275,7 @@ static void hda_exec_init_verbs(struct hda_codec *codec) | |||
3274 | static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | 3275 | static inline void hda_exec_init_verbs(struct hda_codec *codec) {} |
3275 | #endif | 3276 | #endif |
3276 | 3277 | ||
3277 | #ifdef SND_HDA_NEEDS_RESUME | 3278 | #ifdef CONFIG_PM |
3278 | /* | 3279 | /* |
3279 | * call suspend and power-down; used both from PM and power-save | 3280 | * call suspend and power-down; used both from PM and power-save |
3280 | */ | 3281 | */ |
@@ -3315,7 +3316,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
3315 | snd_hda_codec_resume_cache(codec); | 3316 | snd_hda_codec_resume_cache(codec); |
3316 | } | 3317 | } |
3317 | } | 3318 | } |
3318 | #endif /* SND_HDA_NEEDS_RESUME */ | 3319 | #endif /* CONFIG_PM */ |
3319 | 3320 | ||
3320 | 3321 | ||
3321 | /** | 3322 | /** |
@@ -4071,9 +4072,6 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, | |||
4071 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); | 4072 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); |
4072 | 4073 | ||
4073 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4074 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
4074 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
4075 | unsigned int power_state); | ||
4076 | |||
4077 | static void hda_power_work(struct work_struct *work) | 4075 | static void hda_power_work(struct work_struct *work) |
4078 | { | 4076 | { |
4079 | struct hda_codec *codec = | 4077 | struct hda_codec *codec = |
@@ -4376,11 +4374,8 @@ void snd_hda_bus_reboot_notify(struct hda_bus *bus) | |||
4376 | if (!bus) | 4374 | if (!bus) |
4377 | return; | 4375 | return; |
4378 | list_for_each_entry(codec, &bus->codec_list, list) { | 4376 | list_for_each_entry(codec, &bus->codec_list, list) { |
4379 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4377 | if (hda_codec_is_power_on(codec) && |
4380 | if (!codec->power_on) | 4378 | codec->patch_ops.reboot_notify) |
4381 | continue; | ||
4382 | #endif | ||
4383 | if (codec->patch_ops.reboot_notify) | ||
4384 | codec->patch_ops.reboot_notify(codec); | 4379 | codec->patch_ops.reboot_notify(codec); |
4385 | } | 4380 | } |
4386 | } | 4381 | } |
@@ -5079,11 +5074,10 @@ int snd_hda_suspend(struct hda_bus *bus) | |||
5079 | struct hda_codec *codec; | 5074 | struct hda_codec *codec; |
5080 | 5075 | ||
5081 | list_for_each_entry(codec, &bus->codec_list, list) { | 5076 | list_for_each_entry(codec, &bus->codec_list, list) { |
5082 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5077 | if (hda_codec_is_power_on(codec)) |
5083 | if (!codec->power_on) | 5078 | hda_call_codec_suspend(codec); |
5084 | continue; | 5079 | if (codec->patch_ops.post_suspend) |
5085 | #endif | 5080 | codec->patch_ops.post_suspend(codec); |
5086 | hda_call_codec_suspend(codec); | ||
5087 | } | 5081 | } |
5088 | return 0; | 5082 | return 0; |
5089 | } | 5083 | } |
@@ -5103,6 +5097,8 @@ int snd_hda_resume(struct hda_bus *bus) | |||
5103 | struct hda_codec *codec; | 5097 | struct hda_codec *codec; |
5104 | 5098 | ||
5105 | list_for_each_entry(codec, &bus->codec_list, list) { | 5099 | list_for_each_entry(codec, &bus->codec_list, list) { |
5100 | if (codec->patch_ops.pre_resume) | ||
5101 | codec->patch_ops.pre_resume(codec); | ||
5106 | if (snd_hda_codec_needs_resume(codec)) | 5102 | if (snd_hda_codec_needs_resume(codec)) |
5107 | hda_call_codec_resume(codec); | 5103 | hda_call_codec_resume(codec); |
5108 | } | 5104 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index f465e07a4879..755f2b0f9d8e 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -26,10 +26,6 @@ | |||
26 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
27 | #include <sound/hwdep.h> | 27 | #include <sound/hwdep.h> |
28 | 28 | ||
29 | #if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE) | ||
30 | #define SND_HDA_NEEDS_RESUME /* resume control code is required */ | ||
31 | #endif | ||
32 | |||
33 | /* | 29 | /* |
34 | * nodes | 30 | * nodes |
35 | */ | 31 | */ |
@@ -704,8 +700,12 @@ struct hda_codec_ops { | |||
704 | int (*init)(struct hda_codec *codec); | 700 | int (*init)(struct hda_codec *codec); |
705 | void (*free)(struct hda_codec *codec); | 701 | void (*free)(struct hda_codec *codec); |
706 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | 702 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); |
707 | #ifdef SND_HDA_NEEDS_RESUME | 703 | void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg, |
704 | unsigned int power_state); | ||
705 | #ifdef CONFIG_PM | ||
708 | int (*suspend)(struct hda_codec *codec, pm_message_t state); | 706 | int (*suspend)(struct hda_codec *codec, pm_message_t state); |
707 | int (*post_suspend)(struct hda_codec *codec); | ||
708 | int (*pre_resume)(struct hda_codec *codec); | ||
709 | int (*resume)(struct hda_codec *codec); | 709 | int (*resume)(struct hda_codec *codec); |
710 | #endif | 710 | #endif |
711 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 711 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -927,7 +927,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, | |||
927 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); | 927 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); |
928 | 928 | ||
929 | /* cached write */ | 929 | /* cached write */ |
930 | #ifdef SND_HDA_NEEDS_RESUME | 930 | #ifdef CONFIG_PM |
931 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | 931 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, |
932 | int direct, unsigned int verb, unsigned int parm); | 932 | int direct, unsigned int verb, unsigned int parm); |
933 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | 933 | void snd_hda_sequence_write_cache(struct hda_codec *codec, |
@@ -1008,6 +1008,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | |||
1008 | */ | 1008 | */ |
1009 | void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); | 1009 | void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); |
1010 | void snd_hda_bus_reboot_notify(struct hda_bus *bus); | 1010 | void snd_hda_bus_reboot_notify(struct hda_bus *bus); |
1011 | void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | ||
1012 | unsigned int power_state, | ||
1013 | bool eapd_workaround); | ||
1011 | 1014 | ||
1012 | /* | 1015 | /* |
1013 | * power management | 1016 | * power management |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 88b277e97409..2e7ac31afa8d 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -131,7 +131,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
131 | int direction, int idx, int mask, int val); | 131 | int direction, int idx, int mask, int val); |
132 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | 132 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, |
133 | int dir, int idx, int mask, int val); | 133 | int dir, int idx, int mask, int val); |
134 | #ifdef SND_HDA_NEEDS_RESUME | 134 | #ifdef CONFIG_PM |
135 | void snd_hda_codec_resume_amp(struct hda_codec *codec); | 135 | void snd_hda_codec_resume_amp(struct hda_codec *codec); |
136 | #endif | 136 | #endif |
137 | 137 | ||
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 1362c8ba4d1f..8648917acffb 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -563,7 +563,7 @@ static void ad198x_free(struct hda_codec *codec) | |||
563 | snd_hda_detach_beep_device(codec); | 563 | snd_hda_detach_beep_device(codec); |
564 | } | 564 | } |
565 | 565 | ||
566 | #ifdef SND_HDA_NEEDS_RESUME | 566 | #ifdef CONFIG_PM |
567 | static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) | 567 | static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) |
568 | { | 568 | { |
569 | ad198x_shutup(codec); | 569 | ad198x_shutup(codec); |
@@ -579,7 +579,7 @@ static const struct hda_codec_ops ad198x_patch_ops = { | |||
579 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 579 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
580 | .check_power_status = ad198x_check_power_status, | 580 | .check_power_status = ad198x_check_power_status, |
581 | #endif | 581 | #endif |
582 | #ifdef SND_HDA_NEEDS_RESUME | 582 | #ifdef CONFIG_PM |
583 | .suspend = ad198x_suspend, | 583 | .suspend = ad198x_suspend, |
584 | #endif | 584 | #endif |
585 | .reboot_notify = ad198x_shutup, | 585 | .reboot_notify = ad198x_shutup, |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 7f93739b1e33..47d6ffc9b5b5 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
26 | #include "hda_codec.h" | 26 | #include "hda_codec.h" |
27 | #include "hda_local.h" | 27 | #include "hda_local.h" |
28 | #include <sound/tlv.h> | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | */ | 31 | */ |
@@ -61,9 +62,15 @@ struct cs_spec { | |||
61 | 62 | ||
62 | unsigned int hp_detect:1; | 63 | unsigned int hp_detect:1; |
63 | unsigned int mic_detect:1; | 64 | unsigned int mic_detect:1; |
65 | /* CS421x */ | ||
66 | unsigned int spdif_detect:1; | ||
67 | unsigned int sense_b:1; | ||
68 | hda_nid_t vendor_nid; | ||
69 | struct hda_input_mux input_mux; | ||
70 | unsigned int last_input; | ||
64 | }; | 71 | }; |
65 | 72 | ||
66 | /* available models */ | 73 | /* available models with CS420x */ |
67 | enum { | 74 | enum { |
68 | CS420X_MBP53, | 75 | CS420X_MBP53, |
69 | CS420X_MBP55, | 76 | CS420X_MBP55, |
@@ -72,6 +79,12 @@ enum { | |||
72 | CS420X_MODELS | 79 | CS420X_MODELS |
73 | }; | 80 | }; |
74 | 81 | ||
82 | /* CS421x boards */ | ||
83 | enum { | ||
84 | CS421X_CDB4210, | ||
85 | CS421X_MODELS | ||
86 | }; | ||
87 | |||
75 | /* Vendor-specific processing widget */ | 88 | /* Vendor-specific processing widget */ |
76 | #define CS420X_VENDOR_NID 0x11 | 89 | #define CS420X_VENDOR_NID 0x11 |
77 | #define CS_DIG_OUT1_PIN_NID 0x10 | 90 | #define CS_DIG_OUT1_PIN_NID 0x10 |
@@ -111,21 +124,42 @@ enum { | |||
111 | /* 0x0009 - 0x0014 -> 12 test regs */ | 124 | /* 0x0009 - 0x0014 -> 12 test regs */ |
112 | /* 0x0015 - visibility reg */ | 125 | /* 0x0015 - visibility reg */ |
113 | 126 | ||
127 | /* | ||
128 | * Cirrus Logic CS4210 | ||
129 | * | ||
130 | * 1 DAC => HP(sense) / Speakers, | ||
131 | * 1 ADC <= LineIn(sense) / MicIn / DMicIn, | ||
132 | * 1 SPDIF OUT => SPDIF Trasmitter(sense) | ||
133 | */ | ||
134 | #define CS4210_DAC_NID 0x02 | ||
135 | #define CS4210_ADC_NID 0x03 | ||
136 | #define CS421X_VENDOR_NID 0x0B | ||
137 | #define CS421X_DMIC_PIN_NID 0x09 /* Port E */ | ||
138 | #define CS421X_SPDIF_PIN_NID 0x0A /* Port H */ | ||
139 | |||
140 | #define CS421X_IDX_DEV_CFG 0x01 | ||
141 | #define CS421X_IDX_ADC_CFG 0x02 | ||
142 | #define CS421X_IDX_DAC_CFG 0x03 | ||
143 | #define CS421X_IDX_SPK_CTL 0x04 | ||
144 | |||
145 | #define SPDIF_EVENT 0x04 | ||
114 | 146 | ||
115 | static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) | 147 | static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) |
116 | { | 148 | { |
117 | snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0, | 149 | struct cs_spec *spec = codec->spec; |
150 | snd_hda_codec_write(codec, spec->vendor_nid, 0, | ||
118 | AC_VERB_SET_COEF_INDEX, idx); | 151 | AC_VERB_SET_COEF_INDEX, idx); |
119 | return snd_hda_codec_read(codec, CS420X_VENDOR_NID, 0, | 152 | return snd_hda_codec_read(codec, spec->vendor_nid, 0, |
120 | AC_VERB_GET_PROC_COEF, 0); | 153 | AC_VERB_GET_PROC_COEF, 0); |
121 | } | 154 | } |
122 | 155 | ||
123 | static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx, | 156 | static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx, |
124 | unsigned int coef) | 157 | unsigned int coef) |
125 | { | 158 | { |
126 | snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0, | 159 | struct cs_spec *spec = codec->spec; |
160 | snd_hda_codec_write(codec, spec->vendor_nid, 0, | ||
127 | AC_VERB_SET_COEF_INDEX, idx); | 161 | AC_VERB_SET_COEF_INDEX, idx); |
128 | snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0, | 162 | snd_hda_codec_write(codec, spec->vendor_nid, 0, |
129 | AC_VERB_SET_PROC_COEF, coef); | 163 | AC_VERB_SET_PROC_COEF, coef); |
130 | } | 164 | } |
131 | 165 | ||
@@ -347,15 +381,12 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | |||
347 | nid = codec->start_nid; | 381 | nid = codec->start_nid; |
348 | for (i = 0; i < codec->num_nodes; i++, nid++) { | 382 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
349 | unsigned int type; | 383 | unsigned int type; |
350 | int idx; | ||
351 | type = get_wcaps_type(get_wcaps(codec, nid)); | 384 | type = get_wcaps_type(get_wcaps(codec, nid)); |
352 | if (type != AC_WID_AUD_IN) | 385 | if (type != AC_WID_AUD_IN) |
353 | continue; | 386 | continue; |
354 | idx = snd_hda_get_conn_index(codec, nid, pin, 0); | 387 | *idxp = snd_hda_get_conn_index(codec, nid, pin, false); |
355 | if (idx >= 0) { | 388 | if (*idxp >= 0) |
356 | *idxp = idx; | ||
357 | return nid; | 389 | return nid; |
358 | } | ||
359 | } | 390 | } |
360 | return 0; | 391 | return 0; |
361 | } | 392 | } |
@@ -835,6 +866,8 @@ static int build_digital_input(struct hda_codec *codec) | |||
835 | 866 | ||
836 | /* | 867 | /* |
837 | * auto-mute and auto-mic switching | 868 | * auto-mute and auto-mic switching |
869 | * CS421x auto-output redirecting | ||
870 | * HP/SPK/SPDIF | ||
838 | */ | 871 | */ |
839 | 872 | ||
840 | static void cs_automute(struct hda_codec *codec) | 873 | static void cs_automute(struct hda_codec *codec) |
@@ -842,9 +875,25 @@ static void cs_automute(struct hda_codec *codec) | |||
842 | struct cs_spec *spec = codec->spec; | 875 | struct cs_spec *spec = codec->spec; |
843 | struct auto_pin_cfg *cfg = &spec->autocfg; | 876 | struct auto_pin_cfg *cfg = &spec->autocfg; |
844 | unsigned int hp_present; | 877 | unsigned int hp_present; |
878 | unsigned int spdif_present; | ||
845 | hda_nid_t nid; | 879 | hda_nid_t nid; |
846 | int i; | 880 | int i; |
847 | 881 | ||
882 | spdif_present = 0; | ||
883 | if (cfg->dig_outs) { | ||
884 | nid = cfg->dig_out_pins[0]; | ||
885 | if (is_jack_detectable(codec, nid)) { | ||
886 | /* | ||
887 | TODO: SPDIF output redirect when SENSE_B is enabled. | ||
888 | Shared (SENSE_A) jack (e.g HP/mini-TOSLINK) | ||
889 | assumed. | ||
890 | */ | ||
891 | if (snd_hda_jack_detect(codec, nid) | ||
892 | /* && spec->sense_b */) | ||
893 | spdif_present = 1; | ||
894 | } | ||
895 | } | ||
896 | |||
848 | hp_present = 0; | 897 | hp_present = 0; |
849 | for (i = 0; i < cfg->hp_outs; i++) { | 898 | for (i = 0; i < cfg->hp_outs; i++) { |
850 | nid = cfg->hp_pins[i]; | 899 | nid = cfg->hp_pins[i]; |
@@ -854,11 +903,19 @@ static void cs_automute(struct hda_codec *codec) | |||
854 | if (hp_present) | 903 | if (hp_present) |
855 | break; | 904 | break; |
856 | } | 905 | } |
906 | |||
907 | /* mute speakers if spdif or hp jack is plugged in */ | ||
857 | for (i = 0; i < cfg->speaker_outs; i++) { | 908 | for (i = 0; i < cfg->speaker_outs; i++) { |
858 | nid = cfg->speaker_pins[i]; | 909 | nid = cfg->speaker_pins[i]; |
859 | snd_hda_codec_write(codec, nid, 0, | 910 | snd_hda_codec_write(codec, nid, 0, |
860 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 911 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
861 | hp_present ? 0 : PIN_OUT); | 912 | hp_present ? 0 : PIN_OUT); |
913 | /* detect on spdif is specific to CS421x */ | ||
914 | if (spec->vendor_nid == CS421X_VENDOR_NID) { | ||
915 | snd_hda_codec_write(codec, nid, 0, | ||
916 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
917 | spdif_present ? 0 : PIN_OUT); | ||
918 | } | ||
862 | } | 919 | } |
863 | if (spec->board_config == CS420X_MBP53 || | 920 | if (spec->board_config == CS420X_MBP53 || |
864 | spec->board_config == CS420X_MBP55 || | 921 | spec->board_config == CS420X_MBP55 || |
@@ -867,21 +924,62 @@ static void cs_automute(struct hda_codec *codec) | |||
867 | snd_hda_codec_write(codec, 0x01, 0, | 924 | snd_hda_codec_write(codec, 0x01, 0, |
868 | AC_VERB_SET_GPIO_DATA, gpio); | 925 | AC_VERB_SET_GPIO_DATA, gpio); |
869 | } | 926 | } |
927 | |||
928 | /* specific to CS421x */ | ||
929 | if (spec->vendor_nid == CS421X_VENDOR_NID) { | ||
930 | /* mute HPs if spdif jack (SENSE_B) is present */ | ||
931 | for (i = 0; i < cfg->hp_outs; i++) { | ||
932 | nid = cfg->hp_pins[i]; | ||
933 | snd_hda_codec_write(codec, nid, 0, | ||
934 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
935 | (spdif_present && spec->sense_b) ? 0 : PIN_HP); | ||
936 | } | ||
937 | |||
938 | /* SPDIF TX on/off */ | ||
939 | if (cfg->dig_outs) { | ||
940 | nid = cfg->dig_out_pins[0]; | ||
941 | snd_hda_codec_write(codec, nid, 0, | ||
942 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
943 | spdif_present ? PIN_OUT : 0); | ||
944 | |||
945 | } | ||
946 | /* Update board GPIOs if neccessary ... */ | ||
947 | } | ||
870 | } | 948 | } |
871 | 949 | ||
950 | /* | ||
951 | * Auto-input redirect for CS421x | ||
952 | * Switch max 3 inputs of a single ADC (nid 3) | ||
953 | */ | ||
954 | |||
872 | static void cs_automic(struct hda_codec *codec) | 955 | static void cs_automic(struct hda_codec *codec) |
873 | { | 956 | { |
874 | struct cs_spec *spec = codec->spec; | 957 | struct cs_spec *spec = codec->spec; |
875 | struct auto_pin_cfg *cfg = &spec->autocfg; | 958 | struct auto_pin_cfg *cfg = &spec->autocfg; |
876 | hda_nid_t nid; | 959 | hda_nid_t nid; |
877 | unsigned int present; | 960 | unsigned int present; |
878 | 961 | ||
879 | nid = cfg->inputs[spec->automic_idx].pin; | 962 | nid = cfg->inputs[spec->automic_idx].pin; |
880 | present = snd_hda_jack_detect(codec, nid); | 963 | present = snd_hda_jack_detect(codec, nid); |
881 | if (present) | 964 | |
882 | change_cur_input(codec, spec->automic_idx, 0); | 965 | /* specific to CS421x, single ADC */ |
883 | else | 966 | if (spec->vendor_nid == CS421X_VENDOR_NID) { |
884 | change_cur_input(codec, !spec->automic_idx, 0); | 967 | if (present) { |
968 | spec->last_input = spec->cur_input; | ||
969 | spec->cur_input = spec->automic_idx; | ||
970 | } else { | ||
971 | spec->cur_input = spec->last_input; | ||
972 | } | ||
973 | |||
974 | snd_hda_codec_write_cache(codec, spec->cur_adc, 0, | ||
975 | AC_VERB_SET_CONNECT_SEL, | ||
976 | spec->adc_idx[spec->cur_input]); | ||
977 | } else { | ||
978 | if (present) | ||
979 | change_cur_input(codec, spec->automic_idx, 0); | ||
980 | else | ||
981 | change_cur_input(codec, !spec->automic_idx, 0); | ||
982 | } | ||
885 | } | 983 | } |
886 | 984 | ||
887 | /* | 985 | /* |
@@ -911,23 +1009,28 @@ static void init_output(struct hda_codec *codec) | |||
911 | for (i = 0; i < cfg->line_outs; i++) | 1009 | for (i = 0; i < cfg->line_outs; i++) |
912 | snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, | 1010 | snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, |
913 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 1011 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
1012 | /* HP */ | ||
914 | for (i = 0; i < cfg->hp_outs; i++) { | 1013 | for (i = 0; i < cfg->hp_outs; i++) { |
915 | hda_nid_t nid = cfg->hp_pins[i]; | 1014 | hda_nid_t nid = cfg->hp_pins[i]; |
916 | snd_hda_codec_write(codec, nid, 0, | 1015 | snd_hda_codec_write(codec, nid, 0, |
917 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | 1016 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); |
918 | if (!cfg->speaker_outs) | 1017 | if (!cfg->speaker_outs) |
919 | continue; | 1018 | continue; |
920 | if (is_jack_detectable(codec, nid)) { | 1019 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
921 | snd_hda_codec_write(codec, nid, 0, | 1020 | snd_hda_codec_write(codec, nid, 0, |
922 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1021 | AC_VERB_SET_UNSOLICITED_ENABLE, |
923 | AC_USRSP_EN | HP_EVENT); | 1022 | AC_USRSP_EN | HP_EVENT); |
924 | spec->hp_detect = 1; | 1023 | spec->hp_detect = 1; |
925 | } | 1024 | } |
926 | } | 1025 | } |
1026 | |||
1027 | /* Speaker */ | ||
927 | for (i = 0; i < cfg->speaker_outs; i++) | 1028 | for (i = 0; i < cfg->speaker_outs; i++) |
928 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, | 1029 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, |
929 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 1030 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
930 | if (spec->hp_detect) | 1031 | |
1032 | /* SPDIF is enabled on presence detect for CS421x */ | ||
1033 | if (spec->hp_detect || spec->spdif_detect) | ||
931 | cs_automute(codec); | 1034 | cs_automute(codec); |
932 | } | 1035 | } |
933 | 1036 | ||
@@ -961,19 +1064,31 @@ static void init_input(struct hda_codec *codec) | |||
961 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1064 | AC_VERB_SET_UNSOLICITED_ENABLE, |
962 | AC_USRSP_EN | MIC_EVENT); | 1065 | AC_USRSP_EN | MIC_EVENT); |
963 | } | 1066 | } |
964 | change_cur_input(codec, spec->cur_input, 1); | 1067 | /* specific to CS421x */ |
965 | if (spec->mic_detect) | 1068 | if (spec->vendor_nid == CS421X_VENDOR_NID) { |
966 | cs_automic(codec); | 1069 | if (spec->mic_detect) |
967 | 1070 | cs_automic(codec); | |
968 | coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ | 1071 | else { |
969 | if (is_active_pin(codec, CS_DMIC2_PIN_NID)) | 1072 | spec->cur_adc = spec->adc_nid[spec->cur_input]; |
970 | coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */ | 1073 | snd_hda_codec_write(codec, spec->cur_adc, 0, |
971 | if (is_active_pin(codec, CS_DMIC1_PIN_NID)) | 1074 | AC_VERB_SET_CONNECT_SEL, |
972 | coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0 | 1075 | spec->adc_idx[spec->cur_input]); |
973 | * No effect if SPDIF_OUT2 is selected in | 1076 | } |
974 | * IDX_SPDIF_CTL. | 1077 | } else { |
975 | */ | 1078 | change_cur_input(codec, spec->cur_input, 1); |
976 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); | 1079 | if (spec->mic_detect) |
1080 | cs_automic(codec); | ||
1081 | |||
1082 | coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ | ||
1083 | if (is_active_pin(codec, CS_DMIC2_PIN_NID)) | ||
1084 | coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ | ||
1085 | if (is_active_pin(codec, CS_DMIC1_PIN_NID)) | ||
1086 | coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off | ||
1087 | * No effect if SPDIF_OUT2 is | ||
1088 | * selected in IDX_SPDIF_CTL. | ||
1089 | */ | ||
1090 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); | ||
1091 | } | ||
977 | } | 1092 | } |
978 | 1093 | ||
979 | static const struct hda_verb cs_coef_init_verbs[] = { | 1094 | static const struct hda_verb cs_coef_init_verbs[] = { |
@@ -1221,16 +1336,16 @@ static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { | |||
1221 | [CS420X_IMAC27] = imac27_pincfgs, | 1336 | [CS420X_IMAC27] = imac27_pincfgs, |
1222 | }; | 1337 | }; |
1223 | 1338 | ||
1224 | static void fix_pincfg(struct hda_codec *codec, int model) | 1339 | static void fix_pincfg(struct hda_codec *codec, int model, |
1340 | const struct cs_pincfg **pin_configs) | ||
1225 | { | 1341 | { |
1226 | const struct cs_pincfg *cfg = cs_pincfgs[model]; | 1342 | const struct cs_pincfg *cfg = pin_configs[model]; |
1227 | if (!cfg) | 1343 | if (!cfg) |
1228 | return; | 1344 | return; |
1229 | for (; cfg->nid; cfg++) | 1345 | for (; cfg->nid; cfg++) |
1230 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); | 1346 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); |
1231 | } | 1347 | } |
1232 | 1348 | ||
1233 | |||
1234 | static int patch_cs420x(struct hda_codec *codec) | 1349 | static int patch_cs420x(struct hda_codec *codec) |
1235 | { | 1350 | { |
1236 | struct cs_spec *spec; | 1351 | struct cs_spec *spec; |
@@ -1241,11 +1356,13 @@ static int patch_cs420x(struct hda_codec *codec) | |||
1241 | return -ENOMEM; | 1356 | return -ENOMEM; |
1242 | codec->spec = spec; | 1357 | codec->spec = spec; |
1243 | 1358 | ||
1359 | spec->vendor_nid = CS420X_VENDOR_NID; | ||
1360 | |||
1244 | spec->board_config = | 1361 | spec->board_config = |
1245 | snd_hda_check_board_config(codec, CS420X_MODELS, | 1362 | snd_hda_check_board_config(codec, CS420X_MODELS, |
1246 | cs420x_models, cs420x_cfg_tbl); | 1363 | cs420x_models, cs420x_cfg_tbl); |
1247 | if (spec->board_config >= 0) | 1364 | if (spec->board_config >= 0) |
1248 | fix_pincfg(codec, spec->board_config); | 1365 | fix_pincfg(codec, spec->board_config, cs_pincfgs); |
1249 | 1366 | ||
1250 | switch (spec->board_config) { | 1367 | switch (spec->board_config) { |
1251 | case CS420X_IMAC27: | 1368 | case CS420X_IMAC27: |
@@ -1272,6 +1389,562 @@ static int patch_cs420x(struct hda_codec *codec) | |||
1272 | return err; | 1389 | return err; |
1273 | } | 1390 | } |
1274 | 1391 | ||
1392 | /* | ||
1393 | * Cirrus Logic CS4210 | ||
1394 | * | ||
1395 | * 1 DAC => HP(sense) / Speakers, | ||
1396 | * 1 ADC <= LineIn(sense) / MicIn / DMicIn, | ||
1397 | * 1 SPDIF OUT => SPDIF Trasmitter(sense) | ||
1398 | */ | ||
1399 | |||
1400 | /* CS4210 board names */ | ||
1401 | static const char *cs421x_models[CS421X_MODELS] = { | ||
1402 | [CS421X_CDB4210] = "cdb4210", | ||
1403 | }; | ||
1404 | |||
1405 | static const struct snd_pci_quirk cs421x_cfg_tbl[] = { | ||
1406 | /* Test Intel board + CDB2410 */ | ||
1407 | SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210), | ||
1408 | {} /* terminator */ | ||
1409 | }; | ||
1410 | |||
1411 | /* CS4210 board pinconfigs */ | ||
1412 | /* Default CS4210 (CDB4210)*/ | ||
1413 | static const struct cs_pincfg cdb4210_pincfgs[] = { | ||
1414 | { 0x05, 0x0321401f }, | ||
1415 | { 0x06, 0x90170010 }, | ||
1416 | { 0x07, 0x03813031 }, | ||
1417 | { 0x08, 0xb7a70037 }, | ||
1418 | { 0x09, 0xb7a6003e }, | ||
1419 | { 0x0a, 0x034510f0 }, | ||
1420 | {} /* terminator */ | ||
1421 | }; | ||
1422 | |||
1423 | static const struct cs_pincfg *cs421x_pincfgs[CS421X_MODELS] = { | ||
1424 | [CS421X_CDB4210] = cdb4210_pincfgs, | ||
1425 | }; | ||
1426 | |||
1427 | static const struct hda_verb cs421x_coef_init_verbs[] = { | ||
1428 | {0x0B, AC_VERB_SET_PROC_STATE, 1}, | ||
1429 | {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG}, | ||
1430 | /* | ||
1431 | Disable Coefficient Index Auto-Increment(DAI)=1, | ||
1432 | PDREF=0 | ||
1433 | */ | ||
1434 | {0x0B, AC_VERB_SET_PROC_COEF, 0x0001 }, | ||
1435 | |||
1436 | {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG}, | ||
1437 | /* ADC SZCMode = Digital Soft Ramp */ | ||
1438 | {0x0B, AC_VERB_SET_PROC_COEF, 0x0002 }, | ||
1439 | |||
1440 | {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DAC_CFG}, | ||
1441 | {0x0B, AC_VERB_SET_PROC_COEF, | ||
1442 | (0x0002 /* DAC SZCMode = Digital Soft Ramp */ | ||
1443 | | 0x0004 /* Mute DAC on FIFO error */ | ||
1444 | | 0x0008 /* Enable DAC High Pass Filter */ | ||
1445 | )}, | ||
1446 | {} /* terminator */ | ||
1447 | }; | ||
1448 | |||
1449 | /* Errata: CS4210 rev A1 Silicon | ||
1450 | * | ||
1451 | * http://www.cirrus.com/en/pubs/errata/ | ||
1452 | * | ||
1453 | * Description: | ||
1454 | * 1. Performance degredation is present in the ADC. | ||
1455 | * 2. Speaker output is not completely muted upon HP detect. | ||
1456 | * 3. Noise is present when clipping occurs on the amplified | ||
1457 | * speaker outputs. | ||
1458 | * | ||
1459 | * Workaround: | ||
1460 | * The following verb sequence written to the registers during | ||
1461 | * initialization will correct the issues listed above. | ||
1462 | */ | ||
1463 | |||
1464 | static const struct hda_verb cs421x_coef_init_verbs_A1_silicon_fixes[] = { | ||
1465 | {0x0B, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ | ||
1466 | |||
1467 | {0x0B, AC_VERB_SET_COEF_INDEX, 0x0006}, | ||
1468 | {0x0B, AC_VERB_SET_PROC_COEF, 0x9999}, /* Test mode: on */ | ||
1469 | |||
1470 | {0x0B, AC_VERB_SET_COEF_INDEX, 0x000A}, | ||
1471 | {0x0B, AC_VERB_SET_PROC_COEF, 0x14CB}, /* Chop double */ | ||
1472 | |||
1473 | {0x0B, AC_VERB_SET_COEF_INDEX, 0x0011}, | ||
1474 | {0x0B, AC_VERB_SET_PROC_COEF, 0xA2D0}, /* Increase ADC current */ | ||
1475 | |||
1476 | {0x0B, AC_VERB_SET_COEF_INDEX, 0x001A}, | ||
1477 | {0x0B, AC_VERB_SET_PROC_COEF, 0x02A9}, /* Mute speaker */ | ||
1478 | |||
1479 | {0x0B, AC_VERB_SET_COEF_INDEX, 0x001B}, | ||
1480 | {0x0B, AC_VERB_SET_PROC_COEF, 0X1006}, /* Remove noise */ | ||
1481 | |||
1482 | {} /* terminator */ | ||
1483 | }; | ||
1484 | |||
1485 | /* Speaker Amp Gain is controlled by the vendor widget's coef 4 */ | ||
1486 | static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0); | ||
1487 | |||
1488 | static int cs421x_boost_vol_info(struct snd_kcontrol *kcontrol, | ||
1489 | struct snd_ctl_elem_info *uinfo) | ||
1490 | { | ||
1491 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1492 | uinfo->count = 1; | ||
1493 | uinfo->value.integer.min = 0; | ||
1494 | uinfo->value.integer.max = 3; | ||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static int cs421x_boost_vol_get(struct snd_kcontrol *kcontrol, | ||
1499 | struct snd_ctl_elem_value *ucontrol) | ||
1500 | { | ||
1501 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1502 | |||
1503 | ucontrol->value.integer.value[0] = | ||
1504 | cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL) & 0x0003; | ||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol, | ||
1509 | struct snd_ctl_elem_value *ucontrol) | ||
1510 | { | ||
1511 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1512 | |||
1513 | unsigned int vol = ucontrol->value.integer.value[0]; | ||
1514 | unsigned int coef = | ||
1515 | cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL); | ||
1516 | unsigned int original_coef = coef; | ||
1517 | |||
1518 | coef &= ~0x0003; | ||
1519 | coef |= (vol & 0x0003); | ||
1520 | if (original_coef == coef) | ||
1521 | return 0; | ||
1522 | else { | ||
1523 | cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef); | ||
1524 | return 1; | ||
1525 | } | ||
1526 | } | ||
1527 | |||
1528 | static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = { | ||
1529 | |||
1530 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1531 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1532 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1533 | .name = "Speaker Boost Playback Volume", | ||
1534 | .info = cs421x_boost_vol_info, | ||
1535 | .get = cs421x_boost_vol_get, | ||
1536 | .put = cs421x_boost_vol_put, | ||
1537 | .tlv = { .p = cs421x_speaker_boost_db_scale }, | ||
1538 | }; | ||
1539 | |||
1540 | static void cs421x_pinmux_init(struct hda_codec *codec) | ||
1541 | { | ||
1542 | struct cs_spec *spec = codec->spec; | ||
1543 | unsigned int def_conf, coef; | ||
1544 | |||
1545 | /* GPIO, DMIC_SCL, DMIC_SDA and SENSE_B are multiplexed */ | ||
1546 | coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG); | ||
1547 | |||
1548 | if (spec->gpio_mask) | ||
1549 | coef |= 0x0008; /* B1,B2 are GPIOs */ | ||
1550 | else | ||
1551 | coef &= ~0x0008; | ||
1552 | |||
1553 | if (spec->sense_b) | ||
1554 | coef |= 0x0010; /* B2 is SENSE_B, not inverted */ | ||
1555 | else | ||
1556 | coef &= ~0x0010; | ||
1557 | |||
1558 | cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef); | ||
1559 | |||
1560 | if ((spec->gpio_mask || spec->sense_b) && | ||
1561 | is_active_pin(codec, CS421X_DMIC_PIN_NID)) { | ||
1562 | |||
1563 | /* | ||
1564 | GPIO or SENSE_B forced - disconnect the DMIC pin. | ||
1565 | */ | ||
1566 | def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID); | ||
1567 | def_conf &= ~AC_DEFCFG_PORT_CONN; | ||
1568 | def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT); | ||
1569 | snd_hda_codec_set_pincfg(codec, CS421X_DMIC_PIN_NID, def_conf); | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | static void init_cs421x_digital(struct hda_codec *codec) | ||
1574 | { | ||
1575 | struct cs_spec *spec = codec->spec; | ||
1576 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1577 | int i; | ||
1578 | |||
1579 | |||
1580 | for (i = 0; i < cfg->dig_outs; i++) { | ||
1581 | hda_nid_t nid = cfg->dig_out_pins[i]; | ||
1582 | if (!cfg->speaker_outs) | ||
1583 | continue; | ||
1584 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { | ||
1585 | |||
1586 | snd_hda_codec_write(codec, nid, 0, | ||
1587 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1588 | AC_USRSP_EN | SPDIF_EVENT); | ||
1589 | spec->spdif_detect = 1; | ||
1590 | } | ||
1591 | } | ||
1592 | } | ||
1593 | |||
1594 | static int cs421x_init(struct hda_codec *codec) | ||
1595 | { | ||
1596 | struct cs_spec *spec = codec->spec; | ||
1597 | |||
1598 | snd_hda_sequence_write(codec, cs421x_coef_init_verbs); | ||
1599 | snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes); | ||
1600 | |||
1601 | cs421x_pinmux_init(codec); | ||
1602 | |||
1603 | if (spec->gpio_mask) { | ||
1604 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, | ||
1605 | spec->gpio_mask); | ||
1606 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, | ||
1607 | spec->gpio_dir); | ||
1608 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, | ||
1609 | spec->gpio_data); | ||
1610 | } | ||
1611 | |||
1612 | init_output(codec); | ||
1613 | init_input(codec); | ||
1614 | init_cs421x_digital(codec); | ||
1615 | |||
1616 | return 0; | ||
1617 | } | ||
1618 | |||
1619 | /* | ||
1620 | * CS4210 Input MUX (1 ADC) | ||
1621 | */ | ||
1622 | static int cs421x_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
1623 | struct snd_ctl_elem_info *uinfo) | ||
1624 | { | ||
1625 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1626 | struct cs_spec *spec = codec->spec; | ||
1627 | |||
1628 | return snd_hda_input_mux_info(&spec->input_mux, uinfo); | ||
1629 | } | ||
1630 | |||
1631 | static int cs421x_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
1632 | struct snd_ctl_elem_value *ucontrol) | ||
1633 | { | ||
1634 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1635 | struct cs_spec *spec = codec->spec; | ||
1636 | |||
1637 | ucontrol->value.enumerated.item[0] = spec->cur_input; | ||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1641 | static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
1642 | struct snd_ctl_elem_value *ucontrol) | ||
1643 | { | ||
1644 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1645 | struct cs_spec *spec = codec->spec; | ||
1646 | |||
1647 | return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol, | ||
1648 | spec->adc_nid[0], &spec->cur_input); | ||
1649 | |||
1650 | } | ||
1651 | |||
1652 | static struct snd_kcontrol_new cs421x_capture_source = { | ||
1653 | |||
1654 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1655 | .name = "Capture Source", | ||
1656 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
1657 | .info = cs421x_mux_enum_info, | ||
1658 | .get = cs421x_mux_enum_get, | ||
1659 | .put = cs421x_mux_enum_put, | ||
1660 | }; | ||
1661 | |||
1662 | static int cs421x_add_input_volume_control(struct hda_codec *codec, int item) | ||
1663 | { | ||
1664 | struct cs_spec *spec = codec->spec; | ||
1665 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1666 | const struct hda_input_mux *imux = &spec->input_mux; | ||
1667 | hda_nid_t pin = cfg->inputs[item].pin; | ||
1668 | struct snd_kcontrol *kctl; | ||
1669 | u32 caps; | ||
1670 | |||
1671 | if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP)) | ||
1672 | return 0; | ||
1673 | |||
1674 | caps = query_amp_caps(codec, pin, HDA_INPUT); | ||
1675 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | ||
1676 | if (caps <= 1) | ||
1677 | return 0; | ||
1678 | |||
1679 | return add_volume(codec, imux->items[item].label, 0, | ||
1680 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl); | ||
1681 | } | ||
1682 | |||
1683 | /* add a (input-boost) volume control to the given input pin */ | ||
1684 | static int build_cs421x_input(struct hda_codec *codec) | ||
1685 | { | ||
1686 | struct cs_spec *spec = codec->spec; | ||
1687 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1688 | struct hda_input_mux *imux = &spec->input_mux; | ||
1689 | int i, err, type_idx; | ||
1690 | const char *label; | ||
1691 | |||
1692 | if (!spec->num_inputs) | ||
1693 | return 0; | ||
1694 | |||
1695 | /* make bind-capture */ | ||
1696 | spec->capture_bind[0] = make_bind_capture(codec, &snd_hda_bind_sw); | ||
1697 | spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); | ||
1698 | for (i = 0; i < 2; i++) { | ||
1699 | struct snd_kcontrol *kctl; | ||
1700 | int n; | ||
1701 | if (!spec->capture_bind[i]) | ||
1702 | return -ENOMEM; | ||
1703 | kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); | ||
1704 | if (!kctl) | ||
1705 | return -ENOMEM; | ||
1706 | kctl->private_value = (long)spec->capture_bind[i]; | ||
1707 | err = snd_hda_ctl_add(codec, 0, kctl); | ||
1708 | if (err < 0) | ||
1709 | return err; | ||
1710 | for (n = 0; n < AUTO_PIN_LAST; n++) { | ||
1711 | if (!spec->adc_nid[n]) | ||
1712 | continue; | ||
1713 | err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]); | ||
1714 | if (err < 0) | ||
1715 | return err; | ||
1716 | } | ||
1717 | } | ||
1718 | |||
1719 | /* Add Input MUX Items + Capture Volume/Switch */ | ||
1720 | for (i = 0; i < spec->num_inputs; i++) { | ||
1721 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
1722 | snd_hda_add_imux_item(imux, label, spec->adc_idx[i], &type_idx); | ||
1723 | |||
1724 | err = cs421x_add_input_volume_control(codec, i); | ||
1725 | if (err < 0) | ||
1726 | return err; | ||
1727 | } | ||
1728 | |||
1729 | /* | ||
1730 | Add 'Capture Source' Switch if | ||
1731 | * 2 inputs and no mic detec | ||
1732 | * 3 inputs | ||
1733 | */ | ||
1734 | if ((spec->num_inputs == 2 && !spec->mic_detect) || | ||
1735 | (spec->num_inputs == 3)) { | ||
1736 | |||
1737 | err = snd_hda_ctl_add(codec, spec->adc_nid[0], | ||
1738 | snd_ctl_new1(&cs421x_capture_source, codec)); | ||
1739 | if (err < 0) | ||
1740 | return err; | ||
1741 | } | ||
1742 | |||
1743 | return 0; | ||
1744 | } | ||
1745 | |||
1746 | /* Single DAC (Mute/Gain) */ | ||
1747 | static int build_cs421x_output(struct hda_codec *codec) | ||
1748 | { | ||
1749 | hda_nid_t dac = CS4210_DAC_NID; | ||
1750 | struct cs_spec *spec = codec->spec; | ||
1751 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1752 | struct snd_kcontrol *kctl; | ||
1753 | int err; | ||
1754 | char *name = "HP/Speakers"; | ||
1755 | |||
1756 | fix_volume_caps(codec, dac); | ||
1757 | if (!spec->vmaster_sw) { | ||
1758 | err = add_vmaster(codec, dac); | ||
1759 | if (err < 0) | ||
1760 | return err; | ||
1761 | } | ||
1762 | |||
1763 | err = add_mute(codec, name, 0, | ||
1764 | HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); | ||
1765 | if (err < 0) | ||
1766 | return err; | ||
1767 | err = snd_ctl_add_slave(spec->vmaster_sw, kctl); | ||
1768 | if (err < 0) | ||
1769 | return err; | ||
1770 | |||
1771 | err = add_volume(codec, name, 0, | ||
1772 | HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); | ||
1773 | if (err < 0) | ||
1774 | return err; | ||
1775 | err = snd_ctl_add_slave(spec->vmaster_vol, kctl); | ||
1776 | if (err < 0) | ||
1777 | return err; | ||
1778 | |||
1779 | if (cfg->speaker_outs) { | ||
1780 | err = snd_hda_ctl_add(codec, 0, | ||
1781 | snd_ctl_new1(&cs421x_speaker_bost_ctl, codec)); | ||
1782 | if (err < 0) | ||
1783 | return err; | ||
1784 | } | ||
1785 | return err; | ||
1786 | } | ||
1787 | |||
1788 | static int cs421x_build_controls(struct hda_codec *codec) | ||
1789 | { | ||
1790 | int err; | ||
1791 | |||
1792 | err = build_cs421x_output(codec); | ||
1793 | if (err < 0) | ||
1794 | return err; | ||
1795 | err = build_cs421x_input(codec); | ||
1796 | if (err < 0) | ||
1797 | return err; | ||
1798 | err = build_digital_output(codec); | ||
1799 | if (err < 0) | ||
1800 | return err; | ||
1801 | return cs421x_init(codec); | ||
1802 | } | ||
1803 | |||
1804 | static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1805 | { | ||
1806 | switch ((res >> 26) & 0x3f) { | ||
1807 | case HP_EVENT: | ||
1808 | case SPDIF_EVENT: | ||
1809 | cs_automute(codec); | ||
1810 | break; | ||
1811 | |||
1812 | case MIC_EVENT: | ||
1813 | cs_automic(codec); | ||
1814 | break; | ||
1815 | } | ||
1816 | } | ||
1817 | |||
1818 | static int parse_cs421x_input(struct hda_codec *codec) | ||
1819 | { | ||
1820 | struct cs_spec *spec = codec->spec; | ||
1821 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1822 | int i; | ||
1823 | |||
1824 | for (i = 0; i < cfg->num_inputs; i++) { | ||
1825 | hda_nid_t pin = cfg->inputs[i].pin; | ||
1826 | spec->adc_nid[i] = get_adc(codec, pin, &spec->adc_idx[i]); | ||
1827 | spec->cur_input = spec->last_input = i; | ||
1828 | spec->num_inputs++; | ||
1829 | |||
1830 | /* check whether the automatic mic switch is available */ | ||
1831 | if (is_ext_mic(codec, i) && cfg->num_inputs >= 2) { | ||
1832 | spec->mic_detect = 1; | ||
1833 | spec->automic_idx = i; | ||
1834 | } | ||
1835 | } | ||
1836 | return 0; | ||
1837 | } | ||
1838 | |||
1839 | static int cs421x_parse_auto_config(struct hda_codec *codec) | ||
1840 | { | ||
1841 | struct cs_spec *spec = codec->spec; | ||
1842 | int err; | ||
1843 | |||
1844 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); | ||
1845 | if (err < 0) | ||
1846 | return err; | ||
1847 | err = parse_output(codec); | ||
1848 | if (err < 0) | ||
1849 | return err; | ||
1850 | err = parse_cs421x_input(codec); | ||
1851 | if (err < 0) | ||
1852 | return err; | ||
1853 | err = parse_digital_output(codec); | ||
1854 | if (err < 0) | ||
1855 | return err; | ||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1859 | #ifdef CONFIG_PM | ||
1860 | /* | ||
1861 | Manage PDREF, when transitioning to D3hot | ||
1862 | (DAC,ADC) -> D3, PDREF=1, AFG->D3 | ||
1863 | */ | ||
1864 | static int cs421x_suspend(struct hda_codec *codec, pm_message_t state) | ||
1865 | { | ||
1866 | unsigned int coef; | ||
1867 | |||
1868 | snd_hda_shutup_pins(codec); | ||
1869 | |||
1870 | snd_hda_codec_write(codec, CS4210_DAC_NID, 0, | ||
1871 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
1872 | snd_hda_codec_write(codec, CS4210_ADC_NID, 0, | ||
1873 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
1874 | |||
1875 | coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG); | ||
1876 | coef |= 0x0004; /* PDREF */ | ||
1877 | cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef); | ||
1878 | |||
1879 | return 0; | ||
1880 | } | ||
1881 | #endif | ||
1882 | |||
1883 | static struct hda_codec_ops cs4210_patch_ops = { | ||
1884 | .build_controls = cs421x_build_controls, | ||
1885 | .build_pcms = cs_build_pcms, | ||
1886 | .init = cs421x_init, | ||
1887 | .free = cs_free, | ||
1888 | .unsol_event = cs421x_unsol_event, | ||
1889 | #ifdef CONFIG_PM | ||
1890 | .suspend = cs421x_suspend, | ||
1891 | #endif | ||
1892 | }; | ||
1893 | |||
1894 | static int patch_cs421x(struct hda_codec *codec) | ||
1895 | { | ||
1896 | struct cs_spec *spec; | ||
1897 | int err; | ||
1898 | |||
1899 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1900 | if (!spec) | ||
1901 | return -ENOMEM; | ||
1902 | codec->spec = spec; | ||
1903 | |||
1904 | spec->vendor_nid = CS421X_VENDOR_NID; | ||
1905 | |||
1906 | spec->board_config = | ||
1907 | snd_hda_check_board_config(codec, CS421X_MODELS, | ||
1908 | cs421x_models, cs421x_cfg_tbl); | ||
1909 | if (spec->board_config >= 0) | ||
1910 | fix_pincfg(codec, spec->board_config, cs421x_pincfgs); | ||
1911 | /* | ||
1912 | Setup GPIO/SENSE for each board (if used) | ||
1913 | */ | ||
1914 | switch (spec->board_config) { | ||
1915 | case CS421X_CDB4210: | ||
1916 | snd_printd("CS4210 board: %s\n", | ||
1917 | cs421x_models[spec->board_config]); | ||
1918 | /* spec->gpio_mask = 3; | ||
1919 | spec->gpio_dir = 3; | ||
1920 | spec->gpio_data = 3; | ||
1921 | */ | ||
1922 | spec->sense_b = 1; | ||
1923 | |||
1924 | break; | ||
1925 | } | ||
1926 | |||
1927 | /* | ||
1928 | Update the GPIO/DMIC/SENSE_B pinmux before the configuration | ||
1929 | is auto-parsed. If GPIO or SENSE_B is forced, DMIC input | ||
1930 | is disabled. | ||
1931 | */ | ||
1932 | cs421x_pinmux_init(codec); | ||
1933 | |||
1934 | err = cs421x_parse_auto_config(codec); | ||
1935 | if (err < 0) | ||
1936 | goto error; | ||
1937 | |||
1938 | codec->patch_ops = cs4210_patch_ops; | ||
1939 | |||
1940 | return 0; | ||
1941 | |||
1942 | error: | ||
1943 | kfree(codec->spec); | ||
1944 | codec->spec = NULL; | ||
1945 | return err; | ||
1946 | } | ||
1947 | |||
1275 | 1948 | ||
1276 | /* | 1949 | /* |
1277 | * patch entries | 1950 | * patch entries |
@@ -1279,11 +1952,13 @@ static int patch_cs420x(struct hda_codec *codec) | |||
1279 | static const struct hda_codec_preset snd_hda_preset_cirrus[] = { | 1952 | static const struct hda_codec_preset snd_hda_preset_cirrus[] = { |
1280 | { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, | 1953 | { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, |
1281 | { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, | 1954 | { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, |
1955 | { .id = 0x10134210, .name = "CS4210", .patch = patch_cs421x }, | ||
1282 | {} /* terminator */ | 1956 | {} /* terminator */ |
1283 | }; | 1957 | }; |
1284 | 1958 | ||
1285 | MODULE_ALIAS("snd-hda-codec-id:10134206"); | 1959 | MODULE_ALIAS("snd-hda-codec-id:10134206"); |
1286 | MODULE_ALIAS("snd-hda-codec-id:10134207"); | 1960 | MODULE_ALIAS("snd-hda-codec-id:10134207"); |
1961 | MODULE_ALIAS("snd-hda-codec-id:10134210"); | ||
1287 | 1962 | ||
1288 | MODULE_LICENSE("GPL"); | 1963 | MODULE_LICENSE("GPL"); |
1289 | MODULE_DESCRIPTION("Cirrus Logic HD-audio codec"); | 1964 | MODULE_DESCRIPTION("Cirrus Logic HD-audio codec"); |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 884f67b8f4e0..502fc9499453 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -446,6 +446,19 @@ static int conexant_init_jacks(struct hda_codec *codec) | |||
446 | return 0; | 446 | return 0; |
447 | } | 447 | } |
448 | 448 | ||
449 | static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg, | ||
450 | unsigned int power_state) | ||
451 | { | ||
452 | if (power_state == AC_PWRST_D3) | ||
453 | msleep(100); | ||
454 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
455 | power_state); | ||
456 | /* partial workaround for "azx_get_response timeout" */ | ||
457 | if (power_state == AC_PWRST_D0) | ||
458 | msleep(10); | ||
459 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | ||
460 | } | ||
461 | |||
449 | static int conexant_init(struct hda_codec *codec) | 462 | static int conexant_init(struct hda_codec *codec) |
450 | { | 463 | { |
451 | struct conexant_spec *spec = codec->spec; | 464 | struct conexant_spec *spec = codec->spec; |
@@ -588,6 +601,7 @@ static const struct hda_codec_ops conexant_patch_ops = { | |||
588 | .build_pcms = conexant_build_pcms, | 601 | .build_pcms = conexant_build_pcms, |
589 | .init = conexant_init, | 602 | .init = conexant_init, |
590 | .free = conexant_free, | 603 | .free = conexant_free, |
604 | .set_power_state = conexant_set_power, | ||
591 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 605 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
592 | .suspend = conexant_suspend, | 606 | .suspend = conexant_suspend, |
593 | #endif | 607 | #endif |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 52ce07534e5b..694327ae8b71 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2386,7 +2386,7 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state) | |||
2386 | } | 2386 | } |
2387 | #endif | 2387 | #endif |
2388 | 2388 | ||
2389 | #ifdef SND_HDA_NEEDS_RESUME | 2389 | #ifdef CONFIG_PM |
2390 | static int alc_resume(struct hda_codec *codec) | 2390 | static int alc_resume(struct hda_codec *codec) |
2391 | { | 2391 | { |
2392 | msleep(150); /* to avoid pop noise */ | 2392 | msleep(150); /* to avoid pop noise */ |
@@ -2406,7 +2406,7 @@ static const struct hda_codec_ops alc_patch_ops = { | |||
2406 | .init = alc_init, | 2406 | .init = alc_init, |
2407 | .free = alc_free, | 2407 | .free = alc_free, |
2408 | .unsol_event = alc_unsol_event, | 2408 | .unsol_event = alc_unsol_event, |
2409 | #ifdef SND_HDA_NEEDS_RESUME | 2409 | #ifdef CONFIG_PM |
2410 | .resume = alc_resume, | 2410 | .resume = alc_resume, |
2411 | #endif | 2411 | #endif |
2412 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2412 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -2801,7 +2801,8 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
2801 | int i; | 2801 | int i; |
2802 | 2802 | ||
2803 | again: | 2803 | again: |
2804 | spec->multiout.num_dacs = 0; | 2804 | /* set num_dacs once to full for alc_auto_look_for_dac() */ |
2805 | spec->multiout.num_dacs = cfg->line_outs; | ||
2805 | spec->multiout.hp_nid = 0; | 2806 | spec->multiout.hp_nid = 0; |
2806 | spec->multiout.extra_out_nid[0] = 0; | 2807 | spec->multiout.extra_out_nid[0] = 0; |
2807 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); | 2808 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); |
@@ -2834,6 +2835,8 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
2834 | } | 2835 | } |
2835 | } | 2836 | } |
2836 | 2837 | ||
2838 | /* re-count num_dacs and squash invalid entries */ | ||
2839 | spec->multiout.num_dacs = 0; | ||
2837 | for (i = 0; i < cfg->line_outs; i++) { | 2840 | for (i = 0; i < cfg->line_outs; i++) { |
2838 | if (spec->private_dac_nids[i]) | 2841 | if (spec->private_dac_nids[i]) |
2839 | spec->multiout.num_dacs++; | 2842 | spec->multiout.num_dacs++; |
@@ -4410,7 +4413,7 @@ static void alc269_shutup(struct hda_codec *codec) | |||
4410 | } | 4413 | } |
4411 | } | 4414 | } |
4412 | 4415 | ||
4413 | #ifdef SND_HDA_NEEDS_RESUME | 4416 | #ifdef CONFIG_PM |
4414 | static int alc269_resume(struct hda_codec *codec) | 4417 | static int alc269_resume(struct hda_codec *codec) |
4415 | { | 4418 | { |
4416 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | 4419 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { |
@@ -4433,7 +4436,7 @@ static int alc269_resume(struct hda_codec *codec) | |||
4433 | hda_call_check_power_status(codec, 0x01); | 4436 | hda_call_check_power_status(codec, 0x01); |
4434 | return 0; | 4437 | return 0; |
4435 | } | 4438 | } |
4436 | #endif /* SND_HDA_NEEDS_RESUME */ | 4439 | #endif /* CONFIG_PM */ |
4437 | 4440 | ||
4438 | static void alc269_fixup_hweq(struct hda_codec *codec, | 4441 | static void alc269_fixup_hweq(struct hda_codec *codec, |
4439 | const struct alc_fixup *fix, int action) | 4442 | const struct alc_fixup *fix, int action) |
@@ -4725,7 +4728,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
4725 | spec->vmaster_nid = 0x02; | 4728 | spec->vmaster_nid = 0x02; |
4726 | 4729 | ||
4727 | codec->patch_ops = alc_patch_ops; | 4730 | codec->patch_ops = alc_patch_ops; |
4728 | #ifdef SND_HDA_NEEDS_RESUME | 4731 | #ifdef CONFIG_PM |
4729 | codec->patch_ops.resume = alc269_resume; | 4732 | codec->patch_ops.resume = alc269_resume; |
4730 | #endif | 4733 | #endif |
4731 | if (board_config == ALC_MODEL_AUTO) | 4734 | if (board_config == ALC_MODEL_AUTO) |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 56425a53cf1b..fcf4c7142103 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -95,6 +95,7 @@ enum { | |||
95 | STAC_92HD83XXX_PWR_REF, | 95 | STAC_92HD83XXX_PWR_REF, |
96 | STAC_DELL_S14, | 96 | STAC_DELL_S14, |
97 | STAC_92HD83XXX_HP, | 97 | STAC_92HD83XXX_HP, |
98 | STAC_92HD83XXX_HP_cNB11_INTQUAD, | ||
98 | STAC_HP_DV7_4000, | 99 | STAC_HP_DV7_4000, |
99 | STAC_92HD83XXX_MODELS | 100 | STAC_92HD83XXX_MODELS |
100 | }; | 101 | }; |
@@ -1636,10 +1637,17 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = { | |||
1636 | 0x40f000f0, 0x40f000f0, | 1637 | 0x40f000f0, 0x40f000f0, |
1637 | }; | 1638 | }; |
1638 | 1639 | ||
1640 | static const unsigned int hp_cNB11_intquad_pin_configs[10] = { | ||
1641 | 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, | ||
1642 | 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, | ||
1643 | 0x40f000f0, 0x40f000f0, | ||
1644 | }; | ||
1645 | |||
1639 | static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | 1646 | static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { |
1640 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | 1647 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, |
1641 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, | 1648 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, |
1642 | [STAC_DELL_S14] = dell_s14_pin_configs, | 1649 | [STAC_DELL_S14] = dell_s14_pin_configs, |
1650 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, | ||
1643 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, | 1651 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, |
1644 | }; | 1652 | }; |
1645 | 1653 | ||
@@ -1649,6 +1657,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |||
1649 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", | 1657 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", |
1650 | [STAC_DELL_S14] = "dell-s14", | 1658 | [STAC_DELL_S14] = "dell-s14", |
1651 | [STAC_92HD83XXX_HP] = "hp", | 1659 | [STAC_92HD83XXX_HP] = "hp", |
1660 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", | ||
1652 | [STAC_HP_DV7_4000] = "hp-dv7-4000", | 1661 | [STAC_HP_DV7_4000] = "hp-dv7-4000", |
1653 | }; | 1662 | }; |
1654 | 1663 | ||
@@ -1661,7 +1670,47 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |||
1661 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, | 1670 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, |
1662 | "unknown Dell", STAC_DELL_S14), | 1671 | "unknown Dell", STAC_DELL_S14), |
1663 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, | 1672 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, |
1664 | "HP", STAC_92HD83XXX_HP), | 1673 | "HP", STAC_92HD83XXX_HP), |
1674 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, | ||
1675 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1676 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657, | ||
1677 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1678 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658, | ||
1679 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1680 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659, | ||
1681 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1682 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A, | ||
1683 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1684 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, | ||
1685 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1686 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, | ||
1687 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1688 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, | ||
1689 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1690 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B, | ||
1691 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1692 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C, | ||
1693 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1694 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D, | ||
1695 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1696 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E, | ||
1697 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1698 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F, | ||
1699 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1700 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560, | ||
1701 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1702 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B, | ||
1703 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1704 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C, | ||
1705 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1706 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D, | ||
1707 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1708 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591, | ||
1709 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1710 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592, | ||
1711 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1712 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, | ||
1713 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1665 | {} /* terminator */ | 1714 | {} /* terminator */ |
1666 | }; | 1715 | }; |
1667 | 1716 | ||
@@ -4885,7 +4934,18 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer, | |||
4885 | #define stac927x_proc_hook NULL | 4934 | #define stac927x_proc_hook NULL |
4886 | #endif | 4935 | #endif |
4887 | 4936 | ||
4888 | #ifdef SND_HDA_NEEDS_RESUME | 4937 | #ifdef CONFIG_PM |
4938 | static int stac92xx_pre_resume(struct hda_codec *codec) | ||
4939 | { | ||
4940 | struct sigmatel_spec *spec = codec->spec; | ||
4941 | |||
4942 | /* sync mute LED */ | ||
4943 | if (spec->gpio_led) | ||
4944 | stac_gpio_set(codec, spec->gpio_mask, | ||
4945 | spec->gpio_dir, spec->gpio_data); | ||
4946 | return 0; | ||
4947 | } | ||
4948 | |||
4889 | static int stac92xx_resume(struct hda_codec *codec) | 4949 | static int stac92xx_resume(struct hda_codec *codec) |
4890 | { | 4950 | { |
4891 | struct sigmatel_spec *spec = codec->spec; | 4951 | struct sigmatel_spec *spec = codec->spec; |
@@ -4901,29 +4961,19 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4901 | stac_issue_unsol_event(codec, | 4961 | stac_issue_unsol_event(codec, |
4902 | spec->autocfg.line_out_pins[0]); | 4962 | spec->autocfg.line_out_pins[0]); |
4903 | } | 4963 | } |
4904 | /* sync mute LED */ | ||
4905 | if (spec->gpio_led) | ||
4906 | hda_call_check_power_status(codec, 0x01); | ||
4907 | return 0; | 4964 | return 0; |
4908 | } | 4965 | } |
4909 | 4966 | ||
4967 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4910 | /* | 4968 | /* |
4911 | * using power check for controlling mute led of HP notebooks | 4969 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed |
4912 | * check for mute state only on Speakers (nid = 0x10) | 4970 | * as mute LED state is updated in check_power_status hook |
4913 | * | ||
4914 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise | ||
4915 | * the LED is NOT working properly ! | ||
4916 | * | ||
4917 | * Changed name to reflect that it now works for any designated | ||
4918 | * model, not just HP HDX. | ||
4919 | */ | 4971 | */ |
4920 | 4972 | static int stac92xx_update_led_status(struct hda_codec *codec) | |
4921 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4922 | static int stac92xx_hp_check_power_status(struct hda_codec *codec, | ||
4923 | hda_nid_t nid) | ||
4924 | { | 4973 | { |
4925 | struct sigmatel_spec *spec = codec->spec; | 4974 | struct sigmatel_spec *spec = codec->spec; |
4926 | int i, muted = 1; | 4975 | int i, num_ext_dacs, muted = 1; |
4976 | hda_nid_t nid; | ||
4927 | 4977 | ||
4928 | for (i = 0; i < spec->multiout.num_dacs; i++) { | 4978 | for (i = 0; i < spec->multiout.num_dacs; i++) { |
4929 | nid = spec->multiout.dac_nids[i]; | 4979 | nid = spec->multiout.dac_nids[i]; |
@@ -4933,6 +4983,22 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, | |||
4933 | break; | 4983 | break; |
4934 | } | 4984 | } |
4935 | } | 4985 | } |
4986 | if (muted && spec->multiout.hp_nid) | ||
4987 | if (!(snd_hda_codec_amp_read(codec, | ||
4988 | spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) & | ||
4989 | HDA_AMP_MUTE)) { | ||
4990 | muted = 0; /* HP is not muted */ | ||
4991 | } | ||
4992 | num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid); | ||
4993 | for (i = 0; muted && i < num_ext_dacs; i++) { | ||
4994 | nid = spec->multiout.extra_out_nid[i]; | ||
4995 | if (nid == 0) | ||
4996 | break; | ||
4997 | if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
4998 | HDA_AMP_MUTE)) { | ||
4999 | muted = 0; /* extra output is not muted */ | ||
5000 | } | ||
5001 | } | ||
4936 | if (muted) | 5002 | if (muted) |
4937 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | 5003 | spec->gpio_data &= ~spec->gpio_led; /* orange */ |
4938 | else | 5004 | else |
@@ -4946,6 +5012,17 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, | |||
4946 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | 5012 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); |
4947 | return 0; | 5013 | return 0; |
4948 | } | 5014 | } |
5015 | |||
5016 | /* | ||
5017 | * use power check for controlling mute led of HP notebooks | ||
5018 | */ | ||
5019 | static int stac92xx_check_power_status(struct hda_codec *codec, | ||
5020 | hda_nid_t nid) | ||
5021 | { | ||
5022 | stac92xx_update_led_status(codec); | ||
5023 | |||
5024 | return 0; | ||
5025 | } | ||
4949 | #endif | 5026 | #endif |
4950 | 5027 | ||
4951 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | 5028 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) |
@@ -4953,7 +5030,7 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | |||
4953 | stac92xx_shutup(codec); | 5030 | stac92xx_shutup(codec); |
4954 | return 0; | 5031 | return 0; |
4955 | } | 5032 | } |
4956 | #endif | 5033 | #endif /* CONFIG_PM */ |
4957 | 5034 | ||
4958 | static const struct hda_codec_ops stac92xx_patch_ops = { | 5035 | static const struct hda_codec_ops stac92xx_patch_ops = { |
4959 | .build_controls = stac92xx_build_controls, | 5036 | .build_controls = stac92xx_build_controls, |
@@ -4961,9 +5038,10 @@ static const struct hda_codec_ops stac92xx_patch_ops = { | |||
4961 | .init = stac92xx_init, | 5038 | .init = stac92xx_init, |
4962 | .free = stac92xx_free, | 5039 | .free = stac92xx_free, |
4963 | .unsol_event = stac92xx_unsol_event, | 5040 | .unsol_event = stac92xx_unsol_event, |
4964 | #ifdef SND_HDA_NEEDS_RESUME | 5041 | #ifdef CONFIG_PM |
4965 | .suspend = stac92xx_suspend, | 5042 | .suspend = stac92xx_suspend, |
4966 | .resume = stac92xx_resume, | 5043 | .resume = stac92xx_resume, |
5044 | .pre_resume = stac92xx_pre_resume, | ||
4967 | #endif | 5045 | #endif |
4968 | .reboot_notify = stac92xx_shutup, | 5046 | .reboot_notify = stac92xx_shutup, |
4969 | }; | 5047 | }; |
@@ -5482,7 +5560,7 @@ again: | |||
5482 | spec->gpio_data |= spec->gpio_led; | 5560 | spec->gpio_data |= spec->gpio_led; |
5483 | /* register check_power_status callback. */ | 5561 | /* register check_power_status callback. */ |
5484 | codec->patch_ops.check_power_status = | 5562 | codec->patch_ops.check_power_status = |
5485 | stac92xx_hp_check_power_status; | 5563 | stac92xx_check_power_status; |
5486 | } | 5564 | } |
5487 | #endif | 5565 | #endif |
5488 | 5566 | ||
@@ -5810,7 +5888,7 @@ again: | |||
5810 | spec->gpio_data |= spec->gpio_led; | 5888 | spec->gpio_data |= spec->gpio_led; |
5811 | /* register check_power_status callback. */ | 5889 | /* register check_power_status callback. */ |
5812 | codec->patch_ops.check_power_status = | 5890 | codec->patch_ops.check_power_status = |
5813 | stac92xx_hp_check_power_status; | 5891 | stac92xx_check_power_status; |
5814 | } | 5892 | } |
5815 | #endif | 5893 | #endif |
5816 | 5894 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index f38160b00e16..84d8798bf33a 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -1708,7 +1708,7 @@ static void via_unsol_event(struct hda_codec *codec, | |||
1708 | via_gpio_control(codec); | 1708 | via_gpio_control(codec); |
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | #ifdef SND_HDA_NEEDS_RESUME | 1711 | #ifdef CONFIG_PM |
1712 | static int via_suspend(struct hda_codec *codec, pm_message_t state) | 1712 | static int via_suspend(struct hda_codec *codec, pm_message_t state) |
1713 | { | 1713 | { |
1714 | struct via_spec *spec = codec->spec; | 1714 | struct via_spec *spec = codec->spec; |
@@ -1736,7 +1736,7 @@ static const struct hda_codec_ops via_patch_ops = { | |||
1736 | .init = via_init, | 1736 | .init = via_init, |
1737 | .free = via_free, | 1737 | .free = via_free, |
1738 | .unsol_event = via_unsol_event, | 1738 | .unsol_event = via_unsol_event, |
1739 | #ifdef SND_HDA_NEEDS_RESUME | 1739 | #ifdef CONFIG_PM |
1740 | .suspend = via_suspend, | 1740 | .suspend = via_suspend, |
1741 | #endif | 1741 | #endif |
1742 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1742 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index ff29380c9ed3..76258f2a2ffb 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -907,6 +907,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, | |||
907 | struct regulator_init_data *init_data, | 907 | struct regulator_init_data *init_data, |
908 | int voltage) | 908 | int voltage) |
909 | { | 909 | { |
910 | dev_err(codec->dev, "this setup needs regulator support in the kernel\n"); | ||
910 | return -EINVAL; | 911 | return -EINVAL; |
911 | } | 912 | } |
912 | 913 | ||
@@ -1218,6 +1219,34 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) | |||
1218 | return 0; | 1219 | return 0; |
1219 | } | 1220 | } |
1220 | 1221 | ||
1222 | static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec) | ||
1223 | { | ||
1224 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
1225 | int ret; | ||
1226 | |||
1227 | /* set internal ldo to 1.2v */ | ||
1228 | ret = ldo_regulator_register(codec, &ldo_init_data, LDO_VOLTAGE); | ||
1229 | if (ret) { | ||
1230 | dev_err(codec->dev, | ||
1231 | "Failed to register vddd internal supplies: %d\n", ret); | ||
1232 | return ret; | ||
1233 | } | ||
1234 | |||
1235 | sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; | ||
1236 | |||
1237 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), | ||
1238 | sgtl5000->supplies); | ||
1239 | |||
1240 | if (ret) { | ||
1241 | ldo_regulator_remove(codec); | ||
1242 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1243 | return ret; | ||
1244 | } | ||
1245 | |||
1246 | dev_info(codec->dev, "Using internal LDO instead of VDDD\n"); | ||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1221 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | 1250 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) |
1222 | { | 1251 | { |
1223 | u16 reg; | 1252 | u16 reg; |
@@ -1235,30 +1264,9 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1235 | if (!ret) | 1264 | if (!ret) |
1236 | external_vddd = 1; | 1265 | external_vddd = 1; |
1237 | else { | 1266 | else { |
1238 | /* set internal ldo to 1.2v */ | 1267 | ret = sgtl5000_replace_vddd_with_ldo(codec); |
1239 | int voltage = LDO_VOLTAGE; | 1268 | if (ret) |
1240 | |||
1241 | ret = ldo_regulator_register(codec, &ldo_init_data, voltage); | ||
1242 | if (ret) { | ||
1243 | dev_err(codec->dev, | ||
1244 | "Failed to register vddd internal supplies: %d\n", | ||
1245 | ret); | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; | ||
1250 | |||
1251 | ret = regulator_bulk_get(codec->dev, | ||
1252 | ARRAY_SIZE(sgtl5000->supplies), | ||
1253 | sgtl5000->supplies); | ||
1254 | |||
1255 | if (ret) { | ||
1256 | ldo_regulator_remove(codec); | ||
1257 | dev_err(codec->dev, | ||
1258 | "Failed to request supplies: %d\n", ret); | ||
1259 | |||
1260 | return ret; | 1269 | return ret; |
1261 | } | ||
1262 | } | 1270 | } |
1263 | 1271 | ||
1264 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | 1272 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), |
@@ -1287,7 +1295,6 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1287 | * roll back to use internal LDO | 1295 | * roll back to use internal LDO |
1288 | */ | 1296 | */ |
1289 | if (external_vddd && rev >= 0x11) { | 1297 | if (external_vddd && rev >= 0x11) { |
1290 | int voltage = LDO_VOLTAGE; | ||
1291 | /* disable all regulator first */ | 1298 | /* disable all regulator first */ |
1292 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | 1299 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), |
1293 | sgtl5000->supplies); | 1300 | sgtl5000->supplies); |
@@ -1295,23 +1302,10 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | |||
1295 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | 1302 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), |
1296 | sgtl5000->supplies); | 1303 | sgtl5000->supplies); |
1297 | 1304 | ||
1298 | ret = ldo_regulator_register(codec, &ldo_init_data, voltage); | 1305 | ret = sgtl5000_replace_vddd_with_ldo(codec); |
1299 | if (ret) | 1306 | if (ret) |
1300 | return ret; | 1307 | return ret; |
1301 | 1308 | ||
1302 | sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; | ||
1303 | |||
1304 | ret = regulator_bulk_get(codec->dev, | ||
1305 | ARRAY_SIZE(sgtl5000->supplies), | ||
1306 | sgtl5000->supplies); | ||
1307 | if (ret) { | ||
1308 | ldo_regulator_remove(codec); | ||
1309 | dev_err(codec->dev, | ||
1310 | "Failed to request supplies: %d\n", ret); | ||
1311 | |||
1312 | return ret; | ||
1313 | } | ||
1314 | |||
1315 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | 1309 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), |
1316 | sgtl5000->supplies); | 1310 | sgtl5000->supplies); |
1317 | if (ret) | 1311 | if (ret) |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 8499c563a9b5..60d740ebeb5b 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -3409,6 +3409,9 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3409 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); | 3409 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); |
3410 | active &= ~mask; | 3410 | active &= ~mask; |
3411 | 3411 | ||
3412 | /* Acknowledge the interrupts */ | ||
3413 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); | ||
3414 | |||
3412 | if (active & WM8962_FLL_LOCK_EINT) { | 3415 | if (active & WM8962_FLL_LOCK_EINT) { |
3413 | dev_dbg(codec->dev, "FLL locked\n"); | 3416 | dev_dbg(codec->dev, "FLL locked\n"); |
3414 | complete(&wm8962->fll_lock); | 3417 | complete(&wm8962->fll_lock); |
@@ -3433,9 +3436,6 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3433 | msecs_to_jiffies(250)); | 3436 | msecs_to_jiffies(250)); |
3434 | } | 3437 | } |
3435 | 3438 | ||
3436 | /* Acknowledge the interrupts */ | ||
3437 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); | ||
3438 | |||
3439 | return IRQ_HANDLED; | 3439 | return IRQ_HANDLED; |
3440 | } | 3440 | } |
3441 | 3441 | ||
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 9259f1f34899..1f11525d97e8 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
@@ -62,9 +62,9 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream) | |||
62 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); | 62 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); |
63 | 63 | ||
64 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 64 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
65 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1); | 65 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0); |
66 | else | 66 | else |
67 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1); | 67 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0); |
68 | 68 | ||
69 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); | 69 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); |
70 | } | 70 | } |
@@ -80,9 +80,9 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream) | |||
80 | /* Reset transmitter/receiver and sample rate/frame sync generators */ | 80 | /* Reset transmitter/receiver and sample rate/frame sync generators */ |
81 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); | 81 | w = readl(davinci_vc->base + DAVINCI_VC_CTRL); |
82 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 82 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
83 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0); | 83 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1); |
84 | else | 84 | else |
85 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0); | 85 | MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1); |
86 | 86 | ||
87 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); | 87 | writel(w, davinci_vc->base + DAVINCI_VC_CTRL); |
88 | } | 88 | } |
@@ -159,6 +159,7 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
159 | case SNDRV_PCM_TRIGGER_RESUME: | 159 | case SNDRV_PCM_TRIGGER_RESUME: |
160 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 160 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
161 | davinci_vcif_start(substream); | 161 | davinci_vcif_start(substream); |
162 | break; | ||
162 | case SNDRV_PCM_TRIGGER_STOP: | 163 | case SNDRV_PCM_TRIGGER_STOP: |
163 | case SNDRV_PCM_TRIGGER_SUSPEND: | 164 | case SNDRV_PCM_TRIGGER_SUSPEND: |
164 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 165 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 1568eea31f41..c086b78539ee 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <plat/audio.h> | 21 | #include <plat/audio.h> |
22 | 22 | ||
23 | #include "dma.h" | 23 | #include "dma.h" |
24 | #include "idma.h" | ||
24 | #include "i2s.h" | 25 | #include "i2s.h" |
25 | #include "i2s-regs.h" | 26 | #include "i2s-regs.h" |
26 | 27 | ||
@@ -60,6 +61,7 @@ struct i2s_dai { | |||
60 | /* DMA parameters */ | 61 | /* DMA parameters */ |
61 | struct s3c_dma_params dma_playback; | 62 | struct s3c_dma_params dma_playback; |
62 | struct s3c_dma_params dma_capture; | 63 | struct s3c_dma_params dma_capture; |
64 | struct s3c_dma_params idma_playback; | ||
63 | u32 quirks; | 65 | u32 quirks; |
64 | u32 suspend_i2smod; | 66 | u32 suspend_i2smod; |
65 | u32 suspend_i2scon; | 67 | u32 suspend_i2scon; |
@@ -877,6 +879,10 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) | |||
877 | if (i2s->quirks & QUIRK_NEED_RSTCLR) | 879 | if (i2s->quirks & QUIRK_NEED_RSTCLR) |
878 | writel(CON_RSTCLR, i2s->addr + I2SCON); | 880 | writel(CON_RSTCLR, i2s->addr + I2SCON); |
879 | 881 | ||
882 | if (i2s->quirks & QUIRK_SEC_DAI) | ||
883 | idma_reg_addr_init((void *)i2s->addr, | ||
884 | i2s->sec_dai->idma_playback.dma_addr); | ||
885 | |||
880 | probe_exit: | 886 | probe_exit: |
881 | /* Reset any constraint on RFS and BFS */ | 887 | /* Reset any constraint on RFS and BFS */ |
882 | i2s->rfs = 0; | 888 | i2s->rfs = 0; |
@@ -1077,6 +1083,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev) | |||
1077 | sec_dai->dma_playback.dma_size = 4; | 1083 | sec_dai->dma_playback.dma_size = 4; |
1078 | sec_dai->base = regs_base; | 1084 | sec_dai->base = regs_base; |
1079 | sec_dai->quirks = quirks; | 1085 | sec_dai->quirks = quirks; |
1086 | sec_dai->idma_playback.dma_addr = i2s_cfg->idma_addr; | ||
1080 | sec_dai->pri_dai = pri_dai; | 1087 | sec_dai->pri_dai = pri_dai; |
1081 | pri_dai->sec_dai = sec_dai; | 1088 | pri_dai->sec_dai = sec_dai; |
1082 | } | 1089 | } |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e44267f66216..83ad8ca27490 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -577,6 +577,7 @@ int snd_soc_suspend(struct device *dev) | |||
577 | case SND_SOC_BIAS_OFF: | 577 | case SND_SOC_BIAS_OFF: |
578 | codec->driver->suspend(codec, PMSG_SUSPEND); | 578 | codec->driver->suspend(codec, PMSG_SUSPEND); |
579 | codec->suspended = 1; | 579 | codec->suspended = 1; |
580 | codec->cache_sync = 1; | ||
580 | break; | 581 | break; |
581 | default: | 582 | default: |
582 | dev_dbg(codec->dev, "CODEC is on over suspend\n"); | 583 | dev_dbg(codec->dev, "CODEC is on over suspend\n"); |
@@ -1140,7 +1141,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | |||
1140 | } | 1141 | } |
1141 | } | 1142 | } |
1142 | cpu_dai->probed = 1; | 1143 | cpu_dai->probed = 1; |
1143 | /* mark cpu_dai as probed and add to card cpu_dai list */ | 1144 | /* mark cpu_dai as probed and add to card dai list */ |
1144 | list_add(&cpu_dai->card_list, &card->dai_dev_list); | 1145 | list_add(&cpu_dai->card_list, &card->dai_dev_list); |
1145 | } | 1146 | } |
1146 | 1147 | ||
@@ -1171,7 +1172,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | |||
1171 | } | 1172 | } |
1172 | } | 1173 | } |
1173 | 1174 | ||
1174 | /* mark cpu_dai as probed and add to card cpu_dai list */ | 1175 | /* mark codec_dai as probed and add to card dai list */ |
1175 | codec_dai->probed = 1; | 1176 | codec_dai->probed = 1; |
1176 | list_add(&codec_dai->card_list, &card->dai_dev_list); | 1177 | list_add(&codec_dai->card_list, &card->dai_dev_list); |
1177 | } | 1178 | } |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index fbfcda062839..7e15914b3633 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -124,6 +124,36 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | |||
124 | return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); | 124 | return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); |
125 | } | 125 | } |
126 | 126 | ||
127 | /* get snd_card from DAPM context */ | ||
128 | static inline struct snd_card *dapm_get_snd_card( | ||
129 | struct snd_soc_dapm_context *dapm) | ||
130 | { | ||
131 | if (dapm->codec) | ||
132 | return dapm->codec->card->snd_card; | ||
133 | else if (dapm->platform) | ||
134 | return dapm->platform->card->snd_card; | ||
135 | else | ||
136 | BUG(); | ||
137 | |||
138 | /* unreachable */ | ||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | /* get soc_card from DAPM context */ | ||
143 | static inline struct snd_soc_card *dapm_get_soc_card( | ||
144 | struct snd_soc_dapm_context *dapm) | ||
145 | { | ||
146 | if (dapm->codec) | ||
147 | return dapm->codec->card; | ||
148 | else if (dapm->platform) | ||
149 | return dapm->platform->card; | ||
150 | else | ||
151 | BUG(); | ||
152 | |||
153 | /* unreachable */ | ||
154 | return NULL; | ||
155 | } | ||
156 | |||
127 | static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg) | 157 | static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg) |
128 | { | 158 | { |
129 | if (w->codec) | 159 | if (w->codec) |