浏览代码

disp: msm: sde: add support for partial size CWB output buffer

Add support for accepting a smaller output buffer size than full
frame. In this case, input will be cropped as needed and set to
0,0 coordinate in the output buffer.

Change-Id: Ie6d60aa313ae87ce148a08108e09b56c908147da
Signed-off-by: Samantha Tran <[email protected]>
Samantha Tran 4 年之前
父节点
当前提交
928ee64b46
共有 1 个文件被更改,包括 54 次插入8 次删除
  1. 54 8
      msm/sde/sde_encoder_phys_wb.c

+ 54 - 8
msm/sde/sde_encoder_phys_wb.c

@@ -322,8 +322,12 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc,
 	struct sde_hw_wb_cdp_cfg *cdp_cfg;
 	const struct msm_format *format;
 	struct sde_crtc_state *cstate;
+	const struct drm_display_mode *mode;
 	struct sde_rect pu_roi = {0,};
-	int ret;
+	int i, ret;
+	u32 out_width, out_height, data_pt;
+	bool ds_in_use = false;
+	u32 ds_srcw = 0, ds_srch = 0, ds_outw = 0, ds_outh = 0;
 	struct msm_gem_address_space *aspace;
 	u32 fb_mode;
 
@@ -334,6 +338,7 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc,
 	}
 
 	cstate = to_sde_crtc_state(wb_enc->crtc->state);
+	mode = &wb_enc->crtc->state->mode;
 
 	hw_wb = wb_enc->hw_wb;
 	wb_cfg = &wb_enc->wb_cfg;
@@ -397,6 +402,30 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc,
 		wb_cfg->crop.x = wb_cfg->roi.x;
 		wb_cfg->crop.y = wb_cfg->roi.y;
 
+		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++) {
+			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 && data_pt == CAPTURE_DSPP_OUT) {
+			out_width = ds_outw;
+			out_height = ds_outh;
+		} else if (ds_in_use) {
+			out_width = ds_srcw;
+			out_height = ds_srch;
+		} else {
+			out_width = mode->hdisplay;
+			out_height = mode->vdisplay;
+		}
+
 		if (cstate->user_roi_list.num_rects) {
 			sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi);
 
@@ -406,12 +435,18 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc,
 				wb_cfg->crop.y = wb_cfg->crop.y - pu_roi.y;
 				hw_wb->ops.setup_crop(hw_wb, wb_cfg, true);
 			}
-		} else if ((wb_cfg->roi.w != wb_cfg->dest.width) ||
-				(wb_cfg->roi.h != wb_cfg->dest.height)) {
+		} else if ((wb_cfg->roi.w != out_width) ||
+				(wb_cfg->roi.h != out_height)) {
 			hw_wb->ops.setup_crop(hw_wb, wb_cfg, true);
 		} else {
 			hw_wb->ops.setup_crop(hw_wb, wb_cfg, false);
 		}
+
+		/* If output buffer is less than source size, align roi at top left corner */
+		if (wb_cfg->dest.width < out_width || wb_cfg->dest.height < out_height) {
+			wb_cfg->roi.x = 0;
+			wb_cfg->roi.y = 0;
+		}
 	}
 
 	if ((wb_cfg->dest.format->fetch_planes == SDE_PLANE_PLANAR) &&
@@ -737,11 +772,22 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc,
 		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);
+	/*
+	 * If output size is equal to input size ensure wb_roi with x and y offset
+	 * will be within buffer. If output size is smaller, only width and height are taken
+	 * into consideration as output region will begin at top left corner */
+
+	if ((fb->width == out_width && fb->height == out_height) &&
+			(((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] out[%dx%d]\n",
+				wb_roi.x, wb_roi.y, wb_roi.w, wb_roi.h, fb->width, fb->height,
+				out_width, out_height);
+		return -EINVAL;
+	} else if ((fb->width < out_width || fb->height < out_height) &&
+			((wb_roi.w > fb->width || wb_roi.h > fb->height))) {
+		SDE_ERROR("invalid wb roi[%d,%d,%d,%d] fb[%dx%d] out[%dx%d]\n",
+				wb_roi.x, wb_roi.y, wb_roi.w, wb_roi.h, fb->width, fb->height,
+				out_width, out_height);
 		return -EINVAL;
 	}