summaryrefslogtreecommitdiff
authorhualing chen <hualing.chen@amlogic.com>2020-04-28 11:08:50 (GMT)
committer Zhi Zhou <zhi.zhou@amlogic.com>2020-04-30 03:02:27 (GMT)
commitf9d4e3253932450c688e739db7394f9b9d083394 (patch)
tree2bc11c7878773431c82a1925cf825872930debba
parent6d5f19368e24dc658977b8ef06af3243735edbb8 (diff)
downloadmedia_modules-f9d4e3253932450c688e739db7394f9b9d083394.zip
media_modules-f9d4e3253932450c688e739db7394f9b9d083394.tar.gz
media_modules-f9d4e3253932450c688e739db7394f9b9d083394.tar.bz2
dmx: PVR video playback appears stutter sometimes. [1/1]
PD#SWPL-25042 Problem: switch channel when recording, PVR video playback appears stutter sometimes. Solution: 1. check dmx source when set dmx source. 2. check stb source when set stb source. 3. check async fifo info when set reg. Verify: verified on 215. Change-Id: I529fcfba536e2d0010cb4022517bd0f9fe637f0c Signed-off-by: hualing chen <hualing.chen@amlogic.com>
Diffstat
-rw-r--r--drivers/stream_input/parser/hw_demux/aml_dmx.c150
-rw-r--r--drivers/stream_input/parser/hw_demux/aml_dvb.c104
2 files changed, 188 insertions, 66 deletions
diff --git a/drivers/stream_input/parser/hw_demux/aml_dmx.c b/drivers/stream_input/parser/hw_demux/aml_dmx.c
index ef4725d..2be1515 100644
--- a/drivers/stream_input/parser/hw_demux/aml_dmx.c
+++ b/drivers/stream_input/parser/hw_demux/aml_dmx.c
@@ -176,6 +176,7 @@ module_param(use_of_sop, int, 0644);
#define CIPLUS_CONFIG 0x16fd
#define CIPLUS_ENDIAN 0x16fe*/
+
static u32 old_stb_top_config;
static u32 old_fec_input_control;
static int have_old_stb_top_config = 1;
@@ -519,28 +520,28 @@ static void section_buffer_watchdog_func(unsigned long arg)
/* bit 0 -- om_cmd_pending(read) */
/* bit 0 -- om_cmd_read_finished(write) */
/*BUG: If the recoder is running, return */
- if (dmx->record)
- goto end;
- /* OM status is wrong */
- dmx->om_status_error_count++;
- pr_dbg("demux om status \n"
- "%04x\t%03x\t%03x\t%03x\t%01x\t%01x\t"
- "%x\t%x\tdmx%d:status:0x%xerr_cnt:%d-%d\n",
- (om_cmd_status32 >> 12) & 0xf,
- (om_cmd_status32 >> 9) & 0x7,
- (om_cmd_status32 >> 6) & 0x7,
- (om_cmd_status32 >> 3) & 0x7,
- (om_cmd_status32 >> 2) & 0x1,
- (om_cmd_status32 >> 1) & 0x1,
- demux_channel_activity32, section_busy32,
- dmx->id, om_cmd_status32, dmx->om_status_error_count, enable_sec_monitor);
- if (enable_sec_monitor &&
- dmx->om_status_error_count > enable_sec_monitor) {
- /*Reset the demux */
- dmx_reset_dmx_hw_ex_unlock(dvb, dmx, 0);
- /* Reset the error count */
- dmx->om_status_error_count = 0;
- goto end;
+ if (!dmx->record) {
+ /* OM status is wrong */
+ dmx->om_status_error_count++;
+ pr_dbg("demux om status \n"
+ "%04x\t%03x\t%03x\t%03x\t%01x\t%01x\t"
+ "%x\t%x\tdmx%d:status:0x%xerr_cnt:%d-%d\n",
+ (om_cmd_status32 >> 12) & 0xf,
+ (om_cmd_status32 >> 9) & 0x7,
+ (om_cmd_status32 >> 6) & 0x7,
+ (om_cmd_status32 >> 3) & 0x7,
+ (om_cmd_status32 >> 2) & 0x1,
+ (om_cmd_status32 >> 1) & 0x1,
+ demux_channel_activity32, section_busy32,
+ dmx->id, om_cmd_status32, dmx->om_status_error_count, enable_sec_monitor);
+ if (enable_sec_monitor &&
+ dmx->om_status_error_count > enable_sec_monitor) {
+ /*Reset the demux */
+ dmx_reset_dmx_hw_ex_unlock(dvb, dmx, 0);
+ /* Reset the error count */
+ dmx->om_status_error_count = 0;
+ goto end;
+ }
}
} else {
/* OM status is correct, reset the error count */
@@ -3033,6 +3034,7 @@ static int dmx_get_record_flag(struct aml_dmx *dmx)
for (i = 0; i < CHANNEL_COUNT; i++) {
if (dmx->channel[i].used && dmx->channel[i].dvr_feed) {
if (!dmx->record) {
+ pr_error("dmx_get_record_flag set record dmx->id: %d\n", dmx->id);
dmx->record = 1;
if (linked) {
@@ -3050,6 +3052,7 @@ static int dmx_get_record_flag(struct aml_dmx *dmx)
}
if (dmx->record) {
+ pr_error("dmx_get_record_flag clear record dmx->id: %d\n", dmx->id);
dmx->record = 0;
if (linked) {
/*A record will stop, reset the async fifos
@@ -3704,6 +3707,25 @@ static void async_fifo_set_regs(struct aml_asyncfifo *afifo, int source_val)
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;
+
+ 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);
+
+ 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;
+ 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))
+ return;
+
pr_error("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);
@@ -3774,25 +3796,6 @@ static void reset_async_fifos(struct aml_dvb *dvb)
int i, j;
int record_enable;
- pr_dbg("reset ASYNC FIFOs\n");
- for (i = 0; i < dvb->async_fifo_total_count; i++) {
- if (!dvb->asyncfifo[i].init)
- continue;
- pr_dbg("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)) {
- pr_dbg("Set reg failed\n");
- } else
- pr_dbg("Set reg ok\n");
- dvb->asyncfifo[i].buf_toggle = 0;
- dvb->asyncfifo[i].buf_read = 0;
- }
for (j = 0; j < DMX_DEV_COUNT; j++) {
if (!dvb->dmx[j].init)
@@ -3836,22 +3839,51 @@ static void reset_async_fifos(struct aml_dvb *dvb)
break;
}
}
- pr_dbg("Set DMX%d TS_RECORDER_ENABLE to %d\n", dvb->dmx[j].id,
+ pr_error("Set DMX%d TS_RECORDER_ENABLE to %d\n", dvb->dmx[j].id,
record_enable ? 1 : 0);
if (record_enable) {
- /*DMX_SET_REG_MASK(dvb->dmx[j].id,
- *DEMUX_CONTROL, 1<<TS_RECORDER_ENABLE);
- */
- DMX_WRITE_REG(dvb->dmx[j].id, DEMUX_CONTROL,
- 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));
+ }
} else {
- /*DMX_CLEAR_REG_MASK(dvb->dmx[j].id,
- *DEMUX_CONTROL, 1<<TS_ECORDER_ENABLE);
- */
- DMX_WRITE_REG(dvb->dmx[j].id, DEMUX_CONTROL,
- 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)));
+ }
+ }
+ }
+ pr_error("reset ASYNC FIFOs\n");
+ for (i = 0; i < dvb->async_fifo_total_count; i++) {
+ struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];
+ int old;
+
+ if (!dvb->asyncfifo[i].init)
+ continue;
+
+ 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);
+ 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)) {
+ pr_error("Set reg failed\n");
+ } else
+ pr_error("Set reg ok\n");
+ dvb->asyncfifo[i].buf_toggle = 0;
+ dvb->asyncfifo[i].buf_read = 0;
}
}
@@ -4050,9 +4082,7 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq)
if (filter->used)
dmx_set_filter_regs(dmx, n);
}
-
dmx_enable(&dvb->dmx[id]);
-
dmx_smallsec_set(&dmx->smallsec,
dmx->smallsec.enable,
dmx->smallsec.bufsize,
@@ -4118,7 +4148,7 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx,
dvb->dmx_watchdog_disable[dmx->id] = 1;
}
#endif
-
+ pr_error("dmx_reset_dmx_hw_ex_unlock into\n");
WRITE_MPEG_REG(RESET3_REGISTER,
(dmx->id) ? ((dmx->id ==
1) ? RESET_DEMUX1 : RESET_DEMUX2) :
@@ -4269,9 +4299,7 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx,
dmx->sec_cnt_match[n] = 0;
dmx->sec_cnt_crc_fail[n] = 0;
}
-
dmx_enable(dmx);
-
dmx_smallsec_set(&dmx->smallsec,
dmx->smallsec.enable,
dmx->smallsec.bufsize,
@@ -4330,7 +4358,6 @@ void dmx_reset_dmx_hw_ex(struct aml_dvb *dvb, struct aml_dmx *dmx,
int reset_irq)
{
unsigned long flags;
-
spin_lock_irqsave(&dvb->slock, flags);
dmx_reset_dmx_hw_ex_unlock(dvb, dmx, reset_irq);
spin_unlock_irqrestore(&dvb->slock, flags);
@@ -4506,7 +4533,6 @@ int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid)
set_debug_dmx_chanpids(dmx->id, id, pid);
dmx->chan_count++;
-
dmx_enable(dmx);
return id;
@@ -4531,7 +4557,6 @@ void dmx_free_chan(struct aml_dmx *dmx, int cid)
set_debug_dmx_chanpids(dmx->id, cid, -1);
dmx->chan_count--;
-
dmx_enable(dmx);
/*Special pes type channel, check its dvr feed */
@@ -4648,7 +4673,6 @@ static int sf_add_feed(struct aml_dmx *src_dmx, struct dvb_demux_feed *feed)
sf->user++;
debug_sf_user = sf->user;
-
dmx_enable(sf->dmx);
return 0;
diff --git a/drivers/stream_input/parser/hw_demux/aml_dvb.c b/drivers/stream_input/parser/hw_demux/aml_dvb.c
index cdc9b99..fd80a3e 100644
--- a/drivers/stream_input/parser/hw_demux/aml_dvb.c
+++ b/drivers/stream_input/parser/hw_demux/aml_dvb.c
@@ -806,13 +806,62 @@ static ssize_t stb_clear_av(struct class *class,
return size;
}
+static int stb_check_source(const char *buf)
+{
+ struct aml_dvb *dvb = &aml_dvb_device;
+ int ret = 0;
+ char *src;
+
+ switch (dvb->stb_source) {
+ case AM_TS_SRC_TS0:
+ case AM_TS_SRC_S_TS0:
+ src = "ts0";
+ break;
+ case AM_TS_SRC_TS1:
+ case AM_TS_SRC_S_TS1:
+ src = "ts1";
+ break;
+ case AM_TS_SRC_TS2:
+ case AM_TS_SRC_S_TS2:
+ src = "ts2";
+ break;
+ case AM_TS_SRC_TS3:
+ src = "ts3";
+ break;
+ case AM_TS_SRC_HIU:
+ src = "hiu";
+ break;
+ case AM_TS_SRC_HIU1:
+ src = "hiu1";
+ break;
+ case AM_TS_SRC_DMX0:
+ src = "dmx0";
+ break;
+ case AM_TS_SRC_DMX1:
+ src = "dmx1";
+ break;
+ case AM_TS_SRC_DMX2:
+ src = "dmx2";
+ break;
+ default:
+ src = "disable";
+ break;
+ }
+ pr_error("stb_check_source set buf:%s, src:%s\n", buf, src);
+ ret = strcmp(buf,src);
+ return ret;
+}
+
/*Set the STB input source*/
static ssize_t stb_store_source(struct class *class,
struct class_attribute *attr, const char *buf,
size_t size)
{
dmx_source_t src = -1;
-
+ if (stb_check_source(buf) == 0) {
+ pr_error("stb_store_source same source \n");
+ return size;
+ }
if (!strncmp("ts0", buf, 3))
src = DMX_SOURCE_FRONT0;
else if (!strncmp("ts1", buf, 3))
@@ -833,7 +882,6 @@ static ssize_t stb_store_source(struct class *class,
src = DMX_SOURCE_FRONT2 + 100;
if (src != -1)
aml_stb_hw_set_source(&aml_dvb_device, src);
-
return size;
}
@@ -1050,6 +1098,53 @@ static ssize_t demux##i##_show_pcr(struct class *class, \
return sprintf(buf, "%08x\n", f);\
}
+static int dmx_check_source(int i, const char *buf)
+{
+ struct aml_dvb *dvb = &aml_dvb_device;
+ struct aml_dmx *dmx = &dvb->dmx[i];
+ ssize_t ret = 0;
+ char *src;
+ switch (dmx->source) {
+ case AM_TS_SRC_TS0:
+ case AM_TS_SRC_S_TS0:
+ src = "ts0";
+ break;
+ case AM_TS_SRC_TS1:
+ case AM_TS_SRC_S_TS1:
+ src = "ts1";
+ break;
+ case AM_TS_SRC_TS2:
+ case AM_TS_SRC_S_TS2:
+ src = "ts2";
+ break;
+ case AM_TS_SRC_TS3:
+ src = "ts3";
+ break;
+ case AM_TS_SRC_DMX0:
+ src = "dmx0";
+ break;
+ case AM_TS_SRC_DMX1:
+ src = "dmx1";
+ break;
+ case AM_TS_SRC_DMX2:
+ src = "dmx2";
+ break;
+ case AM_TS_SRC_HIU:
+ src = "hiu";
+ break;
+ case AM_TS_SRC_HIU1:
+ src = "hiu1";
+ break;
+ default :
+ src = "";
+ break;
+ }
+ pr_error("dmx_check_source:set[%s]src[%s]dmx[%d]dmx->source:%d\n", buf, src, i, dmx->source);
+ ret = strcmp(buf, src);
+ return ret;
+}
+
+
/*Show the STB input source*/
#define DEMUX_SOURCE_FUNC_DECL(i) \
static ssize_t demux##i##_show_source(struct class *class, \
@@ -1101,7 +1196,10 @@ static ssize_t demux##i##_store_source(struct class *class, \
struct class_attribute *attr, const char *buf, size_t size)\
{\
dmx_source_t src = -1;\
- \
+ if (dmx_check_source(i, buf) == 0) {\
+ pr_error("dmx[%d] source is same [%s]\n", i, buf);\
+ return size;\
+ }\
if (!strncmp("ts0", buf, 3)) {\
src = DMX_SOURCE_FRONT0;\
} else if (!strncmp("ts1", buf, 3)) {\