drm/msm/sde: replace plane property/state handling with msm_prop

Remove plane-oriented property/state handling helper functions and
use the common 'msm_property' functions instead.

Change-Id: Iadf61500be020b432187bde75c681a0a1a0b000f
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 906428d..972d335 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -11,6 +11,9 @@
  */
 #include <linux/debugfs.h>
 #include <uapi/drm/sde_drm.h>
+
+#include "msm_prop.h"
+
 #include "sde_kms.h"
 #include "sde_fence.h"
 #include "sde_formats.h"
@@ -28,8 +31,6 @@
 
 #define SDE_NAME_SIZE  12
 
-#define SDE_STATE_CACHE_SIZE	2
-
 struct sde_plane {
 	struct drm_plane base;
 
@@ -55,12 +56,8 @@
 
 	char pipe_name[SDE_NAME_SIZE];
 
-	/* cache property default values (for reset) */
-	uint64_t property_defaults[PLANE_PROP_COUNT];
-
-	/* cache for unused plane state structures */
-	struct sde_plane_state *state_cache[SDE_STATE_CACHE_SIZE];
-	int state_cache_size;
+	struct msm_property_info property_info;
+	struct msm_property_data property_data[PLANE_PROP_COUNT];
 
 	/* debugfs related stuff */
 	struct dentry *debugfs_root;
@@ -318,29 +315,6 @@
 	}
 }
 
-static void *_sde_plane_get_blob(struct sde_plane_state *pstate,
-		enum msm_mdp_plane_property property, size_t *byte_len)
-{
-	struct drm_property_blob *blob;
-	size_t len = 0;
-	void *ret = 0;
-
-	if (!pstate || (property >= PLANE_PROP_BLOBCOUNT)) {
-		DRM_ERROR("Invalid argument(s)\n");
-	} else {
-		blob = pstate->property_blobs[property];
-		if (blob) {
-			len = blob->length;
-			ret = &blob->data;
-		}
-	}
-
-	if (byte_len)
-		*byte_len = len;
-
-	return ret;
-}
-
 /**
  * _sde_plane_verify_blob - verify incoming blob is big enough to contain
  *                          sub-structure
@@ -418,11 +392,18 @@
 	size_t csc_size = 0;
 	bool user_blob = false;
 
-	if (!psde->pipe_hw->ops.setup_csc)
+	if (!psde || !pstate || !fmt) {
+		DRM_ERROR("Invalid arguments\n");
+		return;
+	}
+	if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_csc)
 		return;
 
 	/* check for user space override */
