Эх сурвалжийг харах

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 <[email protected]>
Dhaval Patel 5 жил өмнө
parent
commit
83860f0642

+ 2 - 0
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);

+ 4 - 1
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:

+ 10 - 3
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);
 

+ 3 - 0
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;

+ 49 - 0
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 :

+ 2 - 0
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;

+ 7 - 0
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

+ 12 - 1
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);