aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolin Chen <Guangyu.Chen@freescale.com>2014-04-10 11:26:15 -0400
committerMark Brown <broonie@linaro.org>2014-04-14 12:26:05 -0400
commitca3e35c7a37cb59b12a1839d03c621cf8fa9a3d9 (patch)
treed616ca42084424a545063bd3cd528eb78490563b
parentc754064453e0d48043bd6a111f5c1f8ef1b75f7e (diff)
ASoC: fsl_sai: Add clock controls for SAI
The SAI mainly has the following clocks: bus clock control and configure registers and to generate synchronous interrupts and DMA requests. mclk1, mclk2, mclk3 to generate the bit clock when the receiver or transmitter is configured for an internally generated bit clock. So this patch adds these clocks and their clock controls to the driver. [ To concern the old DTB cases, I've added a bit of extra code to make the driver compatible with them. And by marking clock NULL if failed to get, the clk_prepare() or clk_get_rate() would easily return 0 so no further path should be broken. -- by Nicolin ] Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com> Acked-by: Xiubo Li <Li.Xiubo@freescale.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/sound/fsl-sai.txt9
-rw-r--r--sound/soc/fsl/fsl_sai.c38
-rw-r--r--sound/soc/fsl/fsl_sai.h4
3 files changed, 46 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt
index 35c09fe5847a..0f4e23828190 100644
--- a/Documentation/devicetree/bindings/sound/fsl-sai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt
@@ -10,7 +10,8 @@ Required properties:
10- compatible: Compatible list, contains "fsl,vf610-sai" or "fsl,imx6sx-sai". 10- compatible: Compatible list, contains "fsl,vf610-sai" or "fsl,imx6sx-sai".
11- reg: Offset and length of the register set for the device. 11- reg: Offset and length of the register set for the device.
12- clocks: Must contain an entry for each entry in clock-names. 12- clocks: Must contain an entry for each entry in clock-names.
13- clock-names : Must include the "sai" entry. 13- clock-names : Must include the "bus" for register access and "mclk1" "mclk2"
14 "mclk3" for bit clock and frame clock providing.
14- dmas : Generic dma devicetree binding as described in 15- dmas : Generic dma devicetree binding as described in
15 Documentation/devicetree/bindings/dma/dma.txt. 16 Documentation/devicetree/bindings/dma/dma.txt.
16- dma-names : Two dmas have to be defined, "tx" and "rx". 17- dma-names : Two dmas have to be defined, "tx" and "rx".
@@ -30,8 +31,10 @@ sai2: sai@40031000 {
30 reg = <0x40031000 0x1000>; 31 reg = <0x40031000 0x1000>;
31 pinctrl-names = "default"; 32 pinctrl-names = "default";
32 pinctrl-0 = <&pinctrl_sai2_1>; 33 pinctrl-0 = <&pinctrl_sai2_1>;
33 clocks = <&clks VF610_CLK_SAI2>; 34 clocks = <&clks VF610_CLK_PLATFORM_BUS>,
34 clock-names = "sai"; 35 <&clks VF610_CLK_SAI2>,
36 <&clks 0>, <&clks 0>;
37 clock-names = "bus", "mclk1", "mclk2", "mclk3";
35 dma-names = "tx", "rx"; 38 dma-names = "tx", "rx";
36 dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>, 39 dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
37 <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>; 40 <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index dde084273c64..1c93282fbd26 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -427,7 +427,15 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
427 struct snd_soc_dai *cpu_dai) 427 struct snd_soc_dai *cpu_dai)
428{ 428{
429 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); 429 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
430 struct device *dev = &sai->pdev->dev;
430 u32 reg; 431 u32 reg;
432 int ret;
433
434 ret = clk_prepare_enable(sai->bus_clk);
435 if (ret) {
436 dev_err(dev, "failed to enable bus clock: %d\n", ret);
437 return ret;
438 }
431 439
432 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 440 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
433 reg = FSL_SAI_TCR3; 441 reg = FSL_SAI_TCR3;
@@ -453,6 +461,8 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
453 461
454 regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, 462 regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
455 ~FSL_SAI_CR3_TRCE); 463 ~FSL_SAI_CR3_TRCE);
464
465 clk_disable_unprepare(sai->bus_clk);
456} 466}
457 467
458static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { 468static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
@@ -585,7 +595,8 @@ static int fsl_sai_probe(struct platform_device *pdev)
585 struct fsl_sai *sai; 595 struct fsl_sai *sai;
586 struct resource *res; 596 struct resource *res;
587 void __iomem *base; 597 void __iomem *base;
588 int irq, ret; 598 char tmp[8];
599 int irq, ret, i;
589 600
590 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); 601 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
591 if (!sai) 602 if (!sai)
@@ -608,12 +619,35 @@ static int fsl_sai_probe(struct platform_device *pdev)
608 return PTR_ERR(base); 619 return PTR_ERR(base);
609 620
610 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, 621 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
611 "sai", base, &fsl_sai_regmap_config); 622 "bus", base, &fsl_sai_regmap_config);
623
624 /* Compatible with old DTB cases */
625 if (IS_ERR(sai->regmap))
626 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
627 "sai", base, &fsl_sai_regmap_config);
612 if (IS_ERR(sai->regmap)) { 628 if (IS_ERR(sai->regmap)) {
613 dev_err(&pdev->dev, "regmap init failed\n"); 629 dev_err(&pdev->dev, "regmap init failed\n");
614 return PTR_ERR(sai->regmap); 630 return PTR_ERR(sai->regmap);
615 } 631 }
616 632
633 /* No error out for old DTB cases but only mark the clock NULL */
634 sai->bus_clk = devm_clk_get(&pdev->dev, "bus");
635 if (IS_ERR(sai->bus_clk)) {
636 dev_err(&pdev->dev, "failed to get bus clock: %ld\n",
637 PTR_ERR(sai->bus_clk));
638 sai->bus_clk = NULL;
639 }
640
641 for (i = 0; i < FSL_SAI_MCLK_MAX; i++) {
642 sprintf(tmp, "mclk%d", i + 1);
643 sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp);
644 if (IS_ERR(sai->mclk_clk[i])) {
645 dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n",
646 i + 1, PTR_ERR(sai->mclk_clk[i]));
647 sai->mclk_clk[i] = NULL;
648 }
649 }
650
617 irq = platform_get_irq(pdev, 0); 651 irq = platform_get_irq(pdev, 0);
618 if (irq < 0) { 652 if (irq < 0) {
619 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); 653 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 677670d62fcd..0e6c9f595d75 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -119,6 +119,8 @@
119#define FSL_SAI_CLK_MAST2 2 119#define FSL_SAI_CLK_MAST2 2
120#define FSL_SAI_CLK_MAST3 3 120#define FSL_SAI_CLK_MAST3 3
121 121
122#define FSL_SAI_MCLK_MAX 3
123
122/* SAI data transfer numbers per DMA request */ 124/* SAI data transfer numbers per DMA request */
123#define FSL_SAI_MAXBURST_TX 6 125#define FSL_SAI_MAXBURST_TX 6
124#define FSL_SAI_MAXBURST_RX 6 126#define FSL_SAI_MAXBURST_RX 6
@@ -126,6 +128,8 @@
126struct fsl_sai { 128struct fsl_sai {
127 struct platform_device *pdev; 129 struct platform_device *pdev;
128 struct regmap *regmap; 130 struct regmap *regmap;
131 struct clk *bus_clk;
132 struct clk *mclk_clk[FSL_SAI_MCLK_MAX];
129 133
130 bool big_endian_regs; 134 bool big_endian_regs;
131 bool big_endian_data; 135 bool big_endian_data;