summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2019-09-17 13:29:17 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:48:52 +0800
commit03944b23b2f2da1b05e79dad3d46db3cd31fd1c6 (patch)
tree6d516924a285b3ed56f2f07517499da23c0cf1b1
parent8a4b48b55237890f15762bd2fdf89dca4f56f4df (diff)
MLK-22591: ASoC: fsl_easrc: Add RUN_STOP in stop context
When record bitstream with ASRC+AK5558, there may be I/O error for the high sample rate case (352kHz/768kHz). The reason is that the context is not fully reset after conversion, the ASRC does not start to work in next conversion. In order to fully reset the context, we need to enable RUN_STOP, then clear the RUN_EN bit. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> (cherry picked from commit 7b44c3c653acf078b6477fbc0393f88708ccb24c)
-rw-r--r--sound/soc/fsl/fsl_easrc.c41
-rw-r--r--sound/soc/fsl/fsl_easrc.h24
2 files changed, 51 insertions, 14 deletions
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 4769c350acb3..d35957c85a9a 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1505,11 +1505,47 @@ int fsl_easrc_start_context(struct fsl_easrc_context *ctx)
int fsl_easrc_stop_context(struct fsl_easrc_context *ctx)
{
struct fsl_easrc *easrc = ctx->easrc;
- int ret;
+ int ret, val, i;
+ int size = 0;
+ int retry = 200;
+
+ regmap_read(easrc->regmap, REG_EASRC_CC(ctx->index), &val);
+
+ if (val & EASRC_CC_EN_MASK) {
+ ret = regmap_update_bits(easrc->regmap,
+ REG_EASRC_CC(ctx->index),
+ EASRC_CC_STOP_MASK, EASRC_CC_STOP);
+ if (ret)
+ return ret;
+
+ do {
+ regmap_read(easrc->regmap, REG_EASRC_SFS(ctx->index), &val);
+ val &= EASRC_SFS_NSGO_MASK;
+ size = val >> EASRC_SFS_NSGO_SHIFT;
+
+ /* Read FIFO, drop the data */
+ for (i = 0; i < size * ctx->channels; i++)
+ regmap_read(easrc->regmap, REG_EASRC_RDFIFO(ctx->index), &val);
+ /* Check RUN_STOP_DONE */
+ regmap_read(easrc->regmap, REG_EASRC_IRQF, &val);
+ if (val & EASRC_IRQF_RSD(1 << ctx->index)) {
+ /*Clear RUN_STOP_DONE*/
+ regmap_write_bits(easrc->regmap,
+ REG_EASRC_IRQF,
+ EASRC_IRQF_RSD(1 << ctx->index),
+ EASRC_IRQF_RSD(1 << ctx->index));
+ break;
+ }
+ udelay(100);
+ } while (--retry);
+
+ if (retry == 0)
+ dev_err(&easrc->pdev->dev, "RUN STOP fail\n");
+ }
ret = regmap_update_bits(easrc->regmap,
REG_EASRC_CC(ctx->index),
- EASRC_CC_EN_MASK, 0);
+ EASRC_CC_EN_MASK | EASRC_CC_STOP_MASK, 0);
if (ret)
return ret;
@@ -2107,6 +2143,7 @@ static bool fsl_easrc_volatile_reg(struct device *dev, unsigned int reg)
case REG_EASRC_SFS(1):
case REG_EASRC_SFS(2):
case REG_EASRC_SFS(3):
+ case REG_EASRC_IRQF:
case REG_EASRC_DBGS:
return true;
default:
diff --git a/sound/soc/fsl/fsl_easrc.h b/sound/soc/fsl/fsl_easrc.h
index 93ee99725afb..f23374fd85ce 100644
--- a/sound/soc/fsl/fsl_easrc.h
+++ b/sound/soc/fsl/fsl_easrc.h
@@ -458,22 +458,22 @@
/* ASRC Interrupt Status Flags (ISF) */
#define EASRC_IRQF_RSD_SHIFT 8
#define EASRC_IRQF_RSD_WIDTH 4
-#define EASRC_IRQF_RSD_MASK ((BIT(EASRC_ISF_RSD_WIDTH) - 1) \
- << EASRC_ISF_RSD_SHIFT)
-#define EASRC_IRQF_RSD(v) (((v) << EASRC_ISF_RSD_SHIFT) \
- & EASRC_ISF_RSD_MASK)
+#define EASRC_IRQF_RSD_MASK ((BIT(EASRC_IRQF_RSD_WIDTH) - 1) \
+ << EASRC_IRQF_RSD_SHIFT)
+#define EASRC_IRQF_RSD(v) (((v) << EASRC_IRQF_RSD_SHIFT) \
+ & EASRC_IRQF_RSD_MASK)
#define EASRC_IRQF_OER_SHIFT 4
#define EASRC_IRQF_OER_WIDTH 4
-#define EASRC_IRQF_OER_MASK ((BIT(EASRC_ISF_OER_WIDTH) - 1) \
- << EASRC_ISF_OER_SHIFT)
-#define EASRC_IRQF_OER(v) (((v) << EASRC_ISF_OER_SHIFT) \
- & EASRC_ISF_OER_MASK)
+#define EASRC_IRQF_OER_MASK ((BIT(EASRC_IRQF_OER_WIDTH) - 1) \
+ << EASRC_IRQF_OER_SHIFT)
+#define EASRC_IRQF_OER(v) (((v) << EASRC_IRQF_OER_SHIFT) \
+ & EASRC_IRQF_OER_MASK)
#define EASRC_IRQF_IFO_SHIFT 0
#define EASRC_IRQF_IFO_WIDTH 4
-#define EASRC_IRQF_IFO_MASK ((BIT(EASRC_ISF_IFO_WIDTH) - 1) \
- << EASRC_ISF_IFO_SHIFT)
-#define EASRC_IRQF_IFO(v) (((v) << EASRC_ISF_IFO_SHIFT) \
- & EASRC_ISF_IFO_MASK)
+#define EASRC_IRQF_IFO_MASK ((BIT(EASRC_IRQF_IFO_WIDTH) - 1) \
+ << EASRC_IRQF_IFO_SHIFT)
+#define EASRC_IRQF_IFO(v) (((v) << EASRC_IRQF_IFO_SHIFT) \
+ & EASRC_IRQF_IFO_MASK)
/* ASRC Context Channel STAT */
#define EASRC_CSx_CSx_SHIFT 0