Browse Source

disp: msm: sde: use dnsc_blur src w/h for calculating crtc/lm w/h

When downscale blur feature is enabled, calculate the mixex and crtc
width and height using the dnsc_blur's src width & height. Update the
sde_crtc_get_mixer width/height functions to return the correct size
based on the features enabled.

Change-Id: I52dd88cc52e1ca5cb37e381e92e0e3032e7b090f
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran 3 years ago
parent
commit
88c9a184f9
3 changed files with 153 additions and 77 deletions
  1. 123 19
      msm/sde/sde_crtc.c
  2. 26 55
      msm/sde/sde_crtc.h
  3. 4 3
      msm/sde/sde_encoder.c

+ 123 - 19
msm/sde/sde_crtc.c

@@ -135,6 +135,100 @@ static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
 	return to_sde_kms(priv->kms);
 	return to_sde_kms(priv->kms);
 }
 }
 
 
+static inline struct drm_connector_state *_sde_crtc_get_virt_conn_state(
+		struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
+{
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state, *virt_conn_state = NULL;
+	struct drm_connector_list_iter conn_iter;
+	int i;
+
+	if (crtc_state->state) {
+		for_each_new_connector_in_state(crtc_state->state, conn, conn_state, i) {
+			if (conn_state && (conn_state->crtc == crtc)
+					&& (conn->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)) {
+				virt_conn_state = conn_state;
+				break;
+			}
+		}
+	} else {
+		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_type == DRM_MODE_CONNECTOR_VIRTUAL)) {
+				virt_conn_state = conn->state;
+				break;
+			}
+		}
+		drm_connector_list_iter_end(&conn_iter);
+	}
+
+	return virt_conn_state;
+}
+
+void sde_crtc_get_mixer_resolution(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state,
+		struct drm_display_mode *mode, u32 *width, u32 *height)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *cstate;
+	struct drm_connector_state *virt_conn_state;
+	struct sde_connector_state *virt_cstate;
+
+	*width = 0;
+	*height = 0;
+
+	if (!crtc || !crtc_state || !mode)
+		return;
+
+	sde_crtc = to_sde_crtc(crtc);
+	cstate = to_sde_crtc_state(crtc_state);
+	virt_conn_state = _sde_crtc_get_virt_conn_state(crtc, crtc_state);
+	virt_cstate = virt_conn_state ? to_sde_connector_state(virt_conn_state) : NULL;
+
+	if (cstate->num_ds_enabled) {
+		*width = cstate->ds_cfg[0].lm_width;
+		*height = cstate->ds_cfg[0].lm_height;
+	} else if (virt_cstate && virt_cstate->dnsc_blur_count) {
+		*width = (virt_cstate->dnsc_blur_cfg[0].src_width
+				* virt_cstate->dnsc_blur_count) / sde_crtc->num_mixers;
+		*height = virt_cstate->dnsc_blur_cfg[0].src_height;
+	} else {
+		*width = mode->hdisplay / sde_crtc->num_mixers;
+		*height = mode->vdisplay;
+	}
+}
+
+void sde_crtc_get_resolution(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state,
+		struct drm_display_mode *mode, u32 *width, u32 *height)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *cstate;
+	struct drm_connector_state *virt_conn_state;
+	struct sde_connector_state *virt_cstate;
+
+	*width = 0;
+	*height = 0;
+
+	if (!crtc || !crtc_state || !mode)
+		return;
+
+	sde_crtc = to_sde_crtc(crtc);
+	cstate = to_sde_crtc_state(crtc_state);
+	virt_conn_state = _sde_crtc_get_virt_conn_state(crtc, crtc_state);
+	virt_cstate = virt_conn_state ? to_sde_connector_state(virt_conn_state) : NULL;
+
+	if (cstate->num_ds_enabled) {
+		*width = cstate->ds_cfg[0].lm_width * cstate->num_ds_enabled;
+		*height = cstate->ds_cfg[0].lm_height;
+	} else if (virt_cstate && virt_cstate->dnsc_blur_count) {
+		*width = virt_cstate->dnsc_blur_cfg[0].src_width * virt_cstate->dnsc_blur_count;
+		*height = virt_cstate->dnsc_blur_cfg[0].src_height;
+	} else {
+		*width = mode->hdisplay;
+		*height = mode->vdisplay;
+	}
+}
+
 /**
 /**
  * sde_crtc_calc_fps() - Calculates fps value.
  * sde_crtc_calc_fps() - Calculates fps value.
  * @sde_crtc   : CRTC structure
  * @sde_crtc   : CRTC structure
@@ -503,6 +597,23 @@ static void sde_crtc_destroy(struct drm_crtc *crtc)
 	kfree(sde_crtc);
 	kfree(sde_crtc);
 }
 }
 
 
+struct sde_connector_state *_sde_crtc_get_sde_connector_state(struct drm_crtc *crtc,
+		struct drm_atomic_state *state)
+{
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	int i;
+
+	for_each_new_connector_in_state(state, conn, conn_state, i) {
+		if (!conn_state || conn_state->crtc != crtc)
+			continue;
+
+		return to_sde_connector_state(conn_state);
+	}
+
+	return NULL;
+}
+
 struct msm_display_mode *sde_crtc_get_msm_mode(struct drm_crtc_state *c_state)
 struct msm_display_mode *sde_crtc_get_msm_mode(struct drm_crtc_state *c_state)
 {
 {
 	struct drm_connector *connector;
 	struct drm_connector *connector;
@@ -906,8 +1017,7 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
 
 
 	/* clear the ROI to null if it matches full screen anyways */
 	/* clear the ROI to null if it matches full screen anyways */
 	adj_mode = &state->adjusted_mode;
 	adj_mode = &state->adjusted_mode;
