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_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;