diff options
author | Dave Airlie <airlied@redhat.com> | 2021-06-24 07:15:17 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2021-06-24 07:21:16 +1000 |
commit | 334200bf52f0637a5ab8331c557dfcecbb9c30fa (patch) | |
tree | 506009c182f6204a0998e2b892716bfa8cbac6e0 /drivers/gpu/drm/msm/dp/dp_display.c | |
parent | 61c0cb8ae7943b4fad5d62213c1748f1a07fe594 (diff) | |
parent | e88bbc91849b2bf57683119c339e52916d34433f (diff) |
Merge tag 'drm-msm-next-2021-06-23b' of https://gitlab.freedesktop.org/drm/msm into drm-next
* devcoredump support for display errors
* dpu: irq cleanup/refactor
* dpu: dt bindings conversion to yaml
* dsi: dt bindings conversion to yaml
* mdp5: alpha/blend_mode/zpos support
* a6xx: cached coherent buffer support
* a660 support
* gpu iova fault improvements:
- info about which block triggered the fault, etc
- generation of gpu devcoredump on fault
* assortment of other cleanups and fixes
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGs4=qsGBBbyn-4JWqW4-YUSTKh67X3DsPQ=T2D9aXKqNA@mail.gmail.com
Diffstat (limited to 'drivers/gpu/drm/msm/dp/dp_display.c')
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_display.c | 121 |
1 files changed, 76 insertions, 45 deletions
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 1784e119269b..051c1be1de7e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -208,10 +208,6 @@ static int dp_display_bind(struct device *dev, struct device *master, dp = container_of(g_dp_display, struct dp_display_private, dp_display); - if (!dp) { - DRM_ERROR("DP driver bind failed. Invalid driver data\n"); - return -EINVAL; - } dp->dp_display.drm_dev = drm; priv = drm->dev_private; @@ -252,10 +248,6 @@ static void dp_display_unbind(struct device *dev, struct device *master, dp = container_of(g_dp_display, struct dp_display_private, dp_display); - if (!dp) { - DRM_ERROR("Invalid DP driver data\n"); - return; - } dp_power_client_deinit(dp->power); dp_aux_unregister(dp->aux); @@ -346,6 +338,12 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->dp_display.max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ; dp->dp_display.max_dp_lanes = dp->parser->max_dp_lanes; + /* + * set sink to normal operation mode -- D0 + * before dpcd read + */ + dp_link_psm_config(dp->link, &dp->panel->link_info, false); + dp_link_reset_phy_params_vx_px(dp->link); rc = dp_ctrl_on_link(dp->ctrl); if (rc) { @@ -406,19 +404,9 @@ static int dp_display_usbpd_configure_cb(struct device *dev) dp = container_of(g_dp_display, struct dp_display_private, dp_display); - if (!dp) { - DRM_ERROR("no driver data found\n"); - rc = -ENODEV; - goto end; - } dp_display_host_init(dp, false); - /* - * set sink to normal operation mode -- D0 - * before dpcd read - */ - dp_link_psm_config(dp->link, &dp->panel->link_info, false); rc = dp_display_process_hpd_high(dp); end: return rc; @@ -437,11 +425,6 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) dp = container_of(g_dp_display, struct dp_display_private, dp_display); - if (!dp) { - DRM_ERROR("no driver data found\n"); - rc = -ENODEV; - return rc; - } dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); @@ -502,7 +485,6 @@ static int dp_display_usbpd_attention_cb(struct device *dev) int rc = 0; u32 sink_request; struct dp_display_private *dp; - struct dp_usbpd *hpd; if (!dev) { DRM_ERROR("invalid dev\n"); @@ -511,12 +493,6 @@ static int dp_display_usbpd_attention_cb(struct device *dev) dp = container_of(g_dp_display, struct dp_display_private, dp_display); - if (!dp) { - DRM_ERROR("no driver data found\n"); - return -ENODEV; - } - - hpd = dp->usbpd; /* check for any test request issued by sink */ rc = dp_link_process_request(dp->link); @@ -579,6 +555,10 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout); } + /* enable HDP irq_hpd/replug interrupt */ + dp_catalog_hpd_config_intr(dp->catalog, + DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true); + mutex_unlock(&dp->event_mutex); /* uevent will complete connection part */ @@ -628,7 +608,26 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) mutex_lock(&dp->event_mutex); state = dp->hpd_state; - if (state == ST_DISCONNECT_PENDING || state == ST_DISCONNECTED) { + + /* disable irq_hpd/replug interrupts */ + dp_catalog_hpd_config_intr(dp->catalog, + DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, false); + + /* unplugged, no more irq_hpd handle */ + dp_del_event(dp, EV_IRQ_HPD_INT); + + if (state == ST_DISCONNECTED) { + /* triggered by irq_hdp with sink_count = 0 */ + if (dp->link->sink_count == 0) { + dp_ctrl_off_phy(dp->ctrl); + hpd->hpd_high = 0; + dp->core_initialized = false; + } + mutex_unlock(&dp->event_mutex); + return 0; + } + + if (state == ST_DISCONNECT_PENDING) { mutex_unlock(&dp->event_mutex); return 0; } @@ -642,9 +641,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp->hpd_state = ST_DISCONNECT_PENDING; - /* disable HPD plug interrupt until disconnect is done */ - dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK - | DP_DP_IRQ_HPD_INT_MASK, false); + /* disable HPD plug interrupts */ + dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, false); hpd->hpd_high = 0; @@ -660,8 +658,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) /* signal the disconnect event early to ensure proper teardown */ dp_display_handle_plugged_change(g_dp_display, false); - dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | - DP_DP_IRQ_HPD_INT_MASK, true); + /* enable HDP plug interrupt to prepare for next plugin */ + dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true); /* uevent will complete disconnection part */ mutex_unlock(&dp->event_mutex); @@ -692,7 +690,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) /* irq_hpd can happen at either connected or disconnected state */ state = dp->hpd_state; - if (state == ST_DISPLAY_OFF) { + if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) { mutex_unlock(&dp->event_mutex); return 0; } @@ -724,7 +722,6 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) static void dp_display_deinit_sub_modules(struct dp_display_private *dp) { dp_debug_put(dp->debug); - dp_ctrl_put(dp->ctrl); dp_panel_put(dp->panel); dp_aux_put(dp->aux); dp_audio_put(dp->audio); @@ -818,13 +815,11 @@ static int dp_init_sub_modules(struct dp_display_private *dp) rc = PTR_ERR(dp->audio); pr_err("failed to initialize audio, rc = %d\n", rc); dp->audio = NULL; - goto error_audio; + goto error_ctrl; } return rc; -error_audio: - dp_ctrl_put(dp->ctrl); error_ctrl: dp_panel_put(dp->panel); error_link: @@ -910,9 +905,13 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data) dp_display->audio_enabled = false; - dp_ctrl_off(dp->ctrl); - - dp->core_initialized = false; + /* triggered by irq_hpd with sink_count = 0 */ + if (dp->link->sink_count == 0) { + dp_ctrl_off_link_stream(dp->ctrl); + } else { + dp_ctrl_off(dp->ctrl); + dp->core_initialized = false; + } dp_display->power_on = false; @@ -1012,6 +1011,33 @@ int dp_display_get_test_bpp(struct msm_dp *dp) dp_display->link->test_video.test_bit_depth); } +void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) +{ + struct dp_display_private *dp_display; + struct drm_device *drm; + + dp_display = container_of(dp, struct dp_display_private, dp_display); + drm = dp->drm_dev; + + /* + * if we are reading registers we need the link clocks to be on + * however till DP cable is connected this will not happen as we + * do not know the resolution to power up with. Hence check the + * power_on status before dumping DP registers to avoid crash due + * to unclocked access + */ + mutex_lock(&dp_display->event_mutex); + + if (!dp->power_on) { + mutex_unlock(&dp_display->event_mutex); + return; + } + + dp_catalog_snapshot(dp_display->catalog, disp_state); + + mutex_unlock(&dp_display->event_mutex); +} + static void dp_display_config_hpd(struct dp_display_private *dp) { @@ -1300,8 +1326,13 @@ static int dp_pm_suspend(struct device *dev) mutex_lock(&dp->event_mutex); - if (dp->core_initialized == true) + if (dp->core_initialized == true) { + /* mainlink enabled */ + if (dp_power_clk_status(dp->power, DP_CTRL_PM)) + dp_ctrl_off_link_stream(dp->ctrl); + dp_display_host_deinit(dp); + } dp->hpd_state = ST_SUSPENDED; |