summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlan Kwong <akwong@codeaurora.org>2016-10-04 09:38:11 -0400
committerAlan Kwong <akwong@codeaurora.org>2016-10-19 17:11:16 -0400
commit58d1938917ab32266aa3b8118d0693b6414bcdd6 (patch)
tree63229ff4baa9f5aa75aa738ec12b51d2c50f3b06 /drivers/gpu
parent0107866c1e93a2adf68bf13e8eacc305852de3e6 (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.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c38
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c29
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c4
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,