|
@@ -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)
|
|
static void _sde_encoder_phys_signal_frame_done(struct sde_encoder_phys *phys_enc)
|
|
{
|
|
{
|
|
struct sde_encoder_phys_cmd *cmd_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_encoder_helper_get_pp_line_count(phys_enc->parent, info);
|
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
|
info[0].pp_idx, info[0].intf_idx,
|
|
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].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);
|
|
scheduler_status, fence_ready);
|
|
|
|
|
|
if (phys_enc->parent_ops.handle_vblank_virt)
|
|
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_encoder_phys *phys_enc = arg;
|
|
struct sde_hw_ctl *ctl;
|
|
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}};
|
|
struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}};
|
|
|
|
|
|
if (!phys_enc || !phys_enc->hw_ctl)
|
|
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");
|
|
SDE_ATRACE_BEGIN("wr_ptr_irq");
|
|
ctl = phys_enc->hw_ctl;
|
|
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)) {
|
|
if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) {
|
|
event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
|
|
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),
|
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
|
ctl->idx - CTL_0, event,
|
|
ctl->idx - CTL_0, event,
|
|
info[0].pp_idx, info[0].intf_idx, info[0].wr_ptr_line_count,
|
|
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 */
|
|
/* Signal any waiting wr_ptr start interrupt */
|
|
wake_up_all(&phys_enc->pending_kickoff_wq);
|
|
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.start_pos = mode->vdisplay;
|
|
tc_cfg.rd_ptr_irq = mode->vdisplay + 1;
|
|
tc_cfg.rd_ptr_irq = mode->vdisplay + 1;
|
|
tc_cfg.wr_ptr_irq = 1;
|
|
tc_cfg.wr_ptr_irq = 1;
|
|
|
|
+ cmd_enc->qsync_threshold_lines = tc_cfg.sync_threshold_start;
|
|
|
|
|
|
SDE_DEBUG_CMDENC(cmd_enc,
|
|
SDE_DEBUG_CMDENC(cmd_enc,
|
|
"tc %d intf %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n",
|
|
"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)) {
|
|
if (sde_connector_is_qsync_updated(phys_enc->connector)) {
|
|
tc_cfg.sync_threshold_start = _get_tearcheck_threshold(
|
|
tc_cfg.sync_threshold_start = _get_tearcheck_threshold(
|
|
phys_enc);
|
|
phys_enc);
|
|
|
|
+ cmd_enc->qsync_threshold_lines = tc_cfg.sync_threshold_start;
|
|
if (phys_enc->has_intf_te &&
|
|
if (phys_enc->has_intf_te &&
|
|
phys_enc->hw_intf->ops.update_tearcheck)
|
|
phys_enc->hw_intf->ops.update_tearcheck)
|
|
phys_enc->hw_intf->ops.update_tearcheck(
|
|
phys_enc->hw_intf->ops.update_tearcheck(
|