drm/msm/sde: enable NV12 modetest for planes

Add basic CSC support and default sharpening config to enable
YUV formats. Always using 601L conversion for now.

Add initial support of plane blob properties.

Change-Id: Ic818da5e1d6a9a5b3a9e32e222518b829a9dce4a
Signed-off-by: Clarence Ip <cip@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 3d9b146..9989901 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -210,14 +210,16 @@
 
 	cfg->fg.alpha_sel = ALPHA_FG_CONST;
 	cfg->bg.alpha_sel = ALPHA_BG_CONST;
-	cfg->fg.const_alpha = pstate->alpha;
-	cfg->bg.const_alpha = 0xFF - pstate->alpha;
+	cfg->fg.const_alpha = pstate->property_values[PLANE_PROP_ALPHA];
+	cfg->bg.const_alpha = 0xFF - cfg->fg.const_alpha;
 
-	if (format->alpha_enable && pstate->premultiplied) {
+	if (format->alpha_enable &&
+			pstate->property_values[PLANE_PROP_PREMULTIPLIED]) {
 		cfg->fg.alpha_sel = ALPHA_FG_CONST;
 		cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
-		if (pstate->alpha != 0xff) {
-			cfg->bg.const_alpha = pstate->alpha;
+		if (pstate->property_values[PLANE_PROP_ALPHA] != 0xff) {
+			cfg->bg.const_alpha =
+				(u32)pstate->property_values[PLANE_PROP_ALPHA];
 			cfg->bg.inv_alpha_sel = 1;
 			cfg->bg.mod_alpha = 1;
 		} else {
@@ -226,8 +228,9 @@
 	} else if (format->alpha_enable) {
 		cfg->fg.alpha_sel = ALPHA_FG_PIXEL;
 		cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
-		if (pstate->alpha != 0xff) {
-			cfg->bg.const_alpha = pstate->alpha;
+		if (pstate->property_values[PLANE_PROP_ALPHA] != 0xff) {
+			cfg->bg.const_alpha =
+				(u32)pstate->property_values[PLANE_PROP_ALPHA];
 			cfg->fg.mod_alpha = 1;
 			cfg->bg.inv_alpha_sel = 1;
 			cfg->bg.mod_alpha = 1;
@@ -319,8 +322,10 @@
 			sde_crtc_get_blend_cfg(&blend, pstates[j]);
 			blend.fg.alpha_sel = ALPHA_FG_CONST;
 			blend.bg.alpha_sel = ALPHA_BG_CONST;
-			blend.fg.const_alpha = pstate->alpha;
-			blend.bg.const_alpha = 0xFF - pstate->alpha;
+			blend.fg.const_alpha =
+				(u32)pstate->property_values[PLANE_PROP_ALPHA];
+			blend.bg.const_alpha = 0xFF -
+				(u32)pstate->property_values[PLANE_PROP_ALPHA];
 			lm->ops.setup_blend_config(lm, j, &blend);
 		}
 	}
@@ -547,7 +552,8 @@
 	struct plane_state *pa = (struct plane_state *)a;
 	struct plane_state *pb = (struct plane_state *)b;
 
-	return pa->state->zpos - pb->state->zpos;
+	return (int)pa->state->property_values[PLANE_PROP_ZPOS] -
+		(int)pb->state->property_values[PLANE_PROP_ZPOS];
 }
 
 static int sde_crtc_atomic_check(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 1de66f7..75f75a0 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -63,10 +63,10 @@
 /**
  * SSPP sub-blocks/features
  * @SDE_SSPP_SRC             Src and fetch part of the pipes,
- * @SDE_SSPP_SCALAR_QSEED2,  QSEED2 algorithm support
- * @SDE_SSPP_SCALAR_QSEED3,  QSEED3 algorithm support
- * @SDE_SSPP_SCALAR_RGB,     RGB Scalar, supported by RGB pipes
- * @SDE_SSPP_CSC,            Support of Color space conversion
+ * @SDE_SSPP_SCALER_QSEED2,  QSEED2 algorithm support
+ * @SDE_SSPP_SCALER_QSEED3,  QSEED3 alogorithm support
+ * @SDE_SSPP_SCALER_RGB,     RGB Scaler, supported by RGB pipes
+ * @SDE_SSPP_CSC,            Support of Color space converion
  * @SDE_SSPP_PA_V1,          Common op-mode register for PA blocks
  * @SDE_SSPP_HIST_V1         Histogram programming method V1
  * @SDE_SSPP_IGC,            Inverse gamma correction
@@ -76,9 +76,9 @@
  */
 enum {
 	SDE_SSPP_SRC = 0x1,
-	SDE_SSPP_SCALAR_QSEED2,
-	SDE_SSPP_SCALAR_QSEED3,
-	SDE_SSPP_SCALAR_RGB,
+	SDE_SSPP_SCALER_QSEED2,
+	SDE_SSPP_SCALER_QSEED3,
+	SDE_SSPP_SCALER_RGB,
 	SDE_SSPP_CSC,
 	SDE_SSPP_PA_V1, /* Common op-mode register for PA blocks */
 	SDE_SSPP_HIST_V1,
@@ -201,10 +201,10 @@
 };
 
 /**
- * struct sde_scalar_info: Scalar information
+ * struct sde_scaler_blk: Scaler information
  * @info:   HW register and features supported by this sub-blk
  */
-struct sde_scalar_blk {
+struct sde_scaler_blk {
 	SDE_HW_SUBBLK_INFO;
 };
 
@@ -230,7 +230,7 @@
  * @danger_lut:  LUT to generate danger signals
  * @safe_lut:    LUT to generate safe signals
  * @src_blk:
- * @scalar_blk:
+ * @scaler_blk:
  * @csc_blk:
  * @pa_blk:
  * @hist_lut:
@@ -243,7 +243,7 @@
 	u32 maxdwnscale;
 	u32 maxupscale;
 	struct sde_src_blk src_blk;
-	struct sde_scalar_blk scalar_blk;
+	struct sde_scaler_blk scaler_blk;
 	struct sde_pp_blk csc_blk;
 	struct sde_pp_blk pa_blk;
 	struct sde_pp_blk hist_lut;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
index 7238890..6ee17d8 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
@@ -16,14 +16,14 @@
 
 /* VIG layer capability */
 #define VIG_17X_MASK \
-	(BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALAR_QSEED2) |\
+	(BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALER_QSEED2) |\
 	BIT(SDE_SSPP_CSC) | BIT(SDE_SSPP_PA_V1) |\
 	BIT(SDE_SSPP_HIST_V1) | BIT(SDE_SSPP_PCC) |\
 	BIT(SDE_SSPP_IGC))
 
 /* RGB layer capability */
 #define RGB_17X_MASK \
-	(BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALAR_RGB) |\
+	(BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALER_RGB) |\
 	BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC))
 
 /* DMA layer capability */
@@ -72,7 +72,7 @@
 		.maxdwnscale = 4, .maxupscale = 20,
 		.src_blk = {.id = SDE_SSPP_SRC,
 			.base = 0x00, .len = 0x150,},
-		.scalar_blk = {.id = SDE_SSPP_SCALAR_QSEED2,
+		.scaler_blk = {.id = SDE_SSPP_SCALER_QSEED2,
 			.base = 0x200, .len = 0x70,},
 		.csc_blk = {.id = SDE_SSPP_CSC,
 			.base = 0x320, .len = 0x44,},
@@ -90,7 +90,7 @@
 		.safe_lut = 0xFF00,
 		.maxdwnscale = 0, .maxupscale = 0,
 		.src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x0,},
-		.scalar_blk = {.id = 0, .base = 0x00, .len = 0x0,},
+		.scaler_blk = {.id = 0, .base = 0x00, .len = 0x0,},
 		.csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
 		.pa_blk = {.id = 0, .base = 0x00, .len = 0x0,},
 		.hist_lut = {.id = 0, .base = 0x00, .len = 0x0,},
@@ -103,7 +103,7 @@
 		.safe_lut = 0xFF00,
 		.maxdwnscale = 0, .maxupscale = 0,
 		.src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x0,},
-		.scalar_blk = {.id = 0, .base = 0x00, .len = 0x0,},
+		.scaler_blk = {.id = 0, .base = 0x00, .len = 0x0,},
 		.csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
 		.pa_blk = {.id = 0, .base = 0x00, .len = 0x0,},
 		.hist_lut = {.id = 0, .base = 0x00, .len = 0x0,},
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c b/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c
index 8162efc..d8e928a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdp_util.c
@@ -29,19 +29,19 @@
 	u32 val;
 
 	/* Matrix coeff */
-	val = (data->csc_mv[0] & 0x1FF) |
-		((data->csc_mv[1] & 0x1FF) << 16);
+	val = (data->csc_mv[0] & 0x1FFF) |
+		((data->csc_mv[1] & 0x1FFF) << 16);
 	SDE_REG_WRITE(c, csc_reg_off,  val);
-	val = (data->csc_mv[2] & 0x1FF) |
-		((data->csc_mv[3] & 0x1FF) << 16);
+	val = (data->csc_mv[2] & 0x1FFF) |
+		((data->csc_mv[3] & 0x1FFF) << 16);
 	SDE_REG_WRITE(c, csc_reg_off + 0x4, val);
-	val = (data->csc_mv[4] & 0x1FF) |
-		((data->csc_mv[5] & 0x1FF) >> 16);
+	val = (data->csc_mv[4] & 0x1FFF) |
+		((data->csc_mv[5] & 0x1FFF) >> 16);
 	SDE_REG_WRITE(c, csc_reg_off + 0x8, val);
-	val = (data->csc_mv[6] & 0x1FF) |
-		((data->csc_mv[7] & 0x1FF) << 16);
+	val = (data->csc_mv[6] & 0x1FFF) |
+		((data->csc_mv[7] & 0x1FFF) << 16);
 	SDE_REG_WRITE(c, csc_reg_off + 0xc, val);
-	val = data->csc_mv[8] & 0x1FF;
+	val = data->csc_mv[8] & 0x1FFF;
 	SDE_REG_WRITE(c, csc_reg_off + 0x10, val);
 
 	/* Pre clamp */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 19cedd3..49b8d5b 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -10,10 +10,10 @@
  * GNU General Public License for more details.
  */
 
-#include "sde_hw_sspp.h"
 #include "sde_hwio.h"
 #include "sde_hw_catalog.h"
 #include "sde_hw_lm.h"
+#include "sde_hw_sspp.h"
 
 #define SDE_MDP_FETCH_CONFIG_RESET_VALUE   0x00000087
 
@@ -62,9 +62,9 @@
 #define SSPP_SW_PIX_EXT_C3_TB              0x124
 #define SSPP_SW_PIX_EXT_C3_REQ_PIXELS      0x128
 #define SSPP_UBWC_ERROR_STATUS             0x138
-#define SSPP_VIG_OP_MODE                   0x200
+#define SSPP_VIG_OP_MODE                   0x0
 
-/* SDE_SSPP_SCALAR_QSEED2 */
+/* SDE_SSPP_SCALER_QSEED2 */
 #define SCALE_CONFIG                       0x04
 #define COMP0_3_PHASE_STEP_X               0x10
 #define COMP0_3_PHASE_STEP_Y               0x14
@@ -76,32 +76,29 @@
 #define COMP1_2_INIT_PHASE_Y               0x2C
 #define VIG_0_QSEED2_SHARP                 0x30
 
-#define VIG_0_CSC_1_MATRIX_COEFF_0         0x20
-#define VIG_0_CSC_1_COMP_0_PRE_CLAMP       0x34
-#define VIG_0_CSC_1_COMP_0_POST_CLAMP      0x40
-#define VIG_0_CSC_1_COMP_0_PRE_BIAS        0x4C
-#define VIG_0_CSC_1_COMP_0_POST_BIAS       0x60
-
 /*
  * MDP Solid fill configuration
  * argb8888
  */
 #define SSPP_SOLID_FILL                   0x4037ff
 
-enum {
-	CSC = 0x1,
-	PA,
-	HIST,
-	SKIN_COL,
-	FOIL,
-	SKY_COL,
-	MEM_PROT_HUE,
-	MEM_PROT_SAT,
-	MEM_PROT_VAL,
-	MEM_PROT_CONT,
-	MEM_PROT_BLEND,
-	PA_SAT_ADJ
-};
+/*
+ * Definitions for ViG op modes
+ */
+#define VIG_OP_CSC_DST_DATAFMT BIT(19)
+#define VIG_OP_CSC_SRC_DATAFMT BIT(18)
+#define VIG_OP_CSC_EN          BIT(17)
+#define VIG_OP_MEM_PROT_CONT   BIT(15)
+#define VIG_OP_MEM_PROT_VAL    BIT(14)
+#define VIG_OP_MEM_PROT_SAT    BIT(13)
+#define VIG_OP_MEM_PROT_HUE    BIT(12)
+#define VIG_OP_HIST            BIT(8)
+#define VIG_OP_SKY_COL         BIT(7)
+#define VIG_OP_FOIL            BIT(6)
+#define VIG_OP_SKIN_COL        BIT(5)
+#define VIG_OP_PA_EN           BIT(4)
+#define VIG_OP_PA_SAT_ZERO_EXP BIT(2)
+#define VIG_OP_MEM_PROT_BLEND  BIT(1)
 
 static inline int _sspp_subblk_offset(struct sde_hw_pipe *ctx,
 		int s_id,
@@ -110,14 +107,17 @@
 	int rc = 0;
 	const struct sde_sspp_sub_blks *sblk = ctx->cap->sblk;
 
+	if (!ctx)
+		return -EINVAL;
+
 	switch (s_id) {
 	case SDE_SSPP_SRC:
 		*idx = sblk->src_blk.base;
 		break;
-	case SDE_SSPP_SCALAR_QSEED2:
-	case SDE_SSPP_SCALAR_QSEED3:
-	case SDE_SSPP_SCALAR_RGB:
-		*idx = sblk->scalar_blk.base;
+	case SDE_SSPP_SCALER_QSEED2:
+	case SDE_SSPP_SCALER_QSEED3:
+	case SDE_SSPP_SCALER_RGB:
+		*idx = sblk->scaler_blk.base;
 		break;
 	case SDE_SSPP_CSC:
 		*idx = sblk->csc_blk.base;
@@ -133,39 +133,28 @@
 		break;
 	default:
 		rc = -EINVAL;
-		pr_err("Unsupported SSPP sub-blk for this hw\n");
 	}
 
 	return rc;
 }
 
 static void _sspp_setup_opmode(struct sde_hw_pipe *ctx,
-		u32 op, u8 en)
+		u32 mask, u8 en)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
 	u32 idx;
 	u32 opmode;
 
