summaryrefslogtreecommitdiff
authorZhiqiang Han <zhiqiang.han@amlogic.com>2020-06-17 06:08:37 (GMT)
committer Hui Zhang <hui.zhang@amlogic.com>2020-06-29 10:11:14 (GMT)
commitd5bd120ff2fd2bca8b226072db62c23ec1dcb836 (patch)
tree4924a88b19c91a0cda03600e07147ccd674174d5
parent198e96d658ae0c82cabe772d05dde5259ba4bdda (diff)
downloadmedia_modules-d5bd120ff2fd2bca8b226072db62c23ec1dcb836.zip
media_modules-d5bd120ff2fd2bca8b226072db62c23ec1dcb836.tar.gz
media_modules-d5bd120ff2fd2bca8b226072db62c23ec1dcb836.tar.bz2
asyncfifo: corrupted data found in recording [1/1]
PD#SWPL-27889 Problem: the starting of rec2 causes corrupted data in rec1. incorrect reg setting on a running asyncfifo Solution: the start reg is a status, not the value set before. Verify: Patchbuild Change-Id: I919e7286ef8c94c0a20b09c23080dc75bcdb0d13 Signed-off-by: Zhiqiang Han <zhiqiang.han@amlogic.com>
Diffstat
-rw-r--r--drivers/stream_input/parser/hw_demux/aml_dmx.c156
1 files changed, 95 insertions, 61 deletions
diff --git a/drivers/stream_input/parser/hw_demux/aml_dmx.c b/drivers/stream_input/parser/hw_demux/aml_dmx.c
index 331b7ac..f2e4351 100644
--- a/drivers/stream_input/parser/hw_demux/aml_dmx.c
+++ b/drivers/stream_input/parser/hw_demux/aml_dmx.c
@@ -3769,33 +3769,49 @@ static void dmx_clear_filter_buffer(struct aml_dmx *dmx, int fid)
static void async_fifo_set_regs(struct aml_asyncfifo *afifo, int source_val)
{
- u32 start_addr = (afifo->secure_enable && afifo->blk.addr) ? afifo->blk.addr :
- virt_to_phys((void *)afifo->pages);
+ u32 start_addr = (afifo->secure_enable && afifo->blk.addr)?
+ afifo->blk.addr : virt_to_phys((void *)afifo->pages);
u32 size = afifo->buf_len;
u32 flush_size = afifo->flush_size;
int factor = dmx_get_order(size / flush_size);
- u32 old_start_addr, old_size, new_size, old_factor, new_factor;
-
+ u32 old_size, new_size, old_factor, new_factor;
int old_src, old_en;
- old_en = READ_ASYNC_FIFO_REG(afifo->id, REG2) & (1 << ASYNC_FIFO_FILL_EN);
- old_src = (READ_ASYNC_FIFO_REG(afifo->id, REG2) >> ASYNC_FIFO_SOURCE_LSB) & 3;
-
- old_start_addr = READ_ASYNC_FIFO_REG(afifo->id, REG0);
+ old_en = READ_ASYNC_FIFO_REG(afifo->id, REG2)
+ & (1 << ASYNC_FIFO_FILL_EN);
+ old_src =
+ (READ_ASYNC_FIFO_REG(afifo->id, REG2) >> ASYNC_FIFO_SOURCE_LSB)
+ & 3;
new_size = (size >> 7) & 0x7fff;
- old_size = (READ_ASYNC_FIFO_REG(afifo->id, REG1) >> ASYNC_FIFO_FLUSH_CNT_LSB) & 0x7fff;
-
- old_factor = (READ_ASYNC_FIFO_REG(afifo->id, REG3) >> ASYNC_FLUSH_SIZE_IRQ_LSB) & 0x7fff;
+ old_size =
+ (READ_ASYNC_FIFO_REG(afifo->id, REG1)
+ >> ASYNC_FIFO_FLUSH_CNT_LSB)
+ & 0x7fff;
+
+ old_factor =
+ (READ_ASYNC_FIFO_REG(afifo->id, REG3)
+ >> ASYNC_FLUSH_SIZE_IRQ_LSB)
+ & 0x7fff;
new_factor = ((size >> (factor + 7)) - 1) & 0x7fff;
- pr_error("async_fifo_set_regs old_src=0x%x source_val=0x%x new_size=0x%x old_size=0x%x old_factor=0x%x new_factor=0x%x old_start_addr=0x%x start_addr=0x%x\n", old_src, source_val, new_size, old_size, old_factor , new_factor,old_start_addr, start_addr);
- if (old_en && (old_src == source_val) && (new_size == old_size) && (old_factor == new_factor) && (old_start_addr == start_addr))
+ pr_inf("AF(%d) [%s] src:0x%x->0x%x size:0x%x->0x%x factor:0x%x->0x%x\n",
+ afifo->id,
+ old_en? "on" : "off",
+ old_src, source_val,
+ old_size, new_size,
+ old_factor, new_factor);
+
+ if (old_en
+ && (old_src == source_val)
+ && (new_size == old_size)
+ && (old_factor == new_factor))
return;
- pr_error("ASYNC FIFO id=%d, link to DMX%d, start_addr %x, buf_size %d,"
+ pr_inf("ASYNC FIFO id=%d, link to DMX%d, start_addr %x, buf_size %d,"
"source value 0x%x, factor %d\n",
afifo->id, afifo->source, start_addr, size, source_val, factor);
+
/* Destination address */
WRITE_ASYNC_FIFO_REG(afifo->id, REG0, start_addr);
@@ -3872,61 +3888,73 @@ static void reset_async_fifos(struct aml_dvb *dvb)
if (!dvb->asyncfifo[i].init)
continue;
- if (dvb->dmx[j].record
- && dvb->dmx[j].id == dvb->asyncfifo[i].source) {
- /*This dmx is linked to the async fifo,
- *Enable the TS_RECORDER_ENABLE
- */
- record_enable = 1;
- if (!low_dmx_fifo) {
- low_dmx_fifo = &dvb->asyncfifo[i];
- } else if (low_dmx_fifo->source >
- dvb->asyncfifo[i].source) {
- if (!high_dmx_fifo)
- high_dmx_fifo = low_dmx_fifo;
- else {
- highest_dmx_fifo = high_dmx_fifo;
- high_dmx_fifo = low_dmx_fifo;
- }
- low_dmx_fifo = &dvb->asyncfifo[i];
- } else if (low_dmx_fifo->source <
- dvb->asyncfifo[i].source) {
- if (!high_dmx_fifo)
- high_dmx_fifo = &dvb->asyncfifo[i];
- else {
- if (high_dmx_fifo->source > dvb->asyncfifo[i].source) {
- highest_dmx_fifo = high_dmx_fifo;
- high_dmx_fifo = &dvb->asyncfifo[i];
- } else {
- highest_dmx_fifo = &dvb->asyncfifo[i];
- }
+ if (!dvb->dmx[j].record
+ || !(dvb->dmx[j].id == dvb->asyncfifo[i].source))
+ continue;
+
+ /*This dmx is linked to the async fifo,
+ *Enable the TS_RECORDER_ENABLE
+ */
+ record_enable = 1;
+ if (!low_dmx_fifo) {
+ low_dmx_fifo = &dvb->asyncfifo[i];
+ } else if (low_dmx_fifo->source >
+ dvb->asyncfifo[i].source) {
+ if (!high_dmx_fifo)
+ high_dmx_fifo = low_dmx_fifo;
+ else {
+ highest_dmx_fifo = high_dmx_fifo;
+ high_dmx_fifo = low_dmx_fifo;
+ }
+ low_dmx_fifo = &dvb->asyncfifo[i];
+ } else if (low_dmx_fifo->source <
+ dvb->asyncfifo[i].source) {
+ if (!high_dmx_fifo)
+ high_dmx_fifo = &dvb->asyncfifo[i];
+ else {
+ if (high_dmx_fifo->source >
+ dvb->asyncfifo[i].source) {
+ highest_dmx_fifo =
+ high_dmx_fifo;
+ high_dmx_fifo =
+ &dvb->asyncfifo[i];
+ } else {
+ highest_dmx_fifo =
+ &dvb->asyncfifo[i];
}
}
-
- break;
}
+ break;
}
- pr_error("Set DMX%d TS_RECORDER_ENABLE to %d\n", dvb->dmx[j].id,
- record_enable ? 1 : 0);
+
+ pr_inf("Set DMX%d TS_RECORDER_ENABLE to %d\n", dvb->dmx[j].id,
+ record_enable ? 1 : 0);
+
if (record_enable) {
- int old_en = DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL) & (1 << TS_RECORDER_ENABLE);
+ int old_en =
+ DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL)
+ & (1 << TS_RECORDER_ENABLE);
if (!old_en) {
DMX_WRITE_REG(dvb->dmx[j].id, DEMUX_CONTROL,
- DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL) |
- (1 << TS_RECORDER_ENABLE));
+ DMX_READ_REG(dvb->dmx[j].id,
+ DEMUX_CONTROL)
+ | (1 << TS_RECORDER_ENABLE));
}
} else {
- int old_en = DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL) & (1 << TS_RECORDER_ENABLE);
+ int old_en =
+ DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL)
+ & (1 << TS_RECORDER_ENABLE);
if (old_en) {
DMX_WRITE_REG(dvb->dmx[j].id, DEMUX_CONTROL,
- DMX_READ_REG(dvb->dmx[j].id, DEMUX_CONTROL) &
- (~(1 << TS_RECORDER_ENABLE)));
+ DMX_READ_REG(dvb->dmx[j].id,
+ DEMUX_CONTROL)
+ & (~(1 << TS_RECORDER_ENABLE)));
}
}
}
- pr_error("reset ASYNC FIFOs\n");
+ pr_inf("reset ASYNC FIFOs\n");
for (i = 0; i < dvb->async_fifo_total_count; i++) {
struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];
int old;
@@ -3934,21 +3962,27 @@ static void reset_async_fifos(struct aml_dvb *dvb)
if (!dvb->asyncfifo[i].init)
continue;
- old = READ_ASYNC_FIFO_REG(afifo->id, REG2) & (1 << ASYNC_FIFO_FILL_EN);
+ old = READ_ASYNC_FIFO_REG(afifo->id, REG2)
+ & (1 << ASYNC_FIFO_FILL_EN);
- if (old && (afifo != low_dmx_fifo) && (afifo != high_dmx_fifo) && (afifo != highest_dmx_fifo)) {
- pr_error("Disable ASYNC FIFO id=%d\n", dvb->asyncfifo[i].id);
+ if (old
+ && (afifo != low_dmx_fifo)
+ && (afifo != high_dmx_fifo)
+ && (afifo != highest_dmx_fifo)) {
+ pr_inf("Disable ASYNC FIFO id=%d\n",
+ dvb->asyncfifo[i].id);
CLEAR_ASYNC_FIFO_REG_MASK(dvb->asyncfifo[i].id, REG1,
1 << ASYNC_FIFO_FLUSH_EN);
CLEAR_ASYNC_FIFO_REG_MASK(dvb->asyncfifo[i].id, REG2,
1 << ASYNC_FIFO_FILL_EN);
- if (READ_ASYNC_FIFO_REG(dvb->asyncfifo[i].id, REG2) &
- (1 << ASYNC_FIFO_FILL_EN) ||
- READ_ASYNC_FIFO_REG(dvb->asyncfifo[i].id, REG1) &
- (1 << ASYNC_FIFO_FLUSH_EN)) {
+ if (READ_ASYNC_FIFO_REG(dvb->asyncfifo[i].id, REG2)
+ & (1 << ASYNC_FIFO_FILL_EN)
+ ||
+ READ_ASYNC_FIFO_REG(dvb->asyncfifo[i].id, REG1)
+ & (1 << ASYNC_FIFO_FLUSH_EN)) {
pr_error("Set reg failed\n");
} else
- pr_error("Set reg ok\n");
+ pr_inf("Set reg ok\n");
dvb->asyncfifo[i].buf_toggle = 0;
dvb->asyncfifo[i].buf_read = 0;
}