ASoC: sun4i-i2s: Add quirks for newer SoCs
Subsystems (4)
PATCH 1/1 ASoC: sun4i-i2s: Add quirks for newer SoCs
From: Marcus Cooper <[email protected]>
Newer SoCs have additional functionality so a quirks structure has been added to handle them. So far we've seen the use of a reset controller, a different address for the TXFIFO and varying register changes.
This patch prepares the driver for these changes and adds the reset specifier.
--- .../devicetree/bindings/sound/sun4i-i2s.txt | 2 + sound/soc/sunxi/sun4i-i2s.c | 47 ++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-)
Documentation/devicetree/bindings/sound/sun4i-i2s.txt +2 -0
@@ -18,6 +18,8 @@ Required properties: - "apb" : clock for the I2S bus interface - "mod" : module clock for the I2S controller - #sound-dai-cells : Must be equal to 0 +- resets: reset specifier for the ahb reset (A31 and newer only) + Example:
sound/soc/sunxi/sun4i-i2s.c +43 -4
112 lines not on this page · raw message
Signature · 1 line
2.11.0
Hi,
Quoted 54 lines · On Tue, Dec 20, 2016 at 03:55:24PM +0100…
From: Marcus Cooper <[email protected]>
Newer SoCs have additional functionality so a quirks structure has been added to handle them. So far we've seen the use of a reset controller, a different address for the TXFIFO and varying register changes.
This patch prepares the driver for these changes and adds the reset specifier.
Signed-off-by Marcus Cooper <[email protected]>--- .../devicetree/bindings/sound/sun4i-i2s.txt | 2 + sound/soc/sunxi/sun4i-i2s.c | 47 ++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-)Documentation/devicetree/bindings/sound/sun4i-i2s.txt +2
-0@@ -18,6 +18,8 @@ Required properties: - "apb" : clock for the I2S bus interface - "mod" : module clock for the I2S controller - #sound-dai-cells : Must be equal to 0 +- resets: reset specifier for the ahb reset (A31 and newer only) + Example:sound/soc/sunxi/sun4i-i2s.c +3
-0@@ -14,9 +14,11 @@#include <linux/clk.h> #include <linux/dmaengine.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <sound/dmaengine_pcm.h> #include <sound/pcm_params.h> @@ -92,6 +94,7 @@ struct sun4i_i2s {struct clk *bus_clk;struct clk *mod_clk;struct regmap *regmap; +struct reset_control *rst;unsigned int mclk_freq;
sound/soc/sunxi/sun4i-i2s.c struct sun4i_i2s_clk_div { · line 116
Quoted 10 lines
sound/soc/sunxi/sun4i-i2s.c +7
-0@@ -104,6 +107,13 @@ struct sun4i_i2s_clk_div {u8 val; }; +struct sun4i_i2s_quirks { +unsigned int reg_dac_txdata;/* TX FIFO offset for DMA config */ +bool has_reset; +const struct regmap_config *sun4i_i2s_regmap; +const struct snd_soc_dai_ops *ops; +}; +
This is quite hard to review without actual example of what you'll put in there.
Quoted 36 lines
sound/soc/sunxi/sun4i-i2s.c +8
-2static const struct sun4i_i2s_clk_div sun4i_i2s_bclk_div[] = { { .div =2 , .val =0 }, { .div =4 , .val =1 },@@ -541,7 +551,6 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = &sun4i_i2s_dai_ops, .symmetric_rates = 1, };@@ -655,6 +664,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev) {struct sun4i_i2s *i2s;struct resource *res; +const struct sun4i_i2s_quirks *quirks;void __iomem *regs;int irq, ret;@@ -680,8 +690,14 @@ static int sun4i_i2s_probe(struct platform_device *pdev)return PTR_ERR (i2s->bus_clk); } + quirks =of_device_get_match_data (&pdev->dev); +if (quirks ==NULL ) { +dev_err (&pdev->dev,"Failed to determine the quirks to use\n" ); +return -ENODEV ; + } + i2s->regmap =devm_regmap_init_mmio (&pdev->dev, regs, - &sun4i_i2s_regmap_config); + quirks->sun4i_i2s_regmap);if (IS_ERR (i2s->regmap)) {dev_err (&pdev->dev,"Regmap initialisation failed\n" );return PTR_ERR (i2s->regmap);
sound/soc/sunxi/sun4i-i2s.c static int sun4i_i2s_probe(struct platform_device *pdev) · line 711
Quoted 4 lines
sound/soc/sunxi/sun4i-i2s.c +1
-0@@ -692,13 +708,25 @@ static int sun4i_i2s_probe(struct platform_device *pdev)dev_err (&pdev->dev,"Can't get our mod clock\n" );return PTR_ERR (i2s->mod_clk); } +
Spurious change?
Quoted 9 lines
sound/soc/sunxi/sun4i-i2s.c +2
-1- i2s->playback_dma_data.addr = res->start +SUN4I_I2S_FIFO_TX_REG ; + i2s->playback_dma_data.addr = res->start + quirks->reg_dac_txdata; i2s->playback_dma_data.maxburst =4 ; i2s->capture_dma_data.addr = res->start +SUN4I_I2S_FIFO_RX_REG ; i2s->capture_dma_data.maxburst =4 ; +if (quirks->has_reset) {
sound/soc/sunxi/sun4i-i2s.c static int sun4i_i2s_probe(struct platform_device *pdev) · line 729
Quoted 10 lines
sound/soc/sunxi/sun4i-i2s.c +10
-0+ i2s->rst =devm_reset_control_get_optional (&pdev->dev,NULL ); +if (IS_ERR (i2s->rst) &&PTR_ERR (i2s->rst) == -EPROBE_DEFER ) { + ret = -EPROBE_DEFER ; +dev_err (&pdev->dev,"Failed to get reset: %d\n" , ret); + goto err_pm_disable; + } +if (!IS_ERR (i2s->rst)) +reset_control_deassert (i2s->rst); + } +
That reset line is not optional. The <A31 SoCs don't need it, and you cover that case already, but it is definitely mandatory for the A31.
Thanks,
Maxime
Signature · 3 lines
Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
Quoted 60 lines · Maxime Ripard
Hi,
Quoted 57 lines · On Tue, Dec 20, 2016 at 03:55:24PM +0100…
From: Marcus Cooper <[email protected]>
Newer SoCs have additional functionality so a quirks structure has been added to handle them. So far we've seen the use of a reset controller, a different address for the TXFIFO and varying register changes.
This patch prepares the driver for these changes and adds the reset specifier.
Signed-off-by Marcus Cooper <[email protected]>--- .../devicetree/bindings/sound/sun4i-i2s.txt | 2 + sound/soc/sunxi/sun4i-i2s.c | 47 ++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-)Documentation/devicetree/bindings/sound/sun4i-i2s.txt +2
-0@@ -18,6 +18,8 @@ Required properties: - "apb" : clock for the I2S bus interface - "mod" : module clock for the I2S controller - #sound-dai-cells : Must be equal to 0 +- resets: reset specifier for the ahb reset (A31 and newer only) + Example:sound/soc/sunxi/sun4i-i2s.c +3
-0@@ -14,9 +14,11 @@#include <linux/clk.h> #include <linux/dmaengine.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <sound/dmaengine_pcm.h> #include <sound/pcm_params.h> @@ -92,6 +94,7 @@ struct sun4i_i2s {struct clk *bus_clk;struct clk *mod_clk;struct regmap *regmap; +struct reset_control *rst;unsigned int mclk_freq;@@ -104,6 +107,13 @@ struct sun4i_i2s_clk_div {u8 val; };
Quoted 10 lines
sound/soc/sunxi/sun4i-i2s.c struct sun4i_i2s_clk_div { · line 116
Quoted 7 lines
sound/soc/sunxi/sun4i-i2s.c +7
-0+struct sun4i_i2s_quirks { +unsigned int reg_dac_txdata;/* TX FIFO offset for DMA config */ +bool has_reset; +const struct regmap_config *sun4i_i2s_regmap; +const struct snd_soc_dai_ops *ops; +}; +This is quite hard to review without actual example of what you'll put in there.
Fair enough...I have a patch for the A31 but haven't got any hardware that I can verify it on. I've confirmed on the H3 but I feel like that patch needs some tidying up. That being said...I'll push it as a patch set and we can talk about the setup.
Quoted 35 lines
Quoted 35 lines
sound/soc/sunxi/sun4i-i2s.c +8
-2static const struct sun4i_i2s_clk_div sun4i_i2s_bclk_div[] = { { .div =2 , .val =0 }, { .div =4 , .val =1 },@@ -541,7 +551,6 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = &sun4i_i2s_dai_ops, .symmetric_rates = 1, };@@ -655,6 +664,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev) {struct sun4i_i2s *i2s;struct resource *res; +const struct sun4i_i2s_quirks *quirks;void __iomem *regs;int irq, ret;@@ -680,8 +690,14 @@ static int sun4i_i2s_probe(struct platform_device *pdev)return PTR_ERR (i2s->bus_clk); } + quirks =of_device_get_match_data (&pdev->dev); +if (quirks ==NULL ) { +dev_err (&pdev->dev,"Failed to determine the quirks to use\n" ); +return -ENODEV ; + } + i2s->regmap =devm_regmap_init_mmio (&pdev->dev, regs, - &sun4i_i2s_regmap_config); + quirks->sun4i_i2s_regmap);if (IS_ERR (i2s->regmap)) {dev_err (&pdev->dev,"Regmap initialisation failed\n" );
Quoted 8 lines
sound/soc/sunxi/sun4i-i2s.c static int sun4i_i2s_probe(struct platform_device *pdev) · line 711
Quoted 6 lines
sound/soc/sunxi/sun4i-i2s.c +1
-0return PTR_ERR (i2s->regmap);@@ -692,13 +708,25 @@ static int sun4i_i2s_probe(struct platform_device *pdev)dev_err (&pdev->dev,"Can't get our mod clock\n" );return PTR_ERR (i2s->mod_clk); } +Spurious change?
ACK
Quoted 21 lines
Quoted 10 lines
sound/soc/sunxi/sun4i-i2s.c +2
-1- i2s->playback_dma_data.addr = res->start +SUN4I_I2S_FIFO_TX_REG ; + i2s->playback_dma_data.addr = res->start + quirks->reg_dac_txdata; i2s->playback_dma_data.maxburst =4 ; i2s->capture_dma_data.addr = res->start +SUN4I_I2S_FIFO_RX_REG ; i2s->capture_dma_data.maxburst =4 ; +if (quirks->has_reset) {sound/soc/sunxi/sun4i-i2s.c static int sun4i_i2s_probe(struct platform_device *pdev) · line 729
Quoted 10 lines
sound/soc/sunxi/sun4i-i2s.c +10
-0+ i2s->rst =devm_reset_control_get_optional (&pdev->dev,NULL ); +if (IS_ERR (i2s->rst) &&PTR_ERR (i2s->rst) == -EPROBE_DEFER ) { + ret = -EPROBE_DEFER ; +dev_err (&pdev->dev,"Failed to get reset: %d\n" , ret); + goto err_pm_disable; + } +if (!IS_ERR (i2s->rst)) +reset_control_deassert (i2s->rst); + } +
Quoted 2 lines
That reset line is not optional. The <A31 SoCs don't need it, and you cover that case already, but it is definitely mandatory for the A31.
OK..I'll search for a better function call. Thanks for this and the other reviews.
CK
Quoted 8 lines
Thanks,
Maxime--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com