mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
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:
committed by
gerrit autosubmit
parent
f92ddcf1c2
commit
ecbdb6bc60
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user