-	if (ctx->cap->features == SDE_SSPP_PA_V1) {
+	if (!_sspp_subblk_offset(ctx, SDE_SSPP_SCALER_QSEED2, &idx) &&
+			(test_bit(SDE_SSPP_CSC, &ctx->cap->features) ||
+			 test_bit(SDE_SSPP_PA_V1, &ctx->cap->features))) {
+		opmode = SDE_REG_READ(&ctx->hw, SSPP_VIG_OP_MODE + idx);
 
-		if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
-			return;
+		if (en)
+			opmode |= mask;
+		else
+			opmode &= ~mask;
 
-		opmode = SDE_REG_READ(c, SSPP_VIG_OP_MODE + idx);
-
-		/* ops */
-		switch (op) {
-		case CSC:
-			if (en)
-				/* CSC_1_EN and CSC_SRC_DATA_FORMAT*/
-				opmode |= BIT(18) | BIT(17);
-			else
-				opmode &= ~BIT(17);
-			break;
-		default:
-			pr_err(" Unsupported operation\n");
-		}
-		SDE_REG_WRITE(c, SSPP_VIG_OP_MODE + idx, opmode);
+		SDE_REG_WRITE(&ctx->hw, SSPP_VIG_OP_MODE + idx, opmode);
 	}
 }
 /**
@@ -175,16 +164,17 @@
 		struct sde_hw_pipe_cfg *cfg,
 		u32 flags)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	struct sde_hw_blk_reg_map *c;
 	struct sde_mdp_format_params *fmt;
 	u32 chroma_samp, unpack, src_format;
 	u32 secure = 0;
 	u32 opmode = 0;
 	u32 idx;
 
-	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx) || !cfg)
 		return;
 
+	c = &ctx->hw;
 	opmode = SDE_REG_READ(c, SSPP_SRC_OP_MODE + idx);
 
 	/* format info */
