Merge "disp: msm: sde: improve qsync trigger window accuracy"

This commit is contained in:
qctecmdr
2022-10-24 12:37:21 -07:00
zatwierdzone przez Gerrit - the friendly Code Review server
3 zmienionych plików z 73 dodań i 47 usunięć

Wyświetl plik

@@ -197,8 +197,8 @@ static void sde_encoder_override_tearcheck_rd_ptr(struct sde_encoder_phys *phys_
sde_encoder_helper_get_pp_line_count(phys_enc->parent, info);
SDE_EVT32_VERBOSE(phys_enc->hw_intf->idx - INTF_0, mode->vdisplay,
cmd_enc->qsync_threshold_lines, info[0].rd_ptr_line_count,
info[0].rd_ptr_frame_count, info[0].wr_ptr_line_count,
cmd_enc->qsync_threshold_lines, adjusted_tear_rd_ptr_line_cnt,
info[0].rd_ptr_line_count, info[0].rd_ptr_frame_count, info[0].wr_ptr_line_count,
info[1].rd_ptr_line_count, info[1].rd_ptr_frame_count, info[1].wr_ptr_line_count);
}
@@ -987,28 +987,34 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc)
struct drm_connector *conn = phys_enc->connector;
u32 qsync_mode;
struct drm_display_mode *mode;
u32 threshold_lines = DEFAULT_TEARCHECK_SYNC_THRESH_START;
u32 threshold_lines, adjusted_threshold_lines;
struct sde_encoder_phys_cmd *cmd_enc =
to_sde_encoder_phys_cmd(phys_enc);
struct sde_encoder_virt *sde_enc;
struct msm_mode_info *info;
if (!conn || !conn->state)
return 0;
sde_enc = to_sde_encoder_virt(phys_enc->parent);
info = &sde_enc->mode_info;
mode = &phys_enc->cached_mode;
qsync_mode = sde_connector_get_qsync_mode(conn);
threshold_lines = adjusted_threshold_lines = DEFAULT_TEARCHECK_SYNC_THRESH_START;
if (mode && (qsync_mode == SDE_RM_QSYNC_CONTINUOUS_MODE)) {
u32 qsync_min_fps = 0;
ktime_t qsync_time_ns;
ktime_t qsync_l_bound_ns, qsync_u_bound_ns;
u32 default_fps = drm_mode_vrefresh(mode);
ktime_t default_time_ns;
ktime_t default_line_time_ns;
ktime_t extra_time_ns;
u32 yres = mode->vtotal;
u32 slow_time_ns;
u32 default_time_ns;
u32 extra_time_ns;
u32 default_line_time_ns;
if (phys_enc->parent_ops.get_qsync_fps)
phys_enc->parent_ops.get_qsync_fps(
phys_enc->parent, &qsync_min_fps, conn->state);
phys_enc->parent_ops.get_qsync_fps(phys_enc->parent, &qsync_min_fps,
conn->state);
if (!qsync_min_fps || !default_fps || !yres) {
SDE_ERROR_CMDENC(cmd_enc,
@@ -1024,32 +1030,51 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc)
goto exit;
}
/* Calculate the number of extra lines*/
slow_time_ns = DIV_ROUND_UP(1000000000, qsync_min_fps);
default_time_ns = DIV_ROUND_UP(1000000000, default_fps);
extra_time_ns = slow_time_ns - default_time_ns;
default_line_time_ns = DIV_ROUND_UP(default_time_ns, yres);
/*
* Calculate safe qsync trigger window by compensating
* the qsync timeout period by panel jitter value.
*
* qsync_safe_window_period = qsync_timeout_period * (1 - jitter) - nominal_period
* nominal_line_time = nominal_period / vtotal
* qsync_safe_window_lines = qsync_safe_window_period / nominal_line_time
*/
qsync_time_ns = mult_frac(1000000000, 1, qsync_min_fps);
default_time_ns = mult_frac(1000000000, 1, default_fps);
threshold_lines = extra_time_ns / default_line_time_ns;
sde_encoder_helper_get_jitter_bounds_ns(qsync_min_fps, info->jitter_numer,
info->jitter_denom, &qsync_l_bound_ns, &qsync_u_bound_ns);
if (!qsync_l_bound_ns || !qsync_u_bound_ns)
qsync_l_bound_ns = qsync_u_bound_ns = qsync_time_ns;
extra_time_ns = qsync_l_bound_ns - default_time_ns;
default_line_time_ns = mult_frac(1, default_time_ns, yres);
threshold_lines = mult_frac(1, extra_time_ns, default_line_time_ns);
/* some DDICs express the timeout value in lines/4, round down to compensate */
threshold_lines = round_down(threshold_lines, 4);
adjusted_threshold_lines = round_down(threshold_lines, 4);
/* remove 2 lines to cover for latency */
if (threshold_lines - 2 > DEFAULT_TEARCHECK_SYNC_THRESH_START)
threshold_lines -= 2;
if (adjusted_threshold_lines - 2 > DEFAULT_TEARCHECK_SYNC_THRESH_START)
adjusted_threshold_lines -= 2;
SDE_DEBUG_CMDENC(cmd_enc, "slow:%d default:%d extra:%d(ns)\n",
slow_time_ns, default_time_ns, extra_time_ns);
SDE_DEBUG_CMDENC(cmd_enc, "min_fps:%d fps:%d yres:%d lines:%d\n",
qsync_min_fps, default_fps, yres, threshold_lines);
SDE_DEBUG_CMDENC(cmd_enc,
"qsync mode:%u min_fps:%u time:%lld low:%lld up:%lld jitter:%u/%u\n",
qsync_mode, qsync_min_fps, qsync_time_ns, qsync_l_bound_ns,
qsync_u_bound_ns, info->jitter_numer, info->jitter_denom);
SDE_DEBUG_CMDENC(cmd_enc,
"default fps:%u time:%lld yres:%u line_time:%lld\n",
default_fps, default_time_ns, yres, default_line_time_ns);
SDE_DEBUG_CMDENC(cmd_enc,
"extra_time:%lld threshold_lines:%u adjusted_threshold_lines:%u\n",
extra_time_ns, threshold_lines, adjusted_threshold_lines);
SDE_EVT32(qsync_mode, qsync_min_fps, extra_time_ns, default_fps,
yres, threshold_lines);
SDE_EVT32(qsync_mode, qsync_min_fps, default_fps, info->jitter_numer,
info->jitter_denom, yres, extra_time_ns, default_line_time_ns,
adjusted_threshold_lines);
}
exit:
return threshold_lines;
return adjusted_threshold_lines;
}
static void sde_encoder_phys_cmd_tearcheck_config(
@@ -1500,17 +1525,22 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
static bool _sde_encoder_phys_cmd_needs_vsync_change(
struct sde_encoder_phys *phys_enc, ktime_t profile_timestamp)
{
struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys_cmd *cmd_enc;
struct sde_encoder_phys_cmd_te_timestamp *cur;
struct sde_encoder_phys_cmd_te_timestamp *prev = NULL;
ktime_t time_diff;
u64 l_bound = 0, u_bound = 0;
struct msm_mode_info *info;
ktime_t l_bound = 0, u_bound = 0;
bool ret = false;
unsigned long lock_flags;
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
sde_encoder_helper_get_jitter_bounds_ns(phys_enc->parent,
&l_bound, &u_bound);
sde_enc = to_sde_encoder_virt(phys_enc->parent);
info = &sde_enc->mode_info;
sde_encoder_helper_get_jitter_bounds_ns(info->frame_rate, info->jitter_numer,
info->jitter_denom, &l_bound, &u_bound);
if (!l_bound || !u_bound) {
SDE_ERROR_CMDENC(cmd_enc, "invalid vsync jitter bounds\n");
return false;