-	crtc_width = sde_crtc_get_width(sde_crtc, crtc_state, adj_mode);
-	crtc_height = sde_crtc_get_mixer_height(sde_crtc, crtc_state, adj_mode);
+	sde_crtc_get_resolution(crtc, state, adj_mode, &crtc_width, &crtc_height);
 	if (crtc_roi->x == 0 && crtc_roi->y == 0 &&
 	if (crtc_roi->x == 0 && crtc_roi->y == 0 &&
 			crtc_roi->w == crtc_width && crtc_roi->h == crtc_height)
 			crtc_roi->w == crtc_width && crtc_roi->h == crtc_height)
 		memset(crtc_roi, 0, sizeof(*crtc_roi));
 		memset(crtc_roi, 0, sizeof(*crtc_roi));
@@ -3489,10 +3599,9 @@ static void _sde_crtc_setup_lm_bounds(struct drm_crtc *crtc, struct drm_crtc_sta
 
 
 	sde_crtc = to_sde_crtc(crtc);
 	sde_crtc = to_sde_crtc(crtc);
 	cstate = to_sde_crtc_state(state);
 	cstate = to_sde_crtc_state(state);
-
 	adj_mode = &state->adjusted_mode;
 	adj_mode = &state->adjusted_mode;
-	mixer_width = sde_crtc_get_mixer_width(sde_crtc, cstate, adj_mode);
-	mixer_height = sde_crtc_get_mixer_height(sde_crtc, cstate, adj_mode);
+
+	sde_crtc_get_mixer_resolution(crtc, state, adj_mode, &mixer_width, &mixer_height);
 
 
 	for (i = 0; i < sde_crtc->num_mixers; i++) {
 	for (i = 0; i < sde_crtc->num_mixers; i++) {
 		cstate->lm_bounds[i].x = mixer_width * i;
 		cstate->lm_bounds[i].x = mixer_width * i;
@@ -4733,11 +4842,10 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
 }
 }
 
 
 /* no input validation - caller API has all the checks */
 /* no input validation - caller API has all the checks */
-static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state,
+static int _sde_crtc_excl_dim_layer_check(struct drm_crtc *crtc, struct drm_crtc_state *state,
 		struct plane_state pstates[], int cnt)
 		struct plane_state pstates[], int cnt)
 {
 {
 	struct sde_crtc_state *cstate = to_sde_crtc_state(state);
 	struct sde_crtc_state *cstate = to_sde_crtc_state(state);
-	struct sde_crtc *sde_crtc = to_sde_crtc(state->crtc);
 	struct drm_display_mode *mode = &state->adjusted_mode;
 	struct drm_display_mode *mode = &state->adjusted_mode;
 	const struct drm_plane_state *pstate;
 	const struct drm_plane_state *pstate;
 	struct sde_plane_state *sde_pstate;
 	struct sde_plane_state *sde_pstate;
@@ -4745,8 +4853,7 @@ static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state,
 	struct sde_rect *rect;
 	struct sde_rect *rect;
 	u32 crtc_width, crtc_height;
 	u32 crtc_width, crtc_height;
 
 
-	crtc_width = sde_crtc_get_width(sde_crtc, cstate, mode);
-	crtc_height = sde_crtc_get_mixer_height(sde_crtc, cstate, mode);
+	sde_crtc_get_resolution(crtc, state, mode, &crtc_width, &crtc_height);
 
 
 	/* Check dim layer rect bounds and stage */
 	/* Check dim layer rect bounds and stage */
 	for (i = 0; i < cstate->num_dim_layers; i++) {
 	for (i = 0; i < cstate->num_dim_layers; i++) {
@@ -5065,8 +5172,7 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
 
 
 	memset(pipe_staged, 0, sizeof(pipe_staged));
 	memset(pipe_staged, 0, sizeof(pipe_staged));
 
 
-	crtc_width = sde_crtc_get_width(sde_crtc, cstate, mode);
-	crtc_height = sde_crtc_get_mixer_height(sde_crtc, cstate, mode);
+	sde_crtc_get_resolution(crtc, state, mode, &crtc_width, &crtc_height);
 
 
 	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
 	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
 		if (IS_ERR_OR_NULL(pstate)) {
 		if (IS_ERR_OR_NULL(pstate)) {
@@ -5200,7 +5306,7 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state,
 
 
 	sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
 	sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
 
 
-	rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt);
+	rc = _sde_crtc_excl_dim_layer_check(crtc, state, pstates, cnt);
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
@@ -5311,9 +5417,8 @@ static int _sde_crtc_check_plane_layout(struct drm_crtc *crtc,
 	struct drm_plane_state *plane_state;
 	struct drm_plane_state *plane_state;
 	struct sde_plane_state *pstate;
 	struct sde_plane_state *pstate;
 	struct drm_display_mode *mode;
 	struct drm_display_mode *mode;
-	struct sde_crtc *sde_crtc;
-	struct sde_crtc_state *cstate;
 	int layout_split;
 	int layout_split;
+	u32 crtc_width, crtc_height;
 
 
 	kms = _sde_crtc_get_kms(crtc);
 	kms = _sde_crtc_get_kms(crtc);
 
 
@@ -5327,8 +5432,8 @@ static int _sde_crtc_check_plane_layout(struct drm_crtc *crtc,
 		return 0;
 		return 0;
 
 
 	mode = &crtc->state->adjusted_mode;
 	mode = &crtc->state->adjusted_mode;
-	sde_crtc = to_sde_crtc(crtc);
-	cstate = to_sde_crtc_state(crtc->state);
+	sde_crtc_get_resolution(crtc, crtc_state, mode, &crtc_width, &crtc_height);
+
 	drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
 	drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
 		plane_state = drm_atomic_get_existing_plane_state(
 		plane_state = drm_atomic_get_existing_plane_state(
 				crtc_state->state, plane);
 				crtc_state->state, plane);
@@ -5336,7 +5441,7 @@ static int _sde_crtc_check_plane_layout(struct drm_crtc *crtc,
 			continue;
 			continue;
 
 
 		pstate = to_sde_plane_state(plane_state);
 		pstate = to_sde_plane_state(plane_state);
-		layout_split = sde_crtc_get_width(sde_crtc, cstate, mode) >> 1;
+		layout_split = crtc_width >> 1;
 
 
 		if (plane_state->crtc_x >= layout_split) {
 		if (plane_state->crtc_x >= layout_split) {
 			plane_state->crtc_x -= layout_split;
 			plane_state->crtc_x -= layout_split;
@@ -6362,8 +6467,7 @@ static int _sde_debugfs_status_show(struct seq_file *s, void *data)
 
 
 	mutex_lock(&sde_crtc->crtc_lock);
 	mutex_lock(&sde_crtc->crtc_lock);
 	mode = &crtc->state->adjusted_mode;
 	mode = &crtc->state->adjusted_mode;
-	mixer_width = sde_crtc_get_mixer_width(sde_crtc, cstate, mode);
-	mixer_height = sde_crtc_get_mixer_height(sde_crtc, cstate, mode);
+	sde_crtc_get_mixer_resolution(crtc, crtc->state, mode, &mixer_width, &mixer_height);
 
 
 	seq_printf(s, "crtc:%d width:%d height:%d\n", DRMID(crtc),
 	seq_printf(s, "crtc:%d width:%d height:%d\n", DRMID(crtc),
 				mixer_width * sde_crtc->num_mixers, mixer_height);
 				mixer_width * sde_crtc->num_mixers, mixer_height);

+ 26 - 55
msm/sde/sde_crtc.h

@@ -545,61 +545,6 @@ struct sde_crtc_irq_info {
 #define sde_crtc_get_property(S, X) \
 #define sde_crtc_get_property(S, X) \
 	((S) && ((X) < CRTC_PROP_COUNT) ? ((S)->property_values[(X)].value) : 0)
 	((S) && ((X) < CRTC_PROP_COUNT) ? ((S)->property_values[(X)].value) : 0)
 
 
-/**
- * sde_crtc_get_mixer_width - get the mixer width
- * Mixer width will be same as panel width(/2 for split)
- * unless destination scaler feature is enabled
- */
-static inline int sde_crtc_get_mixer_width(struct sde_crtc *sde_crtc,
-	struct sde_crtc_state *cstate, struct drm_display_mode *mode)
-{
-	u32 mixer_width;
-
-	if (!sde_crtc || !cstate || !mode)
-		return 0;
-
-	if (cstate->num_ds_enabled)
-		mixer_width = cstate->ds_cfg[0].lm_width;
-	else
-		mixer_width = mode->hdisplay / sde_crtc->num_mixers;
-
-	return mixer_width;
-}
-
-/**
- * sde_crtc_get_mixer_height - get the mixer height
- * Mixer height will be same as panel height unless
- * destination scaler feature is enabled
- */
-static inline int sde_crtc_get_mixer_height(struct sde_crtc *sde_crtc,
-		struct sde_crtc_state *cstate, struct drm_display_mode *mode)
-{
-	if (!sde_crtc || !cstate || !mode)
-		return 0;
-
-	return (cstate->num_ds_enabled ?
-			cstate->ds_cfg[0].lm_height : mode->vdisplay);
-}
-
-/**
- * sde_crtc_get_width - get the correct crtc width based on the features enabled
- */
-static inline int sde_crtc_get_width(struct sde_crtc *sde_crtc,
-	struct sde_crtc_state *cstate, struct drm_display_mode *mode)
-{
-	u32 width;
-
-	if (!sde_crtc || !cstate || !mode)
-		return 0;
-
-	if (cstate->num_ds_enabled)
-		width = cstate->ds_cfg[0].lm_width * cstate->num_ds_enabled;
-	else
-		width = mode->hdisplay;
-
-	return width;
-}
-
 /**
 /**
  * sde_crtc_frame_pending - retun the number of pending frames
  * sde_crtc_frame_pending - retun the number of pending frames
  * @crtc: Pointer to drm crtc object
  * @crtc: Pointer to drm crtc object
@@ -658,6 +603,32 @@ static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc,
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+ * sde_crtc_get_mixer_resolution - Get the mixer resolution based on the features enabled.
+ *     Mixer width will be same as panel width(/2 for split) or src_width of
+ *     destination scaler or downscale-blur.
+ * @drm_crtc: Pointer to drm crtc object
+ * @crtc_state: Pointer to drm crtc state object
+ * @mode: Pointer to drm display mode object
+ * @width: Pointer to width object populated with mixer width by this function
+ * @height: Pointer to height object populated with mixer height by this function
+ */
+void sde_crtc_get_mixer_resolution(struct drm_crtc *sde_crtc, struct drm_crtc_state *crtc_state,
+		struct drm_display_mode *mode, u32 *width, u32 *height);
+
+/**
+ * sde_crtc_get_resolution - Get the crtc resolution based on the features enabled.
+ *     Crtc width will be same as panel width or (src_width of
+ *     destination scaler or downscale-blur) * num_blocks.
+ * @drm_crtc: Pointer to drm crtc object
+ * @crtc_state: Pointer to drm crtc state object
+ * @mode: Pointer to drm display mode object
+ * @width: Pointer to width object populated with crtc width by this function
+ * @height: Pointer to height object populated with crtc height by this function
+ */
+void sde_crtc_get_resolution(struct drm_crtc *sde_crtc, struct drm_crtc_state *crtc_state,
+		struct drm_display_mode *mode, u32 *width, u32 *height);
+
 /**
 /**
  * sde_crtc_vblank - enable or disable vblanks for this crtc
  * sde_crtc_vblank - enable or disable vblanks for this crtc
  * @crtc: Pointer to drm crtc object
  * @crtc: Pointer to drm crtc object

+ 4 - 3
msm/sde/sde_encoder.c

@@ -926,17 +926,18 @@ static int _sde_encoder_atomic_check_pu_roi(struct sde_encoder_virt *sde_enc,
 	struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state,
 	struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state,
 	struct sde_connector_state *sde_conn_state, struct sde_crtc_state *sde_crtc_state)
 	struct sde_connector_state *sde_conn_state, struct sde_crtc_state *sde_crtc_state)
 {
 {
-	struct sde_crtc *sde_crtc = to_sde_crtc(crtc_state->crtc);
 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
 	int ret = 0;
 	int ret = 0;
 
 
 	if (crtc_state->mode_changed || crtc_state->active_changed) {
 	if (crtc_state->mode_changed || crtc_state->active_changed) {
 		struct sde_rect mode_roi, roi;
 		struct sde_rect mode_roi, roi;
+		u32 width, height;
 
 
+		sde_crtc_get_resolution(crtc_state->crtc, crtc_state, mode, &width, &height);
 		mode_roi.x = 0;
 		mode_roi.x = 0;
 		mode_roi.y = 0;
 		mode_roi.y = 0;
-		mode_roi.w = sde_crtc_get_width(sde_crtc, sde_crtc_state, mode);
-		mode_roi.h = sde_crtc_get_mixer_height(sde_crtc, sde_crtc_state, mode);
+		mode_roi.w = width;
+		mode_roi.h = height;
 
 
 		if (sde_conn_state->rois.num_rects) {
 		if (sde_conn_state->rois.num_rects) {
 			sde_kms_rect_merge_rectangles(&sde_conn_state->rois, &roi);
 			sde_kms_rect_merge_rectangles(&sde_conn_state->rois, &roi);