@@ -234,12 +224,15 @@
 			ctx->highest_bank_bit << 18);
 	}
 
+	opmode |= MDSS_MDP_OP_PE_OVERRIDE;
+
 	/* if this is YUV pixel format, enable CSC */
 	if (fmt->is_yuv)
 		src_format |= BIT(15);
-	_sspp_setup_opmode(ctx, CSC, fmt->is_yuv);
 
-	opmode |= MDSS_MDP_OP_PE_OVERRIDE;
+	/* update scaler opmode, if appropriate */
+	_sspp_setup_opmode(ctx,
+		VIG_OP_CSC_EN | VIG_OP_CSC_SRC_DATAFMT, fmt->is_yuv);
 
 	SDE_REG_WRITE(c, SSPP_SRC_FORMAT + idx, src_format);
 	SDE_REG_WRITE(c, SSPP_SRC_UNPACK_PATTERN + idx, unpack);
@@ -251,21 +244,22 @@
 }
 
 static void sde_hw_sspp_setup_pe_config(struct sde_hw_pipe *ctx,
-		struct sde_hw_pipe_cfg *cfg,
 		struct sde_hw_pixel_ext *pe_ext)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	struct sde_hw_blk_reg_map *c;
 	u8 color;
 	u32 lr_pe[4], tb_pe[4], tot_req_pixels[4];
 	const u32 bytemask = 0xff;
 	const u32 shortmask = 0xffff;
 	u32 idx;
 
-	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx) || !pe_ext)
 		return;
 
+	c = &ctx->hw;
+
 	/* program SW pixel extension override for all pipes*/
-	for (color = 0; color < 4; color++) {
+	for (color = 0; color < SDE_MAX_PLANES; color++) {
 		/* color 2 has the same set of registers as color 1 */
 		if (color == 2)
 			continue;
@@ -307,43 +301,58 @@
 			tot_req_pixels[3]);
 }
 
-static void sde_hw_sspp_setup_scalar(struct sde_hw_pipe *ctx,
-		struct sde_hw_pixel_ext *pe_ext)
+static void _sde_hw_sspp_setup_scaler(struct sde_hw_pipe *ctx,
+		struct sde_hw_pixel_ext *pe)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
-	int scale_config;
-	const u8 mask = 0x3;
+	struct sde_hw_blk_reg_map *c;
+	int config_h = 0x0;
+	int config_v = 0x0;
 	u32 idx;
 
-	if (_sspp_subblk_offset(ctx, SDE_SSPP_SCALAR_QSEED2, &idx))
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SCALER_QSEED2, &idx) || !pe)
 		return;
 
-	scale_config = BIT(0) | BIT(1);
-	/* RGB/YUV config */
-	scale_config |= (pe_ext->horz_filter[SDE_SSPP_COMP_LUMA] & mask) << 8;
-	scale_config |= (pe_ext->vert_filter[SDE_SSPP_COMP_LUMA] & mask) << 10;
-	/* Aplha config*/
-	scale_config |= (pe_ext->horz_filter[SDE_SSPP_COMP_ALPHA] & mask) << 16;
-	scale_config |= (pe_ext->vert_filter[SDE_SSPP_COMP_ALPHA] & mask) << 18;
+	c = &ctx->hw;
 
-	SDE_REG_WRITE(c, SCALE_CONFIG + idx,  scale_config);
+	/* enable scaler(s) if valid filter set */
+	if (pe->horz_filter[SDE_SSPP_COMP_0] < SDE_MDP_SCALE_FILTER_MAX)
+		config_h |= pe->horz_filter[SDE_SSPP_COMP_0] << 8;
+	if (pe->horz_filter[SDE_SSPP_COMP_1_2] < SDE_MDP_SCALE_FILTER_MAX)
+		config_h |= pe->horz_filter[SDE_SSPP_COMP_1_2] << 12;
+	if (pe->horz_filter[SDE_SSPP_COMP_3] < SDE_MDP_SCALE_FILTER_MAX)
+		config_h |= pe->horz_filter[SDE_SSPP_COMP_3] << 16;
+
+	if (config_h)
+		config_h |= BIT(0);
+
+	if (pe->vert_filter[SDE_SSPP_COMP_0] < SDE_MDP_SCALE_FILTER_MAX)
+		config_v |= pe->vert_filter[SDE_SSPP_COMP_0] << 10;
+	if (pe->vert_filter[SDE_SSPP_COMP_1_2] < SDE_MDP_SCALE_FILTER_MAX)
+		config_v |= pe->vert_filter[SDE_SSPP_COMP_1_2] << 14;
+	if (pe->vert_filter[SDE_SSPP_COMP_3] < SDE_MDP_SCALE_FILTER_MAX)
+		config_v |= pe->vert_filter[SDE_SSPP_COMP_3] << 18;
+
+	if (config_v)
+		config_v |= BIT(1);
+
+	SDE_REG_WRITE(c, SCALE_CONFIG + idx,  config_h | config_v);
 	SDE_REG_WRITE(c, COMP0_3_INIT_PHASE_X + idx,
-			pe_ext->init_phase_x[SDE_SSPP_COMP_LUMA]);
+		pe->init_phase_x[SDE_SSPP_COMP_0]);
 	SDE_REG_WRITE(c, COMP0_3_INIT_PHASE_Y + idx,
-			pe_ext->init_phase_y[SDE_SSPP_COMP_LUMA]);
+		pe->init_phase_y[SDE_SSPP_COMP_0]);
 	SDE_REG_WRITE(c, COMP0_3_PHASE_STEP_X + idx,
-			pe_ext->phase_step_x[SDE_SSPP_COMP_LUMA]);
+		pe->phase_step_x[SDE_SSPP_COMP_0]);
 	SDE_REG_WRITE(c, COMP0_3_PHASE_STEP_Y + idx,
-			pe_ext->phase_step_y[SDE_SSPP_COMP_LUMA]);
+		pe->phase_step_y[SDE_SSPP_COMP_0]);
 
 	SDE_REG_WRITE(c, COMP1_2_INIT_PHASE_X + idx,
-			pe_ext->init_phase_x[SDE_SSPP_COMP_CHROMA]);
+		pe->init_phase_x[SDE_SSPP_COMP_1_2]);
 	SDE_REG_WRITE(c, COMP1_2_INIT_PHASE_Y + idx,
-			pe_ext->init_phase_y[SDE_SSPP_COMP_CHROMA]);
+		pe->init_phase_y[SDE_SSPP_COMP_1_2]);
 	SDE_REG_WRITE(c, COMP1_2_PHASE_STEP_X + idx,
-			pe_ext->phase_step_x[SDE_SSPP_COMP_CHROMA]);
+		pe->phase_step_x[SDE_SSPP_COMP_1_2]);
 	SDE_REG_WRITE(c, COMP1_2_PHASE_STEP_Y + idx,
-			pe_ext->phase_step_y[SDE_SSPP_COMP_CHROMA]);
+		pe->phase_step_y[SDE_SSPP_COMP_1_2]);
 }
 
 /**
@@ -353,17 +362,19 @@
 		struct sde_hw_pipe_cfg *cfg,
 		struct sde_hw_pixel_ext *pe_ext)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	struct sde_hw_blk_reg_map *c;
 	u32 src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
 	u32 decimation = 0;
 	u32 idx;
 
-	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx) || !cfg)
 		return;
 
+	c = &ctx->hw;
+
 	/* program pixel extension override */
 	if (pe_ext)
