diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index f6c2d877..120445b8 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -5056,6 +5056,25 @@ static int _dsi_display_dev_deinit(struct dsi_display *display) return rc; } +/** + * dsi_display_cont_splash_res_disable() - Disable resource votes added in probe + * @dsi_display: Pointer to dsi display + * Returns: Zero on success + */ +int dsi_display_cont_splash_res_disable(void *dsi_display) +{ + struct dsi_display *display = dsi_display; + int rc = 0; + + /* Remove the panel vote that was added during dsi display probe */ + rc = dsi_pwr_enable_regulator(&display->panel->power_info, false); + if (rc) + DSI_ERR("[%s] failed to disable vregs, rc=%d\n", + display->panel->name, rc); + + return rc; +} + /** * dsi_display_cont_splash_config() - Initialize resources for continuous splash * @dsi_display: Pointer to dsi display @@ -5101,14 +5120,6 @@ int dsi_display_cont_splash_config(void *dsi_display) goto clk_manager_update; } - /* Vote on panel regulator will be removed during suspend path */ - rc = dsi_pwr_enable_regulator(&display->panel->power_info, true); - if (rc) { - DSI_ERR("[%s] failed to enable vregs, rc=%d\n", - display->panel->name, rc); - goto clks_disabled; - } - mutex_unlock(&display->display_lock); /* Set the current brightness level */ @@ -5116,10 +5127,6 @@ int dsi_display_cont_splash_config(void *dsi_display) return rc; -clks_disabled: - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_ALL_CLKS, DSI_CLK_OFF); - clk_manager_update: dsi_display_ctrl_isr_configure(display, false); /* Update splash status for clock manager */ @@ -5461,17 +5468,6 @@ static int dsi_display_bind(struct device *dev, } } - /* Remove the panel vote that was added during dsi display probe */ - if (display->panel) { - rc = dsi_pwr_enable_regulator(&display->panel->power_info, - false); - if (rc) { - DSI_ERR("[%s] failed to disable vregs, rc=%d\n", - display->panel->name, rc); - goto error_host_deinit; - } - } - /* register te irq handler */ dsi_display_register_te_irq(display); @@ -5581,11 +5577,13 @@ static int dsi_display_init(struct dsi_display *display) /* * Vote on panel regulator is added to make sure panel regulators - * are ON until dsi bind is completed for cont-splash enabled usecase. - * This panel regulator vote will be removed after bind is done. + * are ON for cont-splash enabled usecase. + * This panel regulator vote will be removed only in: + * 1) device suspend when cont-splash is enabled. + * 2) cont_splash_res_disable() when cont-splash is disabled. * For GKI, adding this vote will make sure that sync_state - * kernel driver doesn't disable the panel regulators before - * splash_config() function adds vote for these regulators. + * kernel driver doesn't disable the panel regulators after + * dsi probe is complete. */ if (display->panel) { rc = dsi_pwr_enable_regulator(&display->panel->power_info, diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 06251aaa..5398b4bc 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -737,6 +737,14 @@ enum dsi_pixel_format dsi_display_get_dst_format( * Return: Zero on Success */ int dsi_display_cont_splash_config(void *display); + +/** + * dsi_display_cont_splash_res_disable() - Disable resource votes added in probe + * @display: Pointer to dsi display + * Returns: Zero on success + */ +int dsi_display_cont_splash_res_disable(void *display); + /* * dsi_display_get_panel_vfp - get panel vsync * @display: Pointer to private display structure diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 03c7f306..10ef8596 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -325,6 +325,13 @@ struct sde_connector_ops { */ int (*cont_splash_config)(void *display); + /** + * cont_splash_res_disable - Remove any splash resources added in probe + * @display: Pointer to private display handle + * Returns: zero for success, negetive for failure + */ + int (*cont_splash_res_disable)(void *display); + /** * get_panel_vfp - returns original panel vfp * @display: Pointer to private display handle diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 93731938..5020ac05 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1652,6 +1652,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .enable_event = dsi_conn_enable_event, .cmd_transfer = dsi_display_cmd_transfer, .cont_splash_config = dsi_display_cont_splash_config, + .cont_splash_res_disable = dsi_display_cont_splash_res_disable, .get_panel_vfp = dsi_display_get_panel_vfp, .get_default_lms = dsi_display_get_default_lms, .cmd_receive = dsi_display_cmd_receive, @@ -1670,6 +1671,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .check_status = NULL, .cmd_transfer = NULL, .cont_splash_config = NULL, + .cont_splash_res_disable = NULL, .get_panel_vfp = NULL, .cmd_receive = NULL, .install_properties = NULL, @@ -1688,6 +1690,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .config_hdr = dp_connector_config_hdr, .cmd_transfer = NULL, .cont_splash_config = NULL, + .cont_splash_res_disable = NULL, .get_panel_vfp = NULL, .update_pps = dp_connector_update_pps, .cmd_receive = NULL, @@ -2784,6 +2787,66 @@ static struct drm_display_mode *_sde_kms_get_splash_mode( return curr_mode; } +static int sde_kms_inform_cont_splash_res_disable(struct msm_kms *kms, + struct dsi_display *dsi_display) +{ + void *display; + struct drm_encoder *encoder = NULL; + struct msm_display_info info; + struct drm_device *dev; + struct sde_kms *sde_kms; + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector = NULL; + struct sde_connector *sde_conn = NULL; + int rc = 0; + + sde_kms = to_sde_kms(kms); + dev = sde_kms->dev; + display = dsi_display; + if (dsi_display) { + if (dsi_display->bridge->base.encoder) { + encoder = dsi_display->bridge->base.encoder; + SDE_DEBUG("encoder name = %s\n", encoder->name); + } + memset(&info, 0x0, sizeof(info)); + rc = dsi_display_get_info(NULL, &info, display); + if (rc) { + SDE_ERROR("%s: dsi get_info failed: %d\n", + rc, __func__); + encoder = NULL; + } + } + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + /** + * Inform cont_splash is disabled to each interface/connector. + * This is currently supported for DSI interface. + */ + sde_conn = to_sde_connector(connector); + if (sde_conn && sde_conn->ops.cont_splash_res_disable) { + if (!dsi_display || !encoder) { + sde_conn->ops.cont_splash_res_disable + (sde_conn->display); + } else if (connector->encoder_ids[0] + == encoder->base.id) { + /** + * This handles dual DSI + * configuration where one DSI + * interface has cont_splash + * enabled and the other doesn't. + */ + sde_conn->ops.cont_splash_res_disable + (sde_conn->display); + break; + } + } + } + drm_connector_list_iter_end(&conn_iter); + + return 0; +} + static int sde_kms_cont_splash_config(struct msm_kms *kms) { void *display; @@ -2817,6 +2880,7 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms) && (!sde_kms->splash_data.num_splash_regions)) || !sde_kms->splash_data.num_splash_displays) { DRM_INFO("cont_splash feature not enabled\n"); + sde_kms_inform_cont_splash_res_disable(kms, NULL); return rc; } @@ -2833,6 +2897,8 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms) if (!splash_display->cont_splash_enabled) { SDE_DEBUG("display->name = %s splash not enabled\n", dsi_display->name); + sde_kms_inform_cont_splash_res_disable(kms, + dsi_display); continue; }