Loading drivers/gpu/drm/msm/sde/sde_crtc.c +40 −3 Original line number Diff line number Diff line Loading @@ -1504,6 +1504,7 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc) lm->ops.setup_alpha_out(lm, mixer[i].mixer_op_mode); mixer[i].pipe_mask = mixer[i].flush_mask; mixer[i].flush_mask |= ctl->ops.get_bitmask_mixer(ctl, mixer[i].hw_lm->idx); Loading Loading @@ -3313,6 +3314,34 @@ static void _sde_crtc_commit_kickoff_rot(struct drm_crtc *crtc, SDE_ATRACE_END("crtc_kickoff_rot"); } /** * _sde_crtc_remove_pipe_flush - remove staged pipes from flush mask * @sde_crtc: Pointer to sde crtc structure */ static void _sde_crtc_remove_pipe_flush(struct sde_crtc *sde_crtc) { struct sde_crtc_mixer *mixer; struct sde_hw_ctl *ctl; u32 i, flush_mask; if (!sde_crtc) return; mixer = sde_crtc->mixers; for (i = 0; i < sde_crtc->num_mixers; i++) { ctl = mixer[i].hw_ctl; if (!ctl || !ctl->ops.get_pending_flush || !ctl->ops.clear_pending_flush || !ctl->ops.update_pending_flush) continue; flush_mask = ctl->ops.get_pending_flush(ctl); flush_mask &= ~mixer[i].pipe_mask; ctl->ops.clear_pending_flush(ctl); ctl->ops.update_pending_flush(ctl, flush_mask); } } void sde_crtc_commit_kickoff(struct drm_crtc *crtc) { struct drm_encoder *encoder; Loading @@ -3321,6 +3350,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) struct msm_drm_private *priv; struct sde_kms *sde_kms; struct sde_crtc_state *cstate; bool is_error; int ret; if (!crtc) { Loading @@ -3330,6 +3360,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) dev = crtc->dev; sde_crtc = to_sde_crtc(crtc); sde_kms = _sde_crtc_get_kms(crtc); is_error = false; if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev_private) { SDE_ERROR("invalid argument\n"); Loading Loading @@ -3396,7 +3427,11 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n", crtc->base.id, atomic_read(&sde_crtc->frame_pending)); goto end; is_error = true; /* force offline rotation mode since the commit has no pipes */ cstate->sbuf_cfg.rot_op_mode = SDE_CTL_ROT_OP_MODE_OFFLINE; } if (atomic_inc_return(&sde_crtc->frame_pending) == 1) { Loading @@ -3423,14 +3458,16 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) sde_vbif_clear_errors(sde_kms); if (is_error) _sde_crtc_remove_pipe_flush(sde_crtc); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) continue; sde_encoder_kickoff(encoder); sde_encoder_kickoff(encoder, is_error); } end: reinit_completion(&sde_crtc->frame_done_comp); SDE_ATRACE_END("crtc_commit"); return; Loading drivers/gpu/drm/msm/sde/sde_crtc.h +2 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ struct sde_crtc_retire_event { * @encoder: Encoder attached to this lm & ctl * @mixer_op_mode: mixer blending operation mode * @flush_mask: mixer flush mask for ctl, mixer and pipe * @pipe_mask: mixer flush mask for pipe */ struct sde_crtc_mixer { struct sde_hw_mixer *hw_lm; Loading @@ -120,6 +121,7 @@ struct sde_crtc_mixer { struct drm_encoder *encoder; u32 mixer_op_mode; u32 flush_mask; u32 pipe_mask; }; /** Loading drivers/gpu/drm/msm/sde/sde_encoder.c +46 −5 Original line number Diff line number Diff line Loading @@ -3070,7 +3070,46 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, } } void sde_encoder_kickoff(struct drm_encoder *drm_enc) /** * _sde_encoder_reset_ctl_hw - reset h/w configuration for all ctl's associated * with the specified encoder, and unstage all pipes from it * @encoder: encoder pointer * Returns: 0 on success */ static int _sde_encoder_reset_ctl_hw(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; unsigned int i; int rc = 0; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return -EINVAL; } sde_enc = to_sde_encoder_virt(drm_enc); SDE_ATRACE_BEGIN("encoder_release_lm"); SDE_DEBUG_ENC(sde_enc, "\n"); for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; if (!phys) continue; SDE_EVT32(DRMID(drm_enc), phys->intf_idx - INTF_0); rc = sde_encoder_helper_reset_mixers(phys, NULL); if (rc) SDE_EVT32(DRMID(drm_enc), rc, SDE_EVTLOG_ERROR); } SDE_ATRACE_END("encoder_release_lm"); return rc; } void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool is_error) { struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; Loading @@ -3092,6 +3131,10 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc) mod_timer(&sde_enc->frame_done_timer, jiffies + ((atomic_read(&sde_enc->frame_done_timeout) * HZ) / 1000)); /* create a 'no pipes' commit to release buffers on errors */ if (is_error) _sde_encoder_reset_ctl_hw(drm_enc); /* All phys encs are ready to go, trigger the kickoff */ _sde_encoder_kickoff_phys(sde_enc); Loading @@ -3112,7 +3155,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc) SDE_ATRACE_END("encoder_kickoff"); } int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb) { struct drm_encoder *drm_enc; Loading @@ -3129,8 +3172,6 @@ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, memset(&mixer, 0, sizeof(mixer)); /* reset associated CTL/LMs */ if (phys_enc->hw_ctl->ops.clear_pending_flush) phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl); if (phys_enc->hw_ctl->ops.clear_all_blendstages) phys_enc->hw_ctl->ops.clear_all_blendstages(phys_enc->hw_ctl); Loading Loading @@ -3170,7 +3211,7 @@ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, } if (!lm_valid) { SDE_DEBUG_ENC(to_sde_encoder_virt(drm_enc), "lm not found\n"); SDE_ERROR_ENC(to_sde_encoder_virt(drm_enc), "lm not found\n"); return -EFAULT; } return 0; Loading drivers/gpu/drm/msm/sde/sde_encoder.h +3 −1 Original line number Diff line number Diff line Loading @@ -128,8 +128,10 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *encoder); * sde_encoder_kickoff - trigger a double buffer flip of the ctl path * (i.e. ctl flush and start) immediately. * @encoder: encoder pointer * @is_error: whether the current commit needs to be aborted and replaced * with a 'safe' commit */ void sde_encoder_kickoff(struct drm_encoder *encoder); void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error); /** * sde_encoder_wait_for_event - Waits for encoder events Loading drivers/gpu/drm/msm/sde/sde_encoder_phys.h +2 −2 Original line number Diff line number Diff line Loading @@ -522,12 +522,12 @@ void sde_encoder_helper_split_config( enum sde_intf interface); /** * sde_encoder_helper_hw_release - prepare for h/w reset during disable * sde_encoder_helper_reset_mixers - reset mixers associated with phys enc * @phys_enc: Pointer to physical encoder structure * @fb: Optional fb for specifying new mixer output resolution, may be NULL * Return: Zero on success */ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb); /** Loading Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +40 −3 Original line number Diff line number Diff line Loading @@ -1504,6 +1504,7 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc) lm->ops.setup_alpha_out(lm, mixer[i].mixer_op_mode); mixer[i].pipe_mask = mixer[i].flush_mask; mixer[i].flush_mask |= ctl->ops.get_bitmask_mixer(ctl, mixer[i].hw_lm->idx); Loading Loading @@ -3313,6 +3314,34 @@ static void _sde_crtc_commit_kickoff_rot(struct drm_crtc *crtc, SDE_ATRACE_END("crtc_kickoff_rot"); } /** * _sde_crtc_remove_pipe_flush - remove staged pipes from flush mask * @sde_crtc: Pointer to sde crtc structure */ static void _sde_crtc_remove_pipe_flush(struct sde_crtc *sde_crtc) { struct sde_crtc_mixer *mixer; struct sde_hw_ctl *ctl; u32 i, flush_mask; if (!sde_crtc) return; mixer = sde_crtc->mixers; for (i = 0; i < sde_crtc->num_mixers; i++) { ctl = mixer[i].hw_ctl; if (!ctl || !ctl->ops.get_pending_flush || !ctl->ops.clear_pending_flush || !ctl->ops.update_pending_flush) continue; flush_mask = ctl->ops.get_pending_flush(ctl); flush_mask &= ~mixer[i].pipe_mask; ctl->ops.clear_pending_flush(ctl); ctl->ops.update_pending_flush(ctl, flush_mask); } } void sde_crtc_commit_kickoff(struct drm_crtc *crtc) { struct drm_encoder *encoder; Loading @@ -3321,6 +3350,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) struct msm_drm_private *priv; struct sde_kms *sde_kms; struct sde_crtc_state *cstate; bool is_error; int ret; if (!crtc) { Loading @@ -3330,6 +3360,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) dev = crtc->dev; sde_crtc = to_sde_crtc(crtc); sde_kms = _sde_crtc_get_kms(crtc); is_error = false; if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev_private) { SDE_ERROR("invalid argument\n"); Loading Loading @@ -3396,7 +3427,11 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n", crtc->base.id, atomic_read(&sde_crtc->frame_pending)); goto end; is_error = true; /* force offline rotation mode since the commit has no pipes */ cstate->sbuf_cfg.rot_op_mode = SDE_CTL_ROT_OP_MODE_OFFLINE; } if (atomic_inc_return(&sde_crtc->frame_pending) == 1) { Loading @@ -3423,14 +3458,16 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) sde_vbif_clear_errors(sde_kms); if (is_error) _sde_crtc_remove_pipe_flush(sde_crtc); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) continue; sde_encoder_kickoff(encoder); sde_encoder_kickoff(encoder, is_error); } end: reinit_completion(&sde_crtc->frame_done_comp); SDE_ATRACE_END("crtc_commit"); return; Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +2 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ struct sde_crtc_retire_event { * @encoder: Encoder attached to this lm & ctl * @mixer_op_mode: mixer blending operation mode * @flush_mask: mixer flush mask for ctl, mixer and pipe * @pipe_mask: mixer flush mask for pipe */ struct sde_crtc_mixer { struct sde_hw_mixer *hw_lm; Loading @@ -120,6 +121,7 @@ struct sde_crtc_mixer { struct drm_encoder *encoder; u32 mixer_op_mode; u32 flush_mask; u32 pipe_mask; }; /** Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +46 −5 Original line number Diff line number Diff line Loading @@ -3070,7 +3070,46 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, } } void sde_encoder_kickoff(struct drm_encoder *drm_enc) /** * _sde_encoder_reset_ctl_hw - reset h/w configuration for all ctl's associated * with the specified encoder, and unstage all pipes from it * @encoder: encoder pointer * Returns: 0 on success */ static int _sde_encoder_reset_ctl_hw(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; unsigned int i; int rc = 0; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return -EINVAL; } sde_enc = to_sde_encoder_virt(drm_enc); SDE_ATRACE_BEGIN("encoder_release_lm"); SDE_DEBUG_ENC(sde_enc, "\n"); for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; if (!phys) continue; SDE_EVT32(DRMID(drm_enc), phys->intf_idx - INTF_0); rc = sde_encoder_helper_reset_mixers(phys, NULL); if (rc) SDE_EVT32(DRMID(drm_enc), rc, SDE_EVTLOG_ERROR); } SDE_ATRACE_END("encoder_release_lm"); return rc; } void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool is_error) { struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; Loading @@ -3092,6 +3131,10 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc) mod_timer(&sde_enc->frame_done_timer, jiffies + ((atomic_read(&sde_enc->frame_done_timeout) * HZ) / 1000)); /* create a 'no pipes' commit to release buffers on errors */ if (is_error) _sde_encoder_reset_ctl_hw(drm_enc); /* All phys encs are ready to go, trigger the kickoff */ _sde_encoder_kickoff_phys(sde_enc); Loading @@ -3112,7 +3155,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc) SDE_ATRACE_END("encoder_kickoff"); } int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb) { struct drm_encoder *drm_enc; Loading @@ -3129,8 +3172,6 @@ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, memset(&mixer, 0, sizeof(mixer)); /* reset associated CTL/LMs */ if (phys_enc->hw_ctl->ops.clear_pending_flush) phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl); if (phys_enc->hw_ctl->ops.clear_all_blendstages) phys_enc->hw_ctl->ops.clear_all_blendstages(phys_enc->hw_ctl); Loading Loading @@ -3170,7 +3211,7 @@ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, } if (!lm_valid) { SDE_DEBUG_ENC(to_sde_encoder_virt(drm_enc), "lm not found\n"); SDE_ERROR_ENC(to_sde_encoder_virt(drm_enc), "lm not found\n"); return -EFAULT; } return 0; Loading
drivers/gpu/drm/msm/sde/sde_encoder.h +3 −1 Original line number Diff line number Diff line Loading @@ -128,8 +128,10 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *encoder); * sde_encoder_kickoff - trigger a double buffer flip of the ctl path * (i.e. ctl flush and start) immediately. * @encoder: encoder pointer * @is_error: whether the current commit needs to be aborted and replaced * with a 'safe' commit */ void sde_encoder_kickoff(struct drm_encoder *encoder); void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error); /** * sde_encoder_wait_for_event - Waits for encoder events Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys.h +2 −2 Original line number Diff line number Diff line Loading @@ -522,12 +522,12 @@ void sde_encoder_helper_split_config( enum sde_intf interface); /** * sde_encoder_helper_hw_release - prepare for h/w reset during disable * sde_encoder_helper_reset_mixers - reset mixers associated with phys enc * @phys_enc: Pointer to physical encoder structure * @fb: Optional fb for specifying new mixer output resolution, may be NULL * Return: Zero on success */ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc, int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb); /** Loading