aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
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
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')
-rw-r--r--sound/soc/fsl/fsl_dma.c67
-rw-r--r--sound/soc/fsl/fsl_ssi.c25
2 files changed, 73 insertions, 19 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");
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7939c337ed9d..d1c855ade8fb 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -93,6 +93,7 @@ struct fsl_ssi_private {
93 unsigned int playback; 93 unsigned int playback;
94 unsigned int capture; 94 unsigned int capture;
95 int asynchronous; 95 int asynchronous;
96 unsigned int fifo_depth;
96 struct snd_soc_dai_driver cpu_dai_drv; 97 struct snd_soc_dai_driver cpu_dai_drv;
97 struct device_attribute dev_attr; 98 struct device_attribute dev_attr;
98 struct platform_device *pdev; 99 struct platform_device *pdev;
@@ -337,11 +338,20 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
337 338
338 /* 339 /*
339 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We 340 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
340 * don't use FIFO 1. Since the SSI only supports stereo, the 341 * don't use FIFO 1. We program the transmit water to signal a
341 * watermark should never be an odd number. 342 * DMA transfer if there are only two (or fewer) elements left
343 * in the FIFO. Two elements equals one frame (left channel,
344 * right channel). This value, however, depends on the depth of
345 * the transmit buffer.
346 *
347 * We program the receive FIFO to notify us if at least two
348 * elements (one frame) have been written to the FIFO. We could
349 * make this value larger (and maybe we should), but this way
350 * data will be written to memory as soon as it's available.
342 */ 351 */
343 out_be32(&ssi->sfcsr, 352 out_be32(&ssi->sfcsr,
344 CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2)); 353 CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
354 CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2));
345 355
346 /* 356 /*
347 * We keep the SSI disabled because if we enable it, then the 357 * We keep the SSI disabled because if we enable it, then the
@@ -622,6 +632,7 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev,
622 struct device_attribute *dev_attr = NULL; 632 struct device_attribute *dev_attr = NULL;
623 struct device_node *np = of_dev->dev.of_node; 633 struct device_node *np = of_dev->dev.of_node;
624 const char *p, *sprop; 634 const char *p, *sprop;
635 const uint32_t *iprop;
625 struct resource res; 636 struct resource res;
626 char name[64]; 637 char name[64];
627 638
@@ -678,6 +689,14 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev,
678 else 689 else
679 ssi_private->cpu_dai_drv.symmetric_rates = 1; 690 ssi_private->cpu_dai_drv.symmetric_rates = 1;
680 691
692 /* Determine the FIFO depth. */
693 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
694 if (iprop)
695 ssi_private->fifo_depth = *iprop;
696 else
697 /* Older 8610 DTs didn't have the fifo-depth property */
698 ssi_private->fifo_depth = 8;
699
681 /* Initialize the the device_attribute structure */ 700 /* Initialize the the device_attribute structure */
682 dev_attr = &ssi_private->dev_attr; 701 dev_attr = &ssi_private->dev_attr;
683 dev_attr->attr.name = "statistics"; 702 dev_attr->attr.name = "statistics";