diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/atmel/atmel-pcm.c | 14 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-sport.h | 28 | ||||
-rw-r--r-- | sound/soc/codecs/da7210.c | 67 | ||||
-rw-r--r-- | sound/soc/codecs/ssm2602.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8960.c | 209 | ||||
-rw-r--r-- | sound/soc/codecs/wm8960.h | 10 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-evm.c | 16 | ||||
-rw-r--r-- | sound/soc/imx/Kconfig | 8 | ||||
-rw-r--r-- | sound/soc/imx/Makefile | 3 | ||||
-rw-r--r-- | sound/soc/imx/wm1133-ev1.c | 291 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c-i2s-v2.c | 93 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c-i2s-v2.h | 4 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c2412-i2s.h | 4 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s.c | 12 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s.h | 15 | ||||
-rw-r--r-- | sound/soc/soc-cache.c | 83 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 76 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 4 |
18 files changed, 766 insertions, 175 deletions
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index 9ef6b96373f5..fdb255372127 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c | |||
@@ -415,9 +415,12 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
415 | } | 415 | } |
416 | 416 | ||
417 | #ifdef CONFIG_PM | 417 | #ifdef CONFIG_PM |
418 | static int atmel_pcm_suspend(struct snd_soc_dai *dai) | 418 | static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link) |
419 | { | 419 | { |
420 | struct snd_pcm_runtime *runtime = dai->runtime; | 420 | struct snd_pcm *pcm = dai_link->pcm; |
421 | struct snd_pcm_str *stream = &pcm->streams[0]; | ||
422 | struct snd_pcm_substream *substream = stream->substream; | ||
423 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
421 | struct atmel_runtime_data *prtd; | 424 | struct atmel_runtime_data *prtd; |
422 | struct atmel_pcm_dma_params *params; | 425 | struct atmel_pcm_dma_params *params; |
423 | 426 | ||
@@ -439,9 +442,12 @@ static int atmel_pcm_suspend(struct snd_soc_dai *dai) | |||
439 | return 0; | 442 | return 0; |
440 | } | 443 | } |
441 | 444 | ||
442 | static int atmel_pcm_resume(struct snd_soc_dai *dai) | 445 | static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link) |
443 | { | 446 | { |
444 | struct snd_pcm_runtime *runtime = dai->runtime; | 447 | struct snd_pcm *pcm = dai_link->pcm; |
448 | struct snd_pcm_str *stream = &pcm->streams[0]; | ||
449 | struct snd_pcm_substream *substream = stream->substream; | ||
450 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
445 | struct atmel_runtime_data *prtd; | 451 | struct atmel_runtime_data *prtd; |
446 | struct atmel_pcm_dma_params *params; | 452 | struct atmel_pcm_dma_params *params; |
447 | 453 | ||
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h index 2e63dea73e9c..a86e8cc0b2d3 100644 --- a/sound/soc/blackfin/bf5xx-sport.h +++ b/sound/soc/blackfin/bf5xx-sport.h | |||
@@ -34,33 +34,7 @@ | |||
34 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
37 | 37 | #include <asm/bfin_sport.h> | |
38 | struct sport_register { | ||
39 | u16 tcr1; u16 reserved0; | ||
40 | u16 tcr2; u16 reserved1; | ||
41 | u16 tclkdiv; u16 reserved2; | ||
42 | u16 tfsdiv; u16 reserved3; | ||
43 | u32 tx; | ||
44 | u32 reserved_l0; | ||
45 | u32 rx; | ||
46 | u32 reserved_l1; | ||
47 | u16 rcr1; u16 reserved4; | ||
48 | u16 rcr2; u16 reserved5; | ||
49 | u16 rclkdiv; u16 reserved6; | ||
50 | u16 rfsdiv; u16 reserved7; | ||
51 | u16 stat; u16 reserved8; | ||
52 | u16 chnl; u16 reserved9; | ||
53 | u16 mcmc1; u16 reserved10; | ||
54 | u16 mcmc2; u16 reserved11; | ||
55 | u32 mtcs0; | ||
56 | u32 mtcs1; | ||
57 | u32 mtcs2; | ||
58 | u32 mtcs3; | ||
59 | u32 mrcs0; | ||
60 | u32 mrcs1; | ||
61 | u32 mrcs2; | ||
62 | u32 mrcs3; | ||
63 | }; | ||
64 | 38 | ||
65 | #define DESC_ELEMENT_COUNT 9 | 39 | #define DESC_ELEMENT_COUNT 9 |
66 | 40 | ||
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index cf2975a7294a..3bd867de597b 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -74,15 +74,14 @@ | |||
74 | /* INMIX_R bit fields */ | 74 | /* INMIX_R bit fields */ |
75 | #define DA7210_IN_R_EN (1 << 7) | 75 | #define DA7210_IN_R_EN (1 << 7) |
76 | 76 | ||
77 | /* ADC_HPF bit fields */ | ||
78 | #define DA7210_ADC_VOICE_EN (1 << 7) | ||
79 | |||
80 | /* ADC bit fields */ | 77 | /* ADC bit fields */ |
81 | #define DA7210_ADC_L_EN (1 << 3) | 78 | #define DA7210_ADC_L_EN (1 << 3) |
82 | #define DA7210_ADC_R_EN (1 << 7) | 79 | #define DA7210_ADC_R_EN (1 << 7) |
83 | 80 | ||
84 | /* DAC_HPF fields */ | 81 | /* DAC/ADC HPF fields */ |
85 | #define DA7210_DAC_VOICE_EN (1 << 7) | 82 | #define DA7210_VOICE_F0_MASK (0x7 << 4) |
83 | #define DA7210_VOICE_F0_25 (1 << 4) | ||
84 | #define DA7210_VOICE_EN (1 << 7) | ||
86 | 85 | ||
87 | /* DAC_SEL bit fields */ | 86 | /* DAC_SEL bit fields */ |
88 | #define DA7210_DAC_L_SRC_DAI_L (4 << 0) | 87 | #define DA7210_DAC_L_SRC_DAI_L (4 << 0) |
@@ -123,7 +122,15 @@ | |||
123 | #define DA7210_PLL_BYP (1 << 6) | 122 | #define DA7210_PLL_BYP (1 << 6) |
124 | 123 | ||
125 | /* PLL bit fields */ | 124 | /* PLL bit fields */ |
126 | #define DA7210_PLL_FS_48000 (11 << 0) | 125 | #define DA7210_PLL_FS_MASK (0xF << 0) |
126 | #define DA7210_PLL_FS_8000 (0x1 << 0) | ||
127 | #define DA7210_PLL_FS_12000 (0x3 << 0) | ||
128 | #define DA7210_PLL_FS_16000 (0x5 << 0) | ||
129 | #define DA7210_PLL_FS_24000 (0x7 << 0) | ||
130 | #define DA7210_PLL_FS_32000 (0x9 << 0) | ||
131 | #define DA7210_PLL_FS_48000 (0xB << 0) | ||
132 | #define DA7210_PLL_FS_96000 (0xF << 0) | ||
133 | |||
127 | 134 | ||
128 | #define DA7210_VERSION "0.0.1" | 135 | #define DA7210_VERSION "0.0.1" |
129 | 136 | ||
@@ -241,7 +248,8 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, | |||
241 | struct snd_soc_device *socdev = rtd->socdev; | 248 | struct snd_soc_device *socdev = rtd->socdev; |
242 | struct snd_soc_codec *codec = socdev->card->codec; | 249 | struct snd_soc_codec *codec = socdev->card->codec; |
243 | u32 dai_cfg1; | 250 | u32 dai_cfg1; |
244 | u32 reg, mask; | 251 | u32 hpf_reg, hpf_mask, hpf_value; |
252 | u32 fs; | ||
245 | 253 | ||
246 | /* set DAI source to Left and Right ADC */ | 254 | /* set DAI source to Left and Right ADC */ |
247 | da7210_write(codec, DA7210_DAI_SRC_SEL, | 255 | da7210_write(codec, DA7210_DAI_SRC_SEL, |
@@ -265,25 +273,46 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, | |||
265 | 273 | ||
266 | da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); | 274 | da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); |
267 | 275 | ||
268 | /* FIXME | 276 | hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ? |
269 | * | 277 | DA7210_DAC_HPF : DA7210_ADC_HPF; |
270 | * It support 48K only now | 278 | |
271 | */ | ||
272 | switch (params_rate(params)) { | 279 | switch (params_rate(params)) { |
280 | case 8000: | ||
281 | fs = DA7210_PLL_FS_8000; | ||
282 | hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; | ||
283 | hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; | ||
284 | break; | ||
285 | case 12000: | ||
286 | fs = DA7210_PLL_FS_12000; | ||
287 | hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; | ||
288 | hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; | ||
289 | break; | ||
290 | case 16000: | ||
291 | fs = DA7210_PLL_FS_16000; | ||
292 | hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN; | ||
293 | hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN; | ||
294 | break; | ||
295 | case 32000: | ||
296 | fs = DA7210_PLL_FS_32000; | ||
297 | hpf_mask = DA7210_VOICE_EN; | ||
298 | hpf_value = 0; | ||
299 | break; | ||
273 | case 48000: | 300 | case 48000: |
274 | if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { | 301 | fs = DA7210_PLL_FS_48000; |
275 | reg = DA7210_DAC_HPF; | 302 | hpf_mask = DA7210_VOICE_EN; |
276 | mask = DA7210_DAC_VOICE_EN; | 303 | hpf_value = 0; |
277 | } else { | 304 | break; |
278 | reg = DA7210_ADC_HPF; | 305 | case 96000: |
279 | mask = DA7210_ADC_VOICE_EN; | 306 | fs = DA7210_PLL_FS_96000; |
280 | } | 307 | hpf_mask = DA7210_VOICE_EN; |
308 | hpf_value = 0; | ||
281 | break; | 309 | break; |
282 | default: | 310 | default: |
283 | return -EINVAL; | 311 | return -EINVAL; |
284 | } | 312 | } |
285 | 313 | ||
286 | snd_soc_update_bits(codec, reg, mask, 0); | 314 | snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value); |
315 | snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs); | ||
287 | 316 | ||
288 | return 0; | 317 | return 0; |
289 | } | 318 | } |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index d2ff1cde6883..942f5dc30801 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -139,6 +139,7 @@ SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0), | |||
139 | SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), | 139 | SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), |
140 | 140 | ||
141 | SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), | 141 | SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), |
142 | SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0), | ||
142 | SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), | 143 | SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), |
143 | 144 | ||
144 | SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), | 145 | SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), |
@@ -604,8 +605,7 @@ static int ssm2602_init(struct snd_soc_device *socdev) | |||
604 | reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); | 605 | reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); |
605 | ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); | 606 | ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); |
606 | /*select Line in as default input*/ | 607 | /*select Line in as default input*/ |
607 | ssm2602_write(codec, SSM2602_APANA, | 608 | ssm2602_write(codec, SSM2602_APANA, APANA_SELECT_DAC | |
608 | APANA_ENABLE_MIC_BOOST2 | APANA_SELECT_DAC | | ||
609 | APANA_ENABLE_MIC_BOOST); | 609 | APANA_ENABLE_MIC_BOOST); |
610 | ssm2602_write(codec, SSM2602_PWR, 0); | 610 | ssm2602_write(codec, SSM2602_PWR, 0); |
611 | 611 | ||
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index d07bcc1e1c60..c2960d3ec6df 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <sound/soc-dapm.h> | 22 | #include <sound/soc-dapm.h> |
23 | #include <sound/initval.h> | 23 | #include <sound/initval.h> |
24 | #include <sound/tlv.h> | 24 | #include <sound/tlv.h> |
25 | #include <sound/wm8960.h> | ||
25 | 26 | ||
26 | #include "wm8960.h" | 27 | #include "wm8960.h" |
27 | 28 | ||
@@ -30,8 +31,14 @@ | |||
30 | struct snd_soc_codec_device soc_codec_dev_wm8960; | 31 | struct snd_soc_codec_device soc_codec_dev_wm8960; |
31 | 32 | ||
32 | /* R25 - Power 1 */ | 33 | /* R25 - Power 1 */ |
34 | #define WM8960_VMID_MASK 0x180 | ||
33 | #define WM8960_VREF 0x40 | 35 | #define WM8960_VREF 0x40 |
34 | 36 | ||
37 | /* R26 - Power 2 */ | ||
38 | #define WM8960_PWR2_LOUT1 0x40 | ||
39 | #define WM8960_PWR2_ROUT1 0x20 | ||
40 | #define WM8960_PWR2_OUT3 0x02 | ||
41 | |||
35 | /* R28 - Anti-pop 1 */ | 42 | /* R28 - Anti-pop 1 */ |
36 | #define WM8960_POBCTRL 0x80 | 43 | #define WM8960_POBCTRL 0x80 |
37 | #define WM8960_BUFDCOPEN 0x10 | 44 | #define WM8960_BUFDCOPEN 0x10 |
@@ -41,6 +48,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8960; | |||
41 | 48 | ||
42 | /* R29 - Anti-pop 2 */ | 49 | /* R29 - Anti-pop 2 */ |
43 | #define WM8960_DISOP 0x40 | 50 | #define WM8960_DISOP 0x40 |
51 | #define WM8960_DRES_MASK 0x30 | ||
44 | 52 | ||
45 | /* | 53 | /* |
46 | * wm8960 register cache | 54 | * wm8960 register cache |
@@ -67,6 +75,9 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { | |||
67 | struct wm8960_priv { | 75 | struct wm8960_priv { |
68 | u16 reg_cache[WM8960_CACHEREGNUM]; | 76 | u16 reg_cache[WM8960_CACHEREGNUM]; |
69 | struct snd_soc_codec codec; | 77 | struct snd_soc_codec codec; |
78 | struct snd_soc_dapm_widget *lout1; | ||
79 | struct snd_soc_dapm_widget *rout1; | ||
80 | struct snd_soc_dapm_widget *out3; | ||
70 | }; | 81 | }; |
71 | 82 | ||
72 | #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) | 83 | #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) |
@@ -225,10 +236,6 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0, | |||
225 | &wm8960_routput_mixer[0], | 236 | &wm8960_routput_mixer[0], |
226 | ARRAY_SIZE(wm8960_routput_mixer)), | 237 | ARRAY_SIZE(wm8960_routput_mixer)), |
227 | 238 | ||
228 | SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0, | ||
229 | &wm8960_mono_out[0], | ||
230 | ARRAY_SIZE(wm8960_mono_out)), | ||
231 | |||
232 | SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), | 239 | SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), |
233 | SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), | 240 | SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), |
234 | 241 | ||
@@ -247,6 +254,17 @@ SND_SOC_DAPM_OUTPUT("SPK_RN"), | |||
247 | SND_SOC_DAPM_OUTPUT("OUT3"), | 254 | SND_SOC_DAPM_OUTPUT("OUT3"), |
248 | }; | 255 | }; |
249 | 256 | ||
257 | static const struct snd_soc_dapm_widget wm8960_dapm_widgets_out3[] = { | ||
258 | SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0, | ||
259 | &wm8960_mono_out[0], | ||
260 | ARRAY_SIZE(wm8960_mono_out)), | ||
261 | }; | ||
262 | |||
263 | /* Represent OUT3 as a PGA so that it gets turned on with LOUT1/ROUT1 */ | ||
264 | static const struct snd_soc_dapm_widget wm8960_dapm_widgets_capless[] = { | ||
265 | SND_SOC_DAPM_PGA("OUT3 VMID", WM8960_POWER2, 1, 0, NULL, 0), | ||
266 | }; | ||
267 | |||
250 | static const struct snd_soc_dapm_route audio_paths[] = { | 268 | static const struct snd_soc_dapm_route audio_paths[] = { |
251 | { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, | 269 | { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, |
252 | { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, | 270 | { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, |
@@ -277,9 +295,6 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
277 | { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , | 295 | { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , |
278 | { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, | 296 | { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, |
279 | 297 | ||
280 | { "Mono Output Mixer", "Left Switch", "Left Output Mixer" }, | ||
281 | { "Mono Output Mixer", "Right Switch", "Right Output Mixer" }, | ||
282 | |||
283 | { "LOUT1 PGA", NULL, "Left Output Mixer" }, | 298 | { "LOUT1 PGA", NULL, "Left Output Mixer" }, |
284 | { "ROUT1 PGA", NULL, "Right Output Mixer" }, | 299 | { "ROUT1 PGA", NULL, "Right Output Mixer" }, |
285 | 300 | ||
@@ -296,17 +311,65 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
296 | { "SPK_LP", NULL, "Left Speaker Output" }, | 311 | { "SPK_LP", NULL, "Left Speaker Output" }, |
297 | { "SPK_RN", NULL, "Right Speaker Output" }, | 312 | { "SPK_RN", NULL, "Right Speaker Output" }, |
298 | { "SPK_RP", NULL, "Right Speaker Output" }, | 313 | { "SPK_RP", NULL, "Right Speaker Output" }, |
314 | }; | ||
315 | |||
316 | static const struct snd_soc_dapm_route audio_paths_out3[] = { | ||
317 | { "Mono Output Mixer", "Left Switch", "Left Output Mixer" }, | ||
318 | { "Mono Output Mixer", "Right Switch", "Right Output Mixer" }, | ||
299 | 319 | ||
300 | { "OUT3", NULL, "Mono Output Mixer", } | 320 | { "OUT3", NULL, "Mono Output Mixer", } |
301 | }; | 321 | }; |
302 | 322 | ||
323 | static const struct snd_soc_dapm_route audio_paths_capless[] = { | ||
324 | { "HP_L", NULL, "OUT3 VMID" }, | ||
325 | { "HP_R", NULL, "OUT3 VMID" }, | ||
326 | |||
327 | { "OUT3 VMID", NULL, "Left Output Mixer" }, | ||
328 | { "OUT3 VMID", NULL, "Right Output Mixer" }, | ||
329 | }; | ||
330 | |||
303 | static int wm8960_add_widgets(struct snd_soc_codec *codec) | 331 | static int wm8960_add_widgets(struct snd_soc_codec *codec) |
304 | { | 332 | { |
333 | struct wm8960_data *pdata = codec->dev->platform_data; | ||
334 | struct wm8960_priv *wm8960 = codec->private_data; | ||
335 | struct snd_soc_dapm_widget *w; | ||
336 | |||
305 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets, | 337 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets, |
306 | ARRAY_SIZE(wm8960_dapm_widgets)); | 338 | ARRAY_SIZE(wm8960_dapm_widgets)); |
307 | 339 | ||
308 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 340 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
309 | 341 | ||
342 | /* In capless mode OUT3 is used to provide VMID for the | ||
343 | * headphone outputs, otherwise it is used as a mono mixer. | ||
344 | */ | ||
345 | if (pdata && pdata->capless) { | ||
346 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_capless, | ||
347 | ARRAY_SIZE(wm8960_dapm_widgets_capless)); | ||
348 | |||
349 | snd_soc_dapm_add_routes(codec, audio_paths_capless, | ||
350 | ARRAY_SIZE(audio_paths_capless)); | ||
351 | } else { | ||
352 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_out3, | ||
353 | ARRAY_SIZE(wm8960_dapm_widgets_out3)); | ||
354 | |||
355 | snd_soc_dapm_add_routes(codec, audio_paths_out3, | ||
356 | ARRAY_SIZE(audio_paths_out3)); | ||
357 | } | ||
358 | |||
359 | /* We need to power up the headphone output stage out of | ||
360 | * sequence for capless mode. To save scanning the widget | ||
361 | * list each time to find the desired power state do so now | ||
362 | * and save the result. | ||
363 | */ | ||
364 | list_for_each_entry(w, &codec->dapm_widgets, list) { | ||
365 | if (strcmp(w->name, "LOUT1 PGA") == 0) | ||
366 | wm8960->lout1 = w; | ||
367 | if (strcmp(w->name, "ROUT1 PGA") == 0) | ||
368 | wm8960->rout1 = w; | ||
369 | if (strcmp(w->name, "OUT3 VMID") == 0) | ||
370 | wm8960->out3 = w; | ||
371 | } | ||
372 | |||
310 | return 0; | 373 | return 0; |
311 | } | 374 | } |
312 | 375 | ||
@@ -407,10 +470,9 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) | |||
407 | return 0; | 470 | return 0; |
408 | } | 471 | } |
409 | 472 | ||
410 | static int wm8960_set_bias_level(struct snd_soc_codec *codec, | 473 | static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, |
411 | enum snd_soc_bias_level level) | 474 | enum snd_soc_bias_level level) |
412 | { | 475 | { |
413 | struct wm8960_data *pdata = codec->dev->platform_data; | ||
414 | u16 reg; | 476 | u16 reg; |
415 | 477 | ||
416 | switch (level) { | 478 | switch (level) { |
@@ -429,18 +491,8 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, | |||
429 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 491 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
430 | /* Enable anti-pop features */ | 492 | /* Enable anti-pop features */ |
431 | snd_soc_write(codec, WM8960_APOP1, | 493 | snd_soc_write(codec, WM8960_APOP1, |
432 | WM8960_POBCTRL | WM8960_SOFT_ST | | 494 | WM8960_POBCTRL | WM8960_SOFT_ST | |
433 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); | 495 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); |
434 | |||
435 | /* Discharge HP output */ | ||
436 | reg = WM8960_DISOP; | ||
437 | if (pdata) | ||
438 | reg |= pdata->dres << 4; | ||
439 | snd_soc_write(codec, WM8960_APOP2, reg); | ||
440 | |||
441 | msleep(400); | ||
442 | |||
443 | snd_soc_write(codec, WM8960_APOP2, 0); | ||
444 | 496 | ||
445 | /* Enable & ramp VMID at 2x50k */ | 497 | /* Enable & ramp VMID at 2x50k */ |
446 | reg = snd_soc_read(codec, WM8960_POWER1); | 498 | reg = snd_soc_read(codec, WM8960_POWER1); |
@@ -471,8 +523,101 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, | |||
471 | /* Disable VMID and VREF, let them discharge */ | 523 | /* Disable VMID and VREF, let them discharge */ |
472 | snd_soc_write(codec, WM8960_POWER1, 0); | 524 | snd_soc_write(codec, WM8960_POWER1, 0); |
473 | msleep(600); | 525 | msleep(600); |
526 | break; | ||
527 | } | ||
528 | |||
529 | codec->bias_level = level; | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | ||
535 | enum snd_soc_bias_level level) | ||
536 | { | ||
537 | struct wm8960_priv *wm8960 = codec->private_data; | ||
538 | int reg; | ||
539 | |||
540 | switch (level) { | ||
541 | case SND_SOC_BIAS_ON: | ||
542 | break; | ||
543 | |||
544 | case SND_SOC_BIAS_PREPARE: | ||
545 | switch (codec->bias_level) { | ||
546 | case SND_SOC_BIAS_STANDBY: | ||
547 | /* Enable anti pop mode */ | ||
548 | snd_soc_update_bits(codec, WM8960_APOP1, | ||
549 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
550 | WM8960_BUFDCOPEN, | ||
551 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
552 | WM8960_BUFDCOPEN); | ||
553 | |||
554 | /* Enable LOUT1, ROUT1 and OUT3 if they're enabled */ | ||
555 | reg = 0; | ||
556 | if (wm8960->lout1 && wm8960->lout1->power) | ||
557 | reg |= WM8960_PWR2_LOUT1; | ||
558 | if (wm8960->rout1 && wm8960->rout1->power) | ||
559 | reg |= WM8960_PWR2_ROUT1; | ||
560 | if (wm8960->out3 && wm8960->out3->power) | ||
561 | reg |= WM8960_PWR2_OUT3; | ||
562 | snd_soc_update_bits(codec, WM8960_POWER2, | ||
563 | WM8960_PWR2_LOUT1 | | ||
564 | WM8960_PWR2_ROUT1 | | ||
565 | WM8960_PWR2_OUT3, reg); | ||
566 | |||
567 | /* Enable VMID at 2*50k */ | ||
568 | snd_soc_update_bits(codec, WM8960_POWER1, | ||
569 | WM8960_VMID_MASK, 0x80); | ||
570 | |||
571 | /* Ramp */ | ||
572 | msleep(100); | ||
573 | |||
574 | /* Enable VREF */ | ||
575 | snd_soc_update_bits(codec, WM8960_POWER1, | ||
576 | WM8960_VREF, WM8960_VREF); | ||
577 | |||
578 | msleep(100); | ||
579 | break; | ||
580 | |||
581 | case SND_SOC_BIAS_ON: | ||
582 | /* Enable anti-pop mode */ | ||
583 | snd_soc_update_bits(codec, WM8960_APOP1, | ||
584 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
585 | WM8960_BUFDCOPEN, | ||
586 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
587 | WM8960_BUFDCOPEN); | ||
588 | |||
589 | /* Disable VMID and VREF */ | ||
590 | snd_soc_update_bits(codec, WM8960_POWER1, | ||
591 | WM8960_VREF | WM8960_VMID_MASK, 0); | ||
592 | break; | ||
593 | |||
594 | default: | ||
595 | break; | ||
596 | } | ||
597 | break; | ||
598 | |||
599 | case SND_SOC_BIAS_STANDBY: | ||
600 | switch (codec->bias_level) { | ||
601 | case SND_SOC_BIAS_PREPARE: | ||
602 | /* Disable HP discharge */ | ||
603 | snd_soc_update_bits(codec, WM8960_APOP2, | ||
604 | WM8960_DISOP | WM8960_DRES_MASK, | ||
605 | 0); | ||
606 | |||
607 | /* Disable anti-pop features */ | ||
608 | snd_soc_update_bits(codec, WM8960_APOP1, | ||
609 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
610 | WM8960_BUFDCOPEN, | ||
611 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
612 | WM8960_BUFDCOPEN); | ||
613 | break; | ||
614 | |||
615 | default: | ||
616 | break; | ||
617 | } | ||
618 | break; | ||
474 | 619 | ||
475 | snd_soc_write(codec, WM8960_APOP1, 0); | 620 | case SND_SOC_BIAS_OFF: |
476 | break; | 621 | break; |
477 | } | 622 | } |
478 | 623 | ||
@@ -662,7 +807,7 @@ static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) | |||
662 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 807 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
663 | struct snd_soc_codec *codec = socdev->card->codec; | 808 | struct snd_soc_codec *codec = socdev->card->codec; |
664 | 809 | ||
665 | wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF); | 810 | codec->set_bias_level(codec, SND_SOC_BIAS_OFF); |
666 | return 0; | 811 | return 0; |
667 | } | 812 | } |
668 | 813 | ||
@@ -681,8 +826,8 @@ static int wm8960_resume(struct platform_device *pdev) | |||
681 | codec->hw_write(codec->control_data, data, 2); | 826 | codec->hw_write(codec->control_data, data, 2); |
682 | } | 827 | } |
683 | 828 | ||
684 | wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 829 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
685 | wm8960_set_bias_level(codec, codec->suspend_bias_level); | 830 | codec->set_bias_level(codec, codec->suspend_bias_level); |
686 | return 0; | 831 | return 0; |
687 | } | 832 | } |
688 | 833 | ||
@@ -752,6 +897,8 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
752 | goto err; | 897 | goto err; |
753 | } | 898 | } |
754 | 899 | ||
900 | codec->set_bias_level = wm8960_set_bias_level_out3; | ||
901 | |||
755 | if (!pdata) { | 902 | if (!pdata) { |
756 | dev_warn(codec->dev, "No platform data supplied\n"); | 903 | dev_warn(codec->dev, "No platform data supplied\n"); |
757 | } else { | 904 | } else { |
@@ -759,6 +906,9 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
759 | dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); | 906 | dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); |
760 | pdata->dres = 0; | 907 | pdata->dres = 0; |
761 | } | 908 | } |
909 | |||
910 | if (pdata->capless) | ||
911 | codec->set_bias_level = wm8960_set_bias_level_capless; | ||
762 | } | 912 | } |
763 | 913 | ||
764 | mutex_init(&codec->mutex); | 914 | mutex_init(&codec->mutex); |
@@ -769,7 +919,6 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
769 | codec->name = "WM8960"; | 919 | codec->name = "WM8960"; |
770 | codec->owner = THIS_MODULE; | 920 | codec->owner = THIS_MODULE; |
771 | codec->bias_level = SND_SOC_BIAS_OFF; | 921 | codec->bias_level = SND_SOC_BIAS_OFF; |
772 | codec->set_bias_level = wm8960_set_bias_level; | ||
773 | codec->dai = &wm8960_dai; | 922 | codec->dai = &wm8960_dai; |
774 | codec->num_dai = 1; | 923 | codec->num_dai = 1; |
775 | codec->reg_cache_size = WM8960_CACHEREGNUM; | 924 | codec->reg_cache_size = WM8960_CACHEREGNUM; |
@@ -791,7 +940,7 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
791 | 940 | ||
792 | wm8960_dai.dev = codec->dev; | 941 | wm8960_dai.dev = codec->dev; |
793 | 942 | ||
794 | wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 943 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
795 | 944 | ||
796 | /* Latch the update bits */ | 945 | /* Latch the update bits */ |
797 | reg = snd_soc_read(codec, WM8960_LINVOL); | 946 | reg = snd_soc_read(codec, WM8960_LINVOL); |
@@ -840,7 +989,7 @@ err: | |||
840 | 989 | ||
841 | static void wm8960_unregister(struct wm8960_priv *wm8960) | 990 | static void wm8960_unregister(struct wm8960_priv *wm8960) |
842 | { | 991 | { |
843 | wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); | 992 | wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); |
844 | snd_soc_unregister_dai(&wm8960_dai); | 993 | snd_soc_unregister_dai(&wm8960_dai); |
845 | snd_soc_unregister_codec(&wm8960->codec); | 994 | snd_soc_unregister_codec(&wm8960->codec); |
846 | kfree(wm8960); | 995 | kfree(wm8960); |
@@ -882,7 +1031,7 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); | |||
882 | 1031 | ||
883 | static struct i2c_driver wm8960_i2c_driver = { | 1032 | static struct i2c_driver wm8960_i2c_driver = { |
884 | .driver = { | 1033 | .driver = { |
885 | .name = "WM8960 I2C Codec", | 1034 | .name = "wm8960", |
886 | .owner = THIS_MODULE, | 1035 | .owner = THIS_MODULE, |
887 | }, | 1036 | }, |
888 | .probe = wm8960_i2c_probe, | 1037 | .probe = wm8960_i2c_probe, |
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h index c9af56c9d9d4..d67bfe1300da 100644 --- a/sound/soc/codecs/wm8960.h +++ b/sound/soc/codecs/wm8960.h | |||
@@ -114,14 +114,4 @@ | |||
114 | extern struct snd_soc_dai wm8960_dai; | 114 | extern struct snd_soc_dai wm8960_dai; |
115 | extern struct snd_soc_codec_device soc_codec_dev_wm8960; | 115 | extern struct snd_soc_codec_device soc_codec_dev_wm8960; |
116 | 116 | ||
117 | #define WM8960_DRES_400R 0 | ||
118 | #define WM8960_DRES_200R 1 | ||
119 | #define WM8960_DRES_600R 2 | ||
120 | #define WM8960_DRES_150R 3 | ||
121 | #define WM8960_DRES_MAX 3 | ||
122 | |||
123 | struct wm8960_data { | ||
124 | int dres; | ||
125 | }; | ||
126 | |||
127 | #endif | 117 | #endif |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 7ccbe6684fc2..dba6651547c1 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -81,10 +81,24 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
83 | 83 | ||
84 | static int evm_spdif_hw_params(struct snd_pcm_substream *substream, | ||
85 | struct snd_pcm_hw_params *params) | ||
86 | { | ||
87 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
88 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
89 | |||
90 | /* set cpu DAI configuration */ | ||
91 | return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); | ||
92 | } | ||
93 | |||
84 | static struct snd_soc_ops evm_ops = { | 94 | static struct snd_soc_ops evm_ops = { |
85 | .hw_params = evm_hw_params, | 95 | .hw_params = evm_hw_params, |
86 | }; | 96 | }; |
87 | 97 | ||
98 | static struct snd_soc_ops evm_spdif_ops = { | ||
99 | .hw_params = evm_spdif_hw_params, | ||
100 | }; | ||
101 | |||
88 | /* davinci-evm machine dapm widgets */ | 102 | /* davinci-evm machine dapm widgets */ |
89 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | 103 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { |
90 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | 104 | SND_SOC_DAPM_HP("Headphone Jack", NULL), |
@@ -165,7 +179,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
165 | .stream_name = "spdif", | 179 | .stream_name = "spdif", |
166 | .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], | 180 | .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], |
167 | .codec_dai = &dit_stub_dai, | 181 | .codec_dai = &dit_stub_dai, |
168 | .ops = &evm_ops, | 182 | .ops = &evm_spdif_ops, |
169 | }, | 183 | }, |
170 | }; | 184 | }; |
171 | static struct snd_soc_dai_link da8xx_evm_dai = { | 185 | static struct snd_soc_dai_link da8xx_evm_dai = { |
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index c7d0fd9b7de8..c045da8ff61c 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig | |||
@@ -11,3 +11,11 @@ config SND_IMX_SOC | |||
11 | config SND_MXC_SOC_SSI | 11 | config SND_MXC_SOC_SSI |
12 | tristate | 12 | tristate |
13 | 13 | ||
14 | config SND_MXC_SOC_WM1133_EV1 | ||
15 | tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" | ||
16 | depends on SND_IMX_SOC && EXPERIMENTAL | ||
17 | select SND_SOC_WM8350 | ||
18 | select SND_MXC_SOC_SSI | ||
19 | help | ||
20 | Enable support for audio on the i.MX31ADS with the WM1133-EV1 | ||
21 | PMIC board with WM8835x fitted. | ||
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 9f8bb92ddfcc..2d203635ac11 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile | |||
@@ -9,4 +9,7 @@ obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o | |||
9 | 9 | ||
10 | # i.MX Machine Support | 10 | # i.MX Machine Support |
11 | snd-soc-phycore-ac97-objs := phycore-ac97.o | 11 | snd-soc-phycore-ac97-objs := phycore-ac97.o |
12 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o | ||
13 | |||
12 | obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o | 14 | obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o |
15 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o | ||
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c new file mode 100644 index 000000000000..b75fcde85e88 --- /dev/null +++ b/sound/soc/imx/wm1133-ev1.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * wm1133-ev1.c - Audio for WM1133-EV1 on i.MX31ADS | ||
3 | * | ||
4 | * Copyright (c) 2010 Wolfson Microelectronics plc | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
6 | * | ||
7 | * Based on an earlier driver for the same hardware by Liam Girdwood. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/jack.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/soc-dapm.h> | ||
23 | |||
24 | #include <mach/audmux.h> | ||
25 | |||
26 | #include "imx-ssi.h" | ||
27 | #include "../codecs/wm8350.h" | ||
28 | |||
29 | /* There is a silicon mic on the board optionally connected via a solder pad | ||
30 | * SP1. Define this to enable it. | ||
31 | */ | ||
32 | #undef USE_SIMIC | ||
33 | |||
34 | struct _wm8350_audio { | ||
35 | unsigned int channels; | ||
36 | snd_pcm_format_t format; | ||
37 | unsigned int rate; | ||
38 | unsigned int sysclk; | ||
39 | unsigned int bclkdiv; | ||
40 | unsigned int clkdiv; | ||
41 | unsigned int lr_rate; | ||
42 | }; | ||
43 | |||
44 | /* in order of power consumption per rate (lowest first) */ | ||
45 | static const struct _wm8350_audio wm8350_audio[] = { | ||
46 | /* 16bit mono modes */ | ||
47 | {1, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000 >> 1, | ||
48 | WM8350_BCLK_DIV_48, WM8350_DACDIV_3, 16,}, | ||
49 | |||
50 | /* 16 bit stereo modes */ | ||
51 | {2, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000, | ||
52 | WM8350_BCLK_DIV_48, WM8350_DACDIV_6, 32,}, | ||
53 | {2, SNDRV_PCM_FORMAT_S16_LE, 16000, 12288000, | ||
54 | WM8350_BCLK_DIV_24, WM8350_DACDIV_3, 32,}, | ||
55 | {2, SNDRV_PCM_FORMAT_S16_LE, 32000, 12288000, | ||
56 | WM8350_BCLK_DIV_12, WM8350_DACDIV_1_5, 32,}, | ||
57 | {2, SNDRV_PCM_FORMAT_S16_LE, 48000, 12288000, | ||
58 | WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, | ||
59 | {2, SNDRV_PCM_FORMAT_S16_LE, 96000, 24576000, | ||
60 | WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, | ||
61 | {2, SNDRV_PCM_FORMAT_S16_LE, 11025, 11289600, | ||
62 | WM8350_BCLK_DIV_32, WM8350_DACDIV_4, 32,}, | ||
63 | {2, SNDRV_PCM_FORMAT_S16_LE, 22050, 11289600, | ||
64 | WM8350_BCLK_DIV_16, WM8350_DACDIV_2, 32,}, | ||
65 | {2, SNDRV_PCM_FORMAT_S16_LE, 44100, 11289600, | ||
66 | WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, | ||
67 | {2, SNDRV_PCM_FORMAT_S16_LE, 88200, 22579200, | ||
68 | WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, | ||
69 | |||
70 | /* 24bit stereo modes */ | ||
71 | {2, SNDRV_PCM_FORMAT_S24_LE, 48000, 12288000, | ||
72 | WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, | ||
73 | {2, SNDRV_PCM_FORMAT_S24_LE, 96000, 24576000, | ||
74 | WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, | ||
75 | {2, SNDRV_PCM_FORMAT_S24_LE, 44100, 11289600, | ||
76 | WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, | ||
77 | {2, SNDRV_PCM_FORMAT_S24_LE, 88200, 22579200, | ||
78 | WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, | ||
79 | }; | ||
80 | |||
81 | static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, | ||
82 | struct snd_pcm_hw_params *params) | ||
83 | { | ||
84 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
85 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
86 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
87 | int i, found = 0; | ||
88 | snd_pcm_format_t format = params_format(params); | ||
89 | unsigned int rate = params_rate(params); | ||
90 | unsigned int channels = params_channels(params); | ||
91 | u32 dai_format; | ||
92 | |||
93 | /* find the correct audio parameters */ | ||
94 | for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) { | ||
95 | if (rate == wm8350_audio[i].rate && | ||
96 | format == wm8350_audio[i].format && | ||
97 | channels == wm8350_audio[i].channels) { | ||
98 | found = 1; | ||
99 | break; | ||
100 | } | ||
101 | } | ||
102 | if (!found) | ||
103 | return -EINVAL; | ||
104 | |||
105 | /* codec FLL input is 14.75 MHz from MCLK */ | ||
106 | snd_soc_dai_set_pll(codec_dai, 0, 0, 14750000, wm8350_audio[i].sysclk); | ||
107 | |||
108 | dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
109 | SND_SOC_DAIFMT_CBM_CFM; | ||
110 | |||
111 | /* set codec DAI configuration */ | ||
112 | snd_soc_dai_set_fmt(codec_dai, dai_format); | ||
113 | |||
114 | /* set cpu DAI configuration */ | ||
115 | snd_soc_dai_set_fmt(cpu_dai, dai_format); | ||
116 | |||
117 | /* TODO: The SSI driver should figure this out for us */ | ||
118 | switch (channels) { | ||
119 | case 2: | ||
120 | snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); | ||
121 | break; | ||
122 | case 1: | ||
123 | snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffe, 0xffffffe, 1, 0); | ||
124 | break; | ||
125 | default: | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | /* set MCLK as the codec system clock for DAC and ADC */ | ||
130 | snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_MCLK, | ||
131 | wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN); | ||
132 | |||
133 | /* set codec BCLK division for sample rate */ | ||
134 | snd_soc_dai_set_clkdiv(codec_dai, WM8350_BCLK_CLKDIV, | ||
135 | wm8350_audio[i].bclkdiv); | ||
136 | |||
137 | /* DAI is synchronous and clocked with DAC LRCLK & ADC LRC */ | ||
138 | snd_soc_dai_set_clkdiv(codec_dai, | ||
139 | WM8350_DACLR_CLKDIV, wm8350_audio[i].lr_rate); | ||
140 | snd_soc_dai_set_clkdiv(codec_dai, | ||
141 | WM8350_ADCLR_CLKDIV, wm8350_audio[i].lr_rate); | ||
142 | |||
143 | /* now configure DAC and ADC clocks */ | ||
144 | snd_soc_dai_set_clkdiv(codec_dai, | ||
145 | WM8350_DAC_CLKDIV, wm8350_audio[i].clkdiv); | ||
146 | |||
147 | snd_soc_dai_set_clkdiv(codec_dai, | ||
148 | WM8350_ADC_CLKDIV, wm8350_audio[i].clkdiv); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static struct snd_soc_ops wm1133_ev1_ops = { | ||
154 | .hw_params = wm1133_ev1_hw_params, | ||
155 | }; | ||
156 | |||
157 | static const struct snd_soc_dapm_widget wm1133_ev1_widgets[] = { | ||
158 | #ifdef USE_SIMIC | ||
159 | SND_SOC_DAPM_MIC("SiMIC", NULL), | ||
160 | #endif | ||
161 | SND_SOC_DAPM_MIC("Mic1 Jack", NULL), | ||
162 | SND_SOC_DAPM_MIC("Mic2 Jack", NULL), | ||
163 | SND_SOC_DAPM_LINE("Line In Jack", NULL), | ||
164 | SND_SOC_DAPM_LINE("Line Out Jack", NULL), | ||
165 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
166 | }; | ||
167 | |||
168 | /* imx32ads soc_card audio map */ | ||
169 | static const struct snd_soc_dapm_route wm1133_ev1_map[] = { | ||
170 | |||
171 | #ifdef USE_SIMIC | ||
172 | /* SiMIC --> IN1LN (with automatic bias) via SP1 */ | ||
173 | { "IN1LN", NULL, "Mic Bias" }, | ||
174 | { "Mic Bias", NULL, "SiMIC" }, | ||
175 | #endif | ||
176 | |||
177 | /* Mic 1 Jack --> IN1LN and IN1LP (with automatic bias) */ | ||
178 | { "IN1LN", NULL, "Mic Bias" }, | ||
179 | { "IN1LP", NULL, "Mic1 Jack" }, | ||
180 | { "Mic Bias", NULL, "Mic1 Jack" }, | ||
181 | |||
182 | /* Mic 2 Jack --> IN1RN and IN1RP (with automatic bias) */ | ||
183 | { "IN1RN", NULL, "Mic Bias" }, | ||
184 | { "IN1RP", NULL, "Mic1 Jack" }, | ||
185 | { "Mic Bias", NULL, "Mic1 Jack" }, | ||
186 | |||
187 | /* Line in Jack --> AUX (L+R) */ | ||
188 | { "IN3R", NULL, "Line In Jack" }, | ||
189 | { "IN3L", NULL, "Line In Jack" }, | ||
190 | |||
191 | /* Out1 --> Headphone Jack */ | ||
192 | { "Headphone Jack", NULL, "OUT1R" }, | ||
193 | { "Headphone Jack", NULL, "OUT1L" }, | ||
194 | |||
195 | /* Out1 --> Line Out Jack */ | ||
196 | { "Line Out Jack", NULL, "OUT2R" }, | ||
197 | { "Line Out Jack", NULL, "OUT2L" }, | ||
198 | }; | ||
199 | |||
200 | static struct snd_soc_jack hp_jack; | ||
201 | |||
202 | static struct snd_soc_jack_pin hp_jack_pins[] = { | ||
203 | { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE }, | ||
204 | }; | ||
205 | |||
206 | static int wm1133_ev1_init(struct snd_soc_codec *codec) | ||
207 | { | ||
208 | struct snd_soc_card *card = codec->socdev->card; | ||
209 | |||
210 | snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets, | ||
211 | ARRAY_SIZE(wm1133_ev1_widgets)); | ||
212 | |||
213 | snd_soc_dapm_add_routes(codec, wm1133_ev1_map, | ||
214 | ARRAY_SIZE(wm1133_ev1_map)); | ||
215 | |||
216 | /* Headphone jack detection */ | ||
217 | snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack); | ||
218 | snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), | ||
219 | hp_jack_pins); | ||
220 | wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | |||
226 | static struct snd_soc_dai_link wm1133_ev1_dai = { | ||
227 | .name = "WM1133-EV1", | ||
228 | .stream_name = "Audio", | ||
229 | .cpu_dai = &imx_ssi_pcm_dai[0], | ||
230 | .codec_dai = &wm8350_dai, | ||
231 | .init = wm1133_ev1_init, | ||
232 | .ops = &wm1133_ev1_ops, | ||
233 | .symmetric_rates = 1, | ||
234 | }; | ||
235 | |||
236 | static struct snd_soc_card wm1133_ev1 = { | ||
237 | .name = "WM1133-EV1", | ||
238 | .platform = &imx_soc_platform, | ||
239 | .dai_link = &wm1133_ev1_dai, | ||
240 | .num_links = 1, | ||
241 | }; | ||
242 | |||
243 | static struct snd_soc_device wm1133_ev1_snd_devdata = { | ||
244 | .card = &wm1133_ev1, | ||
245 | .codec_dev = &soc_codec_dev_wm8350, | ||
246 | }; | ||
247 | |||
248 | static struct platform_device *wm1133_ev1_snd_device; | ||
249 | |||
250 | static int __init wm1133_ev1_audio_init(void) | ||
251 | { | ||
252 | int ret; | ||
253 | unsigned int ptcr, pdcr; | ||
254 | |||
255 | /* SSI0 mastered by port 5 */ | ||
256 | ptcr = MXC_AUDMUX_V2_PTCR_SYN | | ||
257 | MXC_AUDMUX_V2_PTCR_TFSDIR | | ||
258 | MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) | | ||
259 | MXC_AUDMUX_V2_PTCR_TCLKDIR | | ||
260 | MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); | ||
261 | pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); | ||
262 | mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr); | ||
263 | |||
264 | ptcr = MXC_AUDMUX_V2_PTCR_SYN; | ||
265 | pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0); | ||
266 | mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr); | ||
267 | |||
268 | wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1); | ||
269 | if (!wm1133_ev1_snd_device) | ||
270 | return -ENOMEM; | ||
271 | |||
272 | platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata); | ||
273 | wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev; | ||
274 | ret = platform_device_add(wm1133_ev1_snd_device); | ||
275 | |||
276 | if (ret) | ||
277 | platform_device_put(wm1133_ev1_snd_device); | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | module_init(wm1133_ev1_audio_init); | ||
282 | |||
283 | static void __exit wm1133_ev1_audio_exit(void) | ||
284 | { | ||
285 | platform_device_unregister(wm1133_ev1_snd_device); | ||
286 | } | ||
287 | module_exit(wm1133_ev1_audio_exit); | ||
288 | |||
289 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
290 | MODULE_DESCRIPTION("Audio for WM1133-EV1 on i.MX31ADS"); | ||
291 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index e994d8374fe6..b846f563cb50 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c | |||
@@ -16,18 +16,12 @@ | |||
16 | * option) any later version. | 16 | * option) any later version. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
23 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
24 | #include <linux/kernel.h> | ||
25 | #include <linux/io.h> | 21 | #include <linux/io.h> |
26 | 22 | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
30 | #include <sound/initval.h> | ||
31 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
32 | 26 | ||
33 | #include <plat/regs-s3c2412-iis.h> | 27 | #include <plat/regs-s3c2412-iis.h> |
@@ -469,29 +463,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
469 | 463 | ||
470 | switch (div_id) { | 464 | switch (div_id) { |
471 | case S3C_I2SV2_DIV_BCLK: | 465 | case S3C_I2SV2_DIV_BCLK: |
472 | if (div > 3) { | 466 | switch (div) { |
473 | /* convert value to bit field */ | 467 | case 16: |
474 | 468 | div = S3C2412_IISMOD_BCLK_16FS; | |
475 | switch (div) { | 469 | break; |
476 | case 16: | ||
477 | div = S3C2412_IISMOD_BCLK_16FS; | ||
478 | break; | ||
479 | 470 | ||
480 | case 32: | 471 | case 32: |
481 | div = S3C2412_IISMOD_BCLK_32FS; | 472 | div = S3C2412_IISMOD_BCLK_32FS; |
482 | break; | 473 | break; |
483 | 474 | ||
484 | case 24: | 475 | case 24: |
485 | div = S3C2412_IISMOD_BCLK_24FS; | 476 | div = S3C2412_IISMOD_BCLK_24FS; |
486 | break; | 477 | break; |
487 | 478 | ||
488 | case 48: | 479 | case 48: |
489 | div = S3C2412_IISMOD_BCLK_48FS; | 480 | div = S3C2412_IISMOD_BCLK_48FS; |
490 | break; | 481 | break; |
491 | 482 | ||
492 | default: | 483 | default: |
493 | return -EINVAL; | 484 | return -EINVAL; |
494 | } | ||
495 | } | 485 | } |
496 | 486 | ||
497 | reg = readl(i2s->regs + S3C2412_IISMOD); | 487 | reg = readl(i2s->regs + S3C2412_IISMOD); |
@@ -502,29 +492,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
502 | break; | 492 | break; |
503 | 493 | ||
504 | case S3C_I2SV2_DIV_RCLK: | 494 | case S3C_I2SV2_DIV_RCLK: |
505 | if (div > 3) { | 495 | switch (div) { |
506 | /* convert value to bit field */ | 496 | case 256: |
507 | 497 | div = S3C2412_IISMOD_RCLK_256FS; | |
508 | switch (div) { | 498 | break; |
509 | case 256: | ||
510 | div = S3C2412_IISMOD_RCLK_256FS; | ||
511 | break; | ||
512 | 499 | ||
513 | case 384: | 500 | case 384: |
514 | div = S3C2412_IISMOD_RCLK_384FS; | 501 | div = S3C2412_IISMOD_RCLK_384FS; |
515 | break; | 502 | break; |
516 | 503 | ||
517 | case 512: | 504 | case 512: |
518 | div = S3C2412_IISMOD_RCLK_512FS; | 505 | div = S3C2412_IISMOD_RCLK_512FS; |
519 | break; | 506 | break; |
520 | 507 | ||
521 | case 768: | 508 | case 768: |
522 | div = S3C2412_IISMOD_RCLK_768FS; | 509 | div = S3C2412_IISMOD_RCLK_768FS; |
523 | break; | 510 | break; |
524 | 511 | ||
525 | default: | 512 | default: |
526 | return -EINVAL; | 513 | return -EINVAL; |
527 | } | ||
528 | } | 514 | } |
529 | 515 | ||
530 | reg = readl(i2s->regs + S3C2412_IISMOD); | 516 | reg = readl(i2s->regs + S3C2412_IISMOD); |
@@ -550,6 +536,21 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
550 | return 0; | 536 | return 0; |
551 | } | 537 | } |
552 | 538 | ||
539 | static snd_pcm_sframes_t s3c2412_i2s_delay(struct snd_pcm_substream *substream, | ||
540 | struct snd_soc_dai *dai) | ||
541 | { | ||
542 | struct s3c_i2sv2_info *i2s = to_info(dai); | ||
543 | u32 reg = readl(i2s->regs + S3C2412_IISFIC); | ||
544 | snd_pcm_sframes_t delay; | ||
545 | |||
546 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
547 | delay = S3C2412_IISFIC_TXCOUNT(reg); | ||
548 | else | ||
549 | delay = S3C2412_IISFIC_RXCOUNT(reg); | ||
550 | |||
551 | return delay; | ||
552 | } | ||
553 | |||
553 | /* default table of all avaialable root fs divisors */ | 554 | /* default table of all avaialable root fs divisors */ |
554 | static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; | 555 | static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; |
555 | 556 | ||
@@ -736,6 +737,10 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) | |||
736 | ops->set_fmt = s3c2412_i2s_set_fmt; | 737 | ops->set_fmt = s3c2412_i2s_set_fmt; |
737 | ops->set_clkdiv = s3c2412_i2s_set_clkdiv; | 738 | ops->set_clkdiv = s3c2412_i2s_set_clkdiv; |
738 | 739 | ||
740 | /* Allow overriding by (for example) IISv4 */ | ||
741 | if (!ops->delay) | ||
742 | ops->delay = s3c2412_i2s_delay; | ||
743 | |||
739 | dai->suspend = s3c2412_i2s_suspend; | 744 | dai->suspend = s3c2412_i2s_suspend; |
740 | dai->resume = s3c2412_i2s_resume; | 745 | dai->resume = s3c2412_i2s_resume; |
741 | 746 | ||
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h index ecf8eaaed1db..b094d3c23cbe 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.h +++ b/sound/soc/s3c24xx/s3c-i2s-v2.h | |||
@@ -25,6 +25,10 @@ | |||
25 | #define S3C_I2SV2_DIV_RCLK (2) | 25 | #define S3C_I2SV2_DIV_RCLK (2) |
26 | #define S3C_I2SV2_DIV_PRESCALER (3) | 26 | #define S3C_I2SV2_DIV_PRESCALER (3) |
27 | 27 | ||
28 | #define S3C_I2SV2_CLKSRC_PCLK 0 | ||
29 | #define S3C_I2SV2_CLKSRC_AUDIOBUS 1 | ||
30 | #define S3C_I2SV2_CLKSRC_CDCLK 2 | ||
31 | |||
28 | /** | 32 | /** |
29 | * struct s3c_i2sv2_info - S3C I2S-V2 information | 33 | * struct s3c_i2sv2_info - S3C I2S-V2 information |
30 | * @dev: The parent device passed to use from the probe. | 34 | * @dev: The parent device passed to use from the probe. |
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h index 92848e54be16..60cac002a830 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/sound/soc/s3c24xx/s3c2412-i2s.h | |||
@@ -21,8 +21,8 @@ | |||
21 | #define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK | 21 | #define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK |
22 | #define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER | 22 | #define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER |
23 | 23 | ||
24 | #define S3C2412_CLKSRC_PCLK (0) | 24 | #define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK |
25 | #define S3C2412_CLKSRC_I2SCLK (1) | 25 | #define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS |
26 | 26 | ||
27 | extern struct clk *s3c2412_get_iisclk(void); | 27 | extern struct clk *s3c2412_get_iisclk(void); |
28 | 28 | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 93ed3aad1631..65528943579b 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c | |||
@@ -12,9 +12,6 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
19 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
20 | #include <linux/io.h> | 17 | #include <linux/io.h> |
@@ -130,15 +127,6 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev, | |||
130 | } | 127 | } |
131 | 128 | ||
132 | 129 | ||
133 | #define S3C64XX_I2S_RATES \ | ||
134 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | ||
135 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
136 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
137 | |||
138 | #define S3C64XX_I2S_FMTS \ | ||
139 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
140 | SNDRV_PCM_FMTBIT_S24_LE) | ||
141 | |||
142 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { | 130 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { |
143 | .set_sysclk = s3c64xx_i2s_set_sysclk, | 131 | .set_sysclk = s3c64xx_i2s_set_sysclk, |
144 | }; | 132 | }; |
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h index abe7253b55fc..53d2a0a0df36 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.h +++ b/sound/soc/s3c24xx/s3c64xx-i2s.h | |||
@@ -23,9 +23,18 @@ struct clk; | |||
23 | #define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK | 23 | #define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK |
24 | #define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER | 24 | #define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER |
25 | 25 | ||
26 | #define S3C64XX_CLKSRC_PCLK (0) | 26 | #define S3C64XX_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK |
27 | #define S3C64XX_CLKSRC_MUX (1) | 27 | #define S3C64XX_CLKSRC_MUX S3C_I2SV2_CLKSRC_AUDIOBUS |
28 | #define S3C64XX_CLKSRC_CDCLK (2) | 28 | #define S3C64XX_CLKSRC_CDCLK S3C_I2SV2_CLKSRC_CDCLK |
29 | |||
30 | #define S3C64XX_I2S_RATES \ | ||
31 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | ||
32 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
33 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
34 | |||
35 | #define S3C64XX_I2S_FMTS \ | ||
36 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
37 | SNDRV_PCM_FMTBIT_S24_LE) | ||
29 | 38 | ||
30 | extern struct snd_soc_dai s3c64xx_i2s_dai[]; | 39 | extern struct snd_soc_dai s3c64xx_i2s_dai[]; |
31 | 40 | ||
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 5869dc3be781..bf593a834f5a 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -366,6 +366,84 @@ static int snd_soc_16_8_spi_write(void *control_data, const char *data, | |||
366 | #define snd_soc_16_8_spi_write NULL | 366 | #define snd_soc_16_8_spi_write NULL |
367 | #endif | 367 | #endif |
368 | 368 | ||
369 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
370 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, | ||
371 | unsigned int r) | ||
372 | { | ||
373 | struct i2c_msg xfer[2]; | ||
374 | u16 reg = cpu_to_be16(r); | ||
375 | u16 data; | ||
376 | int ret; | ||
377 | struct i2c_client *client = codec->control_data; | ||
378 | |||
379 | /* Write register */ | ||
380 | xfer[0].addr = client->addr; | ||
381 | xfer[0].flags = 0; | ||
382 | xfer[0].len = 2; | ||
383 | xfer[0].buf = (u8 *)® | ||
384 | |||
385 | /* Read data */ | ||
386 | xfer[1].addr = client->addr; | ||
387 | xfer[1].flags = I2C_M_RD; | ||
388 | xfer[1].len = 2; | ||
389 | xfer[1].buf = (u8 *)&data; | ||
390 | |||
391 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
392 | if (ret != 2) { | ||
393 | dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | return be16_to_cpu(data); | ||
398 | } | ||
399 | #else | ||
400 | #define snd_soc_16_16_read_i2c NULL | ||
401 | #endif | ||
402 | |||
403 | static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, | ||
404 | unsigned int reg) | ||
405 | { | ||
406 | u16 *cache = codec->reg_cache; | ||
407 | |||
408 | if (reg >= codec->reg_cache_size || | ||
409 | snd_soc_codec_volatile_register(codec, reg)) { | ||
410 | if (codec->cache_only) | ||
411 | return -EINVAL; | ||
412 | |||
413 | return codec->hw_read(codec, reg); | ||
414 | } | ||
415 | |||
416 | return cache[reg]; | ||
417 | } | ||
418 | |||
419 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
420 | unsigned int value) | ||
421 | { | ||
422 | u16 *cache = codec->reg_cache; | ||
423 | u8 data[4]; | ||
424 | int ret; | ||
425 | |||
426 | data[0] = (reg >> 8) & 0xff; | ||
427 | data[1] = reg & 0xff; | ||
428 | data[2] = (value >> 8) & 0xff; | ||
429 | data[3] = value & 0xff; | ||
430 | |||
431 | if (reg < codec->reg_cache_size) | ||
432 | cache[reg] = value; | ||
433 | |||
434 | if (codec->cache_only) { | ||
435 | codec->cache_sync = 1; | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | ret = codec->hw_write(codec->control_data, data, 4); | ||
440 | if (ret == 4) | ||
441 | return 0; | ||
442 | if (ret < 0) | ||
443 | return ret; | ||
444 | else | ||
445 | return -EIO; | ||
446 | } | ||
369 | 447 | ||
370 | static struct { | 448 | static struct { |
371 | int addr_bits; | 449 | int addr_bits; |
@@ -400,6 +478,11 @@ static struct { | |||
400 | .i2c_read = snd_soc_16_8_read_i2c, | 478 | .i2c_read = snd_soc_16_8_read_i2c, |
401 | .spi_write = snd_soc_16_8_spi_write, | 479 | .spi_write = snd_soc_16_8_spi_write, |
402 | }, | 480 | }, |
481 | { | ||
482 | .addr_bits = 16, .data_bits = 16, | ||
483 | .write = snd_soc_16_16_write, .read = snd_soc_16_16_read, | ||
484 | .i2c_read = snd_soc_16_16_read_i2c, | ||
485 | }, | ||
403 | }; | 486 | }; |
404 | 487 | ||
405 | /** | 488 | /** |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c8b0556ef431..06c38d1502b7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -315,7 +315,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) | |||
315 | 315 | ||
316 | if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || | 316 | if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || |
317 | machine->symmetric_rates) { | 317 | machine->symmetric_rates) { |
318 | dev_dbg(card->dev, "Symmetry forces %dHz rate\n", | 318 | dev_dbg(card->dev, "Symmetry forces %dHz rate\n", |
319 | machine->rate); | 319 | machine->rate); |
320 | 320 | ||
321 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | 321 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, |
@@ -454,12 +454,15 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
454 | pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, | 454 | pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, |
455 | runtime->hw.rate_max); | 455 | runtime->hw.rate_max); |
456 | 456 | ||
457 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 457 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
458 | cpu_dai->playback.active = codec_dai->playback.active = 1; | 458 | cpu_dai->playback.active++; |
459 | else | 459 | codec_dai->playback.active++; |
460 | cpu_dai->capture.active = codec_dai->capture.active = 1; | 460 | } else { |
461 | cpu_dai->active = codec_dai->active = 1; | 461 | cpu_dai->capture.active++; |
462 | cpu_dai->runtime = runtime; | 462 | codec_dai->capture.active++; |
463 | } | ||
464 | cpu_dai->active++; | ||
465 | codec_dai->active++; | ||
463 | card->codec->active++; | 466 | card->codec->active++; |
464 | mutex_unlock(&pcm_mutex); | 467 | mutex_unlock(&pcm_mutex); |
465 | return 0; | 468 | return 0; |
@@ -535,15 +538,16 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
535 | 538 | ||
536 | mutex_lock(&pcm_mutex); | 539 | mutex_lock(&pcm_mutex); |
537 | 540 | ||
538 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 541 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
539 | cpu_dai->playback.active = codec_dai->playback.active = 0; | 542 | cpu_dai->playback.active--; |
540 | else | 543 | codec_dai->playback.active--; |
541 | cpu_dai->capture.active = codec_dai->capture.active = 0; | 544 | } else { |
542 | 545 | cpu_dai->capture.active--; | |
543 | if (codec_dai->playback.active == 0 && | 546 | codec_dai->capture.active--; |
544 | codec_dai->capture.active == 0) { | ||
545 | cpu_dai->active = codec_dai->active = 0; | ||
546 | } | 547 | } |
548 | |||
549 | cpu_dai->active--; | ||
550 | codec_dai->active--; | ||
547 | codec->active--; | 551 | codec->active--; |
548 | 552 | ||
549 | /* Muting the DAC suppresses artifacts caused during digital | 553 | /* Muting the DAC suppresses artifacts caused during digital |
@@ -563,7 +567,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
563 | 567 | ||
564 | if (platform->pcm_ops->close) | 568 | if (platform->pcm_ops->close) |
565 | platform->pcm_ops->close(substream); | 569 | platform->pcm_ops->close(substream); |
566 | cpu_dai->runtime = NULL; | ||
567 | 570 | ||
568 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 571 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
569 | /* start delayed pop wq here for playback streams */ | 572 | /* start delayed pop wq here for playback streams */ |
@@ -801,6 +804,41 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
801 | return 0; | 804 | return 0; |
802 | } | 805 | } |
803 | 806 | ||
807 | /* | ||
808 | * soc level wrapper for pointer callback | ||
809 | * If cpu_dai, codec_dai, platform driver has the delay callback, than | ||
810 | * the runtime->delay will be updated accordingly. | ||
811 | */ | ||
812 | static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | ||
813 | { | ||
814 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
815 | struct snd_soc_device *socdev = rtd->socdev; | ||
816 | struct snd_soc_card *card = socdev->card; | ||
817 | struct snd_soc_platform *platform = card->platform; | ||
818 | struct snd_soc_dai_link *machine = rtd->dai; | ||
819 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | ||
820 | struct snd_soc_dai *codec_dai = machine->codec_dai; | ||
821 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
822 | snd_pcm_uframes_t offset = 0; | ||
823 | snd_pcm_sframes_t delay = 0; | ||
824 | |||
825 | if (platform->pcm_ops->pointer) | ||
826 | offset = platform->pcm_ops->pointer(substream); | ||
827 | |||
828 | if (cpu_dai->ops->delay) | ||
829 | delay += cpu_dai->ops->delay(substream, cpu_dai); | ||
830 | |||
831 | if (codec_dai->ops->delay) | ||
832 | delay += codec_dai->ops->delay(substream, codec_dai); | ||
833 | |||
834 | if (platform->delay) | ||
835 | delay += platform->delay(substream, codec_dai); | ||
836 | |||
837 | runtime->delay = delay; | ||
838 | |||
839 | return offset; | ||
840 | } | ||
841 | |||
804 | /* ASoC PCM operations */ | 842 | /* ASoC PCM operations */ |
805 | static struct snd_pcm_ops soc_pcm_ops = { | 843 | static struct snd_pcm_ops soc_pcm_ops = { |
806 | .open = soc_pcm_open, | 844 | .open = soc_pcm_open, |
@@ -809,6 +847,7 @@ static struct snd_pcm_ops soc_pcm_ops = { | |||
809 | .hw_free = soc_pcm_hw_free, | 847 | .hw_free = soc_pcm_hw_free, |
810 | .prepare = soc_pcm_prepare, | 848 | .prepare = soc_pcm_prepare, |
811 | .trigger = soc_pcm_trigger, | 849 | .trigger = soc_pcm_trigger, |
850 | .pointer = soc_pcm_pointer, | ||
812 | }; | 851 | }; |
813 | 852 | ||
814 | #ifdef CONFIG_PM | 853 | #ifdef CONFIG_PM |
@@ -858,7 +897,7 @@ static int soc_suspend(struct device *dev) | |||
858 | if (cpu_dai->suspend && !cpu_dai->ac97_control) | 897 | if (cpu_dai->suspend && !cpu_dai->ac97_control) |
859 | cpu_dai->suspend(cpu_dai); | 898 | cpu_dai->suspend(cpu_dai); |
860 | if (platform->suspend) | 899 | if (platform->suspend) |
861 | platform->suspend(cpu_dai); | 900 | platform->suspend(&card->dai_link[i]); |
862 | } | 901 | } |
863 | 902 | ||
864 | /* close any waiting streams and save state */ | 903 | /* close any waiting streams and save state */ |
@@ -947,7 +986,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
947 | if (cpu_dai->resume && !cpu_dai->ac97_control) | 986 | if (cpu_dai->resume && !cpu_dai->ac97_control) |
948 | cpu_dai->resume(cpu_dai); | 987 | cpu_dai->resume(cpu_dai); |
949 | if (platform->resume) | 988 | if (platform->resume) |
950 | platform->resume(cpu_dai); | 989 | platform->resume(&card->dai_link[i]); |
951 | } | 990 | } |
952 | 991 | ||
953 | if (card->resume_post) | 992 | if (card->resume_post) |
@@ -1335,7 +1374,6 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
1335 | dai_link->pcm = pcm; | 1374 | dai_link->pcm = pcm; |
1336 | pcm->private_data = rtd; | 1375 | pcm->private_data = rtd; |
1337 | soc_pcm_ops.mmap = platform->pcm_ops->mmap; | 1376 | soc_pcm_ops.mmap = platform->pcm_ops->mmap; |
1338 | soc_pcm_ops.pointer = platform->pcm_ops->pointer; | ||
1339 | soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; | 1377 | soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; |
1340 | soc_pcm_ops.copy = platform->pcm_ops->copy; | 1378 | soc_pcm_ops.copy = platform->pcm_ops->copy; |
1341 | soc_pcm_ops.silence = platform->pcm_ops->silence; | 1379 | soc_pcm_ops.silence = platform->pcm_ops->silence; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6c3351095786..86ded22e36af 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -97,7 +97,6 @@ static void pop_dbg(u32 pop_time, const char *fmt, ...) | |||
97 | 97 | ||
98 | if (pop_time) { | 98 | if (pop_time) { |
99 | vprintk(fmt, args); | 99 | vprintk(fmt, args); |
100 | pop_wait(pop_time); | ||
101 | } | 100 | } |
102 | 101 | ||
103 | va_end(args); | 102 | va_end(args); |
@@ -314,8 +313,8 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget) | |||
314 | pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", | 313 | pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", |
315 | widget->name, widget->power ? "on" : "off", | 314 | widget->name, widget->power ? "on" : "off", |
316 | codec->pop_time); | 315 | codec->pop_time); |
317 | snd_soc_write(codec, widget->reg, new); | ||
318 | pop_wait(codec->pop_time); | 316 | pop_wait(codec->pop_time); |
317 | snd_soc_write(codec, widget->reg, new); | ||
319 | } | 318 | } |
320 | pr_debug("reg %x old %x new %x change %d\n", widget->reg, | 319 | pr_debug("reg %x old %x new %x change %d\n", widget->reg, |
321 | old, new, change); | 320 | old, new, change); |
@@ -1075,6 +1074,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
1075 | 1074 | ||
1076 | pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", | 1075 | pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", |
1077 | codec->pop_time); | 1076 | codec->pop_time); |
1077 | pop_wait(codec->pop_time); | ||
1078 | 1078 | ||
1079 | return 0; | 1079 | return 0; |
1080 | } | 1080 | } |