From 83860f06427c368adbd3f6c7eee86755e9ab718e Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Sun, 7 Jun 2020 12:58:49 -0700 Subject: [PATCH] disp: msm: pass free dsc and lm availability info to dp Primary and secondary dsi displays are built-in displays and they are supported during all concurrency usecases without resource allocation failure. DP mode filter logic should provide supported mode information based on free mdp resources after dsi resource assignment. Change-Id: I3a9637a91ea1ffcc31997e25caff7f13605283ac Signed-off-by: Dhaval Patel --- msm/dp/dp_display.h | 2 ++ msm/dp/dp_drm.c | 5 ++++- msm/dp/dp_drm.h | 13 +++++++++--- msm/dsi/dsi_display.c | 3 +++ msm/dsi/dsi_panel.c | 49 +++++++++++++++++++++++++++++++++++++++++++ msm/dsi/dsi_panel.h | 2 ++ msm/msm_drv.h | 7 +++++++ msm/sde/sde_kms.c | 13 +++++++++++- 8 files changed, 89 insertions(+), 5 deletions(-) diff --git a/msm/dp/dp_display.h b/msm/dp/dp_display.h index 5c4f1bbd73..5bb2a74ad4 100644 --- a/msm/dp/dp_display.h +++ b/msm/dp/dp_display.h @@ -71,6 +71,8 @@ struct dp_display { bool is_mst_supported; u32 max_pclk_khz; void *dp_mst_prv_info; + u32 max_mixer_count; + u32 max_dsc_count; int (*enable)(struct dp_display *dp_display, void *panel); int (*post_enable)(struct dp_display *dp_display, void *panel); diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index fbe5ee8736..dd9b80fd76 100644 --- a/msm/dp/dp_drm.c +++ b/msm/dp/dp_drm.c @@ -582,7 +582,8 @@ int dp_connector_get_modes(struct drm_connector *connector, return rc; } -int dp_drm_bridge_init(void *data, struct drm_encoder *encoder) +int dp_drm_bridge_init(void *data, struct drm_encoder *encoder, + u32 max_mixer_count, u32 max_dsc_count) { int rc = 0; struct dp_bridge *bridge; @@ -618,6 +619,8 @@ int dp_drm_bridge_init(void *data, struct drm_encoder *encoder) encoder->bridge = &bridge->base; priv->bridges[priv->num_bridges++] = &bridge->base; display->bridge = bridge; + display->max_mixer_count = max_mixer_count; + display->max_dsc_count = max_dsc_count; return 0; error_free_bridge: diff --git a/msm/dp/dp_drm.h b/msm/dp/dp_drm.h index 2f1f107d2d..0ff7a67f52 100644 --- a/msm/dp/dp_drm.h +++ b/msm/dp/dp_drm.h @@ -123,14 +123,21 @@ int dp_connector_get_info(struct drm_connector *connector, struct msm_display_info *info, void *display); /** - * dp_connector_post_open - handle the post open functionalites + * dp_connector_post_open - handle the post open functionalities * @connector: Pointer to drm connector structure * @display: Pointer to private display structure */ void dp_connector_post_open(struct drm_connector *connector, void *display); -int dp_drm_bridge_init(void *display, - struct drm_encoder *encoder); +/** + * dp_drm_bridge_init- drm dp bridge initialize + * @display: Pointer to private display structure + * @encoder: encoder for this dp bridge + * @max_mixer_count: max available mixers for dp display + * @max_dsc_count: max available dsc for dp display + */ +int dp_drm_bridge_init(void *display, struct drm_encoder *encoder, + u32 max_mixer_count, u32 max_dsc_count); void dp_drm_bridge_deinit(void *display); diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 9dbb13bf69..2396b63f22 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -6040,6 +6040,9 @@ int dsi_display_get_info(struct drm_connector *connector, host = &display->panel->host_config; if (host->split_link.split_link_enabled) info->capabilities |= MSM_DISPLAY_SPLIT_LINK; + + info->dsc_count = display->panel->dsc_count; + info->lm_count = display->panel->lm_count; error: mutex_unlock(&display->display_lock); return rc; diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 91a52b7485..9e94281b1b 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -3431,6 +3431,49 @@ int dsi_panel_validate_mode(struct dsi_panel *panel, return 0; } +static int dsi_panel_get_max_res_count(struct dsi_parser_utils *utils, + struct device_node *node, u32 *dsc_count, u32 *lm_count) +{ + const char *compression; + u32 *array = NULL, top_count, len, i; + int rc = -EINVAL; + bool dsc_enable = false; + + *dsc_count = 0; + *lm_count = 0; + compression = utils->get_property(node, "qcom,compression-mode", NULL); + if (compression && !strcmp(compression, "dsc")) + dsc_enable = true; + + len = utils->count_u32_elems(node, "qcom,display-topology"); + if (len <= 0 || len % TOPOLOGY_SET_LEN || + len > (TOPOLOGY_SET_LEN * MAX_TOPOLOGY)) + return rc; + + top_count = len / TOPOLOGY_SET_LEN; + + array = kcalloc(len, sizeof(u32), GFP_KERNEL); + if (!array) + return -ENOMEM; + + rc = utils->read_u32_array(node, "qcom,display-topology", array, len); + if (rc) { + DSI_ERR("unable to read the display topologies, rc = %d\n", rc); + goto read_fail; + } + + for (i = 0; i < top_count; i++) { + *lm_count = max(*lm_count, array[i * TOPOLOGY_SET_LEN]); + if (dsc_enable) + *dsc_count = max(*dsc_count, + array[i * TOPOLOGY_SET_LEN + 1]); + } + +read_fail: + kfree(array); + return 0; +} + int dsi_panel_get_mode_count(struct dsi_panel *panel) { const u32 SINGLE_MODE_SUPPORT = 1; @@ -3439,6 +3482,7 @@ int dsi_panel_get_mode_count(struct dsi_panel *panel) int num_dfps_rates, num_bit_clks; int num_video_modes = 0, num_cmd_modes = 0; int count, rc = 0; + u32 dsc_count = 0, lm_count = 0; if (!panel) { DSI_ERR("invalid params\n"); @@ -3484,6 +3528,11 @@ int dsi_panel_get_mode_count(struct dsi_panel *panel) num_video_modes++; else if (panel->panel_mode == DSI_OP_CMD_MODE) num_cmd_modes++; + + dsi_panel_get_max_res_count(utils, child_np, + &dsc_count, &lm_count); + panel->dsc_count = max(dsc_count, panel->dsc_count); + panel->lm_count = max(lm_count, panel->lm_count); } num_dfps_rates = !panel->dfps_caps.dfps_support ? 1 : diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index e6831c5e1c..195d5464ee 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -221,6 +221,8 @@ struct dsi_panel { struct dsi_panel_spr_info spr_info; bool sync_broadcast_en; + u32 dsc_count; + u32 lm_count; int panel_test_gpio; int power_mode; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index d1f6d440a0..88990df459 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -723,6 +723,10 @@ struct msm_resource_caps_info { * @roi_caps: Region of interest capability info * @qsync_min_fps Minimum fps supported by Qsync feature * @te_source vsync source pin information + * @dsc_count: max dsc hw blocks used by display (only available + * for dsi display) + * @lm_count: max layer mixer blocks used by display (only available + * for dsi display) */ struct msm_display_info { int intf_type; @@ -747,6 +751,9 @@ struct msm_display_info { uint32_t qsync_min_fps; uint32_t te_source; + + uint32_t dsc_count; + uint32_t lm_count; }; #define MSM_MAX_ROI 4 diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index b335f9ab0c..c1602ab3f7 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1333,6 +1333,8 @@ static int _sde_kms_setup_displays(struct drm_device *dev, void *display, *connector; int i, max_encoders; int rc = 0; + u32 dsc_count = 0, mixer_count = 0; + u32 max_dp_dsc_count, max_dp_mixer_count; if (!dev || !priv || !sde_kms) { SDE_ERROR("invalid argument(s)\n"); @@ -1441,8 +1443,16 @@ static int _sde_kms_setup_displays(struct drm_device *dev, sde_connector_destroy(connector); sde_encoder_destroy(encoder); } + + dsc_count += info.dsc_count; + mixer_count += info.lm_count; } + max_dp_mixer_count = sde_kms->catalog->mixer_count > mixer_count ? + sde_kms->catalog->mixer_count - mixer_count : 0; + max_dp_dsc_count = sde_kms->catalog->dsc_count > dsc_count ? + sde_kms->catalog->dsc_count - dsc_count : 0; + /* dp */ for (i = 0; i < sde_kms->dp_display_count && priv->num_encoders < max_encoders; ++i) { @@ -1464,7 +1474,8 @@ static int _sde_kms_setup_displays(struct drm_device *dev, continue; } - rc = dp_drm_bridge_init(display, encoder); + rc = dp_drm_bridge_init(display, encoder, + max_dp_mixer_count, max_dp_dsc_count); if (rc) { SDE_ERROR("dp bridge %d init failed, %d\n", i, rc); sde_encoder_destroy(encoder);