Bladeren bron

disp: msm: sde: add missing validations for dnsc_blur

Add crtc checks to ensure the crtc width is always even number,
so there is no loss while dividing by num_mixers. Add checks in
dnsc_blur to ensure the src is always greater than the dest.

Change-Id: I876f19aa20857dc9ed2649c9cb7569348e7d5fd3
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran 3 jaren geleden
bovenliggende
commit
30aa675422
2 gewijzigde bestanden met toevoegingen van 61 en 30 verwijderingen
  1. 15 0
      msm/sde/sde_crtc.c
  2. 46 30
      msm/sde/sde_encoder_phys_wb.c

+ 15 - 0
msm/sde/sde_crtc.c

@@ -1357,6 +1357,8 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
 	struct sde_crtc *sde_crtc;
 	struct sde_crtc_state *sde_crtc_state;
 	struct msm_mode_info mode_info;
+	u32 crtc_width, crtc_height, mixer_width, mixer_height;
+	struct drm_display_mode *adj_mode;
 	int rc, lm_idx, i;
 
 	if (!crtc || !state)
@@ -1367,6 +1369,19 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
 	sde_crtc = to_sde_crtc(crtc);
 	sde_crtc_state = to_sde_crtc_state(state);
 
+	adj_mode = &state->adjusted_mode;
+	sde_crtc_get_resolution(crtc, state, adj_mode, &crtc_width, &crtc_height);
+	sde_crtc_get_mixer_resolution(crtc, state, adj_mode, &mixer_width, &mixer_height);
+	/* check cumulative mixer w/h is equal full crtc w/h */
+	if (sde_crtc->num_mixers
+			&& (((mixer_width * sde_crtc->num_mixers) != crtc_width)
+				|| (mixer_height != crtc_height))) {
+		SDE_ERROR("%s: invalid w/h crtc:%d,%d, mixer:%d,%d, num_mixers:%d\n",
+				sde_crtc->name, crtc_width, crtc_height, mixer_width, mixer_height,
+				sde_crtc->num_mixers);
+		return -EINVAL;
+	}
+
 	/*
 	 * check connector array cached at modeset time since incoming atomic
 	 * state may not include any connectors if they aren't modified

+ 46 - 30
msm/sde/sde_encoder_phys_wb.c

@@ -747,16 +747,13 @@ static int _sde_enc_phys_wb_validate_dnsc_blur_filter(
 	return 0;
 }
 
-static int _sde_enc_phys_wb_validate_dnsc_blur_ds(struct drm_crtc_state *crtc_state,
-			struct drm_connector_state *conn_state, const struct sde_format *fmt)
+static int _sde_enc_phys_wb_validate_dnsc_blur_filters(struct drm_crtc_state *crtc_state,
+		struct drm_connector_state *conn_state)
 {
-	struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
 	struct sde_connector_state *sde_conn_state = to_sde_connector_state(conn_state);
-	struct sde_kms *sde_kms;
-	struct sde_drm_dnsc_blur_cfg *cfg;
 	struct sde_dnsc_blur_filter_info *filter_info;
-	struct sde_io_res ds_res = {0, }, dnsc_blur_res = {0, };
-	u32 ds_tap_pt = sde_crtc_get_property(cstate, CRTC_PROP_CAPTURE_OUTPUT);
+	struct sde_drm_dnsc_blur_cfg *cfg;
+	struct sde_kms *sde_kms;
 	int ret = 0, i, j;
 
 	sde_kms = sde_connector_get_kms(conn_state->connector);
@@ -765,6 +762,37 @@ static int _sde_enc_phys_wb_validate_dnsc_blur_ds(struct drm_crtc_state *crtc_st
 		return -EINVAL;
 	}
 
+	for (i = 0; i < sde_conn_state->dnsc_blur_count; i++) {
+		cfg = &sde_conn_state->dnsc_blur_cfg[i];
+
+		for (j = 0; j < sde_kms->catalog->dnsc_blur_filter_count; j++) {
+			filter_info = &sde_kms->catalog->dnsc_blur_filters[i];
+			if (cfg->flags_h == filter_info->filter) {
+				ret = _sde_enc_phys_wb_validate_dnsc_blur_filter(filter_info,
+						cfg->src_width, cfg->dst_width);
+				if (ret)
+					break;
+			}
+			if (cfg->flags_v == filter_info->filter) {
+				ret = _sde_enc_phys_wb_validate_dnsc_blur_filter(filter_info,
+						cfg->src_height, cfg->dst_height);
+				if (ret)
+					break;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int _sde_enc_phys_wb_validate_dnsc_blur_ds(struct drm_crtc_state *crtc_state,
+			struct drm_connector_state *conn_state, const struct sde_format *fmt,
+			struct sde_rect *wb_roi)
+{
+	struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
+	struct sde_io_res ds_res = {0, }, dnsc_blur_res = {0, };
+	u32 ds_tap_pt = sde_crtc_get_property(cstate, CRTC_PROP_CAPTURE_OUTPUT);
+
 	sde_crtc_get_ds_io_res(crtc_state, &ds_res);
 	sde_connector_get_dnsc_blur_io_res(conn_state, &dnsc_blur_res);
 
@@ -779,7 +807,9 @@ static int _sde_enc_phys_wb_validate_dnsc_blur_ds(struct drm_crtc_state *crtc_st
 		return 0;
 
 	if (!dnsc_blur_res.src_w || !dnsc_blur_res.src_h
-			|| !dnsc_blur_res.dst_w || !dnsc_blur_res.dst_h) {
+			|| !dnsc_blur_res.dst_w || !dnsc_blur_res.dst_h
+			|| (dnsc_blur_res.src_w < dnsc_blur_res.dst_w)
+			|| (dnsc_blur_res.src_h < dnsc_blur_res.dst_h)) {
 		SDE_ERROR("invalid dnsc_blur cfg src:%ux%u dst:%ux%u\n",
 				dnsc_blur_res.src_w, dnsc_blur_res.src_h,
 				dnsc_blur_res.dst_w, dnsc_blur_res.dst_h);
@@ -804,29 +834,15 @@ static int _sde_enc_phys_wb_validate_dnsc_blur_ds(struct drm_crtc_state *crtc_st
 	} else if (SDE_FORMAT_IS_YUV(fmt)) {
 		SDE_ERROR("YUV output not supported with dnsc_blur\n");
 		return -EINVAL;
+	} else if ((wb_roi->w && (wb_roi->w != dnsc_blur_res.dst_w)) ||
+			(wb_roi->h && (wb_roi->h != dnsc_blur_res.dst_h))) {
+		SDE_ERROR("invalid WB ROI with dnsc_blur, roi:{%d,%d,%d,%d}, dnsc_blur dst:%ux%u\n",
+				wb_roi->x, wb_roi->y, wb_roi->w, wb_roi->h,
+				dnsc_blur_res.dst_w, dnsc_blur_res.dst_h);
+		return -EINVAL;
 	}
 
-	for (i = 0; i < sde_conn_state->dnsc_blur_count; i++) {
-		cfg = &sde_conn_state->dnsc_blur_cfg[i];
-
-		for (j = 0; j < sde_kms->catalog->dnsc_blur_filter_count; j++) {
-			filter_info = &sde_kms->catalog->dnsc_blur_filters[i];
-			if (cfg->flags_h == filter_info->filter) {
-				ret = _sde_enc_phys_wb_validate_dnsc_blur_filter(filter_info,
-						cfg->src_width, cfg->dst_width);
-				if (ret)
-					break;
-			}
-			if (cfg->flags_v == filter_info->filter) {
-				ret = _sde_enc_phys_wb_validate_dnsc_blur_filter(filter_info,
-						cfg->src_height, cfg->dst_height);
-				if (ret)
-					break;
-			}
-		}
-	}
-
-	return ret;
+	return _sde_enc_phys_wb_validate_dnsc_blur_filters(crtc_state, conn_state);
 }
 
 static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc,
@@ -1024,7 +1040,7 @@ static int sde_encoder_phys_wb_atomic_check(struct sde_encoder_phys *phys_enc,
 	if (SDE_FORMAT_IS_YUV(fmt) != !!phys_enc->hw_cdm)
 		crtc_state->mode_changed = true;
 
-	rc = _sde_enc_phys_wb_validate_dnsc_blur_ds(crtc_state, conn_state, fmt);
+	rc = _sde_enc_phys_wb_validate_dnsc_blur_ds(crtc_state, conn_state, fmt, &wb_roi);
 	if (rc) {
 		SDE_ERROR("[enc:%d wb:%d] failed dnsc_blur/ds validation; ret:%d\n",
 				DRMID(phys_enc->parent), WBID(wb_enc), rc);