diff options
| author | Alan Kwong <akwong@codeaurora.org> | 2016-10-04 09:38:11 -0400 |
|---|---|---|
| committer | Alan Kwong <akwong@codeaurora.org> | 2016-10-19 17:11:16 -0400 |
| commit | 58d1938917ab32266aa3b8118d0693b6414bcdd6 (patch) | |
| tree | 63229ff4baa9f5aa75aa738ec12b51d2c50f3b06 /drivers/gpu | |
| parent | 0107866c1e93a2adf68bf13e8eacc305852de3e6 (diff) | |
drm/msm/sde: correct to use sync vblank request for commit
Current sde_wait_for_commit_done is calling asynchronous
drm_crtc_vblank_get/put to enable/disable vblank interrupt.
However, drm_crtc_vblank_get/put submit the vblank request
to a workqueue for later execution. As a result, vblank
irq is not get/put properly prior/after the commit operation
in sde_wait_for_commit_done.
Replace async drm_crtc_vblank_get/put with sync sde_crtc_vblank,
and use reference count in encoder to enable/disable interrupts.
Change-Id: Iccc83983d56b75717eda9c401a54dfe77e945fed
Signed-off-by: Alan Kwong <akwong@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 38 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c | 29 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_kms.c | 4 |
4 files changed, 51 insertions, 22 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 7dbc629eb513..4932d503ddbd 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -141,6 +141,7 @@ enum sde_enc_enable_state { * @spin_lock: Lock for IRQ purposes * @mode_3d: 3D mux configuration * @enable_state: Enable state tracking + * @vblank_refcount: Reference count of vblank request */ struct sde_encoder_phys { struct drm_encoder *parent; @@ -157,6 +158,7 @@ struct sde_encoder_phys { spinlock_t spin_lock; enum sde_3d_blend_mode mode_3d; enum sde_enc_enable_state enable_state; + atomic_t vblank_refcount; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index e7a7d85bb758..0846e4c02885 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -377,20 +377,27 @@ static int sde_encoder_phys_cmd_control_vblank_irq( SDE_ERROR("invalid encoder\n"); return -EINVAL; } - SDE_DEBUG_CMDENC(cmd_enc, "enable %d\n", enable); /* Slave encoders don't report vblank */ - if (sde_encoder_phys_cmd_is_master(phys_enc)) { - if (enable) - ret = sde_encoder_phys_cmd_register_pp_irq(phys_enc, - SDE_IRQ_TYPE_PING_PONG_RD_PTR, - &cmd_enc->pp_rd_ptr_irq_idx, - sde_encoder_phys_cmd_pp_rd_ptr_irq, - "pp_rd_ptr"); - else - ret = sde_encoder_phys_cmd_unregister_pp_irq(phys_enc, - cmd_enc->pp_rd_ptr_irq_idx); - } + if (!sde_encoder_phys_cmd_is_master(phys_enc)) + return 0; + + SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n", + __builtin_return_address(0), + enable, atomic_read(&phys_enc->vblank_refcount)); + + MSM_EVTMSG(phys_enc->parent->dev, NULL, enable, + atomic_read(&phys_enc->vblank_refcount)); + + if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) + ret = sde_encoder_phys_cmd_register_pp_irq(phys_enc, + SDE_IRQ_TYPE_PING_PONG_RD_PTR, + &cmd_enc->pp_rd_ptr_irq_idx, + sde_encoder_phys_cmd_pp_rd_ptr_irq, + "pp_rd_ptr"); + else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0) + ret = sde_encoder_phys_cmd_unregister_pp_irq(phys_enc, + cmd_enc->pp_rd_ptr_irq_idx); if (ret) SDE_ERROR_CMDENC(cmd_enc, @@ -475,6 +482,12 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc) atomic_set(&cmd_enc->pending_cnt, 0); wake_up_all(&cmd_enc->pp_tx_done_wq); phys_enc->enable_state = SDE_ENC_DISABLED; + + if (atomic_read(&phys_enc->vblank_refcount)) + SDE_ERROR("enc:%d role:%d invalid vblank refcount %d\n", + phys_enc->parent->base.id, + phys_enc->split_role, + atomic_read(&phys_enc->vblank_refcount)); } static void sde_encoder_phys_cmd_destroy(struct sde_encoder_phys *phys_enc) @@ -602,6 +615,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( cmd_enc->stream_sel = 0; phys_enc->enable_state = SDE_ENC_DISABLED; atomic_set(&cmd_enc->pending_cnt, 0); + atomic_set(&phys_enc->vblank_refcount, 0); init_waitqueue_head(&cmd_enc->pp_tx_done_wq); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 8ea6daaf26db..1b0a74b92fd0 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -466,15 +466,21 @@ static int sde_encoder_phys_vid_control_vblank_irq( return -EINVAL; } - SDE_DEBUG_VIDENC(vid_enc, "enable %d\n", enable); - /* Slave encoders don't report vblank */ - if (sde_encoder_phys_vid_is_master(phys_enc)) { - if (enable) - ret = sde_encoder_phys_vid_register_irq(phys_enc); - else - ret = sde_encoder_phys_vid_unregister_irq(phys_enc); - } + if (!sde_encoder_phys_vid_is_master(phys_enc)) + return 0; + + SDE_DEBUG_VIDENC(vid_enc, "[%pS] enable=%d/%d\n", + __builtin_return_address(0), + enable, atomic_read(&phys_enc->vblank_refcount)); + + MSM_EVTMSG(phys_enc->parent->dev, NULL, enable, + atomic_read(&phys_enc->vblank_refcount)); + + if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) + ret = sde_encoder_phys_vid_register_irq(phys_enc); + else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0) + ret = sde_encoder_phys_vid_unregister_irq(phys_enc); if (ret) SDE_ERROR_VIDENC(vid_enc, @@ -568,6 +574,12 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc) sde_encoder_phys_vid_wait_for_vblank(vid_enc); sde_encoder_phys_vid_control_vblank_irq(phys_enc, false); } + + if (atomic_read(&phys_enc->vblank_refcount)) + SDE_ERROR("enc:%d role:%d invalid vblank refcount %d\n", + phys_enc->parent->base.id, + phys_enc->split_role, + atomic_read(&phys_enc->vblank_refcount)); } static void sde_encoder_phys_vid_destroy(struct sde_encoder_phys *phys_enc) @@ -749,6 +761,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init( phys_enc->intf_mode = INTF_MODE_VIDEO; spin_lock_init(&phys_enc->spin_lock); init_completion(&vid_enc->vblank_completion); + atomic_set(&phys_enc->vblank_refcount, 0); DRM_INFO_ONCE("intf %d: 3d blend modes not yet supported\n", vid_enc->hw_intf->idx); diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 49e28c4c233e..8664b2ba8748 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -282,7 +282,7 @@ static void sde_wait_for_commit_done(struct msm_kms *kms, } /* ref count the vblank event and interrupts while we wait for it */ - if (drm_crtc_vblank_get(crtc)) + if (sde_crtc_vblank(crtc, true)) return; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { @@ -302,7 +302,7 @@ static void sde_wait_for_commit_done(struct msm_kms *kms, } /* release vblank event ref count */ - drm_crtc_vblank_put(crtc); + sde_crtc_vblank(crtc, false); } static void sde_kms_prepare_fence(struct msm_kms *kms, |
