vdin: sync vdin0 & vdin1 buffer for afbc mode to avoid garbage screen [1/1]

PD#SWPL-3431

Problem:
enter hdmi 4k port will flash garbage screen with afbc mode

Solution:
sync vdin0 & vdin1 buffer for afbc mode

Verify:
x301

Change-Id: I443a9be2ed619a5cd2b6229f15814d8b856c5535
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2019-03-27 11:19:21 +08:00
committed by Tao Zeng
parent 6b0dd621b8
commit 3cb951733a
3 changed files with 254 additions and 43 deletions

View File

@@ -850,8 +850,11 @@ static void vdin_dump_state(struct vdin_dev_s *devp)
i, devp->afbce_info->fm_body_paddr[i],
devp->afbce_info->frame_body_size);
}
if (is_meson_tl1_cpu()) {
pr_info("tl1 preview flag = %d\n",
tl1_vdin1_preview_flag);
}
}
pr_info("tl1 preview flag = %d\n", tl1_vdin1_preview_flag);
pr_info("Vdin driver version : %s\n", VDIN_VER);
}
@@ -2120,6 +2123,43 @@ start_chk:
} else if (parm[1] != NULL) {
vdin_dump_one_afbce_mem(parm[1], devp, 0);
}
} else if (!strcmp(parm[0], "skip_frame_debug")) {
if (parm[1] != NULL) {
if (kstrtouint(parm[1], 10, &skip_frame_debug) == 0)
pr_info("set skip_frame_debug: %d\n",
skip_frame_debug);
} else {
pr_info("skip_frame_debug: %d\n", skip_frame_debug);
}
} else if (!strcmp(parm[0], "afbc_preview_drop_cnt")) {
if (parm[1] != NULL) {
if (kstrtouint(parm[1], 10,
&vdin_afbc_preview_force_drop_frame_cnt) == 0)
pr_info("set vdin_afbc_preview_force_drop_frame_cnt: %d\n",
vdin_afbc_preview_force_drop_frame_cnt);
} else {
pr_info("vdin_afbc_preview_force_drop_frame_cnt: %d\n",
vdin_afbc_preview_force_drop_frame_cnt);
}
} else if (!strcmp(parm[0], "afbc_drop_cnt")) {
if (parm[1] != NULL) {
if (kstrtouint(parm[1], 10,
&vdin_afbc_force_drop_frame_cnt) == 0)
pr_info("set vdin_afbc_force_drop_frame_cnt: %d\n",
vdin_afbc_force_drop_frame_cnt);
} else {
pr_info("vdin_afbc_force_drop_frame_cnt: %d\n",
vdin_afbc_force_drop_frame_cnt);
}
} else if (!strcmp(parm[0], "max_ignore_cnt")) {
if (parm[1] != NULL) {
if (kstrtouint(parm[1], 10, &max_ignore_frame_cnt) == 0)
pr_info("set max_ignore_frame_cnt: %d\n",
max_ignore_frame_cnt);
} else {
pr_info("max_ignore_frame_cnt: %d\n",
max_ignore_frame_cnt);
}
} else {
pr_info("unknown command\n");
}

View File

