aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/atmel/atmel-pcm.c14
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h28
-rw-r--r--sound/soc/codecs/da7210.c67
-rw-r--r--sound/soc/codecs/ssm2602.c4
-rw-r--r--sound/soc/codecs/wm8960.c209
-rw-r--r--sound/soc/codecs/wm8960.h10
-rw-r--r--sound/soc/davinci/davinci-evm.c16
-rw-r--r--sound/soc/imx/Kconfig8
-rw-r--r--sound/soc/imx/Makefile3
-rw-r--r--sound/soc/imx/wm1133-ev1.c291
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c93
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.h4
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.h4
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c12
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h15
-rw-r--r--sound/soc/soc-cache.c83
-rw-r--r--sound/soc/soc-core.c76
-rw-r--r--sound/soc/soc-dapm.c4
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
418static int atmel_pcm_suspend(struct snd_soc_dai *dai) 418static 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
442static int atmel_pcm_resume(struct snd_soc_dai *dai) 445static 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>
38struct 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),
139SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), 139SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
140 140
141SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), 141SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
142SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0),
142SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), 143SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
143 144
144SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), 145SOC_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 @@
30struct snd_soc_codec_device soc_codec_dev_wm8960; 31struct 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] = {
67struct wm8960_priv { 75struct 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
228SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
229 &wm8960_mono_out[0],
230 ARRAY_SIZE(wm8960_mono_out)),
231
232SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), 239SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),
233SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), 240SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),
234 241
@@ -247,6 +254,17 @@ SND_SOC_DAPM_OUTPUT("SPK_RN"),
247SND_SOC_DAPM_OUTPUT("OUT3"), 254SND_SOC_DAPM_OUTPUT("OUT3"),
248}; 255};
249 256
257static const struct snd_soc_dapm_widget wm8960_dapm_widgets_out3[] = {
258SND_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 */
264static const struct snd_soc_dapm_widget wm8960_dapm_widgets_capless[] = {
265SND_SOC_DAPM_PGA("OUT3 VMID", WM8960_POWER2, 1, 0, NULL, 0),
266};
267
250static const struct snd_soc_dapm_route audio_paths[] = { 268static 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
316static 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
323static 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
303static int wm8960_add_widgets(struct snd_soc_codec *codec) 331static 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
410static int wm8960_set_bias_level(struct snd_soc_codec *codec, 473static 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
534static 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
841static void wm8960_unregister(struct wm8960_priv *wm8960) 990static 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
883static struct i2c_driver wm8960_i2c_driver = { 1032static 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 @@
114extern struct snd_soc_dai wm8960_dai; 114extern struct snd_soc_dai wm8960_dai;
115extern struct snd_soc_codec_device soc_codec_dev_wm8960; 115extern 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
123struct 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
84static 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
84static struct snd_soc_ops evm_ops = { 94static struct snd_soc_ops evm_ops = {
85 .hw_params = evm_hw_params, 95 .hw_params = evm_hw_params,
86}; 96};
87 97
98static 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 */
89static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { 103static 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};
171static struct snd_soc_dai_link da8xx_evm_dai = { 185static 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
11config SND_MXC_SOC_SSI 11config SND_MXC_SOC_SSI
12 tristate 12 tristate
13 13
14config 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
11snd-soc-phycore-ac97-objs := phycore-ac97.o 11snd-soc-phycore-ac97-objs := phycore-ac97.o
12snd-soc-wm1133-ev1-objs := wm1133-ev1.o
13
12obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o 14obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
15obj-$(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
34struct _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) */
45static 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
81static 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
153static struct snd_soc_ops wm1133_ev1_ops = {
154 .hw_params = wm1133_ev1_hw_params,
155};
156
157static 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 */
169static 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
200static struct snd_soc_jack hp_jack;
201
202static struct snd_soc_jack_pin hp_jack_pins[] = {
203 { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE },
204};
205
206static 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
226static 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
236static 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
243static struct snd_soc_device wm1133_ev1_snd_devdata = {
244 .card = &wm1133_ev1,
245 .codec_dev = &soc_codec_dev_wm8350,
246};
247
248static struct platform_device *wm1133_ev1_snd_device;
249
250static 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}
281module_init(wm1133_ev1_audio_init);
282
283static void __exit wm1133_ev1_audio_exit(void)
284{
285 platform_device_unregister(wm1133_ev1_snd_device);
286}
287module_exit(wm1133_ev1_audio_exit);
288
289MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
290MODULE_DESCRIPTION("Audio for WM1133-EV1 on i.MX31ADS");
291MODULE_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
539static 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 */
554static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; 555static 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
27extern struct clk *s3c2412_get_iisclk(void); 27extern 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
142static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { 130static 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
30extern struct snd_soc_dai s3c64xx_i2s_dai[]; 39extern 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))
370static 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 *)&reg;
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
403static 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
419static 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
370static struct { 448static 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 */
812static 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 */
805static struct snd_pcm_ops soc_pcm_ops = { 843static 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}