summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2020-06-10 06:53:25 +0000
committerAndroid Partner Code Review <android-gerrit-partner@google.com>2020-06-10 06:53:25 +0000
commita0bd65d5eafce0c91b3d6be4018ae99cafa4bc25 (patch)
treeba0a92f034a888c38f5a9ae9cfe414b9e399c6db
parente4a201b78df3f1c9dedc699087a6af594e7aac7c (diff)
parent266d9bd11995d8734b2228fbe945ab35e145af33 (diff)
downloaddisplay-drivers-a0bd65d5eafce0c91b3d6be4018ae99cafa4bc25.tar.gz
Merge changes from topic "drmWaitVBlank_error" into android-msm-pixel-4.19
* changes: disp: msm: update vblank queue mechanism disp: msm: queue vblank work on disp thread during modeset
-rw-r--r--msm/msm_drv.c9
-rw-r--r--msm/sde/sde_crtc.c4
-rw-r--r--msm/sde/sde_crtc.h3
-rw-r--r--msm/sde/sde_encoder.c42
4 files changed, 37 insertions, 21 deletions
diff --git a/msm/msm_drv.c b/msm/msm_drv.c
index fc5fff14..33f0094b 100644
--- a/msm/msm_drv.c
+++ b/msm/msm_drv.c
@@ -327,6 +327,8 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
int crtc_id, bool enable)
{
struct vblank_work *cur_work;
+ struct drm_crtc *crtc;
+ struct kthread_worker *worker;
if (!priv || crtc_id >= priv->num_crtcs)
return -EINVAL;
@@ -335,14 +337,15 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
if (!cur_work)
return -ENOMEM;
+ crtc = priv->crtcs[crtc_id];
+
kthread_init_work(&cur_work->work, vblank_ctrl_worker);
cur_work->crtc_id = crtc_id;
cur_work->enable = enable;
cur_work->priv = priv;
+ worker = &priv->event_thread[crtc_id].worker;
- kthread_queue_work(&priv->event_thread[crtc_id].worker,
- &cur_work->work);
-
+ kthread_queue_work(worker, &cur_work->work);
return 0;
}
diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c
index f87e2d50..c5b6224b 100644
--- a/msm/sde/sde_crtc.c
+++ b/msm/sde/sde_crtc.c
@@ -465,6 +465,7 @@ static void sde_crtc_destroy(struct drm_crtc *crtc)
_sde_crtc_deinit_events(sde_crtc);
drm_crtc_cleanup(crtc);
+ mutex_destroy(&sde_crtc->vblank_modeset_ctrl_lock);
mutex_destroy(&sde_crtc->crtc_lock);
kfree(sde_crtc);
}
@@ -4882,6 +4883,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
}
sde_crtc = to_sde_crtc(crtc);
+ mutex_lock(&sde_crtc->vblank_modeset_ctrl_lock);
mutex_lock(&sde_crtc->crtc_lock);
SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled);
ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en);
@@ -4890,6 +4892,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
sde_crtc->name, ret);
mutex_unlock(&sde_crtc->crtc_lock);
+ mutex_unlock(&sde_crtc->vblank_modeset_ctrl_lock);
return 0;
}
@@ -6210,6 +6213,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
mutex_init(&sde_crtc->crtc_lock);
spin_lock_init(&sde_crtc->spin_lock);
atomic_set(&sde_crtc->frame_pending, 0);
+ mutex_init(&sde_crtc->vblank_modeset_ctrl_lock);
sde_crtc->enabled = false;
diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h
index a12f3544..9b18dea1 100644
--- a/msm/sde/sde_crtc.h
+++ b/msm/sde/sde_crtc.h
@@ -236,6 +236,8 @@ struct sde_crtc_misr_info {
* @ad_dirty : list containing ad properties that are dirty
* @ad_active : list containing ad properties that are active
* @crtc_lock : crtc lock around create, destroy and access.
+ * @vblank_modeset_ctrl_lock : lock used for controlling vblank
+ during modeset
* @frame_pending : Whether or not an update is pending
* @frame_events : static allocation of in-flight frame events
* @frame_event_list : available frame event list
@@ -310,6 +312,7 @@ struct sde_crtc {
struct mutex crtc_lock;
struct mutex crtc_cp_lock;
+ struct mutex vblank_modeset_ctrl_lock;
atomic_t frame_pending;
struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE];
diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c
index 7ef4211f..e108b8cb 100644
--- a/msm/sde/sde_encoder.c
+++ b/msm/sde/sde_encoder.c
@@ -82,6 +82,11 @@
((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \
((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC))
+#define REQ_SEAMLESS_MODESET_LOCK(adj_mode, is_cmd_mode) \
+ (msm_is_mode_seamless_dms(adj_mode) || \
+ (msm_is_mode_seamless_dyn_clk(adj_mode) && \
+ is_cmd_mode) || msm_is_mode_seamless_poms(adj_mode))
+
/**
* enum sde_enc_rc_events - events for resource control state machine
* @SDE_ENC_RC_EVENT_KICKOFF:
@@ -2913,9 +2918,12 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
enum sde_intf_mode intf_mode;
bool is_cmd_mode = false;
int i = 0, ret;
+ struct sde_crtc *sde_crtc;
+ bool modeset_lock = false;
- if (!drm_enc) {
- SDE_ERROR("invalid encoder\n");
+ if (!drm_enc || !drm_enc->crtc) {
+ SDE_ERROR("invalid params %d %d\n",
+ !drm_enc, drm_enc ? !drm_enc->crtc : -1);
return;
}
@@ -2936,25 +2944,16 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
SDE_EVT32(DRMID(drm_enc));
- /*
- * cache the crtc in sde_enc on enable for duration of use case
- * for correctly servicing asynchronous irq events and timers
- */
- if (!drm_enc->crtc) {
- SDE_ERROR("invalid crtc\n");
- return;
- }
sde_enc->crtc = drm_enc->crtc;
+ sde_crtc = to_sde_crtc(sde_enc->crtc);
list_for_each_entry(conn_iter, connector_list, head)
if (conn_iter->encoder == drm_enc)
conn = conn_iter;
- if (!conn) {
- SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n");
- return;
- } else if (!conn->state) {
- SDE_ERROR_ENC(sde_enc, "invalid connector state\n");
+ if (!conn || !conn->state) {
+ SDE_ERROR_ENC(sde_enc, "invalid connector %d %d\n",
+ !conn, conn ? !conn->state : -1);
return;
}
@@ -2965,6 +2964,10 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
sde_crtc_set_compression_ratio(sde_enc->mode_info, sde_enc->crtc);
+ modeset_lock = REQ_SEAMLESS_MODESET_LOCK(adj_mode,
+ is_cmd_mode);
+ if (modeset_lock)
+ mutex_lock(&sde_crtc->vblank_modeset_ctrl_lock);
/* release resources before seamless mode change */
if (msm_is_mode_seamless_dms(adj_mode) ||
(msm_is_mode_seamless_dyn_clk(adj_mode) &&
@@ -2978,7 +2981,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
SDE_ERROR_ENC(sde_enc,
"sde resource control failed: %d\n",
ret);
- return;
+ goto exit;
}
/*
@@ -3000,7 +3003,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
if (ret) {
SDE_ERROR_ENC(sde_enc,
"failed to reserve hw resources, %d\n", ret);
- return;
+ goto exit;
}
sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG);
@@ -3056,7 +3059,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) {
SDE_ERROR_ENC(sde_enc,
"invalid pingpong block for the encoder\n");
- return;
+ goto exit;
}
phys->hw_pp = sde_enc->hw_pp[i];
phys->connector = conn->state->connector;
@@ -3077,6 +3080,9 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
else if (msm_is_mode_seamless_poms(adj_mode))
_sde_encoder_modeset_helper_locked(drm_enc,
SDE_ENC_RC_EVENT_POST_MODESET);
+exit:
+ if (modeset_lock)
+ mutex_unlock(&sde_crtc->vblank_modeset_ctrl_lock);
}
void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable)