From 452e643352bd41612f5634d8b38d7be9cbc9a875 Mon Sep 17 00:00:00 2001 From: Nilesh Laad Date: Fri, 23 Jun 2023 17:42:52 +0530 Subject: [PATCH] disp: msm: dp: wait for resources init in case of cont splash Driver probe has to wait for dp resource initialization, in case of continuous splash to avoid any resource resets. Change-Id: Idaa506b14132d22b9bfe558c88ab6d33171b4f3b Signed-off-by: Nilesh Laad --- msm/dp/dp_display.c | 41 ++++++++++++++++++++++++++++++++++ msm/dp/dp_display.h | 5 +++++ msm/sde/sde_kms.c | 54 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index b33930a7e5fb..bcb6f8f57ff4 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -177,6 +177,7 @@ struct dp_display_private { struct dentry *root; struct completion notification_comp; struct completion attention_comp; + struct completion res_init_comp; struct dp_hpd *hpd; struct dp_parser *parser; @@ -317,6 +318,42 @@ static void dp_audio_enable(struct dp_display_private *dp, bool enable) } } +/** + * dp_display_cont_splash_config() - Initialize resources for continuous splash + * @dp_display: Pointer to dp display + * Returns: Zero on success + */ +int dp_display_cont_splash_config(void *display) +{ + struct dp_display *dp_display = display; + struct dp_display_private *dp; + int rc = 0; + + /* Vote for gdsc required to read register address space */ + if (!dp_display) { + DP_ERR("invalid input display param\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + if (!dp_display->is_edp) { + DP_ERR("splash handoff for dp not supported\n"); + return -EOPNOTSUPP; + } + + /* wait for the all the resource initialization and voting to + * complete, before we exit driver probe + */ + if (!wait_for_completion_timeout(&dp->res_init_comp, HZ * 10)) { + DP_WARN("timeout waiting for splash_res_init\n"); + rc = -ETIMEDOUT; + } + + return rc; +} + + static int dp_display_parse_boot_display_selection(void) { char *pos = NULL; @@ -1358,6 +1395,9 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->process_hpd_connect = false; dp_display_set_mst_mgr_state(dp, true); + + /* all dp resource init are complete */ + complete_all(&dp->res_init_comp); end: mutex_unlock(&dp->session_lock); @@ -3990,6 +4030,7 @@ static int dp_display_probe(struct platform_device *pdev) init_completion(&dp->notification_comp); init_completion(&dp->attention_comp); + init_completion(&dp->res_init_comp); dp->pdev = pdev; dp->name = "drm_dp"; diff --git a/msm/dp/dp_display.h b/msm/dp/dp_display.h index 9d4cea9810d2..f7088a4aa93b 100644 --- a/msm/dp/dp_display.h +++ b/msm/dp/dp_display.h @@ -168,6 +168,7 @@ int dp_display_get_num_of_boot_displays(void); int dp_display_get_displays(void **displays, int count); int dp_display_get_num_of_streams(void); int dp_display_get_info(void *dp_display, struct dp_display_info *dp_info); +int dp_display_cont_splash_config(void *display); #else static inline int dp_display_get_num_of_displays(void) { @@ -194,5 +195,9 @@ static inline int dp_connector_update_pps(struct drm_connector *connector, { return 0; } +static inline int dp_display_cont_splash_config(void *display) +{ + return 0; +} #endif /* CONFIG_DRM_MSM_DP */ #endif /* _DP_DISPLAY_H_ */ diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 5bdcdd018157..e0df3cc96fd8 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1800,7 +1800,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .set_colorspace = dp_connector_set_colorspace, .config_hdr = dp_connector_config_hdr, .cmd_transfer = NULL, - .cont_splash_config = NULL, + .cont_splash_config = dp_display_cont_splash_config, .cont_splash_res_disable = NULL, .get_panel_vfp = NULL, .update_pps = dp_connector_update_pps, @@ -3381,6 +3381,7 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms, { void *display; struct dsi_display *dsi_display; + struct dp_display *dp_display; struct msm_display_info info; struct drm_encoder *encoder = NULL; struct drm_crtc *crtc = NULL; @@ -3531,6 +3532,57 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms, } } + /* dp */ + for (i = 0; i < sde_kms->dp_display_count; ++i) { + display = sde_kms->dp_displays[i]; + dp_display = (struct dp_display *)display; + + if (!dp_display->cont_splash_enabled) { + SDE_DEBUG("DP-%d splash not enabled\n", i); + continue; + } + + if (dp_display->bridge->base.encoder) { + encoder = dp_display->bridge->base.encoder; + SDE_DEBUG("encoder name = %s\n", encoder->name); + } else { + SDE_DEBUG("Invalid encoder\n"); + break; + } + + mutex_lock(&dev->mode_config.mutex); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + /** + * SDE_KMS doesn't attach more than one encoder to + * a DSI connector. So it is safe to check only with + * the first encoder entry. Revisit this logic if we + * ever have to support continuous splash for + * external displays in MST configuration. + */ + if (connector->encoder_ids[0] == encoder->base.id) + break; + } + + drm_connector_list_iter_end(&conn_iter); + if (!connector) { + SDE_ERROR("connector not initialized\n"); + mutex_unlock(&dev->mode_config.mutex); + return -EINVAL; + } + mutex_unlock(&dev->mode_config.mutex); + + /* Enable all irqs */ + sde_irq_update(kms, true); + + sde_conn = to_sde_connector(connector); + if (sde_conn && sde_conn->ops.cont_splash_config) + sde_conn->ops.cont_splash_config(sde_conn->display); + + /* Disable irqs */ + sde_irq_update(kms, false); + } + return rc; }