Loading drivers/gpu/drm/msm/sde/sde_encoder_phys.h +3 −0 Original line number Diff line number Diff line Loading @@ -381,6 +381,8 @@ struct sde_encoder_phys_cmd_autorefresh { * @rd_ptr_timestamp: last rd_ptr_irq timestamp * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received * @ctl_start_threshold: A threshold in microseconds allows command mode * engine to trigger the retire fence without waiting for rd_ptr. */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; Loading @@ -392,6 +394,7 @@ struct sde_encoder_phys_cmd { ktime_t rd_ptr_timestamp; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; u32 ctl_start_threshold; }; /** Loading drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +27 −9 Original line number Diff line number Diff line Loading @@ -333,9 +333,11 @@ static void sde_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx) * Handle rare cases where the ctl_start_irq is received * after rd_ptr_irq. If it falls within a threshold, it is * guaranteed the frame would be picked up in the current TE. * Signal retire fence immediately in such case. * Signal retire fence immediately in such case. The threshold * timer adds extra line time duration based on lowest panel * fps for qsync enabled case. */ if ((time_diff_us <= SDE_ENC_CTL_START_THRESHOLD_US) if ((time_diff_us <= cmd_enc->ctl_start_threshold) && atomic_add_unless( &phys_enc->pending_retire_fence_cnt, -1, 0)) { Loading Loading @@ -893,7 +895,8 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc, } } static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc, u32 *extra_frame_trigger_time) { struct drm_connector *conn = phys_enc->connector; u32 qsync_mode; Loading @@ -902,6 +905,7 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); *extra_frame_trigger_time = 0; if (!conn || !conn->state) return 0; Loading Loading @@ -955,6 +959,8 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) SDE_EVT32(qsync_mode, qsync_min_fps, extra_time_ns, default_fps, yres, threshold_lines); *extra_frame_trigger_time = extra_time_ns; } exit: Loading @@ -971,7 +977,7 @@ static void sde_encoder_phys_cmd_tearcheck_config( struct sde_hw_tear_check tc_cfg = { 0 }; struct drm_display_mode *mode; bool tc_enable = true; u32 vsync_hz; u32 vsync_hz, extra_frame_trigger_time; struct msm_drm_private *priv; struct sde_kms *sde_kms; Loading Loading @@ -1035,11 +1041,15 @@ static void sde_encoder_phys_cmd_tearcheck_config( */ tc_cfg.sync_cfg_height = 0xFFF0; tc_cfg.vsync_init_val = mode->vdisplay; tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc); tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc, &extra_frame_trigger_time); tc_cfg.sync_threshold_continue = DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE; tc_cfg.start_pos = mode->vdisplay; tc_cfg.rd_ptr_irq = mode->vdisplay + 1; cmd_enc->ctl_start_threshold = (extra_frame_trigger_time / 1000) + SDE_ENC_CTL_START_THRESHOLD_US; SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n", phys_enc->hw_pp->idx - PINGPONG_0, Loading @@ -1057,11 +1067,12 @@ static void sde_encoder_phys_cmd_tearcheck_config( tc_cfg.hw_vsync_mode, tc_cfg.vsync_count, tc_cfg.vsync_init_val); SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u\n", "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u ctl_start_threshold:%d\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, tc_cfg.sync_cfg_height, tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue); tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue, cmd_enc->ctl_start_threshold); if (phys_enc->has_intf_te) { phys_enc->hw_intf->ops.setup_tearcheck(phys_enc->hw_intf, Loading Loading @@ -1333,6 +1344,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); int ret; u32 extra_frame_trigger_time; if (!phys_enc || !phys_enc->hw_pp) { SDE_ERROR("invalid encoder\n"); Loading @@ -1359,7 +1371,8 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( if (sde_connector_qsync_updated(phys_enc->connector)) { tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc); _get_tearcheck_threshold(phys_enc, &extra_frame_trigger_time); if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.update_tearcheck) phys_enc->hw_intf->ops.update_tearcheck( Loading @@ -1367,8 +1380,12 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( else if (phys_enc->hw_pp->ops.update_tearcheck) phys_enc->hw_pp->ops.update_tearcheck( phys_enc->hw_pp, &tc_cfg); cmd_enc->ctl_start_threshold = (extra_frame_trigger_time / 1000) + SDE_ENC_CTL_START_THRESHOLD_US; SDE_EVT32(DRMID(phys_enc->parent), tc_cfg.sync_threshold_start); tc_cfg.sync_threshold_start, cmd_enc->ctl_start_threshold); } SDE_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n", Loading Loading @@ -1675,6 +1692,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( phys_enc->enc_spinlock = p->enc_spinlock; phys_enc->vblank_ctl_lock = p->vblank_ctl_lock; cmd_enc->stream_sel = 0; cmd_enc->ctl_start_threshold = SDE_ENC_CTL_START_THRESHOLD_US; phys_enc->enable_state = SDE_ENC_DISABLED; sde_encoder_phys_cmd_init_ops(&phys_enc->ops); phys_enc->comp_type = p->comp_type; Loading Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys.h +3 −0 Original line number Diff line number Diff line Loading @@ -381,6 +381,8 @@ struct sde_encoder_phys_cmd_autorefresh { * @rd_ptr_timestamp: last rd_ptr_irq timestamp * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received * @ctl_start_threshold: A threshold in microseconds allows command mode * engine to trigger the retire fence without waiting for rd_ptr. */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; Loading @@ -392,6 +394,7 @@ struct sde_encoder_phys_cmd { ktime_t rd_ptr_timestamp; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; u32 ctl_start_threshold; }; /** Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +27 −9 Original line number Diff line number Diff line Loading @@ -333,9 +333,11 @@ static void sde_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx) * Handle rare cases where the ctl_start_irq is received * after rd_ptr_irq. If it falls within a threshold, it is * guaranteed the frame would be picked up in the current TE. * Signal retire fence immediately in such case. * Signal retire fence immediately in such case. The threshold * timer adds extra line time duration based on lowest panel * fps for qsync enabled case. */ if ((time_diff_us <= SDE_ENC_CTL_START_THRESHOLD_US) if ((time_diff_us <= cmd_enc->ctl_start_threshold) && atomic_add_unless( &phys_enc->pending_retire_fence_cnt, -1, 0)) { Loading Loading @@ -893,7 +895,8 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc, } } static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc, u32 *extra_frame_trigger_time) { struct drm_connector *conn = phys_enc->connector; u32 qsync_mode; Loading @@ -902,6 +905,7 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); *extra_frame_trigger_time = 0; if (!conn || !conn->state) return 0; Loading Loading @@ -955,6 +959,8 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc) SDE_EVT32(qsync_mode, qsync_min_fps, extra_time_ns, default_fps, yres, threshold_lines); *extra_frame_trigger_time = extra_time_ns; } exit: Loading @@ -971,7 +977,7 @@ static void sde_encoder_phys_cmd_tearcheck_config( struct sde_hw_tear_check tc_cfg = { 0 }; struct drm_display_mode *mode; bool tc_enable = true; u32 vsync_hz; u32 vsync_hz, extra_frame_trigger_time; struct msm_drm_private *priv; struct sde_kms *sde_kms; Loading Loading @@ -1035,11 +1041,15 @@ static void sde_encoder_phys_cmd_tearcheck_config( */ tc_cfg.sync_cfg_height = 0xFFF0; tc_cfg.vsync_init_val = mode->vdisplay; tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc); tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc, &extra_frame_trigger_time); tc_cfg.sync_threshold_continue = DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE; tc_cfg.start_pos = mode->vdisplay; tc_cfg.rd_ptr_irq = mode->vdisplay + 1; cmd_enc->ctl_start_threshold = (extra_frame_trigger_time / 1000) + SDE_ENC_CTL_START_THRESHOLD_US; SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n", phys_enc->hw_pp->idx - PINGPONG_0, Loading @@ -1057,11 +1067,12 @@ static void sde_encoder_phys_cmd_tearcheck_config( tc_cfg.hw_vsync_mode, tc_cfg.vsync_count, tc_cfg.vsync_init_val); SDE_DEBUG_CMDENC(cmd_enc, "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u\n", "tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u ctl_start_threshold:%d\n", phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->hw_intf->idx - INTF_0, tc_cfg.sync_cfg_height, tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue); tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue, cmd_enc->ctl_start_threshold); if (phys_enc->has_intf_te) { phys_enc->hw_intf->ops.setup_tearcheck(phys_enc->hw_intf, Loading Loading @@ -1333,6 +1344,7 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); int ret; u32 extra_frame_trigger_time; if (!phys_enc || !phys_enc->hw_pp) { SDE_ERROR("invalid encoder\n"); Loading @@ -1359,7 +1371,8 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( if (sde_connector_qsync_updated(phys_enc->connector)) { tc_cfg.sync_threshold_start = _get_tearcheck_threshold(phys_enc); _get_tearcheck_threshold(phys_enc, &extra_frame_trigger_time); if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.update_tearcheck) phys_enc->hw_intf->ops.update_tearcheck( Loading @@ -1367,8 +1380,12 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff( else if (phys_enc->hw_pp->ops.update_tearcheck) phys_enc->hw_pp->ops.update_tearcheck( phys_enc->hw_pp, &tc_cfg); cmd_enc->ctl_start_threshold = (extra_frame_trigger_time / 1000) + SDE_ENC_CTL_START_THRESHOLD_US; SDE_EVT32(DRMID(phys_enc->parent), tc_cfg.sync_threshold_start); tc_cfg.sync_threshold_start, cmd_enc->ctl_start_threshold); } SDE_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n", Loading Loading @@ -1675,6 +1692,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( phys_enc->enc_spinlock = p->enc_spinlock; phys_enc->vblank_ctl_lock = p->vblank_ctl_lock; cmd_enc->stream_sel = 0; cmd_enc->ctl_start_threshold = SDE_ENC_CTL_START_THRESHOLD_US; phys_enc->enable_state = SDE_ENC_DISABLED; sde_encoder_phys_cmd_init_ops(&phys_enc->ops); phys_enc->comp_type = p->comp_type; Loading