[alsa-devel] [PATCH v3 0/9] ASoC: fsl-ssi: offline/online configuration and cleanups
Hi,
This patch series fixes some fsl-ssi code that does not act exactly as it is described in the reference manuals.
The reference manuals before imx51 do mention that some register bits, including TDMAE/RDMAE, should not be changed while the SSI unit is enabled (SSIEN). At the same time the SDMA unit has a undefined request handling if there are DMA requests before the SDMA engine and its channel is configured. The reference manual states that SSI DMA requests are sent as soon as the FIFO and the DMAE bits are enabled. It does not mention a dependency to SCR's TE/RE bit.
To avoid sending DMA requests before a channel is configured, we have to seperate the fsl-ssi behavior into offline and online configuration. SoCs before imx51 have to use offline configuration while later SoC versions can use online reconfiguration.
This series adds support for online configuration and cleans up the configuration register code especially in fsl_ssi_trigger. At the end we have a seperation between enable/disable logic and the actual configuration register values used to enable/disable TX/RX.
v3 adds another fixup for the interrupt stats. The interrupt handler currently writes back a subset of the interrupt flags to clear the interrupts in the status register. This is not implemented on every processor. For example imx27 does not allow writebacks, imx53 does not allow writeback of RFRC and TFRC. The interrupt stats were disabled for imx by default. 'Fix interrupt mapping and release' enables it for mx53 again and changes the writeback flags.
I tested this series on mx53.
The series is based on Mark Brown's topic/fsl branch.
Regards,
Markus
Changes in v3: - Rebase on latest topic/fsl - Added patch to cleanup probe function error handling - Fix interrupt stats for imx53 - Replace imx50-ssi by imx51-ssi
Markus Pargmann (9): ASoC: fsl-ssi: Fix probe error handling ASoC: fsl-ssi: Move sysfs stats to debugfs ASoC: fsl-ssi: Add imx51-ssi and of_device_id matching ASoC: fsl-ssi: Fix interrupt mapping and release ASoC: fsl-ssi: Add offline_config flag ASoC: fsl-ssi: Add configuration helper functions ASoC: fsl-ssi: Move RX/TX configuration to seperate functions ASoC: fsl-ssi: Drop ac97 specific trigger function ARM: DTS: imx5* imx6*, use imx51-ssi
arch/arm/boot/dts/imx51.dtsi | 3 +- arch/arm/boot/dts/imx53.dtsi | 10 +- arch/arm/boot/dts/imx6qdl.dtsi | 12 +- arch/arm/boot/dts/imx6sl.dtsi | 12 +- sound/soc/fsl/fsl_ssi.c | 539 +++++++++++++++++++++++++++-------------- 5 files changed, 387 insertions(+), 189 deletions(-)
This patch fixes the error handling in the fsl-ssi probe function.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index f9f4569..cd9ad8c 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1007,11 +1007,11 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params); if (ret) - goto error_dev; + goto error_pcm; } else { ret = imx_pcm_dma_init(pdev); if (ret) - goto error_dev; + goto error_pcm; } }
@@ -1053,6 +1053,10 @@ done: return 0;
error_dai: + if (ssi_private->ssi_on_imx && !ssi_private->use_dma) + imx_pcm_fiq_exit(pdev); + +error_pcm: snd_soc_unregister_component(&pdev->dev);
error_dev: @@ -1063,7 +1067,9 @@ error_clk: clk_disable_unprepare(ssi_private->clk);
error_irqmap: - irq_dispose_mapping(ssi_private->irq); + if (ssi_private->use_dma && !of_device_is_compatible(pdev->dev.of_node, + "fsl,imx21-ssi")) + irq_dispose_mapping(ssi_private->irq);
return ret; }
On Wed, Dec 18, 2013 at 12:57:37PM +0100, Markus Pargmann wrote:
This patch fixes the error handling in the fsl-ssi probe function.
This doesn't apply against current code, please check and resend.
error_irqmap:
- irq_dispose_mapping(ssi_private->irq);
- if (ssi_private->use_dma && !of_device_is_compatible(pdev->dev.of_node,
"fsl,imx21-ssi"))
irq_dispose_mapping(ssi_private->irq);
This test is icky, a flag set when we create the mapping would be neter.
Hi,
On Thu, Dec 19, 2013 at 01:03:34PM +0000, Mark Brown wrote:
On Wed, Dec 18, 2013 at 12:57:37PM +0100, Markus Pargmann wrote:
This patch fixes the error handling in the fsl-ssi probe function.
This doesn't apply against current code, please check and resend.
Okay, I will rebase on your topic/fsl again.
error_irqmap:
- irq_dispose_mapping(ssi_private->irq);
- if (ssi_private->use_dma && !of_device_is_compatible(pdev->dev.of_node,
"fsl,imx21-ssi"))
irq_dispose_mapping(ssi_private->irq);
This test is icky, a flag set when we create the mapping would be neter.
Fixed.
Thanks,
Markus
Interrupt statistics of fsl_ssi are mainly for debugging purpose. Most of those interrupts show error states, e.g. under/overflow. The stats should be exposed via debugfs instead of sysfs.
This patch moves the statistics file to debugfs.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 184 ++++++++++++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 67 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index cd9ad8c..e949ce5 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -35,6 +35,7 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/clk.h> +#include <linux/debugfs.h> #include <linux/device.h> #include <linux/delay.h> #include <linux/slab.h> @@ -113,6 +114,14 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \ CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
+#define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \ + CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \ + CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN) +#define FSLSSI_SIER_DBG_TX_FLAGS (CCSR_SSI_SIER_TFE0_EN | \ + CCSR_SSI_SIER_TLS_EN | CCSR_SSI_SIER_TFS_EN | \ + CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN) +#define FSLSSI_SISR_MASK (FSLSSI_SIER_DBG_RX_FLAGS | FSLSSI_SIER_DBG_TX_FLAGS) + /** * fsl_ssi_private: per-SSI private data * @@ -132,7 +141,6 @@ struct fsl_ssi_private { unsigned int irq; unsigned int fifo_depth; struct snd_soc_dai_driver cpu_dai_drv; - struct device_attribute dev_attr; struct platform_device *pdev;
bool new_binding; @@ -170,6 +178,8 @@ struct fsl_ssi_private { unsigned int tfe1; unsigned int tfe0; } stats; + struct dentry *dbg_dir; + struct dentry *dbg_stats;
char name[1]; }; @@ -198,7 +208,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) were interrupted for. We mask it with the Interrupt Enable register so that we only check for events that we're interested in. */ - sisr = read_ssi(&ssi->sisr) & SIER_FLAGS; + sisr = read_ssi(&ssi->sisr) & FSLSSI_SISR_MASK;
if (sisr & CCSR_SSI_SISR_RFRC) { ssi_private->stats.rfrc++; @@ -318,6 +328,102 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) return ret; }
+#if IS_ENABLED(CONFIG_DEBUG_FS) +/* Show the statistics of a flag only if its interrupt is enabled. The + * compiler will optimze this code to a no-op if the interrupt is not + * enabled. + */ +#define SIER_SHOW(flag, name) \ + do { \ + if (FSLSSI_SISR_MASK & CCSR_SSI_SIER_##flag) \ + seq_printf(s, #name "=%u\n", ssi_private->stats.name); \ + } while (0) + + +/** + * fsl_sysfs_ssi_show: display SSI statistics + * + * Display the statistics for the current SSI device. To avoid confusion, + * we only show those counts that are enabled. + */ +static ssize_t fsl_ssi_stats_show(struct seq_file *s, void *unused) +{ + struct fsl_ssi_private *ssi_private = s->private; + + SIER_SHOW(RFRC_EN, rfrc); + SIER_SHOW(TFRC_EN, tfrc); + SIER_SHOW(CMDAU_EN, cmdau); + SIER_SHOW(CMDDU_EN, cmddu); + SIER_SHOW(RXT_EN, rxt); + SIER_SHOW(RDR1_EN, rdr1); + SIER_SHOW(RDR0_EN, rdr0); + SIER_SHOW(TDE1_EN, tde1); + SIER_SHOW(TDE0_EN, tde0); + SIER_SHOW(ROE1_EN, roe1); + SIER_SHOW(ROE0_EN, roe0); + SIER_SHOW(TUE1_EN, tue1); + SIER_SHOW(TUE0_EN, tue0); + SIER_SHOW(TFS_EN, tfs); + SIER_SHOW(RFS_EN, rfs); + SIER_SHOW(TLS_EN, tls); + SIER_SHOW(RLS_EN, rls); + SIER_SHOW(RFF1_EN, rff1); + SIER_SHOW(RFF0_EN, rff0); + SIER_SHOW(TFE1_EN, tfe1); + SIER_SHOW(TFE0_EN, tfe0); + + return 0; +} + +static int fsl_ssi_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, fsl_ssi_stats_show, inode->i_private); +} + +static const struct file_operations fsl_ssi_stats_ops = { + .open = fsl_ssi_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private, + struct device *dev) +{ + ssi_private->dbg_dir = debugfs_create_dir(dev_name(dev), NULL); + if (!ssi_private->dbg_dir) + return -ENOMEM; + + ssi_private->dbg_stats = debugfs_create_file("stats", S_IRUGO, + ssi_private->dbg_dir, ssi_private, &fsl_ssi_stats_ops); + if (!ssi_private->dbg_stats) { + debugfs_remove(ssi_private->dbg_dir); + return -ENOMEM; + } + + return 0; +} + +static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private) +{ + debugfs_remove(ssi_private->dbg_stats); + debugfs_remove(ssi_private->dbg_dir); +} + +#else + +static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private, + struct device *dev) +{ + return 0; +} + +static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private) +{ +} + +#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */ + static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; @@ -736,56 +842,6 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = { .write = fsl_ssi_ac97_write, };
-/* Show the statistics of a flag only if its interrupt is enabled. The - * compiler will optimze this code to a no-op if the interrupt is not - * enabled. - */ -#define SIER_SHOW(flag, name) \ - do { \ - if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \ - length += sprintf(buf + length, #name "=%u\n", \ - ssi_private->stats.name); \ - } while (0) - - -/** - * fsl_sysfs_ssi_show: display SSI statistics - * - * Display the statistics for the current SSI device. To avoid confusion, - * we only show those counts that are enabled. - */ -static ssize_t fsl_sysfs_ssi_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fsl_ssi_private *ssi_private = - container_of(attr, struct fsl_ssi_private, dev_attr); - ssize_t length = 0; - - SIER_SHOW(RFRC_EN, rfrc); - SIER_SHOW(TFRC_EN, tfrc); - SIER_SHOW(CMDAU_EN, cmdau); - SIER_SHOW(CMDDU_EN, cmddu); - SIER_SHOW(RXT_EN, rxt); - SIER_SHOW(RDR1_EN, rdr1); - SIER_SHOW(RDR0_EN, rdr0); - SIER_SHOW(TDE1_EN, tde1); - SIER_SHOW(TDE0_EN, tde0); - SIER_SHOW(ROE1_EN, roe1); - SIER_SHOW(ROE0_EN, roe0); - SIER_SHOW(TUE1_EN, tue1); - SIER_SHOW(TUE0_EN, tue0); - SIER_SHOW(TFS_EN, tfs); - SIER_SHOW(RFS_EN, rfs); - SIER_SHOW(TLS_EN, tls); - SIER_SHOW(RLS_EN, rls); - SIER_SHOW(RFF1_EN, rff1); - SIER_SHOW(RFF0_EN, rff0); - SIER_SHOW(TFE1_EN, tfe1); - SIER_SHOW(TFE0_EN, tfe0); - - return length; -} - /** * Make every character in a string lower-case */ @@ -964,20 +1020,6 @@ static int fsl_ssi_probe(struct platform_device *pdev) } }
- /* Initialize the the device_attribute structure */ - dev_attr = &ssi_private->dev_attr; - sysfs_attr_init(&dev_attr->attr); - dev_attr->attr.name = "statistics"; - dev_attr->attr.mode = S_IRUGO; - dev_attr->show = fsl_sysfs_ssi_show; - - ret = device_create_file(&pdev->dev, dev_attr); - if (ret) { - dev_err(&pdev->dev, "could not create sysfs %s file\n", - ssi_private->dev_attr.attr.name); - goto error_clk; - } - /* Register with ASoC */ dev_set_drvdata(&pdev->dev, ssi_private);
@@ -988,6 +1030,10 @@ static int fsl_ssi_probe(struct platform_device *pdev) goto error_dev; }
+ ret = fsl_ssi_debugfs_create(ssi_private, &pdev->dev); + if (ret) + goto error_dbgfs; + if (ssi_private->ssi_on_imx) { if (!ssi_private->use_dma) {
@@ -1057,6 +1103,9 @@ error_dai: imx_pcm_fiq_exit(pdev);
error_pcm: + fsl_ssi_debugfs_remove(ssi_private); + +error_dbgfs: snd_soc_unregister_component(&pdev->dev);
error_dev: @@ -1078,10 +1127,11 @@ static int fsl_ssi_remove(struct platform_device *pdev) { struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
+ fsl_ssi_debugfs_remove(ssi_private); + if (!ssi_private->new_binding) platform_device_unregister(ssi_private->pdev); snd_soc_unregister_component(&pdev->dev); - device_remove_file(&pdev->dev, &ssi_private->dev_attr); if (ssi_private->ssi_on_imx) clk_disable_unprepare(ssi_private->clk); irq_dispose_mapping(ssi_private->irq);
There is a small but significant difference between imx21-ssi and imx51-ssi and above. imx21-ssi does not allow online reconfiguration of some registers. They have to be configured at the beginning.
imx51-ssi has to reconfigure the SSI unit while it is running. Otherwise it would not be possible to have two streams in parallel. The new SDMA unit in imx51 and above has to be configured before the first DMA request arrives. Therefor we need to setup TDMAE/RDMAE just before starting the stream.
This patch introduces distinct imx51-ssi as compatible and adds of_device_id matching in the probe function.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index e949ce5..a889df5 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -122,6 +122,13 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN) #define FSLSSI_SISR_MASK (FSLSSI_SIER_DBG_RX_FLAGS | FSLSSI_SIER_DBG_TX_FLAGS)
+ +enum fsl_ssi_type { + FSL_SSI_MCP8610, + FSL_SSI_MX21, + FSL_SSI_MX51, +}; + /** * fsl_ssi_private: per-SSI private data * @@ -184,6 +191,14 @@ struct fsl_ssi_private { char name[1]; };
+static const struct of_device_id fsl_ssi_ids[] = { + { .compatible = "fsl,mpc8610-ssi", .data = (void *) FSL_SSI_MCP8610}, + { .compatible = "fsl,imx51-ssi", .data = (void *) FSL_SSI_MX51}, + { .compatible = "fsl,imx21-ssi", .data = (void *) FSL_SSI_MX21}, + {} +}; +MODULE_DEVICE_TABLE(of, fsl_ssi_ids); + /** * fsl_ssi_isr: SSI interrupt handler * @@ -863,6 +878,8 @@ static int fsl_ssi_probe(struct platform_device *pdev) int ret = 0; struct device_attribute *dev_attr = NULL; struct device_node *np = pdev->dev.of_node; + const struct of_device_id *of_id; + enum fsl_ssi_type hw_type; const char *p, *sprop; const uint32_t *iprop; struct resource res; @@ -877,6 +894,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) if (!of_device_is_available(np)) return -ENODEV;
+ of_id = of_match_device(fsl_ssi_ids, &pdev->dev); + if (!of_id) + return -EINVAL; + hw_type = (enum fsl_ssi_type) of_id->data; + /* We only support the SSI in "I2S Slave" mode */ sprop = of_get_property(np, "fsl,mode", NULL); if (!sprop) { @@ -953,7 +975,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) /* Older 8610 DTs didn't have the fifo-depth property */ ssi_private->fifo_depth = 8;
- if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { + if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51) { u32 dma_events[2]; ssi_private->ssi_on_imx = true;
@@ -1139,13 +1161,6 @@ static int fsl_ssi_remove(struct platform_device *pdev) return 0; }
-static const struct of_device_id fsl_ssi_ids[] = { - { .compatible = "fsl,mpc8610-ssi", }, - { .compatible = "fsl,imx21-ssi", }, - {} -}; -MODULE_DEVICE_TABLE(of, fsl_ssi_ids); - static struct platform_driver fsl_ssi_driver = { .driver = { .name = "fsl-ssi-dai",
irqs should only be requested/released with enabled DMA and not on MX21. MX21 has some special register write configurations, so we do not add support for statistics on mx21 for the moment.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index a889df5..c361730 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -150,6 +150,7 @@ struct fsl_ssi_private { struct snd_soc_dai_driver cpu_dai_drv; struct platform_device *pdev;
+ enum fsl_ssi_type hw_type; bool new_binding; bool ssi_on_imx; bool imx_ac97; @@ -227,13 +228,15 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
if (sisr & CCSR_SSI_SISR_RFRC) { ssi_private->stats.rfrc++; - sisr2 |= CCSR_SSI_SISR_RFRC; + if (ssi_private->hw_type != FSL_SSI_MX51) + sisr2 |= CCSR_SSI_SISR_RFRC; ret = IRQ_HANDLED; }
if (sisr & CCSR_SSI_SISR_TFRC) { ssi_private->stats.tfrc++; - sisr2 |= CCSR_SSI_SISR_TFRC; + if (ssi_private->hw_type != FSL_SSI_MX51) + sisr2 |= CCSR_SSI_SISR_TFRC; ret = IRQ_HANDLED; }
@@ -925,6 +928,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ssi_private->use_dma = !of_property_read_bool(np, "fsl,fiq-stream-filter"); + ssi_private->hw_type = hw_type;
if (ac97) { memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, @@ -1030,7 +1034,14 @@ static int fsl_ssi_probe(struct platform_device *pdev) dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); - } else if (ssi_private->use_dma) { + } + + /* + * Enable interrupts only for MCP8610 and MX51. The other MXs have + * different writeable interrupt status registers. + */ + if (ssi_private->use_dma && + (hw_type == FSL_SSI_MCP8610 || hw_type == FSL_SSI_MX51)) { /* The 'name' should not have any slashes in it. */ ret = devm_request_irq(&pdev->dev, ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, @@ -1138,8 +1149,8 @@ error_clk: clk_disable_unprepare(ssi_private->clk);
error_irqmap: - if (ssi_private->use_dma && !of_device_is_compatible(pdev->dev.of_node, - "fsl,imx21-ssi")) + if (ssi_private->use_dma && + (hw_type == FSL_SSI_MCP8610 || hw_type == FSL_SSI_MX51)) irq_dispose_mapping(ssi_private->irq);
return ret; @@ -1156,7 +1167,8 @@ static int fsl_ssi_remove(struct platform_device *pdev) snd_soc_unregister_component(&pdev->dev); if (ssi_private->ssi_on_imx) clk_disable_unprepare(ssi_private->clk); - irq_dispose_mapping(ssi_private->irq); + if (ssi_private->use_dma) + irq_dispose_mapping(ssi_private->irq);
return 0; }
Hi Markus,
On Wed, Dec 18, 2013 at 12:57:40PM +0100, Markus Pargmann wrote:
irqs should only be requested/released with enabled DMA and not on MX21. MX21 has some special register write configurations, so we do not add support for statistics on mx21 for the moment.
Signed-off-by: Markus Pargmann mpa@pengutronix.de
sound/soc/fsl/fsl_ssi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
@@ -227,13 +228,15 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
if (sisr & CCSR_SSI_SISR_RFRC) { ssi_private->stats.rfrc++;
sisr2 |= CCSR_SSI_SISR_RFRC;
if (ssi_private->hw_type != FSL_SSI_MX51)
sisr2 |= CCSR_SSI_SISR_RFRC;
ret = IRQ_HANDLED; }
if (sisr & CCSR_SSI_SISR_TFRC) { ssi_private->stats.tfrc++;
sisr2 |= CCSR_SSI_SISR_TFRC;
if (ssi_private->hw_type != FSL_SSI_MX51)
sisr2 |= CCSR_SSI_SISR_TFRC;
I had a hard time on this part of modification because I just saw the commit comments 'not on MX21' until I checked the RM of imx35, which should be same as imx21 one: RFRC and RFRC became non-writeable since imx51. The should be the reason here right?
And just for curiosity, is there any wrong with this part, like causing SSI mis-behavior?
Thank you, Nicolin Chen
Hi Nicolin,
On Fri, Dec 20, 2013 at 05:05:28PM +0800, Nicolin Chen wrote:
Hi Markus,
On Wed, Dec 18, 2013 at 12:57:40PM +0100, Markus Pargmann wrote:
irqs should only be requested/released with enabled DMA and not on MX21. MX21 has some special register write configurations, so we do not add support for statistics on mx21 for the moment.
Signed-off-by: Markus Pargmann mpa@pengutronix.de
sound/soc/fsl/fsl_ssi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
@@ -227,13 +228,15 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
if (sisr & CCSR_SSI_SISR_RFRC) { ssi_private->stats.rfrc++;
sisr2 |= CCSR_SSI_SISR_RFRC;
if (ssi_private->hw_type != FSL_SSI_MX51)
sisr2 |= CCSR_SSI_SISR_RFRC;
ret = IRQ_HANDLED; }
if (sisr & CCSR_SSI_SISR_TFRC) { ssi_private->stats.tfrc++;
sisr2 |= CCSR_SSI_SISR_TFRC;
if (ssi_private->hw_type != FSL_SSI_MX51)
sisr2 |= CCSR_SSI_SISR_TFRC;
I had a hard time on this part of modification because I just saw the commit comments 'not on MX21' until I checked the RM of imx35, which should be same as imx21 one: RFRC and RFRC became non-writeable since imx51. The should be the reason here right?
mx21 has actually no writable bits in SISR at all, it's the same for imx27 and imx31. imx35 would actually work with the current fsl_ssi_isr().
However I just realised that only imx35 has all 6 bits writeable right? So I added another hw_type MX35 to get irq stats working for all imx's.
And just for curiosity, is there any wrong with this part, like causing SSI mis-behavior?
Yes it doesn't work for all SoCs: f0377086 ASoC: fsl: disable ssi irq for imx
Thanks,
Markus
imx50-ssi and later versions of this IP support online reconfiguration of all registers. The reference manual does not list any registers that can only be configured while the SSI unit is disabled. This patch introduces the flag for later use.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index c361730..7a87d06 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -156,6 +156,7 @@ struct fsl_ssi_private { bool imx_ac97; bool use_dma; u8 i2s_mode; + bool offline_config; struct clk *clk; struct snd_dmaengine_dai_dma_data dma_params_tx; struct snd_dmaengine_dai_dma_data dma_params_rx; @@ -979,6 +980,24 @@ static int fsl_ssi_probe(struct platform_device *pdev) /* Older 8610 DTs didn't have the fifo-depth property */ ssi_private->fifo_depth = 8;
+ /* + * imx51 and later SoCs have a slightly different IP that allows the + * SSI configuration while the SSI unit is running. + * + * More important, it is necessary on those SoCs to configure the + * sperate TX/RX DMA bits just before starting the stream + * (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi + * sends any DMA requests to the SDMA unit, otherwise it is not defined + * how the SDMA unit handles the DMA request. + * + * SDMA units are present on devices starting at imx35 but the imx35 + * reference manual states that the DMA bits should not be changed + * while the SSI unit is running (SSIEN). So we support the necessary + * online configuration of fsl-ssi starting at imx51. + */ + if (hw_type != FSL_SSI_MX51) + ssi_private->offline_config = true; + if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51) { u32 dma_events[2]; ssi_private->ssi_on_imx = true;
On Wed, Dec 18, 2013 at 12:57:41PM +0100, Markus Pargmann wrote:
- /*
* imx51 and later SoCs have a slightly different IP that allows the
* SSI configuration while the SSI unit is running.
*
* More important, it is necessary on those SoCs to configure the
* sperate TX/RX DMA bits just before starting the stream
* (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi
* sends any DMA requests to the SDMA unit, otherwise it is not defined
* how the SDMA unit handles the DMA request.
*
* SDMA units are present on devices starting at imx35 but the imx35
* reference manual states that the DMA bits should not be changed
* while the SSI unit is running (SSIEN). So we support the necessary
* online configuration of fsl-ssi starting at imx51.
*/
- if (hw_type != FSL_SSI_MX51)
ssi_private->offline_config = true;
This is really confusing. I'd expect a switch statement here enumerating the pre-i.MX51 hardware types otherwise if there's a new variant added it'll do the wrong thing - the comment sounds like the opposite of the test.
On Thu, Dec 19, 2013 at 01:16:43PM +0000, Mark Brown wrote:
On Wed, Dec 18, 2013 at 12:57:41PM +0100, Markus Pargmann wrote:
- /*
* imx51 and later SoCs have a slightly different IP that allows the
* SSI configuration while the SSI unit is running.
*
* More important, it is necessary on those SoCs to configure the
* sperate TX/RX DMA bits just before starting the stream
* (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi
* sends any DMA requests to the SDMA unit, otherwise it is not defined
* how the SDMA unit handles the DMA request.
*
* SDMA units are present on devices starting at imx35 but the imx35
* reference manual states that the DMA bits should not be changed
* while the SSI unit is running (SSIEN). So we support the necessary
* online configuration of fsl-ssi starting at imx51.
*/
- if (hw_type != FSL_SSI_MX51)
ssi_private->offline_config = true;
This is really confusing. I'd expect a switch statement here enumerating the pre-i.MX51 hardware types otherwise if there's a new variant added it'll do the wrong thing - the comment sounds like the opposite of the test.
Fixed.
Thanks,
Markus
This patch adds a struct 'fsl_ssi_rxtx_reg_val' which holds register values necessary to enable rx/tx. Based on those preset register values, the added configuration functions will cleanly enable/disable different parts of the SSI IP while supporting online/offline configuration. Different operating modes can be setup directly as different register values in fsl_ssi_reg_val.
These functions and structs will help to cleanup and simplify the trigger function to support many different IP versions (online/offline configuration) and different operating modes.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 7a87d06..eabf568 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -129,6 +129,18 @@ enum fsl_ssi_type { FSL_SSI_MX51, };
+struct fsl_ssi_reg_val { + u32 sier; + u32 srcr; + u32 stcr; + u32 scr; +}; + +struct fsl_ssi_rxtx_reg_val { + struct fsl_ssi_reg_val rx; + struct fsl_ssi_reg_val tx; +}; + /** * fsl_ssi_private: per-SSI private data * @@ -163,6 +175,8 @@ struct fsl_ssi_private { struct imx_dma_data filter_data_tx; struct imx_dma_data filter_data_rx; struct imx_pcm_fiq_params fiq_params; + /* Register values for rx/tx configuration */ + struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
struct { unsigned int rfrc; @@ -443,6 +457,114 @@ static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private)
#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
+/* + * Enable/Disable all rx/tx config flags at once. + */ +static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private, + bool enable) +{ + struct ccsr_ssi __iomem *ssi = ssi_private->ssi; + struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val; + + if (enable) { + write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier); + write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr); + write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr); + } else { + write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0); + write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0); + write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0); + } +} + +/* + * Enable/Disable a ssi configuration. You have to pass either + * ssi_private->rxtx_reg_val.rx or tx as vals parameter. + */ +static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable, + struct fsl_ssi_reg_val *vals) +{ + struct ccsr_ssi __iomem *ssi = ssi_private->ssi; + struct fsl_ssi_reg_val *avals; + u32 scr_val = read_ssi(&ssi->scr); + int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) + + !!(scr_val & CCSR_SSI_SCR_RE); + + /* Find the other direction values rx or tx which we do not want to + * modify */ + if (&ssi_private->rxtx_reg_val.rx == vals) + avals = &ssi_private->rxtx_reg_val.tx; + else + avals = &ssi_private->rxtx_reg_val.rx; + + /* If vals should be disabled, start with disabling the unit */ + if (!enable) { + u32 scr = vals->scr & (vals->scr ^ avals->scr); + write_ssi_mask(&ssi->scr, scr, 0); + } + + /* + * We are running on a SoC which does not support online SSI + * reconfiguration, so we have to enable all necessary flags at once + * even if we do not use them later (capture and playback configuration) + */ + if (ssi_private->offline_config) { + if ((enable && !nr_active_streams) || + (!enable && nr_active_streams == 1)) + fsl_ssi_rxtx_config(ssi_private, enable); + + goto config_done; + } + + /* + * Configure single direction units while the SSI unit is running + * (online configuration) + */ + if (enable) { + write_ssi_mask(&ssi->sier, 0, vals->sier); + write_ssi_mask(&ssi->srcr, 0, vals->srcr); + write_ssi_mask(&ssi->stcr, 0, vals->stcr); + } else { + u32 sier; + u32 srcr; + u32 stcr; + + /* + * Disabling the necessary flags for one of rx/tx while the + * other stream is active is a little bit more difficult. We + * have to disable only those flags that differ between both + * streams (rx XOR tx) and that are set in the stream that is + * disabled now. Otherwise we could alter flags of the other + * stream + */ + + /* These assignments are simply vals without bits set in avals*/ + sier = vals->sier & (vals->sier ^ avals->sier); + srcr = vals->srcr & (vals->srcr ^ avals->srcr); + stcr = vals->stcr & (vals->stcr ^ avals->stcr); + + write_ssi_mask(&ssi->srcr, srcr, 0); + write_ssi_mask(&ssi->stcr, stcr, 0); + write_ssi_mask(&ssi->sier, sier, 0); + } + +config_done: + /* Enabling of subunits is done after configuration */ + if (enable) + write_ssi_mask(&ssi->scr, 0, vals->scr); +} + + +static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable) +{ + fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx); +} + +static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable) +{ + fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); +} + static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
This patch defines the appropriate register values for different oparation modes and IP versions. We have to handle DMA/FIQ, AC97, DEBUG-IRQs and offline/online configuration support.
With this patch we cleanup some driver code that was not reference manual conform and try to cleanup the whole trigger function to seperate the actual register values from the enable/disable logic, which is now hidden in fsl_ssi_config helpers.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 94 +++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 46 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index eabf568..26190f9 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -107,13 +107,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) #endif
-/* SIER bitflag of interrupts to enable */ -#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \ - CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \ - CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \ - CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \ - CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN) - #define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \ CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \ CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN) @@ -565,6 +558,43 @@ static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable) fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); }
+/* + * Setup rx/tx register values used to enable/disable the streams. These will + * be used later in fsl_ssi_config to setup the streams without the need to + * check for all different SSI modes. + */ +static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private) +{ + struct fsl_ssi_rxtx_reg_val *reg = &ssi_private->rxtx_reg_val; + + reg->rx.sier = CCSR_SSI_SIER_RFF0_EN; + reg->rx.srcr = CCSR_SSI_SRCR_RFEN0; + reg->rx.scr = 0; + reg->tx.sier = CCSR_SSI_SIER_TFE0_EN; + reg->tx.stcr = CCSR_SSI_STCR_TFEN0; + reg->tx.scr = 0; + + if (!ssi_private->imx_ac97) { + reg->rx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE; + reg->rx.sier |= CCSR_SSI_SIER_RFF0_EN; + reg->tx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE; + reg->tx.sier |= CCSR_SSI_SIER_TFE0_EN; + } + + if (ssi_private->use_dma) { + reg->rx.sier |= CCSR_SSI_SIER_RDMAE; + reg->tx.sier |= CCSR_SSI_SIER_TDMAE; + } else { + reg->rx.sier |= CCSR_SSI_SIER_RIE; + reg->tx.sier |= CCSR_SSI_SIER_TIE; + } + +#if IS_ENABLED(CONFIG_DEBUG_FS) + reg->rx.sier |= FSLSSI_SIER_DBG_RX_FLAGS; + reg->tx.sier |= FSLSSI_SIER_DBG_TX_FLAGS; +#endif +} + static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; @@ -601,6 +631,8 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) u8 wm; int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
+ fsl_ssi_setup_reg_vals(ssi_private); + if (ssi_private->imx_ac97) ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; else @@ -624,13 +656,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) ssi_private->i2s_mode | (synchronous ? CCSR_SSI_SCR_SYN : 0));
- write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | - CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | - CCSR_SSI_STCR_TSCKP, &ssi->stcr); + write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFSI | + CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr); + + write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFSI | + CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
- write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | - CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | - CCSR_SSI_SRCR_RSCKP, &ssi->srcr); /* * The DC and PM bits are only used if the SSI is the clock master. */ @@ -762,57 +793,28 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; - unsigned int sier_bits; - - /* - * Enable only the interrupts and DMA requests - * that are needed for the channel. As the fiq - * is polling for this bits, we have to ensure - * that this are aligned with the preallocated - * buffers - */ - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (ssi_private->use_dma) - sier_bits = SIER_FLAGS; - else - sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN; - } else { - if (ssi_private->use_dma) - sier_bits = SIER_FLAGS; - else - sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN; - }
switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - write_ssi_mask(&ssi->scr, 0, - CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); + fsl_ssi_tx_config(ssi_private, true); else - write_ssi_mask(&ssi->scr, 0, - CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); + fsl_ssi_rx_config(ssi_private, true); break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); + fsl_ssi_tx_config(ssi_private, false); else - write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); - - if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & - (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) - write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); + fsl_ssi_rx_config(ssi_private, false); break;
default: return -EINVAL; }
- write_ssi(sier_bits, &ssi->sier);
return 0; }
The normal trigger function can now be used for AC97. Drop AC97 trigger function.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- sound/soc/fsl/fsl_ssi.c | 61 +++++++------------------------------------------ 1 file changed, 8 insertions(+), 53 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 26190f9..d38f1c1 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -793,6 +793,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); + struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -815,6 +816,12 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, return -EINVAL; }
+ if (ssi_private->imx_ac97) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); + else + write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); + }
return 0; } @@ -859,58 +866,6 @@ static const struct snd_soc_component_driver fsl_ssi_component = { .name = "fsl-ssi", };
-/** - * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit. - * - * This function is called by ALSA to start, stop, pause, and resume the - * transfer of data. - */ -static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata( - rtd->cpu_dai); - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE | - CCSR_SSI_SIER_TFE0_EN); - else - write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE | - CCSR_SSI_SIER_RFF0_EN); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE | - CCSR_SSI_SIER_TFE0_EN, 0); - else - write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE | - CCSR_SSI_SIER_RFF0_EN, 0); - break; - - default: - return -EINVAL; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); - else - write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); - - return 0; -} - -static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { - .startup = fsl_ssi_startup, - .trigger = fsl_ssi_ac97_trigger, -}; - static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { .ac97_control = 1, .playback = { @@ -927,7 +882,7 @@ static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { .rates = SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = &fsl_ssi_ac97_dai_ops, + .ops = &fsl_ssi_dai_ops, };
imx51-ssi and imx21-ssi are different IPs. imx51-ssi supports online reconfiguration and needs this for correct interaction with SDMA. This patch adds imx51-ssi before each imx21-ssi for all imx5/imx6 SoCs.
Signed-off-by: Markus Pargmann mpa@pengutronix.de --- arch/arm/boot/dts/imx51.dtsi | 3 ++- arch/arm/boot/dts/imx53.dtsi | 10 +++++++--- arch/arm/boot/dts/imx6qdl.dtsi | 12 +++++++++--- arch/arm/boot/dts/imx6sl.dtsi | 12 +++++++++--- 4 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index 4bcdd3a..1496421 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -155,7 +155,8 @@ };
ssi2: ssi@70014000 { - compatible = "fsl,imx51-ssi", "fsl,imx21-ssi"; + compatible = "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x70014000 0x4000>; interrupts = <30>; clocks = <&clks 49>; diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index 4307e80..034b8b0 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -149,7 +149,9 @@ };
ssi2: ssi@50014000 { - compatible = "fsl,imx53-ssi", "fsl,imx21-ssi"; + compatible = "fsl,imx53-ssi", + "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x50014000 0x4000>; interrupts = <30>; clocks = <&clks 49>; @@ -1049,7 +1051,8 @@ };
ssi1: ssi@63fcc000 { - compatible = "fsl,imx53-ssi", "fsl,imx21-ssi"; + compatible = "fsl,imx53-ssi", "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x63fcc000 0x4000>; interrupts = <29>; clocks = <&clks 48>; @@ -1076,7 +1079,8 @@ };
ssi3: ssi@63fe8000 { - compatible = "fsl,imx53-ssi", "fsl,imx21-ssi"; + compatible = "fsl,imx53-ssi", "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x63fe8000 0x4000>; interrupts = <96>; clocks = <&clks 50>; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 59154dc..c51440b 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -232,7 +232,9 @@ };
ssi1: ssi@02028000 { - compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; + compatible = "fsl,imx6q-ssi", + "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x02028000 0x4000>; interrupts = <0 46 0x04>; clocks = <&clks 178>; @@ -245,7 +247,9 @@ };
ssi2: ssi@0202c000 { - compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; + compatible = "fsl,imx6q-ssi", + "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x0202c000 0x4000>; interrupts = <0 47 0x04>; clocks = <&clks 179>; @@ -258,7 +262,9 @@ };
ssi3: ssi@02030000 { - compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; + compatible = "fsl,imx6q-ssi", + "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x02030000 0x4000>; interrupts = <0 48 0x04>; clocks = <&clks 180>; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index 28558f1..1e7b712 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -195,7 +195,9 @@ };
ssi1: ssi@02028000 { - compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi"; + compatible = "fsl,imx6sl-ssi", + "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x02028000 0x4000>; interrupts = <0 46 0x04>; clocks = <&clks IMX6SL_CLK_SSI1>; @@ -207,7 +209,9 @@ };
ssi2: ssi@0202c000 { - compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi"; + compatible = "fsl,imx6sl-ssi", + "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x0202c000 0x4000>; interrupts = <0 47 0x04>; clocks = <&clks IMX6SL_CLK_SSI2>; @@ -219,7 +223,9 @@ };
ssi3: ssi@02030000 { - compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi"; + compatible = "fsl,imx6sl-ssi", + "fsl,imx51-ssi", + "fsl,imx21-ssi"; reg = <0x02030000 0x4000>; interrupts = <0 48 0x04>; clocks = <&clks IMX6SL_CLK_SSI3>;
On Wed, Dec 18, 2013 at 12:57:45PM +0100, Markus Pargmann wrote:
imx51-ssi and imx21-ssi are different IPs. imx51-ssi supports online reconfiguration and needs this for correct interaction with SDMA. This patch adds imx51-ssi before each imx21-ssi for all imx5/imx6 SoCs.
Signed-off-by: Markus Pargmann mpa@pengutronix.de
arch/arm/boot/dts/imx51.dtsi | 3 ++- arch/arm/boot/dts/imx53.dtsi | 10 +++++++--- arch/arm/boot/dts/imx6qdl.dtsi | 12 +++++++++--- arch/arm/boot/dts/imx6sl.dtsi | 12 +++++++++--- 4 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index 4bcdd3a..1496421 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -155,7 +155,8 @@ };
ssi2: ssi@70014000 {
compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
compatible = "fsl,imx51-ssi",
"fsl,imx21-ssi";
This is an unnecessary change.
Shawn
reg = <0x70014000 0x4000>; interrupts = <30>; clocks = <&clks 49>;
On Wed, Dec 18, 2013 at 09:58:30PM +0800, Shawn Guo wrote:
On Wed, Dec 18, 2013 at 12:57:45PM +0100, Markus Pargmann wrote:
imx51-ssi and imx21-ssi are different IPs. imx51-ssi supports online reconfiguration and needs this for correct interaction with SDMA. This patch adds imx51-ssi before each imx21-ssi for all imx5/imx6 SoCs.
Signed-off-by: Markus Pargmann mpa@pengutronix.de
arch/arm/boot/dts/imx51.dtsi | 3 ++- arch/arm/boot/dts/imx53.dtsi | 10 +++++++--- arch/arm/boot/dts/imx6qdl.dtsi | 12 +++++++++--- arch/arm/boot/dts/imx6sl.dtsi | 12 +++++++++--- 4 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index 4bcdd3a..1496421 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -155,7 +155,8 @@ };
ssi2: ssi@70014000 {
compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
compatible = "fsl,imx51-ssi",
"fsl,imx21-ssi";
This is an unnecessary change.
Shawn
Thank you, fixed.
Regards,
Markus
participants (4)
-
Mark Brown
-
Markus Pargmann
-
Nicolin Chen
-
Shawn Guo