diff options
Diffstat (limited to 'sound/soc/ep93xx/ep93xx-i2s.c')
-rw-r--r-- | sound/soc/ep93xx/ep93xx-i2s.c | 81 |
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, | |||
156 | static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, | 155 | static 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, | |||
165 | static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 163 | static 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; |
286 | out: | 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: | |||
302 | static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, | 299 | static 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 |
314 | static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) | 311 | static 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 | ||
325 | static int ep93xx_i2s_resume(struct snd_soc_dai *dai) | 324 | static 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 | ||
352 | struct snd_soc_dai ep93xx_i2s_dai = { | 351 | static 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 | }; |
372 | EXPORT_SYMBOL_GPL(ep93xx_i2s_dai); | ||
373 | 369 | ||
374 | static int ep93xx_i2s_probe(struct platform_device *pdev) | 370 | static 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 | ||
448 | static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) | 443 | static 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); |