Message ID | 1397128992-3609-1-git-send-email-Guangyu.Chen@freescale.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
On Thu, Apr 10, 2014 at 07:23:12PM +0800, Nicolin Chen wrote: > 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, > meanwhile, corrects the existing DTS accordingly so those platforms can > benifit from the further feature with different clock sources. > > [ 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 ] In this case, the arch/arm/boot/dts/vf610.dtsi can just go via IMX tree, since nothing should be broken on sound tree even without dts change? Shawn > > Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com> > Acked-by: Xiubo Li <Li.Xiubo@freescale.com> > Acked-by: Shawn Guo <shawn.guo@linaro.org> > --- > > Changelog > v5: > * Dropped mclk preparing and enabling since we are not using them currecntly. > * Made the change compatible to the old DTB. > * Added returned error value print. > v4: > * Merged into single patch. > * Fixed bus clock ID on vf610. > v3: > * Use int type for ret instead of u32. > * Added Acked-by and Tested-by from Xiubo Li. > v2: > * Appended two extra mclks to the driver since SAI actually has three. > * Renamed clock name to 'bus' and 'mclk' according to the reference manual. > > .../devicetree/bindings/sound/fsl-sai.txt | 9 +++-- > arch/arm/boot/dts/vf610.dtsi | 6 ++-- > sound/soc/fsl/fsl_sai.c | 38 ++++++++++++++++++++-- > sound/soc/fsl/fsl_sai.h | 4 +++ > 4 files changed, 50 insertions(+), 7 deletions(-) > > diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt > index 35c09fe..0f4e238 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/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi > index d31ce1b..4c3cd59 100644 > --- a/arch/arm/boot/dts/vf610.dtsi > +++ b/arch/arm/boot/dts/vf610.dtsi > @@ -139,8 +139,10 @@ > compatible = "fsl,vf610-sai"; > reg = <0x40031000 0x1000>; > interrupts = <0 86 0x04>; > - 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"; > status = "disabled"; > }; > > diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c > index db9f75e..5fff2e1 100644 > --- a/sound/soc/fsl/fsl_sai.c > +++ b/sound/soc/fsl/fsl_sai.c > @@ -401,7 +401,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; > @@ -427,6 +435,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 = { > @@ -559,7 +569,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) > @@ -582,12 +593,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 677670d..0e6c9f5 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; > -- > 1.8.4 > >
On Thu, Apr 10, 2014 at 10:07:47PM +0800, Shawn Guo wrote: > On Thu, Apr 10, 2014 at 07:23:12PM +0800, Nicolin Chen wrote: > > 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, > > meanwhile, corrects the existing DTS accordingly so those platforms can > > benifit from the further feature with different clock sources. > > > > [ 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 ] > > In this case, the arch/arm/boot/dts/vf610.dtsi can just go via IMX tree, > since nothing should be broken on sound tree even without dts change? You are right...I'll send the v6. Thank you, Nicolin ---- > > Shawn > > > > > Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com> > > Acked-by: Xiubo Li <Li.Xiubo@freescale.com> > > Acked-by: Shawn Guo <shawn.guo@linaro.org> > > --- > > > > Changelog > > v5: > > * Dropped mclk preparing and enabling since we are not using them currecntly. > > * Made the change compatible to the old DTB. > > * Added returned error value print. > > v4: > > * Merged into single patch. > > * Fixed bus clock ID on vf610. > > v3: > > * Use int type for ret instead of u32. > > * Added Acked-by and Tested-by from Xiubo Li. > > v2: > > * Appended two extra mclks to the driver since SAI actually has three. > > * Renamed clock name to 'bus' and 'mclk' according to the reference manual. > > > > .../devicetree/bindings/sound/fsl-sai.txt | 9 +++-- > > arch/arm/boot/dts/vf610.dtsi | 6 ++-- > > sound/soc/fsl/fsl_sai.c | 38 ++++++++++++++++++++-- > > sound/soc/fsl/fsl_sai.h | 4 +++ > > 4 files changed, 50 insertions(+), 7 deletions(-) > > > > diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt > > index 35c09fe..0f4e238 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/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi > > index d31ce1b..4c3cd59 100644 > > --- a/arch/arm/boot/dts/vf610.dtsi > > +++ b/arch/arm/boot/dts/vf610.dtsi > > @@ -139,8 +139,10 @@ > > compatible = "fsl,vf610-sai"; > > reg = <0x40031000 0x1000>; > > interrupts = <0 86 0x04>; > > - 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"; > > status = "disabled"; > > }; > > > > diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c > > index db9f75e..5fff2e1 100644 > > --- a/sound/soc/fsl/fsl_sai.c > > +++ b/sound/soc/fsl/fsl_sai.c > > @@ -401,7 +401,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; > > @@ -427,6 +435,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 = { > > @@ -559,7 +569,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) > > @@ -582,12 +593,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 677670d..0e6c9f5 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; > > -- > > 1.8.4 > > > > >
diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt index 35c09fe..0f4e238 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/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi index d31ce1b..4c3cd59 100644 --- a/arch/arm/boot/dts/vf610.dtsi +++ b/arch/arm/boot/dts/vf610.dtsi @@ -139,8 +139,10 @@ compatible = "fsl,vf610-sai"; reg = <0x40031000 0x1000>; interrupts = <0 86 0x04>; - 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"; status = "disabled"; }; diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index db9f75e..5fff2e1 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -401,7 +401,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; @@ -427,6 +435,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 = { @@ -559,7 +569,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) @@ -582,12 +593,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 677670d..0e6c9f5 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;