-		sde_hw_sspp_setup_pe_config(ctx, cfg, pe_ext);
+		sde_hw_sspp_setup_pe_config(ctx, pe_ext);
 
 	/* src and dest rect programming */
 	src_xy = (cfg->src_rect.y << 16) |
@@ -380,16 +391,13 @@
 	ystride1 =  (cfg->src.ystride[2]) |
 		(cfg->src.ystride[3] << 16);
 
-	/* program scalar, phase registers, if pipes supporting scaling */
-	if (src_size != dst_size) {
-		if (test_bit(SDE_SSPP_SCALAR_RGB, &ctx->cap->features) ||
-			test_bit(SDE_SSPP_SCALAR_QSEED2, &ctx->cap->features)) {
-			/* program decimation */
-			decimation = ((1 << cfg->horz_decimation) - 1) << 8;
-			decimation |= ((1 << cfg->vert_decimation) - 1);
+	/* program scaler, phase registers, if pipes supporting scaling */
+	if (ctx->cap->features & SDE_SSPP_SCALER) {
+		/* program decimation */
+		decimation = ((1 << cfg->horz_decimation) - 1) << 8;
+		decimation |= ((1 << cfg->vert_decimation) - 1);
 
-			sde_hw_sspp_setup_scalar(ctx, pe_ext);
-		}
+		_sde_hw_sspp_setup_scaler(ctx, pe_ext);
 	}
 
 	/* Rectangle Register programming */
@@ -406,7 +414,6 @@
 static void sde_hw_sspp_setup_sourceaddress(struct sde_hw_pipe *ctx,
 		struct sde_hw_pipe_cfg *cfg)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
 	int i;
 	u32 idx;
 
@@ -414,27 +421,32 @@
 		return;
 
 	for (i = 0; i < cfg->src.num_planes; i++)
-		SDE_REG_WRITE(c, SSPP_SRC0_ADDR + idx + i*0x4,
+		SDE_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR  + idx + i*0x4,
 			cfg->addr.plane[i]);
 }
 
-static void sde_hw_sspp_setup_csc_8bit(struct sde_hw_pipe *ctx,
+static void sde_hw_sspp_setup_csc(struct sde_hw_pipe *ctx,
 		struct sde_csc_cfg *data)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	u32 idx;
 
-	sde_hw_csc_setup(c, VIG_0_CSC_1_MATRIX_COEFF_0, data);
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_CSC, &idx) || !data)
+		return;
+
+	sde_hw_csc_setup(&ctx->hw, idx, data);
 }
 
 static void sde_hw_sspp_setup_sharpening(struct sde_hw_pipe *ctx,
 		struct sde_hw_sharp_cfg *cfg)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	struct sde_hw_blk_reg_map *c;
 	u32 idx;
 
-	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SCALER_QSEED2, &idx) || !cfg)
 		return;
 
+	c = &ctx->hw;
+
 	SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx, cfg->strength);
 	SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0x4, cfg->edge_thr);
 	SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0x8, cfg->smooth_thr);
@@ -445,7 +457,7 @@
 		u32 const_color,
 		u32 flags)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	struct sde_hw_blk_reg_map *c;
 	u32 secure = 0;
 	u32 unpack, src_format, opmode = 0;
 	u32 idx;
@@ -453,6 +465,8 @@
 	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
 		return;
 
+	c = &ctx->hw;
+
 	/* format info */
 	src_format = SSPP_SOLID_FILL;
 	unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) |
@@ -468,7 +482,7 @@
 }
 
 static void sde_hw_sspp_setup_histogram_v1(struct sde_hw_pipe *ctx,
-			void *cfg)
+		void *cfg)
 {
 }
 
@@ -488,14 +502,13 @@
 static void sde_hw_sspp_setup_danger_safe(struct sde_hw_pipe *ctx,
 		u32 danger_lut, u32 safe_lut)
 {
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
 	u32 idx;
 
 	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
 		return;
 
-	SDE_REG_WRITE(c, SSPP_DANGER_LUT + idx, danger_lut);
-	SDE_REG_WRITE(c, SSPP_SAFE_LUT + idx, safe_lut);
+	SDE_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, danger_lut);
+	SDE_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, safe_lut);
 }
 
 static void sde_hw_sspp_qseed2_coeff(void *ctx)
@@ -513,7 +526,7 @@
 		ops->setup_danger_safe = sde_hw_sspp_setup_danger_safe;
 	}
 	if (test_bit(SDE_SSPP_CSC, &features))
-		ops->setup_csc = sde_hw_sspp_setup_csc_8bit;
+		ops->setup_csc = sde_hw_sspp_setup_csc;
 
 	if (test_bit(SDE_SSPP_PA_V1, &features)) {
 		ops->setup_sharpening = sde_hw_sspp_setup_sharpening;
@@ -527,18 +540,20 @@
 }
 
 static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
-		struct sde_mdss_cfg *m,
 		void __iomem *addr,
