diff options
Diffstat (limited to 'sound/soc/jz4740/jz4740-i2s.c')
-rw-r--r-- | sound/soc/jz4740/jz4740-i2s.c | 135 |
1 files changed, 35 insertions, 100 deletions
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 4c849a49c72a..8f220009e0f6 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -29,9 +29,11 @@ | |||
29 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
30 | #include <sound/soc.h> | 30 | #include <sound/soc.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | #include <sound/dmaengine_pcm.h> | ||
33 | |||
34 | #include <asm/mach-jz4740/dma.h> | ||
32 | 35 | ||
33 | #include "jz4740-i2s.h" | 36 | #include "jz4740-i2s.h" |
34 | #include "jz4740-pcm.h" | ||
35 | 37 | ||
36 | #define JZ_REG_AIC_CONF 0x00 | 38 | #define JZ_REG_AIC_CONF 0x00 |
37 | #define JZ_REG_AIC_CTRL 0x04 | 39 | #define JZ_REG_AIC_CTRL 0x04 |
@@ -89,8 +91,8 @@ struct jz4740_i2s { | |||
89 | struct clk *clk_aic; | 91 | struct clk *clk_aic; |
90 | struct clk *clk_i2s; | 92 | struct clk *clk_i2s; |
91 | 93 | ||
92 | struct jz4740_pcm_config pcm_config_playback; | 94 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
93 | struct jz4740_pcm_config pcm_config_capture; | 95 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
94 | }; | 96 | }; |
95 | 97 | ||
96 | static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, | 98 | static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, |
@@ -233,8 +235,6 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
233 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 235 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
234 | { | 236 | { |
235 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 237 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
236 | enum jz4740_dma_width dma_width; | ||
237 | struct jz4740_pcm_config *pcm_config; | ||
238 | unsigned int sample_size; | 238 | unsigned int sample_size; |
239 | uint32_t ctrl; | 239 | uint32_t ctrl; |
240 | 240 | ||
@@ -243,11 +243,9 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
243 | switch (params_format(params)) { | 243 | switch (params_format(params)) { |
244 | case SNDRV_PCM_FORMAT_S8: | 244 | case SNDRV_PCM_FORMAT_S8: |
245 | sample_size = 0; | 245 | sample_size = 0; |
246 | dma_width = JZ4740_DMA_WIDTH_8BIT; | ||
247 | break; | 246 | break; |
248 | case SNDRV_PCM_FORMAT_S16: | 247 | case SNDRV_PCM_FORMAT_S16: |
249 | sample_size = 1; | 248 | sample_size = 1; |
250 | dma_width = JZ4740_DMA_WIDTH_16BIT; | ||
251 | break; | 249 | break; |
252 | default: | 250 | default: |
253 | return -EINVAL; | 251 | return -EINVAL; |
@@ -260,22 +258,13 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
260 | ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; | 258 | ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; |
261 | else | 259 | else |
262 | ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; | 260 | ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; |
263 | |||
264 | pcm_config = &i2s->pcm_config_playback; | ||
265 | pcm_config->dma_config.dst_width = dma_width; | ||
266 | |||
267 | } else { | 261 | } else { |
268 | ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; | 262 | ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; |
269 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; | 263 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; |
270 | |||
271 | pcm_config = &i2s->pcm_config_capture; | ||
272 | pcm_config->dma_config.src_width = dma_width; | ||
273 | } | 264 | } |
274 | 265 | ||
275 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); | 266 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); |
276 | 267 | ||
277 | snd_soc_dai_set_dma_data(dai, substream, pcm_config); | ||
278 | |||
279 | return 0; | 268 | return 0; |
280 | } | 269 | } |
281 | 270 | ||
@@ -342,25 +331,19 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai) | |||
342 | 331 | ||
343 | static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) | 332 | static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) |
344 | { | 333 | { |
345 | struct jz4740_dma_config *dma_config; | 334 | struct snd_dmaengine_dai_dma_data *dma_data; |
346 | 335 | ||
347 | /* Playback */ | 336 | /* Playback */ |
348 | dma_config = &i2s->pcm_config_playback.dma_config; | 337 | dma_data = &i2s->playback_dma_data; |
349 | dma_config->src_width = JZ4740_DMA_WIDTH_32BIT; | 338 | dma_data->maxburst = 16; |
350 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | 339 | dma_data->slave_id = JZ4740_DMA_TYPE_AIC_TRANSMIT; |
351 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; | 340 | dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO; |
352 | dma_config->flags = JZ4740_DMA_SRC_AUTOINC; | ||
353 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
354 | i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
355 | 341 | ||
356 | /* Capture */ | 342 | /* Capture */ |
357 | dma_config = &i2s->pcm_config_capture.dma_config; | 343 | dma_data = &i2s->capture_dma_data; |
358 | dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT; | 344 | dma_data->maxburst = 16; |
359 | dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; | 345 | dma_data->slave_id = JZ4740_DMA_TYPE_AIC_RECEIVE; |
360 | dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; | 346 | dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO; |
361 | dma_config->flags = JZ4740_DMA_DST_AUTOINC; | ||
362 | dma_config->mode = JZ4740_DMA_MODE_SINGLE; | ||
363 | i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; | ||
364 | } | 347 | } |
365 | 348 | ||
366 | static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) | 349 | static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) |
@@ -371,6 +354,8 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) | |||
371 | clk_prepare_enable(i2s->clk_aic); | 354 | clk_prepare_enable(i2s->clk_aic); |
372 | 355 | ||
373 | jz4740_i2c_init_pcm_config(i2s); | 356 | jz4740_i2c_init_pcm_config(i2s); |
357 | snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, | ||
358 | &i2s->capture_dma_data); | ||
374 | 359 | ||
375 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | | 360 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
376 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | | 361 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
@@ -432,91 +417,41 @@ static const struct snd_soc_component_driver jz4740_i2s_component = { | |||
432 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) | 417 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) |
433 | { | 418 | { |
434 | struct jz4740_i2s *i2s; | 419 | struct jz4740_i2s *i2s; |
420 | struct resource *mem; | ||
435 | int ret; | 421 | int ret; |
436 | 422 | ||
437 | i2s = kzalloc(sizeof(*i2s), GFP_KERNEL); | 423 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); |
438 | |||
439 | if (!i2s) | 424 | if (!i2s) |
440 | return -ENOMEM; | 425 | return -ENOMEM; |
441 | 426 | ||
442 | i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 427 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
443 | if (!i2s->mem) { | 428 | i2s->base = devm_ioremap_resource(&pdev->dev, mem); |
444 | ret = -ENOENT; | 429 | if (IS_ERR(i2s->base)) |
445 | goto err_free; | 430 | return PTR_ERR(i2s->base); |
446 | } | ||
447 | |||
448 | i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem), | ||
449 | pdev->name); | ||
450 | if (!i2s->mem) { | ||
451 | ret = -EBUSY; | ||
452 | goto err_free; | ||
453 | } | ||
454 | 431 | ||
455 | i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem)); | 432 | i2s->phys_base = mem->start; |
456 | if (!i2s->base) { | ||
457 | ret = -EBUSY; | ||
458 | goto err_release_mem_region; | ||
459 | } | ||
460 | 433 | ||
461 | i2s->phys_base = i2s->mem->start; | 434 | i2s->clk_aic = devm_clk_get(&pdev->dev, "aic"); |
435 | if (IS_ERR(i2s->clk_aic)) | ||
436 | return PTR_ERR(i2s->clk_aic); | ||
462 | 437 | ||
463 | i2s->clk_aic = clk_get(&pdev->dev, "aic"); | 438 | i2s->clk_i2s = devm_clk_get(&pdev->dev, "i2s"); |
464 | if (IS_ERR(i2s->clk_aic)) { | 439 | if (IS_ERR(i2s->clk_i2s)) |
465 | ret = PTR_ERR(i2s->clk_aic); | 440 | return PTR_ERR(i2s->clk_i2s); |
466 | goto err_iounmap; | ||
467 | } | ||
468 | |||
469 | i2s->clk_i2s = clk_get(&pdev->dev, "i2s"); | ||
470 | if (IS_ERR(i2s->clk_i2s)) { | ||
471 | ret = PTR_ERR(i2s->clk_i2s); | ||
472 | goto err_clk_put_aic; | ||
473 | } | ||
474 | 441 | ||
475 | platform_set_drvdata(pdev, i2s); | 442 | platform_set_drvdata(pdev, i2s); |
476 | ret = snd_soc_register_component(&pdev->dev, &jz4740_i2s_component, | ||
477 | &jz4740_i2s_dai, 1); | ||
478 | 443 | ||
479 | if (ret) { | 444 | ret = devm_snd_soc_register_component(&pdev->dev, |
480 | dev_err(&pdev->dev, "Failed to register DAI\n"); | 445 | &jz4740_i2s_component, &jz4740_i2s_dai, 1); |
481 | goto err_clk_put_i2s; | 446 | if (ret) |
482 | } | 447 | return ret; |
483 | |||
484 | return 0; | ||
485 | |||
486 | err_clk_put_i2s: | ||
487 | clk_put(i2s->clk_i2s); | ||
488 | err_clk_put_aic: | ||
489 | clk_put(i2s->clk_aic); | ||
490 | err_iounmap: | ||
491 | iounmap(i2s->base); | ||
492 | err_release_mem_region: | ||
493 | release_mem_region(i2s->mem->start, resource_size(i2s->mem)); | ||
494 | err_free: | ||
495 | kfree(i2s); | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | 448 | ||
500 | static int jz4740_i2s_dev_remove(struct platform_device *pdev) | 449 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, |
501 | { | 450 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
502 | struct jz4740_i2s *i2s = platform_get_drvdata(pdev); | ||
503 | |||
504 | snd_soc_unregister_component(&pdev->dev); | ||
505 | |||
506 | clk_put(i2s->clk_i2s); | ||
507 | clk_put(i2s->clk_aic); | ||
508 | |||
509 | iounmap(i2s->base); | ||
510 | release_mem_region(i2s->mem->start, resource_size(i2s->mem)); | ||
511 | |||
512 | kfree(i2s); | ||
513 | |||
514 | return 0; | ||
515 | } | 451 | } |
516 | 452 | ||
517 | static struct platform_driver jz4740_i2s_driver = { | 453 | static struct platform_driver jz4740_i2s_driver = { |
518 | .probe = jz4740_i2s_dev_probe, | 454 | .probe = jz4740_i2s_dev_probe, |
519 | .remove = jz4740_i2s_dev_remove, | ||
520 | .driver = { | 455 | .driver = { |
521 | .name = "jz4740-i2s", | 456 | .name = "jz4740-i2s", |
522 | .owner = THIS_MODULE, | 457 | .owner = THIS_MODULE, |