-	csc = _sde_plane_get_blob(pstate, PLANE_PROP_CSC, &csc_size);
+	csc = msm_property_get_blob(&psde->property_info,
+			pstate->property_blobs,
+			&csc_size,
+			PLANE_PROP_CSC);
 	if (csc) {
 		struct sde_csc_cfg cfg;
 		int i;
@@ -496,7 +477,11 @@
 	memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
 
 	/* get scaler config from user space */
-	sc_u = _sde_plane_get_blob(pstate, PLANE_PROP_SCALER, &sc_u_size);
+	/* get scaler config from user space */
+	sc_u = msm_property_get_blob(&psde->property_info,
+			pstate->property_blobs,
+			&sc_u_size,
+			PLANE_PROP_SCALER);
 	if (sc_u) {
 		switch (sc_u->version) {
 		case SDE_DRM_SCALER_V1:
@@ -878,7 +863,10 @@
 	/* get decimation config from user space */
 	deci_w = 0;
 	deci_h = 0;
-	sc_u = _sde_plane_get_blob(pstate, PLANE_PROP_SCALER, &sc_u_size);
+	sc_u = msm_property_get_blob(&psde->property_info,
+			pstate->property_blobs,
+			&sc_u_size,
+			PLANE_PROP_SCALER);
 	if (sc_u) {
 		switch (sc_u->version) {
 		case SDE_DRM_SCALER_V1:
@@ -1071,174 +1059,8 @@
 	}
 }
 
-static inline struct drm_property **_sde_plane_get_property_entry(
-		struct drm_device *dev, enum msm_mdp_plane_property property)
-{
-	struct msm_drm_private *priv;
-
-	if (!dev  || !dev->dev_private || (property >= PLANE_PROP_COUNT))
-		return NULL;
-
-	priv = dev->dev_private;
-
-	return &(priv->plane_property[property]);
-}
-
-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,
-		enum msm_mdp_plane_property property)
-{
-	struct drm_property **prop;
-
-	prop = _sde_plane_get_property_entry(dev, property);
-	if (plane && name && prop) {
-		/* only create the property once */
-		if (*prop == 0) {
-			*prop = drm_property_create_range(dev,
-					0 /* flags */, name, min, max);
-			if (*prop == 0)
-				DRM_ERROR("Create %s property failed\n", name);
-		}
-
-		/* save init value for later */
-		to_sde_plane(plane)->property_defaults[property] = init;
-
-		/* always attach property, if created */
-		if (*prop)
-			drm_object_attach_property(&plane->base, *prop, init);
-	}
-}
-
-static void _sde_plane_install_rotation_property(struct drm_plane *plane,
-		struct drm_device *dev, enum msm_mdp_plane_property property)
-{
-	struct sde_plane *psde;
-	struct drm_property **prop;
-
-	prop = _sde_plane_get_property_entry(dev, property);
-	if (plane && prop) {
-		/* only create the property once */
-		if (*prop == 0) {
-			*prop = drm_mode_create_rotation_property(dev,
-					BIT(DRM_REFLECT_X) |
-					BIT(DRM_REFLECT_Y));
-			if (*prop == 0)
-				DRM_ERROR("Create rotation property failed\n");
-		}
-
-		/* save init value for later */
-		psde = to_sde_plane(plane);
-		psde->property_defaults[property] = 0;
-
-		/* always attach property, if created */
-		if (*prop)
-			drm_object_attach_property(&plane->base, *prop,
-					psde->property_defaults[property]);
-	}
-}
-
-static void _sde_plane_install_enum_property(struct drm_plane *plane,
-		struct drm_device *dev, const char *name, int is_bitmask,
-		const struct drm_prop_enum_list *values, int num_values,
-		enum msm_mdp_plane_property property)
-{
-	struct sde_plane *psde;
-	struct drm_property **prop;
-
-	prop = _sde_plane_get_property_entry(dev, property);
-	if (plane && name && prop && values && num_values) {
-		/* only create the property once */
-		if (*prop == 0) {
-			/* 'bitmask' is a special type of 'enum' */
-			if (is_bitmask)
-				*prop = drm_property_create_bitmask(dev,
-						DRM_MODE_PROP_BITMASK, name,
-						values, num_values, -1);
-			else
-				*prop = drm_property_create_enum(dev,
-						DRM_MODE_PROP_ENUM, name,
-						values, num_values);
-			if (*prop == 0)
-				DRM_ERROR("Create %s property failed\n", name);
-		}
-
-		/* save init value for later */
-		psde = to_sde_plane(plane);
-		psde->property_defaults[property] = 0;
-
-		/* always attach property, if created */
-		if (*prop)
-			drm_object_attach_property(&plane->base, *prop,
-					psde->property_defaults[property]);
-	}
-}
-
-static void _sde_plane_install_blob_property(struct drm_plane *plane,
-		struct drm_device *dev, const char *name,
-		enum msm_mdp_plane_property property)
-{
-	struct sde_plane *psde;
-	struct drm_property **prop;
-
-	prop = _sde_plane_get_property_entry(dev, property);
-	if (plane && name && prop && (property < PLANE_PROP_BLOBCOUNT)) {
-		/* only create the property once */
-		if (*prop == 0) {
-			/* use 'create' for blob property place holder */
-			*prop = drm_property_create(dev,
-					DRM_MODE_PROP_BLOB, name, 0);
-			if (*prop == 0)
-				DRM_ERROR("Create %s property failed\n", name);
-		}
-
-		/* save init value for later */
-		psde = to_sde_plane(plane);
-		psde->property_defaults[property] = 0;
-
-		/* always attach property, if created */
-		if (*prop)
-			drm_object_attach_property(&plane->base, *prop,
-					psde->property_defaults[property]);
-	}
-}
-
-static int _sde_plane_get_property_index(struct drm_plane *plane,
-		struct drm_property *property)
-{
-	struct drm_property **prop_array;
-	int idx = PLANE_PROP_COUNT;
-
-	if (!plane) {
-		DRM_ERROR("Invalid plane\n");
-	} else if (!plane->dev || !plane->dev->dev_private) {
-		/* don't access dev_private if !dev */
-		DRM_ERROR("Invalid device\n");
-	} else if (!property) {
-		DRM_ERROR("Incoming property is NULL\n");
-	} else {
-		prop_array = _sde_plane_get_property_entry(plane->dev, 0);
-		if (!prop_array)
-			/* should never hit this */
-			DRM_ERROR("Invalid property array\n");
-
-		/* linear search is okay */
-		for (idx = 0; idx < PLANE_PROP_COUNT; ++idx) {
-			if (prop_array[idx] == property)
-				break;
-		}
-
-		if (idx == PLANE_PROP_COUNT)
-			DRM_ERROR("Invalid property pointer\n");
-	}
-
-	return idx;
-}
-
 /* helper to install properties which are common to planes and crtcs */
-static void _sde_plane_install_properties(struct drm_plane *plane,
-		struct drm_mode_object *obj,
-		struct sde_mdss_cfg *catalog)
+static void _sde_plane_install_properties(struct drm_plane *plane)
 {
 	static const struct drm_prop_enum_list e_blend_op[] = {
 		{SDE_DRM_BLEND_OP_NOT_DEFINED,    "not_defined"},
@@ -1250,54 +1072,56 @@
 		{SDE_DRM_DEINTERLACE, "deinterlace"}
 	};
 	struct sde_plane *psde = to_sde_plane(plane);
-	struct drm_device *dev = plane->dev;
 
 	DBG("");
 
-	if (!psde || !psde->pipe_hw || !psde->pipe_sblk || !catalog) {
-		DRM_ERROR("Catalog or h/w driver definition error\n");
+	if (!plane || !psde || !psde->pipe_hw || !psde->pipe_sblk) {
+		DRM_ERROR("Invalid argument(s)\n");
 		return;
 	}
 
 	/* range properties */
-	_sde_plane_install_range_property(plane, dev, "zpos", 0, 255,
+	msm_property_install_range(&psde->property_info, "zpos", 0, 255,
 			plane->type == DRM_PLANE_TYPE_PRIMARY ?
 				STAGE_BASE : STAGE0 + drm_plane_index(plane),
 			PLANE_PROP_ZPOS);
 
-	_sde_plane_install_range_property(plane, dev, "alpha", 0, 255, 255,
+	msm_property_install_range(&psde->property_info, "alpha", 0, 255, 255,
 			PLANE_PROP_ALPHA);
 
 	if (psde->pipe_hw->ops.setup_solidfill)
-		_sde_plane_install_range_property(plane, dev, "color_fill",
+		msm_property_install_range(&psde->property_info, "color_fill",
 				0, 0xFFFFFFFF, 0,
 				PLANE_PROP_COLOR_FILL);
 
-	_sde_plane_install_range_property(plane, dev, "sync_fence", 0, ~0, ~0,
-			PLANE_PROP_SYNC_FENCE);
+	msm_property_install_range(&psde->property_info, "sync_fence",
+			0, ~0, ~0, PLANE_PROP_SYNC_FENCE);
 
-	_sde_plane_install_range_property(plane, dev, "sync_fence_timeout",
+	msm_property_install_range(&psde->property_info, "sync_fence_timeout",
 			0, ~0, 10000,
 			PLANE_PROP_SYNC_FENCE_TIMEOUT);
 
 	/* standard properties */
-	_sde_plane_install_rotation_property(plane, dev, PLANE_PROP_ROTATION);
+	msm_property_install_rotation(&psde->property_info,
+			BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y),
+			PLANE_PROP_ROTATION);
 
 	/* enum/bitmask properties */
-	_sde_plane_install_enum_property(plane, dev, "blend_op", 0,
+	msm_property_install_enum(&psde->property_info, "blend_op", 0,
 			e_blend_op, ARRAY_SIZE(e_blend_op),
 			PLANE_PROP_BLEND_OP);
-	_sde_plane_install_enum_property(plane, dev, "src_config", 1,
+	msm_property_install_enum(&psde->property_info, "src_config", 1,
 			e_src_config, ARRAY_SIZE(e_src_config),
 			PLANE_PROP_SRC_CONFIG);
 
 	/* blob properties */
 	if (psde->features & SDE_SSPP_SCALER)
-		_sde_plane_install_blob_property(plane, dev, "scaler",
+		msm_property_install_blob(&psde->property_info, "scaler", 0,
 			PLANE_PROP_SCALER);
-	if (psde->features & BIT(SDE_SSPP_CSC))
-		_sde_plane_install_blob_property(plane, dev, "csc",
+	if (psde->features & BIT(SDE_SSPP_CSC)) {
+		msm_property_install_blob(&psde->property_info, "csc", 0,
 			PLANE_PROP_CSC);
+	}
 }
 
 static int sde_plane_atomic_set_property(struct drm_plane *plane,
@@ -1306,47 +1130,27 @@
 {
 	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
-	struct drm_property_blob *blob, **pr_blob;
 	int idx, ret = -EINVAL;
 
-	idx = _sde_plane_get_property_index(plane, property);
-	if (!state) {
+	DBG("");
+
+	if (!plane) {
+		DRM_ERROR("Invalid plane\n");
+	} else if (!state) {
 		DRM_ERROR("Invalid state\n");
-	} else if (idx >= PLANE_PROP_COUNT) {
-		DRM_ERROR("Invalid property\n");
 	} else {
 		psde = to_sde_plane(plane);
 		pstate = to_sde_plane_state(state);
-
-		DBG("%s: pipe %d, prop %s, val %d", psde->pipe_name,
-				sde_plane_pipe(plane),
-				property->name, (int)val);
-
-		/* extra handling for incoming properties */
-		if ((property->flags & DRM_MODE_PROP_BLOB) &&
-			(idx < PLANE_PROP_BLOBCOUNT)) {
-			/* DRM lookup also takes a reference */
-			blob = drm_property_lookup_blob(plane->dev,
-				(uint32_t)val);
-			if (!blob) {
-				DRM_ERROR("Blob not found\n");
-				val = 0;
-			} else {
-				DBG("Blob %u saved", blob->base.id);
-				val = blob->base.id;
-
-				/* save blobs for later */
-				pr_blob = &pstate->property_blobs[idx];
-				/* need to clear previous reference */
-				if (*pr_blob)
-					drm_property_unreference_blob(*pr_blob);
-				*pr_blob = blob;
-			}
-		} else if (idx == PLANE_PROP_SYNC_FENCE) {
-			_sde_plane_update_sync_fence(plane, pstate, val);
+		ret = msm_property_atomic_set(&psde->property_info,
+				pstate->property_values, pstate->property_blobs,
+				property, val);
+		if (!ret) {
+			idx = msm_property_index(&psde->property_info,
+					property);
+			if (idx == PLANE_PROP_SYNC_FENCE)
+				_sde_plane_update_sync_fence(plane,
+						pstate, val);
 		}
-		pstate->property_values[idx] = val;
-		ret = 0;
 	}
 
 	return ret;
@@ -1357,9 +1161,6 @@
 {
 	DBG("");
 
-	if (!plane)
-		return -EINVAL;
-
 	return sde_plane_atomic_set_property(plane,
 			plane->state, property, val);
 }
@@ -1368,67 +1169,27 @@
 		const struct drm_plane_state *state,
 		struct drm_property *property, uint64_t *val)
 {
+	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
-	int idx, ret = -EINVAL;
+	int ret = -EINVAL;
 
-	idx = _sde_plane_get_property_index(plane, property);
-	if (!state) {
+	DBG("");
+
+	if (!plane) {
+		DRM_ERROR("Invalid plane\n");
+	} else if (!state) {
 		DRM_ERROR("Invalid state\n");
-	} else if (!val) {
-		DRM_ERROR("Value pointer is NULL\n");
-	} else if (idx < PLANE_PROP_COUNT) {
+	} else {
+		psde = to_sde_plane(plane);
 		pstate = to_sde_plane_state(state);
-
-		*val = pstate->property_values[idx];
-		DBG("%d 0x%llX", idx, *val);
-		ret = 0;
+		ret = msm_property_atomic_get(&psde->property_info,
+				pstate->property_values, pstate->property_blobs,
+				property, val);
 	}
 
 	return ret;
 }
 
-static struct sde_plane_state *sde_plane_alloc_state(struct drm_plane *plane)
-{
-	struct sde_plane *psde;
-	struct sde_plane_state *pstate;
-
-	if (!plane)
-		return NULL;
-
-	psde = to_sde_plane(plane);
-	pstate = NULL;
-
-	mutex_lock(&psde->lock);
-	if (psde->state_cache_size)
-		pstate = psde->state_cache[--(psde->state_cache_size)];
-	mutex_unlock(&psde->lock);
-
-	if (!pstate)
-		pstate = kmalloc(sizeof(struct sde_plane_state), GFP_KERNEL);
-
-	return pstate;
-}
-
-static void sde_plane_free_state(struct drm_plane *plane,
-		struct sde_plane_state *pstate)
-{
-	struct sde_plane *psde;
-
-	if (!plane || !pstate)
-		return;
-
-	psde = to_sde_plane(plane);
-
-	mutex_lock(&psde->lock);
-	if (psde->state_cache_size < SDE_STATE_CACHE_SIZE) {
-		psde->state_cache[(psde->state_cache_size)++] = pstate;
-		mutex_unlock(&psde->lock);
-	} else {
-		mutex_unlock(&psde->lock);
-		kfree(pstate);
-	}
-}
-
 static void sde_plane_destroy(struct drm_plane *plane)
 {
 	struct sde_plane *psde;
@@ -1440,6 +1201,7 @@
 
 		debugfs_remove_recursive(psde->debugfs_root);
 
+		msm_property_destroy(&psde->property_info);
 		mutex_destroy(&psde->lock);
 
 		drm_plane_helper_disable(plane);
@@ -1450,10 +1212,6 @@
 		if (psde->pipe_hw)
 			sde_hw_sspp_destroy(psde->pipe_hw);
 
-		/* free state cache */
-		while (psde->state_cache_size > 0)
-			kfree(psde->state_cache[--(psde->state_cache_size)]);
-
 		kfree(psde);
 	}
 }
@@ -1461,14 +1219,15 @@
 static void sde_plane_destroy_state(struct drm_plane *plane,
 		struct drm_plane_state *state)
 {
+	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
-	int i;
 
 	if (!plane || !state) {
 		DRM_ERROR("Invalid plane/state\n");
 		return;
 	}
 
+	psde = to_sde_plane(plane);
 	pstate = to_sde_plane_state(state);
 
 	DBG("");
@@ -1481,33 +1240,32 @@
 	if (pstate->sync_fence)
 		sde_sync_put(pstate->sync_fence);
 
-	/* 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]);
-	sde_plane_free_state(plane, pstate);
+	/* destroy value helper */
+	msm_property_destroy_state(&psde->property_info, pstate,
+			pstate->property_values, pstate->property_blobs);
 }
 
 static struct drm_plane_state *
 sde_plane_duplicate_state(struct drm_plane *plane)
 {
+	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
 	struct sde_plane_state *old_state;
-	int i;
 
 	if (!plane || !plane->state)
 		return NULL;
 
 	old_state = to_sde_plane_state(plane->state);
-	pstate = sde_plane_alloc_state(plane);
-
-	DBG("");
-
+	psde = to_sde_plane(plane);
+	pstate = msm_property_alloc_state(&psde->property_info);
 	if (!pstate)
 		return NULL;
 
-	memcpy(pstate, old_state, sizeof(*pstate));
+	DBG("");
+
+	/* duplicate value helper */
+	msm_property_duplicate_state(&psde->property_info, old_state, pstate,
+			pstate->property_values, pstate->property_blobs);
 
 	/* add ref count for frame buffer */
 	if (pstate->base.fb)
@@ -1520,12 +1278,6 @@
 				property_values[PLANE_PROP_SYNC_FENCE]);
 	}
 
-	/* 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;
 
@@ -1536,7 +1288,6 @@
 {
 	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
-	int i;
 
 	if (!plane) {
 		DRM_ERROR("Invalid plane\n");
@@ -1547,21 +1298,18 @@
 	DBG("%s", psde->pipe_name);
 
 	/* remove previous state, if present */
-	if (plane->state)
+	if (plane->state) {
 		sde_plane_destroy_state(plane, plane->state);
-	plane->state = 0;
-
-	pstate = sde_plane_alloc_state(plane);
-	if (!pstate) {
-		DRM_ERROR("Failed to (re)allocate plane state\n");
-		return;
+		plane->state = 0;
 	}
 
-	memset(pstate, 0, sizeof(*pstate));
+	pstate = msm_property_alloc_state(&psde->property_info);
+	if (!pstate)
+		return;
 
-	/* assign default property values */
-	for (i = 0; i < PLANE_PROP_COUNT; ++i)
-		pstate->property_values[i] = psde->property_defaults[i];
+	/* reset value helper */
+	msm_property_reset_state(&psde->property_info, pstate,
+			pstate->property_values, pstate->property_blobs);
 
 	pstate->base.plane = plane;
 
@@ -1727,7 +1475,12 @@
 	/* success! finalize initialization */
 	drm_plane_helper_add(plane, &sde_plane_helper_funcs);
 
-	_sde_plane_install_properties(plane, &plane->base, kms->catalog);
+	msm_property_init(&psde->property_info, &plane->base, dev,
+			priv->plane_property, psde->property_data,
+			PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
+			sizeof(struct sde_plane_state));
+
+	_sde_plane_install_properties(plane);
 
 	/* save user friendly pipe name for later */
 	snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);