aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Pargmann <mpa@pengutronix.de>2013-07-27 07:31:53 -0400
committerMark Brown <broonie@linaro.org>2013-08-06 12:57:24 -0400
commitde623ece5be03e4447dbe08eaca30c92202a34a2 (patch)
treec9c97c8748bd17eeaeb46d2e710f3181456ef34c
parent8548a464b942a97324d0e3e340ce95356cff32c4 (diff)
ASoC: fsl-ssi: Add support for imx-pcm-fiq
Add support for non-dma pcm for imx platforms with imx-pcm-fiq support. Instead of imx-pcm-audio, in this case imx-pcm-fiq-audio device is added and the SIER flags are set differently. We need imx-pcm-fiq for some boards that use an incompatible codec. imx-pcm-fiq handles those codecs differently and allows to operate with them. DMA is not possible because some data sent by the codecs, e.g. wm9712, is not in the datastream. Also some data is mixed up in the fifos, so that we need to sort them out manually. Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Tested-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,ssi.txt4
-rw-r--r--sound/soc/fsl/fsl_ssi.c79
2 files changed, 71 insertions, 12 deletions
diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
index 5ff76c9c57d2..e45cbce9cbf3 100644
--- a/Documentation/devicetree/bindings/sound/fsl,ssi.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
@@ -47,6 +47,10 @@ Optional properties:
47- codec-handle: Phandle to a 'codec' node that defines an audio 47- codec-handle: Phandle to a 'codec' node that defines an audio
48 codec connected to this SSI. This node is typically 48 codec connected to this SSI. This node is typically
49 a child of an I2C or other control node. 49 a child of an I2C or other control node.
50- fsl,fiq-stream-filter: Bool property. Disabled DMA and use FIQ instead to
51 filter the codec stream. This is necessary for some boards
52 where an incompatible codec is connected to this SSI, e.g.
53 on pca100 and pcm043.
50 54
51Child 'codec' node required properties: 55Child 'codec' node required properties:
52- compatible: Compatible list, contains the name of the codec 56- compatible: Compatible list, contains the name of the codec
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 4d78df7d7f34..8b075ef5c6b9 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -8,6 +8,26 @@
8 * This file is licensed under the terms of the GNU General Public License 8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied. 10 * kind, whether express or implied.
11 *
12 *
13 * Some notes why imx-pcm-fiq is used instead of DMA on some boards:
14 *
15 * The i.MX SSI core has some nasty limitations in AC97 mode. While most
16 * sane processor vendors have a FIFO per AC97 slot, the i.MX has only
17 * one FIFO which combines all valid receive slots. We cannot even select
18 * which slots we want to receive. The WM9712 with which this driver
19 * was developed with always sends GPIO status data in slot 12 which
20 * we receive in our (PCM-) data stream. The only chance we have is to
21 * manually skip this data in the FIQ handler. With sampling rates different
22 * from 48000Hz not every frame has valid receive data, so the ratio
23 * between pcm data and GPIO status data changes. Our FIQ handler is not
24 * able to handle this, hence this driver only works with 48000Hz sampling
25 * rate.
26 * Reading and writing AC97 registers is another challenge. The core
27 * provides us status bits when the read register is updated with *another*
28 * value. When we read the same register two times (and the register still
29 * contains the same value) these status bits are not set. We work
30 * around this by not polling these bits but only wait a fixed delay.
11 */ 31 */
12 32
13#include <linux/init.h> 33#include <linux/init.h>
@@ -121,11 +141,13 @@ struct fsl_ssi_private {
121 141
122 bool new_binding; 142 bool new_binding;
123 bool ssi_on_imx; 143 bool ssi_on_imx;
144 bool use_dma;
124 struct clk *clk; 145 struct clk *clk;
125 struct snd_dmaengine_dai_dma_data dma_params_tx; 146 struct snd_dmaengine_dai_dma_data dma_params_tx;
126 struct snd_dmaengine_dai_dma_data dma_params_rx; 147 struct snd_dmaengine_dai_dma_data dma_params_rx;
127 struct imx_dma_data filter_data_tx; 148 struct imx_dma_data filter_data_tx;
128 struct imx_dma_data filter_data_rx; 149 struct imx_dma_data filter_data_rx;
150 struct imx_pcm_fiq_params fiq_params;
129 151
130 struct { 152 struct {
131 unsigned int rfrc; 153 unsigned int rfrc;
@@ -355,7 +377,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
355 */ 377 */
356 378
357 /* Enable the interrupts and DMA requests */ 379 /* Enable the interrupts and DMA requests */
358 write_ssi(SIER_FLAGS, &ssi->sier); 380 if (ssi_private->use_dma)
381 write_ssi(SIER_FLAGS, &ssi->sier);
382 else
383 write_ssi(CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN |
384 CCSR_SSI_SIER_RIE |
385 CCSR_SSI_SIER_RFF0_EN, &ssi->sier);
359 386
360 /* 387 /*
361 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We 388 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
@@ -543,7 +570,7 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
543{ 570{
544 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); 571 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
545 572
546 if (ssi_private->ssi_on_imx) { 573 if (ssi_private->ssi_on_imx && ssi_private->use_dma) {
547 dai->playback_dma_data = &ssi_private->dma_params_tx; 574 dai->playback_dma_data = &ssi_private->dma_params_tx;
548 dai->capture_dma_data = &ssi_private->dma_params_rx; 575 dai->capture_dma_data = &ssi_private->dma_params_rx;
549 } 576 }
@@ -683,6 +710,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
683 710
684 strcpy(ssi_private->name, p); 711 strcpy(ssi_private->name, p);
685 712
713 ssi_private->use_dma = !of_property_read_bool(np,
714 "fsl,fiq-stream-filter");
715
686 /* Initialize this copy of the CPU DAI driver structure */ 716 /* Initialize this copy of the CPU DAI driver structure */
687 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, 717 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
688 sizeof(fsl_ssi_dai_template)); 718 sizeof(fsl_ssi_dai_template));
@@ -707,12 +737,16 @@ static int fsl_ssi_probe(struct platform_device *pdev)
707 return -ENXIO; 737 return -ENXIO;
708 } 738 }
709 739
710 /* The 'name' should not have any slashes in it. */ 740 if (ssi_private->use_dma) {
711 ret = devm_request_irq(&pdev->dev, ssi_private->irq, fsl_ssi_isr, 0, 741 /* The 'name' should not have any slashes in it. */
712 ssi_private->name, ssi_private); 742 ret = devm_request_irq(&pdev->dev, ssi_private->irq,
713 if (ret < 0) { 743 fsl_ssi_isr, 0, ssi_private->name,
714 dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); 744 ssi_private);
715 goto error_irqmap; 745 if (ret < 0) {
746 dev_err(&pdev->dev, "could not claim irq %u\n",
747 ssi_private->irq);
748 goto error_irqmap;
749 }
716 } 750 }
717 751
718 /* Are the RX and the TX clocks locked? */ 752 /* Are the RX and the TX clocks locked? */
@@ -766,7 +800,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
766 */ 800 */
767 ret = of_property_read_u32_array(pdev->dev.of_node, 801 ret = of_property_read_u32_array(pdev->dev.of_node,
768 "fsl,ssi-dma-events", dma_events, 2); 802 "fsl,ssi-dma-events", dma_events, 2);
769 if (ret) { 803 if (ret && !ssi_private->use_dma) {
770 dev_err(&pdev->dev, "could not get dma events\n"); 804 dev_err(&pdev->dev, "could not get dma events\n");
771 goto error_clk; 805 goto error_clk;
772 } 806 }
@@ -805,9 +839,30 @@ static int fsl_ssi_probe(struct platform_device *pdev)
805 } 839 }
806 840
807 if (ssi_private->ssi_on_imx) { 841 if (ssi_private->ssi_on_imx) {
808 ret = imx_pcm_dma_init(pdev); 842 if (!ssi_private->use_dma) {
809 if (ret) 843
810 goto error_dev; 844 /*
845 * Some boards use an incompatible codec. To get it
846 * working, we are using imx-fiq-pcm-audio, that
847 * can handle those codecs. DMA is not possible in this
848 * situation.
849 */
850
851 ssi_private->fiq_params.irq = ssi_private->irq;
852 ssi_private->fiq_params.base = ssi_private->ssi;
853 ssi_private->fiq_params.dma_params_rx =
854 &ssi_private->dma_params_rx;
855 ssi_private->fiq_params.dma_params_tx =
856 &ssi_private->dma_params_tx;
857
858 ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params);
859 if (ret)
860 goto error_dev;
861 } else {
862 ret = imx_pcm_dma_init(pdev);
863 if (ret)
864 goto error_dev;
865 }
811 } 866 }
812 867
813 /* 868 /*