瀏覽代碼

Merge "disp: msm: sde: update cwb checks for destination scaler" into display-kernel.lnx.5.4

Linux Build Service Account 5 年之前
父節點
當前提交
6db21fc335
共有 1 個文件被更改,包括 72 次插入25 次删除
  1. 72 25
      msm/sde/sde_encoder_phys_wb.c

+ 72 - 25
msm/sde/sde_encoder_phys_wb.c

@@ -604,59 +604,102 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc,
 
 static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc,
 			struct drm_crtc_state *crtc_state,
-			 struct drm_connector_state *conn_state)
+			struct drm_connector_state *conn_state)
 {
+	struct drm_framebuffer *fb;
 	struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
+	const struct drm_display_mode *mode = &crtc_state->mode;
 	struct sde_rect wb_roi = {0,};
 	struct sde_rect pu_roi = {0,};
+	int out_width = 0, out_height = 0;
+	int ds_srcw = 0, ds_srch = 0, ds_outw = 0, ds_outh = 0;
 	int data_pt;
-	int ds_outw = 0;
-	int ds_outh = 0;
 	int ds_in_use = false;
 	int i = 0;
 	int ret = 0;
 
-	if (!phys_enc->in_clone_mode) {
-		SDE_DEBUG("not in CWB mode. early return\n");
-		goto exit;
+	fb = sde_wb_connector_state_get_output_fb(conn_state);
+	if (!fb) {
+		SDE_DEBUG("no output framebuffer\n");
+		return 0;
 	}
 
 	ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi);
 	if (ret) {
 		SDE_ERROR("failed to get roi %d\n", ret);
-		goto exit;
+		return ret;
+	}
+
+	if (!wb_roi.w || !wb_roi.h) {
+		SDE_ERROR("cwb roi is not set wxh:%dx%d\n", wb_roi.w, wb_roi.h);
+		return -EINVAL;
 	}
 
 	data_pt = sde_crtc_get_property(cstate, CRTC_PROP_CAPTURE_OUTPUT);
 
 	/* compute cumulative ds output dimensions if in use */
-	for (i = 0; i < cstate->num_ds; i++)
+	for (i = 0; i < cstate->num_ds; i++) {
 		if (cstate->ds_cfg[i].scl3_cfg.enable) {
 			ds_in_use = true;
 			ds_outw += cstate->ds_cfg[i].scl3_cfg.dst_width;
 			ds_outh = cstate->ds_cfg[i].scl3_cfg.dst_height;
+			ds_srcw +=  cstate->ds_cfg[i].lm_width;
+			ds_srch =  cstate->ds_cfg[i].lm_height;
 		}
+	}
 
-	/* if ds in use check wb roi against ds output dimensions */
-	if ((data_pt == CAPTURE_DSPP_OUT) &&  ds_in_use &&
-			((wb_roi.w != ds_outw) || (wb_roi.h != ds_outh))) {
-		SDE_ERROR("invalid wb roi with dest scalar [%dx%d vs %dx%d]\n",
-				wb_roi.w, wb_roi.h, ds_outw, ds_outh);
-		ret = -EINVAL;
-		goto exit;
+	if ((ds_in_use && (!ds_outw || !ds_outh || !ds_srcw || !ds_srch))) {
+		SDE_ERROR("invalid ds cfg src:%dx%d dst:%dx%d\n",
+				ds_srcw, ds_srch, ds_outw, ds_outh);
+		return -EINVAL;
 	}
 
-	/* validate conn roi against pu rect */
+	/* 1) No DS case: same restrictions for LM & DSSPP tap point
+	 *	a) wb-roi should be inside FB
+	 *	b) mode resolution & wb-roi should be same
+	 * 2) With DS case: restrictions would change based on tap point
+	 *	2.1) LM Tap Point:
+	 *		a) wb-roi should be inside FB
+	 *		b) wb-roi should be same as crtc-LM bounds
+	 *	2.2) DSPP Tap point: same as No DS case
+	 *		a) wb-roi should be inside FB
+	 *		b) mode resolution & wb-roi should be same
+	 */
+	if (ds_in_use && data_pt == CAPTURE_DSPP_OUT) {
+		out_width = ds_outw;
+		out_height = ds_outh;
+	} else if (ds_in_use) { /* LM tap point */
+		out_width = ds_srcw;
+		out_height = ds_srch;
+	} else {
+		out_width = mode->hdisplay;
+		out_height = mode->vdisplay;
+	}
+
+	if ((wb_roi.w != out_width) || (wb_roi.h != out_height)) {
+		SDE_ERROR("invalid wb roi[%dx%d] with ds_use:%d out[%dx%d]\n",
+				wb_roi.w, wb_roi.h, out_width, out_height);
+		return -EINVAL;
+	}
+
+	if (((wb_roi.x + wb_roi.w) > fb->width) ||
+			((wb_roi.y + wb_roi.h) > fb->height)) {
+		SDE_ERROR("invalid wb roi[%d,%d,%d,%d] fb[%dx%d]\n",
+				wb_roi.x, wb_roi.y, wb_roi.w, wb_roi.h,
+				fb->width, fb->height);
+		return -EINVAL;
+	}
+
+	/* validate wb roi against pu rect */
 	if (cstate->user_roi_list.num_rects) {
 		sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi);
 		if (wb_roi.w != pu_roi.w || wb_roi.h != pu_roi.h) {
 			SDE_ERROR("invalid wb roi with pu [%dx%d vs %dx%d]\n",
 					wb_roi.w, wb_roi.h, pu_roi.w, pu_roi.h);
-			ret = -EINVAL;
-			goto exit;
+			return -EINVAL;
 		}
 	}
-exit:
+
 	return ret;
 }
 
@@ -742,6 +785,16 @@ static int sde_encoder_phys_wb_atomic_check(
 	if (SDE_FORMAT_IS_YUV(fmt) != !!phys_enc->hw_cdm)
 		crtc_state->mode_changed = true;
 
+	/* if in clone mode, return after cwb validation */
+	if (phys_enc->in_clone_mode) {
+		rc = _sde_enc_phys_wb_validate_cwb(phys_enc, crtc_state,
+				conn_state);
+		if (rc)
+			SDE_ERROR("failed in cwb validation %d\n", rc);
+
+		return rc;
+	}
+
 	if (wb_roi.w && wb_roi.h) {
 		if (wb_roi.w != mode->hdisplay) {
 			SDE_ERROR("invalid roi w=%d, mode w=%d\n", wb_roi.w,
@@ -786,12 +839,6 @@ static int sde_encoder_phys_wb_atomic_check(
 		}
 	}
 
-	rc = _sde_enc_phys_wb_validate_cwb(phys_enc, crtc_state, conn_state);
-	if (rc) {
-		SDE_ERROR("failed in cwb validation %d\n", rc);
-		return rc;
-	}
-
 	return rc;
 }