瀏覽代碼

disp: msm: sde: add allowed_dsc_reservation_switch capability

This change adds allowed_dsc_reservation_switch to determine if
dsc seamless switch is supported for DP. Also, based on the
flag, it determines and populates the required number of
available resources for DP.

Change-Id: I9cd7219a50d352369c5bc8386ce7dc25c30b80b6
Signed-off-by: Raviteja Tamatam <[email protected]>
Raviteja Tamatam 4 年之前
父節點
當前提交
3789258773

+ 3 - 0
include/uapi/display/drm/sde_drm.h

@@ -453,6 +453,9 @@ struct sde_drm_color {
 /* Color fill outside of the rect, excluding border */
 #define SDE_DRM_DIM_LAYER_EXCLUSIVE     0x2
 
+ /* bitmask for allowed_dsc_reservation_switch property */
+#define SDE_DP_DSC_RESERVATION_SWITCH (1 << 0)
+
 /**
  * struct sde_drm_dim_layer - dim layer cfg struct
  * @flags:         Refer SDE_DRM_DIM_LAYER_CONFIG_FLAG for possible values

+ 19 - 0
msm/dsi/dsi_display.c

@@ -6447,6 +6447,16 @@ struct drm_panel *dsi_display_get_drm_panel(struct dsi_display *display)
 	return &display->panel->drm_panel;
 }
 
+bool dsi_display_has_dsc_switch_support(struct dsi_display *display)
+{
+	if (!display || !display->panel) {
+		pr_err("invalid param(s)\n");
+		return false;
+	}
+
+	return display->panel->dsc_switch_supported;
+}
+
 int dsi_display_drm_ext_bridge_init(struct dsi_display *display,
 		struct drm_encoder *encoder, struct drm_connector *connector)
 {
@@ -6846,6 +6856,7 @@ int dsi_display_get_modes(struct dsi_display *display,
 	u32 sublinks_count, mode_idx, array_idx = 0;
 	struct dsi_dyn_clk_caps *dyn_clk_caps;
 	int i, start, end, rc = -EINVAL;
+	int dsc_modes = 0, nondsc_modes = 0;
 
 	if (!display || !out_modes) {
 		DSI_ERR("Invalid params\n");
@@ -6910,6 +6921,11 @@ int dsi_display_get_modes(struct dsi_display *display,
 		support_cmd_mode = display_mode.panel_mode_caps & DSI_OP_CMD_MODE;
 		support_video_mode = display_mode.panel_mode_caps & DSI_OP_VIDEO_MODE;
 
+		if (display_mode.priv_info->dsc_enabled)
+			dsc_modes++;
+		else
+			nondsc_modes++;
+
 		/* Setup widebus support */
 		display_mode.priv_info->widebus_support =
 				ctrl->ctrl->hw.widebus_support;
@@ -6987,6 +7003,9 @@ int dsi_display_get_modes(struct dsi_display *display,
 		}
 	}
 
+	if (dsc_modes && nondsc_modes)
+		display->panel->dsc_switch_supported = true;
+
 exit:
 	*out_modes = display->modes;
 	rc = 0;

+ 8 - 0
msm/dsi/dsi_display.h

@@ -648,6 +648,14 @@ int dsi_dispaly_static_frame(struct dsi_display *display, bool enable);
  */
 struct drm_panel *dsi_display_get_drm_panel(struct dsi_display *display);
 
