diff options
Diffstat (limited to 'sound/soc/pxa/pxa2xx-i2s.c')
-rw-r--r-- | sound/soc/pxa/pxa2xx-i2s.c | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index c1a5275721e4..3b473b200a8f 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c | |||
@@ -80,6 +80,7 @@ struct pxa_i2s_port { | |||
80 | }; | 80 | }; |
81 | static struct pxa_i2s_port pxa_i2s; | 81 | static struct pxa_i2s_port pxa_i2s; |
82 | static struct clk *clk_i2s; | 82 | static struct clk *clk_i2s; |
83 | static int clk_ena = 0; | ||
83 | 84 | ||
84 | static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { | 85 | static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { |
85 | .name = "I2S PCM Stereo out", | 86 | .name = "I2S PCM Stereo out", |
@@ -101,7 +102,7 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, | |||
101 | struct snd_soc_dai *dai) | 102 | struct snd_soc_dai *dai) |
102 | { | 103 | { |
103 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 104 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
104 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 105 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
105 | 106 | ||
106 | if (IS_ERR(clk_i2s)) | 107 | if (IS_ERR(clk_i2s)) |
107 | return PTR_ERR(clk_i2s); | 108 | return PTR_ERR(clk_i2s); |
@@ -162,13 +163,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
162 | struct snd_pcm_hw_params *params, | 163 | struct snd_pcm_hw_params *params, |
163 | struct snd_soc_dai *dai) | 164 | struct snd_soc_dai *dai) |
164 | { | 165 | { |
165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
166 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
167 | struct pxa2xx_pcm_dma_params *dma_data; | 166 | struct pxa2xx_pcm_dma_params *dma_data; |
168 | 167 | ||
169 | BUG_ON(IS_ERR(clk_i2s)); | 168 | BUG_ON(IS_ERR(clk_i2s)); |
170 | clk_enable(clk_i2s); | 169 | clk_enable(clk_i2s); |
171 | dai->private_data = dai; | 170 | clk_ena = 1; |
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) |
@@ -176,7 +175,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
176 | else | 175 | else |
177 | dma_data = &pxa2xx_i2s_pcm_stereo_in; | 176 | dma_data = &pxa2xx_i2s_pcm_stereo_in; |
178 | 177 | ||
179 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | 178 | snd_soc_dai_set_dma_data(dai, substream, dma_data); |
180 | 179 | ||
181 | /* is port used by another stream */ | 180 | /* is port used by another stream */ |
182 | if (!(SACR0 & SACR0_ENB)) { | 181 | if (!(SACR0 & SACR0_ENB)) { |
@@ -259,9 +258,9 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, | |||
259 | if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { | 258 | if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { |
260 | SACR0 &= ~SACR0_ENB; | 259 | SACR0 &= ~SACR0_ENB; |
261 | pxa_i2s_wait(); | 260 | pxa_i2s_wait(); |
262 | if (dai->private_data != NULL) { | 261 | if (clk_ena) { |
263 | clk_disable(clk_i2s); | 262 | clk_disable(clk_i2s); |
264 | dai->private_data = NULL; | 263 | clk_ena = 0; |
265 | } | 264 | } |
266 | } | 265 | } |
267 | } | 266 | } |
@@ -300,6 +299,35 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) | |||
300 | #define pxa2xx_i2s_resume NULL | 299 | #define pxa2xx_i2s_resume NULL |
301 | #endif | 300 | #endif |
302 | 301 | ||
302 | static int pxa2xx_i2s_probe(struct snd_soc_dai *dai) | ||
303 | { | ||
304 | clk_i2s = clk_get(dai->dev, "I2SCLK"); | ||
305 | if (IS_ERR(clk_i2s)) | ||
306 | return PTR_ERR(clk_i2s); | ||
307 | |||
308 | /* | ||
309 | * PXA Developer's Manual: | ||
310 | * If SACR0[ENB] is toggled in the middle of a normal operation, | ||
311 | * the SACR0[RST] bit must also be set and cleared to reset all | ||
312 | * I2S controller registers. | ||
313 | */ | ||
314 | SACR0 = SACR0_RST; | ||
315 | SACR0 = 0; | ||
316 | /* Make sure RPL and REC are disabled */ | ||
317 | SACR1 = SACR1_DRPL | SACR1_DREC; | ||
318 | /* Along with FIFO servicing */ | ||
319 | SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int pxa2xx_i2s_remove(struct snd_soc_dai *dai) | ||
325 | { | ||
326 | clk_put(clk_i2s); | ||
327 | clk_i2s = ERR_PTR(-ENOENT); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
303 | #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 331 | #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
304 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ | 332 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ |
305 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) | 333 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) |
@@ -313,9 +341,9 @@ static struct snd_soc_dai_ops pxa_i2s_dai_ops = { | |||
313 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, | 341 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, |
314 | }; | 342 | }; |
315 | 343 | ||
316 | struct snd_soc_dai pxa_i2s_dai = { | 344 | static struct snd_soc_dai_driver pxa_i2s_dai = { |
317 | .name = "pxa2xx-i2s", | 345 | .probe = pxa2xx_i2s_probe, |
318 | .id = 0, | 346 | .remove = pxa2xx_i2s_remove, |
319 | .suspend = pxa2xx_i2s_suspend, | 347 | .suspend = pxa2xx_i2s_suspend, |
320 | .resume = pxa2xx_i2s_resume, | 348 | .resume = pxa2xx_i2s_resume, |
321 | .playback = { | 349 | .playback = { |
@@ -332,49 +360,20 @@ struct snd_soc_dai pxa_i2s_dai = { | |||
332 | .symmetric_rates = 1, | 360 | .symmetric_rates = 1, |
333 | }; | 361 | }; |
334 | 362 | ||
335 | EXPORT_SYMBOL_GPL(pxa_i2s_dai); | 363 | static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) |
336 | |||
337 | static int pxa2xx_i2s_probe(struct platform_device *dev) | ||
338 | { | 364 | { |
339 | int ret; | 365 | return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai); |
340 | |||
341 | clk_i2s = clk_get(&dev->dev, "I2SCLK"); | ||
342 | if (IS_ERR(clk_i2s)) | ||
343 | return PTR_ERR(clk_i2s); | ||
344 | |||
345 | pxa_i2s_dai.dev = &dev->dev; | ||
346 | pxa_i2s_dai.private_data = NULL; | ||
347 | ret = snd_soc_register_dai(&pxa_i2s_dai); | ||
348 | if (ret != 0) | ||
349 | clk_put(clk_i2s); | ||
350 | |||
351 | /* | ||
352 | * PXA Developer's Manual: | ||
353 | * If SACR0[ENB] is toggled in the middle of a normal operation, | ||
354 | * the SACR0[RST] bit must also be set and cleared to reset all | ||
355 | * I2S controller registers. | ||
356 | */ | ||
357 | SACR0 = SACR0_RST; | ||
358 | SACR0 = 0; | ||
359 | /* Make sure RPL and REC are disabled */ | ||
360 | SACR1 = SACR1_DRPL | SACR1_DREC; | ||
361 | /* Along with FIFO servicing */ | ||
362 | SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); | ||
363 | |||
364 | return ret; | ||
365 | } | 366 | } |
366 | 367 | ||
367 | static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) | 368 | static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev) |
368 | { | 369 | { |
369 | snd_soc_unregister_dai(&pxa_i2s_dai); | 370 | snd_soc_unregister_dai(&pdev->dev); |
370 | clk_put(clk_i2s); | ||
371 | clk_i2s = ERR_PTR(-ENOENT); | ||
372 | return 0; | 371 | return 0; |
373 | } | 372 | } |
374 | 373 | ||
375 | static struct platform_driver pxa2xx_i2s_driver = { | 374 | static struct platform_driver pxa2xx_i2s_driver = { |
376 | .probe = pxa2xx_i2s_probe, | 375 | .probe = pxa2xx_i2s_drv_probe, |
377 | .remove = __devexit_p(pxa2xx_i2s_remove), | 376 | .remove = __devexit_p(pxa2xx_i2s_drv_remove), |
378 | 377 | ||
379 | .driver = { | 378 | .driver = { |
380 | .name = "pxa2xx-i2s", | 379 | .name = "pxa2xx-i2s", |