diff options
author | Shengjiu Wang <shengjiu.wang@freescale.com> | 2017-06-19 11:41:44 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 6a908c0e060e8c3b9322b6207b1edb35db8696ad (patch) | |
tree | 516dbd8d6686f88c45f6bb1453f690dc65aa60b2 | |
parent | b0e84ac9bb4974292979bc9073e1254678cf96cc (diff) |
MLK-15109-1: ASoC: fsl_esai: introduce SoC specific data
Introduce a SoC data struct which contains the differences between
the different SoCs this driver supports. This makes it easy to support
more differences without having to introduce a new switch/case each
time.
Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
-rw-r--r-- | Documentation/devicetree/bindings/sound/fsl,esai.txt | 2 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_esai.c | 87 |
2 files changed, 64 insertions, 25 deletions
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index 1d527695d6b0..bcb4d3fa2f9e 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt @@ -8,7 +8,7 @@ other DSPs. It has up to six transmitters and four receivers. Required properties: - compatible : Compatible list, must contain "fsl,imx6ull-esai", - "fsl,imx8qxp-v1-esai", + "fsl,imx8qxp-v1-esai", "fsl,imx8qm-esai" "fsl,imx35-esai" or "fsl,vf610-esai" - reg : Offset and length of the register set for the device. diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 10b81ec02f93..01ef99f91ae2 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -82,6 +82,12 @@ struct fsl_edma3_sw_tcd { struct fsl_edma3_hw_tcd *vtcd; }; +struct fsl_esai_soc_data { + bool imx; + bool dma_workaround; + bool channel_swap_workaround; +}; + /** * fsl_esai: ESAI private data * @@ -117,6 +123,7 @@ struct fsl_esai { struct fsl_edma3_sw_tcd tcd_sw[4]; struct dma_pool *tcd_pool; struct snd_dma_buffer buf; + const struct fsl_esai_soc_data *soc; void __iomem *base_gpt0; void __iomem *base_gpt1; void __iomem *base_gpt2; @@ -135,10 +142,43 @@ struct fsl_esai { bool sck_div[2]; bool slave_mode; bool synchronous; - bool dma_workaround; char name[32]; }; +static struct fsl_esai_soc_data fsl_esai_vf610 = { + .imx = false, + .dma_workaround = false, + .channel_swap_workaround = true, +}; + +static struct fsl_esai_soc_data fsl_esai_imx35 = { + .imx = true, + .dma_workaround = false, + .channel_swap_workaround = true, +}; + +static struct fsl_esai_soc_data fsl_esai_imx6ull = { + .imx = true, + .dma_workaround = false, + .channel_swap_workaround = false, +}; + +/* In imx8qxp rev1, the dma request signal is not revert. For esai + * dma request is low valid, but edma assert it as high level valid. + * so we need to use GPT to transfer the dma request signal. + */ +static struct fsl_esai_soc_data fsl_esai_imx8qxp_v1 = { + .imx = true, + .dma_workaround = true, + .channel_swap_workaround = false, +}; + +static struct fsl_esai_soc_data fsl_esai_imx8qm = { + .imx = true, + .dma_workaround = false, + .channel_swap_workaround = false, +}; + static irqreturn_t esai_isr(int irq, void *devid) { struct fsl_esai *esai_priv = (struct fsl_esai *)devid; @@ -752,7 +792,7 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, u32 bclk, mask, val; int ret; - if (esai_priv->dma_workaround) + if (esai_priv->soc->dma_workaround) configure_gpt_dma(substream, dai); /* Override slot_width if being specifically set */ @@ -879,7 +919,7 @@ static int fsl_esai_hw_free(struct snd_pcm_substream *substream, { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai); - if (esai_priv->dma_workaround) + if (esai_priv->soc->dma_workaround) clear_gpt_dma(substream, cpu_dai); return 0; @@ -1126,9 +1166,20 @@ static void fsl_esai_reset(struct snd_pcm_substream *substream, bool stop) imx_start_unlock_pcm_streams(esai_priv->substream, 2, &flags); } +static const struct of_device_id fsl_esai_dt_ids[] = { + { .compatible = "fsl,imx8qxp-v1-esai", .data = &fsl_esai_imx8qxp_v1 }, + { .compatible = "fsl,imx8qm-esai", .data = &fsl_esai_imx8qm }, + { .compatible = "fsl,imx6ull-esai", .data = &fsl_esai_imx6ull }, + { .compatible = "fsl,imx35-esai", .data = &fsl_esai_imx35 }, + { .compatible = "fsl,vf610-esai", .data = &fsl_esai_vf610 }, + {} +}; +MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); + static int fsl_esai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + const struct of_device_id *of_id; struct fsl_esai *esai_priv; struct resource *res; const uint32_t *iprop; @@ -1146,6 +1197,12 @@ static int fsl_esai_probe(struct platform_device *pdev) esai_priv->pdev = pdev; strncpy(esai_priv->name, np->name, sizeof(esai_priv->name) - 1); + of_id = of_match_device(fsl_esai_dt_ids, &pdev->dev); + if (!of_id || !of_id->data) + return -EINVAL; + + esai_priv->soc = of_id->data; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); @@ -1222,22 +1279,13 @@ static int fsl_esai_probe(struct platform_device *pdev) /* From imx6ull, the channel swap issue in underrun/overrun is * fixed in hardware. So remove the workaround. */ - if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-esai") || - of_device_is_compatible(pdev->dev.of_node, "fsl,vf610-esai")) { + if (esai_priv->soc->channel_swap_workaround) { esai_priv->dma_params_tx.check_xrun = fsl_esai_check_xrun; esai_priv->dma_params_rx.check_xrun = fsl_esai_check_xrun; esai_priv->dma_params_tx.device_reset = fsl_esai_reset; esai_priv->dma_params_rx.device_reset = fsl_esai_reset; } - /* In imx8qxp rev1, the dma request signal is not revert. For esai - * dma request is low valid, but edma assert it as high level valid. - * so we need to use GPT to transfer the dma request signal. - * - */ - if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx8qxp-v1-esai")) - esai_priv->dma_workaround = true; - esai_priv->synchronous = of_property_read_bool(np, "fsl,esai-synchronous"); @@ -1284,7 +1332,7 @@ static int fsl_esai_probe(struct platform_device *pdev) buffer_size = IMX_ESAI_DMABUF_SIZE; /*workaround for esai issue in imx8qxp*/ - if (esai_priv->dma_workaround) { + if (esai_priv->soc->dma_workaround) { esai_priv->tcd_pool = dma_pool_create("tcd_pool_esai", &esai_priv->pdev->dev, sizeof(struct fsl_edma3_hw_tcd), 32, 0); @@ -1355,7 +1403,7 @@ static int fsl_esai_remove(struct platform_device *pdev) { struct fsl_esai *esai_priv = dev_get_drvdata(&pdev->dev); - if (esai_priv->dma_workaround) { + if (esai_priv->soc->dma_workaround) { dma_free_writecombine(&esai_priv->pdev->dev, 0x1000, esai_priv->buf.area, @@ -1380,15 +1428,6 @@ static int fsl_esai_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id fsl_esai_dt_ids[] = { - { .compatible = "fsl,imx8qxp-v1-esai", }, - { .compatible = "fsl,imx6ull-esai", }, - { .compatible = "fsl,imx35-esai", }, - { .compatible = "fsl,vf610-esai", }, - {} -}; -MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); - #ifdef CONFIG_PM_SLEEP static int fsl_esai_suspend(struct device *dev) { |