|
@@ -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);
|
|
|
+
|
|
|
+ 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;
|
|
|
|
|
|
- threshold_lines = extra_time_ns / default_line_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;
|