drm/msm/sde: add writeback ROI support for msmskunk

For HW directly supporting writeback ROI x,y offsets
bypass writeback planes offset recalculation.

Change-Id: I8b38b6026482a4f72607ad74bbec2d3f741b94f8
Signed-off-by: abeykun <abeykun@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index ca7a711..940a5f6 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -217,13 +217,25 @@
 		SDE_ERROR("failed to get format %x\n", format->pixel_format);
 		return;
 	}
+	wb_cfg->roi = *wb_roi;
 
-	ret = sde_format_populate_layout_with_roi(mmu_id, fb, wb_roi,
+	if (hw_wb->caps->features & BIT(SDE_WB_XY_ROI_OFFSET)) {
+		ret = sde_format_populate_layout(mmu_id, fb, &wb_cfg->dest);
+		if (ret) {
+			SDE_DEBUG("failed to populate layout %d\n", ret);
+			return;
+		}
+		wb_cfg->dest.width = fb->width;
+		wb_cfg->dest.height = fb->height;
+		wb_cfg->dest.num_planes = wb_cfg->dest.format->num_planes;
+	} else {
+		ret = sde_format_populate_layout_with_roi(mmu_id, fb, wb_roi,
 			&wb_cfg->dest);
-	if (ret) {
-		/* this error should be detected during atomic_check */
-		SDE_DEBUG("failed to populate layout %d\n", ret);
-		return;
+		if (ret) {
+			/* this error should be detected during atomic_check */
+			SDE_DEBUG("failed to populate layout %d\n", ret);
+			return;
+		}
 	}
 
 	if ((wb_cfg->dest.format->fetch_planes == SDE_PLANE_PLANAR) &&
@@ -241,6 +253,9 @@
 			wb_cfg->dest.plane_pitch[2],
 			wb_cfg->dest.plane_pitch[3]);
 
+	if (hw_wb->ops.setup_roi)
+		hw_wb->ops.setup_roi(hw_wb, wb_cfg);
+
 	if (hw_wb->ops.setup_outformat)
 		hw_wb->ops.setup_outformat(hw_wb, wb_cfg);
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 2f187fb..6c480a6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -175,9 +175,11 @@
  * @SDE_WB_TRAFFIC_SHAPER,  Writeback traffic shaper bloc
  * @SDE_WB_UBWC_1_0,        Writeback Universal bandwidth compression 1.0
  *                          support
- * @SDE_WB_WBWC_1_5         UBWC 1.5 support
+ * @SDE_WB_UBWC_1_5         UBWC 1.5 support
  * @SDE_WB_YUV_CONFIG       Writeback supports output of YUV colorspace
  * @SDE_WB_PIPE_ALPHA       Writeback supports pipe alpha
+ * @SDE_WB_XY_ROI_OFFSET    Writeback supports x/y-offset of out ROI in
+ *                          the destination image
  * @SDE_WB_MAX              maximum value
  */
 enum {
@@ -192,6 +194,7 @@
 	SDE_WB_UBWC_1_0,
 	SDE_WB_YUV_CONFIG,
 	SDE_WB_PIPE_ALPHA,
+	SDE_WB_XY_ROI_OFFSET,
 	SDE_WB_MAX
 };
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_wb.c b/drivers/gpu/drm/msm/sde/sde_hw_wb.c
index 60141dc..3c7f2fe 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_wb.c
@@ -43,6 +43,8 @@
 #define WB_CSC_BASE			0x260
 #define WB_DST_ADDR_SW_STATUS		0x2B0
 #define WB_CDP_CTRL			0x2B4
+#define WB_OUT_IMAGE_SIZE		0x2C0
+#define WB_OUT_XY			0x2C4
 
 static struct sde_wb_cfg *_wb_offset(enum sde_wb wb,
 		struct sde_mdss_cfg *m,
@@ -119,7 +121,11 @@
 			(data->dest.plane_pitch[1] << 16);
 	ystride1 = data->dest.plane_pitch[2] |
 			(data->dest.plane_pitch[3] << 16);
-	outsize = (data->dest.height << 16) | data->dest.width;
+
+	if (data->roi.h && data->roi.w)
+		outsize = (data->roi.h << 16) | data->roi.w;
+	else
+		outsize = (data->dest.height << 16) | data->dest.width;
 
 	if (SDE_FORMAT_IS_UBWC(fmt)) {
 		opmode |= BIT(0);
@@ -164,6 +170,20 @@
 				&data->ts_cfg);
 }
 
+static void sde_hw_wb_roi(struct sde_hw_wb *ctx, struct sde_hw_wb_cfg *wb)
+{
+	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	u32 image_size, out_size, out_xy;
+
+	image_size = (wb->dest.height << 16) | wb->dest.width;
+	out_xy = (wb->roi.y << 16) | wb->roi.x;
+	out_size = (wb->roi.h << 16) | wb->roi.w;
+
+	SDE_REG_WRITE(c, WB_OUT_IMAGE_SIZE, image_size);
+	SDE_REG_WRITE(c, WB_OUT_XY, out_xy);
+	SDE_REG_WRITE(c, WB_OUT_SIZE, out_size);
+}
+
 static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
 	unsigned long features)
 {
@@ -172,6 +192,9 @@
 
 	if (test_bit(SDE_WB_TRAFFIC_SHAPER, &features))
 		ops->setup_trafficshaper = sde_hw_wb_traffic_shaper;
+
+	if (test_bit(SDE_WB_XY_ROI_OFFSET, &features))
+		ops->setup_roi = sde_hw_wb_roi;
 }
 
 struct sde_hw_wb *sde_hw_wb_init(enum sde_wb idx,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_wb.h b/drivers/gpu/drm/msm/sde/sde_hw_wb.h
index e01750b..52a5ee5 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_wb.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_wb.h
@@ -24,6 +24,7 @@
 	struct sde_hw_fmt_layout dest;
 	enum sde_intf_mode intf_mode;
 	struct traffic_shaper_cfg ts_cfg;
+	struct sde_rect roi;
 	bool is_secure;
 };
 
@@ -53,6 +54,9 @@
 
 	void (*setup_trafficshaper)(struct sde_hw_wb *ctx,
 		struct sde_hw_wb_cfg *wb);
+
+	void (*setup_roi)(struct sde_hw_wb *ctx,
+		struct sde_hw_wb_cfg *wb);
 };
 
 /**