From 126db6aa9e593d75ca4489f88cb9d27b047ee9f0 Mon Sep 17 00:00:00 2001 From: Sai Srujana Oruganti Date: Mon, 22 May 2023 21:34:58 +0530 Subject: [PATCH 1/2] disp: msm: eDP continuous splash implementation For continuous splash use case bootloader already takes care of eDP hardware states including clocks and regulators. This change avoid touching eDP hardware blocks during eDP initialization sequence. Change-Id: I23635b43ce2a41078383bbcc89aa3f60564599dd Signed-off-by: Sai Srujana Oruganti --- msm/dp/dp_aux.c | 9 +++- msm/dp/dp_aux.h | 3 +- msm/dp/dp_ctrl.c | 68 +++++++++++++++++++----------- msm/dp/dp_ctrl.h | 10 ++--- msm/dp/dp_display.c | 99 +++++++++++++++++++++++++++++++++++++++----- msm/dp/dp_display.h | 17 +++++++- msm/dp/dp_drm.c | 1 + msm/dp/dp_pll.h | 2 +- msm/dp/edp_pll_7nm.c | 10 +++++ msm/sde/sde_kms.c | 3 +- 10 files changed, 177 insertions(+), 45 deletions(-) diff --git a/msm/dp/dp_aux.c b/msm/dp/dp_aux.c index ae00856bb3da..7c4fbc2fbb50 100644 --- a/msm/dp/dp_aux.c +++ b/msm/dp/dp_aux.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ @@ -631,7 +632,7 @@ static void dp_aux_reset_phy_config_indices(struct dp_aux_cfg *aux_cfg) aux_cfg[i].current_index = 0; } -static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg) +static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg, bool skip_op) { struct dp_aux_private *aux; @@ -645,10 +646,16 @@ static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg) if (aux->enabled) return; + /*skip aux init when cont. splash is enabled*/ + if (skip_op) + goto skip_init; + dp_aux_reset_phy_config_indices(aux_cfg); aux->catalog->setup(aux->catalog, aux_cfg); aux->catalog->reset(aux->catalog); aux->catalog->enable(aux->catalog, true); + +skip_init: atomic_set(&aux->aborted, 0); aux->retry_cnt = 0; aux->enabled = true; diff --git a/msm/dp/dp_aux.h b/msm/dp/dp_aux.h index 850941b1e53d..aa762e91acf7 100644 --- a/msm/dp/dp_aux.h +++ b/msm/dp/dp_aux.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ @@ -47,7 +48,7 @@ struct dp_aux { int (*drm_aux_register)(struct dp_aux *aux); void (*drm_aux_deregister)(struct dp_aux *aux); void (*isr)(struct dp_aux *aux); - void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg); + void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg, bool skip_op); void (*deinit)(struct dp_aux *aux); void (*reconfig)(struct dp_aux *aux); void (*abort)(struct dp_aux *aux, bool abort); diff --git a/msm/dp/dp_ctrl.c b/msm/dp/dp_ctrl.c index 395d5a7e1cc9..4f935764cc21 100644 --- a/msm/dp/dp_ctrl.c +++ b/msm/dp/dp_ctrl.c @@ -165,8 +165,13 @@ trigger_idle: * configuration, output format and sink/panel timing information. */ static void dp_ctrl_configure_source_link_params(struct dp_ctrl_private *ctrl, - bool enable) + bool enable, bool skip_op) { + if (skip_op) { + DP_DEBUG("configuring source link params skipped\n"); + return; + } + if (enable) { ctrl->catalog->lane_mapping(ctrl->catalog, ctrl->orientation, ctrl->parser->l_map); @@ -533,7 +538,7 @@ skip_training: return ret; } -static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) +static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, bool skip_op) { int ret = 0; u8 const encoding = 0x1, downspread = 0x00; @@ -547,6 +552,11 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) ctrl->link->link_params.bw_code); link_info.capabilities = ctrl->panel->link_info.capabilities; + if (skip_op) { + DP_DEBUG("link training skipped\n"); + return 0; + } + ret = drm_dp_link_configure(ctrl->aux->drm_aux, &link_info); if (ret) goto end; @@ -592,7 +602,7 @@ end: return ret; } -static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl) +static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool skip_op) { int ret = 0; @@ -604,13 +614,15 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl) * transitioned to PUSH_IDLE. In order to start transmitting a link * training pattern, we have to first to a DP software reset. */ - ctrl->catalog->reset(ctrl->catalog); + + if (!skip_op) + ctrl->catalog->reset(ctrl->catalog); if (ctrl->fec_mode) drm_dp_dpcd_writeb(ctrl->aux->drm_aux, DP_FEC_CONFIGURATION, 0x01); - ret = dp_ctrl_link_train(ctrl); + ret = dp_ctrl_link_train(ctrl, skip_op); end: return ret; @@ -720,7 +732,7 @@ end: ctrl->training_2_pattern = pattern; } -static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow) +static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow, bool skip_op) { int rc = -EINVAL; bool downgrade = false; @@ -746,7 +758,7 @@ static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow) ctrl->link->link_params.lane_count, ctrl->orientation); - dp_ctrl_configure_source_link_params(ctrl, true); + dp_ctrl_configure_source_link_params(ctrl, true, skip_op); if (!(--link_train_max_retries % 10)) { struct dp_link_params *link = &ctrl->link->link_params; @@ -758,7 +770,7 @@ static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow) dp_ctrl_select_training_pattern(ctrl, downgrade); - rc = dp_ctrl_setup_main_link(ctrl); + rc = dp_ctrl_setup_main_link(ctrl, skip_op); if (!rc) break; @@ -782,7 +794,7 @@ static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow) if (rc != -EAGAIN) dp_ctrl_link_rate_down_shift(ctrl); - dp_ctrl_configure_source_link_params(ctrl, false); + dp_ctrl_configure_source_link_params(ctrl, false, skip_op); dp_ctrl_disable_link_clock(ctrl); /* hw recommended delays before retrying link training */ @@ -852,7 +864,7 @@ static int dp_ctrl_disable_stream_clocks(struct dp_ctrl_private *ctrl, } return ret; } -static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset) +static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset, bool skip_op) { struct dp_ctrl_private *ctrl; struct dp_catalog_ctrl *catalog; @@ -867,7 +879,7 @@ static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset) ctrl->orientation = flip; catalog = ctrl->catalog; - if (reset) { + if (reset && !skip_op) { catalog->usb_reset(ctrl->catalog, flip); catalog->phy_reset(ctrl->catalog); } @@ -906,7 +918,7 @@ static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl) ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); } -static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) +static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl, bool skip_op) { int ret = 0; struct dp_ctrl_private *ctrl; @@ -931,7 +943,7 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) goto end; ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_STARTED; - ret = dp_ctrl_setup_main_link(ctrl); + ret = dp_ctrl_setup_main_link(ctrl, skip_op); ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_STARTED; if (ret) { @@ -949,7 +961,7 @@ end: return ret; } -static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl) +static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl, bool skip_op) { int ret = 0; struct dp_ctrl_private *ctrl; @@ -978,14 +990,14 @@ static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl) ctrl->dp_ctrl.stream_off(&ctrl->dp_ctrl, ctrl->panel); ctrl->dp_ctrl.off(&ctrl->dp_ctrl); - ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg); + ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg, skip_op); ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode, - ctrl->fec_mode, ctrl->dsc_mode, false); + ctrl->fec_mode, ctrl->dsc_mode, false, skip_op); if (ret) DP_ERR("failed to enable DP controller\n"); - ctrl->dp_ctrl.stream_on(&ctrl->dp_ctrl, ctrl->panel); + ctrl->dp_ctrl.stream_on(&ctrl->dp_ctrl, ctrl->panel, skip_op); DP_DEBUG("end\n"); } @@ -1228,7 +1240,7 @@ static void dp_ctrl_fec_dsc_setup(struct dp_ctrl_private *ctrl) DP_WARN("failed to enable sink dsc\n"); } -static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) +static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel, bool skip_op) { int rc = 0; bool link_ready = false; @@ -1250,9 +1262,12 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) return rc; } - rc = panel->hw_cfg(panel, true); - if (rc) - return rc; + /*Skip panel config when cont. splash is enabled*/ + if (!skip_op) { + rc = panel->hw_cfg(panel, true); + if (rc) + return rc; + } if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { dp_ctrl_send_phy_test_pattern(ctrl); @@ -1343,7 +1358,7 @@ static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) } static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, - bool fec_mode, bool dsc_mode, bool shallow) + bool fec_mode, bool dsc_mode, bool shallow, bool skip_op) { int rc = 0; struct dp_ctrl_private *ctrl; @@ -1389,9 +1404,13 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, ctrl->initial_lane_count = ctrl->link->link_params.lane_count; ctrl->initial_bw_code = ctrl->link->link_params.bw_code; - rc = dp_ctrl_link_setup(ctrl, shallow); + rc = dp_ctrl_link_setup(ctrl, shallow, skip_op); if (!rc) ctrl->power_on = true; + + /*enable stream clocks when cont. splash is enabled*/ + if (skip_op) + dp_ctrl_enable_stream_clocks(ctrl, ctrl->panel); end: return rc; } @@ -1399,6 +1418,7 @@ end: static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; + bool skip_op = false; if (!dp_ctrl) return; @@ -1409,7 +1429,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) return; ctrl->catalog->fec_config(ctrl->catalog, false); - dp_ctrl_configure_source_link_params(ctrl, false); + dp_ctrl_configure_source_link_params(ctrl, false, skip_op); ctrl->catalog->reset(ctrl->catalog); /* Make sure DP is disabled before clk disable */ diff --git a/msm/dp/dp_ctrl.h b/msm/dp/dp_ctrl.h index 225a4bf54daf..0f506d7294d8 100644 --- a/msm/dp/dp_ctrl.h +++ b/msm/dp/dp_ctrl.h @@ -16,17 +16,17 @@ #include "dp_debug.h" struct dp_ctrl { - int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset); + int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset, bool skip_op); void (*deinit)(struct dp_ctrl *dp_ctrl); int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool fec_en, - bool dsc_en, bool shallow); + bool dsc_en, bool shallow, bool skip_op); void (*off)(struct dp_ctrl *dp_ctrl); void (*abort)(struct dp_ctrl *dp_ctrl, bool abort); void (*isr)(struct dp_ctrl *dp_ctrl); bool (*handle_sink_request)(struct dp_ctrl *dp_ctrl); - void (*process_phy_test_request)(struct dp_ctrl *dp_ctrl); - int (*link_maintenance)(struct dp_ctrl *dp_ctrl); - int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); + void (*process_phy_test_request)(struct dp_ctrl *dp_ctrl, bool skip_op); + int (*link_maintenance)(struct dp_ctrl *dp_ctrl, bool skip_op); + int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel, bool skip_op); void (*stream_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*stream_pre_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*set_mst_channel_info)(struct dp_ctrl *dp_ctrl, diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index 11349989c449..292c6cef76a2 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -136,6 +136,12 @@ static char *dp_display_state_name(enum dp_display_states state) static struct dp_display *g_dp_display[MAX_DP_ACTIVE_DISPLAY]; #define HPD_STRING_SIZE 30 +static char edp_display_primary[MAX_CMDLINE_PARAM_LEN]; + +static struct dp_display_boot_param boot_displays[MAX_DP_ACTIVE_BOOT_DISPLAY] = { + {.boot_param = edp_display_primary}, +}; + struct dp_hdcp_dev { void *fd; struct sde_hdcp_ops *ops; @@ -229,6 +235,13 @@ static const struct of_device_id dp_dt_match[] = { {} }; +bool is_skip_required(struct dp_display *display) +{ + if (!display) + return false; + return display->cont_splash_enabled; +} + static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp) { return dp->link->hdcp_status.hdcp_version && dp->hdcp.ops; @@ -304,6 +317,35 @@ static void dp_audio_enable(struct dp_display_private *dp, bool enable) } } +static int dp_display_parse_boot_display_selection(void) +{ + char *pos = NULL; + char disp_buf[MAX_CMDLINE_PARAM_LEN] = {'\0'}; + int i, j; + + for (i = 0; i < MAX_DP_ACTIVE_BOOT_DISPLAY; i++) { + strlcpy(disp_buf, boot_displays[i].boot_param, + MAX_CMDLINE_PARAM_LEN); + + pos = strnstr(disp_buf, ":", strlen(disp_buf)); + + /* Use ':' as a delimiter to retrieve the display name */ + if (!pos) { + DP_DEBUG("display name[%s]is not valid\n", disp_buf); + continue; + } + + for (j = 0; (disp_buf + j) < pos; j++) + boot_displays[i].name[j] = *(disp_buf + j); + + boot_displays[i].name[j] = '\0'; + + boot_displays[i].boot_disp_en = true; + } + + return 0; +} + static void dp_display_update_hdcp_status(struct dp_display_private *dp, bool reset) { @@ -1060,6 +1102,8 @@ static int dp_display_host_init(struct dp_display_private *dp) bool flip = false; bool reset; int rc = 0; + bool skip_op = is_skip_required(&dp->dp_display); + if (dp_display_state_is(DP_STATE_INITIALIZED)) { dp_display_state_log("[already initialized]"); @@ -1079,7 +1123,7 @@ static int dp_display_host_init(struct dp_display_private *dp) } dp->hpd->host_init(dp->hpd, &dp->catalog->hpd); - rc = dp->ctrl->init(dp->ctrl, flip, reset); + rc = dp->ctrl->init(dp->ctrl, flip, reset, skip_op); if (rc) { DP_WARN("Ctrl init Failed.\n"); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_CASE2, dp->state); @@ -1122,7 +1166,8 @@ static int dp_display_panel_ready(struct dp_display_private *dp) return -ETIMEDOUT; } } - dp->panel->init(dp->panel); + if (!dp->dp_display.cont_splash_enabled) + dp->panel->init(dp->panel); return 0; } @@ -1130,6 +1175,7 @@ static int dp_display_panel_ready(struct dp_display_private *dp) static int dp_display_host_ready(struct dp_display_private *dp) { int rc = 0; + bool skip_op; if (!dp_display_state_is(DP_STATE_INITIALIZED)) { rc = dp_display_host_init(dp); @@ -1160,11 +1206,11 @@ static int dp_display_host_ready(struct dp_display_private *dp) * the connect/disconnect notifications do not currently have any * sessions IDs. */ + skip_op = dp->dp_display.cont_splash_enabled; dp->aux->abort(dp->aux, false); dp->ctrl->abort(dp->ctrl, false); - dp->aux->init(dp->aux, dp->parser->aux_cfg); - + dp->aux->init(dp->aux, dp->parser->aux_cfg, skip_op); dp_display_state_add(DP_STATE_READY); /* log this as it results from user action of cable connection */ DP_INFO("[OK]\n"); @@ -1220,6 +1266,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) int rc = -EINVAL; unsigned long wait_timeout_ms; unsigned long t; + bool skip_op = is_skip_required(&dp->dp_display); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state); mutex_lock(&dp->session_lock); @@ -1302,7 +1349,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp_display_mst_init(dp); rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, - dp->panel->fec_en, dp->panel->dsc_en, false); + dp->panel->fec_en, dp->panel->dsc_en, false, skip_op); if (rc) { dp_display_state_remove(DP_STATE_CONNECTED); goto end; @@ -1702,8 +1749,9 @@ static int dp_display_stream_enable(struct dp_display_private *dp, struct dp_panel *dp_panel) { int rc = 0; + bool skip_op = is_skip_required(&dp->dp_display); - rc = dp->ctrl->stream_on(dp->ctrl, dp_panel); + rc = dp->ctrl->stream_on(dp->ctrl, dp_panel, skip_op); if (dp->debug->tpg_state) dp_panel->tpg_config(dp_panel, true); @@ -1742,6 +1790,7 @@ static void dp_display_attention_work(struct work_struct *work) struct dp_display_private *dp = container_of(work, struct dp_display_private, attention_work); int rc = 0; + bool skip_op = is_skip_required(&dp->dp_display); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state); mutex_lock(&dp->session_lock); @@ -1805,18 +1854,18 @@ static void dp_display_attention_work(struct work_struct *work) if (dp->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { SDE_EVT32_EXTERNAL(dp->state, DP_TEST_LINK_PHY_TEST_PATTERN); - dp->ctrl->process_phy_test_request(dp->ctrl); + dp->ctrl->process_phy_test_request(dp->ctrl, skip_op); } if (dp->link->sink_request & DP_TEST_LINK_TRAINING) { SDE_EVT32_EXTERNAL(dp->state, DP_TEST_LINK_TRAINING); dp->link->send_test_response(dp->link); - rc = dp->ctrl->link_maintenance(dp->ctrl); + rc = dp->ctrl->link_maintenance(dp->ctrl, skip_op); } if (dp->link->sink_request & DP_LINK_STATUS_UPDATED) { SDE_EVT32_EXTERNAL(dp->state, DP_LINK_STATUS_UPDATED); - rc = dp->ctrl->link_maintenance(dp->ctrl); + rc = dp->ctrl->link_maintenance(dp->ctrl, skip_op); } if (!rc) @@ -2066,6 +2115,9 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error_pll; } + if (dp->dp_display.cont_splash_enabled) + dp->pll->cont_splash_enabled = 1; + dp->power = dp_power_get(dp->parser, dp->pll); if (IS_ERR(dp->power)) { rc = PTR_ERR(dp->power); @@ -2283,6 +2335,7 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) struct dp_panel *dp_panel; int rc = 0; bool shallow_mode = true; + bool skip_op = is_skip_required(dp_display); if (!dp_display || !panel) { DP_ERR("invalid input\n"); @@ -2385,7 +2438,7 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) * and required things. */ rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, dp_panel->fec_en, - dp_panel->dsc_en, shallow_mode); + dp_panel->dsc_en, shallow_mode, skip_op); if (rc) goto end; @@ -2573,6 +2626,11 @@ end: static void dp_display_stream_post_enable(struct dp_display_private *dp, struct dp_panel *dp_panel) { + + if (dp->dp_display.cont_splash_enabled) { + dp->dp_display.cont_splash_enabled = false; + dp->pll->cont_splash_enabled = false; + } dp_panel->spd_config(dp_panel); dp_panel->setup_hdr(dp_panel, NULL, false, 0, true); } @@ -3953,6 +4011,10 @@ static int dp_display_probe(struct platform_device *pdev) dp_display->is_edp = (info->display_type == DRM_MODE_CONNECTOR_eDP) ? true : false; dp_display->edp_detect = dp_display_edp_detect; + if (dp_display->is_edp) { + if (dp_display_get_num_of_boot_displays()) + dp_display->cont_splash_enabled = 1; + } rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { DP_ERR("component add failed, rc=%d\n", rc); @@ -3985,6 +4047,17 @@ int dp_display_get_displays(void **displays, int count) return i; } +int dp_display_get_num_of_boot_displays(void) +{ + int i; + int count = 0; + + for (i = 0; i < MAX_DP_ACTIVE_BOOT_DISPLAY; i++) { + if (boot_displays[i].boot_disp_en == true) + count++; + } + return count; +} int dp_display_get_num_of_displays(void) { int i; @@ -4151,7 +4224,7 @@ static struct platform_driver dp_display_driver = { void __init dp_display_register(void) { - + dp_display_parse_boot_display_selection(); platform_driver_register(&dp_display_driver); } @@ -4159,3 +4232,7 @@ void __exit dp_display_unregister(void) { platform_driver_unregister(&dp_display_driver); } +module_param_string(edp_display0, edp_display_primary, MAX_CMDLINE_PARAM_LEN, + 0600); +MODULE_PARM_DESC(edp_display0, + "msm_drm.edp_display0=: where is 'primary dp display node name' "); diff --git a/msm/dp/dp_display.h b/msm/dp/dp_display.h index 892322fa2fc2..13181732cf32 100644 --- a/msm/dp/dp_display.h +++ b/msm/dp/dp_display.h @@ -16,6 +16,9 @@ #define DP_MST_SIM_MAX_PORTS 8 #define MAX_DP_ACTIVE_DISPLAY 8 +#define MAX_DP_ACTIVE_BOOT_DISPLAY 1 + +#define MAX_CMDLINE_PARAM_LEN 512 enum dp_drv_state { PM_DEFAULT, @@ -39,6 +42,13 @@ struct dp_display_info { u32 stream_cnt; }; +struct dp_display_boot_param { + char name[MAX_CMDLINE_PARAM_LEN]; + char *boot_param; + bool boot_disp_en; + void *disp; +}; + struct dp_mst_drm_cbs { void (*hpd)(void *display, bool hpd_status); void (*hpd_irq)(void *display, struct dp_mst_hpd_info *info); @@ -86,6 +96,7 @@ struct dp_display { void *dp_mst_prv_info; u32 max_mixer_count; u32 max_dsc_count; + bool cont_splash_enabled; int (*enable)(struct dp_display *dp_display, void *panel); int (*post_enable)(struct dp_display *dp_display, void *panel); @@ -149,9 +160,9 @@ struct dp_display { u32 strm_id, const char **display_type); int (*edp_detect)(struct dp_display *dp_display); }; - #if IS_ENABLED(CONFIG_DRM_MSM_DP) int dp_display_get_num_of_displays(void); +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); @@ -160,6 +171,10 @@ static inline int dp_display_get_num_of_displays(void) { return 0; } +static inline int dp_display_get_num_of_boot_displays(void) +{ + return 0; +} static inline int dp_display_get_displays(void **displays, int count) { return 0; diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index 6e054af5dc3d..1342726043e8 100644 --- a/msm/dp/dp_drm.c +++ b/msm/dp/dp_drm.c @@ -463,6 +463,7 @@ int dp_connector_get_info(struct drm_connector *connector, if (display && display->is_edp) { info->intf_type = DRM_MODE_CONNECTOR_eDP; info->display_type = SDE_CONNECTOR_PRIMARY; + info->is_connected = true; } else { info->capabilities |= MSM_DISPLAY_CAP_HOT_PLUG; } diff --git a/msm/dp/dp_pll.h b/msm/dp/dp_pll.h index fa56964ab533..780a00c6dbfa 100644 --- a/msm/dp/dp_pll.h +++ b/msm/dp/dp_pll.h @@ -127,7 +127,7 @@ struct dp_pll { bool ssc_en; bool bonding_en; - + bool cont_splash_enabled; void *priv; struct dp_pll_db pll_db; struct dp_pll_vco_clk pll_clks[DP_PLL_NUM_CLKS]; diff --git a/msm/dp/edp_pll_7nm.c b/msm/dp/edp_pll_7nm.c index da26cb657884..1f3b60a1f325 100644 --- a/msm/dp/edp_pll_7nm.c +++ b/msm/dp/edp_pll_7nm.c @@ -277,6 +277,8 @@ static int edp_config_vco_rate_7nm(struct dp_pll *pll, DP_ERR("VCO Init DB failed\n"); return rc; } + if (pll->cont_splash_enabled) + return 0; dp_pll_write(dp_phy, DP_PHY_PD_CTL, 0x7d); /* Make sure the PLL register writes are done */ @@ -460,6 +462,11 @@ static int edp_pll_enable_7nm(struct dp_pll *pll) pll->aux->state &= ~DP_STATE_PLL_LOCKED; + if (pll->cont_splash_enabled) { + pll->aux->state |= DP_STATE_PLL_LOCKED; + return rc; + } + dp_pll_write(dp_phy, DP_PHY_CFG, 0x01); dp_pll_write(dp_phy, DP_PHY_CFG, 0x05); dp_pll_write(dp_phy, DP_PHY_CFG, 0x01); @@ -790,6 +797,9 @@ static int edp_pll_vco_div_clk_set_rate(struct clk_hw *hw, unsigned long rate, pll_link = to_dp_vco_hw(hw); pll = pll_link->priv; + if (pll->cont_splash_enabled) + return rc; + if (rate != edp_pll_vco_div_clk_get_rate(pll)) { DP_ERR("unsupported rate %lu failed\n", rate); return rc; diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 308200bd8579..b416840b5f7c 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -4426,7 +4426,8 @@ static int _sde_kms_get_splash_data(struct sde_kms *sde_kms, * cont_splash_region should be collection of all memory regions * Ex: */ - num_displays = dsi_display_get_num_of_displays(); + num_displays = dsi_display_get_num_of_displays() + + dp_display_get_num_of_boot_displays(); num_regions = of_property_count_u64_elems(node, "reg") / 2; data->num_splash_displays = num_displays; From ea245e7982147e234773528e78f64db2135fb846 Mon Sep 17 00:00:00 2001 From: Sai Srujana Oruganti Date: Sun, 18 Jun 2023 21:35:42 +0530 Subject: [PATCH 2/2] disp: msm: sde: Remove pm vote at time of handoff Additional pm vote is added when cont splash is enabled for eDP. This vote has to be removed at the time of handoff. Change-Id: Ib1c0cc58f0be1031d405ca8941d3e7984b1e9f46 Signed-off-by: Sai Srujana Oruganti --- msm/sde/sde_kms.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index b416840b5f7c..c7c4b224ee73 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1255,6 +1255,16 @@ static void _sde_kms_release_splash_resource(struct sde_kms *sde_kms, SDE_EVT32(DRMID(crtc), crtc->state->active, sde_kms->splash_data.num_splash_displays); + /*remove all votes if eDP displays are done with splash*/ + if (dp_display_get_num_of_boot_displays()) { + for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) + sde_power_data_bus_set_quota(phandle, i, + SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA, + phandle->ib_quota[i]); + pm_runtime_put_sync(sde_kms->dev->dev); + sde_kms->splash_data.num_splash_displays--; + } + for (i = 0; i < MAX_DSI_DISPLAYS; i++) { splash_display = &sde_kms->splash_data.splash_display[i]; if (splash_display->encoder &&