aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/ep93xx/ep93xx-i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/ep93xx/ep93xx-i2s.c')
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c81
1 files changed, 38 insertions, 43 deletions
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 00b946632184..042f4e93746f 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -31,7 +31,6 @@
31#include <mach/dma.h> 31#include <mach/dma.h>
32 32
33#include "ep93xx-pcm.h" 33#include "ep93xx-pcm.h"
34#include "ep93xx-i2s.h"
35 34
36#define EP93XX_I2S_TXCLKCFG 0x00 35#define EP93XX_I2S_TXCLKCFG 0x00
37#define EP93XX_I2S_RXCLKCFG 0x04 36#define EP93XX_I2S_RXCLKCFG 0x04
@@ -145,8 +144,8 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
145 struct snd_soc_dai *dai) 144 struct snd_soc_dai *dai)
146{ 145{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 146 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 147 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
149 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; 148 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
150 149
151 snd_soc_dai_set_dma_data(cpu_dai, substream, 150 snd_soc_dai_set_dma_data(cpu_dai, substream,
152 &info->dma_params[substream->stream]); 151 &info->dma_params[substream->stream]);
@@ -156,8 +155,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
156static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, 155static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
157 struct snd_soc_dai *dai) 156 struct snd_soc_dai *dai)
158{ 157{
159 struct snd_soc_pcm_runtime *rtd = substream->private_data; 158 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
160 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data;
161 159
162 ep93xx_i2s_disable(info, substream->stream); 160 ep93xx_i2s_disable(info, substream->stream);
163} 161}
@@ -165,7 +163,7 @@ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
165static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 163static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
166 unsigned int fmt) 164 unsigned int fmt)
167{ 165{
168 struct ep93xx_i2s_info *info = cpu_dai->private_data; 166 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
169 unsigned int clk_cfg, lin_ctrl; 167 unsigned int clk_cfg, lin_ctrl;
170 168
171 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); 169 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
@@ -242,11 +240,9 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
242 struct snd_pcm_hw_params *params, 240 struct snd_pcm_hw_params *params,
243 struct snd_soc_dai *dai) 241 struct snd_soc_dai *dai)
244{ 242{
245 struct snd_soc_pcm_runtime *rtd = substream->private_data; 243 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
246 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
247 struct ep93xx_i2s_info *info = cpu_dai->private_data;
248 unsigned word_len, div, sdiv, lrdiv; 244 unsigned word_len, div, sdiv, lrdiv;
249 int found = 0, err; 245 int err;
250 246
251 switch (params_format(params)) { 247 switch (params_format(params)) {
252 case SNDRV_PCM_FORMAT_S16_LE: 248 case SNDRV_PCM_FORMAT_S16_LE:
@@ -271,21 +267,22 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
271 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); 267 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
272 268
273 /* 269 /*
274 * Calculate the sdiv (bit clock) and lrdiv (left/right clock) values. 270 * EP93xx I2S module can be setup so SCLK / LRCLK value can be
275 * If the lrclk is pulse length is larger than the word size, then the 271 * 32, 64, 128. MCLK / SCLK value can be 2 and 4.
276 * bit clock will be gated for the unused bits. 272 * We set LRCLK equal to `rate' and minimum SCLK / LRCLK
273 * value is 64, because our sample size is 32 bit * 2 channels.
274 * I2S standard permits us to transmit more bits than
275 * the codec uses.
277 */ 276 */
278 div = (clk_get_rate(info->mclk) / params_rate(params)) * 277 div = clk_get_rate(info->mclk) / params_rate(params);
279 params_channels(params); 278 sdiv = 4;
280 for (sdiv = 2; sdiv <= 4; sdiv += 2) 279 if (div > (256 + 512) / 2) {
281 for (lrdiv = 32; lrdiv <= 128; lrdiv <<= 1) 280 lrdiv = 128;
282 if (sdiv * lrdiv == div) { 281 } else {
283 found = 1; 282 lrdiv = 64;
284 goto out; 283 if (div < (128 + 256) / 2)
285 } 284 sdiv = 2;
286out: 285 }
287 if (!found)
288 return -EINVAL;
289 286
290 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); 287 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
291 if (err) 288 if (err)
@@ -302,7 +299,7 @@ out:
302static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 299static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
303 unsigned int freq, int dir) 300 unsigned int freq, int dir)
304{ 301{
305 struct ep93xx_i2s_info *info = cpu_dai->private_data; 302 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
306 303
307 if (dir == SND_SOC_CLOCK_IN || clk_id != 0) 304 if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
308 return -EINVAL; 305 return -EINVAL;
@@ -313,24 +310,28 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
313#ifdef CONFIG_PM 310#ifdef CONFIG_PM
314static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) 311static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
315{ 312{
316 struct ep93xx_i2s_info *info = dai->private_data; 313 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
317 314
318 if (!dai->active) 315 if (!dai->active)
319 return; 316 return 0;
320 317
321 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); 318 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
322 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); 319 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
320
321 return 0;
323} 322}
324 323
325static int ep93xx_i2s_resume(struct snd_soc_dai *dai) 324static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
326{ 325{
327 struct ep93xx_i2s_info *info = dai->private_data; 326 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
328 327
329 if (!dai->active) 328 if (!dai->active)
330 return; 329 return 0;
331 330
332 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); 331 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
333 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); 332 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
333
334 return 0;
334} 335}
335#else 336#else
336#define ep93xx_i2s_suspend NULL 337#define ep93xx_i2s_suspend NULL
@@ -345,31 +346,26 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
345 .set_fmt = ep93xx_i2s_set_dai_fmt, 346 .set_fmt = ep93xx_i2s_set_dai_fmt,
346}; 347};
347 348
348#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 349#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
349 SNDRV_PCM_FMTBIT_S24_LE | \
350 SNDRV_PCM_FMTBIT_S32_LE)
351 350
352struct snd_soc_dai ep93xx_i2s_dai = { 351static struct snd_soc_dai_driver ep93xx_i2s_dai = {
353 .name = "ep93xx-i2s",
354 .id = 0,
355 .symmetric_rates= 1, 352 .symmetric_rates= 1,
356 .suspend = ep93xx_i2s_suspend, 353 .suspend = ep93xx_i2s_suspend,
357 .resume = ep93xx_i2s_resume, 354 .resume = ep93xx_i2s_resume,
358 .playback = { 355 .playback = {
359 .channels_min = 2, 356 .channels_min = 2,
360 .channels_max = 2, 357 .channels_max = 2,
361 .rates = SNDRV_PCM_RATE_8000_48000, 358 .rates = SNDRV_PCM_RATE_8000_192000,
362 .formats = EP93XX_I2S_FORMATS, 359 .formats = EP93XX_I2S_FORMATS,
363 }, 360 },
364 .capture = { 361 .capture = {
365 .channels_min = 2, 362 .channels_min = 2,
366 .channels_max = 2, 363 .channels_max = 2,
367 .rates = SNDRV_PCM_RATE_8000_48000, 364 .rates = SNDRV_PCM_RATE_8000_192000,
368 .formats = EP93XX_I2S_FORMATS, 365 .formats = EP93XX_I2S_FORMATS,
369 }, 366 },
370 .ops = &ep93xx_i2s_dai_ops, 367 .ops = &ep93xx_i2s_dai_ops,
371}; 368};
372EXPORT_SYMBOL_GPL(ep93xx_i2s_dai);
373 369
374static int ep93xx_i2s_probe(struct platform_device *pdev) 370static int ep93xx_i2s_probe(struct platform_device *pdev)
375{ 371{
@@ -383,8 +379,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
383 goto fail; 379 goto fail;
384 } 380 }
385 381
386 ep93xx_i2s_dai.dev = &pdev->dev; 382 dev_set_drvdata(&pdev->dev, info);
387 ep93xx_i2s_dai.private_data = info;
388 info->dma_params = ep93xx_i2s_dma_params; 383 info->dma_params = ep93xx_i2s_dma_params;
389 384
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 385 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -424,7 +419,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
424 goto fail_put_sclk; 419 goto fail_put_sclk;
425 } 420 }
426 421
427 err = snd_soc_register_dai(&ep93xx_i2s_dai); 422 err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
428 if (err) 423 if (err)
429 goto fail_put_lrclk; 424 goto fail_put_lrclk;
430 425
@@ -447,9 +442,9 @@ fail:
447 442
448static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) 443static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
449{ 444{
450 struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; 445 struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
451 446
452 snd_soc_unregister_dai(&ep93xx_i2s_dai); 447 snd_soc_unregister_dai(&pdev->dev);
453 clk_put(info->lrclk); 448 clk_put(info->lrclk);
454 clk_put(info->sclk); 449 clk_put(info->sclk);
455 clk_put(info->mclk); 450 clk_put(info->mclk);