+/**
+ * dsi_display_has_dsc_switch_support() - check if dsc switch is supported.
+ * @display:            Handle to display.
+ *
+ * Return: True of panel supports both dsc and non-dsc modes.
+ */
+bool dsi_display_has_dsc_switch_support(struct dsi_display *display);
+
 /**
  * dsi_display_enable_event() - enable interrupt based connector event
  * @connector:          Pointer to drm connector structure

+ 8 - 0
msm/dsi/dsi_panel.c

@@ -3025,6 +3025,14 @@ static int dsi_panel_parse_topology(
 		goto parse_fail;
 	}
 
+	if (!(priv_info->dsc_enabled || priv_info->vdc_enabled) !=
+			!topology[top_sel].num_enc) {
+		DSI_ERR("topology and compression info mismatch dsc:%d vdc:%d num_enc:%d\n",
+			priv_info->dsc_enabled, priv_info->vdc_enabled,
+			topology[top_sel].num_enc);
+		goto parse_fail;
+	}
+
 	if (priv_info->dsc_enabled)
 		topology[top_sel].comp_type = MSM_DISPLAY_COMPRESSION_DSC;
 	else if (priv_info->vdc_enabled)

+ 1 - 0
msm/dsi/dsi_panel.h

@@ -228,6 +228,7 @@ struct dsi_panel {
 	struct dsi_dfps_capabilities dfps_caps;
 	struct dsi_dyn_clk_caps dyn_clk_caps;
 	struct dsi_panel_phy_props phy_props;
+	bool dsc_switch_supported;
 
 	struct dsi_display_mode *cur_mode;
 	u32 num_timing_nodes;

+ 6 - 0
msm/sde/sde_connector.c

@@ -411,6 +411,7 @@ static void sde_connector_get_avail_res_info(struct drm_connector *conn,
 {
 	struct sde_kms *sde_kms;
 	struct drm_encoder *drm_enc = NULL;
+	struct sde_connector *sde_conn;
 
 	sde_kms = _sde_connector_get_kms(conn);
 	if (!sde_kms) {
@@ -418,12 +419,17 @@ static void sde_connector_get_avail_res_info(struct drm_connector *conn,
 		return;
 	}
 
+	sde_conn = to_sde_connector(conn);
 	if (conn->state && conn->state->best_encoder)
 		drm_enc = conn->state->best_encoder;
 	else
 		drm_enc = conn->encoder;
 
 	sde_rm_get_resource_info(&sde_kms->rm, drm_enc, avail_res);
+	if ((sde_kms->catalog->allowed_dsc_reservation_switch &
+		SDE_DP_DSC_RESERVATION_SWITCH) &&
+		sde_conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort)
+		avail_res->num_dsc = sde_kms->catalog->dsc_count;
 
 	avail_res->max_mixer_width = sde_kms->catalog->max_mixer_width;
 }

+ 11 - 0
msm/sde/sde_crtc.c

@@ -5628,6 +5628,10 @@ static void sde_crtc_setup_capabilities_blob(struct sde_kms_info *info,
 	sde_kms_info_add_keyint(info, "skip_inline_rot_threshold",
 			catalog->skip_inline_rot_threshold);
 
+	if (catalog->allowed_dsc_reservation_switch)
+		sde_kms_info_add_keyint(info, "allowed_dsc_reservation_switch",
+			catalog->allowed_dsc_reservation_switch);
+
 	if (catalog->uidle_cfg.uidle_rev)
 		sde_kms_info_add_keyint(info, "has_uidle",
 			true);
@@ -5816,6 +5820,8 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
 					catalog->demura_count);
 	}
 
+	sde_kms_info_add_keyint(info, "dsc_block_count", catalog->dsc_count);
+
 	msm_property_install_blob(&sde_crtc->property_info, "capabilities",
 		DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_INFO);
 
@@ -7137,6 +7143,11 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
 		return ERR_PTR(rc);
 	}
 
+	if (kms->catalog->allowed_dsc_reservation_switch && !kms->dsc_switch_support) {
+		SDE_DEBUG("dsc switch not supported\n");
+		kms->catalog->allowed_dsc_reservation_switch = 0;
+	}
+
 	/* create CRTC properties */
 	msm_property_init(&sde_crtc->property_info, &crtc->base, dev,
 			priv->crtc_property, sde_crtc->property_data,

+ 2 - 0
msm/sde/sde_hw_catalog.h

@@ -1500,6 +1500,7 @@ struct sde_perf_cfg {
  * @ubwc_bw_calc_version indicate how UBWC BW has to be calculated
  * @skip_inline_rot_thresh    Skip inline rotation threshold
  * @has_idle_pc        indicate if idle power collapse feature is supported
+ * @allowed_dsc_reservation_switch  intf to which dsc reservation switch is supported
  * @wakeup_with_touch  indicate early wake up display with input touch event
  * @has_hdr            HDR feature support
  * @has_hdr_plus       HDR10+ feature support
@@ -1590,6 +1591,7 @@ struct sde_mdss_cfg {
 	u32 ubwc_bw_calc_version;
 	bool skip_inline_rot_threshold;
 	bool has_idle_pc;
+	u32 allowed_dsc_reservation_switch;
 	bool wakeup_with_touch;
 	u32 vbif_qos_nlvl;
 	u32 ts_prefill_rev;

+ 6 - 0
msm/sde/sde_kms.c

@@ -1932,6 +1932,9 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 
 		dsc_count += info.dsc_count;
 		mixer_count += info.lm_count;
+
+		if (dsi_display_has_dsc_switch_support(display))
+			sde_kms->dsc_switch_support = true;
 	}
 
 	max_dp_mixer_count = sde_kms->catalog->mixer_count > mixer_count ?
@@ -1939,6 +1942,9 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 	max_dp_dsc_count = sde_kms->catalog->dsc_count > dsc_count ?
 				sde_kms->catalog->dsc_count - dsc_count : 0;
 
+	if (sde_kms->catalog->allowed_dsc_reservation_switch &
+			SDE_DP_DSC_RESERVATION_SWITCH)
+		max_dp_dsc_count = sde_kms->catalog->dsc_count;
 	/* dp */
 	for (i = 0; i < sde_kms->dp_display_count &&
 			priv->num_encoders < max_encoders; ++i) {

+ 1 - 0
msm/sde/sde_kms.h

@@ -294,6 +294,7 @@ struct sde_kms {
 	int dp_display_count;
 	void **dp_displays;
 	int dp_stream_count;
+	bool dsc_switch_support;
 
 	bool has_danger_ctrl;