vpp: lowlatency: add rdmd lowlatency line check [1/1]

PD#SWPL-204261

Problem:
display anomaly caused by frame over-field

Solution:
add rdmd lowlatency line check

Verify:
t5m

Change-Id: I14accc686b1c74160a4945d6fb5b1e1c331036f1
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
This commit is contained in:
Jian Cao
2025-02-26 13:19:29 +00:00
committed by gerrit autosubmit
parent f92ddcf1c2
commit ecbdb6bc60
8 changed files with 205 additions and 38 deletions
+5
View File
@@ -300,6 +300,11 @@ int _vsync_rdma_config(int rdma_type)
return 0;
}
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
if (rdma_type == EX_VSYNC_RDMA &&
is_video_process_in_thread() && vpp_low_latency_check())
return -2;
#endif
if (rdma_type == EX_VSYNC_RDMA) {
spin_lock_irqsave(&lock, flags);
force_rdma_config[rdma_type] = 1;
+1
View File
@@ -82,6 +82,7 @@ int is_in_vsync_isr_viu2(u8 cur_cpuid);
int is_in_vsync_isr_viu3(u8 cur_cpuid);
int is_video_process_in_thread(void);
bool get_lowlatency_mode(void);
int vpp_low_latency_check(void);
#ifdef CONFIG_AMLOGIC_LCD
#ifdef CONFIG_AMLOGIC_BL_LDIM
int is_in_ldim_vsync_isr(u8 cur_cpuid);
+1 -1
View File
@@ -2849,7 +2849,7 @@ u32 vlock_fsm_to_en_func(struct stvlock_sig_sts *pvlock,
(pvlock->output_hz != 100) && (pvlock->output_hz != 120))
pvlock->phlock_percent = 25;
else if (vlock_input_hz == 60 || vlock_input_hz == 120)
pvlock->phlock_percent = 30;
pvlock->phlock_percent = 50;
else
pvlock->phlock_percent = 40;
+2 -1
View File
@@ -1124,7 +1124,8 @@ static void frc_drv_initial(struct frc_dev_s *devp)
fw_data->holdline_parm.reg_post_dly_vofst = 0;/*fixed*/
fw_data->holdline_parm.reg_mc_dly_vofst0 = 1;/*fixed*/
fw_data->frc_top_type.motion_ctrl = RD_MOTION_BY_VPU_ISR;
fw_data->frc_top_type.motion_ctrl = is_video_process_in_thread() ?
RD_MOTION_BY_INP_ISR : RD_MOTION_BY_VPU_ISR; //vpp low latency need frc inp isr
for (i = 0; i < RD_REG_MAX; i++)
fw_data->reg_val[i].addr = 0x0;
if (fw_data->frc_top_type.chip != 0)
+3 -1
View File
@@ -143,8 +143,9 @@
// frc_20241016 frc disable when vsize change
// frc_20241023 fix absolute value operation on unsigned int
// frc_20241022 frc add std flow
// frc_2024-1104 frc coverity
#define FRC_FW_VER "2024-1104 frc coverity"
#define FRC_FW_VER "2024-1108 frc add vpp low latency support"
#define FRC_KERDRV_VER 3500
#define FRC_DEVNO 1
@@ -867,4 +868,5 @@ int frc_buf_set(struct frc_dev_s *frc_devp);
void set_vsync_2to1_mode(u8 enable);
void set_pre_vsync_mode(u8 enable);
struct frc_fw_data_s *get_fw_data(void);
int is_video_process_in_thread(void);
#endif
+49
View File
@@ -689,6 +689,8 @@ atomic_t video_prevsync_inirq_flag = ATOMIC_INIT(0);
atomic_t video_pause_flag = ATOMIC_INIT(0);
atomic_t video_proc_lock = ATOMIC_INIT(0);
atomic_t video_recv_cnt = ATOMIC_INIT(0);
atomic_t video_llm_wake = ATOMIC_INIT(1);
atomic_t video_llm_done = ATOMIC_INIT(1);
int trickmode_duration;
int trickmode_duration_count;
u32 trickmode_vpts;
@@ -5462,6 +5464,7 @@ static irqreturn_t vsync_isr(int irq, void *dev_id)
lowlatency_overrun_recovery_cnt++;
vsync_cnt[VPP0]++;
}
atomic_set(&video_llm_wake, 1);
return IRQ_HANDLED;
}
@@ -13739,6 +13742,48 @@ static ssize_t lowlatency_en_store(const struct class *cla,
return count;
}
static ssize_t lowlatency_debug_show(const struct class *cla,
const struct class_attribute *attr,
char *buf)
{
ssize_t len = 0;
u32 p0 = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0, p5 = 0;
get_low_latency_params(&p0, &p1, &p2, &p3, &p4, &p5);
len += sprintf(buf + len,
"frame_line_threshold: %d\n", p0);
len += sprintf(buf + len,
"rdma_line_threshold: %d\n", p1);
len += sprintf(buf + len,
"rdma_check_min_line: %d\n", p2);
len += sprintf(buf + len,
"rdma_check_max_line: %d\n", p3);
len += sprintf(buf + len,
"rdma_add_delay_ms: %d\n", p4);
len += sprintf(buf + len,
"only_vpp_wake: %d\n", p5);
return len;
}
static ssize_t lowlatency_debug_store(const struct class *cla,
const struct class_attribute *attr,
const char *buf, size_t count)
{
int p[6];
if (likely(parse_para(buf, 6, p) == 6)) {
/* default values: 10 7 0 0 0 0 */
set_low_latency_params(p[0], p[1], p[2], p[3], p[4], p[5]);
} else {
pr_err("invalid parameter\n");
return -EINVAL;
}
return count;
}
static struct class_attribute amvideo_class_attrs[] = {
__ATTR(axis,
0664,
@@ -14376,6 +14421,10 @@ static struct class_attribute amvideo_class_attrs[] = {
0664,
lowlatency_en_show,
lowlatency_en_store),
__ATTR(lowlatency_debug,
0664,
lowlatency_debug_show,
lowlatency_debug_store),
};
static struct class_attribute amvideo_poll_class_attrs[] = {
+139 -35
View File
@@ -82,13 +82,17 @@ static u32 lowlatency_proc_done;
static u32 lowlatency_overflow_cnt;
static u32 lowlatency_overrun_cnt;
u32 lowlatency_overrun_recovery_cnt;
static u32 lowlatency_max_proc_lines;
static int lowlatency_max_proc_lines;
static u32 lowlatency_max_enter_lines;
static u32 lowlatency_max_exit_lines;
static u32 lowlatency_min_enter_lines = 0xffffffff;
static u32 lowlatency_min_exit_lines = 0xffffffff;
static u32 lowlatency_rdma_proc_drop;
static u32 lowlatency_rdma_err_drop;
static u32 lowlatency_rdma_err2_drop;
static u32 vsync_proc_done;
static u32 line_threshold = 10;
u32 frame_line_threshold = 10; /* n/100 */
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
static bool first_irq = true;
#endif
@@ -108,6 +112,13 @@ static const struct vinfo_s *vinfo;
static unsigned int low_latency_ver;
static u32 lowlatency_enable;
u32 rdma_check_min_line, rdma_check_max_line;
u32 rdma_line_threshold = 7; /* n/1000 */
u32 rdma_add_delay_ms;
u32 only_vpp_wake;
static DEFINE_SPINLOCK(video_llm_lock);
void get_low_latency_info(u32 *enable, u32 *version)
{
if (!enable || !version) {
@@ -129,6 +140,28 @@ int get_low_latency_version(void)
return lowlatency_enable ? low_latency_ver : 0;
}
void get_low_latency_params(u32 *p0, u32 *p1, u32 *p2, u32 *p3, u32 *p4, u32 *p5)
{
if (p0 && p1 && p2 && p3 && p4 && p5) {
*p0 = frame_line_threshold;
*p1 = rdma_line_threshold;
*p2 = rdma_check_min_line;
*p3 = rdma_check_max_line;
*p4 = rdma_add_delay_ms;
*p5 = only_vpp_wake;
}
}
void set_low_latency_params(u32 p0, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5)
{
frame_line_threshold = p0;
rdma_line_threshold = p1;
rdma_check_min_line = p2;
rdma_check_max_line = p3;
rdma_add_delay_ms = p4;
only_vpp_wake = p5;
}
u32 vsync_proc_drop;
ulong lowlatency_vsync_count;
bool overrun_flag;
@@ -1794,8 +1827,8 @@ int proc_lowlatency_frame(u8 instance_id)
vinfo_height = cur_vinfo->height;
start_line = get_active_start_line();
min_line = (vinfo_height * line_threshold) / 100 + start_line;
max_line = (vinfo_height * (100 - line_threshold)) / 100 + start_line;
min_line = (vinfo_height * frame_line_threshold) / 100 + start_line;
max_line = (vinfo_height * (100 - frame_line_threshold)) / 100 + start_line;
enc_line1 = get_cur_enc_line();
if (enc_line1 >= max_line || overrun_flag) {
lowlatency_proc_drop++;
@@ -1915,7 +1948,17 @@ ssize_t lowlatency_states_show(const struct class *cla,
atomic_read(&video_recv_cnt));
len += sprintf(buf + len,
"line threshold %d\n",
line_threshold);
frame_line_threshold);
len += sprintf(buf + len,
"rdma proc drop %llu\n",
(unsigned long long)lowlatency_rdma_proc_drop);
len += sprintf(buf + len,
"rdma err drop %llu\n",
(unsigned long long)lowlatency_rdma_err_drop);
len += sprintf(buf + len,
"rdma err2 drop %llu\n",
(unsigned long long)lowlatency_rdma_err2_drop);
return len;
}
@@ -1945,6 +1988,9 @@ ssize_t lowlatency_states_store(const struct class *cla,
lowlatency_skip_frame_cnt = 0;
vsync_proc_drop = 0;
vsync_proc_done = 0;
lowlatency_rdma_proc_drop = 0;
lowlatency_rdma_err_drop = 0;
lowlatency_rdma_err2_drop = 0;
pr_info("Clear the lowlatency states information!\n");
return count;
}
@@ -1954,25 +2000,96 @@ static int line_n_in;
static struct task_struct *video_thread;
static wait_queue_head_t frame_process_wq;
static bool video_thread_init_done;
static int wake_flag;
void vpp_lowlatency_wakeup(void)
{
u32 enc_line;
if (only_vpp_wake && !wake_flag)
return;
if (get_low_latency_version() != 2 || !video_thread_init_done)
return;
spin_lock(&video_llm_lock);
if (!atomic_read(&video_llm_wake) || !atomic_read(&video_llm_done)) {
spin_unlock(&video_llm_lock);
return;
}
atomic_set(&video_llm_wake, 0);
atomic_set(&video_llm_done, 0);
spin_unlock(&video_llm_lock);
line_n_in = 1;
wake_up_interruptible(&frame_process_wq);
enc_line = get_cur_enc_line();
if (debug_flag & DEBUG_FLAG_LATENCY)
pr_info("%s, wakeup enc_line:%d wake_flag:%d\n", __func__,
enc_line, wake_flag);
}
static irqreturn_t line_n_isr(int irq, void *dev_id)
{
if (get_low_latency_version() == 2) {
if (debug_flag & DEBUG_FLAG_LATENCY)
pr_info("line_n isr\n");
line_n_in = 1;
if (video_thread_init_done)
wake_up_interruptible(&frame_process_wq);
}
wake_flag = 1;
vpp_lowlatency_wakeup();
wake_flag = 0;
return IRQ_HANDLED;
}
int vpp_low_latency_check(void)
{
u32 enc_line, min_line, max_line, start_line, vinfo_height;
const struct vinfo_s *cur_vinfo;
static ulong last_vsync_count;
if (get_low_latency_version() != 2)
return 0;
cur_vinfo = get_current_vinfo();
if (!cur_vinfo) {
lowlatency_rdma_proc_drop++;
return -1;
}
if (cur_vinfo->field_height != cur_vinfo->height)
vinfo_height = cur_vinfo->field_height;
else
vinfo_height = cur_vinfo->height;
// check line count and configure only within the threshold range.
start_line = get_active_start_line();
min_line = 0;
max_line = (vinfo_height * (1000 - rdma_line_threshold)) / 1000 + 1 + start_line;
if (rdma_check_min_line)
min_line = rdma_check_min_line;
if (rdma_check_max_line)
max_line = rdma_check_max_line;
enc_line = get_cur_enc_line();
if (enc_line < min_line || enc_line > max_line) {
if (debug_flag & DEBUG_FLAG_LATENCY)
pr_info("%s enc_line:%d min_line:%d max_line:%d\n",
__func__, enc_line, min_line, max_line);
lowlatency_rdma_err_drop++;
return -1;
}
// avoid repeated configuration within the same vsync.
if (last_vsync_count == lowlatency_vsync_count) {
lowlatency_rdma_err2_drop++;
return -2;
}
last_vsync_count = lowlatency_vsync_count;
return 0;
}
static int process_frame(void)
{
u32 enc_line1, enc_line2, last_line;
u32 min_line, max_line, start_line, vinfo_height;
int enc_line1, enc_line2;
int max_line, start_line, vinfo_height;
const struct vinfo_s *cur_vinfo;
bool err_flag = false;
static ulong last_vsync_count;
if (legacy_vpp)
@@ -1989,12 +2106,15 @@ static int process_frame(void)
else
vinfo_height = cur_vinfo->height;
if (rdma_add_delay_ms)
mdelay(rdma_add_delay_ms);
start_line = get_active_start_line();
min_line = (vinfo_height * line_threshold) / 100 + start_line;
max_line = (vinfo_height * (100 - line_threshold)) / 100 + start_line;
max_line = (vinfo_height * (100 - frame_line_threshold)) / 100 + start_line;
enc_line1 = get_cur_enc_line();
if (debug_flag & DEBUG_FLAG_LATENCY)
pr_info("process frame start, line:%d\n", enc_line1);
pr_info("process frame start, line:%d start_line:%d max_line:%d\n",
enc_line1, start_line, max_line);
if (enc_line1 >= max_line || overrun_flag) {
lowlatency_proc_drop++;
@@ -2013,23 +2133,6 @@ static int process_frame(void)
return -4;
}
last_line = enc_line1;
while (enc_line1 < min_line) {
usleep_range(500, 600);
enc_line1 = get_cur_enc_line();
if (last_line == enc_line1) {
/* active line no change */
err_flag = true;
break;
}
last_line = enc_line1;
}
if (err_flag) {
lowlatency_err_drop++;
atomic_dec(&video_proc_lock);
return -5;
}
atomic_set(&video_inirq_flag, 1);
enc_line1 = get_cur_enc_line();
@@ -2081,6 +2184,7 @@ static int threadfunc(void *data)
start_time = ktime_get();
ret = process_frame();
atomic_set(&video_llm_done, 1);
diff_time = ktime_sub(ktime_get(), start_time);
time_cost_ms = ktime_to_ms(diff_time);
time_cost_us = ktime_to_us(diff_time);
@@ -44,6 +44,9 @@ extern bool over_field;
extern bool dvel_status;
#endif
extern atomic_t video_llm_wake;
extern atomic_t video_llm_done;
ssize_t lowlatency_states_store(const struct class *cla,
const struct class_attribute *attr,
const char *buf, size_t count);
@@ -62,6 +65,8 @@ void vf_pq_process(struct vframe_s *vf,
void get_low_latency_info(u32 *enable, u32 *version);
void set_low_latency_info(u32 enable, u32 version);
int get_low_latency_version(void);
void get_low_latency_params(u32 *p0, u32 *p1, u32 *p2, u32 *p3, u32 *p4, u32 *p5);
void set_low_latency_params(u32 p0, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5);
void video_lowlatency_init(struct platform_device *pdev);
void video_lowlatency_exit(void);
void video_lowlatency_line_n_num(void);