drm/msm/sde: explicitly enumerate supported plane formats

Explicitly list supported formats rather than attempting to
infer what is supported based on h/w features. This makes
the determination of supported formats more reliable, and
also opens the way to account for different h/w blocks
supporting different sets of formats.

Change-Id: I39b223638c2c126d57eee5551a57c7b8fd7cb1f5
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 0f8a8e1..6841c2b 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -62,6 +62,7 @@
 
 	struct msm_property_info property_info;
 	struct msm_property_data property_data[PLANE_PROP_COUNT];
+	struct drm_property_blob *blob_sde_info;
 
 	/* debugfs related stuff */
 	struct dentry *debugfs_root;
@@ -1105,6 +1106,8 @@
 	static const struct drm_prop_enum_list e_src_config[] = {
 		{SDE_DRM_DEINTERLACE, "deinterlace"}
 	};
+	const struct sde_format_extended *format_list;
+	static struct sde_kms_info sde_info;
 	struct sde_plane *psde = to_sde_plane(plane);
 
 	DBG("");
@@ -1153,6 +1156,29 @@
 		msm_property_install_blob(&psde->property_info, "csc", 0,
 			PLANE_PROP_CSC);
 	}
+	format_list = psde->pipe_sblk->format_list;
+	if (format_list) {
+		/* assume single thread */
+		struct sde_kms_info *info = &sde_info;
+
+		msm_property_install_blob(&psde->property_info, "sde_info",
+				DRM_MODE_PROP_IMMUTABLE,
+				PLANE_PROP_SDE_INFO);
+		sde_kms_info_reset(info);
+		sde_kms_info_start(info, "pixel_formats");
+		while (format_list->fourcc_format) {
+			sde_kms_info_append_format(info,
+					format_list->fourcc_format,
+					format_list->modifier);
+			++format_list;
+		}
+		sde_kms_info_stop(info);
+		msm_property_set_blob(&psde->property_info,
+				&psde->blob_sde_info,
+				SDE_KMS_INFO_DATA(info),
+				SDE_KMS_INFO_DATALEN(info),
+				PLANE_PROP_SDE_INFO);
+	}
 }
 
 static int sde_plane_atomic_set_property(struct drm_plane *plane,
@@ -1231,6 +1257,8 @@
 
 		debugfs_remove_recursive(psde->debugfs_root);
 
+		if (psde->blob_sde_info)
+			drm_property_unreference_blob(psde->blob_sde_info);
 		msm_property_destroy(&psde->property_info);
 		mutex_destroy(&psde->lock);
 
@@ -1478,12 +1506,16 @@
 	/* cache features mask for later */
 	psde->features = psde->pipe_hw->cap->features;
 	psde->pipe_sblk = psde->pipe_hw->cap->sblk;
+	if (!psde->pipe_sblk) {
+		SDE_ERROR("invalid sblk on pipe %d\n", pipe);
+		goto clean_sspp;
+	}
 
 	/* add plane to DRM framework */
-	psde->nformats = sde_populate_formats(psde->formats,
-		ARRAY_SIZE(psde->formats),
-		!(psde->features & BIT(SDE_SSPP_CSC)) ||
-		!(psde->features & SDE_SSPP_SCALER));
+	psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
+			psde->formats,
+			0,
+			ARRAY_SIZE(psde->formats));
 
 	if (!psde->nformats) {
 		DRM_ERROR("[%u]No valid formats for plane\n", pipe);