summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBing Song <bing.song@nxp.com>2020-07-09 13:54:58 +0800
committerBing Song <bing.song@nxp.com>2020-07-10 16:48:12 +0800
commit3e26378f5315cf77a49e86b7658442ac42f2bd1a (patch)
tree9f0dade9aa063b6db16db1f845dc79e4b8b13a0a
parent3e415d0fadc13d42b2d6ec75701d2c16a1777723 (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>
-rw-r--r--sound/soc/fsl/fsl_dsp.c23
-rw-r--r--sound/soc/fsl/fsl_dsp_audiomix.c12
-rw-r--r--sound/soc/fsl/fsl_dsp_audiomix.h4
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