diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt index 35c09fe5847a7c51adf48bb726f03d721f3b3b37..0f4e23828190f7bda8d9b829ab7410276b2ead5f 100644 --- a/Documentation/devicetree/bindings/sound/fsl-sai.txt +++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt @@ -10,7 +10,8 @@ Required properties: - compatible: Compatible list, contains "fsl,vf610-sai" or "fsl,imx6sx-sai". - reg: Offset and length of the register set for the device. - clocks: Must contain an entry for each entry in clock-names. -- clock-names : Must include the "sai" entry. +- clock-names : Must include the "bus" for register access and "mclk1" "mclk2" + "mclk3" for bit clock and frame clock providing. - dmas : Generic dma devicetree binding as described in Documentation/devicetree/bindings/dma/dma.txt. - dma-names : Two dmas have to be defined, "tx" and "rx". @@ -30,8 +31,10 @@ sai2: sai@40031000 { reg = <0x40031000 0x1000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai2_1>; - clocks = <&clks VF610_CLK_SAI2>; - clock-names = "sai"; + clocks = <&clks VF610_CLK_PLATFORM_BUS>, + <&clks VF610_CLK_SAI2>, + <&clks 0>, <&clks 0>; + clock-names = "bus", "mclk1", "mclk2", "mclk3"; dma-names = "tx", "rx"; dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>, <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>; diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index dde084273c6422ace0a607b6567f28141a7dbf8d..1c93282fbd2696a9475499ee7e4b0d51ddb0f615 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, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + struct device *dev = &sai->pdev->dev; u32 reg; + int ret; + + ret = clk_prepare_enable(sai->bus_clk); + if (ret) { + dev_err(dev, "failed to enable bus clock: %d\n", ret); + return ret; + } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) reg = FSL_SAI_TCR3; @@ -453,6 +461,8 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream, regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, ~FSL_SAI_CR3_TRCE); + + clk_disable_unprepare(sai->bus_clk); } static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { @@ -585,7 +595,8 @@ static int fsl_sai_probe(struct platform_device *pdev) struct fsl_sai *sai; struct resource *res; void __iomem *base; - int irq, ret; + char tmp[8]; + int irq, ret, i; sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); if (!sai) @@ -608,12 +619,35 @@ static int fsl_sai_probe(struct platform_device *pdev) return PTR_ERR(base); sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, - "sai", base, &fsl_sai_regmap_config); + "bus", base, &fsl_sai_regmap_config); + + /* Compatible with old DTB cases */ + if (IS_ERR(sai->regmap)) + sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, + "sai", base, &fsl_sai_regmap_config); if (IS_ERR(sai->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); return PTR_ERR(sai->regmap); } + /* No error out for old DTB cases but only mark the clock NULL */ + sai->bus_clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(sai->bus_clk)) { + dev_err(&pdev->dev, "failed to get bus clock: %ld\n", + PTR_ERR(sai->bus_clk)); + sai->bus_clk = NULL; + } + + for (i = 0; i < FSL_SAI_MCLK_MAX; i++) { + sprintf(tmp, "mclk%d", i + 1); + sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp); + if (IS_ERR(sai->mclk_clk[i])) { + dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n", + i + 1, PTR_ERR(sai->mclk_clk[i])); + sai->mclk_clk[i] = NULL; + } + } + irq = platform_get_irq(pdev, 0); if (irq < 0) { 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 677670d62fcdac033c0f1dd548b17f15a132b30c..0e6c9f595d7550957eabc534174b7a14b2056422 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -119,6 +119,8 @@ #define FSL_SAI_CLK_MAST2 2 #define FSL_SAI_CLK_MAST3 3 +#define FSL_SAI_MCLK_MAX 3 + /* SAI data transfer numbers per DMA request */ #define FSL_SAI_MAXBURST_TX 6 #define FSL_SAI_MAXBURST_RX 6 @@ -126,6 +128,8 @@ struct fsl_sai { struct platform_device *pdev; struct regmap *regmap; + struct clk *bus_clk; + struct clk *mclk_clk[FSL_SAI_MCLK_MAX]; bool big_endian_regs; bool big_endian_data;