Kaynağa Gözat

disp: msm: sde: correct num_datapath during PM resume with CWB

In PM resume with CWB concurrency usecase, crtc pointer in
conn->state is NULL since drm_mode_config_reset operation is
performed on pm_resume. This change relies on conn_mask in
new_crtc_state for primary connector retrieval and also adds
get_num_lm_from_mode callback to DSI for LM count retrieval
from dsi panel topology. Existing get_mode_info api cannot
retrieve the topology info because mode->priv_info is NULL.
This occurs as WB encoder is added in the drm encoder_list
before primary encoder, introduced as part of commit d28ebf05f4aa
("disp: msm: sde: populate WB display encoder list before dsi").

Change-Id: I55358fd88ab778bd81475cf3628be13335de1cb5
Signed-off-by: Jayaprakash Madisetty <[email protected]>
Signed-off-by: Samantha Tran <[email protected]>
Jayaprakash Madisetty 4 yıl önce
ebeveyn
işleme
a29369e224

+ 9 - 0
msm/dsi/dsi_display.h

@@ -437,6 +437,15 @@ int dsi_display_get_qsync_min_fps(void *dsi_display, u32 mode_fps);
  */
 int dsi_display_get_avr_step_req_fps(void *dsi_display, u32 mode_fps);
 
+/*
+ * dsi_conn_get_lm_from_mode() - retrieves LM count from dsi mode priv info
+ * @display:            Handle to display.
+ * @mode:               Pointer to DRM mode structure
+ *
+ * Return: LM count from dsi panel topology
+ */
+int dsi_conn_get_lm_from_mode(void *dsi_display, const struct drm_display_mode *mode);
+
 /**
  * dsi_display_find_mode() - retrieve cached DSI mode given relevant params
  * @display:            Handle to display.

+ 23 - 0
msm/dsi/dsi_drm.c

@@ -549,6 +549,29 @@ u32 dsi_drm_get_dfps_maxfps(void *display)
 	return dfps_maxfps;
 }
 
+int dsi_conn_get_lm_from_mode(void *display, const struct drm_display_mode *drm_mode)
+{
+	struct dsi_display *dsi_display = display;
+	struct dsi_display_mode dsi_mode, *panel_dsi_mode;
+	int rc = -EINVAL;
+
+	if (!dsi_display || !drm_mode) {
+		DSI_ERR("Invalid params %d %d\n", !display, !drm_mode);
+		return rc;
+	}
+
+	convert_to_dsi_mode(drm_mode, &dsi_mode);
+
+	rc = dsi_display_find_mode(dsi_display, &dsi_mode, NULL, &panel_dsi_mode);
+	if (rc) {
+		DSI_ERR("mode not found %d\n", rc);
+		drm_mode_debug_printmodeline(drm_mode);
+		return rc;
+	}
+
+	return panel_dsi_mode->priv_info->topology.num_lm;
+}
+
 int dsi_conn_get_mode_info(struct drm_connector *connector,
 		const struct drm_display_mode *drm_mode,
 		struct msm_sub_mode *sub_mode,

+ 14 - 0
msm/sde/sde_connector.c

@@ -475,6 +475,20 @@ int sde_connector_set_msm_mode(struct drm_connector_state *conn_state,
 	return 0;
 }
 
+int sde_connector_get_lm_cnt_from_topology(struct drm_connector *conn,
+		const struct drm_display_mode *drm_mode)
+{
+	struct sde_connector *c_conn;
+
+	c_conn = to_sde_connector(conn);
+
+	if (!c_conn || c_conn->connector_type != DRM_MODE_CONNECTOR_DSI ||
+		!c_conn->ops.get_num_lm_from_mode)
+		return -EINVAL;
+
+	return c_conn->ops.get_num_lm_from_mode(c_conn->display, drm_mode);
+}
+
 int sde_connector_get_mode_info(struct drm_connector *conn,
 		const struct drm_display_mode *drm_mode,
 		struct msm_sub_mode *sub_mode,

+ 17 - 0
msm/sde/sde_connector.h

@@ -422,6 +422,14 @@ struct sde_connector_ops {
 	 */
 	void (*set_submode_info)(struct drm_connector *conn,
 		void *info, void *display, struct drm_display_mode *drm_mode);
