mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
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 <shuai.li@amlogic.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user