+		struct sde_mdss_cfg *catalog,
 		struct sde_hw_blk_reg_map *b)
 {
 	int i;
 
-	for (i = 0; i < m->sspp_count; i++) {
-		if (sspp == m->sspp[i].id) {
-			b->base_off = addr;
-			b->blk_off = m->sspp[i].base;
-			b->hwversion = m->hwversion;
-			return &m->sspp[i];
+	if ((sspp < SSPP_MAX) && catalog && addr && b) {
+		for (i = 0; i < catalog->sspp_count; i++) {
+			if (sspp == catalog->sspp[i].id) {
+				b->base_off = addr;
+				b->blk_off = catalog->sspp[i].base;
+				b->hwversion = catalog->hwversion;
+				return &catalog->sspp[i];
+			}
 		}
 	}
 
@@ -547,39 +562,39 @@
 
 struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
 			void __iomem *addr,
-			struct sde_mdss_cfg *m)
+			struct sde_mdss_cfg *catalog)
 {
-	struct sde_hw_pipe *c;
+	struct sde_hw_pipe *ctx;
 	struct sde_sspp_cfg *cfg;
 
-	c = kzalloc(sizeof(*c), GFP_KERNEL);
-	if (!c)
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
 		return ERR_PTR(-ENOMEM);
 
-	cfg = _sspp_offset(idx, m, addr, &c->hw);
+	cfg = _sspp_offset(idx, addr, catalog, &ctx->hw);
 	if (IS_ERR_OR_NULL(cfg)) {
-		kfree(c);
+		kfree(ctx);
 		return ERR_PTR(-EINVAL);
 	}
 
 	/* Assign ops */
-	c->idx = idx;
-	c->cap = cfg;
-	_setup_layer_ops(&c->ops, c->cap->features);
-	c->highest_bank_bit = m->mdp[0].highest_bank_bit;
+	ctx->idx = idx;
+	ctx->cap = cfg;
+	_setup_layer_ops(&ctx->ops, ctx->cap->features);
+	ctx->highest_bank_bit = catalog->mdp[0].highest_bank_bit;
 
 	/*
 	 * Perform any default initialization for the sspp blocks
 	 */
-	if (test_bit(SDE_SSPP_SCALAR_QSEED2, &cfg->features))
-		sde_hw_sspp_qseed2_coeff(c);
+	if (test_bit(SDE_SSPP_SCALER_QSEED2, &cfg->features))
+		sde_hw_sspp_qseed2_coeff(ctx);
 
-	if (test_bit(SDE_MDP_PANIC_PER_PIPE, &m->mdp[0].features))
-		sde_hw_sspp_setup_danger_safe(c,
+	if (test_bit(SDE_MDP_PANIC_PER_PIPE, &catalog->mdp[0].features))
+		sde_hw_sspp_setup_danger_safe(ctx,
 				cfg->sblk->danger_lut,
 				cfg->sblk->safe_lut);
 
-	return c;
+	return ctx;
 }
 
 void sde_hw_sspp_destroy(struct sde_hw_pipe *ctx)
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
index feb5e85..768201c 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
@@ -29,12 +29,22 @@
 #define SDE_SSPP_ROT_90  0x10
 
 /**
+ * Define all scaler feature bits in catalog
+ */
+#define SDE_SSPP_SCALER ((1UL << SDE_SSPP_SCALER_RGB) | \
+	(1UL << SDE_SSPP_SCALER_QSEED2) | \
+	(1UL << SDE_SSPP_SCALER_QSEED3))
+
+/**
  * Component indices
  */
 enum {
-	SDE_SSPP_COMP_LUMA = 0,
-	SDE_SSPP_COMP_CHROMA = 1,
-	SDE_SSPP_COMP_ALPHA = 3
+	SDE_SSPP_COMP_0,
+	SDE_SSPP_COMP_1_2,
+	SDE_SSPP_COMP_2,
+	SDE_SSPP_COMP_3,
+
+	SDE_SSPP_COMP_MAX
 };
 
 enum {
@@ -179,8 +189,7 @@
 	 * @ctx: Pointer to pipe context
 	 * @data: Pointer to config structure
 	 */
-	void (*setup_csc)(struct sde_hw_pipe *ctx,
-			struct sde_csc_cfg *data);
+	void (*setup_csc)(struct sde_hw_pipe *ctx, struct sde_csc_cfg *data);
 
 	/**
 	 * setup_solidfill - enable/disable colorfill
@@ -265,11 +274,11 @@
  * Should be called once before accessing every pipe.
  * @idx:  Pipe index for which driver object is required
  * @addr: Mapped register io address of MDP
- * @m:    pointer to mdss catalog data @ops:
+ * @catalog : Pointer to mdss catalog data
  */
 struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
 			void __iomem *addr,
-			struct sde_mdss_cfg *m);
+			struct sde_mdss_cfg *catalog);
 
 /**
  * sde_hw_sspp_destroy(): Destroys SSPP driver context
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 1721493..c5e225f 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -121,9 +121,10 @@
 	struct drm_plane_state base;
 
 	/* aligned with property */
-	uint8_t premultiplied;
-	uint8_t zpos;
-	uint8_t alpha;
+	uint64_t property_values[PLANE_PROP_COUNT];
+
+	/* blob properties */
+	struct drm_property_blob *property_blobs[PLANE_PROP_BLOBCOUNT];
 
 	/* assigned by crtc blender */
 	enum sde_stage stage;
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 993df81..7393764 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -21,10 +21,10 @@
 #define PHASE_STEP_UNIT_SCALE   ((int) (1 << PHASE_STEP_SHIFT))
 #define PHASE_RESIDUAL		15
 
-#define SDE_PLANE_FEATURE_SCALER \
-	(BIT(SDE_SSPP_SCALAR_QSEED2)| \
-		BIT(SDE_SSPP_SCALAR_QSEED3)| \
-		BIT(SDE_SSPP_SCALAR_RGB))
+#define SHARP_STRENGTH_DEFAULT	32
+#define SHARP_EDGE_THR_DEFAULT	112
+#define SHARP_SMOOTH_THR_DEFAULT	8
+#define SHARP_NOISE_THR_DEFAULT	2
 
 #ifndef SDE_PLANE_DEBUG_START
 #define SDE_PLANE_DEBUG_START()
@@ -42,13 +42,13 @@
 
 	enum sde_sspp pipe;
 	uint32_t features;      /* capabilities from catalog */
-	uint32_t flush_mask;    /* used to commit pipe registers */
 	uint32_t nformats;
 	uint32_t formats[32];
 
 	struct sde_hw_pipe *pipe_hw;
 	struct sde_hw_pipe_cfg pipe_cfg;
 	struct sde_hw_pixel_ext pixel_ext;
+	struct sde_hw_sharp_cfg sharp_cfg;
 };
 #define to_sde_plane(x) container_of(x, struct sde_plane, base)
 
@@ -57,7 +57,7 @@
 	return state->fb && state->crtc;
 }
 
-static void sde_plane_set_scanout(struct drm_plane *plane,
+static void _sde_plane_set_scanout(struct drm_plane *plane,
 		struct sde_hw_pipe_cfg *pipe_cfg, struct drm_framebuffer *fb)
 {
 	struct sde_plane *psde = to_sde_plane(plane);
@@ -81,53 +81,63 @@
 	}
 }
 
