diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2020-06-10 06:53:25 +0000 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2020-06-10 06:53:25 +0000 |
commit | a0bd65d5eafce0c91b3d6be4018ae99cafa4bc25 (patch) | |
tree | ba0a92f034a888c38f5a9ae9cfe414b9e399c6db | |
parent | e4a201b78df3f1c9dedc699087a6af594e7aac7c (diff) | |
parent | 266d9bd11995d8734b2228fbe945ab35e145af33 (diff) | |
download | display-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.c | 9 | ||||
-rw-r--r-- | msm/sde/sde_crtc.c | 4 | ||||
-rw-r--r-- | msm/sde/sde_crtc.h | 3 | ||||
-rw-r--r-- | msm/sde/sde_encoder.c | 42 |
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) |