msm: sde: Add support for 1.5x downscale in rotator

msmcobalt v2 supports 1.5x downscaling in the rotator.

CRs-Fixed: 1055035
Change-Id: Icd71fd6d53783a7972305d1256acb209698e575d
Signed-off-by: Benjamin Chan <bkchan@codeaurora.org>
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index ef41759..b3e8170 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -62,9 +62,27 @@
 	SDE_QOS_MAX,
 };
 
+/**
+ * enum sde_rot_type: SDE rotator HW version
+ * @SDE_ROT_TYPE_V1_0: V1.0 HW version
+ * @SDE_ROT_TYPE_V1_1: V1.1 HW version
+ */
+enum sde_rot_type {
+	SDE_ROT_TYPE_V1_0 = 0x10000000,
+	SDE_ROT_TYPE_V1_1 = 0x10010000,
+	SDE_ROT_TYPE_MAX,
+};
+
+/**
+ * enum sde_caps_settings: SDE rotator capability definition
+ * @SDE_CAPS_R1_WB: MDSS V1.x WB block
+ * @SDE_CAPS_R3_WB: MDSS V3.x WB block
+ * @SDE_CAPS_R3_1P5_DOWNSCALE: 1.5x downscale rotator support
+ */
 enum sde_caps_settings {
 	SDE_CAPS_R1_WB,
 	SDE_CAPS_R3_WB,
+	SDE_CAPS_R3_1P5_DOWNSCALE,
 	SDE_CAPS_MAX,
 };
 
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index 7ec7efe..6caf50c 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -338,16 +338,19 @@
  * @cfg: Fetch configuration
  * @danger_lut: real-time QoS LUT for danger setting (not used)
  * @safe_lut: real-time QoS LUT for safe setting (not used)
+ * @dnsc_factor_w: downscale factor for width
+ * @dnsc_factor_h: downscale factor for height
  * @flags: Control flag
  */
 static void sde_hw_rotator_setup_fetchengine(struct sde_hw_rotator_context *ctx,
 		enum sde_rot_queue_prio queue_id,
 		struct sde_hw_rot_sspp_cfg *cfg, u32 danger_lut, u32 safe_lut,
-		u32 flags)
+		u32 dnsc_factor_w, u32 dnsc_factor_h, u32 flags)
 {
 	struct sde_hw_rotator *rot = ctx->rot;
 	struct sde_mdp_format_params *fmt;
 	struct sde_mdp_data *data;
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
 	u32 *wrptr;
 	u32 opmode = 0;
 	u32 chroma_samp = 0;
@@ -466,10 +469,19 @@
 	SDE_REGDMA_BLKWRITE_DATA(wrptr, opmode);
 
 	/* setup source fetch config, TP10 uses different block size */
-	if (sde_mdp_is_tp10_format(fmt))
-		fetch_blocksize = SDE_ROT_SSPP_FETCH_BLOCKSIZE_96;
-	else
-		fetch_blocksize = SDE_ROT_SSPP_FETCH_BLOCKSIZE_128;
+	if (test_bit(SDE_CAPS_R3_1P5_DOWNSCALE, mdata->sde_caps_map) &&
+			(dnsc_factor_w == 1) && (dnsc_factor_h == 1)) {
+		if (sde_mdp_is_tp10_format(fmt))
+			fetch_blocksize = SDE_ROT_SSPP_FETCH_BLOCKSIZE_144_EXT;
+		else
+			fetch_blocksize = SDE_ROT_SSPP_FETCH_BLOCKSIZE_192_EXT;
+	} else {
+		if (sde_mdp_is_tp10_format(fmt))
+			fetch_blocksize = SDE_ROT_SSPP_FETCH_BLOCKSIZE_96;
+		else
+			fetch_blocksize = SDE_ROT_SSPP_FETCH_BLOCKSIZE_128;
+	}
+
 	SDE_REGDMA_WRITE(wrptr, ROT_SSPP_FETCH_CONFIG,
 			fetch_blocksize |
 			SDE_ROT_SSPP_FETCH_CONFIG_RESET_VALUE |
@@ -1307,7 +1319,8 @@
 					true : false);
 
 	rot->ops.setup_rotator_fetchengine(ctx, ctx->q_id,
-			&sspp_cfg, danger_lut, safe_lut, flags);
+			&sspp_cfg, danger_lut, safe_lut,
+			entry->dnsc_factor_w, entry->dnsc_factor_h, flags);
 
 	wb_cfg.img_width = item->output.width;
 	wb_cfg.img_height = item->output.height;
