author | hualing 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) |
commit | f9d4e3253932450c688e739db7394f9b9d083394 (patch) | |
tree | 2bc11c7878773431c82a1925cf825872930debba | |
parent | 6d5f19368e24dc658977b8ef06af3243735edbb8 (diff) | |
download | media_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>
-rw-r--r-- | drivers/stream_input/parser/hw_demux/aml_dmx.c | 150 | ||||
-rw-r--r-- | drivers/stream_input/parser/hw_demux/aml_dvb.c | 104 |
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)) {\ |