Loading drivers/gpu/drm/msm/sde/sde_connector.c +1 −0 Original line number Diff line number Diff line Loading @@ -1736,6 +1736,7 @@ static void sde_connector_check_status_work(struct work_struct *work) event.length = sizeof(bool); msm_mode_object_event_notify(&conn->base.base, conn->base.dev, &event, (u8 *)&panel_dead); sde_encoder_display_failure_notification(conn->encoder); } static const struct drm_connector_helper_funcs sde_connector_helper_ops = { Loading drivers/gpu/drm/msm/sde/sde_encoder.c +43 −1 Original line number Diff line number Diff line Loading @@ -1513,6 +1513,29 @@ static int _sde_encoder_dsc_disable(struct sde_encoder_virt *sde_enc) return ret; } static int _sde_encoder_switch_to_watchdog_vsync(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; struct msm_display_info disp_info; if (!drm_enc) { pr_err("invalid drm encoder\n"); return -EINVAL; } sde_enc = to_sde_encoder_virt(drm_enc); sde_encoder_control_te(drm_enc, false); memcpy(&disp_info, &sde_enc->disp_info, sizeof(disp_info)); disp_info.is_te_using_watchdog_timer = true; _sde_encoder_update_vsync_source(sde_enc, &disp_info, false); sde_encoder_control_te(drm_enc, true); return 0; } static int _sde_encoder_update_rsc_client( struct drm_encoder *drm_enc, struct sde_encoder_rsc_config *config, bool enable) Loading Loading @@ -1652,7 +1675,12 @@ static int _sde_encoder_update_rsc_client( if (ret) { SDE_ERROR_ENC(sde_enc, "wait for vblank failed ret:%d\n", ret); break; /** * rsc hardware may hang without vsync. avoid rsc hang * by generating the vsync from watchdog timer. */ if (crtc->base.id == wait_vblank_crtc_id) _sde_encoder_switch_to_watchdog_vsync(drm_enc); } } Loading Loading @@ -4758,3 +4786,17 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder) return ret; } int sde_encoder_display_failure_notification(struct drm_encoder *enc) { /** * panel may stop generating te signal (vsync) during esd failure. rsc * hardware may hang without vsync. Avoid rsc hang by generating the * vsync from watchdog timer instead of panel. */ _sde_encoder_switch_to_watchdog_vsync(enc); sde_encoder_wait_for_event(enc, MSM_ENC_TX_COMPLETE); return 0; } drivers/gpu/drm/msm/sde/sde_encoder.h +10 −0 Original line number Diff line number Diff line Loading @@ -237,4 +237,14 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc); */ 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. * 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 */ int sde_encoder_display_failure_notification(struct drm_encoder *enc); #endif /* __SDE_ENCODER_H__ */ drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +12 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -450,6 +450,17 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( cmd_enc->pp_timeout_report_cnt++; if (sde_encoder_phys_cmd_is_master(phys_enc)) { /* trigger the retire fence if it was missed */ if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); } SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, atomic_read(&phys_enc->pending_kickoff_cnt), Loading Loading
drivers/gpu/drm/msm/sde/sde_connector.c +1 −0 Original line number Diff line number Diff line Loading @@ -1736,6 +1736,7 @@ static void sde_connector_check_status_work(struct work_struct *work) event.length = sizeof(bool); msm_mode_object_event_notify(&conn->base.base, conn->base.dev, &event, (u8 *)&panel_dead); sde_encoder_display_failure_notification(conn->encoder); } static const struct drm_connector_helper_funcs sde_connector_helper_ops = { Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +43 −1 Original line number Diff line number Diff line Loading @@ -1513,6 +1513,29 @@ static int _sde_encoder_dsc_disable(struct sde_encoder_virt *sde_enc) return ret; } static int _sde_encoder_switch_to_watchdog_vsync(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; struct msm_display_info disp_info; if (!drm_enc) { pr_err("invalid drm encoder\n"); return -EINVAL; } sde_enc = to_sde_encoder_virt(drm_enc); sde_encoder_control_te(drm_enc, false); memcpy(&disp_info, &sde_enc->disp_info, sizeof(disp_info)); disp_info.is_te_using_watchdog_timer = true; _sde_encoder_update_vsync_source(sde_enc, &disp_info, false); sde_encoder_control_te(drm_enc, true); return 0; } static int _sde_encoder_update_rsc_client( struct drm_encoder *drm_enc, struct sde_encoder_rsc_config *config, bool enable) Loading Loading @@ -1652,7 +1675,12 @@ static int _sde_encoder_update_rsc_client( if (ret) { SDE_ERROR_ENC(sde_enc, "wait for vblank failed ret:%d\n", ret); break; /** * rsc hardware may hang without vsync. avoid rsc hang * by generating the vsync from watchdog timer. */ if (crtc->base.id == wait_vblank_crtc_id) _sde_encoder_switch_to_watchdog_vsync(drm_enc); } } Loading Loading @@ -4758,3 +4786,17 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder) return ret; } int sde_encoder_display_failure_notification(struct drm_encoder *enc) { /** * panel may stop generating te signal (vsync) during esd failure. rsc * hardware may hang without vsync. Avoid rsc hang by generating the * vsync from watchdog timer instead of panel. */ _sde_encoder_switch_to_watchdog_vsync(enc); sde_encoder_wait_for_event(enc, MSM_ENC_TX_COMPLETE); return 0; }
drivers/gpu/drm/msm/sde/sde_encoder.h +10 −0 Original line number Diff line number Diff line Loading @@ -237,4 +237,14 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc); */ 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. * 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 */ int sde_encoder_display_failure_notification(struct drm_encoder *enc); #endif /* __SDE_ENCODER_H__ */
drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +12 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -450,6 +450,17 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( cmd_enc->pp_timeout_report_cnt++; if (sde_encoder_phys_cmd_is_master(phys_enc)) { /* trigger the retire fence if it was missed */ if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0); } SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, atomic_read(&phys_enc->pending_kickoff_cnt), Loading