@@ -1523,6 +1536,11 @@
 
 	set_bit(SDE_CAPS_R3_WB, mdata->sde_caps_map);
 
+	if (hw_version != SDE_ROT_TYPE_V1_0) {
+		SDEROT_DBG("Supporting 1.5 downscale for SDE Rotator\n");
+		set_bit(SDE_CAPS_R3_1P5_DOWNSCALE,  mdata->sde_caps_map);
+	}
+
 	return 0;
 }
 
@@ -1675,6 +1693,7 @@
 static int sde_hw_rotator_validate_entry(struct sde_rot_mgr *mgr,
 		struct sde_rot_entry *entry)
 {
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
 	int ret = 0;
 	u16 src_w, src_h, dst_w, dst_h;
 	struct sde_rotation_item *item = &entry->item;
@@ -1698,7 +1717,7 @@
 		if ((src_w % dst_w) || (src_h % dst_h)) {
 			SDEROT_DBG("non integral scale not support\n");
 			ret = -EINVAL;
-			goto dnsc_err;
+			goto dnsc_1p5_check;
 		}
 		entry->dnsc_factor_w = src_w / dst_w;
 		if ((entry->dnsc_factor_w & (entry->dnsc_factor_w - 1)) ||
@@ -1727,6 +1746,32 @@
 		SDEROT_DBG("downscale with ubwc cannot be more than 2\n");
 		ret = -EINVAL;
 	}
+	goto dnsc_err;
+
+dnsc_1p5_check:
+	/* Check for 1.5 downscale that only applies to V2 HW */
+	if (test_bit(SDE_CAPS_R3_1P5_DOWNSCALE, mdata->sde_caps_map)) {
+		entry->dnsc_factor_w = src_w / dst_w;
+		if ((entry->dnsc_factor_w != 1) ||
+				((dst_w * 3) != (src_w * 2))) {
+			SDEROT_DBG(
+				"No supporting non 1.5 downscale width ratio, src_w:%d, dst_w:%d\n",
+				src_w, dst_w);
+			ret = -EINVAL;
+			goto dnsc_err;
+		}
+
+		entry->dnsc_factor_h = src_h / dst_h;
+		if ((entry->dnsc_factor_h != 1) ||
+				((dst_h * 3) != (src_h * 2))) {
+			SDEROT_DBG(
+				"Not supporting non 1.5 downscale height ratio, src_h:%d, dst_h:%d\n",
+				src_h, dst_h);
+			ret = -EINVAL;
+			goto dnsc_err;
+		}
+		ret = 0;
+	}
 
 dnsc_err:
 	/* Downscaler does not support asymmetrical dnsc */
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
index d0c15f4..3267e44 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
@@ -128,6 +128,8 @@
 #define SDE_ROT_SSPP_FETCH_CONFIG_RESET_VALUE   0x00087
 #define SDE_ROT_SSPP_FETCH_BLOCKSIZE_128        (0 << 16)
 #define SDE_ROT_SSPP_FETCH_BLOCKSIZE_96         (2 << 16)
+#define SDE_ROT_SSPP_FETCH_BLOCKSIZE_192_EXT    ((0 << 16) | (1 << 15))
+#define SDE_ROT_SSPP_FETCH_BLOCKSIZE_144_EXT    ((2 << 16) | (1 << 15))
 
 
 /* SDE_ROT_WB:
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
index 272b15e..b95f838 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
@@ -116,6 +116,8 @@
 	 * @cfg:        Rotator Fetch engine configuration parameters
 	 * @danger_lut: Danger LUT setting
 	 * @safe_lut:   Safe LUT setting
+	 * @dnsc_factor_w: Downscale factor for width
+	 * @dnsc_factor_h: Downscale factor for height
 	 * @flags:      Specific config flag, see SDE_ROT_FLAG_ for details
 	 */
 	void (*setup_rotator_fetchengine)(
@@ -124,6 +126,8 @@
 			struct sde_hw_rot_sspp_cfg     *cfg,
 			u32                             danger_lut,
 			u32                             safe_lut,
+			u32                             dnsc_factor_w,
+			u32                             dnsc_factor_h,
 			u32                             flags);
 
 	/**