aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh/fsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh/fsi.c')
-rw-r--r--sound/soc/sh/fsi.c271
1 files changed, 130 insertions, 141 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 44123248b630..9c49c11c43ce 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -17,7 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/clk.h> 20#include <linux/pm_runtime.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <sound/core.h> 22#include <sound/core.h>
23#include <sound/pcm.h> 23#include <sound/pcm.h>
@@ -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;
@@ -108,7 +105,6 @@ struct fsi_priv {
108struct fsi_master { 105struct fsi_master {
109 void __iomem *base; 106 void __iomem *base;
110 int irq; 107 int irq;
111 struct clk *clk;
112 struct fsi_priv fsia; 108 struct fsi_priv fsia;
113 struct fsi_priv fsib; 109 struct fsi_priv fsib;
114 struct sh_fsi_platform_info *info; 110 struct sh_fsi_platform_info *info;
@@ -308,62 +304,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
308 return residue; 304 return residue;
309} 305}
310 306
311static 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
340static 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
356static 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/************************************************************************ 307/************************************************************************
368 308
369 309
@@ -435,44 +375,6 @@ static void fsi_soft_all_reset(void)
435 mdelay(10); 375 mdelay(10);
436} 376}
437 377
438static 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
460static 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 */ 378/* playback interrupt */
477static int fsi_data_push(struct fsi_priv *fsi) 379static int fsi_data_push(struct fsi_priv *fsi)
478{ 380{
@@ -481,6 +383,8 @@ static int fsi_data_push(struct fsi_priv *fsi)
481 int send; 383 int send;
482 int fifo_free; 384 int fifo_free;
483 int width; 385 int width;
386 u8 *start;
387 int i;
484 388
485 if (!fsi || 389 if (!fsi ||
486 !fsi->substream || 390 !fsi->substream ||
@@ -515,12 +419,22 @@ static int fsi_data_push(struct fsi_priv *fsi)
515 if (fifo_free < send) 419 if (fifo_free < send)
516 send = fifo_free; 420 send = fifo_free;
517 421
518 if (2 == width) 422 start = runtime->dma_area;
519 fsi_16data_push(fsi, runtime, send); 423 start += fsi->byte_offset;
520 else if (4 == width) 424
521 fsi_32data_push(fsi, runtime, send); 425 switch (width) {
522 else 426 case 2:
427 for (i = 0; i < send; i++)
428 fsi_reg_write(fsi, DODT,
429 ((u32)*((u16 *)start + i) << 8));
430 break;
431 case 4:
432 for (i = 0; i < send; i++)
433 fsi_reg_write(fsi, DODT, *((u32 *)start + i));
434 break;
435 default:
523 return -EINVAL; 436 return -EINVAL;
437 }
524 438
525 fsi->byte_offset += send * width; 439 fsi->byte_offset += send * width;
526 440
@@ -532,6 +446,75 @@ static int fsi_data_push(struct fsi_priv *fsi)
532 return 0; 446 return 0;
533} 447}
534 448
449static int fsi_data_pop(struct fsi_priv *fsi)
450{
451 struct snd_pcm_runtime *runtime;
452 struct snd_pcm_substream *substream = NULL;
453 int free;
454 int fifo_fill;
455 int width;
456 u8 *start;
457 int i;
458
459 if (!fsi ||
460 !fsi->substream ||
461 !fsi->substream->runtime)
462 return -EINVAL;
463
464 runtime = fsi->substream->runtime;
465
466 /* FSI FIFO has limit.
467 * So, this driver can not send periods data at a time
468 */
469 if (fsi->byte_offset >=
470 fsi->period_len * (fsi->periods + 1)) {
471
472 substream = fsi->substream;
473 fsi->periods = (fsi->periods + 1) % runtime->periods;
474
475 if (0 == fsi->periods)
476 fsi->byte_offset = 0;
477 }
478
479 /* get 1 channel data width */
480 width = frames_to_bytes(runtime, 1) / fsi->chan;
481
482 /* get free space for alsa */
483 free = (fsi->buffer_len - fsi->byte_offset) / width;
484
485 /* get recv size */
486 fifo_fill = fsi_get_fifo_residue(fsi, 0);
487
488 if (free < fifo_fill)
489 fifo_fill = free;
490
491 start = runtime->dma_area;
492 start += fsi->byte_offset;
493
494 switch (width) {
495 case 2:
496 for (i = 0; i < fifo_fill; i++)
497 *((u16 *)start + i) =
498 (u16)(fsi_reg_read(fsi, DIDT) >> 8);
499 break;
500 case 4:
501 for (i = 0; i < fifo_fill; i++)
502 *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
503 break;
504 default:
505 return -EINVAL;
506 }
507
508 fsi->byte_offset += fifo_fill * width;
509
510 fsi_irq_enable(fsi, 0);
511
512 if (substream)
513 snd_pcm_period_elapsed(substream);
514
515 return 0;
516}
517
535static irqreturn_t fsi_interrupt(int irq, void *data) 518static irqreturn_t fsi_interrupt(int irq, void *data)
536{ 519{
537 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; 520 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010;
@@ -545,6 +528,10 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
545 fsi_data_push(&master->fsia); 528 fsi_data_push(&master->fsia);
546 if (int_st & INT_B_OUT) 529 if (int_st & INT_B_OUT)
547 fsi_data_push(&master->fsib); 530 fsi_data_push(&master->fsib);
531 if (int_st & INT_A_IN)
532 fsi_data_pop(&master->fsia);
533 if (int_st & INT_B_IN)
534 fsi_data_pop(&master->fsib);
548 535
549 fsi_master_write(INT_ST, 0x0000000); 536 fsi_master_write(INT_ST, 0x0000000);
550 537
@@ -571,7 +558,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
571 int is_master; 558 int is_master;
572 int ret = 0; 559 int ret = 0;
573 560
574 clk_enable(master->clk); 561 pm_runtime_get_sync(dai->dev);
575 562
576 /* CKG1 */ 563 /* CKG1 */
577 data = is_play ? (1 << 0) : (1 << 4); 564 data = is_play ? (1 << 0) : (1 << 4);
@@ -664,8 +651,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
664 } 651 }
665 652
666 fsi_reg_write(fsi, reg, data); 653 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 654
670 /* 655 /*
671 * clear clk reset if master mode 656 * clear clk reset if master mode
@@ -688,7 +673,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
688 fsi_irq_disable(fsi, is_play); 673 fsi_irq_disable(fsi, is_play);
689 fsi_clk_ctrl(fsi, 0); 674 fsi_clk_ctrl(fsi, 0);
690 675
691 clk_disable(master->clk); 676 pm_runtime_put_sync(dai->dev);
692} 677}
693 678
694static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, 679static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -699,16 +684,12 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
699 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 684 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
700 int ret = 0; 685 int ret = 0;
701 686
702 /* capture not supported */
703 if (!is_play)
704 return -ENODEV;
705
706 switch (cmd) { 687 switch (cmd) {
707 case SNDRV_PCM_TRIGGER_START: 688 case SNDRV_PCM_TRIGGER_START:
708 fsi_stream_push(fsi, substream, 689 fsi_stream_push(fsi, substream,
709 frames_to_bytes(runtime, runtime->buffer_size), 690 frames_to_bytes(runtime, runtime->buffer_size),
710 frames_to_bytes(runtime, runtime->period_size)); 691 frames_to_bytes(runtime, runtime->period_size));
711 ret = fsi_data_push(fsi); 692 ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
712 break; 693 break;
713 case SNDRV_PCM_TRIGGER_STOP: 694 case SNDRV_PCM_TRIGGER_STOP:
714 fsi_irq_disable(fsi, is_play); 695 fsi_irq_disable(fsi, is_play);
@@ -780,10 +761,9 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
780{ 761{
781 struct snd_pcm_runtime *runtime = substream->runtime; 762 struct snd_pcm_runtime *runtime = substream->runtime;
782 struct fsi_priv *fsi = fsi_get(substream); 763 struct fsi_priv *fsi = fsi_get(substream);
783 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
784 long location; 764 long location;
785 765
786 location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play); 766 location = (fsi->byte_offset - 1);
787 if (location < 0) 767 if (location < 0)
788 location = 0; 768 location = 0;
789 769
@@ -845,7 +825,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
845 .channels_min = 1, 825 .channels_min = 1,
846 .channels_max = 8, 826 .channels_max = 8,
847 }, 827 },
848 /* capture not supported */ 828 .capture = {
829 .rates = FSI_RATES,
830 .formats = FSI_FMTS,
831 .channels_min = 1,
832 .channels_max = 8,
833 },
849 .ops = &fsi_dai_ops, 834 .ops = &fsi_dai_ops,
850 }, 835 },
851 { 836 {
@@ -857,7 +842,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
857 .channels_min = 1, 842 .channels_min = 1,
858 .channels_max = 8, 843 .channels_max = 8,
859 }, 844 },
860 /* capture not supported */ 845 .capture = {
846 .rates = FSI_RATES,
847 .formats = FSI_FMTS,
848 .channels_min = 1,
849 .channels_max = 8,
850 },
861 .ops = &fsi_dai_ops, 851 .ops = &fsi_dai_ops,
862 }, 852 },
863}; 853};
@@ -881,7 +871,6 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform);
881static int fsi_probe(struct platform_device *pdev) 871static int fsi_probe(struct platform_device *pdev)
882{ 872{
883 struct resource *res; 873 struct resource *res;
884 char clk_name[8];
885 unsigned int irq; 874 unsigned int irq;
886 int ret; 875 int ret;
887 876
@@ -912,23 +901,8 @@ static int fsi_probe(struct platform_device *pdev)
912 master->fsia.base = master->base; 901 master->fsia.base = master->base;
913 master->fsib.base = master->base + 0x40; 902 master->fsib.base = master->base + 0x40;
914 903
915 master->fsia.dma_chan = -1; 904 pm_runtime_enable(&pdev->dev);
916 master->fsib.dma_chan = -1; 905 pm_runtime_resume(&pdev->dev);
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 */
925 snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
926 master->clk = clk_get(NULL, clk_name);
927 if (IS_ERR(master->clk)) {
928 dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
929 ret = -EIO;
930 goto exit_free_dma;
931 }
932 906
933 fsi_soc_dai[0].dev = &pdev->dev; 907 fsi_soc_dai[0].dev = &pdev->dev;
934 fsi_soc_dai[1].dev = &pdev->dev; 908 fsi_soc_dai[1].dev = &pdev->dev;
@@ -938,7 +912,7 @@ static int fsi_probe(struct platform_device *pdev)
938 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); 912 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
939 if (ret) { 913 if (ret) {
940 dev_err(&pdev->dev, "irq request err\n"); 914 dev_err(&pdev->dev, "irq request err\n");
941 goto exit_free_dma; 915 goto exit_iounmap;
942 } 916 }
943 917
944 ret = snd_soc_register_platform(&fsi_soc_platform); 918 ret = snd_soc_register_platform(&fsi_soc_platform);
@@ -951,10 +925,9 @@ static int fsi_probe(struct platform_device *pdev)
951 925
952exit_free_irq: 926exit_free_irq:
953 free_irq(irq, master); 927 free_irq(irq, master);
954exit_free_dma:
955 fsi_free_dma_chan();
956exit_iounmap: 928exit_iounmap:
957 iounmap(master->base); 929 iounmap(master->base);
930 pm_runtime_disable(&pdev->dev);
958exit_kfree: 931exit_kfree:
959 kfree(master); 932 kfree(master);
960 master = NULL; 933 master = NULL;
@@ -967,9 +940,7 @@ static int fsi_remove(struct platform_device *pdev)
967 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); 940 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
968 snd_soc_unregister_platform(&fsi_soc_platform); 941 snd_soc_unregister_platform(&fsi_soc_platform);
969 942
970 clk_put(master->clk); 943 pm_runtime_disable(&pdev->dev);
971
972 fsi_free_dma_chan();
973 944
974 free_irq(master->irq, master); 945 free_irq(master->irq, master);
975 946
@@ -979,9 +950,27 @@ static int fsi_remove(struct platform_device *pdev)
979 return 0; 950 return 0;
980} 951}
981 952
953static int fsi_runtime_nop(struct device *dev)
954{
955 /* Runtime PM callback shared between ->runtime_suspend()
956 * and ->runtime_resume(). Simply returns success.
957 *
958 * This driver re-initializes all registers after
959 * pm_runtime_get_sync() anyway so there is no need
960 * to save and restore registers here.
961 */
962 return 0;
963}
964
965static struct dev_pm_ops fsi_pm_ops = {
966 .runtime_suspend = fsi_runtime_nop,
967 .runtime_resume = fsi_runtime_nop,
968};
969
982static struct platform_driver fsi_driver = { 970static struct platform_driver fsi_driver = {
983 .driver = { 971 .driver = {
984 .name = "sh_fsi", 972 .name = "sh_fsi",
973 .pm = &fsi_pm_ops,
985 }, 974 },
986 .probe = fsi_probe, 975 .probe = fsi_probe,
987 .remove = fsi_remove, 976 .remove = fsi_remove,