-static void sde_plane_scale_helper(struct drm_plane *plane,
+static void _sde_plane_setup_scaler(struct drm_plane *plane,
 		uint32_t src, uint32_t dst, uint32_t *phase_steps,
 		enum sde_hw_filter *filter, struct sde_mdp_format_params *fmt,
 		uint32_t chroma_subsampling)
 {
 	/* calcualte phase steps, leave init phase as zero */
-	phase_steps[SDE_SSPP_COMP_LUMA] =
+	phase_steps[SDE_SSPP_COMP_0] =
 		mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
-	phase_steps[SDE_SSPP_COMP_CHROMA] =
-		phase_steps[SDE_SSPP_COMP_LUMA] / chroma_subsampling;
+	phase_steps[SDE_SSPP_COMP_1_2] =
+		phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
+	phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
+	phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
 
 	/* calculate scaler config, if necessary */
-	if (src != dst) {
-		filter[SDE_SSPP_COMP_ALPHA] = (src < dst) ?
-				SDE_MDP_SCALE_FILTER_BIL :
-				SDE_MDP_SCALE_FILTER_PCMN;
+	if (fmt->is_yuv || src != dst) {
+		filter[SDE_SSPP_COMP_3] =
+			(src <= dst) ? SDE_MDP_SCALE_FILTER_BIL :
+			SDE_MDP_SCALE_FILTER_PCMN;
 
-		if (fmt->is_yuv)
-			filter[SDE_SSPP_COMP_LUMA] = SDE_MDP_SCALE_FILTER_CA;
-		else
-			filter[SDE_SSPP_COMP_LUMA] =
-					filter[SDE_SSPP_COMP_ALPHA];
+		if (fmt->is_yuv) {
+			filter[SDE_SSPP_COMP_0] = SDE_MDP_SCALE_FILTER_CA;
+			filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
+		} else {
+			filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
+			filter[SDE_SSPP_COMP_1_2] =
+				SDE_MDP_SCALE_FILTER_NEAREST;
+		}
+	} else {
+		/* disable scaler */
+		filter[SDE_SSPP_COMP_0] = SDE_MDP_SCALE_FILTER_MAX;
+		filter[SDE_SSPP_COMP_1_2] = SDE_MDP_SCALE_FILTER_MAX;
+		filter[SDE_SSPP_COMP_3] = SDE_MDP_SCALE_FILTER_MAX;
 	}
 }
 
-/* CIFIX: clean up fmt/subsampling params once we're using fourcc formats */
-static void _sde_plane_pixel_ext_helper(struct drm_plane *plane,
+static void _sde_plane_setup_pixel_ext(struct drm_plane *plane,
 		uint32_t src, uint32_t dst, uint32_t decimated_src,
 		uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
-		int *out_edge2, struct sde_mdp_format_params *fmt,
-		uint32_t chroma_subsampling, bool post_compare)
+		int *out_edge2, enum sde_hw_filter *filter,
+		struct sde_mdp_format_params *fmt, uint32_t chroma_subsampling,
+		bool post_compare)
 {
-	/* CIFIX: adapted from mdss_mdp_pipe_calc_pixel_extn() */
 	int64_t edge1, edge2, caf;
 	uint32_t src_work;
 	int i, tmp;
 
-	if (plane && phase_steps && out_src && out_edge1 && out_edge2 && fmt) {
-		/* enable CAF for YUV formats */
-		if (fmt->is_yuv)
+	if (plane && phase_steps && out_src && out_edge1 &&
+			out_edge2 && filter && fmt) {
+		/* handle CAF for YUV formats */
+		if (fmt->is_yuv && SDE_MDP_SCALE_FILTER_CA == *filter)
 			caf = PHASE_STEP_UNIT_SCALE;
 		else
 			caf = 0;
 
 		for (i = 0; i < SDE_MAX_PLANES; i++) {
 			src_work = decimated_src;
-			if (i == 1 || i == 2)
+			if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
 				src_work /= chroma_subsampling;
 			if (post_compare)
 				src = src_work;
@@ -160,15 +170,15 @@
 			*(out_src + i) = src_work;
 
 			/* edge updates taken from __pxl_extn_helper */
-			/* CIFIX: why are we casting first to uint32_t? */
 			if (edge1 >= 0) {
 				tmp = (uint32_t)edge1;
 				tmp >>= PHASE_STEP_SHIFT;
 				*(out_edge1 + i) = -tmp;
 			} else {
 				tmp = (uint32_t)(-edge1);
-				*(out_edge1 + i) = (tmp + PHASE_STEP_UNIT_SCALE
-						- 1) >> PHASE_STEP_SHIFT;
+				*(out_edge1 + i) =
+					(tmp + PHASE_STEP_UNIT_SCALE - 1) >>
+					PHASE_STEP_SHIFT;
 			}
 			if (edge2 >= 0) {
 				tmp = (uint32_t)edge2;
@@ -176,14 +186,54 @@
 				*(out_edge2 + i) = -tmp;
 			} else {
 				tmp = (uint32_t)(-edge2);
-				*(out_edge2 + i) = (tmp + PHASE_STEP_UNIT_SCALE
-						- 1) >> PHASE_STEP_SHIFT;
+				*(out_edge2 + i) =
+					(tmp + PHASE_STEP_UNIT_SCALE - 1) >>
+					PHASE_STEP_SHIFT;
 			}
 		}
 	}
 }
 
-static int sde_plane_mode_set(struct drm_plane *plane,
+static void _sde_plane_setup_csc(struct sde_plane *psde,
+		struct sde_plane_state *pstate,
+		struct sde_mdp_format_params *fmt)
+{
+	static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
+		{
+			0x0254, 0x0000, 0x0331,
+			0x0254, 0xff37, 0xfe60,
+			0x0254, 0x0409, 0x0000,
+		},
+		{ 0xfff0, 0xff80, 0xff80,},
+		{ 0x0, 0x0, 0x0,},
+		{ 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,},
+	};
+
+	static const struct sde_csc_cfg sde_csc_NOP = {
+		{
+			0x0200, 0x0000, 0x0000,
+			0x0000, 0x0200, 0x0000,
+			0x0000, 0x0000, 0x0200,
+		},
+		{ 0x0, 0x0, 0x0,},
+		{ 0x0, 0x0, 0x0,},
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,},
+		{ 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,},
+	};
+
+	if (!psde->pipe_hw->ops.setup_csc)
+		return;
+
+	if (fmt->is_yuv)
+		psde->pipe_hw->ops.setup_csc(psde->pipe_hw,
+			(struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L);
+	else
+		psde->pipe_hw->ops.setup_csc(psde->pipe_hw,
+			(struct sde_csc_cfg *)&sde_csc_NOP);
+}
+
+static int _sde_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		int crtc_x, int crtc_y,
 		unsigned int crtc_w, unsigned int crtc_h,
@@ -221,12 +271,12 @@
 	memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
 
 	psde->pipe_cfg.src.format = sde_mdp_get_format_params(pix_format,
-			0/* CIFIX: fmt_modifier */);
+			fb->modifier[0]);
 	psde->pipe_cfg.src.width = fb->width;
 	psde->pipe_cfg.src.height = fb->height;
 	psde->pipe_cfg.src.num_planes = nplanes;
 
-	sde_plane_set_scanout(plane, &psde->pipe_cfg, fb);
+	_sde_plane_set_scanout(plane, &psde->pipe_cfg, fb);
 
 	psde->pipe_cfg.src_rect.x = src_x;
 	psde->pipe_cfg.src_rect.y = src_y;
@@ -257,10 +307,10 @@
 		memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
 
 		/* calculate phase steps */
-		sde_plane_scale_helper(plane, src_w, crtc_w,
+		_sde_plane_setup_scaler(plane, src_w, crtc_w,
 				pe->phase_step_x,
 				pe->horz_filter, fmt, chroma_subsample_h);
-		sde_plane_scale_helper(plane, src_h, crtc_h,
+		_sde_plane_setup_scaler(plane, src_h, crtc_h,
 				pe->phase_step_y,
 				pe->vert_filter, fmt, chroma_subsample_v);
 
@@ -269,24 +319,22 @@
 				psde->pipe_cfg.horz_decimation);
 		if (fmt->is_yuv)
 			tmp &= ~0x1;
-		_sde_plane_pixel_ext_helper(plane, src_w, crtc_w, tmp,
+		_sde_plane_setup_pixel_ext(plane, src_w, crtc_w, tmp,
 				pe->phase_step_x,
 				pe->roi_w,
 				pe->num_ext_pxls_left,
-				pe->num_ext_pxls_right, fmt,
+				pe->num_ext_pxls_right, pe->horz_filter, fmt,
 				chroma_subsample_h, 0);
 
 		tmp = DECIMATED_DIMENSION(src_h,
 				psde->pipe_cfg.vert_decimation);
-		_sde_plane_pixel_ext_helper(plane, src_h, crtc_h, tmp,
+		_sde_plane_setup_pixel_ext(plane, src_h, crtc_h, tmp,
 				pe->phase_step_y,
 				pe->roi_h,
 				pe->num_ext_pxls_top,
-				pe->num_ext_pxls_btm, fmt,
+				pe->num_ext_pxls_btm, pe->vert_filter, fmt,
 				chroma_subsample_v, 1);
 
-		/* CIFIX: port "Single pixel rgb scale adjustment"? */
-
 		for (i = 0; i < SDE_MAX_PLANES; i++) {
 			if (pe->num_ext_pxls_left[i] >= 0)
 				pe->left_rpt[i] =
@@ -320,12 +368,24 @@
 
 	if (psde->pipe_hw->ops.setup_sourceformat)
 		psde->pipe_hw->ops.setup_sourceformat(psde->pipe_hw,
-				&psde->pipe_cfg, 0 /* CIFIX: flags */);
+				&psde->pipe_cfg, 0);
 	if (psde->pipe_hw->ops.setup_rects)
 		psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
 				&psde->pipe_cfg, &psde->pixel_ext);
 
+	/* update sharpening */
+	psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
+	psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
+	psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
+	psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
+
+	if (psde->pipe_hw->ops.setup_sharpening)
+		psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
+			&psde->sharp_cfg);
+
 	/* update csc */
+	if (fmt->is_yuv)
+		_sde_plane_setup_csc(psde, pstate, fmt);
 
 	SDE_PLANE_DEBUG_END();
 	return ret;
@@ -377,7 +437,7 @@
 		/* CIFIX: don't use mdp format? */
 		format = to_mdp_format(msm_framebuffer_format(state->fb));
 		if (MDP_FORMAT_IS_YUV(format) &&
-			(!(psde->features & SDE_PLANE_FEATURE_SCALER) ||
+			(!(psde->features & SDE_SSPP_SCALER) ||
 			 !(psde->features & BIT(SDE_SSPP_CSC)))) {
 			dev_err(plane->dev->dev,
 				"Pipe doesn't support YUV\n");
@@ -385,7 +445,7 @@
 			return -EINVAL;
 		}
 
-		if (!(psde->features & SDE_PLANE_FEATURE_SCALER) &&
+		if (!(psde->features & SDE_SSPP_SCALER) &&
 			(((state->src_w >> 16) != state->crtc_w) ||
 			((state->src_h >> 16) != state->crtc_h))) {
 			dev_err(plane->dev->dev,
@@ -415,8 +475,8 @@
 		}
 		if (full_modeset) {
 			struct drm_crtc_state *crtc_state =
-					drm_atomic_get_crtc_state(state->state,
-							state->crtc);
+				drm_atomic_get_crtc_state(state->state,
+					state->crtc);
 			crtc_state->mode_changed = true;
 			to_sde_plane_state(state)->mode_changed = true;
 		}
@@ -428,7 +488,7 @@
 }
 
 static void sde_plane_atomic_update(struct drm_plane *plane,
-				     struct drm_plane_state *old_state)
+				struct drm_plane_state *old_state)
 {
 	struct sde_plane *sde_plane = to_sde_plane(plane);
 	struct drm_plane_state *state = plane->state;
@@ -442,7 +502,7 @@
 		int ret;
 
 		to_sde_plane_state(state)->pending = true;
-		ret = sde_plane_mode_set(plane,
+		ret = _sde_plane_mode_set(plane,
 				state->crtc, state->fb,
 				state->crtc_x, state->crtc_y,
 				state->crtc_w, state->crtc_h,
@@ -451,36 +511,55 @@
 		/* atomic_check should have ensured that this doesn't fail */
 		WARN_ON(ret < 0);
 	} else {
-		sde_plane_set_scanout(plane, &sde_plane->pipe_cfg, state->fb);
+		_sde_plane_set_scanout(plane, &sde_plane->pipe_cfg, state->fb);
 	}
 	SDE_PLANE_DEBUG_END();
 }
 
+static void _sde_plane_install_range_property(struct drm_plane *plane,
+		struct drm_device *dev, const char *name,
+		uint64_t min, uint64_t max, uint64_t init,
+		struct drm_property **prop)
+{
+	if (plane && dev && name && prop) {
+		/* only create the property once */
+		if (*prop == 0) {
+			*prop = drm_property_create_range(dev,
+					0 /* flags */, name, min, max);
+			if (*prop == 0)
+				dev_warn(dev->dev,
+					"Create property %s failed\n", name);
+		}
+
+		/* always attach property, if created */
+		if (*prop)
+			drm_object_attach_property(&plane->base, *prop, init);
+	}
+}
+
+static void _sde_plane_install_blob_property(struct drm_plane *plane,
+		struct drm_device *dev, const char *name,
+		struct drm_property **prop)
+{
+}
+
 /* helper to install properties which are common to planes and crtcs */
-static void sde_plane_install_properties(struct drm_plane *plane,
+static void _sde_plane_install_properties(struct drm_plane *plane,
 		struct drm_mode_object *obj)
 {
 	struct drm_device *dev = plane->dev;
 	struct msm_drm_private *dev_priv = dev->dev_private;
-	struct drm_property *prop;
 
 	SDE_PLANE_DEBUG_START();
-#define INSTALL_PROPERTY(name, NAME, init_val, fnc, ...) {}
 
-#define INSTALL_RANGE_PROPERTY(name, NAME, min, max, init_val) \
-		INSTALL_PROPERTY(name, NAME, init_val, \
-				create_range, min, max)
+	/* range/enum properties */
+	_sde_plane_install_range_property(plane, dev, "zpos", 1, 255, 1,
+			&(dev_priv->plane_property[PLANE_PROP_ZPOS]));
 
-#define INSTALL_ENUM_PROPERTY(name, NAME, init_val) \
-		INSTALL_PROPERTY(name, NAME, init_val, \
-				create_enum, name##_prop_enum_list, \
-				ARRAY_SIZE(name##_prop_enum_list))
+	/* blob properties */
+	_sde_plane_install_blob_property(plane, dev, "pixext",
+			&(dev_priv->plane_property[PLANE_PROP_PIXEXT]));
 
-	INSTALL_RANGE_PROPERTY(zpos, ZPOS, 1, 255, 1);
-
-#undef INSTALL_RANGE_PROPERTY
-#undef INSTALL_ENUM_PROPERTY
-#undef INSTALL_PROPERTY
 	SDE_PLANE_DEBUG_END();
 }
 
@@ -490,29 +569,49 @@
 {
 	struct drm_device *dev = plane->dev;
 	struct sde_plane_state *pstate;
+	struct drm_property_blob *blob, **prop_blob;
 	struct msm_drm_private *dev_priv = dev->dev_private;
-	int ret = 0;
+	int idx, ret = -EINVAL;
 
 	SDE_PLANE_DEBUG_START();
 
 	pstate = to_sde_plane_state(state);
 
-#define SET_PROPERTY(name, NAME, type) do { \
-		if (dev_priv->plane_property[PLANE_PROP_##NAME] == property) { \
-			pstate->name = (type)val; \
-			DBG("Set property %s %d", #name, (type)val); \
-			goto done; \
-		} \
-	} while (0)
+	for (idx = 0; idx < PLANE_PROP_COUNT && ret; ++idx) {
+		if (dev_priv->plane_property[idx] == property) {
+			DBG("Set property %d <= %d", idx, (int)val);
 
-	SET_PROPERTY(zpos, ZPOS, uint8_t);
+			/* FUTURE: Add special handling here */
+			if (property->flags & DRM_MODE_PROP_BLOB) {
+				blob = drm_property_lookup_blob(dev,
+					(uint32_t)val);
+				if (!blob) {
+					dev_err(dev->dev, "Blob not found\n");
+					val = 0;
+				} else {
+					val = blob->base.id;
 
-	dev_err(dev->dev, "Invalid property\n");
-	ret = -EINVAL;
-done:
+					/* save blobs for later */
+					prop_blob =
+						&pstate->property_blobs[idx -
+						PLANE_PROP_FIRSTBLOB];
+					/* need to clear previous reference */
+					if (*prop_blob)
+						drm_property_unreference_blob(
+						    *prop_blob);
+					*prop_blob = blob;
+				}
+			}
+			pstate->property_values[idx] = val;
+			ret = 0;
+		}
+	}
+
+	if (ret == -EINVAL)
+		dev_err(dev->dev, "Invalid property set\n");
+
 	SDE_PLANE_DEBUG_END();
 	return ret;
-#undef SET_PROPERTY
 }
 
 static int sde_plane_set_property(struct drm_plane *plane,
@@ -534,27 +633,27 @@
 	struct drm_device *dev = plane->dev;
 	struct sde_plane_state *pstate;
 	struct msm_drm_private *dev_priv = dev->dev_private;
-	int ret = 0;
+	int idx, ret = -EINVAL;
 
 	SDE_PLANE_DEBUG_START();
+
 	pstate = to_sde_plane_state(state);
 
-#define GET_PROPERTY(name, NAME, type) do { \
-		if (dev_priv->plane_property[PLANE_PROP_##NAME] == property) { \
-			*val = pstate->name; \
-			DBG("Get property %s %lld", #name, *val); \
-			goto done; \
-		} \
-	} while (0)
+	for (idx = 0; idx < PLANE_PROP_COUNT; ++idx) {
+		if (dev_priv->plane_property[idx] == property) {
+			*val = pstate->property_values[idx];
+			DBG("Get property %d %lld", idx, *val);
+			ret = 0;
+			break;
+		}
+	}
 
-	GET_PROPERTY(zpos, ZPOS, uint8_t);
+	if (ret == -EINVAL)
+		dev_err(dev->dev, "Invalid property get\n");
 
-	dev_err(dev->dev, "Invalid property\n");
-	ret = -EINVAL;
-done:
 	SDE_PLANE_DEBUG_END();
+
 	return ret;
-#undef SET_PROPERTY
 }
 
 static void sde_plane_destroy(struct drm_plane *plane)
@@ -567,6 +666,8 @@
 		sde_hw_sspp_destroy(psde->pipe_hw);
 
 	drm_plane_helper_disable(plane);
+
+	/* this will destroy the states as well */
 	drm_plane_cleanup(plane);
 
 	kfree(psde);
@@ -577,11 +678,25 @@
 static void sde_plane_destroy_state(struct drm_plane *plane,
 		struct drm_plane_state *state)
 {
+	struct sde_plane_state *pstate;
+	int i;
+
 	SDE_PLANE_DEBUG_START();
+
+	/* remove ref count for frame buffers */
 	if (state->fb)
 		drm_framebuffer_unreference(state->fb);
 
-	kfree(to_sde_plane_state(state));
+	pstate = to_sde_plane_state(state);
+
+	/* remove ref count for blobs */
+	for (i = 0; i < PLANE_PROP_BLOBCOUNT; ++i)
+		if (pstate->property_blobs[i])
+			drm_property_unreference_blob(
+					pstate->property_blobs[i]);
+
+	kfree(pstate);
+
 	SDE_PLANE_DEBUG_END();
 }
 
@@ -589,6 +704,7 @@
 sde_plane_duplicate_state(struct drm_plane *plane)
 {
 	struct sde_plane_state *pstate;
+	int i;
 
 	if (WARN_ON(!plane->state))
 		return NULL;
@@ -596,15 +712,23 @@
 	SDE_PLANE_DEBUG_START();
 	pstate = kmemdup(to_sde_plane_state(plane->state),
 			sizeof(*pstate), GFP_KERNEL);
+	if (pstate) {
+		/* add ref count for frame buffer */
+		if (pstate->base.fb)
+			drm_framebuffer_reference(pstate->base.fb);
 
-	if (pstate && pstate->base.fb)
-		drm_framebuffer_reference(pstate->base.fb);
+		/* add ref count for blobs */
+		for (i = 0; i < PLANE_PROP_BLOBCOUNT; ++i)
+			if (pstate->property_blobs[i])
+				drm_property_reference_blob(
+						pstate->property_blobs[i]);
 
-	pstate->mode_changed = false;
-	pstate->pending = false;
+		pstate->mode_changed = false;
+		pstate->pending = false;
+	}
 	SDE_PLANE_DEBUG_END();
 
-	return &pstate->base;
+	return pstate ? &pstate->base : NULL;
 }
 
 static void sde_plane_reset(struct drm_plane *plane)
@@ -621,13 +745,14 @@
 	memset(pstate, 0, sizeof(struct sde_plane_state));
 
 	/* assign default blend parameters */
-	pstate->alpha = 255;
-	pstate->premultiplied = 0;
+	pstate->property_values[PLANE_PROP_ALPHA] = 255;
+	pstate->property_values[PLANE_PROP_PREMULTIPLIED] = 0;
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY)
-		pstate->zpos = STAGE_BASE;
+		pstate->property_values[PLANE_PROP_ZPOS] = STAGE_BASE;
 	else
-		pstate->zpos = STAGE0 + drm_plane_index(plane);
+		pstate->property_values[PLANE_PROP_ZPOS] =
+			STAGE0 + drm_plane_index(plane);
 
 	pstate->base.plane = plane;
 
@@ -662,13 +787,12 @@
 }
 
 /* initialize plane */
-struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe,
-		bool private_plane)
+struct drm_plane *sde_plane_init(struct drm_device *dev,
+		uint32_t pipe, bool private_plane)
 {
 	static const char tmp_name[] = "---";
 	struct drm_plane *plane = NULL;
 	struct sde_plane *psde;
-	struct sde_hw_ctl *sde_ctl;
 	struct msm_drm_private *priv;
 	struct sde_kms *kms;
 	struct sde_mdss_cfg *sde_cat;
@@ -712,7 +836,7 @@
 	psde->nformats = mdp_get_formats(psde->formats,
 		ARRAY_SIZE(psde->formats),
 		!(psde->features & BIT(SDE_SSPP_CSC)) ||
-		!(psde->features & SDE_PLANE_FEATURE_SCALER));
+		!(psde->features & SDE_SSPP_SCALER));
 
 	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
@@ -723,7 +847,7 @@
 
 	drm_plane_helper_add(plane, &sde_plane_helper_funcs);
 
-	sde_plane_install_properties(plane, &plane->base);
+	_sde_plane_install_properties(plane, &plane->base);
 
 	psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, sde_cat);
 	if (IS_ERR(psde->pipe_hw)) {
@@ -732,15 +856,6 @@
 		goto fail;
 	}
 
-	/* cache flush mask for later */
-	sde_ctl = sde_hw_ctl_init(CTL_0, kms->mmio, sde_cat);
-	if (!IS_ERR(sde_ctl)) {
-		if (sde_ctl->ops.get_bitmask_sspp)
-			sde_ctl->ops.get_bitmask_sspp(sde_ctl,
-					&psde->flush_mask, pipe);
-		sde_hw_ctl_destroy(sde_ctl);
-	}
-
 	pr_err("%s: Successfully created plane\n", __func__);
 	return plane;