Loading drivers/gpu/drm/msm/sde/sde_crtc.c +25 −6 Original line number Diff line number Diff line Loading @@ -3406,16 +3406,18 @@ static void _sde_crtc_remove_pipe_flush(struct sde_crtc *sde_crtc) * _sde_crtc_reset_hw - attempt hardware reset on errors * @crtc: Pointer to DRM crtc instance * @old_state: Pointer to crtc state for previous commit * @dump_status: Whether or not to dump debug status before reset * Returns: Zero if current commit should still be attempted */ static int _sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state) struct drm_crtc_state *old_state, bool dump_status) { struct drm_plane *plane_halt[MAX_PLANES]; struct drm_plane *plane; const struct drm_plane_state *pstate; struct sde_crtc *sde_crtc; struct sde_hw_ctl *ctl; enum sde_ctl_rot_op_mode old_rot_op_mode; signed int i, plane_count; int rc; Loading @@ -3423,6 +3425,13 @@ static int _sde_crtc_reset_hw(struct drm_crtc *crtc, return -EINVAL; sde_crtc = to_sde_crtc(crtc); old_rot_op_mode = to_sde_crtc_state(old_state)->sbuf_cfg.rot_op_mode; SDE_EVT32(DRMID(crtc), old_rot_op_mode, dump_status, SDE_EVTLOG_FUNC_ENTRY); if (dump_status) SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus"); for (i = 0; i < sde_crtc->num_mixers; ++i) { ctl = sde_crtc->mixers[i].hw_ctl; if (!ctl || !ctl->ops.reset) Loading @@ -3438,11 +3447,19 @@ static int _sde_crtc_reset_hw(struct drm_crtc *crtc, } } /* early out if simple ctl reset succeeded */ if (i == sde_crtc->num_mixers) { SDE_EVT32(DRMID(crtc), i); /* * Early out if simple ctl reset succeeded and previous commit * did not involve the rotator. * * If the previous commit had rotation enabled, then the ctl * reset would also have reset the rotator h/w. The rotator * programming for the current commit may need to be repeated, * depending on the rotation mode; don't handle this for now * and just force a hard reset in those cases. */ if (i == sde_crtc->num_mixers && old_rot_op_mode == SDE_CTL_ROT_OP_MODE_OFFLINE) return false; } SDE_DEBUG("crtc%d: issuing hard reset\n", DRMID(crtc)); Loading Loading @@ -3615,7 +3632,8 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, * preparing for the kickoff */ if (reset_req) { if (_sde_crtc_reset_hw(crtc, old_state)) if (_sde_crtc_reset_hw(crtc, old_state, !sde_crtc->reset_request)) is_error = true; /* force offline rotation mode since the commit has no pipes */ Loading @@ -3623,6 +3641,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, cstate->sbuf_cfg.rot_op_mode = SDE_CTL_ROT_OP_MODE_OFFLINE; } sde_crtc->reset_request = reset_req; /* wait for frame_event_done completion */ SDE_ATRACE_BEGIN("wait_for_frame_done_event"); Loading drivers/gpu/drm/msm/sde/sde_crtc.h +3 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,8 @@ struct sde_crtc_event { * @enabled : whether the SDE CRTC is currently enabled. updated in the * commit-thread, not state-swap time which is earlier, so * safe to make decisions on during VBLANK on/off work * @reset_request : whether or not a h/w request was requested for the previous * frame * @ds_reconfig : force reconfiguration of the destination scaler block * @feature_list : list of color processing features supported on a crtc * @active_list : list of color processing features are active Loading Loading @@ -247,6 +249,7 @@ struct sde_crtc { bool vblank_requested; bool suspend; bool enabled; bool reset_request; bool ds_reconfig; struct list_head feature_list; Loading drivers/gpu/drm/msm/sde/sde_encoder.c +18 −1 Original line number Diff line number Diff line Loading @@ -3398,6 +3398,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; bool needs_hw_reset = false; uint32_t ln_cnt1, ln_cnt2; unsigned int i; int rc, ret = 0; Loading @@ -3410,6 +3411,13 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); /* save this for later, in case of errors */ if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count( sde_enc->cur_master); else ln_cnt1 = -EINVAL; /* prepare for next kickoff, may include waiting on previous kickoff */ SDE_ATRACE_BEGIN("enc_prepare_for_kickoff"); for (i = 0; i < sde_enc->num_phys_encs; i++) { Loading @@ -3436,7 +3444,16 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, /* if any phys needs reset, reset all phys, in-order */ if (needs_hw_reset) { SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_CASE1); /* query line count before cur_master is updated */ if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( sde_enc->cur_master); else ln_cnt2 = -EINVAL; SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2, SDE_EVTLOG_FUNC_CASE1); for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; if (phys && phys->ops.hw_reset) Loading drivers/gpu/drm/msm/sde/sde_encoder_phys.h +3 −1 Original line number Diff line number Diff line Loading @@ -132,7 +132,8 @@ struct sde_encoder_virt_ops { * @restore: Restore all the encoder configs. * @is_autorefresh_enabled: provides the autorefresh current * enable/disable state. * @get_line_count: Obtain current vertical line count * @get_line_count: Obtain current internal vertical line count * @get_wr_line_count: Obtain current output vertical line count * @wait_dma_trigger: Returns true if lut dma has to trigger and wait * unitl transaction is complete. * @wait_for_active: Wait for display scan line to be in active area Loading Loading @@ -182,6 +183,7 @@ struct sde_encoder_phys_ops { void (*restore)(struct sde_encoder_phys *phys); bool (*is_autorefresh_enabled)(struct sde_encoder_phys *phys); int (*get_line_count)(struct sde_encoder_phys *phys); int (*get_wr_line_count)(struct sde_encoder_phys *phys); bool (*wait_dma_trigger)(struct sde_encoder_phys *phys); int (*wait_for_active)(struct sde_encoder_phys *phys); }; Loading drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +23 −6 Original line number Diff line number Diff line Loading @@ -448,9 +448,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( cmd_enc->pp_timeout_report_cnt = PP_TIMEOUT_MAX_TRIALS; frame_event |= SDE_ENCODER_FRAME_EVENT_PANEL_DEAD; sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR); SDE_DBG_DUMP("panic"); sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR); } else if (cmd_enc->pp_timeout_report_cnt == 1) { /* to avoid flooding, only log first time, and "dead" time */ SDE_ERROR_CMDENC(cmd_enc, Loading @@ -461,10 +459,6 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( atomic_read(&phys_enc->pending_kickoff_cnt)); SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FATAL); sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR); SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus"); sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR); } atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); Loading Loading @@ -958,6 +952,28 @@ static int sde_encoder_phys_cmd_get_line_count( return hw_pp->ops.get_line_count(hw_pp); } static int sde_encoder_phys_cmd_get_write_line_count( struct sde_encoder_phys *phys_enc) { struct sde_hw_pingpong *hw_pp; struct sde_hw_pp_vsync_info info; if (!phys_enc || !phys_enc->hw_pp) return -EINVAL; if (!sde_encoder_phys_cmd_is_master(phys_enc)) return -EINVAL; hw_pp = phys_enc->hw_pp; if (!hw_pp->ops.get_vsync_info) return -EINVAL; if (hw_pp->ops.get_vsync_info(hw_pp, &info)) return -EINVAL; return (int)info.wr_ptr_line_count; } static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_cmd *cmd_enc = Loading Loading @@ -1302,6 +1318,7 @@ static void sde_encoder_phys_cmd_init_ops( ops->is_autorefresh_enabled = sde_encoder_phys_cmd_is_autorefresh_enabled; ops->get_line_count = sde_encoder_phys_cmd_get_line_count; ops->get_wr_line_count = sde_encoder_phys_cmd_get_write_line_count; ops->wait_for_active = NULL; } Loading Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +25 −6 Original line number Diff line number Diff line Loading @@ -3406,16 +3406,18 @@ static void _sde_crtc_remove_pipe_flush(struct sde_crtc *sde_crtc) * _sde_crtc_reset_hw - attempt hardware reset on errors * @crtc: Pointer to DRM crtc instance * @old_state: Pointer to crtc state for previous commit * @dump_status: Whether or not to dump debug status before reset * Returns: Zero if current commit should still be attempted */ static int _sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state) struct drm_crtc_state *old_state, bool dump_status) { struct drm_plane *plane_halt[MAX_PLANES]; struct drm_plane *plane; const struct drm_plane_state *pstate; struct sde_crtc *sde_crtc; struct sde_hw_ctl *ctl; enum sde_ctl_rot_op_mode old_rot_op_mode; signed int i, plane_count; int rc; Loading @@ -3423,6 +3425,13 @@ static int _sde_crtc_reset_hw(struct drm_crtc *crtc, return -EINVAL; sde_crtc = to_sde_crtc(crtc); old_rot_op_mode = to_sde_crtc_state(old_state)->sbuf_cfg.rot_op_mode; SDE_EVT32(DRMID(crtc), old_rot_op_mode, dump_status, SDE_EVTLOG_FUNC_ENTRY); if (dump_status) SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus"); for (i = 0; i < sde_crtc->num_mixers; ++i) { ctl = sde_crtc->mixers[i].hw_ctl; if (!ctl || !ctl->ops.reset) Loading @@ -3438,11 +3447,19 @@ static int _sde_crtc_reset_hw(struct drm_crtc *crtc, } } /* early out if simple ctl reset succeeded */ if (i == sde_crtc->num_mixers) { SDE_EVT32(DRMID(crtc), i); /* * Early out if simple ctl reset succeeded and previous commit * did not involve the rotator. * * If the previous commit had rotation enabled, then the ctl * reset would also have reset the rotator h/w. The rotator * programming for the current commit may need to be repeated, * depending on the rotation mode; don't handle this for now * and just force a hard reset in those cases. */ if (i == sde_crtc->num_mixers && old_rot_op_mode == SDE_CTL_ROT_OP_MODE_OFFLINE) return false; } SDE_DEBUG("crtc%d: issuing hard reset\n", DRMID(crtc)); Loading Loading @@ -3615,7 +3632,8 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, * preparing for the kickoff */ if (reset_req) { if (_sde_crtc_reset_hw(crtc, old_state)) if (_sde_crtc_reset_hw(crtc, old_state, !sde_crtc->reset_request)) is_error = true; /* force offline rotation mode since the commit has no pipes */ Loading @@ -3623,6 +3641,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, cstate->sbuf_cfg.rot_op_mode = SDE_CTL_ROT_OP_MODE_OFFLINE; } sde_crtc->reset_request = reset_req; /* wait for frame_event_done completion */ SDE_ATRACE_BEGIN("wait_for_frame_done_event"); Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +3 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,8 @@ struct sde_crtc_event { * @enabled : whether the SDE CRTC is currently enabled. updated in the * commit-thread, not state-swap time which is earlier, so * safe to make decisions on during VBLANK on/off work * @reset_request : whether or not a h/w request was requested for the previous * frame * @ds_reconfig : force reconfiguration of the destination scaler block * @feature_list : list of color processing features supported on a crtc * @active_list : list of color processing features are active Loading Loading @@ -247,6 +249,7 @@ struct sde_crtc { bool vblank_requested; bool suspend; bool enabled; bool reset_request; bool ds_reconfig; struct list_head feature_list; Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +18 −1 Original line number Diff line number Diff line Loading @@ -3398,6 +3398,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; bool needs_hw_reset = false; uint32_t ln_cnt1, ln_cnt2; unsigned int i; int rc, ret = 0; Loading @@ -3410,6 +3411,13 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); /* save this for later, in case of errors */ if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count( sde_enc->cur_master); else ln_cnt1 = -EINVAL; /* prepare for next kickoff, may include waiting on previous kickoff */ SDE_ATRACE_BEGIN("enc_prepare_for_kickoff"); for (i = 0; i < sde_enc->num_phys_encs; i++) { Loading @@ -3436,7 +3444,16 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, /* if any phys needs reset, reset all phys, in-order */ if (needs_hw_reset) { SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_CASE1); /* query line count before cur_master is updated */ if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count) ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count( sde_enc->cur_master); else ln_cnt2 = -EINVAL; SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2, SDE_EVTLOG_FUNC_CASE1); for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; if (phys && phys->ops.hw_reset) Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys.h +3 −1 Original line number Diff line number Diff line Loading @@ -132,7 +132,8 @@ struct sde_encoder_virt_ops { * @restore: Restore all the encoder configs. * @is_autorefresh_enabled: provides the autorefresh current * enable/disable state. * @get_line_count: Obtain current vertical line count * @get_line_count: Obtain current internal vertical line count * @get_wr_line_count: Obtain current output vertical line count * @wait_dma_trigger: Returns true if lut dma has to trigger and wait * unitl transaction is complete. * @wait_for_active: Wait for display scan line to be in active area Loading Loading @@ -182,6 +183,7 @@ struct sde_encoder_phys_ops { void (*restore)(struct sde_encoder_phys *phys); bool (*is_autorefresh_enabled)(struct sde_encoder_phys *phys); int (*get_line_count)(struct sde_encoder_phys *phys); int (*get_wr_line_count)(struct sde_encoder_phys *phys); bool (*wait_dma_trigger)(struct sde_encoder_phys *phys); int (*wait_for_active)(struct sde_encoder_phys *phys); }; Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +23 −6 Original line number Diff line number Diff line Loading @@ -448,9 +448,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( cmd_enc->pp_timeout_report_cnt = PP_TIMEOUT_MAX_TRIALS; frame_event |= SDE_ENCODER_FRAME_EVENT_PANEL_DEAD; sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR); SDE_DBG_DUMP("panic"); sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR); } else if (cmd_enc->pp_timeout_report_cnt == 1) { /* to avoid flooding, only log first time, and "dead" time */ SDE_ERROR_CMDENC(cmd_enc, Loading @@ -461,10 +459,6 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( atomic_read(&phys_enc->pending_kickoff_cnt)); SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FATAL); sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR); SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus"); sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR); } atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); Loading Loading @@ -958,6 +952,28 @@ static int sde_encoder_phys_cmd_get_line_count( return hw_pp->ops.get_line_count(hw_pp); } static int sde_encoder_phys_cmd_get_write_line_count( struct sde_encoder_phys *phys_enc) { struct sde_hw_pingpong *hw_pp; struct sde_hw_pp_vsync_info info; if (!phys_enc || !phys_enc->hw_pp) return -EINVAL; if (!sde_encoder_phys_cmd_is_master(phys_enc)) return -EINVAL; hw_pp = phys_enc->hw_pp; if (!hw_pp->ops.get_vsync_info) return -EINVAL; if (hw_pp->ops.get_vsync_info(hw_pp, &info)) return -EINVAL; return (int)info.wr_ptr_line_count; } static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_cmd *cmd_enc = Loading Loading @@ -1302,6 +1318,7 @@ static void sde_encoder_phys_cmd_init_ops( ops->is_autorefresh_enabled = sde_encoder_phys_cmd_is_autorefresh_enabled; ops->get_line_count = sde_encoder_phys_cmd_get_line_count; ops->get_wr_line_count = sde_encoder_phys_cmd_get_write_line_count; ops->wait_for_active = NULL; } Loading