From a424d39cf5cce6122940842d2e6ff45b08e74ac7 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Wed, 12 Jun 2019 16:13:45 +0800 Subject: [PATCH] audio: Fix audio stuck [1/1] PD#SWPL-9142 Problem: Audio stuck in stress test. Solution: Work around: Wait until the fifo stops and then stop toddr. Verify: Tl1. Change-Id: I8ce50732a7e23124b4b37374aa4505d79cd68cfe Signed-off-by: Shuai Li --- sound/soc/amlogic/auge/ddr_mngr.c | 39 ++++++++++++++++++++++++++++--- sound/soc/amlogic/auge/ddr_mngr.h | 4 ++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 67c6cec21b0b..71480b0e3d55 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -446,6 +446,11 @@ unsigned int aml_toddr_get_status(struct toddr *to) return aml_audiobus_read(actrl, reg); } +unsigned int aml_toddr_get_fifo_cnt(struct toddr *to) +{ + return (aml_toddr_get_status(to) & TODDR_FIFO_CNT) >> 8; +} + void aml_toddr_ack_irq(struct toddr *to, int status) { struct aml_audio_controller *actrl = to->actrl; @@ -529,6 +534,31 @@ bool aml_toddr_burst_finished(struct toddr *to) struct aml_audio_controller *actrl = to->actrl; unsigned int reg_base = to->reg_base; unsigned int reg; + bool fifo_stop = false; + + /* This is a SW workaround. + * If not wait until the fifo stops, + * DDR will stuck and could not recover unless reboot. + */ + for (i = 0; i < 10; i++) { + unsigned int cnt0, cnt1, cnt2; + + cnt0 = aml_toddr_get_fifo_cnt(to); + udelay(10); + cnt1 = aml_toddr_get_fifo_cnt(to); + udelay(10); + cnt2 = aml_toddr_get_fifo_cnt(to); + pr_debug("i: %d, fifo cnt:[%d] cnt1:[%d] cnt2:[%d]\n", + i, cnt0, cnt1, cnt2); + + /* fifo stopped */ + if ((cnt0 == cnt1) && (cnt0 == cnt2) && (cnt0 < (0x40 - 2))) { + pr_info("%s(), i (%d) cnt(%d) break out\n", + __func__, i, cnt2); + fifo_stop = true; + break; + } + } /* max 200us delay */ for (i = 0; i < 200; i++) { @@ -540,12 +570,15 @@ bool aml_toddr_burst_finished(struct toddr *to) aml_audiobus_update_bits(actrl, reg, 0xf << 8, 0x2 << 8); addr_reply = aml_toddr_get_position(to); - if (addr_request == addr_reply) + if (addr_request == addr_reply) { + pr_info("%s(), fifo_stop %d\n", __func__, fifo_stop); return true; + } udelay(1); - pr_debug("delay:[%dus]; FRDDR_STATUS2: [0x%x] [0x%x]\n", - i, addr_request, addr_reply); + if ((i % 20) == 0) + pr_info("delay:[%dus]; FRDDR_STATUS2: [0x%x] [0x%x]\n", + i, addr_request, addr_reply); } pr_err("Error: 200us time out, TODDR_STATUS2: [0x%x] [0x%x]\n", addr_request, addr_reply); diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index c3e9c7b263e1..5e0ddf5b3583 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -31,6 +31,9 @@ #define MEMIF_INT_FIFO_DEPTH BIT(5) #define MEMIF_INT_MASK GENMASK(7, 0) +#define TODDR_FIFO_CNT GENMASK(19, 8) +#define FRDDR_FIFO_CNT GENMASK(17, 8) + enum ddr_num { DDR_A, DDR_B, @@ -252,6 +255,7 @@ void aml_toddr_force_finish(struct toddr *to); void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt); unsigned int aml_toddr_get_status(struct toddr *to); +unsigned int aml_toddr_get_fifo_cnt(struct toddr *to); void aml_toddr_ack_irq(struct toddr *to, int status); void aml_toddr_insert_chanum(struct toddr *to);