Loading drivers/gpu/drm/msm/sde/sde_encoder.c +46 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,7 @@ enum sde_enc_rc_states { * clks and resources after IDLE_TIMEOUT time. * @vsync_event_work: worker to handle vsync event for autorefresh * @input_event_work: worker to handle input device touch events * @esd_trigger_work: worker to handle esd trigger events * @input_handler: handler for input device events * @topology: topology of the display * @vblank_enabled: boolean to track userspace vblank vote Loading Loading @@ -249,6 +250,7 @@ struct sde_encoder_virt { struct kthread_delayed_work delayed_off_work; struct kthread_work vsync_event_work; struct kthread_work input_event_work; struct kthread_work esd_trigger_work; struct input_handler *input_handler; struct msm_display_topology topology; bool vblank_enabled; Loading Loading @@ -3539,6 +3541,20 @@ static void sde_encoder_vsync_event_handler(unsigned long data) &sde_enc->vsync_event_work); } static void sde_encoder_esd_trigger_work_handler(struct kthread_work *work) { struct sde_encoder_virt *sde_enc = container_of(work, struct sde_encoder_virt, esd_trigger_work); if (!sde_enc) { SDE_ERROR("invalid sde encoder\n"); return; } sde_encoder_resource_control(&sde_enc->base, SDE_ENC_RC_EVENT_KICKOFF); } static void sde_encoder_input_event_work_handler(struct kthread_work *work) { struct sde_encoder_virt *sde_enc = container_of(work, Loading Loading @@ -4528,6 +4544,9 @@ struct drm_encoder *sde_encoder_init( kthread_init_work(&sde_enc->input_event_work, sde_encoder_input_event_work_handler); kthread_init_work(&sde_enc->esd_trigger_work, sde_encoder_esd_trigger_work_handler); memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info)); SDE_DEBUG_ENC(sde_enc, "created\n"); Loading Loading @@ -4789,6 +4808,33 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder) int sde_encoder_display_failure_notification(struct drm_encoder *enc) { struct msm_drm_thread *disp_thread = NULL; struct msm_drm_private *priv = NULL; struct sde_encoder_virt *sde_enc = NULL; if (!enc || !enc->dev || !enc->dev->dev_private) { SDE_ERROR("invalid parameters\n"); return -EINVAL; } priv = enc->dev->dev_private; sde_enc = to_sde_encoder_virt(enc); if (!sde_enc->crtc || (sde_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread))) { SDE_DEBUG_ENC(sde_enc, "invalid cached CRTC: %d or crtc index: %d\n", sde_enc->crtc == NULL, sde_enc->crtc ? sde_enc->crtc->index : -EINVAL); return -EINVAL; } SDE_EVT32_VERBOSE(DRMID(enc)); disp_thread = &priv->disp_thread[sde_enc->crtc->index]; kthread_queue_work(&disp_thread->worker, &sde_enc->esd_trigger_work); kthread_flush_work(&sde_enc->esd_trigger_work); /** * panel may stop generating te signal (vsync) during esd failure. rsc * hardware may hang without vsync. Avoid rsc hang by generating the Loading drivers/gpu/drm/msm/sde/sde_encoder.h +5 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,11 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder); * sde_encoder_display_failure_notification - update sde encoder state for * esd timeout or other display failure notification. This event flows from * dsi, sde_connector to sde_encoder. * * This api must not be called from crtc_commit (display) thread because it * requests the flush work on same thread. It is called from esd check thread * based on current design. * * TODO: manage the event at sde_kms level for forward processing. * @drm_enc: Pointer to drm encoder structure * @Return: true if successful in updating the encoder structure Loading Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +46 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,7 @@ enum sde_enc_rc_states { * clks and resources after IDLE_TIMEOUT time. * @vsync_event_work: worker to handle vsync event for autorefresh * @input_event_work: worker to handle input device touch events * @esd_trigger_work: worker to handle esd trigger events * @input_handler: handler for input device events * @topology: topology of the display * @vblank_enabled: boolean to track userspace vblank vote Loading Loading @@ -249,6 +250,7 @@ struct sde_encoder_virt { struct kthread_delayed_work delayed_off_work; struct kthread_work vsync_event_work; struct kthread_work input_event_work; struct kthread_work esd_trigger_work; struct input_handler *input_handler; struct msm_display_topology topology; bool vblank_enabled; Loading Loading @@ -3539,6 +3541,20 @@ static void sde_encoder_vsync_event_handler(unsigned long data) &sde_enc->vsync_event_work); } static void sde_encoder_esd_trigger_work_handler(struct kthread_work *work) { struct sde_encoder_virt *sde_enc = container_of(work, struct sde_encoder_virt, esd_trigger_work); if (!sde_enc) { SDE_ERROR("invalid sde encoder\n"); return; } sde_encoder_resource_control(&sde_enc->base, SDE_ENC_RC_EVENT_KICKOFF); } static void sde_encoder_input_event_work_handler(struct kthread_work *work) { struct sde_encoder_virt *sde_enc = container_of(work, Loading Loading @@ -4528,6 +4544,9 @@ struct drm_encoder *sde_encoder_init( kthread_init_work(&sde_enc->input_event_work, sde_encoder_input_event_work_handler); kthread_init_work(&sde_enc->esd_trigger_work, sde_encoder_esd_trigger_work_handler); memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info)); SDE_DEBUG_ENC(sde_enc, "created\n"); Loading Loading @@ -4789,6 +4808,33 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder) int sde_encoder_display_failure_notification(struct drm_encoder *enc) { struct msm_drm_thread *disp_thread = NULL; struct msm_drm_private *priv = NULL; struct sde_encoder_virt *sde_enc = NULL; if (!enc || !enc->dev || !enc->dev->dev_private) { SDE_ERROR("invalid parameters\n"); return -EINVAL; } priv = enc->dev->dev_private; sde_enc = to_sde_encoder_virt(enc); if (!sde_enc->crtc || (sde_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread))) { SDE_DEBUG_ENC(sde_enc, "invalid cached CRTC: %d or crtc index: %d\n", sde_enc->crtc == NULL, sde_enc->crtc ? sde_enc->crtc->index : -EINVAL); return -EINVAL; } SDE_EVT32_VERBOSE(DRMID(enc)); disp_thread = &priv->disp_thread[sde_enc->crtc->index]; kthread_queue_work(&disp_thread->worker, &sde_enc->esd_trigger_work); kthread_flush_work(&sde_enc->esd_trigger_work); /** * panel may stop generating te signal (vsync) during esd failure. rsc * hardware may hang without vsync. Avoid rsc hang by generating the Loading
drivers/gpu/drm/msm/sde/sde_encoder.h +5 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,11 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder); * sde_encoder_display_failure_notification - update sde encoder state for * esd timeout or other display failure notification. This event flows from * dsi, sde_connector to sde_encoder. * * This api must not be called from crtc_commit (display) thread because it * requests the flush work on same thread. It is called from esd check thread * based on current design. * * TODO: manage the event at sde_kms level for forward processing. * @drm_enc: Pointer to drm encoder structure * @Return: true if successful in updating the encoder structure Loading