aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorNicolin Chen <Guangyu.Chen@freescale.com>2014-04-10 11:26:15 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:58:17 -0400
commit80f676b476d21c22bda1daf62998e5a837f8e4df (patch)
tree448392361dc9db831ea923836e4454b0907f6639 /sound/soc/fsl
parente3e74c9e6e4f68826d672f18c60066883956e118 (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> (cherry picked from commit 17d1eb6628e70488c44c46003dcfe583696bb7b7)
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_sai.c38
-rw-r--r--sound/soc/fsl/fsl_sai.h4
2 files changed, 40 insertions, 2 deletions
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 71688fa4f400..c7874b357ef2 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;