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);