Pārlūkot izejas kodu

Merge "disp: msm: sde: reduce complexity in sde_encoder_virt_mode_set"

qctecmdr 5 gadi atpakaļ
vecāks
revīzija
62287d239e
1 mainītis faili ar 136 papildinājumiem un 101 dzēšanām
  1. 136 101
      msm/sde/sde_encoder.c

+ 136 - 101
msm/sde/sde_encoder.c

@@ -2066,54 +2066,13 @@ static void sde_encoder_virt_mode_switch(struct drm_encoder *drm_enc,
 	}
 	}
 }
 }
 
 
-static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
-				      struct drm_display_mode *mode,
-				      struct drm_display_mode *adj_mode)
+static struct drm_connector *_sde_encoder_get_connector(
+		struct drm_device *dev, struct drm_encoder *drm_enc)
 {
 {
-	struct sde_encoder_virt *sde_enc;
-	struct sde_kms *sde_kms;
 	struct drm_connector_list_iter conn_iter;
 	struct drm_connector_list_iter conn_iter;
 	struct drm_connector *conn = NULL, *conn_search;
 	struct drm_connector *conn = NULL, *conn_search;
-	struct sde_rm_hw_iter dsc_iter, pp_iter, qdss_iter;
-	struct sde_rm_hw_iter vdc_iter;
-	struct sde_rm_hw_request request_hw;
-	enum sde_intf_mode intf_mode;
-	bool is_cmd_mode = false;
-	int i = 0, ret;
-
-	if (!drm_enc) {
-		SDE_ERROR("invalid encoder\n");
-		return;
-	}
-
-	if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) {
-		SDE_ERROR("power resource is not enabled\n");
-		return;
-	}
-
-	sde_enc = to_sde_encoder_virt(drm_enc);
-	SDE_DEBUG_ENC(sde_enc, "\n");
-
-	if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE))
-		is_cmd_mode = true;
 
 
-	sde_kms = sde_encoder_get_kms(drm_enc);
-	if (!sde_kms)
-		return;
-
-	SDE_EVT32(DRMID(drm_enc));
-
-	/*
-	 * cache the crtc in sde_enc on enable for duration of use case
-	 * for correctly servicing asynchronous irq events and timers
-	 */
-	if (!drm_enc->crtc) {
-		SDE_ERROR("invalid crtc\n");
-		return;
-	}
-	sde_enc->crtc = drm_enc->crtc;
-
-	drm_connector_list_iter_begin(sde_kms->dev, &conn_iter);
+	drm_connector_list_iter_begin(dev, &conn_iter);
 	drm_for_each_connector_iter(conn_search, &conn_iter) {
 	drm_for_each_connector_iter(conn_search, &conn_iter) {
 		if (conn_search->encoder == drm_enc) {
 		if (conn_search->encoder == drm_enc) {
 			conn = conn_search;
 			conn = conn_search;
@@ -2122,56 +2081,17 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	}
 	}
 	drm_connector_list_iter_end(&conn_iter);
 	drm_connector_list_iter_end(&conn_iter);
 
 
-	sde_crtc_set_qos_dirty(sde_enc->crtc);
-
-	if (!conn) {
-		SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n");
-		return;
-	} else if (!conn->state) {
-		SDE_ERROR_ENC(sde_enc, "invalid connector state\n");
-		return;
-	}
-
-	intf_mode = sde_encoder_get_intf_mode(drm_enc);
-
-	/* store the mode_info */
-	sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info);
-
-	sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc);
-
-	/* release resources before seamless mode change */
-	if (msm_is_mode_seamless_dms(adj_mode) ||
-			(msm_is_mode_seamless_dyn_clk(adj_mode) &&
-			 is_cmd_mode)) {
-		/* restore resource state before releasing them */
-		ret = sde_encoder_resource_control(drm_enc,
-				SDE_ENC_RC_EVENT_PRE_MODESET);
-		if (ret) {
-			SDE_ERROR_ENC(sde_enc,
-					"sde resource control failed: %d\n",
-					ret);
-			return;
-		}
-
-		/*
-		 * Disable dce before switch the mode and after pre_modeset,
-		 * to guarantee that previous kickoff finished.
-		 */
-		sde_encoder_dce_disable(sde_enc);
-	} else if (msm_is_mode_seamless_poms(adj_mode)) {
-		_sde_encoder_modeset_helper_locked(drm_enc,
-					SDE_ENC_RC_EVENT_PRE_MODESET);
-		sde_encoder_virt_mode_switch(drm_enc, intf_mode, adj_mode);
-	}
+	return conn;
+}
 
 
-	/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
-	ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state,
-			conn->state, false);
-	if (ret) {
-		SDE_ERROR_ENC(sde_enc,
-				"failed to reserve hw resources, %d\n", ret);
-		return;
-	}
+static void _sde_encoder_virt_populate_hw_res(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
+	struct sde_kms *sde_kms = sde_encoder_get_kms(drm_enc);
+	struct sde_rm_hw_iter pp_iter, qdss_iter;
+	struct sde_rm_hw_iter dsc_iter, vdc_iter;
+	struct sde_rm_hw_request request_hw;
+	int i;
 
 
 	sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG);
 	sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG);
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
@@ -2233,7 +2153,129 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 		else
 		else
 			sde_enc->hw_dsc_pp[i] = NULL;
 			sde_enc->hw_dsc_pp[i] = NULL;
 	}
 	}
