Loading msm/msm_drv.c +1 −9 Original line number Original line Diff line number Diff line Loading @@ -339,14 +339,6 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv, cur_work->crtc_id = crtc_id; cur_work->crtc_id = crtc_id; cur_work->enable = enable; cur_work->enable = enable; cur_work->priv = priv; cur_work->priv = priv; /* During modeset scenario, vblank request is queued to * display thread to avoid enabling irq resulting in * vblank refcount mismatch */ if (crtc->state && drm_atomic_crtc_needs_modeset(crtc->state)) worker = &priv->disp_thread[crtc_id].worker; else worker = &priv->event_thread[crtc_id].worker; worker = &priv->event_thread[crtc_id].worker; kthread_queue_work(worker, &cur_work->work); kthread_queue_work(worker, &cur_work->work); Loading msm/sde/sde_crtc.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -4839,6 +4839,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) } } sde_crtc = to_sde_crtc(crtc); sde_crtc = to_sde_crtc(crtc); mutex_lock(&sde_crtc->vblank_modeset_ctrl_lock); mutex_lock(&sde_crtc->crtc_lock); mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled); SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled); ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en); ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en); Loading @@ -4847,6 +4848,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) sde_crtc->name, ret); sde_crtc->name, ret); mutex_unlock(&sde_crtc->crtc_lock); mutex_unlock(&sde_crtc->crtc_lock); mutex_unlock(&sde_crtc->vblank_modeset_ctrl_lock); return 0; return 0; } } Loading Loading @@ -6132,6 +6134,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) mutex_init(&sde_crtc->crtc_lock); mutex_init(&sde_crtc->crtc_lock); spin_lock_init(&sde_crtc->spin_lock); spin_lock_init(&sde_crtc->spin_lock); atomic_set(&sde_crtc->frame_pending, 0); atomic_set(&sde_crtc->frame_pending, 0); mutex_init(&sde_crtc->vblank_modeset_ctrl_lock); sde_crtc->enabled = false; sde_crtc->enabled = false; Loading msm/sde/sde_crtc.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -236,6 +236,8 @@ struct sde_crtc_misr_info { * @ad_dirty : list containing ad properties that are dirty * @ad_dirty : list containing ad properties that are dirty * @ad_active : list containing ad properties that are active * @ad_active : list containing ad properties that are active * @crtc_lock : crtc lock around create, destroy and access. * @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_pending : Whether or not an update is pending * @frame_events : static allocation of in-flight frame events * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list * @frame_event_list : available frame event list Loading Loading @@ -309,6 +311,7 @@ struct sde_crtc { struct mutex crtc_lock; struct mutex crtc_lock; struct mutex crtc_cp_lock; struct mutex crtc_cp_lock; struct mutex vblank_modeset_ctrl_lock; atomic_t frame_pending; atomic_t frame_pending; struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; Loading msm/sde/sde_encoder.c +24 −18 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,11 @@ ((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \ ((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \ ((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC)) ((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 * enum sde_enc_rc_events - events for resource control state machine * @SDE_ENC_RC_EVENT_KICKOFF: * @SDE_ENC_RC_EVENT_KICKOFF: Loading Loading @@ -2878,9 +2883,12 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, enum sde_intf_mode intf_mode; enum sde_intf_mode intf_mode; bool is_cmd_mode = false; bool is_cmd_mode = false; int i = 0, ret; int i = 0, ret; struct sde_crtc *sde_crtc; bool modeset_lock = false; if (!drm_enc) { if (!drm_enc || !drm_enc->crtc) { SDE_ERROR("invalid encoder\n"); SDE_ERROR("invalid params %d %d\n", !drm_enc, drm_enc ? !drm_enc->crtc : -1); return; return; } } Loading @@ -2901,25 +2909,16 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, SDE_EVT32(DRMID(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_enc->crtc = drm_enc->crtc; sde_crtc = to_sde_crtc(sde_enc->crtc); list_for_each_entry(conn_iter, connector_list, head) list_for_each_entry(conn_iter, connector_list, head) if (conn_iter->encoder == drm_enc) if (conn_iter->encoder == drm_enc) conn = conn_iter; conn = conn_iter; if (!conn) { if (!conn || !conn->state) { SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n"); SDE_ERROR_ENC(sde_enc, "invalid connector %d %d\n", return; !conn, conn ? !conn->state : -1); } else if (!conn->state) { SDE_ERROR_ENC(sde_enc, "invalid connector state\n"); return; return; } } Loading @@ -2930,6 +2929,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); 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 */ /* release resources before seamless mode change */ if (msm_is_mode_seamless_dms(adj_mode) || if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && (msm_is_mode_seamless_dyn_clk(adj_mode) && Loading @@ -2941,7 +2944,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, SDE_ERROR_ENC(sde_enc, SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", "sde resource control failed: %d\n", ret); ret); return; goto exit; } } /* /* Loading @@ -2961,7 +2964,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, if (ret) { if (ret) { SDE_ERROR_ENC(sde_enc, SDE_ERROR_ENC(sde_enc, "failed to reserve hw resources, %d\n", ret); "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); sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG); Loading Loading @@ -3017,7 +3020,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) { if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) { SDE_ERROR_ENC(sde_enc, SDE_ERROR_ENC(sde_enc, "invalid pingpong block for the encoder\n"); "invalid pingpong block for the encoder\n"); return; goto exit; } } phys->hw_pp = sde_enc->hw_pp[i]; phys->hw_pp = sde_enc->hw_pp[i]; phys->connector = conn->state->connector; phys->connector = conn->state->connector; Loading @@ -3035,6 +3038,9 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, else if (msm_is_mode_seamless_poms(adj_mode)) else if (msm_is_mode_seamless_poms(adj_mode)) _sde_encoder_modeset_helper_locked(drm_enc, _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_POST_MODESET); 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) void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable) Loading Loading
msm/msm_drv.c +1 −9 Original line number Original line Diff line number Diff line Loading @@ -339,14 +339,6 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv, cur_work->crtc_id = crtc_id; cur_work->crtc_id = crtc_id; cur_work->enable = enable; cur_work->enable = enable; cur_work->priv = priv; cur_work->priv = priv; /* During modeset scenario, vblank request is queued to * display thread to avoid enabling irq resulting in * vblank refcount mismatch */ if (crtc->state && drm_atomic_crtc_needs_modeset(crtc->state)) worker = &priv->disp_thread[crtc_id].worker; else worker = &priv->event_thread[crtc_id].worker; worker = &priv->event_thread[crtc_id].worker; kthread_queue_work(worker, &cur_work->work); kthread_queue_work(worker, &cur_work->work); Loading
msm/sde/sde_crtc.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -4839,6 +4839,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) } } sde_crtc = to_sde_crtc(crtc); sde_crtc = to_sde_crtc(crtc); mutex_lock(&sde_crtc->vblank_modeset_ctrl_lock); mutex_lock(&sde_crtc->crtc_lock); mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled); SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled); ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en); ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en); Loading @@ -4847,6 +4848,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) sde_crtc->name, ret); sde_crtc->name, ret); mutex_unlock(&sde_crtc->crtc_lock); mutex_unlock(&sde_crtc->crtc_lock); mutex_unlock(&sde_crtc->vblank_modeset_ctrl_lock); return 0; return 0; } } Loading Loading @@ -6132,6 +6134,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) mutex_init(&sde_crtc->crtc_lock); mutex_init(&sde_crtc->crtc_lock); spin_lock_init(&sde_crtc->spin_lock); spin_lock_init(&sde_crtc->spin_lock); atomic_set(&sde_crtc->frame_pending, 0); atomic_set(&sde_crtc->frame_pending, 0); mutex_init(&sde_crtc->vblank_modeset_ctrl_lock); sde_crtc->enabled = false; sde_crtc->enabled = false; Loading
msm/sde/sde_crtc.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -236,6 +236,8 @@ struct sde_crtc_misr_info { * @ad_dirty : list containing ad properties that are dirty * @ad_dirty : list containing ad properties that are dirty * @ad_active : list containing ad properties that are active * @ad_active : list containing ad properties that are active * @crtc_lock : crtc lock around create, destroy and access. * @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_pending : Whether or not an update is pending * @frame_events : static allocation of in-flight frame events * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list * @frame_event_list : available frame event list Loading Loading @@ -309,6 +311,7 @@ struct sde_crtc { struct mutex crtc_lock; struct mutex crtc_lock; struct mutex crtc_cp_lock; struct mutex crtc_cp_lock; struct mutex vblank_modeset_ctrl_lock; atomic_t frame_pending; atomic_t frame_pending; struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; Loading
msm/sde/sde_encoder.c +24 −18 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,11 @@ ((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \ ((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \ ((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC)) ((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 * enum sde_enc_rc_events - events for resource control state machine * @SDE_ENC_RC_EVENT_KICKOFF: * @SDE_ENC_RC_EVENT_KICKOFF: Loading Loading @@ -2878,9 +2883,12 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, enum sde_intf_mode intf_mode; enum sde_intf_mode intf_mode; bool is_cmd_mode = false; bool is_cmd_mode = false; int i = 0, ret; int i = 0, ret; struct sde_crtc *sde_crtc; bool modeset_lock = false; if (!drm_enc) { if (!drm_enc || !drm_enc->crtc) { SDE_ERROR("invalid encoder\n"); SDE_ERROR("invalid params %d %d\n", !drm_enc, drm_enc ? !drm_enc->crtc : -1); return; return; } } Loading @@ -2901,25 +2909,16 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, SDE_EVT32(DRMID(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_enc->crtc = drm_enc->crtc; sde_crtc = to_sde_crtc(sde_enc->crtc); list_for_each_entry(conn_iter, connector_list, head) list_for_each_entry(conn_iter, connector_list, head) if (conn_iter->encoder == drm_enc) if (conn_iter->encoder == drm_enc) conn = conn_iter; conn = conn_iter; if (!conn) { if (!conn || !conn->state) { SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n"); SDE_ERROR_ENC(sde_enc, "invalid connector %d %d\n", return; !conn, conn ? !conn->state : -1); } else if (!conn->state) { SDE_ERROR_ENC(sde_enc, "invalid connector state\n"); return; return; } } Loading @@ -2930,6 +2929,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); 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 */ /* release resources before seamless mode change */ if (msm_is_mode_seamless_dms(adj_mode) || if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && (msm_is_mode_seamless_dyn_clk(adj_mode) && Loading @@ -2941,7 +2944,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, SDE_ERROR_ENC(sde_enc, SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", "sde resource control failed: %d\n", ret); ret); return; goto exit; } } /* /* Loading @@ -2961,7 +2964,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, if (ret) { if (ret) { SDE_ERROR_ENC(sde_enc, SDE_ERROR_ENC(sde_enc, "failed to reserve hw resources, %d\n", ret); "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); sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG); Loading Loading @@ -3017,7 +3020,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) { if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) { SDE_ERROR_ENC(sde_enc, SDE_ERROR_ENC(sde_enc, "invalid pingpong block for the encoder\n"); "invalid pingpong block for the encoder\n"); return; goto exit; } } phys->hw_pp = sde_enc->hw_pp[i]; phys->hw_pp = sde_enc->hw_pp[i]; phys->connector = conn->state->connector; phys->connector = conn->state->connector; Loading @@ -3035,6 +3038,9 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, else if (msm_is_mode_seamless_poms(adj_mode)) else if (msm_is_mode_seamless_poms(adj_mode)) _sde_encoder_modeset_helper_locked(drm_enc, _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_POST_MODESET); 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) void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable) Loading