[RFC PATCH v2 16/20] drm/amd/display: add support to post-blend CTM colorop

Melissa Wen <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx,org.freedesktop.lists.dri-devel
Message-ID <[email protected]>
Initialize the AMD post-blend color pipeline with CTM as the first color
operation in the AMD post-blend color pipeline. AMD post-blend color
pipeline for DCN3 is described in `DCN 3.0 family color caps and
mapping` of the kernel doc.

Link: https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/display-manager.html#dc-color-capabilities-between-dcn-generations
Signed-off-by: Melissa Wen <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  3 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 81 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 38 +++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h |  2 +
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    | 38 +++++++++
 5 files changed, 162 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 74f700fbeb6f..1c890ded8f9b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1100,6 +1100,9 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state);
 int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc);
 int amdgpu_dm_check_crtc_color_mgmt(struct dm_crtc_state *crtc,
 				    bool check_only);
+int amdgpu_dm_crtc_set_colorop_properties(struct drm_crtc_state *crtc_state,
+					  struct dc_stream_state *dc_stream_state,
+					  bool check_only);
 int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 				      struct drm_plane_state *plane_state,
 				      struct dc_plane_state *dc_plane_state);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 54b3c163a36c..20996af68f04 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1176,6 +1176,87 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state)
 	return 0;
 }
 