@@ -96,12 +96,22 @@ spinlock_t tl1_preview_lock;
static int canvas_config_mode = 2;
static bool work_mode_simple;
static int phase_lock_flag;
static int max_ignore_frames[2] = {2, 2};
static int max_ignore_frames[2] = {2, 1};
/*game_mode_switch_frames:min num is 5 by 1080p60hz input test*/
static int game_mode_switch_frames = 10;
static int game_mode_phlock_switch_frames = 60;
static int ignore_frames[2] = {0, 0};
static unsigned int dv_work_delby;
static int tl1_vdin1_preview_ready_flag;
static unsigned int vdin_afbc_force_drop_frame = 1;
static struct vf_entry *vfe_drop_force;
unsigned int vdin_afbc_preview_force_drop_frame_cnt = 1;
unsigned int vdin_afbc_force_drop_frame_cnt = 2;
unsigned int max_ignore_frame_cnt = 2;
unsigned int skip_frame_debug;
/* viu isr select:
* enable viu_hw_irq for the bandwidth is enough on gxbb/gxtvbb and laters ic
*/
@@ -115,18 +125,12 @@ MODULE_PARM_DESC(canvas_config_mode, "canvas configure mode");
module_param(work_mode_simple, bool, 0664);
MODULE_PARM_DESC(work_mode_simple, "enable/disable simple work mode");
//module_param(max_ignore_frames, int, 0664);
//MODULE_PARM_DESC(max_ignore_frames, "ignore first <n> frames");
//module_param(ignore_frames, int, 0664);
//MODULE_PARM_DESC(ignore_frames, "ignore first <n> frames");
module_param(viu_hw_irq, bool, 0664);
MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq");
module_param(dv_work_delby, uint, 0664);
MODULE_PARM_DESC(dv_work_delby, "dv_work_delby");
module_param(viu_hw_irq, bool, 0664);
MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq");
module_param(game_mode_switch_frames, int, 0664);
MODULE_PARM_DESC(game_mode_switch_frames, "game mode switch <n> frames");
@@ -213,13 +217,18 @@ int vdin_open_fe(enum tvin_port_e port, int index, struct vdin_dev_s *devp)
devp->frontend = fe;
devp->parm.port = port;
/* for atv snow function */
if ((port == TVIN_PORT_CVBS3) &&
(devp->parm.info.fmt == TVIN_SIG_FMT_NULL))
devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M;
else
devp->parm.info.fmt = TVIN_SIG_FMT_NULL;
devp->parm.info.status = TVIN_SIG_STATUS_NULL;
/* don't change parm.info for tl1_vdin1_preview,
* for it should follow vdin0 parm.info
*/
if (tl1_vdin1_preview_flag == 0) {
/* for atv snow function */
if ((port == TVIN_PORT_CVBS3) &&
(devp->parm.info.fmt == TVIN_SIG_FMT_NULL))
devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M;
else
devp->parm.info.fmt = TVIN_SIG_FMT_NULL;
devp->parm.info.status = TVIN_SIG_STATUS_NULL;
}
/* clear color para*/
memset(&devp->pre_prop, 0, sizeof(devp->pre_prop));
/* clear color para*/
@@ -665,10 +674,22 @@ void vdin_start_dec(struct vdin_dev_s *devp)
devp->index, jiffies_to_msecs(jiffies),
jiffies_to_msecs(jiffies)-devp->start_time);
if ((devp->afbce_mode == 1) && is_meson_tl1_cpu() &&
(devp->h_active >= 1920) && (devp->v_active >= 1080)) {
tl1_vdin1_preview_flag = 1;
max_ignore_frames[devp->index] = 9;
if ((devp->afbce_mode == 1) && is_meson_tl1_cpu()) {
if ((devp->h_active >= 1920) && (devp->v_active >= 1080)) {
tl1_vdin1_preview_flag = 1;
tl1_vdin1_data_readied = 0;
tl1_vdin1_preview_ready_flag = 0;
vdin_afbc_force_drop_frame =
vdin_afbc_preview_force_drop_frame_cnt;
pr_info("vdin.%d tl1_vdin1_preview state init\n",
devp->index);
} else {
tl1_vdin1_preview_flag = 0;
vdin_afbc_force_drop_frame =
vdin_afbc_force_drop_frame_cnt;
}
vfe_drop_force = NULL;
max_ignore_frames[devp->index] = max_ignore_frame_cnt;
}
}
@@ -695,7 +716,6 @@ void vdin_stop_dec(struct vdin_dev_s *devp)
#endif
disable_irq_nosync(devp->irq);
afbc_init_flag[devp->index] = 0;
max_ignore_frames[devp->index] = 2;
if (is_meson_tl1_cpu() && (devp->afbce_mode == 1)) {
while (++afbc_write_down_flag[devp->index] <
@@ -706,6 +726,10 @@ void vdin_stop_dec(struct vdin_dev_s *devp)
break;
}
}
if (is_meson_tl1_cpu() && (tl1_vdin1_preview_flag == 1)) {
if (devp->index == 1)
tl1_vdin1_preview_flag = 0;
}
if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) &&
devp->frontend->dec_ops &&
@@ -1316,6 +1340,47 @@ static void vdin_hist_tgt(struct vdin_dev_s *devp, struct vframe_s *vf)
spin_unlock_irqrestore(&devp->hist_lock, flags);
}
static bool vdin_skip_frame_check(struct vdin_dev_s *devp)
{
ulong flags = 0;
int skip_flag = 0;
spin_lock_irqsave(&tl1_preview_lock, flags);
if (devp->afbce_mode == 0) {
spin_unlock_irqrestore(&tl1_preview_lock, flags);
return false;
}
if (tl1_vdin1_preview_flag == 1) {
if (tl1_vdin1_preview_ready_flag == 0) {
skip_flag = 1;
} else {
if (vdin_afbc_force_drop_frame > 0) {
vdin_afbc_force_drop_frame--;
skip_flag = 1;
}
}
} else {
if (vdin_afbc_force_drop_frame > 0) {
vdin_afbc_force_drop_frame--;
skip_flag = 1;
}
}
if (skip_flag) {
vfe_drop_force = receiver_vf_get(devp->vfp);
if (vfe_drop_force)
receiver_vf_put(&vfe_drop_force->vf, devp->vfp);
else
pr_info("vdin.%d: skip vf get error\n", devp->index);
spin_unlock_irqrestore(&tl1_preview_lock, flags);
return true;
}
spin_unlock_irqrestore(&tl1_preview_lock, flags);
return false;
}
/*
*VDIN_FLAG_RDMA_ENABLE=1
* provider_vf_put(devp->last_wr_vfe, devp->vfp);
@@ -1354,6 +1419,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
if (!devp->frontend) {
devp->vdin_irq_flag = 1;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
goto irq_handled;
}
@@ -1395,6 +1464,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
vdin_hw_disable(offset);
devp->flags &= ~VDIN_FLAG_DEC_STOP_ISR;
devp->vdin_irq_flag = 2;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
goto irq_handled;
}
@@ -1406,8 +1479,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
/*save the first field stamp*/
devp->stamp = stamp;
devp->vdin_irq_flag = 3;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
goto irq_handled;
}
/* use RDMA and not game mode */
if (devp->last_wr_vfe && (devp->flags&VDIN_FLAG_RDMA_ENABLE) &&
!(devp->game_mode & VDIN_GAME_MODE_1) &&
!(devp->game_mode & VDIN_GAME_MODE_2)) {
@@ -1440,6 +1518,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
tl1_vdin1_height;
devp->last_wr_vfe->vf.width =
tl1_vdin1_width;
tl1_vdin1_preview_ready_flag = 1;
} else {
tl1_vdin1_preview_ready_flag = 0;
}
} else if ((devp->index == 1) &&
(tl1_vdin1_preview_flag == 1)) {
@@ -1461,6 +1542,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
}
} else {
devp->vdin_irq_flag = 15;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1480,17 +1565,34 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
vf_notify_receiver("dv_vdin",
VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
else
else {
#endif
vf_notify_receiver(devp->name,
if (vdin_skip_frame_check(devp)) {
devp->vdin_irq_flag = 16;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index,
devp->vdin_irq_flag);
}
vdin_drop_cnt++;
} else {
vf_notify_receiver(devp->name,
VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
NULL);
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
}
#endif
}
}
/*check vs is valid base on the time during continuous vs*/
if (vdin_check_cycle(devp) && (!(isr_flag & VDIN_BYPASS_CYC_CHECK))
&& (!(devp->flags & VDIN_FLAG_SNOW_FLAG))) {
devp->vdin_irq_flag = 4;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1516,6 +1618,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
(state != TVIN_SM_STATUS_STABLE)) &&
(!(devp->flags & VDIN_FLAG_SNOW_FLAG))) {
devp->vdin_irq_flag = 6;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1530,6 +1636,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
VIDTYPE_INTERLACE_BOTTOM)
) {
devp->vdin_irq_flag = 7;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1560,6 +1670,11 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
pre_prop->color_fmt_range = prop->color_fmt_range;
pre_prop->dest_cfmt = prop->dest_cfmt;
ignore_frames[devp->index] = 0;
devp->vdin_irq_flag = 20;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1585,6 +1700,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
decops = devp->frontend->dec_ops;
if (decops->decode_isr(devp->frontend, devp->hcnt64) == TVIN_BUF_SKIP) {
devp->vdin_irq_flag = 8;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1593,10 +1712,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
curr_wr_vf->phase = sm_ops->get_secam_phase(devp->frontend) ?
VFRAME_PHASE_DB : VFRAME_PHASE_DR;
if (ignore_frames[devp->index] < max_ignore_frames[devp->index]) {
ignore_frames[devp->index]++;
devp->vdin_irq_flag = 12;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
ignore_frames[devp->index]++;
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1604,6 +1726,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
if (sm_ops->check_frame_skip &&
sm_ops->check_frame_skip(devp->frontend)) {
devp->vdin_irq_flag = 13;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
if (devp->flags&VDIN_FLAG_RDMA_ENABLE)
ignore_frames[devp->index] = 0;
@@ -1622,6 +1748,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
devp->index);
} else {
devp->vdin_irq_flag = 14;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/
goto irq_handled;
@@ -1733,6 +1863,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
tl1_vdin1_height;
curr_wr_vfe->vf.width =
tl1_vdin1_width;
tl1_vdin1_preview_ready_flag = 1;
} else {
tl1_vdin1_preview_ready_flag = 0;
}
} else if ((devp->index == 1) &&
(tl1_vdin1_preview_flag == 1)) {
@@ -1755,6 +1888,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
}
} else {
devp->vdin_irq_flag = 15;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index, devp->vdin_irq_flag);
}
vdin_drop_cnt++;
goto irq_handled;
}
@@ -1770,8 +1907,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
phase_lock_flag++;
if (phase_lock_flag >= game_mode_phlock_switch_frames) {
if (vdin_dbg_en) {
pr_info(
"switch game mode (%d-->5), frame_cnt=%d\n",
pr_info("switch game mode (%d-->5), frame_cnt=%d\n",
devp->game_mode,
devp->frame_cnt);
}
@@ -1828,6 +1964,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) ||
(devp->game_mode & VDIN_GAME_MODE_1)) {
/* not RDMA, or game mode 1 */
if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) {
//if (vdin_dbg_en)
//pr_info("vdin1 preview dont notify receiver.\n");
@@ -1839,13 +1976,27 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
vf_notify_receiver("dv_vdin",
VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
else
else {
#endif
vf_notify_receiver(devp->name,
if (vdin_skip_frame_check(devp)) {
devp->vdin_irq_flag = 17;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index,
devp->vdin_irq_flag);
}
vdin_drop_cnt++;
} else {
vf_notify_receiver(devp->name,
VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
NULL);
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
}
#endif
}
} else if (devp->game_mode & VDIN_GAME_MODE_2) {
/* game mode 2 */
spin_lock_irqsave(&tl1_preview_lock, flags1);
if ((devp->index == 0) &&
(tl1_vdin1_preview_flag == 1)) {
@@ -1857,6 +2008,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
tl1_vdin1_height;
next_wr_vfe->vf.width =
tl1_vdin1_width;
tl1_vdin1_preview_ready_flag = 1;
} else {
tl1_vdin1_preview_ready_flag = 0;
}
} else if ((devp->index == 1) &&
(tl1_vdin1_preview_flag == 1)) {
@@ -1874,23 +2028,34 @@ irqreturn_t vdin_isr(int irq, void *dev_id)
//if (vdin_dbg_en)
//pr_info("vdin1 preview dont notify receiver.\n");
} else {
vf_notify_receiver(devp->name,
VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
if (vdin_dbg_en) {
next_wr_vfe->vf.ready_clock[1] =
sched_clock();
pr_info("vdin put latency %lld us.first %lld us\n",
if (vdin_skip_frame_check(devp)) {
devp->vdin_irq_flag = 18;
if (skip_frame_debug) {
pr_info("vdin.%d: vdin_irq_flag=%d\n",
devp->index,
devp->vdin_irq_flag);
}
vdin_drop_cnt++;
} else {
vf_notify_receiver(devp->name,
VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
if (vdin_dbg_en) {
next_wr_vfe->vf.ready_clock[1] =
sched_clock();
pr_info("vdin put latency %lld us.first %lld us\n",
func_div(next_wr_vfe->vf.ready_clock[1],
1000),
1000),
func_div(next_wr_vfe->vf.ready_clock[0],
1000));
1000));
}
}
}
}
devp->frame_cnt++;
irq_handled:
/*hdmi skip policy should adapt to all drop vframe case*/
/*hdmi skip policy should adapt to all drop front vframe case*/
if ((devp->vfp->skip_vf_num > 0) &&
(vf_drop_cnt < vdin_drop_cnt))
vdin_vf_disp_mode_skip(devp->vfp);
@@ -2391,8 +2556,9 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
devp_vdin1->unstable_flag = false;
devp_vdin1->parm.info.fmt = fmt;
devp_vdin1->parm.port = devp->parm.port;
devp_vdin1->parm.info.status = TVIN_SIG_STATUS_STABLE;
devp_vdin1->fmt_info_p = (struct tvin_format_s *)
tvin_get_fmt_info(fmt);
tvin_get_fmt_info(fmt);
if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) {
/*init queue*/
@@ -2429,7 +2595,8 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
(void *)devp_vdin1);
if (ret != 0) {
pr_info("tl1_vdin1_preview request irq error.\n");
return -1;
mutex_unlock(&devp_vdin1->fe_lock);
break;
}
devp_vdin1->flags |= VDIN_FLAG_ISR_REQ;
} else {

View File

@@ -364,6 +364,10 @@ struct vdin_v4l2_param_s {
};
extern unsigned int tl1_vdin1_preview_flag;
extern unsigned int vdin_afbc_preview_force_drop_frame_cnt;
extern unsigned int vdin_afbc_force_drop_frame_cnt;
extern unsigned int max_ignore_frame_cnt;
extern unsigned int skip_frame_debug;
extern struct vframe_provider_s *vf_get_provider_by_name(
const char *provider_name);