Merge "disp: msm: sde: override tearcheck rd_ptr_val when qsync is enabled"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
249b73b0c7
@@ -415,6 +415,7 @@ struct sde_encoder_phys_cmd_te_timestamp {
|
||||
* @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger
|
||||
* @te_timestamp_list: List head for the TE timestamp list
|
||||
* @te_timestamp: Array of size MAX_TE_PROFILE_COUNT te_timestamp_list elements
|
||||
* @qsync_threshold_lines: tearcheck threshold lines calculated based on qsync_min_fps
|
||||
*/
|
||||
struct sde_encoder_phys_cmd {
|
||||
struct sde_encoder_phys base;
|
||||
@@ -427,6 +428,7 @@ struct sde_encoder_phys_cmd {
|
||||
struct list_head te_timestamp_list;
|
||||
struct sde_encoder_phys_cmd_te_timestamp
|
||||
te_timestamp[MAX_TE_PROFILE_COUNT];
|
||||
u32 qsync_threshold_lines;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -171,6 +171,37 @@ static void _sde_encoder_phys_cmd_update_intf_cfg(
|
||||
}
|
||||
}
|
||||
|
||||
static void sde_encoder_override_tearcheck_rd_ptr(struct sde_encoder_phys *phys_enc)
|
||||
{
|
||||
struct sde_hw_intf *hw_intf;
|
||||
struct drm_display_mode *mode;
|
||||
struct sde_encoder_phys_cmd *cmd_enc;
|
||||
struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}};
|
||||
u32 adjusted_tear_rd_ptr_line_cnt;
|
||||
|
||||
if (!phys_enc || !phys_enc->hw_intf)
|
||||
return;
|
||||
|
||||
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||
hw_intf = phys_enc->hw_intf;
|
||||
mode = &phys_enc->cached_mode;
|
||||
|
||||
/* Configure TE rd_ptr_val to the end of qsync Start Window.
|
||||
* This ensures next frame trigger_start does not get latched in the current
|
||||
* vsync window.
|
||||
*/
|
||||
adjusted_tear_rd_ptr_line_cnt = mode->vdisplay + cmd_enc->qsync_threshold_lines + 1;
|
||||
|
||||
if (hw_intf && hw_intf->ops.override_tear_rd_ptr_val)
|
||||
hw_intf->ops.override_tear_rd_ptr_val(hw_intf, adjusted_tear_rd_ptr_line_cnt);
|
||||
|
||||
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,
|
||||
info[1].rd_ptr_line_count, info[1].rd_ptr_frame_count, info[1].wr_ptr_line_count);
|
||||
}
|
||||
|
||||
static void _sde_encoder_phys_signal_frame_done(struct sde_encoder_phys *phys_enc)
|
||||
{
|
||||
struct sde_encoder_phys_cmd *cmd_enc;
|
||||
@@ -309,9 +340,9 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx)
|
||||
sde_encoder_helper_get_pp_line_count(phys_enc->parent, info);
|
||||
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
||||
info[0].pp_idx, info[0].intf_idx,
|
||||
info[0].wr_ptr_line_count, info[0].intf_frame_count,
|
||||
info[0].wr_ptr_line_count, info[0].intf_frame_count, info[0].rd_ptr_line_count,
|
||||
info[1].pp_idx, info[1].intf_idx,
|
||||
info[1].wr_ptr_line_count, info[1].intf_frame_count,
|
||||
info[1].wr_ptr_line_count, info[1].intf_frame_count, info[1].rd_ptr_line_count,
|
||||
scheduler_status, fence_ready);
|
||||
|
||||
if (phys_enc->parent_ops.handle_vblank_virt)
|
||||
@@ -327,7 +358,7 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx)
|
||||
{
|
||||
struct sde_encoder_phys *phys_enc = arg;
|
||||
struct sde_hw_ctl *ctl;
|
||||
u32 event = 0;
|
||||
u32 event = 0, qsync_mode = 0;
|
||||
struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}};
|
||||
|
||||
if (!phys_enc || !phys_enc->hw_ctl)
|
||||
@@ -335,6 +366,7 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx)
|
||||
|
||||
SDE_ATRACE_BEGIN("wr_ptr_irq");
|
||||
ctl = phys_enc->hw_ctl;
|
||||
qsync_mode = sde_connector_get_qsync_mode(phys_enc->connector);
|
||||
|
||||
if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) {
|
||||
event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
|
||||
@@ -350,7 +382,10 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx)
|
||||
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
||||
ctl->idx - CTL_0, event,
|
||||
info[0].pp_idx, info[0].intf_idx, info[0].wr_ptr_line_count,
|
||||
info[1].pp_idx, info[1].intf_idx, info[1].wr_ptr_line_count);
|
||||
info[1].pp_idx, info[1].intf_idx, info[1].wr_ptr_line_count, qsync_mode);
|
||||
|
||||
if (qsync_mode)
|
||||
sde_encoder_override_tearcheck_rd_ptr(phys_enc);
|
||||
|
||||
/* Signal any waiting wr_ptr start interrupt */
|
||||
wake_up_all(&phys_enc->pending_kickoff_wq);
|
||||
@@ -1092,6 +1127,7 @@ static void sde_encoder_phys_cmd_tearcheck_config(
|
||||
tc_cfg.start_pos = mode->vdisplay;
|
||||
tc_cfg.rd_ptr_irq = mode->vdisplay + 1;
|
||||
tc_cfg.wr_ptr_irq = 1;
|
||||
cmd_enc->qsync_threshold_lines = tc_cfg.sync_threshold_start;
|
||||
|
||||
SDE_DEBUG_CMDENC(cmd_enc,
|
||||
"tc %d intf %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n",
|
||||
@@ -1418,6 +1454,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
|
||||
if (sde_connector_is_qsync_updated(phys_enc->connector)) {
|
||||
tc_cfg.sync_threshold_start = _get_tearcheck_threshold(
|
||||
phys_enc);
|
||||
cmd_enc->qsync_threshold_lines = tc_cfg.sync_threshold_start;
|
||||
if (phys_enc->has_intf_te &&
|
||||
phys_enc->hw_intf->ops.update_tearcheck)
|
||||
phys_enc->hw_intf->ops.update_tearcheck(
|
||||
|
@@ -858,6 +858,21 @@ static int sde_hw_intf_v1_check_and_reset_tearcheck(struct sde_hw_intf *intf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sde_hw_intf_override_tear_rd_ptr_val(struct sde_hw_intf *intf,
|
||||
u32 adjusted_rd_ptr_val)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c;
|
||||
|
||||
if (!intf || !adjusted_rd_ptr_val)
|
||||
return;
|
||||
|
||||
c = &intf->hw;
|
||||
|
||||
SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, (adjusted_rd_ptr_val & 0xFFFF));
|
||||
/* ensure rd_ptr_val is written */
|
||||
wmb();
|
||||
}
|
||||
|
||||
static void sde_hw_intf_vsync_sel(struct sde_hw_intf *intf,
|
||||
u32 vsync_source)
|
||||
{
|
||||
@@ -956,6 +971,8 @@ static void _setup_intf_ops(struct sde_hw_intf_ops *ops,
|
||||
ops->vsync_sel = sde_hw_intf_vsync_sel;
|
||||
ops->check_and_reset_tearcheck =
|
||||
sde_hw_intf_v1_check_and_reset_tearcheck;
|
||||
ops->override_tear_rd_ptr_val =
|
||||
sde_hw_intf_override_tear_rd_ptr_val;
|
||||
}
|
||||
|
||||
if (cap & BIT(SDE_INTF_RESET_COUNTER))
|
||||
|
@@ -247,6 +247,13 @@ struct sde_hw_intf_ops {
|
||||
* Get the INTF interrupt status
|
||||
*/
|
||||
u32 (*get_intr_status)(struct sde_hw_intf *intf);
|
||||
|
||||
/**
|
||||
* Override tear check rd_ptr_val with adjusted_linecnt
|
||||
* when qsync is enabled.
|
||||
*/
|
||||
void (*override_tear_rd_ptr_val)(struct sde_hw_intf *intf,
|
||||
u32 adjusted_linecnt);
|
||||
};
|
||||
|
||||
struct sde_hw_intf {
|
||||
|
Viittaa uudesa ongelmassa
Block a user