+static int
+__set_dm_crtc_colorop_3x4_matrix(struct drm_crtc_state *crtc_state,
+				 struct dc_stream_state *dc_stream_state,
+				 struct drm_colorop *colorop,
+				 bool check_only)
+{
+	struct drm_colorop_state *colorop_state = NULL;
+	struct drm_atomic_commit *state = crtc_state->state;
+	const struct drm_property_blob *blob;
+	struct drm_color_ctm_3x4 *ctm = NULL;
+
+	/* If CRTC COLOR_PIPELINE property == Bypass */
+	if (!colorop) {
+		if (!check_only) {
+			dc_stream_state->gamut_remap_matrix.enable_remap = false;
+			dc_stream_state->csc_color_matrix.enable_adjustment = false;
+		}
+		return 0;
+	}
+
+	colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
+
+	if (colorop_state && colorop->type == DRM_COLOROP_CTM_3X4) {
+		if (colorop_state->bypass) {
+			if (!check_only) {
+				dc_stream_state->gamut_remap_matrix.enable_remap = false;
+				dc_stream_state->csc_color_matrix.enable_adjustment = false;
+			}
+		} else {
+			drm_dbg(state->dev, "3x4 matrix colorop with ID: %d\n", colorop->base.id);
+			blob = colorop_state->data;
+			if (blob->length != sizeof(struct drm_color_ctm_3x4)) {
+				drm_warn(state->dev, "blob->length (%zu) isn't equal to drm_color_ctm_3x4 (%zu)\n",
+					 blob->length, sizeof(struct drm_color_ctm_3x4));
+				return -EINVAL;
+			}
+			if (!check_only) {
+				ctm = (struct drm_color_ctm_3x4 *) blob->data;
+				__drm_ctm_3x4_to_dc_matrix(ctm, dc_stream_state->gamut_remap_matrix.matrix);
+				dc_stream_state->gamut_remap_matrix.enable_remap = true;
+				dc_stream_state->csc_color_matrix.enable_adjustment = false;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * amdgpu_dm_crtc_set_colorop_properties: Set colorop props if programmable by DC.
+ * @crtc_state: DRM crtc state
+ * @dc_stream_state: AMDGPU DC stream state
+ * @check_only: only check color state without update dc stream
+ *
+ * This function verifies post-blend CTM and LUT sizes: if there is enough space, and for
+ * output transfer function, if its parameters can be calculated by AMD
+ * color module. The main difference with CRTC color mgmt properties is that
+ * post-blend degamma is not part of the color pipeline since it's actually
+ * supported pre-blend only.
+ *
+ * If it's not an atomic check, DC resources are checked and updated
+ * accordingly.
+ *
+ * Returns:
+ * 0 on success. Error code if validation fails.
+ */
+
+int
+amdgpu_dm_crtc_set_colorop_properties(struct drm_crtc_state *crtc_state,
+				      struct dc_stream_state *dc_stream_state,
+				      bool check_only)
+{
+	struct drm_colorop *colorop = crtc_state->color_pipeline;
+	int ret;
+
+	/* 3x4 matrix */
+	ret = __set_dm_crtc_colorop_3x4_matrix(crtc_state, dc_stream_state, colorop, check_only);
+
+	return ret;
+}
+
 /**
  * amdgpu_dm_check_crtc_color_mgmt: Check if DRM color props are programmable by DC.
  * @crtc: amdgpu_dm crtc state
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 1c3e7ccb9eda..0abe8ab9184b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -252,3 +252,41 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	return ret;
 }
+
+int amdgpu_dm_initialize_crtc_default_pipeline(struct drm_crtc *crtc,
+					       struct drm_prop_enum_list *list)
+{
+	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
+	struct drm_device *dev = crtc->dev;
+	int ret;
+	int i = 0;
+
+	memset(ops, 0, sizeof(ops));
+
+	/* 3x4 matrix */
+	ops[i] = kzalloc_obj(struct drm_colorop);
+	if (!ops[i]) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_crtc_colorop_ctm_3x4_init(dev, ops[i], crtc, NULL,
+					    DRM_COLOROP_FLAG_ALLOW_BYPASS);
+	if (ret)
+		goto cleanup;
+
+	list->type = ops[i]->base.id;
+
+	i++;
+
+	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
+
+	return 0;
+cleanup:
+	if (ret == -ENOMEM)
+		drm_err(crtc->dev, "KMS: Failed to allocate colorop\n");
+
+	drm_colorop_pipeline_destroy(dev);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
index 7b71d3144391..85c21669bf78 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
@@ -34,4 +34,6 @@ extern const u64 amdgpu_dm_supported_fm;
 
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);
 
+int amdgpu_dm_initialize_crtc_default_pipeline(struct drm_crtc *crtc, struct drm_prop_enum_list *list);
+
 #endif /* __AMDGPU_DM_COLOROP_H__*/
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 3dcedaa67ed8..6226c9ba5fce 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -32,6 +32,7 @@
 #include "amdgpu_dm_replay.h"
 #include "amdgpu_dm_crtc.h"
 #include "amdgpu_dm_plane.h"
+#include "amdgpu_dm_colorop.h"
 #include "amdgpu_dm_trace.h"
 #include "amdgpu_dm_debugfs.h"
 #include "modules/inc/mod_power.h"
@@ -518,6 +519,43 @@ amdgpu_dm_atomic_crtc_get_property(struct drm_crtc *crtc,
 
 	return 0;
 }
+#else
+
+#define MAX_CRTC_COLOR_PIPELINES 5
+
+static int
+dm_crtc_init_colorops(struct drm_crtc *crtc)
+{
+	struct drm_prop_enum_list pipelines[MAX_CRTC_COLOR_PIPELINES] = {};
+	struct drm_device *dev = crtc->dev;
+	struct amdgpu_device *adev = drm_to_adev(dev);
+	struct dc *dc = adev->dm.dc;
+	int len = 0;
+	int ret = 0;
+	int i;
+
+	/* initialize pipeline */
+	if (dc->ctx->dce_version >= DCN_VERSION_3_0) {
+		ret = amdgpu_dm_initialize_crtc_default_pipeline(crtc, &pipelines[len]);
+		if (ret) {
+			drm_err(dev, "Failed to create color pipeline for CRTC %d: %d\n",
+				crtc->base.id, ret);
+			goto out;
+		}
+		len++;
+
+		/* Create COLOR_PIPELINE property and attach */
+		ret = drm_crtc_create_color_pipeline_property(crtc, pipelines, len);
+	}
+
+out:
+	for (i = 0; i < len; i++)
+		kfree(pipelines[i].name);
+
+	return ret;
+}
+
+
 #endif
 
 /* Implemented only the options currently available for the driver */
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.