Loading drivers/gpu/drm/msm/sde/sde_crtc.c +58 −23 Original line number Diff line number Diff line Loading @@ -1517,7 +1517,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) struct sde_crtc_state *cstate; struct sde_kms *sde_kms; unsigned long flags; bool disable_inprogress = false; if (!work) { SDE_ERROR("invalid work handle\n"); Loading @@ -1543,9 +1542,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) SDE_DEBUG("crtc%d event:%u ts:%lld\n", crtc->base.id, fevent->event, ktime_to_ns(fevent->ts)); disable_inprogress = fevent->event & SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; fevent->event &= ~SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE || (fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR) || Loading @@ -1566,15 +1562,17 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) ktime_to_ns(fevent->ts)); SDE_EVT32(DRMID(crtc), fevent->event, SDE_EVTLOG_FUNC_CASE2); if (!disable_inprogress) sde_core_perf_crtc_release_bw(crtc); } else { SDE_EVT32_VERBOSE(DRMID(crtc), fevent->event, SDE_EVTLOG_FUNC_CASE3); } if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE && !disable_inprogress) if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE || (fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR)) complete_all(&sde_crtc->frame_done_comp); if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE) sde_core_perf_crtc_update(crtc, 0, false); } else { SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id, Loading Loading @@ -1629,11 +1627,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event) fevent->event = event; fevent->crtc = crtc; fevent->ts = ktime_get(); if (event & SDE_ENCODER_FRAME_EVENT_DURING_DISABLE) sde_crtc_frame_event_work(&fevent->work); else kthread_queue_work(&priv->disp_thread[pipe_id].worker, &fevent->work); kthread_queue_work(&sde_crtc->event_worker, &fevent->work); } void sde_crtc_complete_commit(struct drm_crtc *crtc, Loading Loading @@ -2085,6 +2079,36 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc, cstate->property_values, cstate->property_blobs); } static int _sde_crtc_wait_for_frame_done(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; int ret, rc = 0; if (!crtc) { SDE_ERROR("invalid argument\n"); return -EINVAL; } sde_crtc = to_sde_crtc(crtc); if (!atomic_read(&sde_crtc->frame_pending)) { SDE_DEBUG("no frames pending\n"); return 0; } SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_ENTRY); ret = wait_for_completion_timeout(&sde_crtc->frame_done_comp, msecs_to_jiffies(SDE_FRAME_DONE_TIMEOUT)); if (!ret) { SDE_ERROR("frame done completion wait timed out, ret:%d\n", ret); SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FATAL); rc = -ETIMEDOUT; } SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT); return rc; } void sde_crtc_commit_kickoff(struct drm_crtc *crtc) { struct drm_encoder *encoder; Loading Loading @@ -2129,19 +2153,21 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) sde_encoder_prepare_for_kickoff(encoder, ¶ms); } if (atomic_read(&sde_crtc->frame_pending) > 2) { /* framework allows only 1 outstanding + current */ SDE_ERROR("crtc%d invalid frame pending\n", crtc->base.id); SDE_EVT32(DRMID(crtc), 0); /* wait for frame_event_done completion */ if (_sde_crtc_wait_for_frame_done(crtc)) { SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n", crtc->base.id, atomic_read(&sde_crtc->frame_pending)); goto end; } else if (atomic_inc_return(&sde_crtc->frame_pending) == 1) { } if (atomic_inc_return(&sde_crtc->frame_pending) == 1) { /* acquire bandwidth and other resources */ SDE_DEBUG("crtc%d first commit\n", crtc->base.id); SDE_EVT32(DRMID(crtc), 1); SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_CASE1); } else { SDE_DEBUG("crtc%d commit\n", crtc->base.id); SDE_EVT32(DRMID(crtc), 2); SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_CASE2); } sde_crtc->play_count++; Loading @@ -2151,6 +2177,9 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) sde_encoder_kickoff(encoder); } reinit_completion(&sde_crtc->frame_done_comp); end: SDE_ATRACE_END("crtc_commit"); return; Loading Loading @@ -2444,6 +2473,12 @@ static void sde_crtc_disable(struct drm_crtc *crtc) mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(crtc)); /* wait for frame_event_done completion */ if (_sde_crtc_wait_for_frame_done(crtc)) SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n", crtc->base.id, atomic_read(&sde_crtc->frame_pending)); if (atomic_read(&sde_crtc->vblank_refcount) && !sde_crtc->suspend) { SDE_ERROR("crtc%d invalid vblank refcount\n", crtc->base.id); Loading @@ -2455,8 +2490,6 @@ static void sde_crtc_disable(struct drm_crtc *crtc) } if (atomic_read(&sde_crtc->frame_pending)) { /* release bandwidth and other resources */ SDE_ERROR("crtc%d invalid frame pending\n", crtc->base.id); SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->frame_pending), SDE_EVTLOG_FUNC_CASE2); sde_core_perf_crtc_release_bw(crtc); Loading Loading @@ -3714,6 +3747,8 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) spin_lock_init(&sde_crtc->spin_lock); atomic_set(&sde_crtc->frame_pending, 0); init_completion(&sde_crtc->frame_done_comp); INIT_LIST_HEAD(&sde_crtc->frame_event_list); INIT_LIST_HEAD(&sde_crtc->user_event_list); for (i = 0; i < ARRAY_SIZE(sde_crtc->frame_events); i++) { Loading drivers/gpu/drm/msm/sde/sde_crtc.h +2 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ struct sde_crtc_event { * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list * @spin_lock : spin lock for frame event, transaction status, etc... * @frame_done_comp : for frame_event_done synchronization * @event_thread : Pointer to event handler thread * @event_worker : Event worker queue * @event_cache : Local cache of event worker structures Loading Loading @@ -186,6 +187,7 @@ struct sde_crtc { struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; struct list_head frame_event_list; spinlock_t spin_lock; struct completion frame_done_comp; /* for handling internal event thread */ struct task_struct *event_thread; Loading drivers/gpu/drm/msm/sde/sde_encoder.c +2 −15 Original line number Diff line number Diff line Loading @@ -56,9 +56,6 @@ (p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \ ##__VA_ARGS__) /* timeout in frames waiting for frame done */ #define SDE_ENCODER_FRAME_DONE_TIMEOUT 60 /* * Two to anticipate panels that can do cmd/vid dynamic switching * plan is to create all possible physical encoder types, and switch between Loading Loading @@ -173,7 +170,6 @@ enum sde_enc_rc_states { * @rsc_cfg: rsc configuration * @cur_conn_roi: current connector roi * @prv_conn_roi: previous connector roi to optimize if unchanged * @disable_inprogress: sde encoder disable is in progress. */ struct sde_encoder_virt { struct drm_encoder base; Loading Loading @@ -217,7 +213,6 @@ struct sde_encoder_virt { struct sde_encoder_rsc_config rsc_cfg; struct sde_rect cur_conn_roi; struct sde_rect prv_conn_roi; bool disable_inprogress; }; #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) Loading Loading @@ -1643,7 +1638,6 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) SDE_EVT32(DRMID(drm_enc)); sde_enc->cur_master = NULL; sde_enc->disable_inprogress = false; for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading Loading @@ -1702,7 +1696,6 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) priv = drm_enc->dev->dev_private; sde_kms = to_sde_kms(priv->kms); sde_enc->disable_inprogress = true; SDE_EVT32(DRMID(drm_enc)); Loading Loading @@ -1868,9 +1861,6 @@ static void sde_encoder_frame_done_callback( sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); if (sde_enc->disable_inprogress) event |= SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; if (sde_enc->crtc_frame_event_cb) sde_enc->crtc_frame_event_cb( sde_enc->crtc_frame_event_cb_data, event); Loading Loading @@ -2332,7 +2322,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc) SDE_DEBUG_ENC(sde_enc, "\n"); atomic_set(&sde_enc->frame_done_timeout, SDE_ENCODER_FRAME_DONE_TIMEOUT * 1000 / SDE_FRAME_DONE_TIMEOUT * 1000 / drm_enc->crtc->state->adjusted_mode.vrefresh); mod_timer(&sde_enc->frame_done_timer, jiffies + ((atomic_read(&sde_enc->frame_done_timeout) * HZ) / 1000)); Loading Loading @@ -2913,9 +2903,6 @@ static void sde_encoder_frame_done_timeout(unsigned long data) SDE_ERROR_ENC(sde_enc, "frame done timeout\n"); event = SDE_ENCODER_FRAME_EVENT_ERROR; if (sde_enc->disable_inprogress) event |= SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; SDE_EVT32(DRMID(drm_enc), event); sde_enc->crtc_frame_event_cb(sde_enc->crtc_frame_event_cb_data, event); } Loading drivers/gpu/drm/msm/sde/sde_encoder.h +0 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ #define SDE_ENCODER_FRAME_EVENT_DONE BIT(0) #define SDE_ENCODER_FRAME_EVENT_ERROR BIT(1) #define SDE_ENCODER_FRAME_EVENT_PANEL_DEAD BIT(2) #define SDE_ENCODER_FRAME_EVENT_DURING_DISABLE BIT(3) /** * Encoder functions and data types Loading drivers/gpu/drm/msm/sde/sde_kms.h +4 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,10 @@ #define SDE_NAME_SIZE 12 /* timeout in frames waiting for frame done */ #define SDE_FRAME_DONE_TIMEOUT 60 /* * struct sde_irq_callback - IRQ callback handlers * @list: list to callback Loading Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +58 −23 Original line number Diff line number Diff line Loading @@ -1517,7 +1517,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) struct sde_crtc_state *cstate; struct sde_kms *sde_kms; unsigned long flags; bool disable_inprogress = false; if (!work) { SDE_ERROR("invalid work handle\n"); Loading @@ -1543,9 +1542,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) SDE_DEBUG("crtc%d event:%u ts:%lld\n", crtc->base.id, fevent->event, ktime_to_ns(fevent->ts)); disable_inprogress = fevent->event & SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; fevent->event &= ~SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE || (fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR) || Loading @@ -1566,15 +1562,17 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) ktime_to_ns(fevent->ts)); SDE_EVT32(DRMID(crtc), fevent->event, SDE_EVTLOG_FUNC_CASE2); if (!disable_inprogress) sde_core_perf_crtc_release_bw(crtc); } else { SDE_EVT32_VERBOSE(DRMID(crtc), fevent->event, SDE_EVTLOG_FUNC_CASE3); } if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE && !disable_inprogress) if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE || (fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR)) complete_all(&sde_crtc->frame_done_comp); if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE) sde_core_perf_crtc_update(crtc, 0, false); } else { SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id, Loading Loading @@ -1629,11 +1627,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event) fevent->event = event; fevent->crtc = crtc; fevent->ts = ktime_get(); if (event & SDE_ENCODER_FRAME_EVENT_DURING_DISABLE) sde_crtc_frame_event_work(&fevent->work); else kthread_queue_work(&priv->disp_thread[pipe_id].worker, &fevent->work); kthread_queue_work(&sde_crtc->event_worker, &fevent->work); } void sde_crtc_complete_commit(struct drm_crtc *crtc, Loading Loading @@ -2085,6 +2079,36 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc, cstate->property_values, cstate->property_blobs); } static int _sde_crtc_wait_for_frame_done(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; int ret, rc = 0; if (!crtc) { SDE_ERROR("invalid argument\n"); return -EINVAL; } sde_crtc = to_sde_crtc(crtc); if (!atomic_read(&sde_crtc->frame_pending)) { SDE_DEBUG("no frames pending\n"); return 0; } SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_ENTRY); ret = wait_for_completion_timeout(&sde_crtc->frame_done_comp, msecs_to_jiffies(SDE_FRAME_DONE_TIMEOUT)); if (!ret) { SDE_ERROR("frame done completion wait timed out, ret:%d\n", ret); SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FATAL); rc = -ETIMEDOUT; } SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT); return rc; } void sde_crtc_commit_kickoff(struct drm_crtc *crtc) { struct drm_encoder *encoder; Loading Loading @@ -2129,19 +2153,21 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) sde_encoder_prepare_for_kickoff(encoder, ¶ms); } if (atomic_read(&sde_crtc->frame_pending) > 2) { /* framework allows only 1 outstanding + current */ SDE_ERROR("crtc%d invalid frame pending\n", crtc->base.id); SDE_EVT32(DRMID(crtc), 0); /* wait for frame_event_done completion */ if (_sde_crtc_wait_for_frame_done(crtc)) { SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n", crtc->base.id, atomic_read(&sde_crtc->frame_pending)); goto end; } else if (atomic_inc_return(&sde_crtc->frame_pending) == 1) { } if (atomic_inc_return(&sde_crtc->frame_pending) == 1) { /* acquire bandwidth and other resources */ SDE_DEBUG("crtc%d first commit\n", crtc->base.id); SDE_EVT32(DRMID(crtc), 1); SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_CASE1); } else { SDE_DEBUG("crtc%d commit\n", crtc->base.id); SDE_EVT32(DRMID(crtc), 2); SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_CASE2); } sde_crtc->play_count++; Loading @@ -2151,6 +2177,9 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) sde_encoder_kickoff(encoder); } reinit_completion(&sde_crtc->frame_done_comp); end: SDE_ATRACE_END("crtc_commit"); return; Loading Loading @@ -2444,6 +2473,12 @@ static void sde_crtc_disable(struct drm_crtc *crtc) mutex_lock(&sde_crtc->crtc_lock); SDE_EVT32(DRMID(crtc)); /* wait for frame_event_done completion */ if (_sde_crtc_wait_for_frame_done(crtc)) SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n", crtc->base.id, atomic_read(&sde_crtc->frame_pending)); if (atomic_read(&sde_crtc->vblank_refcount) && !sde_crtc->suspend) { SDE_ERROR("crtc%d invalid vblank refcount\n", crtc->base.id); Loading @@ -2455,8 +2490,6 @@ static void sde_crtc_disable(struct drm_crtc *crtc) } if (atomic_read(&sde_crtc->frame_pending)) { /* release bandwidth and other resources */ SDE_ERROR("crtc%d invalid frame pending\n", crtc->base.id); SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->frame_pending), SDE_EVTLOG_FUNC_CASE2); sde_core_perf_crtc_release_bw(crtc); Loading Loading @@ -3714,6 +3747,8 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) spin_lock_init(&sde_crtc->spin_lock); atomic_set(&sde_crtc->frame_pending, 0); init_completion(&sde_crtc->frame_done_comp); INIT_LIST_HEAD(&sde_crtc->frame_event_list); INIT_LIST_HEAD(&sde_crtc->user_event_list); for (i = 0; i < ARRAY_SIZE(sde_crtc->frame_events); i++) { Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +2 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ struct sde_crtc_event { * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list * @spin_lock : spin lock for frame event, transaction status, etc... * @frame_done_comp : for frame_event_done synchronization * @event_thread : Pointer to event handler thread * @event_worker : Event worker queue * @event_cache : Local cache of event worker structures Loading Loading @@ -186,6 +187,7 @@ struct sde_crtc { struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; struct list_head frame_event_list; spinlock_t spin_lock; struct completion frame_done_comp; /* for handling internal event thread */ struct task_struct *event_thread; Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +2 −15 Original line number Diff line number Diff line Loading @@ -56,9 +56,6 @@ (p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \ ##__VA_ARGS__) /* timeout in frames waiting for frame done */ #define SDE_ENCODER_FRAME_DONE_TIMEOUT 60 /* * Two to anticipate panels that can do cmd/vid dynamic switching * plan is to create all possible physical encoder types, and switch between Loading Loading @@ -173,7 +170,6 @@ enum sde_enc_rc_states { * @rsc_cfg: rsc configuration * @cur_conn_roi: current connector roi * @prv_conn_roi: previous connector roi to optimize if unchanged * @disable_inprogress: sde encoder disable is in progress. */ struct sde_encoder_virt { struct drm_encoder base; Loading Loading @@ -217,7 +213,6 @@ struct sde_encoder_virt { struct sde_encoder_rsc_config rsc_cfg; struct sde_rect cur_conn_roi; struct sde_rect prv_conn_roi; bool disable_inprogress; }; #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) Loading Loading @@ -1643,7 +1638,6 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) SDE_EVT32(DRMID(drm_enc)); sde_enc->cur_master = NULL; sde_enc->disable_inprogress = false; for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading Loading @@ -1702,7 +1696,6 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) priv = drm_enc->dev->dev_private; sde_kms = to_sde_kms(priv->kms); sde_enc->disable_inprogress = true; SDE_EVT32(DRMID(drm_enc)); Loading Loading @@ -1868,9 +1861,6 @@ static void sde_encoder_frame_done_callback( sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); if (sde_enc->disable_inprogress) event |= SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; if (sde_enc->crtc_frame_event_cb) sde_enc->crtc_frame_event_cb( sde_enc->crtc_frame_event_cb_data, event); Loading Loading @@ -2332,7 +2322,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc) SDE_DEBUG_ENC(sde_enc, "\n"); atomic_set(&sde_enc->frame_done_timeout, SDE_ENCODER_FRAME_DONE_TIMEOUT * 1000 / SDE_FRAME_DONE_TIMEOUT * 1000 / drm_enc->crtc->state->adjusted_mode.vrefresh); mod_timer(&sde_enc->frame_done_timer, jiffies + ((atomic_read(&sde_enc->frame_done_timeout) * HZ) / 1000)); Loading Loading @@ -2913,9 +2903,6 @@ static void sde_encoder_frame_done_timeout(unsigned long data) SDE_ERROR_ENC(sde_enc, "frame done timeout\n"); event = SDE_ENCODER_FRAME_EVENT_ERROR; if (sde_enc->disable_inprogress) event |= SDE_ENCODER_FRAME_EVENT_DURING_DISABLE; SDE_EVT32(DRMID(drm_enc), event); sde_enc->crtc_frame_event_cb(sde_enc->crtc_frame_event_cb_data, event); } Loading
drivers/gpu/drm/msm/sde/sde_encoder.h +0 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ #define SDE_ENCODER_FRAME_EVENT_DONE BIT(0) #define SDE_ENCODER_FRAME_EVENT_ERROR BIT(1) #define SDE_ENCODER_FRAME_EVENT_PANEL_DEAD BIT(2) #define SDE_ENCODER_FRAME_EVENT_DURING_DISABLE BIT(3) /** * Encoder functions and data types Loading
drivers/gpu/drm/msm/sde/sde_kms.h +4 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,10 @@ #define SDE_NAME_SIZE 12 /* timeout in frames waiting for frame done */ #define SDE_FRAME_DONE_TIMEOUT 60 /* * struct sde_irq_callback - IRQ callback handlers * @list: list to callback Loading