summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2019-09-17 13:29:17 +0800
committerShengjiu Wang <shengjiu.wang@nxp.com>2019-09-18 17:40:06 +0800
commit7b44c3c653acf078b6477fbc0393f88708ccb24c (patch)
treefc7a09476a1daf5c3c17ce0a9467efebc4e2772f /sound
parente86924ba7b54947a64b2cd3cba73cd6a4e5df6c1 (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>
Diffstat (limited to 'sound')
-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 a97ff44a9046..44ded1cddf6b 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 289a98c374d1..7ed04ea5755c 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