aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/pxa2xx-i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/pxa/pxa2xx-i2s.c')
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c89
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};
81static struct pxa_i2s_port pxa_i2s; 81static struct pxa_i2s_port pxa_i2s;
82static struct clk *clk_i2s; 82static struct clk *clk_i2s;
83static int clk_ena = 0;
83 84
84static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { 85static 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
302static 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
324static 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
316struct snd_soc_dai pxa_i2s_dai = { 344static 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
335EXPORT_SYMBOL_GPL(pxa_i2s_dai); 363static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
336
337static 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
367static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) 368static 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
375static struct platform_driver pxa2xx_i2s_driver = { 374static 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",