+}
+
+static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc,
+		struct drm_display_mode *adj_mode, bool pre_modeset)
+{
+	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
+	enum sde_intf_mode intf_mode;
+	int ret;
+	bool is_cmd_mode;
+
+	if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE))
+		is_cmd_mode = true;
+
+	if (pre_modeset) {
+		intf_mode = sde_encoder_get_intf_mode(drm_enc);
+		if (msm_is_mode_seamless_dms(adj_mode) ||
+				(msm_is_mode_seamless_dyn_clk(adj_mode) &&
+				 is_cmd_mode)) {
+			/* restore resource state before releasing them */
+			ret = sde_encoder_resource_control(drm_enc,
+					SDE_ENC_RC_EVENT_PRE_MODESET);
+			if (ret) {
+				SDE_ERROR_ENC(sde_enc,
+					"sde resource control failed: %d\n",
+					ret);
+				return ret;
+			}
+
+			/*
+			 * Disable dce before switching the mode and after pre-
+			 * modeset to guarantee previous kickoff has finished.
+			 */
+			sde_encoder_dce_disable(sde_enc);
+		} else if (msm_is_mode_seamless_poms(adj_mode)) {
+			_sde_encoder_modeset_helper_locked(drm_enc,
+					SDE_ENC_RC_EVENT_PRE_MODESET);
+			sde_encoder_virt_mode_switch(drm_enc, intf_mode,
+					adj_mode);
+		}
+	} else {
+		if (msm_is_mode_seamless_dms(adj_mode) ||
+				(msm_is_mode_seamless_dyn_clk(adj_mode) &&
+				is_cmd_mode))
+			sde_encoder_resource_control(&sde_enc->base,
+					SDE_ENC_RC_EVENT_POST_MODESET);
+		else if (msm_is_mode_seamless_poms(adj_mode))
+			_sde_encoder_modeset_helper_locked(drm_enc,
+					SDE_ENC_RC_EVENT_POST_MODESET);
+	}
+
+	return 0;
+}
+
+static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
+				      struct drm_display_mode *mode,
+				      struct drm_display_mode *adj_mode)
+{
+	struct sde_encoder_virt *sde_enc;
+	struct sde_kms *sde_kms;
+	struct drm_connector *conn;
+	int i = 0, ret;
+
+	if (!drm_enc) {
+		SDE_ERROR("invalid encoder\n");
+		return;
+	}
+
+	if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) {
+		SDE_ERROR("power resource is not enabled\n");
+		return;
+	}
+
+	sde_kms = sde_encoder_get_kms(drm_enc);
+	if (!sde_kms)
+		return;
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+	SDE_DEBUG_ENC(sde_enc, "\n");
+	SDE_EVT32(DRMID(drm_enc));
+
+	/*
+	 * cache the crtc in sde_enc on enable for duration of use case
+	 * for correctly servicing asynchronous irq events and timers
+	 */
+	if (!drm_enc->crtc) {
+		SDE_ERROR("invalid crtc\n");
+		return;
+	}
+
+	sde_enc->crtc = drm_enc->crtc;
+	sde_crtc_set_qos_dirty(drm_enc->crtc);
+
+	/* get and store the mode_info */
+	conn = _sde_encoder_get_connector(sde_kms->dev, drm_enc);
+	if (!conn) {
+		SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n");
+		return;
+	} else if (!conn->state) {
+		SDE_ERROR_ENC(sde_enc, "invalid connector state\n");
+		return;
+	}
+
+	sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info);
+	sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc);
+
+	/* release resources before seamless mode change */
+	ret = sde_encoder_virt_modeset_rc(drm_enc, adj_mode, true);
+	if (ret)
+		return;
+
+	/* reserve dynamic resources now, indicating non test-only */
+	ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state,
+			conn->state, false);
+	if (ret) {
+		SDE_ERROR_ENC(sde_enc,
+				"failed to reserve hw resources, %d\n", ret);
+		return;
+	}
+
+	/* assign the reserved HW blocks to this encoder */
+	_sde_encoder_virt_populate_hw_res(drm_enc);
 
 
+	/* perform mode_set on phys_encs */
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
 
 
@@ -2251,14 +2293,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	}
 	}
 
 
 	/* update resources after seamless mode change */
 	/* update resources after seamless mode change */
-	if (msm_is_mode_seamless_dms(adj_mode) ||
-			(msm_is_mode_seamless_dyn_clk(adj_mode) &&
-			is_cmd_mode))
-		sde_encoder_resource_control(&sde_enc->base,
-						SDE_ENC_RC_EVENT_POST_MODESET);
-	else if (msm_is_mode_seamless_poms(adj_mode))
-		_sde_encoder_modeset_helper_locked(drm_enc,
-						SDE_ENC_RC_EVENT_POST_MODESET);
+	sde_encoder_virt_modeset_rc(drm_enc, adj_mode, false);
 }
 }
 
 
 void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable)
 void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable)