diff options
| author | Kuninori Morimoto <morimoto.kuninori@renesas.com> | 2009-10-29 23:02:39 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-10-30 06:35:30 -0400 |
| commit | 9ddc9aa910687a8787dbbdc53dcd48e738b197d9 (patch) | |
| tree | 4573c0394bc9d4c568d0bd5c40e2736cf86816a9 | |
| parent | 67e646cd7b51e1d5847fb506d4419d436ea25fda (diff) | |
ASoC: sh: FSI: Remove DMA support
SuperH FSI device have the hardware limitation to use DMA.
If DMA is used, LCD output will be broken.
Maybe there are some solution. But I don't know how to do it now.
This patch remove DMA support and use soft transfer.
Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
| -rw-r--r-- | sound/soc/sh/Kconfig | 1 | ||||
| -rw-r--r-- | sound/soc/sh/fsi.c | 141 |
2 files changed, 20 insertions, 122 deletions
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 9154b4363db3..9e6976586554 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
| @@ -23,7 +23,6 @@ config SND_SOC_SH4_SSI | |||
| 23 | config SND_SOC_SH4_FSI | 23 | config SND_SOC_SH4_FSI |
| 24 | tristate "SH4 FSI support" | 24 | tristate "SH4 FSI support" |
| 25 | depends on CPU_SUBTYPE_SH7724 | 25 | depends on CPU_SUBTYPE_SH7724 |
| 26 | select SH_DMA | ||
| 27 | help | 26 | help |
| 28 | This option enables FSI sound support | 27 | This option enables FSI sound support |
| 29 | 28 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 44123248b630..9742a280ba15 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
| @@ -26,8 +26,6 @@ | |||
| 26 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
| 27 | #include <sound/sh_fsi.h> | 27 | #include <sound/sh_fsi.h> |
| 28 | #include <asm/atomic.h> | 28 | #include <asm/atomic.h> |
| 29 | #include <asm/dma.h> | ||
| 30 | #include <asm/dma-sh.h> | ||
| 31 | 29 | ||
| 32 | #define DO_FMT 0x0000 | 30 | #define DO_FMT 0x0000 |
| 33 | #define DOFF_CTL 0x0004 | 31 | #define DOFF_CTL 0x0004 |
| @@ -97,7 +95,6 @@ struct fsi_priv { | |||
| 97 | 95 | ||
| 98 | int fifo_max; | 96 | int fifo_max; |
| 99 | int chan; | 97 | int chan; |
| 100 | int dma_chan; | ||
| 101 | 98 | ||
| 102 | int byte_offset; | 99 | int byte_offset; |
| 103 | int period_len; | 100 | int period_len; |
| @@ -308,62 +305,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) | |||
| 308 | return residue; | 305 | return residue; |
| 309 | } | 306 | } |
| 310 | 307 | ||
| 311 | static int fsi_get_residue(struct fsi_priv *fsi, int is_play) | ||
| 312 | { | ||
| 313 | int residue; | ||
| 314 | int width; | ||
| 315 | struct snd_pcm_runtime *runtime; | ||
| 316 | |||
| 317 | runtime = fsi->substream->runtime; | ||
| 318 | |||
| 319 | /* get 1 channel data width */ | ||
| 320 | width = frames_to_bytes(runtime, 1) / fsi->chan; | ||
| 321 | |||
| 322 | if (2 == width) | ||
| 323 | residue = fsi_get_fifo_residue(fsi, is_play); | ||
| 324 | else | ||
| 325 | residue = get_dma_residue(fsi->dma_chan); | ||
| 326 | |||
| 327 | return residue; | ||
| 328 | } | ||
| 329 | |||
| 330 | /************************************************************************ | ||
| 331 | |||
| 332 | |||
| 333 | basic dma function | ||
| 334 | |||
| 335 | |||
| 336 | ************************************************************************/ | ||
| 337 | #define PORTA_DMA 0 | ||
| 338 | #define PORTB_DMA 1 | ||
| 339 | |||
| 340 | static int fsi_get_dma_chan(void) | ||
| 341 | { | ||
| 342 | if (0 != request_dma(PORTA_DMA, "fsia")) | ||
| 343 | return -EIO; | ||
| 344 | |||
| 345 | if (0 != request_dma(PORTB_DMA, "fsib")) { | ||
| 346 | free_dma(PORTA_DMA); | ||
| 347 | return -EIO; | ||
| 348 | } | ||
| 349 | |||
| 350 | master->fsia.dma_chan = PORTA_DMA; | ||
| 351 | master->fsib.dma_chan = PORTB_DMA; | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | static void fsi_free_dma_chan(void) | ||
| 357 | { | ||
| 358 | dma_wait_for_completion(PORTA_DMA); | ||
| 359 | dma_wait_for_completion(PORTB_DMA); | ||
| 360 | free_dma(PORTA_DMA); | ||
| 361 | free_dma(PORTB_DMA); | ||
| 362 | |||
| 363 | master->fsia.dma_chan = -1; | ||
| 364 | master->fsib.dma_chan = -1; | ||
| 365 | } | ||
| 366 | |||
| 367 | /************************************************************************ | 308 | /************************************************************************ |
| 368 | 309 | ||
| 369 | 310 | ||
| @@ -435,44 +376,6 @@ static void fsi_soft_all_reset(void) | |||
| 435 | mdelay(10); | 376 | mdelay(10); |
| 436 | } | 377 | } |
| 437 | 378 | ||
| 438 | static void fsi_16data_push(struct fsi_priv *fsi, | ||
| 439 | struct snd_pcm_runtime *runtime, | ||
| 440 | int send) | ||
| 441 | { | ||
| 442 | u16 *dma_start; | ||
| 443 | u32 snd; | ||
| 444 | int i; | ||
| 445 | |||
| 446 | /* get dma start position for FSI */ | ||
| 447 | dma_start = (u16 *)runtime->dma_area; | ||
| 448 | dma_start += fsi->byte_offset / 2; | ||
| 449 | |||
| 450 | /* | ||
| 451 | * soft dma | ||
| 452 | * FSI can not use DMA when 16bpp | ||
| 453 | */ | ||
| 454 | for (i = 0; i < send; i++) { | ||
| 455 | snd = (u32)dma_start[i]; | ||
| 456 | fsi_reg_write(fsi, DODT, snd << 8); | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | static void fsi_32data_push(struct fsi_priv *fsi, | ||
| 461 | struct snd_pcm_runtime *runtime, | ||
| 462 | int send) | ||
| 463 | { | ||
| 464 | u32 *dma_start; | ||
| 465 | |||
| 466 | /* get dma start position for FSI */ | ||
| 467 | dma_start = (u32 *)runtime->dma_area; | ||
| 468 | dma_start += fsi->byte_offset / 4; | ||
| 469 | |||
| 470 | dma_wait_for_completion(fsi->dma_chan); | ||
| 471 | dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR)); | ||
| 472 | dma_write(fsi->dma_chan, (u32)dma_start, | ||
| 473 | (u32)(fsi->base + DODT), send * 4); | ||
| 474 | } | ||
| 475 | |||
| 476 | /* playback interrupt */ | 379 | /* playback interrupt */ |
| 477 | static int fsi_data_push(struct fsi_priv *fsi) | 380 | static int fsi_data_push(struct fsi_priv *fsi) |
| 478 | { | 381 | { |
| @@ -481,6 +384,8 @@ static int fsi_data_push(struct fsi_priv *fsi) | |||
| 481 | int send; | 384 | int send; |
| 482 | int fifo_free; | 385 | int fifo_free; |
| 483 | int width; | 386 | int width; |
| 387 | u8 *start; | ||
| 388 | int i; | ||
| 484 | 389 | ||
| 485 | if (!fsi || | 390 | if (!fsi || |
| 486 | !fsi->substream || | 391 | !fsi->substream || |
| @@ -515,12 +420,22 @@ static int fsi_data_push(struct fsi_priv *fsi) | |||
| 515 | if (fifo_free < send) | 420 | if (fifo_free < send) |
| 516 | send = fifo_free; | 421 | send = fifo_free; |
| 517 | 422 | ||
| 518 | if (2 == width) | 423 | start = runtime->dma_area; |
| 519 | fsi_16data_push(fsi, runtime, send); | 424 | start += fsi->byte_offset; |
| 520 | else if (4 == width) | 425 | |
| 521 | fsi_32data_push(fsi, runtime, send); | 426 | switch (width) { |
| 522 | else | 427 | case 2: |
| 428 | for (i = 0; i < send; i++) | ||
| 429 | fsi_reg_write(fsi, DODT, | ||
| 430 | ((u32)*((u16 *)start + i) << 8)); | ||
| 431 | break; | ||
| 432 | case 4: | ||
| 433 | for (i = 0; i < send; i++) | ||
| 434 | fsi_reg_write(fsi, DODT, *((u32 *)start + i)); | ||
| 435 | break; | ||
| 436 | default: | ||
| 523 | return -EINVAL; | 437 | return -EINVAL; |
| 438 | } | ||
| 524 | 439 | ||
| 525 | fsi->byte_offset += send * width; | 440 | fsi->byte_offset += send * width; |
| 526 | 441 | ||
| @@ -664,8 +579,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
| 664 | } | 579 | } |
| 665 | 580 | ||
| 666 | fsi_reg_write(fsi, reg, data); | 581 | fsi_reg_write(fsi, reg, data); |
| 667 | dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n", | ||
| 668 | msg, fsi->chan, fsi->dma_chan); | ||
| 669 | 582 | ||
| 670 | /* | 583 | /* |
| 671 | * clear clk reset if master mode | 584 | * clear clk reset if master mode |
| @@ -780,10 +693,9 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) | |||
| 780 | { | 693 | { |
| 781 | struct snd_pcm_runtime *runtime = substream->runtime; | 694 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 782 | struct fsi_priv *fsi = fsi_get(substream); | 695 | struct fsi_priv *fsi = fsi_get(substream); |
| 783 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
| 784 | long location; | 696 | long location; |
| 785 | 697 | ||
| 786 | location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play); | 698 | location = (fsi->byte_offset - 1); |
| 787 | if (location < 0) | 699 | if (location < 0) |
| 788 | location = 0; | 700 | location = 0; |
| 789 | 701 | ||
| @@ -912,22 +824,13 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 912 | master->fsia.base = master->base; | 824 | master->fsia.base = master->base; |
| 913 | master->fsib.base = master->base + 0x40; | 825 | master->fsib.base = master->base + 0x40; |
| 914 | 826 | ||
| 915 | master->fsia.dma_chan = -1; | ||
| 916 | master->fsib.dma_chan = -1; | ||
| 917 | |||
| 918 | ret = fsi_get_dma_chan(); | ||
| 919 | if (ret < 0) { | ||
| 920 | dev_err(&pdev->dev, "cannot get dma api\n"); | ||
| 921 | goto exit_iounmap; | ||
| 922 | } | ||
| 923 | |||
| 924 | /* FSI is based on SPU mstp */ | 827 | /* FSI is based on SPU mstp */ |
| 925 | snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id); | 828 | snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id); |
| 926 | master->clk = clk_get(NULL, clk_name); | 829 | master->clk = clk_get(NULL, clk_name); |
| 927 | if (IS_ERR(master->clk)) { | 830 | if (IS_ERR(master->clk)) { |
| 928 | dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name); | 831 | dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name); |
| 929 | ret = -EIO; | 832 | ret = -EIO; |
| 930 | goto exit_free_dma; | 833 | goto exit_iounmap; |
| 931 | } | 834 | } |
| 932 | 835 | ||
| 933 | fsi_soc_dai[0].dev = &pdev->dev; | 836 | fsi_soc_dai[0].dev = &pdev->dev; |
| @@ -938,7 +841,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 938 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); | 841 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); |
| 939 | if (ret) { | 842 | if (ret) { |
| 940 | dev_err(&pdev->dev, "irq request err\n"); | 843 | dev_err(&pdev->dev, "irq request err\n"); |
| 941 | goto exit_free_dma; | 844 | goto exit_iounmap; |
| 942 | } | 845 | } |
| 943 | 846 | ||
| 944 | ret = snd_soc_register_platform(&fsi_soc_platform); | 847 | ret = snd_soc_register_platform(&fsi_soc_platform); |
| @@ -951,8 +854,6 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 951 | 854 | ||
| 952 | exit_free_irq: | 855 | exit_free_irq: |
| 953 | free_irq(irq, master); | 856 | free_irq(irq, master); |
| 954 | exit_free_dma: | ||
| 955 | fsi_free_dma_chan(); | ||
| 956 | exit_iounmap: | 857 | exit_iounmap: |
| 957 | iounmap(master->base); | 858 | iounmap(master->base); |
| 958 | exit_kfree: | 859 | exit_kfree: |
| @@ -969,8 +870,6 @@ static int fsi_remove(struct platform_device *pdev) | |||
| 969 | 870 | ||
| 970 | clk_put(master->clk); | 871 | clk_put(master->clk); |
| 971 | 872 | ||
| 972 | fsi_free_dma_chan(); | ||
| 973 | |||
| 974 | free_irq(master->irq, master); | 873 | free_irq(master->irq, master); |
| 975 | 874 | ||
| 976 | iounmap(master->base); | 875 | iounmap(master->base); |
