aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl/fsl_dma.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2010-08-06 13:16:12 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-08-18 15:28:02 -0400
commit8e9d869028f3ce13631af5ef41910ad8d8e6c246 (patch)
tree55644bd6b4afd5563be83c2873724d1ed2b5f77b /sound/soc/fsl/fsl_dma.c
parent2bda3527e4ccb0ddff28f0de11c5cf2484eb99d0 (diff)
asoc/multi-component: fsl: add support for variable SSI FIFO depth
Add code that programs the DMA and SSI controllers differently based on the FIFO depth of the SSI. The SSI devices on the MPC8610 and the P1022 are identical in every way except one: the transmit and receive FIFO depth. On the MPC8610, the depth is eight. On the P1022, it's fifteen. The device tree nodes for the SSI include a "fsl,fifo-depth" property that specifies the FIFO depth. Signed-off-by: Timur Tabi <timur@freescale.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/fsl/fsl_dma.c')
-rw-r--r--sound/soc/fsl/fsl_dma.c67
1 files changed, 51 insertions, 16 deletions
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 57774cb91ae3..dfe1cb94a70f 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -60,6 +60,7 @@ struct dma_object {
60 struct snd_soc_platform_driver dai; 60 struct snd_soc_platform_driver dai;
61 dma_addr_t ssi_stx_phys; 61 dma_addr_t ssi_stx_phys;
62 dma_addr_t ssi_srx_phys; 62 dma_addr_t ssi_srx_phys;
63 unsigned int ssi_fifo_depth;
63 struct ccsr_dma_channel __iomem *channel; 64 struct ccsr_dma_channel __iomem *channel;
64 unsigned int irq; 65 unsigned int irq;
65 bool assigned; 66 bool assigned;
@@ -99,6 +100,7 @@ struct fsl_dma_private {
99 unsigned int irq; 100 unsigned int irq;
100 struct snd_pcm_substream *substream; 101 struct snd_pcm_substream *substream;
101 dma_addr_t ssi_sxx_phys; 102 dma_addr_t ssi_sxx_phys;
103 unsigned int ssi_fifo_depth;
102 dma_addr_t ld_buf_phys; 104 dma_addr_t ld_buf_phys;
103 unsigned int current_link; 105 unsigned int current_link;
104 dma_addr_t dma_buf_phys; 106 dma_addr_t dma_buf_phys;
@@ -431,6 +433,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
431 else 433 else
432 dma_private->ssi_sxx_phys = dma->ssi_srx_phys; 434 dma_private->ssi_sxx_phys = dma->ssi_srx_phys;
433 435
436 dma_private->ssi_fifo_depth = dma->ssi_fifo_depth;
434 dma_private->dma_channel = dma->channel; 437 dma_private->dma_channel = dma->channel;
435 dma_private->irq = dma->irq; 438 dma_private->irq = dma->irq;
436 dma_private->substream = substream; 439 dma_private->substream = substream;
@@ -544,11 +547,11 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
544 struct device *dev = rtd->platform->dev; 547 struct device *dev = rtd->platform->dev;
545 548
546 /* Number of bits per sample */ 549 /* Number of bits per sample */
547 unsigned int sample_size = 550 unsigned int sample_bits =
548 snd_pcm_format_physical_width(params_format(hw_params)); 551 snd_pcm_format_physical_width(params_format(hw_params));
549 552
550 /* Number of bytes per frame */ 553 /* Number of bytes per frame */
551 unsigned int frame_size = 2 * (sample_size / 8); 554 unsigned int sample_bytes = sample_bits / 8;
552 555
553 /* Bus address of SSI STX register */ 556 /* Bus address of SSI STX register */
554 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys; 557 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
@@ -588,7 +591,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
588 * that offset here. While we're at it, also tell the DMA controller 591 * that offset here. While we're at it, also tell the DMA controller
589 * how much data to transfer per sample. 592 * how much data to transfer per sample.
590 */ 593 */
591 switch (sample_size) { 594 switch (sample_bits) {
592 case 8: 595 case 8:
593 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; 596 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
594 ssi_sxx_phys += 3; 597 ssi_sxx_phys += 3;
@@ -602,22 +605,42 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
602 break; 605 break;
603 default: 606 default:
604 /* We should never get here */ 607 /* We should never get here */
605 dev_err(dev, "unsupported sample size %u\n", sample_size); 608 dev_err(dev, "unsupported sample size %u\n", sample_bits);
606 return -EINVAL; 609 return -EINVAL;
607 } 610 }
608 611
609 /* 612 /*
610 * BWC should always be a multiple of the frame size. BWC determines 613 * BWC determines how many bytes are sent/received before the DMA
611 * how many bytes are sent/received before the DMA controller checks the 614 * controller checks the SSI to see if it needs to stop. BWC should
612 * SSI to see if it needs to stop. For playback, the transmit FIFO can 615 * always be a multiple of the frame size, so that we always transmit
613 * hold three frames, so we want to send two frames at a time. For 616 * whole frames. Each frame occupies two slots in the FIFO. The
614 * capture, the receive FIFO is triggered when it contains one frame, so 617 * parameter for CCSR_DMA_MR_BWC() is rounded down the next power of two
615 * we want to receive one frame at a time. 618 * (MR[BWC] can only represent even powers of two).
619 *
620 * To simplify the process, we set BWC to the largest value that is
621 * less than or equal to the FIFO watermark. For playback, this ensures
622 * that we transfer the maximum amount without overrunning the FIFO.
623 * For capture, this ensures that we transfer the maximum amount without
624 * underrunning the FIFO.
625 *
626 * f = SSI FIFO depth
627 * w = SSI watermark value (which equals f - 2)
628 * b = DMA bandwidth count (in bytes)
629 * s = sample size (in bytes, which equals frame_size * 2)
630 *
631 * For playback, we never transmit more than the transmit FIFO
632 * watermark, otherwise we might write more data than the FIFO can hold.
633 * The watermark is equal to the FIFO depth minus two.
634 *
635 * For capture, two equations must hold:
636 * w > f - (b / s)
637 * w >= b / s
638 *
639 * So, b > 2 * s, but b must also be <= s * w. To simplify, we set
640 * b = s * w, which is equal to
641 * (dma_private->ssi_fifo_depth - 2) * sample_bytes.
616 */ 642 */
617 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 643 mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes);
618 mr |= CCSR_DMA_MR_BWC(2 * frame_size);
619 else
620 mr |= CCSR_DMA_MR_BWC(frame_size);
621 644
622 out_be32(&dma_channel->mr, mr); 645 out_be32(&dma_channel->mr, mr);
623 646
@@ -871,6 +894,7 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev,
871 struct device_node *np = of_dev->dev.of_node; 894 struct device_node *np = of_dev->dev.of_node;
872 struct device_node *ssi_np; 895 struct device_node *ssi_np;
873 struct resource res; 896 struct resource res;
897 const uint32_t *iprop;
874 int ret; 898 int ret;
875 899
876 /* Find the SSI node that points to us. */ 900 /* Find the SSI node that points to us. */
@@ -881,15 +905,17 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev,
881 } 905 }
882 906
883 ret = of_address_to_resource(ssi_np, 0, &res); 907 ret = of_address_to_resource(ssi_np, 0, &res);
884 of_node_put(ssi_np);
885 if (ret) { 908 if (ret) {
886 dev_err(&of_dev->dev, "could not determine device resources\n"); 909 dev_err(&of_dev->dev, "could not determine resources for %s\n",
910 ssi_np->full_name);
911 of_node_put(ssi_np);
887 return ret; 912 return ret;
888 } 913 }
889 914
890 dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL); 915 dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL);
891 if (!dma) { 916 if (!dma) {
892 dev_err(&of_dev->dev, "could not allocate dma object\n"); 917 dev_err(&of_dev->dev, "could not allocate dma object\n");
918 of_node_put(ssi_np);
893 return -ENOMEM; 919 return -ENOMEM;
894 } 920 }
895 921
@@ -902,6 +928,15 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev,
902 dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0); 928 dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0);
903 dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0); 929 dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0);
904 930
931 iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
932 if (iprop)
933 dma->ssi_fifo_depth = *iprop;
934 else
935 /* Older 8610 DTs didn't have the fifo-depth property */
936 dma->ssi_fifo_depth = 8;
937
938 of_node_put(ssi_np);
939
905 ret = snd_soc_register_platform(&of_dev->dev, &dma->dai); 940 ret = snd_soc_register_platform(&of_dev->dev, &dma->dai);
906 if (ret) { 941 if (ret) {
907 dev_err(&of_dev->dev, "could not register platform\n"); 942 dev_err(&of_dev->dev, "could not register platform\n");