diff options
author | Bing Song <bing.song@nxp.com> | 2020-07-09 13:54:58 +0800 |
---|---|---|
committer | Bing Song <bing.song@nxp.com> | 2020-07-10 16:48:12 +0800 |
commit | 3e26378f5315cf77a49e86b7658442ac42f2bd1a (patch) | |
tree | 9f0dade9aa063b6db16db1f845dc79e4b8b13a0a /sound | |
parent | 3e415d0fadc13d42b2d6ec75701d2c16a1777723 (diff) |
MLK-24365-11 dsp: wait DSP idle before close it.
Wait DSP to idle before gate OCRAM_A clock as FW code locate on
OCRAM_A when LPA. Or DSP will hang.
Signed-off-by: Bing Song <bing.song@nxp.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/fsl/fsl_dsp.c | 23 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_dsp_audiomix.c | 12 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_dsp_audiomix.h | 4 |
3 files changed, 38 insertions, 1 deletions
diff --git a/sound/soc/fsl/fsl_dsp.c b/sound/soc/fsl/fsl_dsp.c index dbf2819bc1e7..547713907580 100644 --- a/sound/soc/fsl/fsl_dsp.c +++ b/sound/soc/fsl/fsl_dsp.c @@ -404,6 +404,25 @@ static int fsl_dsp_open(struct inode *inode, struct file *file) return ret; } +static int fsl_dsp_wait_idle(struct fsl_dsp *dsp_priv) +{ + int timeout = 200; + + if (dsp_priv->dsp_is_lpa) { + /* FW code is on OCRAM_A, Need wait DSP idle before gate */ + /* OCRAM_A clock. Or DSP will hang */ + while (!imx_audiomix_dsp_pwaitmode(dsp_priv->audiomix)) { + if (!timeout--) { + dev_err(dsp_priv->dev, "DSP failed to idle\n"); + return -ETIME; + } + udelay(5); + } + } + + return 0; +} + int fsl_dsp_close_func(struct xf_client *client) { struct fsl_dsp *dsp_priv; @@ -418,6 +437,10 @@ int fsl_dsp_close_func(struct xf_client *client) xf_msg_free_all(proxy, &client->queue); dsp_priv = (struct fsl_dsp *)client->global; + + /* wait until DSP idle */ + fsl_dsp_wait_idle(dsp_priv); + dev = dsp_priv->dev; pm_runtime_put_sync(dev); diff --git a/sound/soc/fsl/fsl_dsp_audiomix.c b/sound/soc/fsl/fsl_dsp_audiomix.c index 679550ae857d..d86d70795846 100644 --- a/sound/soc/fsl/fsl_dsp_audiomix.c +++ b/sound/soc/fsl/fsl_dsp_audiomix.c @@ -54,6 +54,18 @@ bool imx_audiomix_dsp_reset(struct imx_audiomix_dsp_data *data) } EXPORT_SYMBOL(imx_audiomix_dsp_reset); +bool imx_audiomix_dsp_pwaitmode(struct imx_audiomix_dsp_data *data) +{ + u32 val; + + val = readl(data->base + AudioDSP_REG2); + if (val & AudioDSP_REG2_PWAITMODE) + return true; + else + return false; +} +EXPORT_SYMBOL(imx_audiomix_dsp_pwaitmode); + static int imx_audiomix_dsp_probe(struct platform_device *pdev) { struct imx_audiomix_dsp_data *drvdata; diff --git a/sound/soc/fsl/fsl_dsp_audiomix.h b/sound/soc/fsl/fsl_dsp_audiomix.h index 40fdf0d30dfa..2920442b8a4e 100644 --- a/sound/soc/fsl/fsl_dsp_audiomix.h +++ b/sound/soc/fsl/fsl_dsp_audiomix.h @@ -13,12 +13,14 @@ #define AudioDSP_REG2 0x108 #define AudioDSP_REG3 0x10c -#define AudioDSP_REG2_RUNSTALL BIT(5) +#define AudioDSP_REG2_RUNSTALL BIT(5) +#define AudioDSP_REG2_PWAITMODE BIT(1) struct imx_audiomix_dsp_data; void imx_audiomix_dsp_start(struct imx_audiomix_dsp_data *data); void imx_audiomix_dsp_stall(struct imx_audiomix_dsp_data *data); void imx_audiomix_dsp_pid_set(struct imx_audiomix_dsp_data *data, u32 val); bool imx_audiomix_dsp_reset(struct imx_audiomix_dsp_data *data); +bool imx_audiomix_dsp_pwaitmode(struct imx_audiomix_dsp_data *data); #endif |