diff options
Diffstat (limited to 'sound/soc/pxa/pxa2xx-i2s.c')
-rw-r--r-- | sound/soc/pxa/pxa2xx-i2s.c | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 2f4b6e489b78..6b8f655d1ad8 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c | |||
@@ -106,10 +106,8 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, | |||
106 | if (IS_ERR(clk_i2s)) | 106 | if (IS_ERR(clk_i2s)) |
107 | return PTR_ERR(clk_i2s); | 107 | return PTR_ERR(clk_i2s); |
108 | 108 | ||
109 | if (!cpu_dai->active) { | 109 | if (!cpu_dai->active) |
110 | SACR0 |= SACR0_RST; | ||
111 | SACR0 = 0; | 110 | SACR0 = 0; |
112 | } | ||
113 | 111 | ||
114 | return 0; | 112 | return 0; |
115 | } | 113 | } |
@@ -169,6 +167,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
169 | 167 | ||
170 | BUG_ON(IS_ERR(clk_i2s)); | 168 | BUG_ON(IS_ERR(clk_i2s)); |
171 | clk_enable(clk_i2s); | 169 | clk_enable(clk_i2s); |
170 | dai->private_data = dai; | ||
172 | pxa_i2s_wait(); | 171 | pxa_i2s_wait(); |
173 | 172 | ||
174 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 173 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -178,9 +177,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
178 | 177 | ||
179 | /* is port used by another stream */ | 178 | /* is port used by another stream */ |
180 | if (!(SACR0 & SACR0_ENB)) { | 179 | if (!(SACR0 & SACR0_ENB)) { |
181 | |||
182 | SACR0 = 0; | 180 | SACR0 = 0; |
183 | SACR1 = 0; | ||
184 | if (pxa_i2s.master) | 181 | if (pxa_i2s.master) |
185 | SACR0 |= SACR0_BCKD; | 182 | SACR0 |= SACR0_BCKD; |
186 | 183 | ||
@@ -226,6 +223,10 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
226 | 223 | ||
227 | switch (cmd) { | 224 | switch (cmd) { |
228 | case SNDRV_PCM_TRIGGER_START: | 225 | case SNDRV_PCM_TRIGGER_START: |
226 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
227 | SACR1 &= ~SACR1_DRPL; | ||
228 | else | ||
229 | SACR1 &= ~SACR1_DREC; | ||
229 | SACR0 |= SACR0_ENB; | 230 | SACR0 |= SACR0_ENB; |
230 | break; | 231 | break; |
231 | case SNDRV_PCM_TRIGGER_RESUME: | 232 | case SNDRV_PCM_TRIGGER_RESUME: |
@@ -252,21 +253,19 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, | |||
252 | SAIMR &= ~SAIMR_RFS; | 253 | SAIMR &= ~SAIMR_RFS; |
253 | } | 254 | } |
254 | 255 | ||
255 | if (SACR1 & (SACR1_DREC | SACR1_DRPL)) { | 256 | if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { |
256 | SACR0 &= ~SACR0_ENB; | 257 | SACR0 &= ~SACR0_ENB; |
257 | pxa_i2s_wait(); | 258 | pxa_i2s_wait(); |
258 | clk_disable(clk_i2s); | 259 | if (dai->private_data != NULL) { |
260 | clk_disable(clk_i2s); | ||
261 | dai->private_data = NULL; | ||
262 | } | ||
259 | } | 263 | } |
260 | |||
261 | clk_put(clk_i2s); | ||
262 | } | 264 | } |
263 | 265 | ||
264 | #ifdef CONFIG_PM | 266 | #ifdef CONFIG_PM |
265 | static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai) | 267 | static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai) |
266 | { | 268 | { |
267 | if (!dai->active) | ||
268 | return 0; | ||
269 | |||
270 | /* store registers */ | 269 | /* store registers */ |
271 | pxa_i2s.sacr0 = SACR0; | 270 | pxa_i2s.sacr0 = SACR0; |
272 | pxa_i2s.sacr1 = SACR1; | 271 | pxa_i2s.sacr1 = SACR1; |
@@ -281,16 +280,14 @@ static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai) | |||
281 | 280 | ||
282 | static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) | 281 | static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) |
283 | { | 282 | { |
284 | if (!dai->active) | ||
285 | return 0; | ||
286 | |||
287 | pxa_i2s_wait(); | 283 | pxa_i2s_wait(); |
288 | 284 | ||
289 | SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB; | 285 | SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB; |
290 | SACR1 = pxa_i2s.sacr1; | 286 | SACR1 = pxa_i2s.sacr1; |
291 | SAIMR = pxa_i2s.saimr; | 287 | SAIMR = pxa_i2s.saimr; |
292 | SADIV = pxa_i2s.sadiv; | 288 | SADIV = pxa_i2s.sadiv; |
293 | SACR0 |= SACR0_ENB; | 289 | |
290 | SACR0 = pxa_i2s.sacr0; | ||
294 | 291 | ||
295 | return 0; | 292 | return 0; |
296 | } | 293 | } |
@@ -329,6 +326,7 @@ struct snd_soc_dai pxa_i2s_dai = { | |||
329 | .rates = PXA2XX_I2S_RATES, | 326 | .rates = PXA2XX_I2S_RATES, |
330 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 327 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
331 | .ops = &pxa_i2s_dai_ops, | 328 | .ops = &pxa_i2s_dai_ops, |
329 | .symmetric_rates = 1, | ||
332 | }; | 330 | }; |
333 | 331 | ||
334 | EXPORT_SYMBOL_GPL(pxa_i2s_dai); | 332 | EXPORT_SYMBOL_GPL(pxa_i2s_dai); |
@@ -342,10 +340,24 @@ static int pxa2xx_i2s_probe(struct platform_device *dev) | |||
342 | return PTR_ERR(clk_i2s); | 340 | return PTR_ERR(clk_i2s); |
343 | 341 | ||
344 | pxa_i2s_dai.dev = &dev->dev; | 342 | pxa_i2s_dai.dev = &dev->dev; |
343 | pxa_i2s_dai.private_data = NULL; | ||
345 | ret = snd_soc_register_dai(&pxa_i2s_dai); | 344 | ret = snd_soc_register_dai(&pxa_i2s_dai); |
346 | if (ret != 0) | 345 | if (ret != 0) |
347 | clk_put(clk_i2s); | 346 | clk_put(clk_i2s); |
348 | 347 | ||
348 | /* | ||
349 | * PXA Developer's Manual: | ||
350 | * If SACR0[ENB] is toggled in the middle of a normal operation, | ||
351 | * the SACR0[RST] bit must also be set and cleared to reset all | ||
352 | * I2S controller registers. | ||
353 | */ | ||
354 | SACR0 = SACR0_RST; | ||
355 | SACR0 = 0; | ||
356 | /* Make sure RPL and REC are disabled */ | ||
357 | SACR1 = SACR1_DRPL | SACR1_DREC; | ||
358 | /* Along with FIFO servicing */ | ||
359 | SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); | ||
360 | |||
349 | return ret; | 361 | return ret; |
350 | } | 362 | } |
351 | 363 | ||