+
+	/*
+	 * get_num_lm_from_mode - Get LM count from topology for this drm mode
+	 * @display: Pointer to private display structure
+	 * @mode: Pointer to drm mode info structure
+	 */
+	int (*get_num_lm_from_mode)(void *display, const struct drm_display_mode *mode);
+
 };
 
 /**
@@ -1063,6 +1071,15 @@ int sde_connector_helper_reset_custom_properties(
 int sde_connector_state_get_mode_info(struct drm_connector_state *conn_state,
 	struct msm_mode_info *mode_info);
 
+/**
+ * sde_connector_get_lm_cnt_from_topology - retrieves the topology info
+ *	from the panel mode and returns the lm count.
+ * conn: Pointer to DRM connector object
+ * drm_mode: Pointer to the drm mode structure
+ */
+int sde_connector_get_lm_cnt_from_topology(struct drm_connector *conn,
+	 const struct drm_display_mode *drm_mode);
+
 /**
  * sde_connector_state_get_topology - get topology from given connector state
  * conn_state: Pointer to the DRM connector state object

+ 28 - 11
msm/sde/sde_crtc.c

@@ -5390,40 +5390,57 @@ end:
 }
 
 /**
- * sde_crtc_get_num_datapath - get the number of datapath active
- *				of primary connector
+ * sde_crtc_get_num_datapath - get the number of layermixers active
+ *				on primary connector
  * @crtc: Pointer to DRM crtc object
- * @connector: Pointer to DRM connector object of WB in CWB case
+ * @virtual_conn: Pointer to DRM connector object of WB in CWB case
+ * @crtc_state:	Pointer to DRM crtc state
  */
 int sde_crtc_get_num_datapath(struct drm_crtc *crtc,
-		struct drm_connector *connector)
+	struct drm_connector *virtual_conn, struct drm_crtc_state *crtc_state)
 {
 	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
+	struct drm_connector *conn, *primary_conn = NULL;
 	struct sde_connector_state *sde_conn_state = NULL;
-	struct drm_connector *conn;
 	struct drm_connector_list_iter conn_iter;
+	int num_lm = 0;
 
-	if (!sde_crtc || !connector) {
+	if (!sde_crtc || !virtual_conn || !crtc_state) {
 		SDE_DEBUG("Invalid argument\n");
 		return 0;
 	}
 
+	/* return num_mixers used for primary when available in sde_crtc */
 	if (sde_crtc->num_mixers)
 		return sde_crtc->num_mixers;
 
 	drm_connector_list_iter_begin(crtc->dev, &conn_iter);
 	drm_for_each_connector_iter(conn, &conn_iter) {
-		if (conn->state && conn->state->crtc == crtc &&
-				 conn != connector)
+		if ((drm_connector_mask(conn) & crtc_state->connector_mask)
+			 && conn != virtual_conn) {
 			sde_conn_state = to_sde_connector_state(conn->state);
+			primary_conn = conn;
+			break;
+		}
 	}
-
 	drm_connector_list_iter_end(&conn_iter);
 
+	/* if primary sde_conn_state has mode info available, return num_lm from here */
 	if (sde_conn_state)
-		return sde_conn_state->mode_info.topology.num_lm;
+		num_lm = sde_conn_state->mode_info.topology.num_lm;
+
+	/* if PM resume occurs with CWB enabled, retrieve num_lm from primary dsi panel mode */
+	if (primary_conn && !num_lm) {
+		num_lm = sde_connector_get_lm_cnt_from_topology(primary_conn,
+				&crtc_state->adjusted_mode);
+		if (num_lm < 0) {
+			SDE_DEBUG("lm cnt fail for conn:%d num_lm:%d\n",
+					 primary_conn->base.id, num_lm);
+			num_lm = 0;
+		}
+	}
 
-	return 0;
+	return num_lm;
 }
 
 int sde_crtc_vblank(struct drm_crtc *crtc, bool en)

+ 2 - 1
msm/sde/sde_crtc.h

@@ -1003,9 +1003,10 @@ void sde_crtc_static_cache_read_kickoff(struct drm_crtc *crtc);
  *				of primary connector
  * @crtc: Pointer to DRM crtc object
  * @connector: Pointer to DRM connector object of WB in CWB case
+ * @crtc_state:	Pointer to DRM crtc state
  */
 int sde_crtc_get_num_datapath(struct drm_crtc *crtc,
-		struct drm_connector *connector);
+	struct drm_connector *connector, struct drm_crtc_state *crtc_state);
 
 /**
  * sde_crtc_reset_sw_state - reset dirty proerties on crtc and

+ 1 - 0
msm/sde/sde_kms.c

@@ -1763,6 +1763,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 		.get_avr_step_req = dsi_display_get_avr_step_req_fps,
 		.prepare_commit = dsi_conn_prepare_commit,
 		.set_submode_info = dsi_conn_set_submode_blob_info,
+		.get_num_lm_from_mode = dsi_conn_get_lm_from_mode,
 	};
 	static const struct sde_connector_ops wb_ops = {
 		.post_init =    sde_wb_connector_post_init,

+ 1 - 1
msm/sde/sde_rm.c

@@ -2152,7 +2152,7 @@ static int _sde_rm_populate_requirements(
 			&rm->topology_tbl[SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE];
 
 		num_lm = sde_crtc_get_num_datapath(crtc_state->crtc,
-				conn_state->connector);
+				conn_state->connector, crtc_state);
 
 		if (num_lm == 1)
 			reqs->topology =