dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt
@ 2023-10-05 17:14 Melissa Wen
  2023-10-05 17:14 ` [PATCH v4 01/32] drm/drm_mode_object: increase max objects to accommodate new color props Melissa Wen
                   ` (32 more replies)
  0 siblings, 33 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:14 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, airlied, brian.starkey,
	christian.koenig, daniel, liviu.dudau, maarten.lankhorst,
	mripard, tzimmermann, Xinhui.Pan
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Hello,

Just another iteration for AMD driver-specific color properties.
Basically, addressing comments from the previous version.

Recap: this series extends the current KMS color management API with AMD
driver-specific properties to enhance the color management support on
AMD Steam Deck. The key additions to the color pipeline include:

- plane degamma LUT and pre-defined TF;
- plane HDR multiplier;
- plane CTM 3x4;
- plane shaper LUT and pre-defined TF;
- plane 3D LUT;
- plane blend LUT and pre-defined TF;
- CRTC gamma pre-defined TF;

You can find the AMD HW color capabilities documented here:
https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/display-manager.html#color-management-properties

The userspace case is Gamescope[1], the compositor for SteamOS.
Gamescope has already adopted AMD driver-specific properties to
implement comprehensive color management support, including gamut
mapping, HDR rendering, SDR on HDR, HDR on SDR. Using these features in
the SteamOS 3.5[2] users can expect a significantly enhanced visual
experience. 

You can find a brief overview of the Steam Deck color pipeline here:
https://github.com/ValveSoftware/gamescope/blob/master/src/docs/Steam%20Deck%20Display%20Pipeline.png

Changes from:

[RFC] https://lore.kernel.org/dri-devel/20230423141051.702990-1-mwen@igalia.com
- Remove KConfig and guard properties with `AMD_PRIVATE_COLOR`;
- Remove properties for post-blending/CRTC shaper TF+LUT and 3D LUT;
- Use color caps to improve the support of pre-defined curve;

[v1] https://lore.kernel.org/dri-devel/20230523221520.3115570-1-mwen@igalia.com
- Replace DRM_ by AMDGPU_ prefix for transfer function (TF) enum; 
- Explicitly define EOTFs and inverse EOTFs and set props accordingly;
- Document pre-defined transfer functions;
- Remove HLG transfer function from supported TFs;
- Remove misleading comments;
- Remove post-blending shaper TF+LUT and 3D LUT support;
- Move driver-specific property operations from amdgpu_display.c to
  amdgpu_dm_color.c;
- Reset planes if any color props change;
- Add plane CTM 3x4 support;
- Removed two DC fixes already applied upstream;

[v2] https://lore.kernel.org/dri-devel/20230810160314.48225-1-mwen@igalia.com
- Many documentation fixes: BT.709 OETF, description of sRGB and pure
  power functions, TF+1D LUT behavior;
- Rename CTM2 to CTM 3x4 and fix misleading comment about DC gamut remap;
- Squash `Linear` and `Unity` TF in `Identity`;
- Remove the `MPC gamut remap` patch already applied upstream[3];
- Remove outdated delta segmentation fix;
- Nits/small fixes;

[v3] https://lore.kernel.org/amd-gfx/20230925194932.1329483-1-mwen@igalia.com
- Add table to describe value range in linear and non-linear forms
- Comment the PQ TF need after HDR multiplier
- Advertise the 3D LUT size as the size of a single-dimension (read-only)
- remove function to check expected size from 3DLUT caps
- cleanup comments

It's worth noting that driver-specific properties are guarded by
`AMD_PRIVATE_COLOR`. So, finally, this is the color management API when
driver-specific properties are enabled:

+----------------------+
|   PLANE              |
|                      |
|  +----------------+  |
|  | AMD Degamma    |  |
|  |                |  |
|  | EOTF | 1D LUT  |  |
|  +--------+-------+  |
|           |          |
|  +--------v-------+  |
|  |    AMD HDR     |  |
|  |    Multiply    |  |
|  +--------+-------+  |
|           |          |
|  +--------v-------+  |
|  |  AMD CTM (3x4) |  |
|  +--------+-------+  |
|           |          |
|  +--------v-------+  |
|  | AMD Shaper     |  |
|  |                |  |
|  | inv_EOTF |     |  |
|  | Custom 1D LUT  |  |
|  +--------+-------+  |
|           |          |
|  +--------v-------+  |
|  |   AMD 3D LUT   |  |
|  |   17^3/12-bit  |  |
|  +--------+-------+  |
|           |          |
|  +--------v-------+  |
|  | AMD Blend      |  |
|  |                |  |
|  | EOTF | 1D LUT  |  |
|  +--------+-------+  |
|           |          |
++----------v---------++
||      Blending      ||
++----------+---------++
|    CRTC   |          |
|           |          |
|   +-------v-------+  |
|   | DRM Degamma   |  |
|   |               |  |
|   | Custom 1D LUT |  |
|   +-------+-------+  |
|           |          |
|   +-------v-------+  |
|   | DRM CTM (3x3) |  |
|   +-------+-------+  |
|           |          |
|   +-------v-------+  |
|   | DRM Gamma     |  |
|   |               |  |
|   | Custom 1D LUT |  |
|   +---------------+  |
|   | *AMD Gamma    |  |
|   |   inv_EOTF    |  |
|   +---------------+  |
|                      |
+----------------------+

Please, let us know your thoughts.

Best Regards,

Melissa Wen

[1] https://github.com/ValveSoftware/gamescope
[2] https://store.steampowered.com/news/app/1675200/view/3686804163591367815
[3] https://lore.kernel.org/dri-devel/20230721132431.692158-1-mwen@igalia.com

Joshua Ashton (14):
  drm/amd/display: add plane degamma TF driver-specific property
  drm/amd/display: add plane HDR multiplier driver-specific property
  drm/amd/display: add plane blend LUT and TF driver-specific properties
  drm/amd/display: add CRTC gamma TF support
  drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func
  drm/amd/display: mark plane as needing reset if color props change
  drm/amd/display: add plane degamma TF and LUT support
  drm/amd/display: add dc_fixpt_from_s3132 helper
  drm/amd/display: add HDR multiplier support
  drm/amd/display: handle empty LUTs in __set_input_tf
  drm/amd/display: add plane blend LUT and TF support
  drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG
  drm/amd/display: copy 3D LUT settings from crtc state to stream_update
  drm/amd/display: Add 3x4 CTM support for plane CTM

Melissa Wen (18):
  drm/drm_mode_object: increase max objects to accommodate new color
    props
  drm/drm_property: make replace_property_blob_from_id a DRM helper
  drm/drm_plane: track color mgmt changes per plane
  drm/amd/display: add driver-specific property for plane degamma LUT
  drm/amd/display: explicitly define EOTF and inverse EOTF
  drm/amd/display: document AMDGPU pre-defined transfer functions
  drm/amd/display: add plane 3D LUT driver-specific properties
  drm/amd/display: add plane shaper LUT and TF driver-specific
    properties
  drm/amd/display: add CRTC gamma TF driver-specific property
  drm/amd/display: add comments to describe DM crtc color mgmt behavior
  drm/amd/display: encapsulate atomic regamma operation
  drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
  drm/amd/display: reject atomic commit if setting both plane and CRTC
    degamma
  drm/amd/display: add plane shaper LUT support
  drm/amd/display: add plane shaper TF support
  drm/amd/display: add plane 3D LUT support
  drm/amd/display: add plane CTM driver-specific property
  drm/amd/display: add plane CTM support

 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  90 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  34 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 108 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 821 ++++++++++++++++--
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |  72 ++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 224 ++++-
 .../gpu/drm/amd/display/include/fixed31_32.h  |  12 +
 drivers/gpu/drm/arm/malidp_crtc.c             |   2 +-
 drivers/gpu/drm/drm_atomic.c                  |   1 +
 drivers/gpu/drm/drm_atomic_state_helper.c     |   1 +
 drivers/gpu/drm/drm_atomic_uapi.c             |  43 +-
 drivers/gpu/drm/drm_property.c                |  49 ++
 include/drm/drm_mode_object.h                 |   2 +-
 include/drm/drm_plane.h                       |   7 +
 include/drm/drm_property.h                    |   6 +
 include/uapi/drm/drm_mode.h                   |   8 +
 16 files changed, 1371 insertions(+), 109 deletions(-)

-- 
2.40.1


^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH v4 01/32] drm/drm_mode_object: increase max objects to accommodate new color props
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
@ 2023-10-05 17:14 ` Melissa Wen
  2023-10-05 17:14 ` [PATCH v4 02/32] drm/drm_property: make replace_property_blob_from_id a DRM helper Melissa Wen
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:14 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, maarten.lankhorst, mripard, tzimmermann,
	airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

DRM_OBJECT_MAX_PROPERTY limits the number of properties to be attached
and we are increasing that value all time we add a new property (generic
or driver-specific).

In this series, we are adding 13 new KMS driver-specific properties for
AMD color manage:
- CRTC Gamma enumerated Transfer Function
- Plane: Degamma LUT+size+TF, HDR multiplier, shaper LUT+size+TF, 3D
  LUT+size, blend LUT+size+TF (12)

Therefore, just increase DRM_OBJECT_MAX_PROPERTY to a number (64) that
accomodates these new properties and gives some room for others,
avoiding change this number everytime we add a new KMS property.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 include/drm/drm_mode_object.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index 912f1e415685..08d7a7f0188f 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -60,7 +60,7 @@ struct drm_mode_object {
 	void (*free_cb)(struct kref *kref);
 };
 
-#define DRM_OBJECT_MAX_PROPERTY 24
+#define DRM_OBJECT_MAX_PROPERTY 64
 /**
  * struct drm_object_properties - property tracking for &drm_mode_object
  */
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 02/32] drm/drm_property: make replace_property_blob_from_id a DRM helper
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
  2023-10-05 17:14 ` [PATCH v4 01/32] drm/drm_mode_object: increase max objects to accommodate new color props Melissa Wen
@ 2023-10-05 17:14 ` Melissa Wen
  2023-10-05 17:14 ` [PATCH v4 03/32] drm/drm_plane: track color mgmt changes per plane Melissa Wen
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:14 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, liviu.dudau, brian.starkey, airlied,
	daniel, maarten.lankhorst, mripard, tzimmermann
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Place it in drm_property where drm_property_replace_blob and
drm_property_lookup_blob live. Then we can use the DRM helper for
driver-specific KMS properties too.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/arm/malidp_crtc.c |  2 +-
 drivers/gpu/drm/drm_atomic_uapi.c | 43 ++++-----------------------
 drivers/gpu/drm/drm_property.c    | 49 +++++++++++++++++++++++++++++++
 include/drm/drm_property.h        |  6 ++++
 4 files changed, 61 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c
index dc01c43f6193..d72c22dcf685 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -221,7 +221,7 @@ static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc,
 
 	/*
 	 * The size of the ctm is checked in
-	 * drm_atomic_replace_property_blob_from_id.
+	 * drm_property_replace_blob_from_id.
 	 */
 	ctm = (struct drm_color_ctm *)state->ctm->data;
 	for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) {
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index d867e7f9f2cd..a6a9ee5086dd 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -362,39 +362,6 @@ static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
 	return fence_ptr;
 }
 
-static int
-drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
-					 struct drm_property_blob **blob,
-					 uint64_t blob_id,
-					 ssize_t expected_size,
-					 ssize_t expected_elem_size,
-					 bool *replaced)
-{
-	struct drm_property_blob *new_blob = NULL;
-
-	if (blob_id != 0) {
-		new_blob = drm_property_lookup_blob(dev, blob_id);
-		if (new_blob == NULL)
-			return -EINVAL;
-
-		if (expected_size > 0 &&
-		    new_blob->length != expected_size) {
-			drm_property_blob_put(new_blob);
-			return -EINVAL;
-		}
-		if (expected_elem_size > 0 &&
-		    new_blob->length % expected_elem_size != 0) {
-			drm_property_blob_put(new_blob);
-			return -EINVAL;
-		}
-	}
-
-	*replaced |= drm_property_replace_blob(blob, new_blob);
-	drm_property_blob_put(new_blob);
-
-	return 0;
-}
-
 static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 		struct drm_crtc_state *state, struct drm_property *property,
 		uint64_t val)
@@ -415,7 +382,7 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 	} else if (property == config->prop_vrr_enabled) {
 		state->vrr_enabled = val;
 	} else if (property == config->degamma_lut_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
+		ret = drm_property_replace_blob_from_id(dev,
 					&state->degamma_lut,
 					val,
 					-1, sizeof(struct drm_color_lut),
@@ -423,7 +390,7 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 		state->color_mgmt_changed |= replaced;
 		return ret;
 	} else if (property == config->ctm_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
+		ret = drm_property_replace_blob_from_id(dev,
 					&state->ctm,
 					val,
 					sizeof(struct drm_color_ctm), -1,
@@ -431,7 +398,7 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 		state->color_mgmt_changed |= replaced;
 		return ret;
 	} else if (property == config->gamma_lut_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
+		ret = drm_property_replace_blob_from_id(dev,
 					&state->gamma_lut,
 					val,
 					-1, sizeof(struct drm_color_lut),
@@ -563,7 +530,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 	} else if (property == plane->color_range_property) {
 		state->color_range = val;
 	} else if (property == config->prop_fb_damage_clips) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
+		ret = drm_property_replace_blob_from_id(dev,
 					&state->fb_damage_clips,
 					val,
 					-1,
@@ -729,7 +696,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		if (state->link_status != DRM_LINK_STATUS_GOOD)
 			state->link_status = val;
 	} else if (property == config->hdr_output_metadata_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
+		ret = drm_property_replace_blob_from_id(dev,
 				&state->hdr_output_metadata,
 				val,
 				sizeof(struct hdr_output_metadata), -1,
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index dfec479830e4..f72ef6493340 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -751,6 +751,55 @@ bool drm_property_replace_blob(struct drm_property_blob **blob,
 }
 EXPORT_SYMBOL(drm_property_replace_blob);
 
+/**
+ * drm_property_replace_blob_from_id - replace a blob property taking a reference
+ * @dev: DRM device
+ * @blob: a pointer to the member blob to be replaced
+ * @blob_id: the id of the new blob to replace with
+ * @expected_size: expected size of the blob property
+ * @expected_elem_size: expected size of an element in the blob property
+ * @replaced: if the blob was in fact replaced
+ *
+ * Look up the new blob from id, take its reference, check expected sizes of
+ * the blob and its element and replace the old blob by the new one. Advertise
+ * if the replacement operation was successful.
+ *
+ * Return: true if the blob was in fact replaced. -EINVAL if the new blob was
+ * not found or sizes don't match.
+ */
+int drm_property_replace_blob_from_id(struct drm_device *dev,
+					 struct drm_property_blob **blob,
+					 uint64_t blob_id,
+					 ssize_t expected_size,
+					 ssize_t expected_elem_size,
+					 bool *replaced)
+{
+	struct drm_property_blob *new_blob = NULL;
+
+	if (blob_id != 0) {
+		new_blob = drm_property_lookup_blob(dev, blob_id);
+		if (new_blob == NULL)
+			return -EINVAL;
+
+		if (expected_size > 0 &&
+		    new_blob->length != expected_size) {
+			drm_property_blob_put(new_blob);
+			return -EINVAL;
+		}
+		if (expected_elem_size > 0 &&
+		    new_blob->length % expected_elem_size != 0) {
+			drm_property_blob_put(new_blob);
+			return -EINVAL;
+		}
+	}
+
+	*replaced |= drm_property_replace_blob(blob, new_blob);
+	drm_property_blob_put(new_blob);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_property_replace_blob_from_id);
+
 int drm_mode_getblob_ioctl(struct drm_device *dev,
 			   void *data, struct drm_file *file_priv)
 {
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
index 65bc9710a470..082f29156b3e 100644
--- a/include/drm/drm_property.h
+++ b/include/drm/drm_property.h
@@ -279,6 +279,12 @@ struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
 						   const void *data);
 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
 						   uint32_t id);
+int drm_property_replace_blob_from_id(struct drm_device *dev,
+				      struct drm_property_blob **blob,
+				      uint64_t blob_id,
+				      ssize_t expected_size,
+				      ssize_t expected_elem_size,
+				      bool *replaced);
 int drm_property_replace_global_blob(struct drm_device *dev,
 				     struct drm_property_blob **replace,
 				     size_t length,
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 03/32] drm/drm_plane: track color mgmt changes per plane
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
  2023-10-05 17:14 ` [PATCH v4 01/32] drm/drm_mode_object: increase max objects to accommodate new color props Melissa Wen
  2023-10-05 17:14 ` [PATCH v4 02/32] drm/drm_property: make replace_property_blob_from_id a DRM helper Melissa Wen
@ 2023-10-05 17:14 ` Melissa Wen
  2023-10-05 17:14 ` [PATCH v4 04/32] drm/amd/display: add driver-specific property for plane degamma LUT Melissa Wen
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:14 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, maarten.lankhorst, mripard, tzimmermann,
	airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

We will add color mgmt properties to DRM planes in the next patches and
we want to track when one of this properties change to define atomic
commit behaviors. Using a similar approach from CRTC color props, we set
a color_mgmt_changed boolean whenever a plane color prop changes.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/drm_atomic.c              | 1 +
 drivers/gpu/drm/drm_atomic_state_helper.c | 1 +
 include/drm/drm_plane.h                   | 7 +++++++
 3 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 2c454568a607..2925371d230d 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -724,6 +724,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
 		   drm_get_color_encoding_name(state->color_encoding));
 	drm_printf(p, "\tcolor-range=%s\n",
 		   drm_get_color_range_name(state->color_range));
+	drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
 
 	if (plane->funcs->atomic_print_state)
 		plane->funcs->atomic_print_state(p, state);
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 784e63d70a42..25bb0859fda7 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -338,6 +338,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
 	state->fence = NULL;
 	state->commit = NULL;
 	state->fb_damage_clips = NULL;
+	state->color_mgmt_changed = false;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
 
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 51291983ea44..52c3287da0da 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -237,6 +237,13 @@ struct drm_plane_state {
 
 	/** @state: backpointer to global drm_atomic_state */
 	struct drm_atomic_state *state;
+
+	/**
+	 * @color_mgmt_changed: Color management properties have changed. Used
+	 * by the atomic helpers and drivers to steer the atomic commit control
+	 * flow.
+	 */
+	bool color_mgmt_changed : 1;
 };
 
 static inline struct drm_rect
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 04/32] drm/amd/display: add driver-specific property for plane degamma LUT
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (2 preceding siblings ...)
  2023-10-05 17:14 ` [PATCH v4 03/32] drm/drm_plane: track color mgmt changes per plane Melissa Wen
@ 2023-10-05 17:14 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 05/32] drm/amd/display: add plane degamma TF driver-specific property Melissa Wen
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:14 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Hook up driver-specific atomic operations for managing AMD color
properties. Create AMD driver-specific color management properties
and attach them according to HW capabilities defined by `struct
dc_color_caps`.

First add plane degamma LUT properties that means user-blob and its
size. We will add more plane color properties in the next patches. In
addition, we define AMD_PRIVATE_COLOR to guard these driver-specific
plane properties.

Plane degamma can be used to linearize input space for arithmetical
operations that are more accurate when applied in linear color.

v2:
- update degamma LUT prop description
- move private color operations from amdgpu_display to amdgpu_dm_color

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Co-developed-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 11 +++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  5 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 11 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 24 ++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 81 +++++++++++++++++++
 5 files changed, 132 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index d8083972e393..2d00802b3265 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -343,6 +343,17 @@ struct amdgpu_mode_info {
 	int			disp_priority;
 	const struct amdgpu_display_funcs *funcs;
 	const enum drm_plane_type *plane_type;
+
+	/* Driver-private color mgmt props */
+
+	/* @plane_degamma_lut_property: Plane property to set a degamma LUT to
+	 * convert input space before blending.
+	 */
+	struct drm_property *plane_degamma_lut_property;
+	/* @plane_degamma_lut_size_property: Plane property to define the max
+	 * size of degamma LUT as supported by the driver (read-only).
+	 */
+	struct drm_property *plane_degamma_lut_size_property;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a59a11ae42db..7c55b1c0ac5c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4106,6 +4106,11 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
 		return r;
 	}
 
+#ifdef AMD_PRIVATE_COLOR
+	if (amdgpu_dm_create_color_properties(adev))
+		return -ENOMEM;
+#endif
+
 	r = amdgpu_dm_audio_init(adev);
 	if (r) {
 		dc_release_state(state->context);
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 b16613082bc3..0f565469b4b5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -727,6 +727,16 @@ extern const struct amdgpu_ip_block_version dm_ip_block;
 struct dm_plane_state {
 	struct drm_plane_state base;
 	struct dc_plane_state *dc_state;
+
+	/* Plane color mgmt */
+	/**
+	 * @degamma_lut:
+	 *
+	 * 1D LUT for mapping framebuffer/plane pixel data before sampling or
+	 * blending operations. It's usually applied to linearize input space.
+	 * The blob (if not NULL) is an array of &struct drm_color_lut.
+	 */
+	struct drm_property_blob *degamma_lut;
 };
 
 struct dm_crtc_state {
@@ -817,6 +827,7 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
 #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
 
 void amdgpu_dm_init_color_mod(void);
+int amdgpu_dm_create_color_properties(struct amdgpu_device *adev);
 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_update_plane_color_mgmt(struct dm_crtc_state *crtc,
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 a4cb23d059bd..cf175b86ba80 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
@@ -84,6 +84,30 @@ void amdgpu_dm_init_color_mod(void)
 	setup_x_points_distribution();
 }
 
+#ifdef AMD_PRIVATE_COLOR
+int
+amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
+{
+	struct drm_property *prop;
+
+	prop = drm_property_create(adev_to_drm(adev),
+				   DRM_MODE_PROP_BLOB,
+				   "AMD_PLANE_DEGAMMA_LUT", 0);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_degamma_lut_property = prop;
+
+	prop = drm_property_create_range(adev_to_drm(adev),
+					 DRM_MODE_PROP_IMMUTABLE,
+					 "AMD_PLANE_DEGAMMA_LUT_SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_degamma_lut_size_property = prop;
+
+	return 0;
+}
+#endif
+
 /**
  * __extract_blob_lut - Extracts the DRM lut and lut size from a blob.
  * @blob: DRM color mgmt property blob
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 03df26bd8e83..69357a8ae887 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1353,6 +1353,9 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
 		dc_plane_state_retain(dm_plane_state->dc_state);
 	}
 
+	if (dm_plane_state->degamma_lut)
+		drm_property_blob_get(dm_plane_state->degamma_lut);
+
 	return &dm_plane_state->base;
 }
 
@@ -1420,12 +1423,83 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
 {
 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
 
+	if (dm_plane_state->degamma_lut)
+		drm_property_blob_put(dm_plane_state->degamma_lut);
+
 	if (dm_plane_state->dc_state)
 		dc_plane_state_release(dm_plane_state->dc_state);
 
 	drm_atomic_helper_plane_destroy_state(plane, state);
 }
 
+#ifdef AMD_PRIVATE_COLOR
+static void
+dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
+					     struct drm_plane *plane)
+{
+	struct amdgpu_mode_info mode_info = dm->adev->mode_info;
+	struct dpp_color_caps dpp_color_caps = dm->dc->caps.color.dpp;
+
+	/* Check HW color pipeline capabilities for DPP (pre-blending) before expose*/
+	if (dpp_color_caps.dgam_ram || dpp_color_caps.gamma_corr) {
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_degamma_lut_property, 0);
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_degamma_lut_size_property,
+					   MAX_COLOR_LUT_ENTRIES);
+	}
+}
+
+static int
+dm_atomic_plane_set_property(struct drm_plane *plane,
+			     struct drm_plane_state *state,
+			     struct drm_property *property,
+			     uint64_t val)
+{
+	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
+	struct amdgpu_device *adev = drm_to_adev(plane->dev);
+	bool replaced = false;
+	int ret;
+
+	if (property == adev->mode_info.plane_degamma_lut_property) {
+		ret = drm_property_replace_blob_from_id(plane->dev,
+							&dm_plane_state->degamma_lut,
+							val,
+							-1, sizeof(struct drm_color_lut),
+							&replaced);
+		dm_plane_state->base.color_mgmt_changed |= replaced;
+		return ret;
+	} else {
+		drm_dbg_atomic(plane->dev,
+			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
+			       plane->base.id, plane->name,
+			       property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+dm_atomic_plane_get_property(struct drm_plane *plane,
+			     const struct drm_plane_state *state,
+			     struct drm_property *property,
+			     uint64_t *val)
+{
+	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
+	struct amdgpu_device *adev = drm_to_adev(plane->dev);
+
+	if (property == adev->mode_info.plane_degamma_lut_property) {
+		*val = (dm_plane_state->degamma_lut) ?
+			dm_plane_state->degamma_lut->base.id : 0;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
 static const struct drm_plane_funcs dm_plane_funcs = {
 	.update_plane	= drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
@@ -1434,6 +1508,10 @@ static const struct drm_plane_funcs dm_plane_funcs = {
 	.atomic_duplicate_state = dm_drm_plane_duplicate_state,
 	.atomic_destroy_state = dm_drm_plane_destroy_state,
 	.format_mod_supported = dm_plane_format_mod_supported,
+#ifdef AMD_PRIVATE_COLOR
+	.atomic_set_property = dm_atomic_plane_set_property,
+	.atomic_get_property = dm_atomic_plane_get_property,
+#endif
 };
 
 int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
@@ -1513,6 +1591,9 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 
 	drm_plane_helper_add(plane, &dm_plane_helper_funcs);
 
+#ifdef AMD_PRIVATE_COLOR
+	dm_atomic_plane_attach_color_mgmt_properties(dm, plane);
+#endif
 	/* Create (reset) the plane state */
 	if (plane->funcs->reset)
 		plane->funcs->reset(plane);
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 05/32] drm/amd/display: add plane degamma TF driver-specific property
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (3 preceding siblings ...)
  2023-10-05 17:14 ` [PATCH v4 04/32] drm/amd/display: add driver-specific property for plane degamma LUT Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 06/32] drm/amd/display: explicitly define EOTF and inverse EOTF Melissa Wen
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Allow userspace to tell the kernel driver the input space and,
therefore, uses correct predefined transfer function (TF) to go from
encoded values to linear values.

v2:
- rename TF enum prefix from DRM_ to AMDGPU_ (Harry)
- remove HLG TF

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Co-developed-by: Melissa Wen <mwen@igalia.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  5 +++++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 19 +++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 21 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 19 +++++++++++++++--
 4 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 2d00802b3265..9b6fab86c6c3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -354,6 +354,11 @@ struct amdgpu_mode_info {
 	 * size of degamma LUT as supported by the driver (read-only).
 	 */
 	struct drm_property *plane_degamma_lut_size_property;
+	/**
+	 * @plane_degamma_tf_property: Plane pre-defined transfer function to
+	 * to go from scanout/encoded values to linear values.
+	 */
+	struct drm_property *plane_degamma_tf_property;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
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 0f565469b4b5..4c4cdf7fc6be 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -724,6 +724,18 @@ struct amdgpu_dm_wb_connector {
 
 extern const struct amdgpu_ip_block_version dm_ip_block;
 
+enum amdgpu_transfer_function {
+	AMDGPU_TRANSFER_FUNCTION_DEFAULT,
+	AMDGPU_TRANSFER_FUNCTION_SRGB,
+	AMDGPU_TRANSFER_FUNCTION_BT709,
+	AMDGPU_TRANSFER_FUNCTION_PQ,
+	AMDGPU_TRANSFER_FUNCTION_LINEAR,
+	AMDGPU_TRANSFER_FUNCTION_UNITY,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA22,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA24,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA26,
+};
+
 struct dm_plane_state {
 	struct drm_plane_state base;
 	struct dc_plane_state *dc_state;
@@ -737,6 +749,13 @@ struct dm_plane_state {
 	 * The blob (if not NULL) is an array of &struct drm_color_lut.
 	 */
 	struct drm_property_blob *degamma_lut;
+	/**
+	 * @degamma_tf:
+	 *
+	 * Predefined transfer function to tell DC driver the input space to
+	 * linearize.
+	 */
+	enum amdgpu_transfer_function degamma_tf;
 };
 
 struct dm_crtc_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 cf175b86ba80..56ce008b9095 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
@@ -85,6 +85,18 @@ void amdgpu_dm_init_color_mod(void)
 }
 
 #ifdef AMD_PRIVATE_COLOR
+static const struct drm_prop_enum_list amdgpu_transfer_function_enum_list[] = {
+	{ AMDGPU_TRANSFER_FUNCTION_DEFAULT, "Default" },
+	{ AMDGPU_TRANSFER_FUNCTION_SRGB, "sRGB" },
+	{ AMDGPU_TRANSFER_FUNCTION_BT709, "BT.709" },
+	{ AMDGPU_TRANSFER_FUNCTION_PQ, "PQ (Perceptual Quantizer)" },
+	{ AMDGPU_TRANSFER_FUNCTION_LINEAR, "Linear" },
+	{ AMDGPU_TRANSFER_FUNCTION_UNITY, "Unity" },
+	{ AMDGPU_TRANSFER_FUNCTION_GAMMA22, "Gamma 2.2" },
+	{ AMDGPU_TRANSFER_FUNCTION_GAMMA24, "Gamma 2.4" },
+	{ AMDGPU_TRANSFER_FUNCTION_GAMMA26, "Gamma 2.6" },
+};
+
 int
 amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 {
@@ -104,6 +116,15 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_degamma_lut_size_property = prop;
 
+	prop = drm_property_create_enum(adev_to_drm(adev),
+					DRM_MODE_PROP_ENUM,
+					"AMD_PLANE_DEGAMMA_TF",
+					amdgpu_transfer_function_enum_list,
+					ARRAY_SIZE(amdgpu_transfer_function_enum_list));
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_degamma_tf_property = prop;
+
 	return 0;
 }
 #endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 69357a8ae887..04af6db8cffd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1332,8 +1332,11 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
 	amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL);
 	WARN_ON(amdgpu_state == NULL);
 
-	if (amdgpu_state)
-		__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
+	if (!amdgpu_state)
+		return;
+
+	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
+	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
 }
 
 static struct drm_plane_state *
@@ -1356,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
 	if (dm_plane_state->degamma_lut)
 		drm_property_blob_get(dm_plane_state->degamma_lut);
 
+	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
+
 	return &dm_plane_state->base;
 }
 
@@ -1447,6 +1452,9 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
 		drm_object_attach_property(&plane->base,
 					   mode_info.plane_degamma_lut_size_property,
 					   MAX_COLOR_LUT_ENTRIES);
+		drm_object_attach_property(&plane->base,
+					   dm->adev->mode_info.plane_degamma_tf_property,
+					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
 	}
 }
 
@@ -1469,6 +1477,11 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
 							&replaced);
 		dm_plane_state->base.color_mgmt_changed |= replaced;
 		return ret;
+	} else if (property == adev->mode_info.plane_degamma_tf_property) {
+		if (dm_plane_state->degamma_tf != val) {
+			dm_plane_state->degamma_tf = val;
+			dm_plane_state->base.color_mgmt_changed = 1;
+		}
 	} else {
 		drm_dbg_atomic(plane->dev,
 			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
@@ -1492,6 +1505,8 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 	if (property == adev->mode_info.plane_degamma_lut_property) {
 		*val = (dm_plane_state->degamma_lut) ?
 			dm_plane_state->degamma_lut->base.id : 0;
+	} else if (property == adev->mode_info.plane_degamma_tf_property) {
+		*val = dm_plane_state->degamma_tf;
 	} else {
 		return -EINVAL;
 	}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 06/32] drm/amd/display: explicitly define EOTF and inverse EOTF
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (4 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 05/32] drm/amd/display: add plane degamma TF driver-specific property Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-11-15 18:25   ` Harry Wentland
  2023-10-05 17:15 ` [PATCH v4 07/32] drm/amd/display: document AMDGPU pre-defined transfer functions Melissa Wen
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Instead of relying on color block names to get the transfer function
intention regarding encoding pixel's luminance, define supported
Electro-Optical Transfer Functions (EOTFs) and inverse EOTFs, that
includes pure gamma or standardized transfer functions.

v3:
- squash linear and unity TFs to identity (Pekka)
- define the right TFs for BT.709 (Pekka and Harry)
- add comment about AMD TF coefficients

Suggested-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 27 +++++---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 67 ++++++++++++++-----
 2 files changed, 71 insertions(+), 23 deletions(-)

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 4c4cdf7fc6be..fc4f188d397e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -724,16 +724,27 @@ struct amdgpu_dm_wb_connector {
 
 extern const struct amdgpu_ip_block_version dm_ip_block;
 
+/* enum amdgpu_transfer_function: pre-defined transfer function supported by AMD.
+ *
+ * It includes standardized transfer functions and pure power functions. The
+ * transfer function coefficients are available at modules/color/color_gamma.c
+ */
 enum amdgpu_transfer_function {
 	AMDGPU_TRANSFER_FUNCTION_DEFAULT,
-	AMDGPU_TRANSFER_FUNCTION_SRGB,
-	AMDGPU_TRANSFER_FUNCTION_BT709,
-	AMDGPU_TRANSFER_FUNCTION_PQ,
-	AMDGPU_TRANSFER_FUNCTION_LINEAR,
-	AMDGPU_TRANSFER_FUNCTION_UNITY,
-	AMDGPU_TRANSFER_FUNCTION_GAMMA22,
-	AMDGPU_TRANSFER_FUNCTION_GAMMA24,
-	AMDGPU_TRANSFER_FUNCTION_GAMMA26,
+	AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF,
+	AMDGPU_TRANSFER_FUNCTION_PQ_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_IDENTITY,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_BT709_OETF,
+	AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF,
+	AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF,
+        AMDGPU_TRANSFER_FUNCTION_COUNT
 };
 
 struct dm_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 56ce008b9095..d03bdb010e8b 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
@@ -85,18 +85,57 @@ void amdgpu_dm_init_color_mod(void)
 }
 
 #ifdef AMD_PRIVATE_COLOR
-static const struct drm_prop_enum_list amdgpu_transfer_function_enum_list[] = {
-	{ AMDGPU_TRANSFER_FUNCTION_DEFAULT, "Default" },
-	{ AMDGPU_TRANSFER_FUNCTION_SRGB, "sRGB" },
-	{ AMDGPU_TRANSFER_FUNCTION_BT709, "BT.709" },
-	{ AMDGPU_TRANSFER_FUNCTION_PQ, "PQ (Perceptual Quantizer)" },
-	{ AMDGPU_TRANSFER_FUNCTION_LINEAR, "Linear" },
-	{ AMDGPU_TRANSFER_FUNCTION_UNITY, "Unity" },
-	{ AMDGPU_TRANSFER_FUNCTION_GAMMA22, "Gamma 2.2" },
-	{ AMDGPU_TRANSFER_FUNCTION_GAMMA24, "Gamma 2.4" },
-	{ AMDGPU_TRANSFER_FUNCTION_GAMMA26, "Gamma 2.6" },
+static const char * const
+amdgpu_transfer_function_names[] = {
+	[AMDGPU_TRANSFER_FUNCTION_DEFAULT]		= "Default",
+	[AMDGPU_TRANSFER_FUNCTION_IDENTITY]		= "Identity",
+	[AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF]		= "sRGB EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF]	= "BT.709 inv_OETF",
+	[AMDGPU_TRANSFER_FUNCTION_PQ_EOTF]		= "PQ EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF]		= "Gamma 2.2 EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF]		= "Gamma 2.4 EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF]		= "Gamma 2.6 EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF]	= "sRGB inv_EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_BT709_OETF]		= "BT.709 OETF",
+	[AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF]		= "PQ inv_EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF]	= "Gamma 2.2 inv_EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF]	= "Gamma 2.4 inv_EOTF",
+	[AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF]	= "Gamma 2.6 inv_EOTF",
 };
 
+static const u32 amdgpu_eotf =
+	BIT(AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_PQ_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF);
+
+static struct drm_property *
+amdgpu_create_tf_property(struct drm_device *dev,
+			  const char *name,
+			  u32 supported_tf)
+{
+	u32 transfer_functions = supported_tf |
+				 BIT(AMDGPU_TRANSFER_FUNCTION_DEFAULT) |
+				 BIT(AMDGPU_TRANSFER_FUNCTION_IDENTITY);
+	struct drm_prop_enum_list enum_list[AMDGPU_TRANSFER_FUNCTION_COUNT];
+	int i, len;
+
+	len = 0;
+	for (i = 0; i < AMDGPU_TRANSFER_FUNCTION_COUNT; i++) {
+		if ((transfer_functions & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = amdgpu_transfer_function_names[i];
+		len++;
+	}
+
+	return drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
+					name, enum_list, len);
+}
+
 int
 amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 {
@@ -116,11 +155,9 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_degamma_lut_size_property = prop;
 
-	prop = drm_property_create_enum(adev_to_drm(adev),
-					DRM_MODE_PROP_ENUM,
-					"AMD_PLANE_DEGAMMA_TF",
-					amdgpu_transfer_function_enum_list,
-					ARRAY_SIZE(amdgpu_transfer_function_enum_list));
+	prop = amdgpu_create_tf_property(adev_to_drm(adev),
+					 "AMD_PLANE_DEGAMMA_TF",
+					 amdgpu_eotf);
 	if (!prop)
 		return -ENOMEM;
 	adev->mode_info.plane_degamma_tf_property = prop;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 07/32] drm/amd/display: document AMDGPU pre-defined transfer functions
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (5 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 06/32] drm/amd/display: explicitly define EOTF and inverse EOTF Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-11-15 18:26   ` Harry Wentland
  2023-10-05 17:15 ` [PATCH v4 08/32] drm/amd/display: add plane HDR multiplier driver-specific property Melissa Wen
                   ` (25 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Brief documentation about pre-defined transfer function usage on AMD
display driver and standardized EOTFs and inverse EOTFs.

v3:
- Document BT709 OETF (Pekka)
- Fix description of sRGB and pure power funcs (Pekka)

v4:
- Add description of linear and non-linear forms (Harry)

Co-developed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 62 +++++++++++++++++++
 1 file changed, 62 insertions(+)

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 d03bdb010e8b..d5dbd20a6766 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
@@ -85,6 +85,68 @@ void amdgpu_dm_init_color_mod(void)
 }
 
 #ifdef AMD_PRIVATE_COLOR
+/* Pre-defined Transfer Functions (TF)
+ *
+ * AMD driver supports pre-defined mathematical functions for transferring
+ * between encoded values and optical/linear space. Depending on HW color caps,
+ * ROMs and curves built by the AMD color module support these transforms.
+ *
+ * The driver-specific color implementation exposes properties for pre-blending
+ * degamma TF, shaper TF (before 3D LUT), and blend(dpp.ogam) TF and
+ * post-blending regamma (mpc.ogam) TF. However, only pre-blending degamma
+ * supports ROM curves. AMD color module uses pre-defined coefficients to build
+ * curves for the other blocks. What can be done by each color block is
+ * described by struct dpp_color_capsand struct mpc_color_caps.
+ *
+ * AMD driver-specific color API exposes the following pre-defined transfer
+ * functions:
+ *
+ * - Identity: linear/identity relationship between pixel value and
+ *   luminance value;
+ * - Gamma 2.2, Gamma 2.4, Gamma 2.6: pure power functions;
+ * - sRGB: 2.4: The piece-wise transfer function from IEC 61966-2-1:1999;
+ * - BT.709: has a linear segment in the bottom part and then a power function
+ *   with a 0.45 (~1/2.22) gamma for the rest of the range; standardized by
+ *   ITU-R BT.709-6;
+ * - PQ (Perceptual Quantizer): used for HDR display, allows luminance range
+ *   capability of 0 to 10,000 nits; standardized by SMPTE ST 2084.
+ *
+ * The AMD color model is designed with an assumption that SDR (sRGB, BT.709,
+ * Gamma 2.2, etc.) peak white maps (normalized to 1.0 FP) to 80 nits in the PQ
+ * system. This has the implication that PQ EOTF (non-linear to linear) maps to
+ * [0.0..125.0] where 125.0 = 10,000 nits / 80 nits.
+ *
+ * Non-linear and linear forms are described in the table below:
+ *
+ * ┌───────────┬─────────────────────┬──────────────────────┐
+ * │           │     Non-linear      │   Linear             │
+ * ├───────────┼─────────────────────┼──────────────────────┤
+ * │      sRGB │ UNORM or [0.0, 1.0] │ [0.0, 1.0]           │
+ * ├───────────┼─────────────────────┼──────────────────────┤
+ * │     BT709 │ UNORM or [0.0, 1.0] │ [0.0, 1.0]           │
+ * ├───────────┼─────────────────────┼──────────────────────┤
+ * │ Gamma 2.x │ UNORM or [0.0, 1.0] │ [0.0, 1.0]           │
+ * ├───────────┼─────────────────────┼──────────────────────┤
+ * │        PQ │ UNORM or FP16 CCCS* │ [0.0, 125.0]         │
+ * ├───────────┼─────────────────────┼──────────────────────┤
+ * │  Identity │ UNORM or FP16 CCCS* │ [0.0, 1.0] or CCCS** │
+ * └───────────┴─────────────────────┴──────────────────────┘
+ * * CCCS: Windows canonical composition color space
+ * ** Respectively
+ *
+ * In the driver-specific API, color block names attached to TF properties
+ * suggest the intention regarding non-linear encoding pixel's luminance
+ * values. As some newer encodings don't use gamma curve, we make encoding and
+ * decoding explicit by defining an enum list of transfer functions supported
+ * in terms of EOTF and inverse EOTF, where:
+ *
+ * - EOTF (electro-optical transfer function): is the transfer function to go
+ *   from the encoded value to an optical (linear) value. De-gamma functions
+ *   traditionally do this.
+ * - Inverse EOTF (simply the inverse of the EOTF): is usually intended to go
+ *   from an optical/linear space (which might have been used for blending)
+ *   back to the encoded values. Gamma functions traditionally do this.
+ */
 static const char * const
 amdgpu_transfer_function_names[] = {
 	[AMDGPU_TRANSFER_FUNCTION_DEFAULT]		= "Default",
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 08/32] drm/amd/display: add plane HDR multiplier driver-specific property
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (6 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 07/32] drm/amd/display: document AMDGPU pre-defined transfer functions Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-11-15 18:26   ` Harry Wentland
  2023-10-05 17:15 ` [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties Melissa Wen
                   ` (24 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Multiplier to 'gain' the plane. When PQ is decoded using the fixed func
transfer function to the internal FP16 fb, 1.0 -> 80 nits (on AMD at
least) When sRGB is decoded, 1.0 -> 1.0.  Therefore, 1.0 multiplier = 80
nits for SDR content. So if you want, 203 nits for SDR content, pass in
(203.0 / 80.0).

v4:
- comment about the PQ TF need for L-to-NL (from Harry's review)

Signed-off-by: Joshua Ashton <joshua@froggi.es>
Co-developed-by: Melissa Wen <mwen@igalia.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h        |  4 ++++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h   | 17 +++++++++++++++++
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c |  6 ++++++
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 13 +++++++++++++
 4 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 9b6fab86c6c3..62044d41da75 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -359,6 +359,10 @@ struct amdgpu_mode_info {
 	 * to go from scanout/encoded values to linear values.
 	 */
 	struct drm_property *plane_degamma_tf_property;
+	/**
+	 * @plane_hdr_mult_property:
+	 */
+	struct drm_property *plane_hdr_mult_property;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
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 fc4f188d397e..bb2ce843369d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -55,6 +55,9 @@
 #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
 #define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
 #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
+
+#define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL)
+
 /*
 #include "include/amdgpu_dal_power_if.h"
 #include "amdgpu_dm_irq.h"
@@ -767,6 +770,20 @@ struct dm_plane_state {
 	 * linearize.
 	 */
 	enum amdgpu_transfer_function degamma_tf;
+	/**
+	 * @hdr_mult:
+	 *
+	 * Multiplier to 'gain' the plane.  When PQ is decoded using the fixed
+	 * func transfer function to the internal FP16 fb, 1.0 -> 80 nits (on
+	 * AMD at least). When sRGB is decoded, 1.0 -> 1.0, obviously.
+	 * Therefore, 1.0 multiplier = 80 nits for SDR content.  So if you
+	 * want, 203 nits for SDR content, pass in (203.0 / 80.0).  Format is
+	 * S31.32 sign-magnitude.
+	 *
+	 * HDR multiplier can wide range beyond [0.0, 1.0]. This means that PQ
+	 * TF is needed for any subsequent linear-to-non-linear transforms.
+	 */
+	__u64 hdr_mult;
 };
 
 struct dm_crtc_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 d5dbd20a6766..caf49a044ab4 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
@@ -224,6 +224,12 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_degamma_tf_property = prop;
 
+	prop = drm_property_create_range(adev_to_drm(adev),
+					 0, "AMD_PLANE_HDR_MULT", 0, U64_MAX);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_hdr_mult_property = prop;
+
 	return 0;
 }
 #endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 04af6db8cffd..ae64d4b73360 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1337,6 +1337,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
 
 	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
 	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
+	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
 }
 
 static struct drm_plane_state *
@@ -1360,6 +1361,7 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
 		drm_property_blob_get(dm_plane_state->degamma_lut);
 
 	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
+	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
 
 	return &dm_plane_state->base;
 }
@@ -1456,6 +1458,10 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
 					   dm->adev->mode_info.plane_degamma_tf_property,
 					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
 	}
+	/* HDR MULT is always available */
+	drm_object_attach_property(&plane->base,
+				   dm->adev->mode_info.plane_hdr_mult_property,
+				   AMDGPU_HDR_MULT_DEFAULT);
 }
 
 static int
@@ -1482,6 +1488,11 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
 			dm_plane_state->degamma_tf = val;
 			dm_plane_state->base.color_mgmt_changed = 1;
 		}
+	} else if (property == adev->mode_info.plane_hdr_mult_property) {
+		if (dm_plane_state->hdr_mult != val) {
+			dm_plane_state->hdr_mult = val;
+			dm_plane_state->base.color_mgmt_changed = 1;
+		}
 	} else {
 		drm_dbg_atomic(plane->dev,
 			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
@@ -1507,6 +1518,8 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 			dm_plane_state->degamma_lut->base.id : 0;
 	} else if (property == adev->mode_info.plane_degamma_tf_property) {
 		*val = dm_plane_state->degamma_tf;
+	} else if (property == adev->mode_info.plane_hdr_mult_property) {
+		*val = dm_plane_state->hdr_mult;
 	} else {
 		return -EINVAL;
 	}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (7 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 08/32] drm/amd/display: add plane HDR multiplier driver-specific property Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-06  9:09   ` Sebastian Wick
  2023-11-02  3:48   ` Joshua Ashton
  2023-10-05 17:15 ` [PATCH v4 10/32] drm/amd/display: add plane shaper LUT and TF " Melissa Wen
                   ` (23 subsequent siblings)
  32 siblings, 2 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Add 3D LUT property for plane color transformations using a 3D lookup
table. 3D LUT allows for highly accurate and complex color
transformations and is suitable to adjust the balance between color
channels. It's also more complex to manage and require more
computational resources.

Since a 3D LUT has a limited number of entries in each dimension we want
to use them in an optimal fashion. This means using the 3D LUT in a
colorspace that is optimized for human vision, such as sRGB, PQ, or
another non-linear space. Therefore, userpace may need one 1D LUT
(shaper) before it to delinearize content and another 1D LUT after 3D
LUT (blend) to linearize content again for blending. The next patches
add these 1D LUTs to the plane color mgmt pipeline.

v3:
- improve commit message about 3D LUT
- describe the 3D LUT entries and size (Harry)

v4:
- advertise 3D LUT max size as the size of a single-dimension

Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 18 +++++++++++++++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  9 ++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 14 +++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 23 +++++++++++++++++++
 4 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 62044d41da75..f7adaa52c23f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -363,6 +363,24 @@ struct amdgpu_mode_info {
 	 * @plane_hdr_mult_property:
 	 */
 	struct drm_property *plane_hdr_mult_property;
+	/**
+	 * @plane_lut3d_property: Plane property for color transformation using
+	 * a 3D LUT (pre-blending), a three-dimensional array where each
+	 * element is an RGB triplet. Each dimension has a size of the cubed
+	 * root of lut3d_size. The array contains samples from the approximated
+	 * function. On AMD, values between samples are estimated by
+	 * tetrahedral interpolation. The array is accessed with three indices,
+	 * one for each input dimension (color channel), blue being the
+	 * outermost dimension, red the innermost.
+	 */
+	struct drm_property *plane_lut3d_property;
+	/**
+	 * @plane_degamma_lut_size_property: Plane property to define the max
+	 * size of 3D LUT as supported by the driver (read-only). The max size
+	 * is the max size of one dimension and, therefore, the max number of
+	 * entries for 3D LUT array is the 3D LUT size cubed;
+	 */
+	struct drm_property *plane_lut3d_size_property;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
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 bb2ce843369d..7a2350c62cf1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -784,6 +784,11 @@ struct dm_plane_state {
 	 * TF is needed for any subsequent linear-to-non-linear transforms.
 	 */
 	__u64 hdr_mult;
+	/**
+	 * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
+	 * &struct drm_color_lut.
+	 */
+	struct drm_property_blob *lut3d;
 };
 
 struct dm_crtc_state {
@@ -869,6 +874,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
 
 void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
 
+/* 3D LUT max size is 17x17x17 (4913 entries) */
+#define MAX_COLOR_3DLUT_SIZE 17
+#define MAX_COLOR_3DLUT_BITDEPTH 12
+/* 1D LUT size */
 #define MAX_COLOR_LUT_ENTRIES 4096
 /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
 #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
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 caf49a044ab4..011f2f9ec890 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
@@ -230,6 +230,20 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_hdr_mult_property = prop;
 
+	prop = drm_property_create(adev_to_drm(adev),
+				   DRM_MODE_PROP_BLOB,
+				   "AMD_PLANE_LUT3D", 0);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_lut3d_property = prop;
+
+	prop = drm_property_create_range(adev_to_drm(adev),
+					 DRM_MODE_PROP_IMMUTABLE,
+					 "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_lut3d_size_property = prop;
+
 	return 0;
 }
 #endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index ae64d4b73360..068798ffdd56 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1359,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
 
 	if (dm_plane_state->degamma_lut)
 		drm_property_blob_get(dm_plane_state->degamma_lut);
+	if (dm_plane_state->lut3d)
+		drm_property_blob_get(dm_plane_state->lut3d);
 
 	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
 	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
@@ -1432,6 +1434,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
 
 	if (dm_plane_state->degamma_lut)
 		drm_property_blob_put(dm_plane_state->degamma_lut);
+	if (dm_plane_state->lut3d)
+		drm_property_blob_put(dm_plane_state->lut3d);
 
 	if (dm_plane_state->dc_state)
 		dc_plane_state_release(dm_plane_state->dc_state);
@@ -1462,6 +1466,14 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
 	drm_object_attach_property(&plane->base,
 				   dm->adev->mode_info.plane_hdr_mult_property,
 				   AMDGPU_HDR_MULT_DEFAULT);
+
+	if (dpp_color_caps.hw_3d_lut) {
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_lut3d_property, 0);
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_lut3d_size_property,
+					   MAX_COLOR_3DLUT_SIZE);
+	}
 }
 
 static int
@@ -1493,6 +1505,14 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
 			dm_plane_state->hdr_mult = val;
 			dm_plane_state->base.color_mgmt_changed = 1;
 		}
+	} else if (property == adev->mode_info.plane_lut3d_property) {
+		ret = drm_property_replace_blob_from_id(plane->dev,
+							&dm_plane_state->lut3d,
+							val, -1,
+							sizeof(struct drm_color_lut),
+							&replaced);
+		dm_plane_state->base.color_mgmt_changed |= replaced;
+		return ret;
 	} else {
 		drm_dbg_atomic(plane->dev,
 			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
@@ -1520,6 +1540,9 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = dm_plane_state->degamma_tf;
 	} else if (property == adev->mode_info.plane_hdr_mult_property) {
 		*val = dm_plane_state->hdr_mult;
+	} else 	if (property == adev->mode_info.plane_lut3d_property) {
+		*val = (dm_plane_state->lut3d) ?
+			dm_plane_state->lut3d->base.id : 0;
 	} else {
 		return -EINVAL;
 	}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 10/32] drm/amd/display: add plane shaper LUT and TF driver-specific properties
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (8 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-11-15 18:27   ` Harry Wentland
  2023-10-05 17:15 ` [PATCH v4 11/32] drm/amd/display: add plane blend " Melissa Wen
                   ` (22 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

On AMD HW, 3D LUT always assumes a preceding shaper 1D LUT used for
delinearizing and/or normalizing the color space before applying a 3D
LUT. Add pre-defined transfer function to enable delinearizing content
with or without shaper LUT, where AMD color module calculates the
resulted shaper curve. We apply an inverse EOTF to go from linear
values to encoded values. If we are already in a non-linear space and/or
don't need to normalize values, we can bypass shaper LUT with a linear
transfer function that is also the default TF value.

There is no shaper ROM. When setting shaper TF (!= Identity) and LUT at
the same time, the color module will combine the pre-defined TF and the
custom LUT values into the LUT that's actually programmed.

v2:
- squash commits for shaper LUT and shaper TF
- define inverse EOTF as supported shaper TFs

v3:
- spell out TF+LUT behavior in the commit and comments (Harry)
- replace BT709 EOTF by inv OETF

Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 21 ++++++++++++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 11 +++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 29 +++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 32 +++++++++++++++++++
 4 files changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index f7adaa52c23f..af70db4f6b4b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -363,6 +363,27 @@ struct amdgpu_mode_info {
 	 * @plane_hdr_mult_property:
 	 */
 	struct drm_property *plane_hdr_mult_property;
+	/**
+	 * @shaper_lut_property: Plane property to set pre-blending shaper LUT
+	 * that converts color content before 3D LUT. If
+	 * plane_shaper_tf_property != Identity TF, AMD color module will
+	 * combine the user LUT values with pre-defined TF into the LUT
+	 * parameters to be programmed.
+	 */
+	struct drm_property *plane_shaper_lut_property;
+	/**
+	 * @shaper_lut_size_property: Plane property for the size of
+	 * pre-blending shaper LUT as supported by the driver (read-only).
+	 */
+	struct drm_property *plane_shaper_lut_size_property;
+	/**
+	 * @plane_shaper_tf_property: Plane property to set a predefined
+	 * transfer function for pre-blending shaper (before applying 3D LUT)
+	 * with or without LUT. There is no shaper ROM, but we can use AMD
+	 * color modules to program LUT parameters from predefined TF (or
+	 * from a combination of pre-defined TF and the custom 1D LUT).
+	 */
+	struct drm_property *plane_shaper_tf_property;
 	/**
 	 * @plane_lut3d_property: Plane property for color transformation using
 	 * a 3D LUT (pre-blending), a three-dimensional array where each
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 7a2350c62cf1..0e2a04a3caf3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -784,6 +784,17 @@ struct dm_plane_state {
 	 * TF is needed for any subsequent linear-to-non-linear transforms.
 	 */
 	__u64 hdr_mult;
+	/**
+	 * @shaper_lut: shaper lookup table blob. The blob (if not NULL) is an
+	 * array of &struct drm_color_lut.
+	 */
+	struct drm_property_blob *shaper_lut;
+	/**
+	 * @shaper_tf:
+	 *
+	 * Predefined transfer function to delinearize color space.
+	 */
+	enum amdgpu_transfer_function shaper_tf;
 	/**
 	 * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
 	 * &struct drm_color_lut.
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 011f2f9ec890..d3c7f9a13a61 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
@@ -173,6 +173,14 @@ static const u32 amdgpu_eotf =
 	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF) |
 	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF);
 
+static const u32 amdgpu_inv_eotf =
+	BIT(AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_BT709_OETF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF) |
+	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF);
+
 static struct drm_property *
 amdgpu_create_tf_property(struct drm_device *dev,
 			  const char *name,
@@ -230,6 +238,27 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_hdr_mult_property = prop;
 
+	prop = drm_property_create(adev_to_drm(adev),
+				   DRM_MODE_PROP_BLOB,
+				   "AMD_PLANE_SHAPER_LUT", 0);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_shaper_lut_property = prop;
+
+	prop = drm_property_create_range(adev_to_drm(adev),
+					 DRM_MODE_PROP_IMMUTABLE,
+					 "AMD_PLANE_SHAPER_LUT_SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_shaper_lut_size_property = prop;
+
+	prop = amdgpu_create_tf_property(adev_to_drm(adev),
+					 "AMD_PLANE_SHAPER_TF",
+					 amdgpu_inv_eotf);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_shaper_tf_property = prop;
+
 	prop = drm_property_create(adev_to_drm(adev),
 				   DRM_MODE_PROP_BLOB,
 				   "AMD_PLANE_LUT3D", 0);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 068798ffdd56..a381b3558bd1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1338,6 +1338,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
 	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
 	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
 	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
+	amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
 }
 
 static struct drm_plane_state *
@@ -1359,11 +1360,14 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
 
 	if (dm_plane_state->degamma_lut)
 		drm_property_blob_get(dm_plane_state->degamma_lut);
+	if (dm_plane_state->shaper_lut)
+		drm_property_blob_get(dm_plane_state->shaper_lut);
 	if (dm_plane_state->lut3d)
 		drm_property_blob_get(dm_plane_state->lut3d);
 
 	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
 	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
+	dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf;
 
 	return &dm_plane_state->base;
 }
@@ -1436,6 +1440,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
 		drm_property_blob_put(dm_plane_state->degamma_lut);
 	if (dm_plane_state->lut3d)
 		drm_property_blob_put(dm_plane_state->lut3d);
+	if (dm_plane_state->shaper_lut)
+		drm_property_blob_put(dm_plane_state->shaper_lut);
 
 	if (dm_plane_state->dc_state)
 		dc_plane_state_release(dm_plane_state->dc_state);
@@ -1468,6 +1474,14 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
 				   AMDGPU_HDR_MULT_DEFAULT);
 
 	if (dpp_color_caps.hw_3d_lut) {
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_shaper_lut_property, 0);
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_shaper_lut_size_property,
+					   MAX_COLOR_LUT_ENTRIES);
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_shaper_tf_property,
+					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
 		drm_object_attach_property(&plane->base,
 					   mode_info.plane_lut3d_property, 0);
 		drm_object_attach_property(&plane->base,
@@ -1505,6 +1519,19 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
 			dm_plane_state->hdr_mult = val;
 			dm_plane_state->base.color_mgmt_changed = 1;
 		}
+	} else if (property == adev->mode_info.plane_shaper_lut_property) {
+		ret = drm_property_replace_blob_from_id(plane->dev,
+							&dm_plane_state->shaper_lut,
+							val, -1,
+							sizeof(struct drm_color_lut),
+							&replaced);
+		dm_plane_state->base.color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == adev->mode_info.plane_shaper_tf_property) {
+		if (dm_plane_state->shaper_tf != val) {
+			dm_plane_state->shaper_tf = val;
+			dm_plane_state->base.color_mgmt_changed = 1;
+		}
 	} else if (property == adev->mode_info.plane_lut3d_property) {
 		ret = drm_property_replace_blob_from_id(plane->dev,
 							&dm_plane_state->lut3d,
@@ -1540,6 +1567,11 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = dm_plane_state->degamma_tf;
 	} else if (property == adev->mode_info.plane_hdr_mult_property) {
 		*val = dm_plane_state->hdr_mult;
+	} else 	if (property == adev->mode_info.plane_shaper_lut_property) {
+		*val = (dm_plane_state->shaper_lut) ?
+			dm_plane_state->shaper_lut->base.id : 0;
+	} else if (property == adev->mode_info.plane_shaper_tf_property) {
+		*val = dm_plane_state->shaper_tf;
 	} else 	if (property == adev->mode_info.plane_lut3d_property) {
 		*val = (dm_plane_state->lut3d) ?
 			dm_plane_state->lut3d->base.id : 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 11/32] drm/amd/display: add plane blend LUT and TF driver-specific properties
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (9 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 10/32] drm/amd/display: add plane shaper LUT and TF " Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-11-15 18:27   ` Harry Wentland
  2023-10-05 17:15 ` [PATCH v4 12/32] drm/amd/display: add CRTC gamma TF driver-specific property Melissa Wen
                   ` (21 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Blend 1D LUT or a pre-defined transfer function (TF) can be set to
linearize content before blending, so that it's positioned just before
blending planes in the AMD color mgmt pipeline, and after 3D LUT
(non-linear space). Shaper and Blend LUTs are 1D LUTs that sandwich 3D
LUT. Drivers should advertize blend properties according to HW caps.

There is no blend ROM for pre-defined TF. When setting blend TF (!=
Identity) and LUT at the same time, the color module will combine the
pre-defined TF and the custom LUT values into the LUT that's actually
programmed.

v3:
- spell out TF+LUT behavior in the commit and comments (Harry)

Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 22 ++++++++++++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 12 +++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 21 +++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 36 +++++++++++++++++++
 4 files changed, 91 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index af70db4f6b4b..dee35d208493 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -402,6 +402,28 @@ struct amdgpu_mode_info {
 	 * entries for 3D LUT array is the 3D LUT size cubed;
 	 */
 	struct drm_property *plane_lut3d_size_property;
+	/**
+	 * @plane_blend_lut_property: Plane property for output gamma before
+	 * blending. Userspace set a blend LUT to convert colors after 3D LUT
+	 * conversion. It works as a post-3DLUT 1D LUT. With shaper LUT, they
+	 * are sandwiching 3D LUT with two 1D LUT. If plane_blend_tf_property
+	 * != Identity TF, AMD color module will combine the user LUT values
+	 * with pre-defined TF into the LUT parameters to be programmed.
+	 */
+	struct drm_property *plane_blend_lut_property;
+	/**
+	 * @plane_blend_lut_size_property: Plane property to define the max
+	 * size of blend LUT as supported by the driver (read-only).
+	 */
+	struct drm_property *plane_blend_lut_size_property;
+	/**
+	 * @plane_blend_tf_property: Plane property to set a predefined
+	 * transfer function for pre-blending blend/out_gamma (after applying
+	 * 3D LUT) with or without LUT. There is no blend ROM, but we can use
+	 * AMD color modules to program LUT parameters from predefined TF (or
+	 * from a combination of pre-defined TF and the custom 1D LUT).
+	 */
+	struct drm_property *plane_blend_tf_property;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
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 0e2a04a3caf3..1b96c742d747 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -800,6 +800,18 @@ struct dm_plane_state {
 	 * &struct drm_color_lut.
 	 */
 	struct drm_property_blob *lut3d;
+	/**
+	 * @blend_lut: blend lut lookup table blob. The blob (if not NULL) is an
+	 * array of &struct drm_color_lut.
+	 */
+	struct drm_property_blob *blend_lut;
+	/**
+	 * @blend_tf:
+	 *
+	 * Pre-defined transfer function for converting plane pixel data before
+	 * applying blend LUT.
+	 */
+	enum amdgpu_transfer_function blend_tf;
 };
 
 struct dm_crtc_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 d3c7f9a13a61..82c554662faa 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
@@ -273,6 +273,27 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_lut3d_size_property = prop;
 
+	prop = drm_property_create(adev_to_drm(adev),
+				   DRM_MODE_PROP_BLOB,
+				   "AMD_PLANE_BLEND_LUT", 0);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_blend_lut_property = prop;
+
+	prop = drm_property_create_range(adev_to_drm(adev),
+					 DRM_MODE_PROP_IMMUTABLE,
+					 "AMD_PLANE_BLEND_LUT_SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_blend_lut_size_property = prop;
+
+	prop = amdgpu_create_tf_property(adev_to_drm(adev),
+					 "AMD_PLANE_BLEND_TF",
+					 amdgpu_eotf);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_blend_tf_property = prop;
+
 	return 0;
 }
 #endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index a381b3558bd1..f1070ca7076a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1339,6 +1339,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
 	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
 	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
 	amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
+	amdgpu_state->blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
 }
 
 static struct drm_plane_state *
@@ -1364,10 +1365,13 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
 		drm_property_blob_get(dm_plane_state->shaper_lut);
 	if (dm_plane_state->lut3d)
 		drm_property_blob_get(dm_plane_state->lut3d);
+	if (dm_plane_state->blend_lut)
+		drm_property_blob_get(dm_plane_state->blend_lut);
 
 	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
 	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
 	dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf;
+	dm_plane_state->blend_tf = old_dm_plane_state->blend_tf;
 
 	return &dm_plane_state->base;
 }
@@ -1442,6 +1446,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
 		drm_property_blob_put(dm_plane_state->lut3d);
 	if (dm_plane_state->shaper_lut)
 		drm_property_blob_put(dm_plane_state->shaper_lut);
+	if (dm_plane_state->blend_lut)
+		drm_property_blob_put(dm_plane_state->blend_lut);
 
 	if (dm_plane_state->dc_state)
 		dc_plane_state_release(dm_plane_state->dc_state);
@@ -1488,6 +1494,17 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
 					   mode_info.plane_lut3d_size_property,
 					   MAX_COLOR_3DLUT_SIZE);
 	}
+
+	if (dpp_color_caps.ogam_ram) {
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_blend_lut_property, 0);
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_blend_lut_size_property,
+					   MAX_COLOR_LUT_ENTRIES);
+		drm_object_attach_property(&plane->base,
+					   mode_info.plane_blend_tf_property,
+					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
+	}
 }
 
 static int
@@ -1540,6 +1557,19 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
 							&replaced);
 		dm_plane_state->base.color_mgmt_changed |= replaced;
 		return ret;
+	} else if (property == adev->mode_info.plane_blend_lut_property) {
+		ret = drm_property_replace_blob_from_id(plane->dev,
+							&dm_plane_state->blend_lut,
+							val, -1,
+							sizeof(struct drm_color_lut),
+							&replaced);
+		dm_plane_state->base.color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == adev->mode_info.plane_blend_tf_property) {
+		if (dm_plane_state->blend_tf != val) {
+			dm_plane_state->blend_tf = val;
+			dm_plane_state->base.color_mgmt_changed = 1;
+		}
 	} else {
 		drm_dbg_atomic(plane->dev,
 			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
@@ -1575,6 +1605,12 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 	} else 	if (property == adev->mode_info.plane_lut3d_property) {
 		*val = (dm_plane_state->lut3d) ?
 			dm_plane_state->lut3d->base.id : 0;
+	} else 	if (property == adev->mode_info.plane_blend_lut_property) {
+		*val = (dm_plane_state->blend_lut) ?
+			dm_plane_state->blend_lut->base.id : 0;
+	} else if (property == adev->mode_info.plane_blend_tf_property) {
+		*val = dm_plane_state->blend_tf;
+
 	} else {
 		return -EINVAL;
 	}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 12/32] drm/amd/display: add CRTC gamma TF driver-specific property
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (10 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 11/32] drm/amd/display: add plane blend " Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-11-15 18:27   ` Harry Wentland
  2023-10-05 17:15 ` [PATCH v4 13/32] drm/amd/display: add comments to describe DM crtc color mgmt behavior Melissa Wen
                   ` (20 subsequent siblings)
  32 siblings, 1 reply; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Add AMD pre-defined transfer function property to default DRM CRTC gamma
to convert to wire encoding with or without a user gamma LUT. There is
no post-blending regamma ROM for pre-defined TF. When setting Gamma TF
(!= Identity) and LUT at the same time, the color module will combine
the pre-defined TF and the custom LUT values into the LUT that's
actually programmed.

v2:
- enable CRTC prop in the end of driver-specific prop sequence
- define inverse EOTFs as supported regamma TFs
- reword driver-specific function doc to remove shaper/3D LUT

v3:
- spell out TF+LUT behavior in the commit and comments (Harry)

Co-developed-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  7 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  8 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   |  7 ++
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    | 72 +++++++++++++++++++
 4 files changed, 94 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index dee35d208493..071cc10bfd90 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -424,6 +424,13 @@ struct amdgpu_mode_info {
 	 * from a combination of pre-defined TF and the custom 1D LUT).
 	 */
 	struct drm_property *plane_blend_tf_property;
+	/* @regamma_tf_property: Transfer function for CRTC regamma
+	 * (post-blending). Possible values are defined by `enum
+	 * amdgpu_transfer_function`. There is no regamma ROM, but we can use
+	 * AMD color modules to program LUT parameters from predefined TF (or
+	 * from a combination of pre-defined TF and the custom 1D LUT).
+	 */
+	struct drm_property *regamma_tf_property;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
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 1b96c742d747..c138457ff12e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -836,6 +836,14 @@ struct dm_crtc_state {
 	struct dc_info_packet vrr_infopacket;
 
 	int abm_level;
+
+        /**
+	 * @regamma_tf:
+	 *
+	 * Pre-defined transfer function for converting internal FB -> wire
+	 * encoding.
+	 */
+	enum amdgpu_transfer_function regamma_tf;
 };
 
 #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
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 82c554662faa..2ecfa0e886e8 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
@@ -294,6 +294,13 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_blend_tf_property = prop;
 
+	prop = amdgpu_create_tf_property(adev_to_drm(adev),
+					 "AMD_CRTC_REGAMMA_TF",
+					 amdgpu_inv_eotf);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.regamma_tf_property = prop;
+
 	return 0;
 }
 #endif
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 440fc0869a34..d746f0aa0f11 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
@@ -253,6 +253,7 @@ static struct drm_crtc_state *dm_crtc_duplicate_state(struct drm_crtc *crtc)
 	state->freesync_config = cur->freesync_config;
 	state->cm_has_degamma = cur->cm_has_degamma;
 	state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
+	state->regamma_tf = cur->regamma_tf;
 	state->crc_skip_count = cur->crc_skip_count;
 	state->mpo_requested = cur->mpo_requested;
 	/* TODO Duplicate dc_stream after objects are stream object is flattened */
@@ -289,6 +290,70 @@ static int amdgpu_dm_crtc_late_register(struct drm_crtc *crtc)
 }
 #endif
 
+#ifdef AMD_PRIVATE_COLOR
+/**
+ * drm_crtc_additional_color_mgmt - enable additional color properties
+ * @crtc: DRM CRTC
+ *
+ * This function lets the driver enable post-blending CRTC regamma transfer
+ * function property in addition to DRM CRTC gamma LUT. Default value means
+ * linear transfer function, which is the default CRTC gamma LUT behaviour
+ * without this property.
+ */
+static void
+dm_crtc_additional_color_mgmt(struct drm_crtc *crtc)
+{
+	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
+
+	if(adev->dm.dc->caps.color.mpc.ogam_ram)
+		drm_object_attach_property(&crtc->base,
+					   adev->mode_info.regamma_tf_property,
+					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
+}
+
+static int
+amdgpu_dm_atomic_crtc_set_property(struct drm_crtc *crtc,
+				   struct drm_crtc_state *state,
+				   struct drm_property *property,
+				   uint64_t val)
+{
+	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
+	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state);
+
+	if (property == adev->mode_info.regamma_tf_property) {
+		if (acrtc_state->regamma_tf != val) {
+			acrtc_state->regamma_tf = val;
+			acrtc_state->base.color_mgmt_changed |= 1;
+		}
+	} else {
+		drm_dbg_atomic(crtc->dev,
+			       "[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
+			       crtc->base.id, crtc->name,
+			       property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+amdgpu_dm_atomic_crtc_get_property(struct drm_crtc *crtc,
+				   const struct drm_crtc_state *state,
+				   struct drm_property *property,
+				   uint64_t *val)
+{
+	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
+	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state);
+
+	if (property == adev->mode_info.regamma_tf_property)
+		*val = acrtc_state->regamma_tf;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+#endif
+
 /* Implemented only the options currently available for the driver */
 static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
 	.reset = dm_crtc_reset_state,
@@ -307,6 +372,10 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
 #if defined(CONFIG_DEBUG_FS)
 	.late_register = amdgpu_dm_crtc_late_register,
 #endif
+#ifdef AMD_PRIVATE_COLOR
+	.atomic_set_property = amdgpu_dm_atomic_crtc_set_property,
+	.atomic_get_property = amdgpu_dm_atomic_crtc_get_property,
+#endif
 };
 
 static void dm_crtc_helper_disable(struct drm_crtc *crtc)
@@ -470,6 +539,9 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
 
 	drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
 
+#ifdef AMD_PRIVATE_COLOR
+	dm_crtc_additional_color_mgmt(&acrtc->base);
+#endif
 	return 0;
 
 fail:
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 13/32] drm/amd/display: add comments to describe DM crtc color mgmt behavior
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (11 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 12/32] drm/amd/display: add CRTC gamma TF driver-specific property Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 14/32] drm/amd/display: encapsulate atomic regamma operation Melissa Wen
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Describe some expected behavior of the AMD DM color mgmt programming.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c  | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

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 2ecfa0e886e8..2b2826a1d855 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
@@ -660,13 +660,25 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
 		crtc->cm_is_degamma_srgb = true;
 		stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS;
 		stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
-
+		/*
+		 * Note: although we pass has_rom as parameter here, we never
+		 * actually use ROM because the color module only takes the ROM
+		 * path if transfer_func->type == PREDEFINED.
+		 *
+		 * See more in mod_color_calculate_regamma_params()
+		 */
 		r = __set_legacy_tf(stream->out_transfer_func, regamma_lut,
 				    regamma_size, has_rom);
 		if (r)
 			return r;
 	} else if (has_regamma) {
-		/* If atomic regamma, CRTC RGM goes into RGM LUT. */
+		/*
+		 * CRTC RGM goes into RGM LUT.
+		 *
+		 * Note: there is no implicit sRGB regamma here. We are using
+		 * degamma calculation from color module to calculate the curve
+		 * from a linear base.
+		 */
 		stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS;
 		stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 14/32] drm/amd/display: encapsulate atomic regamma operation
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (12 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 13/32] drm/amd/display: add comments to describe DM crtc color mgmt behavior Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 15/32] drm/amd/display: add CRTC gamma TF support Melissa Wen
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

We will wire up MPC 3D LUT to DM CRTC color pipeline in the next patch,
but so far, only for atomic interface. By checking
set_output_transfer_func in DC drivers with MPC 3D LUT support, we can
verify that regamma is only programmed when 3D LUT programming fails. As
a groundwork to introduce 3D LUT programming and better understand each
step, detach atomic regamma programming from the crtc colocr updating
code.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 55 ++++++++++++-------
 1 file changed, 35 insertions(+), 20 deletions(-)

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 2b2826a1d855..0487fb715945 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
@@ -524,6 +524,37 @@ static int __set_output_tf(struct dc_transfer_func *func,
 	return res ? 0 : -ENOMEM;
 }
 
+static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream,
+					const struct drm_color_lut *regamma_lut,
+					uint32_t regamma_size, bool has_rom)
+{
+	struct dc_transfer_func *out_tf = stream->out_transfer_func;
+	int ret = 0;
+
+	if (regamma_size) {
+		/*
+		 * CRTC RGM goes into RGM LUT.
+		 *
+		 * Note: there is no implicit sRGB regamma here. We are using
+		 * degamma calculation from color module to calculate the curve
+		 * from a linear base.
+		 */
+		out_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+		out_tf->tf = TRANSFER_FUNCTION_LINEAR;
+
+		ret = __set_output_tf(out_tf, regamma_lut, regamma_size, has_rom);
+	} else {
+		/*
+		 * No CRTC RGM means we can just put the block into bypass
+		 * since we don't have any plane level adjustments using it.
+		 */
+		out_tf->type = TF_TYPE_BYPASS;
+		out_tf->tf = TRANSFER_FUNCTION_LINEAR;
+	}
+
+	return ret;
+}
+
 /**
  * __set_input_tf - calculates the input transfer function based on expected
  * input space.
@@ -671,28 +702,12 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
 				    regamma_size, has_rom);
 		if (r)
 			return r;
-	} else if (has_regamma) {
-		/*
-		 * CRTC RGM goes into RGM LUT.
-		 *
-		 * Note: there is no implicit sRGB regamma here. We are using
-		 * degamma calculation from color module to calculate the curve
-		 * from a linear base.
-		 */
-		stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS;
-		stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
-
-		r = __set_output_tf(stream->out_transfer_func, regamma_lut,
-				    regamma_size, has_rom);
+	} else {
+		regamma_size = has_regamma ? regamma_size : 0;
+		r = amdgpu_dm_set_atomic_regamma(stream, regamma_lut,
+						 regamma_size, has_rom);
 		if (r)
 			return r;
-	} else {
-		/*
-		 * No CRTC RGM means we can just put the block into bypass
-		 * since we don't have any plane level adjustments using it.
-		 */
-		stream->out_transfer_func->type = TF_TYPE_BYPASS;
-		stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
 	}
 
 	/*
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 15/32] drm/amd/display: add CRTC gamma TF support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (13 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 14/32] drm/amd/display: encapsulate atomic regamma operation Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 16/32] drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func Melissa Wen
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Add predefined transfer function programming. There is no post-blending
out gamma ROM for hardcoded curves, but we can use AMD color modules to
program LUT parameters from pre-defined coefficients and an empty
regamma LUT (or bump up LUT parameters with pre-defined TF values).

v2:
- update crtc color mgmt if regamma TF differs between states (Joshua)
- map inverse EOTF to DC transfer function (Melissa)

v3:
- update AMDGPU TF list

v4:
- update comment regarding regamma behavior

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Co-developed-by: Melissa Wen <mwen@igalia.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 77 +++++++++++++++----
 2 files changed, 61 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 7c55b1c0ac5c..846dbeddd0fb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9876,6 +9876,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 	 * when a modeset is needed, to ensure it gets reprogrammed.
 	 */
 	if (dm_new_crtc_state->base.color_mgmt_changed ||
+	    dm_old_crtc_state->regamma_tf != dm_new_crtc_state->regamma_tf ||
 	    drm_atomic_crtc_needs_modeset(new_crtc_state)) {
 		ret = amdgpu_dm_update_crtc_color_mgmt(dm_new_crtc_state);
 		if (ret)
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 0487fb715945..782adb8bea43 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
@@ -489,16 +489,18 @@ static int __set_output_tf(struct dc_transfer_func *func,
 	struct calculate_buffer cal_buffer = {0};
 	bool res;
 
-	ASSERT(lut && lut_size == MAX_COLOR_LUT_ENTRIES);
-
 	cal_buffer.buffer_index = -1;
 
-	gamma = dc_create_gamma();
-	if (!gamma)
-		return -ENOMEM;
+	if (lut_size) {
+		ASSERT(lut && lut_size == MAX_COLOR_LUT_ENTRIES);
 
-	gamma->num_entries = lut_size;
-	__drm_lut_to_dc_gamma(lut, gamma, false);
+		gamma = dc_create_gamma();
+		if (!gamma)
+			return -ENOMEM;
+
+		gamma->num_entries = lut_size;
+		__drm_lut_to_dc_gamma(lut, gamma, false);
+	}
 
 	if (func->tf == TRANSFER_FUNCTION_LINEAR) {
 		/*
@@ -506,41 +508,49 @@ static int __set_output_tf(struct dc_transfer_func *func,
 		 * on top of a linear input. But degamma params can be used
 		 * instead to simulate this.
 		 */
-		gamma->type = GAMMA_CUSTOM;
+		if (gamma)
+			gamma->type = GAMMA_CUSTOM;
 		res = mod_color_calculate_degamma_params(NULL, func,
-							gamma, true);
+							 gamma, gamma != NULL);
 	} else {
 		/*
 		 * Assume sRGB. The actual mapping will depend on whether the
 		 * input was legacy or not.
 		 */
-		gamma->type = GAMMA_CS_TFM_1D;
-		res = mod_color_calculate_regamma_params(func, gamma, false,
+		if (gamma)
+			gamma->type = GAMMA_CS_TFM_1D;
+		res = mod_color_calculate_regamma_params(func, gamma, gamma != NULL,
 							 has_rom, NULL, &cal_buffer);
 	}
 
-	dc_gamma_release(&gamma);
+	if (gamma)
+		dc_gamma_release(&gamma);
 
 	return res ? 0 : -ENOMEM;
 }
 
 static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream,
 					const struct drm_color_lut *regamma_lut,
-					uint32_t regamma_size, bool has_rom)
+					uint32_t regamma_size, bool has_rom,
+					enum dc_transfer_func_predefined tf)
 {
 	struct dc_transfer_func *out_tf = stream->out_transfer_func;
 	int ret = 0;
 
-	if (regamma_size) {
+	if (regamma_size || tf != TRANSFER_FUNCTION_LINEAR) {
 		/*
 		 * CRTC RGM goes into RGM LUT.
 		 *
 		 * Note: there is no implicit sRGB regamma here. We are using
 		 * degamma calculation from color module to calculate the curve
-		 * from a linear base.
+		 * from a linear base if gamma TF is not set. However, if gamma
+		 * TF (!= Linear) and LUT are set at the same time, we will use
+		 * regamma calculation, and the color module will combine the
+		 * pre-defined TF and the custom LUT values into the LUT that's
+		 * actually programmed.
 		 */
 		out_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
-		out_tf->tf = TRANSFER_FUNCTION_LINEAR;
+		out_tf->tf = tf;
 
 		ret = __set_output_tf(out_tf, regamma_lut, regamma_size, has_rom);
 	} else {
@@ -586,6 +596,36 @@ static int __set_input_tf(struct dc_transfer_func *func,
 	return res ? 0 : -ENOMEM;
 }
 
+static enum dc_transfer_func_predefined
+amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
+{
+	switch (tf)
+	{
+	default:
+	case AMDGPU_TRANSFER_FUNCTION_DEFAULT:
+	case AMDGPU_TRANSFER_FUNCTION_IDENTITY:
+		return TRANSFER_FUNCTION_LINEAR;
+	case AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF:
+	case AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF:
+		return TRANSFER_FUNCTION_SRGB;
+	case AMDGPU_TRANSFER_FUNCTION_BT709_OETF:
+	case AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF:
+		return TRANSFER_FUNCTION_BT709;
+	case AMDGPU_TRANSFER_FUNCTION_PQ_EOTF:
+	case AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF:
+		return TRANSFER_FUNCTION_PQ;
+	case AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF:
+	case AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF:
+		return TRANSFER_FUNCTION_GAMMA22;
+	case AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF:
+	case AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF:
+		return TRANSFER_FUNCTION_GAMMA24;
+	case AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF:
+	case AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF:
+		return TRANSFER_FUNCTION_GAMMA26;
+	}
+}
+
 /**
  * amdgpu_dm_verify_lut_sizes - verifies if DRM luts match the hw supported sizes
  * @crtc_state: the DRM CRTC state
@@ -653,9 +693,12 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
 	const struct drm_color_lut *degamma_lut, *regamma_lut;
 	uint32_t degamma_size, regamma_size;
 	bool has_regamma, has_degamma;
+	enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_LINEAR;
 	bool is_legacy;
 	int r;
 
+	tf = amdgpu_tf_to_dc_tf(crtc->regamma_tf);
+
 	r = amdgpu_dm_verify_lut_sizes(&crtc->base);
 	if (r)
 		return r;
@@ -705,7 +748,7 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
 	} else {
 		regamma_size = has_regamma ? regamma_size : 0;
 		r = amdgpu_dm_set_atomic_regamma(stream, regamma_lut,
-						 regamma_size, has_rom);
+						 regamma_size, has_rom, tf);
 		if (r)
 			return r;
 	}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 16/32] drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (14 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 15/32] drm/amd/display: add CRTC gamma TF support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 17/32] drm/amd/display: mark plane as needing reset if color props change Melissa Wen
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Otherwise this is just initialized to 0. This needs to actually have a
value so that compute_curve can work for PQ EOTF.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Co-developed-by: Melissa Wen <mwen@igalia.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 2 ++
 1 file changed, 2 insertions(+)

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 782adb8bea43..e81263d60b7d 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
@@ -72,6 +72,7 @@
  */
 
 #define MAX_DRM_LUT_VALUE 0xFFFF
+#define SDR_WHITE_LEVEL_INIT_VALUE 80
 
 /**
  * amdgpu_dm_init_color_mod - Initialize the color module.
@@ -551,6 +552,7 @@ static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream,
 		 */
 		out_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
 		out_tf->tf = tf;
+		out_tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
 
 		ret = __set_output_tf(out_tf, regamma_lut, regamma_size, has_rom);
 	} else {
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 17/32] drm/amd/display: mark plane as needing reset if color props change
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (15 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 16/32] drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 18/32] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane Melissa Wen
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

We should reset a plane state if at least one of the color management
properties differs from old and new state.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Co-developed-by: Melissa Wen <mwen@igalia.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 846dbeddd0fb..d44fd8cb6edf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9944,6 +9944,10 @@ static bool should_reset_plane(struct drm_atomic_state *state,
 	 */
 	for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) {
 		struct amdgpu_framebuffer *old_afb, *new_afb;
+		struct dm_plane_state *dm_new_other_state, *dm_old_other_state;
+
+		dm_new_other_state = to_dm_plane_state(new_other_state);
+		dm_old_other_state = to_dm_plane_state(old_other_state);
 
 		if (other->type == DRM_PLANE_TYPE_CURSOR)
 			continue;
@@ -9980,6 +9984,17 @@ static bool should_reset_plane(struct drm_atomic_state *state,
 		    old_other_state->color_encoding != new_other_state->color_encoding)
 			return true;
 
+		/* HDR/Transfer Function changes. */
+		if (dm_old_other_state->degamma_tf != dm_new_other_state->degamma_tf ||
+		    dm_old_other_state->degamma_lut != dm_new_other_state->degamma_lut ||
+		    dm_old_other_state->hdr_mult != dm_new_other_state->hdr_mult ||
+		    dm_old_other_state->shaper_lut != dm_new_other_state->shaper_lut ||
+		    dm_old_other_state->shaper_tf != dm_new_other_state->shaper_tf ||
+		    dm_old_other_state->lut3d != dm_new_other_state->lut3d ||
+		    dm_old_other_state->blend_lut != dm_new_other_state->blend_lut ||
+		    dm_old_other_state->blend_tf != dm_new_other_state->blend_tf)
+			return true;
+
 		/* Framebuffer checks fall at the end. */
 		if (!old_other_state->fb || !new_other_state->fb)
 			continue;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 18/32] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (16 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 17/32] drm/amd/display: mark plane as needing reset if color props change Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 19/32] drm/amd/display: add plane degamma TF and LUT support Melissa Wen
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

The next patch adds pre-blending degamma to AMD color mgmt pipeline, but
pre-blending degamma caps (DPP) is currently in use to provide DRM CRTC
atomic degamma or implict degamma on legacy gamma. Detach degamma usage
regarging CRTC color properties to manage plane and CRTC color
correction combinations.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 60 +++++++++++++------
 1 file changed, 42 insertions(+), 18 deletions(-)

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 e81263d60b7d..ffdf493b8ef2 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
@@ -788,20 +788,9 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
 	return 0;
 }
 
-/**
- * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane.
- * @crtc: amdgpu_dm crtc state
- * @dc_plane_state: target DC surface
- *
- * Update the underlying dc_stream_state's input transfer function (ITF) in
- * preparation for hardware commit. The transfer function used depends on
- * the preparation done on the stream for color management.
- *
- * Returns:
- * 0 on success. -ENOMEM if mem allocation fails.
- */
-int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
-				      struct dc_plane_state *dc_plane_state)
+static int
+map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
+			     struct dc_plane_state *dc_plane_state)
 {
 	const struct drm_color_lut *degamma_lut;
 	enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB;
@@ -824,8 +813,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 						 &degamma_size);
 		ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES);
 
-		dc_plane_state->in_transfer_func->type =
-			TF_TYPE_DISTRIBUTED_POINTS;
+		dc_plane_state->in_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS;
 
 		/*
 		 * This case isn't fully correct, but also fairly
@@ -861,7 +849,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 				   degamma_lut, degamma_size);
 		if (r)
 			return r;
-	} else if (crtc->cm_is_degamma_srgb) {
+	} else {
 		/*
 		 * For legacy gamma support we need the regamma input
 		 * in linear space. Assume that the input is sRGB.
@@ -871,8 +859,44 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 
 		if (tf != TRANSFER_FUNCTION_SRGB &&
 		    !mod_color_calculate_degamma_params(NULL,
-			    dc_plane_state->in_transfer_func, NULL, false))
+							dc_plane_state->in_transfer_func,
+							NULL, false))
 			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
+ * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane.
+ * @crtc: amdgpu_dm crtc state
+ * @dc_plane_state: target DC surface
+ *
+ * Update the underlying dc_stream_state's input transfer function (ITF) in
+ * preparation for hardware commit. The transfer function used depends on
+ * the preparation done on the stream for color management.
+ *
+ * Returns:
+ * 0 on success. -ENOMEM if mem allocation fails.
+ */
+int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
+				      struct dc_plane_state *dc_plane_state)
+{
+	bool has_crtc_cm_degamma;
+	int ret;
+
+	has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb);
+	if (has_crtc_cm_degamma){
+		/*
+		 * AMD HW doesn't have post-blending degamma caps. When DRM
+		 * CRTC atomic degamma is set, we maps it to DPP degamma block
+		 * (pre-blending) or, on legacy gamma, we use DPP degamma to
+		 * linearize (implicit degamma) from sRGB/BT709 according to
+		 * the input space.
+		 */
+		ret = map_crtc_degamma_to_dc_plane(crtc, dc_plane_state);
+		if (ret)
+			return ret;
 	} else {
 		/* ...Otherwise we can just bypass the DGM block. */
 		dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 19/32] drm/amd/display: add plane degamma TF and LUT support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (17 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 18/32] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 20/32] drm/amd/display: reject atomic commit if setting both plane and CRTC degamma Melissa Wen
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Set DC plane with user degamma LUT or predefined TF from driver-specific
plane color properties. If plane and CRTC degamma are set in the same
time, plane degamma has priority.  That means, we only set CRTC degamma
if we don't have plane degamma LUT or TF to configure. We return -EINVAL
if we don't have plane degamma settings, so we can continue and check
CRTC degamma.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  4 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 70 +++++++++++++++++--
 3 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d44fd8cb6edf..a8a1690b7322 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5191,7 +5191,9 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
 	 * Always set input transfer function, since plane state is refreshed
 	 * every time.
 	 */
-	ret = amdgpu_dm_update_plane_color_mgmt(dm_crtc_state, dc_plane_state);
+	ret = amdgpu_dm_update_plane_color_mgmt(dm_crtc_state,
+						plane_state,
+						dc_plane_state);
 	if (ret)
 		return ret;
 
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 c138457ff12e..c5ec6e4f15c2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -918,6 +918,7 @@ int amdgpu_dm_create_color_properties(struct amdgpu_device *adev);
 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_update_plane_color_mgmt(struct dm_crtc_state *crtc,
+				      struct drm_plane_state *plane_state,
 				      struct dc_plane_state *dc_plane_state);
 
 void amdgpu_dm_update_connector_after_detect(
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 ffdf493b8ef2..6acc9ebc52da 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
@@ -867,9 +867,58 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
 	return 0;
 }
 
+static int
+__set_dm_plane_degamma(struct drm_plane_state *plane_state,
+		       struct dc_plane_state *dc_plane_state)
+{
+	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+	const struct drm_color_lut *degamma_lut;
+	enum amdgpu_transfer_function tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
+	uint32_t degamma_size;
+	bool has_degamma_lut;
+	int ret;
+
+	degamma_lut = __extract_blob_lut(dm_plane_state->degamma_lut,
+					 &degamma_size);
+
+	has_degamma_lut = degamma_lut &&
+			  !__is_lut_linear(degamma_lut, degamma_size);
+
+	tf = dm_plane_state->degamma_tf;
+
+	/* If we don't have plane degamma LUT nor TF to set on DC, we have
+	 * nothing to do here, return.
+	 */
+	if (!has_degamma_lut && tf == AMDGPU_TRANSFER_FUNCTION_DEFAULT)
+		return -EINVAL;
+
+	dc_plane_state->in_transfer_func->tf = amdgpu_tf_to_dc_tf(tf);
+
+	if (has_degamma_lut) {
+		ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES);
+
+		dc_plane_state->in_transfer_func->type =
+			TF_TYPE_DISTRIBUTED_POINTS;
+
+		ret = __set_input_tf(dc_plane_state->in_transfer_func,
+				     degamma_lut, degamma_size);
+		if (ret)
+			return ret;
+       } else {
+		dc_plane_state->in_transfer_func->type =
+			TF_TYPE_PREDEFINED;
+
+		if (!mod_color_calculate_degamma_params(NULL,
+		    dc_plane_state->in_transfer_func, NULL, false))
+			return -ENOMEM;
+	}
+	return 0;
+}
+
 /**
  * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane.
  * @crtc: amdgpu_dm crtc state
+ * @plane_state: DRM plane state
  * @dc_plane_state: target DC surface
  *
  * Update the underlying dc_stream_state's input transfer function (ITF) in
@@ -880,13 +929,28 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
  * 0 on success. -ENOMEM if mem allocation fails.
  */
 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)
 {
 	bool has_crtc_cm_degamma;
 	int ret;
 
+	/* Initially, we can just bypass the DGM block. */
+	dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
+	dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
+
+	/* After, we start to update values according to color props */
 	has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb);
-	if (has_crtc_cm_degamma){
+
+	ret = __set_dm_plane_degamma(plane_state, dc_plane_state);
+	if (ret != -EINVAL)
+		return ret;
+
+	/* If we are here, it means we don't have plane degamma settings, check
+	 * if we have CRTC degamma waiting for mapping to pre-blending degamma
+	 * block
+	 */
+	if (has_crtc_cm_degamma) {
 		/*
 		 * AMD HW doesn't have post-blending degamma caps. When DRM
 		 * CRTC atomic degamma is set, we maps it to DPP degamma block
@@ -897,10 +961,6 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 		ret = map_crtc_degamma_to_dc_plane(crtc, dc_plane_state);
 		if (ret)
 			return ret;
-	} else {
-		/* ...Otherwise we can just bypass the DGM block. */
-		dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
-		dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
 	}
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 20/32] drm/amd/display: reject atomic commit if setting both plane and CRTC degamma
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (18 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 19/32] drm/amd/display: add plane degamma TF and LUT support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 21/32] drm/amd/display: add dc_fixpt_from_s3132 helper Melissa Wen
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

DC only has pre-blending degamma caps (plane/DPP) that is currently in
use for CRTC/post-blending degamma, so that we don't have HW caps to
perform plane and CRTC degamma at the same time. Reject atomic updates
when serspace sets both plane and CRTC degamma properties.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

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 6acc9ebc52da..354ab46894d2 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
@@ -943,9 +943,20 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 	has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb);
 
 	ret = __set_dm_plane_degamma(plane_state, dc_plane_state);
-	if (ret != -EINVAL)
+	if (ret == -ENOMEM)
 		return ret;
 
+	/* We only have one degamma block available (pre-blending) for the
+	 * whole color correction pipeline, so that we can't actually perform
+	 * plane and CRTC degamma at the same time. Explicitly reject atomic
+	 * updates when userspace sets both plane and CRTC degamma properties.
+	 */
+	if (has_crtc_cm_degamma && ret != -EINVAL){
+		drm_dbg_kms(crtc->base.crtc->dev,
+			    "doesn't support plane and CRTC degamma at the same time\n");
+			return -EINVAL;
+	}
+
 	/* If we are here, it means we don't have plane degamma settings, check
 	 * if we have CRTC degamma waiting for mapping to pre-blending degamma
 	 * block
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 21/32] drm/amd/display: add dc_fixpt_from_s3132 helper
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (19 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 20/32] drm/amd/display: reject atomic commit if setting both plane and CRTC degamma Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 22/32] drm/amd/display: add HDR multiplier support Melissa Wen
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Detach value translation from CTM to reuse it for programming HDR
multiplier property.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c  |  8 +-------
 drivers/gpu/drm/amd/display/include/fixed31_32.h     | 12 ++++++++++++
 2 files changed, 13 insertions(+), 7 deletions(-)

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 354ab46894d2..599bba566226 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
@@ -404,7 +404,6 @@ static void __drm_lut_to_dc_gamma(const struct drm_color_lut *lut,
 static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm,
 				   struct fixed31_32 *matrix)
 {
-	int64_t val;
 	int i;
 
 	/*
@@ -423,12 +422,7 @@ static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm,
 		}
 
 		/* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */
-		val = ctm->matrix[i - (i / 4)];
-		/* If negative, convert to 2's complement. */
-		if (val & (1ULL << 63))
-			val = -(val & ~(1ULL << 63));
-
-		matrix[i].value = val;
+		matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i - (i / 4)]);
 	}
 }
 
diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h
index d4cf7ead1d87..84da1dd34efd 100644
--- a/drivers/gpu/drm/amd/display/include/fixed31_32.h
+++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h
@@ -69,6 +69,18 @@ static const struct fixed31_32 dc_fixpt_epsilon = { 1LL };
 static const struct fixed31_32 dc_fixpt_half = { 0x80000000LL };
 static const struct fixed31_32 dc_fixpt_one = { 0x100000000LL };
 
+static inline struct fixed31_32 dc_fixpt_from_s3132(__u64 x)
+{
+	struct fixed31_32 val;
+
+	/* If negative, convert to 2's complement. */
+	if (x & (1ULL << 63))
+		x = -(x & ~(1ULL << 63));
+
+	val.value = x;
+	return val;
+}
+
 /*
  * @brief
  * Initialization routines
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 22/32] drm/amd/display: add HDR multiplier support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (20 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 21/32] drm/amd/display: add dc_fixpt_from_s3132 helper Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 23/32] drm/amd/display: add plane shaper LUT support Melissa Wen
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

With `dc_fixpt_from_s3132()` translation, we can just use it to set
hdr_mult.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c       | 1 +
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a8a1690b7322..ded52dd780c8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8286,6 +8286,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			bundle->surface_updates[planes_count].gamma = dc_plane->gamma_correction;
 			bundle->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func;
 			bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
+			bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult;
 		}
 
 		amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_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 599bba566226..849e07dd436a 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
@@ -926,6 +926,7 @@ 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)
 {
+	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
 	bool has_crtc_cm_degamma;
 	int ret;
 
@@ -936,6 +937,8 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 	/* After, we start to update values according to color props */
 	has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb);
 
+	dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult);
+
 	ret = __set_dm_plane_degamma(plane_state, dc_plane_state);
 	if (ret == -ENOMEM)
 		return ret;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 23/32] drm/amd/display: add plane shaper LUT support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (21 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 22/32] drm/amd/display: add HDR multiplier support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 24/32] drm/amd/display: add plane shaper TF support Melissa Wen
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Map DC shaper LUT to DM plane color management. Shaper LUT can be used
to delinearize and/or normalize the color space for computational
efficiency and achiving specific visual styles. If a plane degamma is
apply to linearize the color space, a custom shaper 1D LUT can be used
just before applying 3D LUT.

v2:
- use DPP color caps to verify plane 3D LUT support
- add debug message if shaper LUT programming fails

v4:
- remove helper to check 3D LUT color caps (Harry)
- update desc of lut3d-setup helper from MPC to DPP

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  1 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 97 ++++++++++++++++++-
 3 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index ded52dd780c8..c79cd98d1228 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8287,6 +8287,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			bundle->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func;
 			bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
 			bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult;
+			bundle->surface_updates[planes_count].func_shaper = dc_plane->in_shaper_func;
 		}
 
 		amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state,
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 c5ec6e4f15c2..219efa7fe181 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -908,6 +908,8 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
 /* 3D LUT max size is 17x17x17 (4913 entries) */
 #define MAX_COLOR_3DLUT_SIZE 17
 #define MAX_COLOR_3DLUT_BITDEPTH 12
+int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
+				struct drm_plane_state *plane_state);
 /* 1D LUT size */
 #define MAX_COLOR_LUT_ENTRIES 4096
 /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
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 849e07dd436a..1d18f447f387 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
@@ -622,6 +622,63 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
 	}
 }
 
+static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
+				       uint32_t shaper_size,
+				       struct dc_transfer_func *func_shaper)
+{
+	int ret = 0;
+
+	if (shaper_size) {
+		/*
+		 * If user shaper LUT is set, we assume a linear color space
+		 * (linearized by degamma 1D LUT or not).
+		 */
+		func_shaper->type = TF_TYPE_DISTRIBUTED_POINTS;
+		func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
+
+		ret = __set_output_tf(func_shaper, shaper_lut, shaper_size, false);
+	} else {
+		func_shaper->type = TF_TYPE_BYPASS;
+		func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
+	}
+
+	return ret;
+}
+
+/**
+ * amdgpu_dm_verify_lut3d_size - verifies if 3D LUT is supported and if user
+ * shaper and 3D LUTs match the hw supported size
+ * @adev: amdgpu device
+ * @crtc_state: the DRM CRTC state
+ *
+ * Verifies if pre-blending (DPP) 3D LUT is supported by the HW (DCN 2.0 or
+ * newer) and if the user shaper and 3D LUTs match the supported size.
+ *
+ * Returns:
+ * 0 on success. -EINVAL if lut size are invalid.
+ */
+int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
+				struct drm_plane_state *plane_state)
+{
+	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+	const struct drm_color_lut *shaper = NULL;
+	uint32_t exp_size, size;
+	bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut;
+
+	/* shaper LUT is only available if 3D LUT color caps */
+	exp_size = has_3dlut ? MAX_COLOR_LUT_ENTRIES : 0;
+	shaper = __extract_blob_lut(dm_plane_state->shaper_lut, &size);
+
+	if (shaper && size != exp_size) {
+		drm_dbg(&adev->ddev,
+			"Invalid Shaper LUT size. Should be %u but got %u.\n",
+			exp_size, size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * amdgpu_dm_verify_lut_sizes - verifies if DRM luts match the hw supported sizes
  * @crtc_state: the DRM CRTC state
@@ -909,6 +966,34 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
 	return 0;
 }
 
+static int
+amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
+				     struct dc_plane_state *dc_plane_state)
+{
+	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+	const struct drm_color_lut *shaper_lut;
+	uint32_t shaper_size;
+	int ret;
+
+	/* We have nothing to do here, return */
+	if (!plane_state->color_mgmt_changed)
+		return 0;
+
+	dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult);
+
+	shaper_lut = __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_size);
+	shaper_size = shaper_lut != NULL ? shaper_size : 0;
+
+	ret = amdgpu_dm_atomic_shaper_lut(shaper_lut, shaper_size,
+					  dc_plane_state->in_shaper_func);
+	if (ret)
+		drm_dbg_kms(plane_state->plane->dev,
+			    "setting plane %d shaper LUT failed.\n",
+			    plane_state->plane->index);
+
+	return ret;
+}
+
 /**
  * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane.
  * @crtc: amdgpu_dm crtc state
@@ -926,10 +1011,16 @@ 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)
 {
-	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+	struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev);
 	bool has_crtc_cm_degamma;
 	int ret;
 
+	ret = amdgpu_dm_verify_lut3d_size(adev, plane_state);
+	if (ret) {
+		drm_dbg_driver(&adev->ddev, "amdgpu_dm_verify_lut3d_size() failed\n");
+		return ret;
+	}
+
 	/* Initially, we can just bypass the DGM block. */
 	dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
 	dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
@@ -937,8 +1028,6 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 	/* After, we start to update values according to color props */
 	has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb);
 
-	dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult);
-
 	ret = __set_dm_plane_degamma(plane_state, dc_plane_state);
 	if (ret == -ENOMEM)
 		return ret;
@@ -971,5 +1060,5 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 			return ret;
 	}
 
-	return 0;
+	return amdgpu_dm_plane_set_color_properties(plane_state, dc_plane_state);
 }
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 24/32] drm/amd/display: add plane shaper TF support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (22 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 23/32] drm/amd/display: add plane shaper LUT support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 25/32] drm/amd/display: add plane 3D LUT support Melissa Wen
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Enable usage of predefined transfer func in addition to shaper 1D LUT.
That means we can save some complexity by just setting a predefined
curve, instead of programming a custom curve when preparing color space
for applying 3D LUT.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c   | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

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 1d18f447f387..0e65bf0a886e 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
@@ -623,20 +623,23 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
 }
 
 static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
+				       bool has_rom,
+				       enum dc_transfer_func_predefined tf,
 				       uint32_t shaper_size,
 				       struct dc_transfer_func *func_shaper)
 {
 	int ret = 0;
 
-	if (shaper_size) {
+	if (shaper_size || tf != TRANSFER_FUNCTION_LINEAR) {
 		/*
 		 * If user shaper LUT is set, we assume a linear color space
 		 * (linearized by degamma 1D LUT or not).
 		 */
 		func_shaper->type = TF_TYPE_DISTRIBUTED_POINTS;
-		func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
+		func_shaper->tf = tf;
+		func_shaper->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
 
-		ret = __set_output_tf(func_shaper, shaper_lut, shaper_size, false);
+		ret = __set_output_tf(func_shaper, shaper_lut, shaper_size, has_rom);
 	} else {
 		func_shaper->type = TF_TYPE_BYPASS;
 		func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
@@ -971,6 +974,7 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 				     struct dc_plane_state *dc_plane_state)
 {
 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+	enum amdgpu_transfer_function shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
 	const struct drm_color_lut *shaper_lut;
 	uint32_t shaper_size;
 	int ret;
@@ -983,8 +987,11 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 
 	shaper_lut = __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_size);
 	shaper_size = shaper_lut != NULL ? shaper_size : 0;
+	shaper_tf = dm_plane_state->shaper_tf;
 
-	ret = amdgpu_dm_atomic_shaper_lut(shaper_lut, shaper_size,
+	ret = amdgpu_dm_atomic_shaper_lut(shaper_lut, false,
+					  amdgpu_tf_to_dc_tf(shaper_tf),
+					  shaper_size,
 					  dc_plane_state->in_shaper_func);
 	if (ret)
 		drm_dbg_kms(plane_state->plane->dev,
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 25/32] drm/amd/display: add plane 3D LUT support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (23 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 24/32] drm/amd/display: add plane shaper TF support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 26/32] drm/amd/display: handle empty LUTs in __set_input_tf Melissa Wen
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Wire up DC 3D LUT to DM plane color management (pre-blending). On AMD
display HW, 3D LUT comes after a shaper curve and we always have to
program a shaper curve to delinearize or normalize the color space
before applying a 3D LUT (since we have a reduced number of LUT
entries).

In this version, the default values of 3D LUT for size and bit_depth are
17x17x17 and 12-bit, but we already provide here a more generic
mechanisms to program other supported values (9x9x9 size and 10-bit).

v2:
- started with plane 3D LUT instead of CRTC 3D LUT support

v4:
- lut3d_size is the max dimension size instead of # of entries

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 102 +++++++++++++++++-
 2 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c79cd98d1228..26d19159bd79 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8288,6 +8288,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
 			bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult;
 			bundle->surface_updates[planes_count].func_shaper = dc_plane->in_shaper_func;
+			bundle->surface_updates[planes_count].lut3d_func = dc_plane->lut3d_func;
 		}
 
 		amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_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 0e65bf0a886e..9c38291c42a2 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
@@ -622,6 +622,86 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
 	}
 }
 
+static void __to_dc_lut3d_color(struct dc_rgb *rgb,
+				const struct drm_color_lut lut,
+				int bit_precision)
+{
+	rgb->red = drm_color_lut_extract(lut.red, bit_precision);
+	rgb->green = drm_color_lut_extract(lut.green, bit_precision);
+	rgb->blue  = drm_color_lut_extract(lut.blue, bit_precision);
+}
+
+static void __drm_3dlut_to_dc_3dlut(const struct drm_color_lut *lut,
+				    uint32_t lut3d_size,
+				    struct tetrahedral_params *params,
+				    bool use_tetrahedral_9,
+				    int bit_depth)
+{
+	struct dc_rgb *lut0;
+	struct dc_rgb *lut1;
+	struct dc_rgb *lut2;
+	struct dc_rgb *lut3;
+	int lut_i, i;
+
+
+	if (use_tetrahedral_9) {
+		lut0 = params->tetrahedral_9.lut0;
+		lut1 = params->tetrahedral_9.lut1;
+		lut2 = params->tetrahedral_9.lut2;
+		lut3 = params->tetrahedral_9.lut3;
+	} else {
+		lut0 = params->tetrahedral_17.lut0;
+		lut1 = params->tetrahedral_17.lut1;
+		lut2 = params->tetrahedral_17.lut2;
+		lut3 = params->tetrahedral_17.lut3;
+	}
+
+	for (lut_i = 0, i = 0; i < lut3d_size - 4; lut_i++, i += 4) {
+		/*
+		 * We should consider the 3D LUT RGB values are distributed
+		 * along four arrays lut0-3 where the first sizes 1229 and the
+		 * other 1228. The bit depth supported for 3dlut channel is
+		 * 12-bit, but DC also supports 10-bit.
+		 *
+		 * TODO: improve color pipeline API to enable the userspace set
+		 * bit depth and 3D LUT size/stride, as specified by VA-API.
+		 */
+		__to_dc_lut3d_color(&lut0[lut_i], lut[i], bit_depth);
+		__to_dc_lut3d_color(&lut1[lut_i], lut[i + 1], bit_depth);
+		__to_dc_lut3d_color(&lut2[lut_i], lut[i + 2], bit_depth);
+		__to_dc_lut3d_color(&lut3[lut_i], lut[i + 3], bit_depth);
+	}
+	/* lut0 has 1229 points (lut_size/4 + 1) */
+	__to_dc_lut3d_color(&lut0[lut_i], lut[i], bit_depth);
+}
+
+/* amdgpu_dm_atomic_lut3d - set DRM 3D LUT to DC stream
+ * @drm_lut3d: user 3D LUT
+ * @drm_lut3d_size: size of 3D LUT
+ * @lut3d: DC 3D LUT
+ *
+ * Map user 3D LUT data to DC 3D LUT and all necessary bits to program it
+ * on DCN accordingly.
+ */
+static void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut3d,
+				   uint32_t drm_lut3d_size,
+				   struct dc_3dlut *lut)
+{
+	if (!drm_lut3d_size) {
+		lut->state.bits.initialized = 0;
+	} else {
+		/* Stride and bit depth are not programmable by API yet.
+		 * Therefore, only supports 17x17x17 3D LUT (12-bit).
+		 */
+		lut->lut_3d.use_tetrahedral_9 = false;
+		lut->lut_3d.use_12bits = true;
+		lut->state.bits.initialized = 1;
+		__drm_3dlut_to_dc_3dlut(drm_lut3d, drm_lut3d_size, &lut->lut_3d,
+					lut->lut_3d.use_tetrahedral_9,
+					MAX_COLOR_3DLUT_BITDEPTH);
+	}
+}
+
 static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
 				       bool has_rom,
 				       enum dc_transfer_func_predefined tf,
@@ -664,8 +744,8 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
 				struct drm_plane_state *plane_state)
 {
 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
-	const struct drm_color_lut *shaper = NULL;
-	uint32_t exp_size, size;
+	const struct drm_color_lut *shaper = NULL, *lut3d = NULL;
+	uint32_t exp_size, size, dim_size = MAX_COLOR_3DLUT_SIZE;
 	bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut;
 
 	/* shaper LUT is only available if 3D LUT color caps */
@@ -679,6 +759,17 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
 		return -EINVAL;
 	}
 
+	/* The number of 3D LUT entries is the dimension size cubed */
+	exp_size = has_3dlut ? dim_size * dim_size * dim_size : 0;
+	lut3d = __extract_blob_lut(dm_plane_state->lut3d, &size);
+
+	if (lut3d && size != exp_size) {
+		drm_dbg(&adev->ddev,
+			"Invalid 3D LUT size. Should be %u but got %u.\n",
+			exp_size, size);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -975,8 +1066,8 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 {
 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
 	enum amdgpu_transfer_function shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
-	const struct drm_color_lut *shaper_lut;
-	uint32_t shaper_size;
+	const struct drm_color_lut *shaper_lut, *lut3d;
+	uint32_t shaper_size, lut3d_size;
 	int ret;
 
 	/* We have nothing to do here, return */
@@ -988,7 +1079,10 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 	shaper_lut = __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_size);
 	shaper_size = shaper_lut != NULL ? shaper_size : 0;
 	shaper_tf = dm_plane_state->shaper_tf;
+	lut3d = __extract_blob_lut(dm_plane_state->lut3d, &lut3d_size);
+	lut3d_size = lut3d != NULL ? lut3d_size : 0;
 
+	amdgpu_dm_atomic_lut3d(lut3d, lut3d_size, dc_plane_state->lut3d_func);
 	ret = amdgpu_dm_atomic_shaper_lut(shaper_lut, false,
 					  amdgpu_tf_to_dc_tf(shaper_tf),
 					  shaper_size,
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 26/32] drm/amd/display: handle empty LUTs in __set_input_tf
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (24 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 25/32] drm/amd/display: add plane 3D LUT support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 27/32] drm/amd/display: add plane blend LUT and TF support Melissa Wen
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Unlike degamma, blend gamma doesn't support hardcoded curve
(predefined/ROM), but we can use AMD color module to fill blend gamma
parameters when we have non-linear plane gamma TF without plane gamma
LUT. The regular degamma path doesn't hit this.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 20 +++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

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 9c38291c42a2..25e9aa147e00 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
@@ -577,17 +577,21 @@ static int __set_input_tf(struct dc_transfer_func *func,
 	struct dc_gamma *gamma = NULL;
 	bool res;
 
-	gamma = dc_create_gamma();
-	if (!gamma)
-		return -ENOMEM;
+	if (lut_size) {
+		gamma = dc_create_gamma();
+		if (!gamma)
+			return -ENOMEM;
 
-	gamma->type = GAMMA_CUSTOM;
-	gamma->num_entries = lut_size;
+		gamma->type = GAMMA_CUSTOM;
+		gamma->num_entries = lut_size;
 
-	__drm_lut_to_dc_gamma(lut, gamma, false);
+		__drm_lut_to_dc_gamma(lut, gamma, false);
+	}
 
-	res = mod_color_calculate_degamma_params(NULL, func, gamma, true);
-	dc_gamma_release(&gamma);
+	res = mod_color_calculate_degamma_params(NULL, func, gamma, gamma != NULL);
+
+	if (gamma)
+		dc_gamma_release(&gamma);
 
 	return res ? 0 : -ENOMEM;
 }
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 27/32] drm/amd/display: add plane blend LUT and TF support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (25 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 26/32] drm/amd/display: handle empty LUTs in __set_input_tf Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 28/32] drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG Melissa Wen
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Map plane blend properties to DPP blend gamma. Plane blend is a
post-3D LUT curve that linearizes color space for blending. It may be
defined by a user-blob LUT and/or predefined transfer function. As
hardcoded curve (ROM) is not supported on blend gamma, we use AMD color
module to fill parameters when setting non-linear TF with empty LUT.

v2:
- rename DRM TFs to AMDGPU TFs

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 56 +++++++++++++++++--
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 26d19159bd79..4b4181447df9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8289,6 +8289,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult;
 			bundle->surface_updates[planes_count].func_shaper = dc_plane->in_shaper_func;
 			bundle->surface_updates[planes_count].lut3d_func = dc_plane->lut3d_func;
+			bundle->surface_updates[planes_count].blend_tf = dc_plane->blend_tf;
 		}
 
 		amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_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 25e9aa147e00..0909ed5639bf 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
@@ -732,6 +732,35 @@ static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
 	return ret;
 }
 
+static int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
+				       bool has_rom,
+				       enum dc_transfer_func_predefined tf,
+				       uint32_t blend_size,
+				       struct dc_transfer_func *func_blend)
+{
+	int ret = 0;
+
+	if (blend_size || tf != TRANSFER_FUNCTION_LINEAR) {
+		/*
+		 * DRM plane gamma LUT or TF means we are linearizing color
+		 * space before blending (similar to degamma programming). As
+		 * we don't have hardcoded curve support, or we use AMD color
+		 * module to fill the parameters that will be translated to HW
+		 * points.
+		 */
+		func_blend->type = TF_TYPE_DISTRIBUTED_POINTS;
+		func_blend->tf = tf;
+		func_blend->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+
+		ret = __set_input_tf(func_blend, blend_lut, blend_size);
+	} else {
+		func_blend->type = TF_TYPE_BYPASS;
+		func_blend->tf = TRANSFER_FUNCTION_LINEAR;
+	}
+
+	return ret;
+}
+
 /**
  * amdgpu_dm_verify_lut3d_size - verifies if 3D LUT is supported and if user
  * shaper and 3D LUTs match the hw supported size
@@ -1070,8 +1099,9 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 {
 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
 	enum amdgpu_transfer_function shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
-	const struct drm_color_lut *shaper_lut, *lut3d;
-	uint32_t shaper_size, lut3d_size;
+	enum amdgpu_transfer_function blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
+	const struct drm_color_lut *shaper_lut, *lut3d, *blend_lut;
+	uint32_t shaper_size, lut3d_size, blend_size;
 	int ret;
 
 	/* We have nothing to do here, return */
@@ -1091,12 +1121,30 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 					  amdgpu_tf_to_dc_tf(shaper_tf),
 					  shaper_size,
 					  dc_plane_state->in_shaper_func);
-	if (ret)
+	if (ret) {
 		drm_dbg_kms(plane_state->plane->dev,
 			    "setting plane %d shaper LUT failed.\n",
 			    plane_state->plane->index);
 
-	return ret;
+		return ret;
+	}
+
+	blend_tf = dm_plane_state->blend_tf;
+	blend_lut = __extract_blob_lut(dm_plane_state->blend_lut, &blend_size);
+	blend_size = blend_lut != NULL ? blend_size : 0;
+
+	ret = amdgpu_dm_atomic_blend_lut(blend_lut, false,
+					 amdgpu_tf_to_dc_tf(blend_tf),
+					 blend_size, dc_plane_state->blend_tf);
+	if (ret) {
+		drm_dbg_kms(plane_state->plane->dev,
+			    "setting plane %d gamma lut failed.\n",
+			    plane_state->plane->index);
+
+		return ret;
+	}
+
+	return 0;
 }
 
 /**
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 28/32] drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (26 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 27/32] drm/amd/display: add plane blend LUT and TF support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 29/32] drm/amd/display: copy 3D LUT settings from crtc state to stream_update Melissa Wen
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Need to funnel the color caps through to these functions so it can check
that the hardware is capable.

v2:
- remove redundant color caps assignment on plane degamma map (Harry)
- pass color caps to degamma params

v3:
- remove unused color_caps parameter from set_color_properties (Harry)

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 29 ++++++++++++-------
 1 file changed, 18 insertions(+), 11 deletions(-)

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 0909ed5639bf..251b5f14bd89 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
@@ -564,6 +564,7 @@ static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream,
 /**
  * __set_input_tf - calculates the input transfer function based on expected
  * input space.
+ * @caps: dc color capabilities
  * @func: transfer function
  * @lut: lookup table that defines the color space
  * @lut_size: size of respective lut.
@@ -571,7 +572,7 @@ static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream,
  * Returns:
  * 0 in case of success. -ENOMEM if fails.
  */
-static int __set_input_tf(struct dc_transfer_func *func,
+static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *func,
 			  const struct drm_color_lut *lut, uint32_t lut_size)
 {
 	struct dc_gamma *gamma = NULL;
@@ -588,7 +589,7 @@ static int __set_input_tf(struct dc_transfer_func *func,
 		__drm_lut_to_dc_gamma(lut, gamma, false);
 	}
 
-	res = mod_color_calculate_degamma_params(NULL, func, gamma, gamma != NULL);
+	res = mod_color_calculate_degamma_params(caps, func, gamma, gamma != NULL);
 
 	if (gamma)
 		dc_gamma_release(&gamma);
@@ -752,7 +753,7 @@ static int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
 		func_blend->tf = tf;
 		func_blend->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
 
-		ret = __set_input_tf(func_blend, blend_lut, blend_size);
+		ret = __set_input_tf(NULL, func_blend, blend_lut, blend_size);
 	} else {
 		func_blend->type = TF_TYPE_BYPASS;
 		func_blend->tf = TRANSFER_FUNCTION_LINEAR;
@@ -968,7 +969,8 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
 
 static int
 map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
-			     struct dc_plane_state *dc_plane_state)
+			     struct dc_plane_state *dc_plane_state,
+			     struct dc_color_caps *caps)
 {
 	const struct drm_color_lut *degamma_lut;
 	enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB;
@@ -1023,7 +1025,7 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
 			dc_plane_state->in_transfer_func->tf =
 				TRANSFER_FUNCTION_LINEAR;
 
-		r = __set_input_tf(dc_plane_state->in_transfer_func,
+		r = __set_input_tf(caps, dc_plane_state->in_transfer_func,
 				   degamma_lut, degamma_size);
 		if (r)
 			return r;
@@ -1036,7 +1038,7 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
 		dc_plane_state->in_transfer_func->tf = tf;
 
 		if (tf != TRANSFER_FUNCTION_SRGB &&
-		    !mod_color_calculate_degamma_params(NULL,
+		    !mod_color_calculate_degamma_params(caps,
 							dc_plane_state->in_transfer_func,
 							NULL, false))
 			return -ENOMEM;
@@ -1047,7 +1049,8 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
 
 static int
 __set_dm_plane_degamma(struct drm_plane_state *plane_state,
-		       struct dc_plane_state *dc_plane_state)
+		       struct dc_plane_state *dc_plane_state,
+		       struct dc_color_caps *color_caps)
 {
 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
 	const struct drm_color_lut *degamma_lut;
@@ -1078,7 +1081,7 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
 		dc_plane_state->in_transfer_func->type =
 			TF_TYPE_DISTRIBUTED_POINTS;
 
-		ret = __set_input_tf(dc_plane_state->in_transfer_func,
+		ret = __set_input_tf(color_caps, dc_plane_state->in_transfer_func,
 				     degamma_lut, degamma_size);
 		if (ret)
 			return ret;
@@ -1086,7 +1089,7 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
 		dc_plane_state->in_transfer_func->type =
 			TF_TYPE_PREDEFINED;
 
-		if (!mod_color_calculate_degamma_params(NULL,
+		if (!mod_color_calculate_degamma_params(color_caps,
 		    dc_plane_state->in_transfer_func, NULL, false))
 			return -ENOMEM;
 	}
@@ -1165,6 +1168,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 				      struct dc_plane_state *dc_plane_state)
 {
 	struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev);
+	struct dc_color_caps *color_caps = NULL;
 	bool has_crtc_cm_degamma;
 	int ret;
 
@@ -1174,6 +1178,9 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 		return ret;
 	}
 
+	if (dc_plane_state->ctx && dc_plane_state->ctx->dc)
+		color_caps = &dc_plane_state->ctx->dc->caps.color;
+
 	/* Initially, we can just bypass the DGM block. */
 	dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
 	dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
@@ -1181,7 +1188,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 	/* After, we start to update values according to color props */
 	has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb);
 
-	ret = __set_dm_plane_degamma(plane_state, dc_plane_state);
+	ret = __set_dm_plane_degamma(plane_state, dc_plane_state, color_caps);
 	if (ret == -ENOMEM)
 		return ret;
 
@@ -1208,7 +1215,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 		 * linearize (implicit degamma) from sRGB/BT709 according to
 		 * the input space.
 		 */
-		ret = map_crtc_degamma_to_dc_plane(crtc, dc_plane_state);
+		ret = map_crtc_degamma_to_dc_plane(crtc, dc_plane_state, color_caps);
 		if (ret)
 			return ret;
 	}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 29/32] drm/amd/display: copy 3D LUT settings from crtc state to stream_update
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (27 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 28/32] drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 30/32] drm/amd/display: add plane CTM driver-specific property Melissa Wen
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

When commiting planes, we copy color mgmt resources to the stream state.
Do the same for shaper and 3D LUTs.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
Co-developed-by: Melissa Wen <mwen@igalia.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4b4181447df9..5e64eda6ed11 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8501,6 +8501,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 				&acrtc_state->stream->csc_color_matrix;
 			bundle->stream_update.out_transfer_func =
 				acrtc_state->stream->out_transfer_func;
+			bundle->stream_update.lut3d_func =
+				(struct dc_3dlut *) acrtc_state->stream->lut3d_func;
+			bundle->stream_update.func_shaper =
+				(struct dc_transfer_func *) acrtc_state->stream->func_shaper;
 		}
 
 		acrtc_state->stream->abm_level = acrtc_state->abm_level;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 30/32] drm/amd/display: add plane CTM driver-specific property
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (28 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 29/32] drm/amd/display: copy 3D LUT settings from crtc state to stream_update Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 31/32] drm/amd/display: add plane CTM support Melissa Wen
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Plane CTM for pre-blending color space conversion. Only enable
driver-specific plane CTM property on drivers that support both pre- and
post-blending gamut remap matrix, i.e., DCN3+ family. Otherwise it
conflits with DRM CRTC CTM property.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  2 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  7 +++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   |  7 +++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 20 +++++++++++++++++++
 4 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 071cc10bfd90..1347022ce57d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -363,6 +363,8 @@ struct amdgpu_mode_info {
 	 * @plane_hdr_mult_property:
 	 */
 	struct drm_property *plane_hdr_mult_property;
+
+	struct drm_property *plane_ctm_property;
 	/**
 	 * @shaper_lut_property: Plane property to set pre-blending shaper LUT
 	 * that converts color content before 3D LUT. If
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 219efa7fe181..c9cd2e5f79ae 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -784,6 +784,13 @@ struct dm_plane_state {
 	 * TF is needed for any subsequent linear-to-non-linear transforms.
 	 */
 	__u64 hdr_mult;
+	/**
+	 * @ctm:
+	 *
+	 * Color transformation matrix. The blob (if not NULL) is a &struct
+	 * drm_color_ctm_3x4.
+	 */
+	struct drm_property_blob *ctm;
 	/**
 	 * @shaper_lut: shaper lookup table blob. The blob (if not NULL) is an
 	 * array of &struct drm_color_lut.
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 251b5f14bd89..41c5926ca068 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
@@ -239,6 +239,13 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
 		return -ENOMEM;
 	adev->mode_info.plane_hdr_mult_property = prop;
 
+	prop = drm_property_create(adev_to_drm(adev),
+				   DRM_MODE_PROP_BLOB,
+				   "AMD_PLANE_CTM", 0);
+	if (!prop)
+		return -ENOMEM;
+	adev->mode_info.plane_ctm_property = prop;
+
 	prop = drm_property_create(adev_to_drm(adev),
 				   DRM_MODE_PROP_BLOB,
 				   "AMD_PLANE_SHAPER_LUT", 0);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index f1070ca7076a..d9537d9bf18c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1361,6 +1361,8 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
 
 	if (dm_plane_state->degamma_lut)
 		drm_property_blob_get(dm_plane_state->degamma_lut);
+	if (dm_plane_state->ctm)
+		drm_property_blob_get(dm_plane_state->ctm);
 	if (dm_plane_state->shaper_lut)
 		drm_property_blob_get(dm_plane_state->shaper_lut);
 	if (dm_plane_state->lut3d)
@@ -1442,6 +1444,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
 
 	if (dm_plane_state->degamma_lut)
 		drm_property_blob_put(dm_plane_state->degamma_lut);
+	if (dm_plane_state->ctm)
+		drm_property_blob_put(dm_plane_state->ctm);
 	if (dm_plane_state->lut3d)
 		drm_property_blob_put(dm_plane_state->lut3d);
 	if (dm_plane_state->shaper_lut)
@@ -1479,6 +1483,11 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
 				   dm->adev->mode_info.plane_hdr_mult_property,
 				   AMDGPU_HDR_MULT_DEFAULT);
 
+	/* Only enable plane CTM if both DPP and MPC gamut remap is available. */
+	if (dm->dc->caps.color.mpc.gamut_remap)
+		drm_object_attach_property(&plane->base,
+					   dm->adev->mode_info.plane_ctm_property, 0);
+
 	if (dpp_color_caps.hw_3d_lut) {
 		drm_object_attach_property(&plane->base,
 					   mode_info.plane_shaper_lut_property, 0);
@@ -1536,6 +1545,14 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
 			dm_plane_state->hdr_mult = val;
 			dm_plane_state->base.color_mgmt_changed = 1;
 		}
+	} else if (property == adev->mode_info.plane_ctm_property) {
+		ret = drm_property_replace_blob_from_id(plane->dev,
+							&dm_plane_state->ctm,
+							val,
+							sizeof(struct drm_color_ctm), -1,
+							&replaced);
+		dm_plane_state->base.color_mgmt_changed |= replaced;
+		return ret;
 	} else if (property == adev->mode_info.plane_shaper_lut_property) {
 		ret = drm_property_replace_blob_from_id(plane->dev,
 							&dm_plane_state->shaper_lut,
@@ -1597,6 +1614,9 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = dm_plane_state->degamma_tf;
 	} else if (property == adev->mode_info.plane_hdr_mult_property) {
 		*val = dm_plane_state->hdr_mult;
+	} else if (property == adev->mode_info.plane_ctm_property) {
+		*val = (dm_plane_state->ctm) ?
+			dm_plane_state->ctm->base.id : 0;
 	} else 	if (property == adev->mode_info.plane_shaper_lut_property) {
 		*val = (dm_plane_state->shaper_lut) ?
 			dm_plane_state->shaper_lut->base.id : 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 31/32] drm/amd/display: add plane CTM support
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (29 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 30/32] drm/amd/display: add plane CTM driver-specific property Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-05 17:15 ` [PATCH v4 32/32] drm/amd/display: Add 3x4 CTM support for plane CTM Melissa Wen
  2023-10-06  9:28 ` [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Sebastian Wick
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

Map the plane CTM driver-specific property to DC plane, instead of DC
stream. The remaining steps to program DPP block are already implemented
on DC shared-code.

v3:
- fix comment about plane and CRTC CTMs priorities (Harry)

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 26 +++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5e64eda6ed11..7de67b5ab6e9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9998,6 +9998,7 @@ static bool should_reset_plane(struct drm_atomic_state *state,
 		if (dm_old_other_state->degamma_tf != dm_new_other_state->degamma_tf ||
 		    dm_old_other_state->degamma_lut != dm_new_other_state->degamma_lut ||
 		    dm_old_other_state->hdr_mult != dm_new_other_state->hdr_mult ||
+		    dm_old_other_state->ctm != dm_new_other_state->ctm ||
 		    dm_old_other_state->shaper_lut != dm_new_other_state->shaper_lut ||
 		    dm_old_other_state->shaper_tf != dm_new_other_state->shaper_tf ||
 		    dm_old_other_state->lut3d != dm_new_other_state->lut3d ||
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 41c5926ca068..bc9dd75e8881 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
@@ -1175,6 +1175,8 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 				      struct dc_plane_state *dc_plane_state)
 {
 	struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev);
+	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+	struct drm_color_ctm *ctm = NULL;
 	struct dc_color_caps *color_caps = NULL;
 	bool has_crtc_cm_degamma;
 	int ret;
@@ -1227,5 +1229,29 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 			return ret;
 	}
 
+	/* Setup CRTC CTM. */
+	if (dm_plane_state->ctm) {
+		ctm = (struct drm_color_ctm *)dm_plane_state->ctm->data;
+		/*
+		 * DCN2 and older don't support both pre-blending and
+		 * post-blending gamut remap. For this HW family, if we have
+		 * the plane and CRTC CTMs simultaneously, CRTC CTM takes
+		 * priority, and we discard plane CTM, as implemented in
+		 * dcn10_program_gamut_remap(). However, DCN3+ has DPP
+		 * (pre-blending) and MPC (post-blending) `gamut remap` blocks;
+		 * therefore, we can program plane and CRTC CTMs together by
+		 * mapping CRTC CTM to MPC and keeping plane CTM setup at DPP,
+		 * as it's done by dcn30_program_gamut_remap().
+		 */
+		__drm_ctm_to_dc_matrix(ctm, dc_plane_state->gamut_remap_matrix.matrix);
+
+		dc_plane_state->gamut_remap_matrix.enable_remap = true;
+		dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
+	} else {
+		/* Bypass CTM. */
+		dc_plane_state->gamut_remap_matrix.enable_remap = false;
+		dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
+	}
+
 	return amdgpu_dm_plane_set_color_properties(plane_state, dc_plane_state);
 }
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v4 32/32] drm/amd/display: Add 3x4 CTM support for plane CTM
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (30 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 31/32] drm/amd/display: add plane CTM support Melissa Wen
@ 2023-10-05 17:15 ` Melissa Wen
  2023-10-06  9:28 ` [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Sebastian Wick
  32 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-10-05 17:15 UTC (permalink / raw)
  To: amd-gfx, Harry Wentland, Rodrigo Siqueira, sunpeng.li,
	Alex Deucher, dri-devel, christian.koenig, Xinhui.Pan, airlied,
	daniel, maarten.lankhorst, mripard, tzimmermann
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim

From: Joshua Ashton <joshua@froggi.es>

Create drm_color_ctm_3x4 to support 3x4-dimension plane CTM matrix and
convert DRM CTM to DC CSC float matrix.

v3:
- rename ctm2 to ctm_3x4 (Harry)

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Joshua Ashton <joshua@froggi.es>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 28 +++++++++++++++++--
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  2 +-
 include/uapi/drm/drm_mode.h                   |  8 ++++++
 3 files changed, 34 insertions(+), 4 deletions(-)

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 bc9dd75e8881..655c18c9a2d7 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
@@ -433,6 +433,28 @@ static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm,
 	}
 }
 
+/**
+ * __drm_ctm_3x4_to_dc_matrix - converts a DRM CTM 3x4 to a DC CSC float matrix
+ * @ctm: DRM color transformation matrix with 3x4 dimensions
+ * @matrix: DC CSC float matrix
+ *
+ * The matrix needs to be a 3x4 (12 entry) matrix.
+ */
+static void __drm_ctm_3x4_to_dc_matrix(const struct drm_color_ctm_3x4 *ctm,
+				       struct fixed31_32 *matrix)
+{
+	int i;
+
+	/* The format provided is S31.32, using signed-magnitude representation.
+	 * Our fixed31_32 is also S31.32, but is using 2's complement. We have
+	 * to convert from signed-magnitude to 2's complement.
+	 */
+	for (i = 0; i < 12; i++) {
+		/* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */
+		matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i]);
+	}
+}
+
 /**
  * __set_legacy_tf - Calculates the legacy transfer function
  * @func: transfer function
@@ -1176,7 +1198,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 {
 	struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev);
 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
-	struct drm_color_ctm *ctm = NULL;
+	struct drm_color_ctm_3x4 *ctm = NULL;
 	struct dc_color_caps *color_caps = NULL;
 	bool has_crtc_cm_degamma;
 	int ret;
@@ -1231,7 +1253,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 
 	/* Setup CRTC CTM. */
 	if (dm_plane_state->ctm) {
-		ctm = (struct drm_color_ctm *)dm_plane_state->ctm->data;
+		ctm = (struct drm_color_ctm_3x4 *)dm_plane_state->ctm->data;
 		/*
 		 * DCN2 and older don't support both pre-blending and
 		 * post-blending gamut remap. For this HW family, if we have
@@ -1243,7 +1265,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 		 * mapping CRTC CTM to MPC and keeping plane CTM setup at DPP,
 		 * as it's done by dcn30_program_gamut_remap().
 		 */
-		__drm_ctm_to_dc_matrix(ctm, dc_plane_state->gamut_remap_matrix.matrix);
+		__drm_ctm_3x4_to_dc_matrix(ctm, dc_plane_state->gamut_remap_matrix.matrix);
 
 		dc_plane_state->gamut_remap_matrix.enable_remap = true;
 		dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index d9537d9bf18c..a3935c56189b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1549,7 +1549,7 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
 		ret = drm_property_replace_blob_from_id(plane->dev,
 							&dm_plane_state->ctm,
 							val,
-							sizeof(struct drm_color_ctm), -1,
+							sizeof(struct drm_color_ctm_3x4), -1,
 							&replaced);
 		dm_plane_state->base.color_mgmt_changed |= replaced;
 		return ret;
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 46becedf5b2f..a811d24e8ed5 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -838,6 +838,14 @@ struct drm_color_ctm {
 	__u64 matrix[9];
 };
 
+struct drm_color_ctm_3x4 {
+	/*
+	 * Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude
+	 * (not two's complement!) format.
+	 */
+	__u64 matrix[12];
+};
+
 struct drm_color_lut {
 	/*
 	 * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties
  2023-10-05 17:15 ` [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties Melissa Wen
@ 2023-10-06  9:09   ` Sebastian Wick
  2023-11-06 18:46     ` Melissa Wen
  2023-11-02  3:48   ` Joshua Ashton
  1 sibling, 1 reply; 47+ messages in thread
From: Sebastian Wick @ 2023-10-06  9:09 UTC (permalink / raw)
  To: Melissa Wen
  Cc: Pekka Paalanen, kernel-dev, Shashank Sharma, sunpeng.li,
	Xinhui.Pan, Rodrigo Siqueira, Xaver Hugl, dri-devel,
	Nicholas Kazlauskas, Alex Hung, amd-gfx, Alex Deucher,
	christian.koenig, Joshua Ashton, sungjoon.kim

On Thu, Oct 05, 2023 at 04:15:04PM -0100, Melissa Wen wrote:
> Add 3D LUT property for plane color transformations using a 3D lookup
> table. 3D LUT allows for highly accurate and complex color
> transformations and is suitable to adjust the balance between color
> channels. It's also more complex to manage and require more
> computational resources.
> 
> Since a 3D LUT has a limited number of entries in each dimension we want
> to use them in an optimal fashion. This means using the 3D LUT in a
> colorspace that is optimized for human vision, such as sRGB, PQ, or
> another non-linear space. Therefore, userpace may need one 1D LUT
> (shaper) before it to delinearize content and another 1D LUT after 3D
> LUT (blend) to linearize content again for blending. The next patches
> add these 1D LUTs to the plane color mgmt pipeline.
> 
> v3:
> - improve commit message about 3D LUT
> - describe the 3D LUT entries and size (Harry)
> 
> v4:
> - advertise 3D LUT max size as the size of a single-dimension
> 
> Signed-off-by: Melissa Wen <mwen@igalia.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 18 +++++++++++++++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  9 ++++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 14 +++++++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 23 +++++++++++++++++++
>  4 files changed, 64 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 62044d41da75..f7adaa52c23f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -363,6 +363,24 @@ struct amdgpu_mode_info {
>  	 * @plane_hdr_mult_property:
>  	 */
>  	struct drm_property *plane_hdr_mult_property;
> +	/**
> +	 * @plane_lut3d_property: Plane property for color transformation using
> +	 * a 3D LUT (pre-blending), a three-dimensional array where each
> +	 * element is an RGB triplet. Each dimension has a size of the cubed
> +	 * root of lut3d_size. The array contains samples from the approximated

This should be "Each dimension has a size of lut3d_size" now.

> +	 * function. On AMD, values between samples are estimated by
> +	 * tetrahedral interpolation. The array is accessed with three indices,
> +	 * one for each input dimension (color channel), blue being the
> +	 * outermost dimension, red the innermost.
> +	 */
> +	struct drm_property *plane_lut3d_property;
> +	/**
> +	 * @plane_degamma_lut_size_property: Plane property to define the max
> +	 * size of 3D LUT as supported by the driver (read-only). The max size
> +	 * is the max size of one dimension and, therefore, the max number of
> +	 * entries for 3D LUT array is the 3D LUT size cubed;
> +	 */
> +	struct drm_property *plane_lut3d_size_property;
>  };
>  
>  #define AMDGPU_MAX_BL_LEVEL 0xFF
> 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 bb2ce843369d..7a2350c62cf1 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -784,6 +784,11 @@ struct dm_plane_state {
>  	 * TF is needed for any subsequent linear-to-non-linear transforms.
>  	 */
>  	__u64 hdr_mult;
> +	/**
> +	 * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
> +	 * &struct drm_color_lut.
> +	 */
> +	struct drm_property_blob *lut3d;
>  };
>  
>  struct dm_crtc_state {
> @@ -869,6 +874,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
>  
>  void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
>  
> +/* 3D LUT max size is 17x17x17 (4913 entries) */
> +#define MAX_COLOR_3DLUT_SIZE 17
> +#define MAX_COLOR_3DLUT_BITDEPTH 12
> +/* 1D LUT size */
>  #define MAX_COLOR_LUT_ENTRIES 4096
>  /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
>  #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
> 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 caf49a044ab4..011f2f9ec890 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
> @@ -230,6 +230,20 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>  		return -ENOMEM;
>  	adev->mode_info.plane_hdr_mult_property = prop;
>  
> +	prop = drm_property_create(adev_to_drm(adev),
> +				   DRM_MODE_PROP_BLOB,
> +				   "AMD_PLANE_LUT3D", 0);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_lut3d_property = prop;
> +
> +	prop = drm_property_create_range(adev_to_drm(adev),
> +					 DRM_MODE_PROP_IMMUTABLE,
> +					 "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_lut3d_size_property = prop;
> +
>  	return 0;
>  }
>  #endif
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index ae64d4b73360..068798ffdd56 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1359,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
>  
>  	if (dm_plane_state->degamma_lut)
>  		drm_property_blob_get(dm_plane_state->degamma_lut);
> +	if (dm_plane_state->lut3d)
> +		drm_property_blob_get(dm_plane_state->lut3d);
>  
>  	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
>  	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
> @@ -1432,6 +1434,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
>  
>  	if (dm_plane_state->degamma_lut)
>  		drm_property_blob_put(dm_plane_state->degamma_lut);
> +	if (dm_plane_state->lut3d)
> +		drm_property_blob_put(dm_plane_state->lut3d);
>  
>  	if (dm_plane_state->dc_state)
>  		dc_plane_state_release(dm_plane_state->dc_state);
> @@ -1462,6 +1466,14 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
>  	drm_object_attach_property(&plane->base,
>  				   dm->adev->mode_info.plane_hdr_mult_property,
>  				   AMDGPU_HDR_MULT_DEFAULT);
> +
> +	if (dpp_color_caps.hw_3d_lut) {
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_lut3d_property, 0);
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_lut3d_size_property,
> +					   MAX_COLOR_3DLUT_SIZE);
> +	}
>  }
>  
>  static int
> @@ -1493,6 +1505,14 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
>  			dm_plane_state->hdr_mult = val;
>  			dm_plane_state->base.color_mgmt_changed = 1;
>  		}
> +	} else if (property == adev->mode_info.plane_lut3d_property) {
> +		ret = drm_property_replace_blob_from_id(plane->dev,
> +							&dm_plane_state->lut3d,
> +							val, -1,
> +							sizeof(struct drm_color_lut),
> +							&replaced);
> +		dm_plane_state->base.color_mgmt_changed |= replaced;
> +		return ret;
>  	} else {
>  		drm_dbg_atomic(plane->dev,
>  			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> @@ -1520,6 +1540,9 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
>  		*val = dm_plane_state->degamma_tf;
>  	} else if (property == adev->mode_info.plane_hdr_mult_property) {
>  		*val = dm_plane_state->hdr_mult;
> +	} else 	if (property == adev->mode_info.plane_lut3d_property) {
> +		*val = (dm_plane_state->lut3d) ?
> +			dm_plane_state->lut3d->base.id : 0;
>  	} else {
>  		return -EINVAL;
>  	}
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt
  2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
                   ` (31 preceding siblings ...)
  2023-10-05 17:15 ` [PATCH v4 32/32] drm/amd/display: Add 3x4 CTM support for plane CTM Melissa Wen
@ 2023-10-06  9:28 ` Sebastian Wick
  2023-11-06 19:33   ` Melissa Wen
  32 siblings, 1 reply; 47+ messages in thread
From: Sebastian Wick @ 2023-10-06  9:28 UTC (permalink / raw)
  To: Melissa Wen, David Airlie, Daniel Vetter
  Cc: liviu.dudau, dri-devel, Shashank Sharma, Rodrigo Siqueira,
	amd-gfx, Alex Hung, kernel-dev, sunpeng.li, mripard,
	sungjoon.kim, Pekka Paalanen, Xinhui.Pan, Xaver Hugl,
	Nicholas Kazlauskas, tzimmermann, Alex Deucher, christian.koenig,
	Joshua Ashton

On Thu, Oct 05, 2023 at 04:14:55PM -0100, Melissa Wen wrote:
> Hello,
> 
> Just another iteration for AMD driver-specific color properties.
> Basically, addressing comments from the previous version.
> 
> Recap: this series extends the current KMS color management API with AMD
> driver-specific properties to enhance the color management support on
> AMD Steam Deck. The key additions to the color pipeline include:

Did you talk with the maintainers about this already? The last few times
driver specific properties, and even kind of generic plane properties
with a fixed position in the pipeline were proposed they were all
NAKed. Just putting them behind a define doesn't sound great and I don't
think there is any precedence for allowing this in. This is basically
just more burden for upstream without any benefits for upstream.

Maybe you can separate the uAPI changes from the internal improvements
to land at least parts of this faster.

> - plane degamma LUT and pre-defined TF;
> - plane HDR multiplier;
> - plane CTM 3x4;
> - plane shaper LUT and pre-defined TF;
> - plane 3D LUT;
> - plane blend LUT and pre-defined TF;
> - CRTC gamma pre-defined TF;
> 
> You can find the AMD HW color capabilities documented here:
> https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/display-manager.html#color-management-properties
> 
> The userspace case is Gamescope[1], the compositor for SteamOS.
> Gamescope has already adopted AMD driver-specific properties to
> implement comprehensive color management support, including gamut
> mapping, HDR rendering, SDR on HDR, HDR on SDR. Using these features in
> the SteamOS 3.5[2] users can expect a significantly enhanced visual
> experience. 
> 
> You can find a brief overview of the Steam Deck color pipeline here:
> https://github.com/ValveSoftware/gamescope/blob/master/src/docs/Steam%20Deck%20Display%20Pipeline.png
> 
> Changes from:
> 
> [RFC] https://lore.kernel.org/dri-devel/20230423141051.702990-1-mwen@igalia.com
> - Remove KConfig and guard properties with `AMD_PRIVATE_COLOR`;
> - Remove properties for post-blending/CRTC shaper TF+LUT and 3D LUT;
> - Use color caps to improve the support of pre-defined curve;
> 
> [v1] https://lore.kernel.org/dri-devel/20230523221520.3115570-1-mwen@igalia.com
> - Replace DRM_ by AMDGPU_ prefix for transfer function (TF) enum; 
> - Explicitly define EOTFs and inverse EOTFs and set props accordingly;
> - Document pre-defined transfer functions;
> - Remove HLG transfer function from supported TFs;
> - Remove misleading comments;
> - Remove post-blending shaper TF+LUT and 3D LUT support;
> - Move driver-specific property operations from amdgpu_display.c to
>   amdgpu_dm_color.c;
> - Reset planes if any color props change;
> - Add plane CTM 3x4 support;
> - Removed two DC fixes already applied upstream;
> 
> [v2] https://lore.kernel.org/dri-devel/20230810160314.48225-1-mwen@igalia.com
> - Many documentation fixes: BT.709 OETF, description of sRGB and pure
>   power functions, TF+1D LUT behavior;
> - Rename CTM2 to CTM 3x4 and fix misleading comment about DC gamut remap;
> - Squash `Linear` and `Unity` TF in `Identity`;
> - Remove the `MPC gamut remap` patch already applied upstream[3];
> - Remove outdated delta segmentation fix;
> - Nits/small fixes;
> 
> [v3] https://lore.kernel.org/amd-gfx/20230925194932.1329483-1-mwen@igalia.com
> - Add table to describe value range in linear and non-linear forms
> - Comment the PQ TF need after HDR multiplier
> - Advertise the 3D LUT size as the size of a single-dimension (read-only)
> - remove function to check expected size from 3DLUT caps
> - cleanup comments
> 
> It's worth noting that driver-specific properties are guarded by
> `AMD_PRIVATE_COLOR`. So, finally, this is the color management API when
> driver-specific properties are enabled:
> 
> +----------------------+
> |   PLANE              |
> |                      |
> |  +----------------+  |
> |  | AMD Degamma    |  |
> |  |                |  |
> |  | EOTF | 1D LUT  |  |
> |  +--------+-------+  |
> |           |          |
> |  +--------v-------+  |
> |  |    AMD HDR     |  |
> |  |    Multiply    |  |
> |  +--------+-------+  |
> |           |          |
> |  +--------v-------+  |
> |  |  AMD CTM (3x4) |  |
> |  +--------+-------+  |
> |           |          |
> |  +--------v-------+  |
> |  | AMD Shaper     |  |
> |  |                |  |
> |  | inv_EOTF |     |  |
> |  | Custom 1D LUT  |  |
> |  +--------+-------+  |
> |           |          |
> |  +--------v-------+  |
> |  |   AMD 3D LUT   |  |
> |  |   17^3/12-bit  |  |
> |  +--------+-------+  |
> |           |          |
> |  +--------v-------+  |
> |  | AMD Blend      |  |
> |  |                |  |
> |  | EOTF | 1D LUT  |  |
> |  +--------+-------+  |
> |           |          |
> ++----------v---------++
> ||      Blending      ||
> ++----------+---------++
> |    CRTC   |          |
> |           |          |
> |   +-------v-------+  |
> |   | DRM Degamma   |  |
> |   |               |  |
> |   | Custom 1D LUT |  |
> |   +-------+-------+  |
> |           |          |
> |   +-------v-------+  |
> |   | DRM CTM (3x3) |  |
> |   +-------+-------+  |
> |           |          |
> |   +-------v-------+  |
> |   | DRM Gamma     |  |
> |   |               |  |
> |   | Custom 1D LUT |  |
> |   +---------------+  |
> |   | *AMD Gamma    |  |
> |   |   inv_EOTF    |  |
> |   +---------------+  |
> |                      |
> +----------------------+
> 
> Please, let us know your thoughts.
> 
> Best Regards,
> 
> Melissa Wen
> 
> [1] https://github.com/ValveSoftware/gamescope
> [2] https://store.steampowered.com/news/app/1675200/view/3686804163591367815
> [3] https://lore.kernel.org/dri-devel/20230721132431.692158-1-mwen@igalia.com
> 
> Joshua Ashton (14):
>   drm/amd/display: add plane degamma TF driver-specific property
>   drm/amd/display: add plane HDR multiplier driver-specific property
>   drm/amd/display: add plane blend LUT and TF driver-specific properties
>   drm/amd/display: add CRTC gamma TF support
>   drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func
>   drm/amd/display: mark plane as needing reset if color props change
>   drm/amd/display: add plane degamma TF and LUT support
>   drm/amd/display: add dc_fixpt_from_s3132 helper
>   drm/amd/display: add HDR multiplier support
>   drm/amd/display: handle empty LUTs in __set_input_tf
>   drm/amd/display: add plane blend LUT and TF support
>   drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG
>   drm/amd/display: copy 3D LUT settings from crtc state to stream_update
>   drm/amd/display: Add 3x4 CTM support for plane CTM
> 
> Melissa Wen (18):
>   drm/drm_mode_object: increase max objects to accommodate new color
>     props
>   drm/drm_property: make replace_property_blob_from_id a DRM helper
>   drm/drm_plane: track color mgmt changes per plane
>   drm/amd/display: add driver-specific property for plane degamma LUT
>   drm/amd/display: explicitly define EOTF and inverse EOTF
>   drm/amd/display: document AMDGPU pre-defined transfer functions
>   drm/amd/display: add plane 3D LUT driver-specific properties
>   drm/amd/display: add plane shaper LUT and TF driver-specific
>     properties
>   drm/amd/display: add CRTC gamma TF driver-specific property
>   drm/amd/display: add comments to describe DM crtc color mgmt behavior
>   drm/amd/display: encapsulate atomic regamma operation
>   drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
>   drm/amd/display: reject atomic commit if setting both plane and CRTC
>     degamma
>   drm/amd/display: add plane shaper LUT support
>   drm/amd/display: add plane shaper TF support
>   drm/amd/display: add plane 3D LUT support
>   drm/amd/display: add plane CTM driver-specific property
>   drm/amd/display: add plane CTM support
> 
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  90 ++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  34 +-
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 108 +++
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 821 ++++++++++++++++--
>  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |  72 ++
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 224 ++++-
>  .../gpu/drm/amd/display/include/fixed31_32.h  |  12 +
>  drivers/gpu/drm/arm/malidp_crtc.c             |   2 +-
>  drivers/gpu/drm/drm_atomic.c                  |   1 +
>  drivers/gpu/drm/drm_atomic_state_helper.c     |   1 +
>  drivers/gpu/drm/drm_atomic_uapi.c             |  43 +-
>  drivers/gpu/drm/drm_property.c                |  49 ++
>  include/drm/drm_mode_object.h                 |   2 +-
>  include/drm/drm_plane.h                       |   7 +
>  include/drm/drm_property.h                    |   6 +
>  include/uapi/drm/drm_mode.h                   |   8 +
>  16 files changed, 1371 insertions(+), 109 deletions(-)
> 
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties
  2023-10-05 17:15 ` [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties Melissa Wen
  2023-10-06  9:09   ` Sebastian Wick
@ 2023-11-02  3:48   ` Joshua Ashton
  2023-11-02  7:31     ` Joshua Ashton
  2023-11-06 18:49     ` Melissa Wen
  1 sibling, 2 replies; 47+ messages in thread
From: Joshua Ashton @ 2023-11-02  3:48 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Harry Wentland, Rodrigo Siqueira,
	sunpeng.li, Alex Deucher, dri-devel, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, sungjoon.kim



On 10/5/23 18:15, Melissa Wen wrote:
> Add 3D LUT property for plane color transformations using a 3D lookup
> table. 3D LUT allows for highly accurate and complex color
> transformations and is suitable to adjust the balance between color
> channels. It's also more complex to manage and require more
> computational resources.
> 
> Since a 3D LUT has a limited number of entries in each dimension we want
> to use them in an optimal fashion. This means using the 3D LUT in a
> colorspace that is optimized for human vision, such as sRGB, PQ, or
> another non-linear space. Therefore, userpace may need one 1D LUT
> (shaper) before it to delinearize content and another 1D LUT after 3D
> LUT (blend) to linearize content again for blending. The next patches
> add these 1D LUTs to the plane color mgmt pipeline.
> 
> v3:
> - improve commit message about 3D LUT
> - describe the 3D LUT entries and size (Harry)
> 
> v4:
> - advertise 3D LUT max size as the size of a single-dimension
> 
> Signed-off-by: Melissa Wen <mwen@igalia.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 18 +++++++++++++++
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  9 ++++++++
>   .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 14 +++++++++++
>   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 23 +++++++++++++++++++
>   4 files changed, 64 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 62044d41da75..f7adaa52c23f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -363,6 +363,24 @@ struct amdgpu_mode_info {
>   	 * @plane_hdr_mult_property:
>   	 */
>   	struct drm_property *plane_hdr_mult_property;
> +	/**
> +	 * @plane_lut3d_property: Plane property for color transformation using
> +	 * a 3D LUT (pre-blending), a three-dimensional array where each
> +	 * element is an RGB triplet. Each dimension has a size of the cubed
> +	 * root of lut3d_size. The array contains samples from the approximated
> +	 * function. On AMD, values between samples are estimated by
> +	 * tetrahedral interpolation. The array is accessed with three indices,
> +	 * one for each input dimension (color channel), blue being the
> +	 * outermost dimension, red the innermost.
> +	 */
> +	struct drm_property *plane_lut3d_property;
> +	/**
> +	 * @plane_degamma_lut_size_property: Plane property to define the max
> +	 * size of 3D LUT as supported by the driver (read-only). The max size
> +	 * is the max size of one dimension and, therefore, the max number of
> +	 * entries for 3D LUT array is the 3D LUT size cubed;
> +	 */
> +	struct drm_property *plane_lut3d_size_property;
>   };
>   
>   #define AMDGPU_MAX_BL_LEVEL 0xFF
> 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 bb2ce843369d..7a2350c62cf1 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -784,6 +784,11 @@ struct dm_plane_state {
>   	 * TF is needed for any subsequent linear-to-non-linear transforms.
>   	 */
>   	__u64 hdr_mult;
> +	/**
> +	 * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
> +	 * &struct drm_color_lut.
> +	 */
> +	struct drm_property_blob *lut3d;
>   };
>   
>   struct dm_crtc_state {
> @@ -869,6 +874,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
>   
>   void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
>   
> +/* 3D LUT max size is 17x17x17 (4913 entries) */
> +#define MAX_COLOR_3DLUT_SIZE 17
> +#define MAX_COLOR_3DLUT_BITDEPTH 12
> +/* 1D LUT size */
>   #define MAX_COLOR_LUT_ENTRIES 4096
>   /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
>   #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
> 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 caf49a044ab4..011f2f9ec890 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
> @@ -230,6 +230,20 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>   		return -ENOMEM;
>   	adev->mode_info.plane_hdr_mult_property = prop;
>   
> +	prop = drm_property_create(adev_to_drm(adev),
> +				   DRM_MODE_PROP_BLOB,
> +				   "AMD_PLANE_LUT3D", 0);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_lut3d_property = prop;
> +
> +	prop = drm_property_create_range(adev_to_drm(adev),
> +					 DRM_MODE_PROP_IMMUTABLE,
> +					 "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_lut3d_size_property = prop;
> +
>   	return 0;
>   }
>   #endif
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index ae64d4b73360..068798ffdd56 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1359,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
>   
>   	if (dm_plane_state->degamma_lut)
>   		drm_property_blob_get(dm_plane_state->degamma_lut);
> +	if (dm_plane_state->lut3d)
> +		drm_property_blob_get(dm_plane_state->lut3d);

This is wrong, and was breaking state restoration on suspend.

dm_plane_state->lut3d is always NULL as it's the new zero-ed state, you 
need to check the old_dm_plane_state's values and then set it on the new 
state after _get.

It should be like this: (based on end of the patchset).

	if (old_dm_plane_state->degamma_lut) {
		drm_property_blob_get(old_dm_plane_state->degamma_lut);
		dm_plane_state->degamma_lut = old_dm_plane_state->degamma_lut;
	}
	if (old_dm_plane_state->ctm) {
		drm_property_blob_get(old_dm_plane_state->ctm);
		dm_plane_state->ctm = old_dm_plane_state->ctm;
	}
	if (old_dm_plane_state->shaper_lut) {
		drm_property_blob_get(old_dm_plane_state->shaper_lut);
		dm_plane_state->shaper_lut = old_dm_plane_state->shaper_lut;
	}
	if (old_dm_plane_state->lut3d) {
		drm_property_blob_get(old_dm_plane_state->lut3d);
		dm_plane_state->lut3d = old_dm_plane_state->lut3d;
	}
	if (old_dm_plane_state->blend_lut) {
		drm_property_blob_get(old_dm_plane_state->blend_lut);
		dm_plane_state->blend_lut = old_dm_plane_state->blend_lut;
	}

because it doesn't do the memcpy like the base drm atomic stuff.

I also had to add a patch to ensure color mgmt was updated on unsuspend 
always too, but that's not related to this patchset and also affected 
stuff beforehand.

I'll send that patch in a bit.

Thanks!
- Joshie 🐸✨

>   
>   	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
>   	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
> @@ -1432,6 +1434,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
>   
>   	if (dm_plane_state->degamma_lut)
>   		drm_property_blob_put(dm_plane_state->degamma_lut);
> +	if (dm_plane_state->lut3d)
> +		drm_property_blob_put(dm_plane_state->lut3d);
>   
>   	if (dm_plane_state->dc_state)
>   		dc_plane_state_release(dm_plane_state->dc_state);
> @@ -1462,6 +1466,14 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
>   	drm_object_attach_property(&plane->base,
>   				   dm->adev->mode_info.plane_hdr_mult_property,
>   				   AMDGPU_HDR_MULT_DEFAULT);
> +
> +	if (dpp_color_caps.hw_3d_lut) {
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_lut3d_property, 0);
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_lut3d_size_property,
> +					   MAX_COLOR_3DLUT_SIZE);
> +	}
>   }
>   
>   static int
> @@ -1493,6 +1505,14 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
>   			dm_plane_state->hdr_mult = val;
>   			dm_plane_state->base.color_mgmt_changed = 1;
>   		}
> +	} else if (property == adev->mode_info.plane_lut3d_property) {
> +		ret = drm_property_replace_blob_from_id(plane->dev,
> +							&dm_plane_state->lut3d,
> +							val, -1,
> +							sizeof(struct drm_color_lut),
> +							&replaced);
> +		dm_plane_state->base.color_mgmt_changed |= replaced;
> +		return ret;
>   	} else {
>   		drm_dbg_atomic(plane->dev,
>   			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> @@ -1520,6 +1540,9 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
>   		*val = dm_plane_state->degamma_tf;
>   	} else if (property == adev->mode_info.plane_hdr_mult_property) {
>   		*val = dm_plane_state->hdr_mult;
> +	} else 	if (property == adev->mode_info.plane_lut3d_property) {
> +		*val = (dm_plane_state->lut3d) ?
> +			dm_plane_state->lut3d->base.id : 0;
>   	} else {
>   		return -EINVAL;
>   	}

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties
  2023-11-02  3:48   ` Joshua Ashton
@ 2023-11-02  7:31     ` Joshua Ashton
  2023-11-06 18:52       ` Melissa Wen
  2023-11-06 18:49     ` Melissa Wen
  1 sibling, 1 reply; 47+ messages in thread
From: Joshua Ashton @ 2023-11-02  7:31 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Harry Wentland, Rodrigo Siqueira,
	sunpeng.li, Alex Deucher, dri-devel, christian.koenig,
	Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, sungjoon.kim

Also, Melissa, you cannot do:

	if (!plane_state->color_mgmt_changed)
		return 0;

in amdgpu_dm_plane_set_color_properties.

The allocation for dc_plane_state could be new and zero'ed so it needs 
to be set every time. (Until AMDGPU has better dedup'ing of stuff there)

The reason it looked like it worked for you now is because the duplicate 
was broken, so color mgmt for planes was always being marked as dirty there.

Thanks

- Joshie 🐸✨

On 11/2/23 03:48, Joshua Ashton wrote:
> 
> 
> On 10/5/23 18:15, Melissa Wen wrote:
>> Add 3D LUT property for plane color transformations using a 3D lookup
>> table. 3D LUT allows for highly accurate and complex color
>> transformations and is suitable to adjust the balance between color
>> channels. It's also more complex to manage and require more
>> computational resources.
>>
>> Since a 3D LUT has a limited number of entries in each dimension we want
>> to use them in an optimal fashion. This means using the 3D LUT in a
>> colorspace that is optimized for human vision, such as sRGB, PQ, or
>> another non-linear space. Therefore, userpace may need one 1D LUT
>> (shaper) before it to delinearize content and another 1D LUT after 3D
>> LUT (blend) to linearize content again for blending. The next patches
>> add these 1D LUTs to the plane color mgmt pipeline.
>>
>> v3:
>> - improve commit message about 3D LUT
>> - describe the 3D LUT entries and size (Harry)
>>
>> v4:
>> - advertise 3D LUT max size as the size of a single-dimension
>>
>> Signed-off-by: Melissa Wen <mwen@igalia.com>
>> ---
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 18 +++++++++++++++
>>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  9 ++++++++
>>   .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 14 +++++++++++
>>   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 23 +++++++++++++++++++
>>   4 files changed, 64 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
>> index 62044d41da75..f7adaa52c23f 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
>> @@ -363,6 +363,24 @@ struct amdgpu_mode_info {
>>        * @plane_hdr_mult_property:
>>        */
>>       struct drm_property *plane_hdr_mult_property;
>> +    /**
>> +     * @plane_lut3d_property: Plane property for color transformation 
>> using
>> +     * a 3D LUT (pre-blending), a three-dimensional array where each
>> +     * element is an RGB triplet. Each dimension has a size of the cubed
>> +     * root of lut3d_size. The array contains samples from the 
>> approximated
>> +     * function. On AMD, values between samples are estimated by
>> +     * tetrahedral interpolation. The array is accessed with three 
>> indices,
>> +     * one for each input dimension (color channel), blue being the
>> +     * outermost dimension, red the innermost.
>> +     */
>> +    struct drm_property *plane_lut3d_property;
>> +    /**
>> +     * @plane_degamma_lut_size_property: Plane property to define the 
>> max
>> +     * size of 3D LUT as supported by the driver (read-only). The max 
>> size
>> +     * is the max size of one dimension and, therefore, the max 
>> number of
>> +     * entries for 3D LUT array is the 3D LUT size cubed;
>> +     */
>> +    struct drm_property *plane_lut3d_size_property;
>>   };
>>   #define AMDGPU_MAX_BL_LEVEL 0xFF
>> 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 bb2ce843369d..7a2350c62cf1 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> @@ -784,6 +784,11 @@ struct dm_plane_state {
>>        * TF is needed for any subsequent linear-to-non-linear transforms.
>>        */
>>       __u64 hdr_mult;
>> +    /**
>> +     * @lut3d: 3D lookup table blob. The blob (if not NULL) is an 
>> array of
>> +     * &struct drm_color_lut.
>> +     */
>> +    struct drm_property_blob *lut3d;
>>   };
>>   struct dm_crtc_state {
>> @@ -869,6 +874,10 @@ void amdgpu_dm_update_freesync_caps(struct 
>> drm_connector *connector,
>>   void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
>> +/* 3D LUT max size is 17x17x17 (4913 entries) */
>> +#define MAX_COLOR_3DLUT_SIZE 17
>> +#define MAX_COLOR_3DLUT_BITDEPTH 12
>> +/* 1D LUT size */
>>   #define MAX_COLOR_LUT_ENTRIES 4096
>>   /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
>>   #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
>> 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 caf49a044ab4..011f2f9ec890 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
>> @@ -230,6 +230,20 @@ amdgpu_dm_create_color_properties(struct 
>> amdgpu_device *adev)
>>           return -ENOMEM;
>>       adev->mode_info.plane_hdr_mult_property = prop;
>> +    prop = drm_property_create(adev_to_drm(adev),
>> +                   DRM_MODE_PROP_BLOB,
>> +                   "AMD_PLANE_LUT3D", 0);
>> +    if (!prop)
>> +        return -ENOMEM;
>> +    adev->mode_info.plane_lut3d_property = prop;
>> +
>> +    prop = drm_property_create_range(adev_to_drm(adev),
>> +                     DRM_MODE_PROP_IMMUTABLE,
>> +                     "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
>> +    if (!prop)
>> +        return -ENOMEM;
>> +    adev->mode_info.plane_lut3d_size_property = prop;
>> +
>>       return 0;
>>   }
>>   #endif
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> index ae64d4b73360..068798ffdd56 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> @@ -1359,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane 
>> *plane)
>>       if (dm_plane_state->degamma_lut)
>>           drm_property_blob_get(dm_plane_state->degamma_lut);
>> +    if (dm_plane_state->lut3d)
>> +        drm_property_blob_get(dm_plane_state->lut3d);
> 
> This is wrong, and was breaking state restoration on suspend.
> 
> dm_plane_state->lut3d is always NULL as it's the new zero-ed state, you 
> need to check the old_dm_plane_state's values and then set it on the new 
> state after _get.
> 
> It should be like this: (based on end of the patchset).
> 
>      if (old_dm_plane_state->degamma_lut) {
>          drm_property_blob_get(old_dm_plane_state->degamma_lut);
>          dm_plane_state->degamma_lut = old_dm_plane_state->degamma_lut;
>      }
>      if (old_dm_plane_state->ctm) {
>          drm_property_blob_get(old_dm_plane_state->ctm);
>          dm_plane_state->ctm = old_dm_plane_state->ctm;
>      }
>      if (old_dm_plane_state->shaper_lut) {
>          drm_property_blob_get(old_dm_plane_state->shaper_lut);
>          dm_plane_state->shaper_lut = old_dm_plane_state->shaper_lut;
>      }
>      if (old_dm_plane_state->lut3d) {
>          drm_property_blob_get(old_dm_plane_state->lut3d);
>          dm_plane_state->lut3d = old_dm_plane_state->lut3d;
>      }
>      if (old_dm_plane_state->blend_lut) {
>          drm_property_blob_get(old_dm_plane_state->blend_lut);
>          dm_plane_state->blend_lut = old_dm_plane_state->blend_lut;
>      }
> 
> because it doesn't do the memcpy like the base drm atomic stuff.
> 
> I also had to add a patch to ensure color mgmt was updated on unsuspend 
> always too, but that's not related to this patchset and also affected 
> stuff beforehand.
> 
> I'll send that patch in a bit.
> 
> Thanks!
> - Joshie 🐸✨
> 
>>       dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
>>       dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
>> @@ -1432,6 +1434,8 @@ static void dm_drm_plane_destroy_state(struct 
>> drm_plane *plane,
>>       if (dm_plane_state->degamma_lut)
>>           drm_property_blob_put(dm_plane_state->degamma_lut);
>> +    if (dm_plane_state->lut3d)
>> +        drm_property_blob_put(dm_plane_state->lut3d);
>>       if (dm_plane_state->dc_state)
>>           dc_plane_state_release(dm_plane_state->dc_state);
>> @@ -1462,6 +1466,14 @@ 
>> dm_atomic_plane_attach_color_mgmt_properties(struct 
>> amdgpu_display_manager *dm,
>>       drm_object_attach_property(&plane->base,
>>                      dm->adev->mode_info.plane_hdr_mult_property,
>>                      AMDGPU_HDR_MULT_DEFAULT);
>> +
>> +    if (dpp_color_caps.hw_3d_lut) {
>> +        drm_object_attach_property(&plane->base,
>> +                       mode_info.plane_lut3d_property, 0);
>> +        drm_object_attach_property(&plane->base,
>> +                       mode_info.plane_lut3d_size_property,
>> +                       MAX_COLOR_3DLUT_SIZE);
>> +    }
>>   }
>>   static int
>> @@ -1493,6 +1505,14 @@ dm_atomic_plane_set_property(struct drm_plane 
>> *plane,
>>               dm_plane_state->hdr_mult = val;
>>               dm_plane_state->base.color_mgmt_changed = 1;
>>           }
>> +    } else if (property == adev->mode_info.plane_lut3d_property) {
>> +        ret = drm_property_replace_blob_from_id(plane->dev,
>> +                            &dm_plane_state->lut3d,
>> +                            val, -1,
>> +                            sizeof(struct drm_color_lut),
>> +                            &replaced);
>> +        dm_plane_state->base.color_mgmt_changed |= replaced;
>> +        return ret;
>>       } else {
>>           drm_dbg_atomic(plane->dev,
>>                      "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
>> @@ -1520,6 +1540,9 @@ dm_atomic_plane_get_property(struct drm_plane 
>> *plane,
>>           *val = dm_plane_state->degamma_tf;
>>       } else if (property == adev->mode_info.plane_hdr_mult_property) {
>>           *val = dm_plane_state->hdr_mult;
>> +    } else     if (property == adev->mode_info.plane_lut3d_property) {
>> +        *val = (dm_plane_state->lut3d) ?
>> +            dm_plane_state->lut3d->base.id : 0;
>>       } else {
>>           return -EINVAL;
>>       }

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties
  2023-10-06  9:09   ` Sebastian Wick
@ 2023-11-06 18:46     ` Melissa Wen
  0 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-11-06 18:46 UTC (permalink / raw)
  To: Sebastian Wick
  Cc: Pekka Paalanen, kernel-dev, Shashank Sharma, sunpeng.li,
	Xinhui.Pan, Rodrigo Siqueira, Xaver Hugl, dri-devel,
	Nicholas Kazlauskas, Alex Hung, amd-gfx, Alex Deucher,
	christian.koenig, Joshua Ashton, sungjoon.kim

On 10/06, Sebastian Wick wrote:
> On Thu, Oct 05, 2023 at 04:15:04PM -0100, Melissa Wen wrote:
> > Add 3D LUT property for plane color transformations using a 3D lookup
> > table. 3D LUT allows for highly accurate and complex color
> > transformations and is suitable to adjust the balance between color
> > channels. It's also more complex to manage and require more
> > computational resources.
> > 
> > Since a 3D LUT has a limited number of entries in each dimension we want
> > to use them in an optimal fashion. This means using the 3D LUT in a
> > colorspace that is optimized for human vision, such as sRGB, PQ, or
> > another non-linear space. Therefore, userpace may need one 1D LUT
> > (shaper) before it to delinearize content and another 1D LUT after 3D
> > LUT (blend) to linearize content again for blending. The next patches
> > add these 1D LUTs to the plane color mgmt pipeline.
> > 
> > v3:
> > - improve commit message about 3D LUT
> > - describe the 3D LUT entries and size (Harry)
> > 
> > v4:
> > - advertise 3D LUT max size as the size of a single-dimension
> > 
> > Signed-off-by: Melissa Wen <mwen@igalia.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 18 +++++++++++++++
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  9 ++++++++
> >  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 14 +++++++++++
> >  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 23 +++++++++++++++++++
> >  4 files changed, 64 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > index 62044d41da75..f7adaa52c23f 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > @@ -363,6 +363,24 @@ struct amdgpu_mode_info {
> >  	 * @plane_hdr_mult_property:
> >  	 */
> >  	struct drm_property *plane_hdr_mult_property;
> > +	/**
> > +	 * @plane_lut3d_property: Plane property for color transformation using
> > +	 * a 3D LUT (pre-blending), a three-dimensional array where each
> > +	 * element is an RGB triplet. Each dimension has a size of the cubed
> > +	 * root of lut3d_size. The array contains samples from the approximated
> 
> This should be "Each dimension has a size of lut3d_size" now.

You're right. Thanks for pointed it out.

> 
> > +	 * function. On AMD, values between samples are estimated by
> > +	 * tetrahedral interpolation. The array is accessed with three indices,
> > +	 * one for each input dimension (color channel), blue being the
> > +	 * outermost dimension, red the innermost.
> > +	 */
> > +	struct drm_property *plane_lut3d_property;
> > +	/**
> > +	 * @plane_degamma_lut_size_property: Plane property to define the max
> > +	 * size of 3D LUT as supported by the driver (read-only). The max size
> > +	 * is the max size of one dimension and, therefore, the max number of
> > +	 * entries for 3D LUT array is the 3D LUT size cubed;
> > +	 */
> > +	struct drm_property *plane_lut3d_size_property;
> >  };
> >  
> >  #define AMDGPU_MAX_BL_LEVEL 0xFF
> > 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 bb2ce843369d..7a2350c62cf1 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > @@ -784,6 +784,11 @@ struct dm_plane_state {
> >  	 * TF is needed for any subsequent linear-to-non-linear transforms.
> >  	 */
> >  	__u64 hdr_mult;
> > +	/**
> > +	 * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
> > +	 * &struct drm_color_lut.
> > +	 */
> > +	struct drm_property_blob *lut3d;
> >  };
> >  
> >  struct dm_crtc_state {
> > @@ -869,6 +874,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
> >  
> >  void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
> >  
> > +/* 3D LUT max size is 17x17x17 (4913 entries) */
> > +#define MAX_COLOR_3DLUT_SIZE 17
> > +#define MAX_COLOR_3DLUT_BITDEPTH 12
> > +/* 1D LUT size */
> >  #define MAX_COLOR_LUT_ENTRIES 4096
> >  /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
> >  #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
> > 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 caf49a044ab4..011f2f9ec890 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
> > @@ -230,6 +230,20 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
> >  		return -ENOMEM;
> >  	adev->mode_info.plane_hdr_mult_property = prop;
> >  
> > +	prop = drm_property_create(adev_to_drm(adev),
> > +				   DRM_MODE_PROP_BLOB,
> > +				   "AMD_PLANE_LUT3D", 0);
> > +	if (!prop)
> > +		return -ENOMEM;
> > +	adev->mode_info.plane_lut3d_property = prop;
> > +
> > +	prop = drm_property_create_range(adev_to_drm(adev),
> > +					 DRM_MODE_PROP_IMMUTABLE,
> > +					 "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
> > +	if (!prop)
> > +		return -ENOMEM;
> > +	adev->mode_info.plane_lut3d_size_property = prop;
> > +
> >  	return 0;
> >  }
> >  #endif
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > index ae64d4b73360..068798ffdd56 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > @@ -1359,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
> >  
> >  	if (dm_plane_state->degamma_lut)
> >  		drm_property_blob_get(dm_plane_state->degamma_lut);
> > +	if (dm_plane_state->lut3d)
> > +		drm_property_blob_get(dm_plane_state->lut3d);
> >  
> >  	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
> >  	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
> > @@ -1432,6 +1434,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
> >  
> >  	if (dm_plane_state->degamma_lut)
> >  		drm_property_blob_put(dm_plane_state->degamma_lut);
> > +	if (dm_plane_state->lut3d)
> > +		drm_property_blob_put(dm_plane_state->lut3d);
> >  
> >  	if (dm_plane_state->dc_state)
> >  		dc_plane_state_release(dm_plane_state->dc_state);
> > @@ -1462,6 +1466,14 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
> >  	drm_object_attach_property(&plane->base,
> >  				   dm->adev->mode_info.plane_hdr_mult_property,
> >  				   AMDGPU_HDR_MULT_DEFAULT);
> > +
> > +	if (dpp_color_caps.hw_3d_lut) {
> > +		drm_object_attach_property(&plane->base,
> > +					   mode_info.plane_lut3d_property, 0);
> > +		drm_object_attach_property(&plane->base,
> > +					   mode_info.plane_lut3d_size_property,
> > +					   MAX_COLOR_3DLUT_SIZE);
> > +	}
> >  }
> >  
> >  static int
> > @@ -1493,6 +1505,14 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
> >  			dm_plane_state->hdr_mult = val;
> >  			dm_plane_state->base.color_mgmt_changed = 1;
> >  		}
> > +	} else if (property == adev->mode_info.plane_lut3d_property) {
> > +		ret = drm_property_replace_blob_from_id(plane->dev,
> > +							&dm_plane_state->lut3d,
> > +							val, -1,
> > +							sizeof(struct drm_color_lut),
> > +							&replaced);
> > +		dm_plane_state->base.color_mgmt_changed |= replaced;
> > +		return ret;
> >  	} else {
> >  		drm_dbg_atomic(plane->dev,
> >  			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> > @@ -1520,6 +1540,9 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
> >  		*val = dm_plane_state->degamma_tf;
> >  	} else if (property == adev->mode_info.plane_hdr_mult_property) {
> >  		*val = dm_plane_state->hdr_mult;
> > +	} else 	if (property == adev->mode_info.plane_lut3d_property) {
> > +		*val = (dm_plane_state->lut3d) ?
> > +			dm_plane_state->lut3d->base.id : 0;
> >  	} else {
> >  		return -EINVAL;
> >  	}
> > -- 
> > 2.40.1
> > 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties
  2023-11-02  3:48   ` Joshua Ashton
  2023-11-02  7:31     ` Joshua Ashton
@ 2023-11-06 18:49     ` Melissa Wen
  1 sibling, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-11-06 18:49 UTC (permalink / raw)
  To: Joshua Ashton
  Cc: Sebastian Wick, Pekka Paalanen, kernel-dev, Shashank Sharma,
	sunpeng.li, Xinhui.Pan, Rodrigo Siqueira, Xaver Hugl, dri-devel,
	Nicholas Kazlauskas, Alex Hung, amd-gfx, Alex Deucher,
	christian.koenig, sungjoon.kim

On 11/02, Joshua Ashton wrote:
> 
> 
> On 10/5/23 18:15, Melissa Wen wrote:
> > Add 3D LUT property for plane color transformations using a 3D lookup
> > table. 3D LUT allows for highly accurate and complex color
> > transformations and is suitable to adjust the balance between color
> > channels. It's also more complex to manage and require more
> > computational resources.
> > 
> > Since a 3D LUT has a limited number of entries in each dimension we want
> > to use them in an optimal fashion. This means using the 3D LUT in a
> > colorspace that is optimized for human vision, such as sRGB, PQ, or
> > another non-linear space. Therefore, userpace may need one 1D LUT
> > (shaper) before it to delinearize content and another 1D LUT after 3D
> > LUT (blend) to linearize content again for blending. The next patches
> > add these 1D LUTs to the plane color mgmt pipeline.
> > 
> > v3:
> > - improve commit message about 3D LUT
> > - describe the 3D LUT entries and size (Harry)
> > 
> > v4:
> > - advertise 3D LUT max size as the size of a single-dimension
> > 
> > Signed-off-by: Melissa Wen <mwen@igalia.com>
> > ---
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 18 +++++++++++++++
> >   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  9 ++++++++
> >   .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 14 +++++++++++
> >   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 23 +++++++++++++++++++
> >   4 files changed, 64 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > index 62044d41da75..f7adaa52c23f 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > @@ -363,6 +363,24 @@ struct amdgpu_mode_info {
> >   	 * @plane_hdr_mult_property:
> >   	 */
> >   	struct drm_property *plane_hdr_mult_property;
> > +	/**
> > +	 * @plane_lut3d_property: Plane property for color transformation using
> > +	 * a 3D LUT (pre-blending), a three-dimensional array where each
> > +	 * element is an RGB triplet. Each dimension has a size of the cubed
> > +	 * root of lut3d_size. The array contains samples from the approximated
> > +	 * function. On AMD, values between samples are estimated by
> > +	 * tetrahedral interpolation. The array is accessed with three indices,
> > +	 * one for each input dimension (color channel), blue being the
> > +	 * outermost dimension, red the innermost.
> > +	 */
> > +	struct drm_property *plane_lut3d_property;
> > +	/**
> > +	 * @plane_degamma_lut_size_property: Plane property to define the max
> > +	 * size of 3D LUT as supported by the driver (read-only). The max size
> > +	 * is the max size of one dimension and, therefore, the max number of
> > +	 * entries for 3D LUT array is the 3D LUT size cubed;
> > +	 */
> > +	struct drm_property *plane_lut3d_size_property;
> >   };
> >   #define AMDGPU_MAX_BL_LEVEL 0xFF
> > 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 bb2ce843369d..7a2350c62cf1 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > @@ -784,6 +784,11 @@ struct dm_plane_state {
> >   	 * TF is needed for any subsequent linear-to-non-linear transforms.
> >   	 */
> >   	__u64 hdr_mult;
> > +	/**
> > +	 * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
> > +	 * &struct drm_color_lut.
> > +	 */
> > +	struct drm_property_blob *lut3d;
> >   };
> >   struct dm_crtc_state {
> > @@ -869,6 +874,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
> >   void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
> > +/* 3D LUT max size is 17x17x17 (4913 entries) */
> > +#define MAX_COLOR_3DLUT_SIZE 17
> > +#define MAX_COLOR_3DLUT_BITDEPTH 12
> > +/* 1D LUT size */
> >   #define MAX_COLOR_LUT_ENTRIES 4096
> >   /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
> >   #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
> > 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 caf49a044ab4..011f2f9ec890 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
> > @@ -230,6 +230,20 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
> >   		return -ENOMEM;
> >   	adev->mode_info.plane_hdr_mult_property = prop;
> > +	prop = drm_property_create(adev_to_drm(adev),
> > +				   DRM_MODE_PROP_BLOB,
> > +				   "AMD_PLANE_LUT3D", 0);
> > +	if (!prop)
> > +		return -ENOMEM;
> > +	adev->mode_info.plane_lut3d_property = prop;
> > +
> > +	prop = drm_property_create_range(adev_to_drm(adev),
> > +					 DRM_MODE_PROP_IMMUTABLE,
> > +					 "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
> > +	if (!prop)
> > +		return -ENOMEM;
> > +	adev->mode_info.plane_lut3d_size_property = prop;
> > +
> >   	return 0;
> >   }
> >   #endif
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > index ae64d4b73360..068798ffdd56 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > @@ -1359,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
> >   	if (dm_plane_state->degamma_lut)
> >   		drm_property_blob_get(dm_plane_state->degamma_lut);
> > +	if (dm_plane_state->lut3d)
> > +		drm_property_blob_get(dm_plane_state->lut3d);
> 
> This is wrong, and was breaking state restoration on suspend.
> 
> dm_plane_state->lut3d is always NULL as it's the new zero-ed state, you need
> to check the old_dm_plane_state's values and then set it on the new state
> after _get.
> 
> It should be like this: (based on end of the patchset).
> 
> 	if (old_dm_plane_state->degamma_lut) {
> 		drm_property_blob_get(old_dm_plane_state->degamma_lut);
> 		dm_plane_state->degamma_lut = old_dm_plane_state->degamma_lut;
> 	}
> 	if (old_dm_plane_state->ctm) {
> 		drm_property_blob_get(old_dm_plane_state->ctm);
> 		dm_plane_state->ctm = old_dm_plane_state->ctm;
> 	}
> 	if (old_dm_plane_state->shaper_lut) {
> 		drm_property_blob_get(old_dm_plane_state->shaper_lut);
> 		dm_plane_state->shaper_lut = old_dm_plane_state->shaper_lut;
> 	}
> 	if (old_dm_plane_state->lut3d) {
> 		drm_property_blob_get(old_dm_plane_state->lut3d);
> 		dm_plane_state->lut3d = old_dm_plane_state->lut3d;
> 	}
> 	if (old_dm_plane_state->blend_lut) {
> 		drm_property_blob_get(old_dm_plane_state->blend_lut);
> 		dm_plane_state->blend_lut = old_dm_plane_state->blend_lut;
> 	}
> 
> because it doesn't do the memcpy like the base drm atomic stuff.

Nice catch! I'll update all related patches in the next version.

Thank you!

Melissa

> 
> I also had to add a patch to ensure color mgmt was updated on unsuspend
> always too, but that's not related to this patchset and also affected stuff
> beforehand.
> 
> I'll send that patch in a bit.
> 
> Thanks!
> - Joshie 🐸✨
> 
> >   	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
> >   	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
> > @@ -1432,6 +1434,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
> >   	if (dm_plane_state->degamma_lut)
> >   		drm_property_blob_put(dm_plane_state->degamma_lut);
> > +	if (dm_plane_state->lut3d)
> > +		drm_property_blob_put(dm_plane_state->lut3d);
> >   	if (dm_plane_state->dc_state)
> >   		dc_plane_state_release(dm_plane_state->dc_state);
> > @@ -1462,6 +1466,14 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
> >   	drm_object_attach_property(&plane->base,
> >   				   dm->adev->mode_info.plane_hdr_mult_property,
> >   				   AMDGPU_HDR_MULT_DEFAULT);
> > +
> > +	if (dpp_color_caps.hw_3d_lut) {
> > +		drm_object_attach_property(&plane->base,
> > +					   mode_info.plane_lut3d_property, 0);
> > +		drm_object_attach_property(&plane->base,
> > +					   mode_info.plane_lut3d_size_property,
> > +					   MAX_COLOR_3DLUT_SIZE);
> > +	}
> >   }
> >   static int
> > @@ -1493,6 +1505,14 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
> >   			dm_plane_state->hdr_mult = val;
> >   			dm_plane_state->base.color_mgmt_changed = 1;
> >   		}
> > +	} else if (property == adev->mode_info.plane_lut3d_property) {
> > +		ret = drm_property_replace_blob_from_id(plane->dev,
> > +							&dm_plane_state->lut3d,
> > +							val, -1,
> > +							sizeof(struct drm_color_lut),
> > +							&replaced);
> > +		dm_plane_state->base.color_mgmt_changed |= replaced;
> > +		return ret;
> >   	} else {
> >   		drm_dbg_atomic(plane->dev,
> >   			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> > @@ -1520,6 +1540,9 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
> >   		*val = dm_plane_state->degamma_tf;
> >   	} else if (property == adev->mode_info.plane_hdr_mult_property) {
> >   		*val = dm_plane_state->hdr_mult;
> > +	} else 	if (property == adev->mode_info.plane_lut3d_property) {
> > +		*val = (dm_plane_state->lut3d) ?
> > +			dm_plane_state->lut3d->base.id : 0;
> >   	} else {
> >   		return -EINVAL;
> >   	}

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties
  2023-11-02  7:31     ` Joshua Ashton
@ 2023-11-06 18:52       ` Melissa Wen
  0 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-11-06 18:52 UTC (permalink / raw)
  To: Joshua Ashton
  Cc: Sebastian Wick, Pekka Paalanen, kernel-dev, Shashank Sharma,
	sunpeng.li, Xinhui.Pan, Rodrigo Siqueira, Xaver Hugl, dri-devel,
	Nicholas Kazlauskas, Alex Hung, amd-gfx, Alex Deucher,
	christian.koenig, sungjoon.kim

On 11/02, Joshua Ashton wrote:
> Also, Melissa, you cannot do:
> 
> 	if (!plane_state->color_mgmt_changed)
> 		return 0;
> 
> in amdgpu_dm_plane_set_color_properties.
> 
> The allocation for dc_plane_state could be new and zero'ed so it needs to be
> set every time. (Until AMDGPU has better dedup'ing of stuff there)
> 
> The reason it looked like it worked for you now is because the duplicate was
> broken, so color mgmt for planes was always being marked as dirty there.

I see, it makes sense. I'll double-check it out, but thanks again for
debugging the issue.

BR,

Melissa

> 
> Thanks
> 
> - Joshie 🐸✨
> 
> On 11/2/23 03:48, Joshua Ashton wrote:
> > 
> > 
> > On 10/5/23 18:15, Melissa Wen wrote:
> > > Add 3D LUT property for plane color transformations using a 3D lookup
> > > table. 3D LUT allows for highly accurate and complex color
> > > transformations and is suitable to adjust the balance between color
> > > channels. It's also more complex to manage and require more
> > > computational resources.
> > > 
> > > Since a 3D LUT has a limited number of entries in each dimension we want
> > > to use them in an optimal fashion. This means using the 3D LUT in a
> > > colorspace that is optimized for human vision, such as sRGB, PQ, or
> > > another non-linear space. Therefore, userpace may need one 1D LUT
> > > (shaper) before it to delinearize content and another 1D LUT after 3D
> > > LUT (blend) to linearize content again for blending. The next patches
> > > add these 1D LUTs to the plane color mgmt pipeline.
> > > 
> > > v3:
> > > - improve commit message about 3D LUT
> > > - describe the 3D LUT entries and size (Harry)
> > > 
> > > v4:
> > > - advertise 3D LUT max size as the size of a single-dimension
> > > 
> > > Signed-off-by: Melissa Wen <mwen@igalia.com>
> > > ---
> > >   drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 18 +++++++++++++++
> > >   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  9 ++++++++
> > >   .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 14 +++++++++++
> > >   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 23 +++++++++++++++++++
> > >   4 files changed, 64 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > > index 62044d41da75..f7adaa52c23f 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > > @@ -363,6 +363,24 @@ struct amdgpu_mode_info {
> > >        * @plane_hdr_mult_property:
> > >        */
> > >       struct drm_property *plane_hdr_mult_property;
> > > +    /**
> > > +     * @plane_lut3d_property: Plane property for color
> > > transformation using
> > > +     * a 3D LUT (pre-blending), a three-dimensional array where each
> > > +     * element is an RGB triplet. Each dimension has a size of the cubed
> > > +     * root of lut3d_size. The array contains samples from the
> > > approximated
> > > +     * function. On AMD, values between samples are estimated by
> > > +     * tetrahedral interpolation. The array is accessed with three
> > > indices,
> > > +     * one for each input dimension (color channel), blue being the
> > > +     * outermost dimension, red the innermost.
> > > +     */
> > > +    struct drm_property *plane_lut3d_property;
> > > +    /**
> > > +     * @plane_degamma_lut_size_property: Plane property to define
> > > the max
> > > +     * size of 3D LUT as supported by the driver (read-only). The
> > > max size
> > > +     * is the max size of one dimension and, therefore, the max
> > > number of
> > > +     * entries for 3D LUT array is the 3D LUT size cubed;
> > > +     */
> > > +    struct drm_property *plane_lut3d_size_property;
> > >   };
> > >   #define AMDGPU_MAX_BL_LEVEL 0xFF
> > > 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 bb2ce843369d..7a2350c62cf1 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > > @@ -784,6 +784,11 @@ struct dm_plane_state {
> > >        * TF is needed for any subsequent linear-to-non-linear transforms.
> > >        */
> > >       __u64 hdr_mult;
> > > +    /**
> > > +     * @lut3d: 3D lookup table blob. The blob (if not NULL) is an
> > > array of
> > > +     * &struct drm_color_lut.
> > > +     */
> > > +    struct drm_property_blob *lut3d;
> > >   };
> > >   struct dm_crtc_state {
> > > @@ -869,6 +874,10 @@ void amdgpu_dm_update_freesync_caps(struct
> > > drm_connector *connector,
> > >   void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
> > > +/* 3D LUT max size is 17x17x17 (4913 entries) */
> > > +#define MAX_COLOR_3DLUT_SIZE 17
> > > +#define MAX_COLOR_3DLUT_BITDEPTH 12
> > > +/* 1D LUT size */
> > >   #define MAX_COLOR_LUT_ENTRIES 4096
> > >   /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
> > >   #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
> > > 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 caf49a044ab4..011f2f9ec890 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
> > > @@ -230,6 +230,20 @@ amdgpu_dm_create_color_properties(struct
> > > amdgpu_device *adev)
> > >           return -ENOMEM;
> > >       adev->mode_info.plane_hdr_mult_property = prop;
> > > +    prop = drm_property_create(adev_to_drm(adev),
> > > +                   DRM_MODE_PROP_BLOB,
> > > +                   "AMD_PLANE_LUT3D", 0);
> > > +    if (!prop)
> > > +        return -ENOMEM;
> > > +    adev->mode_info.plane_lut3d_property = prop;
> > > +
> > > +    prop = drm_property_create_range(adev_to_drm(adev),
> > > +                     DRM_MODE_PROP_IMMUTABLE,
> > > +                     "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
> > > +    if (!prop)
> > > +        return -ENOMEM;
> > > +    adev->mode_info.plane_lut3d_size_property = prop;
> > > +
> > >       return 0;
> > >   }
> > >   #endif
> > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > > index ae64d4b73360..068798ffdd56 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> > > @@ -1359,6 +1359,8 @@ dm_drm_plane_duplicate_state(struct drm_plane
> > > *plane)
> > >       if (dm_plane_state->degamma_lut)
> > >           drm_property_blob_get(dm_plane_state->degamma_lut);
> > > +    if (dm_plane_state->lut3d)
> > > +        drm_property_blob_get(dm_plane_state->lut3d);
> > 
> > This is wrong, and was breaking state restoration on suspend.
> > 
> > dm_plane_state->lut3d is always NULL as it's the new zero-ed state, you
> > need to check the old_dm_plane_state's values and then set it on the new
> > state after _get.
> > 
> > It should be like this: (based on end of the patchset).
> > 
> >      if (old_dm_plane_state->degamma_lut) {
> >          drm_property_blob_get(old_dm_plane_state->degamma_lut);
> >          dm_plane_state->degamma_lut = old_dm_plane_state->degamma_lut;
> >      }
> >      if (old_dm_plane_state->ctm) {
> >          drm_property_blob_get(old_dm_plane_state->ctm);
> >          dm_plane_state->ctm = old_dm_plane_state->ctm;
> >      }
> >      if (old_dm_plane_state->shaper_lut) {
> >          drm_property_blob_get(old_dm_plane_state->shaper_lut);
> >          dm_plane_state->shaper_lut = old_dm_plane_state->shaper_lut;
> >      }
> >      if (old_dm_plane_state->lut3d) {
> >          drm_property_blob_get(old_dm_plane_state->lut3d);
> >          dm_plane_state->lut3d = old_dm_plane_state->lut3d;
> >      }
> >      if (old_dm_plane_state->blend_lut) {
> >          drm_property_blob_get(old_dm_plane_state->blend_lut);
> >          dm_plane_state->blend_lut = old_dm_plane_state->blend_lut;
> >      }
> > 
> > because it doesn't do the memcpy like the base drm atomic stuff.
> > 
> > I also had to add a patch to ensure color mgmt was updated on unsuspend
> > always too, but that's not related to this patchset and also affected
> > stuff beforehand.
> > 
> > I'll send that patch in a bit.
> > 
> > Thanks!
> > - Joshie 🐸✨
> > 
> > >       dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
> > >       dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
> > > @@ -1432,6 +1434,8 @@ static void dm_drm_plane_destroy_state(struct
> > > drm_plane *plane,
> > >       if (dm_plane_state->degamma_lut)
> > >           drm_property_blob_put(dm_plane_state->degamma_lut);
> > > +    if (dm_plane_state->lut3d)
> > > +        drm_property_blob_put(dm_plane_state->lut3d);
> > >       if (dm_plane_state->dc_state)
> > >           dc_plane_state_release(dm_plane_state->dc_state);
> > > @@ -1462,6 +1466,14 @@
> > > dm_atomic_plane_attach_color_mgmt_properties(struct
> > > amdgpu_display_manager *dm,
> > >       drm_object_attach_property(&plane->base,
> > >                      dm->adev->mode_info.plane_hdr_mult_property,
> > >                      AMDGPU_HDR_MULT_DEFAULT);
> > > +
> > > +    if (dpp_color_caps.hw_3d_lut) {
> > > +        drm_object_attach_property(&plane->base,
> > > +                       mode_info.plane_lut3d_property, 0);
> > > +        drm_object_attach_property(&plane->base,
> > > +                       mode_info.plane_lut3d_size_property,
> > > +                       MAX_COLOR_3DLUT_SIZE);
> > > +    }
> > >   }
> > >   static int
> > > @@ -1493,6 +1505,14 @@ dm_atomic_plane_set_property(struct drm_plane
> > > *plane,
> > >               dm_plane_state->hdr_mult = val;
> > >               dm_plane_state->base.color_mgmt_changed = 1;
> > >           }
> > > +    } else if (property == adev->mode_info.plane_lut3d_property) {
> > > +        ret = drm_property_replace_blob_from_id(plane->dev,
> > > +                            &dm_plane_state->lut3d,
> > > +                            val, -1,
> > > +                            sizeof(struct drm_color_lut),
> > > +                            &replaced);
> > > +        dm_plane_state->base.color_mgmt_changed |= replaced;
> > > +        return ret;
> > >       } else {
> > >           drm_dbg_atomic(plane->dev,
> > >                      "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> > > @@ -1520,6 +1540,9 @@ dm_atomic_plane_get_property(struct drm_plane
> > > *plane,
> > >           *val = dm_plane_state->degamma_tf;
> > >       } else if (property == adev->mode_info.plane_hdr_mult_property) {
> > >           *val = dm_plane_state->hdr_mult;
> > > +    } else     if (property == adev->mode_info.plane_lut3d_property) {
> > > +        *val = (dm_plane_state->lut3d) ?
> > > +            dm_plane_state->lut3d->base.id : 0;
> > >       } else {
> > >           return -EINVAL;
> > >       }

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt
  2023-10-06  9:28 ` [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Sebastian Wick
@ 2023-11-06 19:33   ` Melissa Wen
  0 siblings, 0 replies; 47+ messages in thread
From: Melissa Wen @ 2023-11-06 19:33 UTC (permalink / raw)
  To: Sebastian Wick
  Cc: liviu.dudau, dri-devel, Shashank Sharma, Rodrigo Siqueira,
	amd-gfx, Alex Hung, kernel-dev, sunpeng.li, mripard,
	sungjoon.kim, Pekka Paalanen, Xinhui.Pan, Xaver Hugl,
	Nicholas Kazlauskas, tzimmermann, Alex Deucher, christian.koenig,
	Joshua Ashton

On 10/06, Sebastian Wick wrote:
> On Thu, Oct 05, 2023 at 04:14:55PM -0100, Melissa Wen wrote:
> > Hello,
> > 
> > Just another iteration for AMD driver-specific color properties.
> > Basically, addressing comments from the previous version.
> > 
> > Recap: this series extends the current KMS color management API with AMD
> > driver-specific properties to enhance the color management support on
> > AMD Steam Deck. The key additions to the color pipeline include:
> 
> Did you talk with the maintainers about this already? The last few times
> driver specific properties, and even kind of generic plane properties
> with a fixed position in the pipeline were proposed they were all
> NAKed. Just putting them behind a define doesn't sound great and I don't
> think there is any precedence for allowing this in. This is basically
> just more burden for upstream without any benefits for upstream.

Hi Sebastian,

Sorry for delaying. I believe it was already answered during the XDC KMS
color workshop, but: yes, I've talked with them and they are fine with
the cflags approach. Remember that we are not using here kconfig anymore.
The driver-specific properties (creation and attachment) are guarded by
cflags, not a kernel building option. We changed to cflags after Harry's
suggestion in the first version.

I think the main point for upstream it now is that we can actually
exercise the plane color properties and all machinery around new color
elements (as 3D LUT) with a userspace that cares about it (Gamescope).
Worth mentioning that I removed CRTC shaper/3D LUT support from previous
version, because, even with the internal implementation, we don't have
how to exercise these CRTC properties right now.

Finally, the main goal is ofc attaching it to the generic API from
Harry's series. We are all in the same page about it.

BR,

Melissa

> 
> Maybe you can separate the uAPI changes from the internal improvements
> to land at least parts of this faster.
> 
> > - plane degamma LUT and pre-defined TF;
> > - plane HDR multiplier;
> > - plane CTM 3x4;
> > - plane shaper LUT and pre-defined TF;
> > - plane 3D LUT;
> > - plane blend LUT and pre-defined TF;
> > - CRTC gamma pre-defined TF;
> > 
> > You can find the AMD HW color capabilities documented here:
> > https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/display-manager.html#color-management-properties
> > 
> > The userspace case is Gamescope[1], the compositor for SteamOS.
> > Gamescope has already adopted AMD driver-specific properties to
> > implement comprehensive color management support, including gamut
> > mapping, HDR rendering, SDR on HDR, HDR on SDR. Using these features in
> > the SteamOS 3.5[2] users can expect a significantly enhanced visual
> > experience. 
> > 
> > You can find a brief overview of the Steam Deck color pipeline here:
> > https://github.com/ValveSoftware/gamescope/blob/master/src/docs/Steam%20Deck%20Display%20Pipeline.png
> > 
> > Changes from:
> > 
> > [RFC] https://lore.kernel.org/dri-devel/20230423141051.702990-1-mwen@igalia.com
> > - Remove KConfig and guard properties with `AMD_PRIVATE_COLOR`;
> > - Remove properties for post-blending/CRTC shaper TF+LUT and 3D LUT;
> > - Use color caps to improve the support of pre-defined curve;
> > 
> > [v1] https://lore.kernel.org/dri-devel/20230523221520.3115570-1-mwen@igalia.com
> > - Replace DRM_ by AMDGPU_ prefix for transfer function (TF) enum; 
> > - Explicitly define EOTFs and inverse EOTFs and set props accordingly;
> > - Document pre-defined transfer functions;
> > - Remove HLG transfer function from supported TFs;
> > - Remove misleading comments;
> > - Remove post-blending shaper TF+LUT and 3D LUT support;
> > - Move driver-specific property operations from amdgpu_display.c to
> >   amdgpu_dm_color.c;
> > - Reset planes if any color props change;
> > - Add plane CTM 3x4 support;
> > - Removed two DC fixes already applied upstream;
> > 
> > [v2] https://lore.kernel.org/dri-devel/20230810160314.48225-1-mwen@igalia.com
> > - Many documentation fixes: BT.709 OETF, description of sRGB and pure
> >   power functions, TF+1D LUT behavior;
> > - Rename CTM2 to CTM 3x4 and fix misleading comment about DC gamut remap;
> > - Squash `Linear` and `Unity` TF in `Identity`;
> > - Remove the `MPC gamut remap` patch already applied upstream[3];
> > - Remove outdated delta segmentation fix;
> > - Nits/small fixes;
> > 
> > [v3] https://lore.kernel.org/amd-gfx/20230925194932.1329483-1-mwen@igalia.com
> > - Add table to describe value range in linear and non-linear forms
> > - Comment the PQ TF need after HDR multiplier
> > - Advertise the 3D LUT size as the size of a single-dimension (read-only)
> > - remove function to check expected size from 3DLUT caps
> > - cleanup comments
> > 
> > It's worth noting that driver-specific properties are guarded by
> > `AMD_PRIVATE_COLOR`. So, finally, this is the color management API when
> > driver-specific properties are enabled:
> > 
> > +----------------------+
> > |   PLANE              |
> > |                      |
> > |  +----------------+  |
> > |  | AMD Degamma    |  |
> > |  |                |  |
> > |  | EOTF | 1D LUT  |  |
> > |  +--------+-------+  |
> > |           |          |
> > |  +--------v-------+  |
> > |  |    AMD HDR     |  |
> > |  |    Multiply    |  |
> > |  +--------+-------+  |
> > |           |          |
> > |  +--------v-------+  |
> > |  |  AMD CTM (3x4) |  |
> > |  +--------+-------+  |
> > |           |          |
> > |  +--------v-------+  |
> > |  | AMD Shaper     |  |
> > |  |                |  |
> > |  | inv_EOTF |     |  |
> > |  | Custom 1D LUT  |  |
> > |  +--------+-------+  |
> > |           |          |
> > |  +--------v-------+  |
> > |  |   AMD 3D LUT   |  |
> > |  |   17^3/12-bit  |  |
> > |  +--------+-------+  |
> > |           |          |
> > |  +--------v-------+  |
> > |  | AMD Blend      |  |
> > |  |                |  |
> > |  | EOTF | 1D LUT  |  |
> > |  +--------+-------+  |
> > |           |          |
> > ++----------v---------++
> > ||      Blending      ||
> > ++----------+---------++
> > |    CRTC   |          |
> > |           |          |
> > |   +-------v-------+  |
> > |   | DRM Degamma   |  |
> > |   |               |  |
> > |   | Custom 1D LUT |  |
> > |   +-------+-------+  |
> > |           |          |
> > |   +-------v-------+  |
> > |   | DRM CTM (3x3) |  |
> > |   +-------+-------+  |
> > |           |          |
> > |   +-------v-------+  |
> > |   | DRM Gamma     |  |
> > |   |               |  |
> > |   | Custom 1D LUT |  |
> > |   +---------------+  |
> > |   | *AMD Gamma    |  |
> > |   |   inv_EOTF    |  |
> > |   +---------------+  |
> > |                      |
> > +----------------------+
> > 
> > Please, let us know your thoughts.
> > 
> > Best Regards,
> > 
> > Melissa Wen
> > 
> > [1] https://github.com/ValveSoftware/gamescope
> > [2] https://store.steampowered.com/news/app/1675200/view/3686804163591367815
> > [3] https://lore.kernel.org/dri-devel/20230721132431.692158-1-mwen@igalia.com
> > 
> > Joshua Ashton (14):
> >   drm/amd/display: add plane degamma TF driver-specific property
> >   drm/amd/display: add plane HDR multiplier driver-specific property
> >   drm/amd/display: add plane blend LUT and TF driver-specific properties
> >   drm/amd/display: add CRTC gamma TF support
> >   drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func
> >   drm/amd/display: mark plane as needing reset if color props change
> >   drm/amd/display: add plane degamma TF and LUT support
> >   drm/amd/display: add dc_fixpt_from_s3132 helper
> >   drm/amd/display: add HDR multiplier support
> >   drm/amd/display: handle empty LUTs in __set_input_tf
> >   drm/amd/display: add plane blend LUT and TF support
> >   drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG
> >   drm/amd/display: copy 3D LUT settings from crtc state to stream_update
> >   drm/amd/display: Add 3x4 CTM support for plane CTM
> > 
> > Melissa Wen (18):
> >   drm/drm_mode_object: increase max objects to accommodate new color
> >     props
> >   drm/drm_property: make replace_property_blob_from_id a DRM helper
> >   drm/drm_plane: track color mgmt changes per plane
> >   drm/amd/display: add driver-specific property for plane degamma LUT
> >   drm/amd/display: explicitly define EOTF and inverse EOTF
> >   drm/amd/display: document AMDGPU pre-defined transfer functions
> >   drm/amd/display: add plane 3D LUT driver-specific properties
> >   drm/amd/display: add plane shaper LUT and TF driver-specific
> >     properties
> >   drm/amd/display: add CRTC gamma TF driver-specific property
> >   drm/amd/display: add comments to describe DM crtc color mgmt behavior
> >   drm/amd/display: encapsulate atomic regamma operation
> >   drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
> >   drm/amd/display: reject atomic commit if setting both plane and CRTC
> >     degamma
> >   drm/amd/display: add plane shaper LUT support
> >   drm/amd/display: add plane shaper TF support
> >   drm/amd/display: add plane 3D LUT support
> >   drm/amd/display: add plane CTM driver-specific property
> >   drm/amd/display: add plane CTM support
> > 
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  90 ++
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  34 +-
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 108 +++
> >  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 821 ++++++++++++++++--
> >  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |  72 ++
> >  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 224 ++++-
> >  .../gpu/drm/amd/display/include/fixed31_32.h  |  12 +
> >  drivers/gpu/drm/arm/malidp_crtc.c             |   2 +-
> >  drivers/gpu/drm/drm_atomic.c                  |   1 +
> >  drivers/gpu/drm/drm_atomic_state_helper.c     |   1 +
> >  drivers/gpu/drm/drm_atomic_uapi.c             |  43 +-
> >  drivers/gpu/drm/drm_property.c                |  49 ++
> >  include/drm/drm_mode_object.h                 |   2 +-
> >  include/drm/drm_plane.h                       |   7 +
> >  include/drm/drm_property.h                    |   6 +
> >  include/uapi/drm/drm_mode.h                   |   8 +
> >  16 files changed, 1371 insertions(+), 109 deletions(-)
> > 
> > -- 
> > 2.40.1
> > 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 06/32] drm/amd/display: explicitly define EOTF and inverse EOTF
  2023-10-05 17:15 ` [PATCH v4 06/32] drm/amd/display: explicitly define EOTF and inverse EOTF Melissa Wen
@ 2023-11-15 18:25   ` Harry Wentland
  0 siblings, 0 replies; 47+ messages in thread
From: Harry Wentland @ 2023-11-15 18:25 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Rodrigo Siqueira, sunpeng.li, Alex Deucher,
	dri-devel, christian.koenig, Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim



On 2023-10-05 13:15, Melissa Wen wrote:
> Instead of relying on color block names to get the transfer function
> intention regarding encoding pixel's luminance, define supported
> Electro-Optical Transfer Functions (EOTFs) and inverse EOTFs, that
> includes pure gamma or standardized transfer functions.
> 
> v3:
> - squash linear and unity TFs to identity (Pekka)
> - define the right TFs for BT.709 (Pekka and Harry)
> - add comment about AMD TF coefficients
> 
> Suggested-by: Harry Wentland <harry.wentland@amd.com>
> Signed-off-by: Melissa Wen <mwen@igalia.com>

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 27 +++++---
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 67 ++++++++++++++-----
>  2 files changed, 71 insertions(+), 23 deletions(-)
> 
> 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 4c4cdf7fc6be..fc4f188d397e 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -724,16 +724,27 @@ struct amdgpu_dm_wb_connector {
>  
>  extern const struct amdgpu_ip_block_version dm_ip_block;
>  
> +/* enum amdgpu_transfer_function: pre-defined transfer function supported by AMD.
> + *
> + * It includes standardized transfer functions and pure power functions. The
> + * transfer function coefficients are available at modules/color/color_gamma.c
> + */
>  enum amdgpu_transfer_function {
>  	AMDGPU_TRANSFER_FUNCTION_DEFAULT,
> -	AMDGPU_TRANSFER_FUNCTION_SRGB,
> -	AMDGPU_TRANSFER_FUNCTION_BT709,
> -	AMDGPU_TRANSFER_FUNCTION_PQ,
> -	AMDGPU_TRANSFER_FUNCTION_LINEAR,
> -	AMDGPU_TRANSFER_FUNCTION_UNITY,
> -	AMDGPU_TRANSFER_FUNCTION_GAMMA22,
> -	AMDGPU_TRANSFER_FUNCTION_GAMMA24,
> -	AMDGPU_TRANSFER_FUNCTION_GAMMA26,
> +	AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF,
> +	AMDGPU_TRANSFER_FUNCTION_PQ_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_IDENTITY,
> +	AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_BT709_OETF,
> +	AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF,
> +	AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF,
> +        AMDGPU_TRANSFER_FUNCTION_COUNT
>  };
>  
>  struct dm_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 56ce008b9095..d03bdb010e8b 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
> @@ -85,18 +85,57 @@ void amdgpu_dm_init_color_mod(void)
>  }
>  
>  #ifdef AMD_PRIVATE_COLOR
> -static const struct drm_prop_enum_list amdgpu_transfer_function_enum_list[] = {
> -	{ AMDGPU_TRANSFER_FUNCTION_DEFAULT, "Default" },
> -	{ AMDGPU_TRANSFER_FUNCTION_SRGB, "sRGB" },
> -	{ AMDGPU_TRANSFER_FUNCTION_BT709, "BT.709" },
> -	{ AMDGPU_TRANSFER_FUNCTION_PQ, "PQ (Perceptual Quantizer)" },
> -	{ AMDGPU_TRANSFER_FUNCTION_LINEAR, "Linear" },
> -	{ AMDGPU_TRANSFER_FUNCTION_UNITY, "Unity" },
> -	{ AMDGPU_TRANSFER_FUNCTION_GAMMA22, "Gamma 2.2" },
> -	{ AMDGPU_TRANSFER_FUNCTION_GAMMA24, "Gamma 2.4" },
> -	{ AMDGPU_TRANSFER_FUNCTION_GAMMA26, "Gamma 2.6" },
> +static const char * const
> +amdgpu_transfer_function_names[] = {
> +	[AMDGPU_TRANSFER_FUNCTION_DEFAULT]		= "Default",
> +	[AMDGPU_TRANSFER_FUNCTION_IDENTITY]		= "Identity",
> +	[AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF]		= "sRGB EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF]	= "BT.709 inv_OETF",
> +	[AMDGPU_TRANSFER_FUNCTION_PQ_EOTF]		= "PQ EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF]		= "Gamma 2.2 EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF]		= "Gamma 2.4 EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF]		= "Gamma 2.6 EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF]	= "sRGB inv_EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_BT709_OETF]		= "BT.709 OETF",
> +	[AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF]		= "PQ inv_EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF]	= "Gamma 2.2 inv_EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF]	= "Gamma 2.4 inv_EOTF",
> +	[AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF]	= "Gamma 2.6 inv_EOTF",
>  };
>  
> +static const u32 amdgpu_eotf =
> +	BIT(AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_PQ_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF);
> +
> +static struct drm_property *
> +amdgpu_create_tf_property(struct drm_device *dev,
> +			  const char *name,
> +			  u32 supported_tf)
> +{
> +	u32 transfer_functions = supported_tf |
> +				 BIT(AMDGPU_TRANSFER_FUNCTION_DEFAULT) |
> +				 BIT(AMDGPU_TRANSFER_FUNCTION_IDENTITY);
> +	struct drm_prop_enum_list enum_list[AMDGPU_TRANSFER_FUNCTION_COUNT];
> +	int i, len;
> +
> +	len = 0;
> +	for (i = 0; i < AMDGPU_TRANSFER_FUNCTION_COUNT; i++) {
> +		if ((transfer_functions & BIT(i)) == 0)
> +			continue;
> +
> +		enum_list[len].type = i;
> +		enum_list[len].name = amdgpu_transfer_function_names[i];
> +		len++;
> +	}
> +
> +	return drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
> +					name, enum_list, len);
> +}
> +
>  int
>  amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>  {
> @@ -116,11 +155,9 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>  		return -ENOMEM;
>  	adev->mode_info.plane_degamma_lut_size_property = prop;
>  
> -	prop = drm_property_create_enum(adev_to_drm(adev),
> -					DRM_MODE_PROP_ENUM,
> -					"AMD_PLANE_DEGAMMA_TF",
> -					amdgpu_transfer_function_enum_list,
> -					ARRAY_SIZE(amdgpu_transfer_function_enum_list));
> +	prop = amdgpu_create_tf_property(adev_to_drm(adev),
> +					 "AMD_PLANE_DEGAMMA_TF",
> +					 amdgpu_eotf);
>  	if (!prop)
>  		return -ENOMEM;
>  	adev->mode_info.plane_degamma_tf_property = prop;


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 07/32] drm/amd/display: document AMDGPU pre-defined transfer functions
  2023-10-05 17:15 ` [PATCH v4 07/32] drm/amd/display: document AMDGPU pre-defined transfer functions Melissa Wen
@ 2023-11-15 18:26   ` Harry Wentland
  0 siblings, 0 replies; 47+ messages in thread
From: Harry Wentland @ 2023-11-15 18:26 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Rodrigo Siqueira, sunpeng.li, Alex Deucher,
	dri-devel, christian.koenig, Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim



On 2023-10-05 13:15, Melissa Wen wrote:
> Brief documentation about pre-defined transfer function usage on AMD
> display driver and standardized EOTFs and inverse EOTFs.
> 
> v3:
> - Document BT709 OETF (Pekka)
> - Fix description of sRGB and pure power funcs (Pekka)
> 
> v4:
> - Add description of linear and non-linear forms (Harry)
> 
> Co-developed-by: Harry Wentland <harry.wentland@amd.com>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> Signed-off-by: Melissa Wen <mwen@igalia.com>

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> ---
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 62 +++++++++++++++++++
>  1 file changed, 62 insertions(+)
> 
> 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 d03bdb010e8b..d5dbd20a6766 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
> @@ -85,6 +85,68 @@ void amdgpu_dm_init_color_mod(void)
>  }
>  
>  #ifdef AMD_PRIVATE_COLOR
> +/* Pre-defined Transfer Functions (TF)
> + *
> + * AMD driver supports pre-defined mathematical functions for transferring
> + * between encoded values and optical/linear space. Depending on HW color caps,
> + * ROMs and curves built by the AMD color module support these transforms.
> + *
> + * The driver-specific color implementation exposes properties for pre-blending
> + * degamma TF, shaper TF (before 3D LUT), and blend(dpp.ogam) TF and
> + * post-blending regamma (mpc.ogam) TF. However, only pre-blending degamma
> + * supports ROM curves. AMD color module uses pre-defined coefficients to build
> + * curves for the other blocks. What can be done by each color block is
> + * described by struct dpp_color_capsand struct mpc_color_caps.
> + *
> + * AMD driver-specific color API exposes the following pre-defined transfer
> + * functions:
> + *
> + * - Identity: linear/identity relationship between pixel value and
> + *   luminance value;
> + * - Gamma 2.2, Gamma 2.4, Gamma 2.6: pure power functions;
> + * - sRGB: 2.4: The piece-wise transfer function from IEC 61966-2-1:1999;
> + * - BT.709: has a linear segment in the bottom part and then a power function
> + *   with a 0.45 (~1/2.22) gamma for the rest of the range; standardized by
> + *   ITU-R BT.709-6;
> + * - PQ (Perceptual Quantizer): used for HDR display, allows luminance range
> + *   capability of 0 to 10,000 nits; standardized by SMPTE ST 2084.
> + *
> + * The AMD color model is designed with an assumption that SDR (sRGB, BT.709,
> + * Gamma 2.2, etc.) peak white maps (normalized to 1.0 FP) to 80 nits in the PQ
> + * system. This has the implication that PQ EOTF (non-linear to linear) maps to
> + * [0.0..125.0] where 125.0 = 10,000 nits / 80 nits.
> + *
> + * Non-linear and linear forms are described in the table below:
> + *
> + * ┌───────────┬─────────────────────┬──────────────────────┐
> + * │           │     Non-linear      │   Linear             │
> + * ├───────────┼─────────────────────┼──────────────────────┤
> + * │      sRGB │ UNORM or [0.0, 1.0] │ [0.0, 1.0]           │
> + * ├───────────┼─────────────────────┼──────────────────────┤
> + * │     BT709 │ UNORM or [0.0, 1.0] │ [0.0, 1.0]           │
> + * ├───────────┼─────────────────────┼──────────────────────┤
> + * │ Gamma 2.x │ UNORM or [0.0, 1.0] │ [0.0, 1.0]           │
> + * ├───────────┼─────────────────────┼──────────────────────┤
> + * │        PQ │ UNORM or FP16 CCCS* │ [0.0, 125.0]         │
> + * ├───────────┼─────────────────────┼──────────────────────┤
> + * │  Identity │ UNORM or FP16 CCCS* │ [0.0, 1.0] or CCCS** │
> + * └───────────┴─────────────────────┴──────────────────────┘
> + * * CCCS: Windows canonical composition color space
> + * ** Respectively
> + *
> + * In the driver-specific API, color block names attached to TF properties
> + * suggest the intention regarding non-linear encoding pixel's luminance
> + * values. As some newer encodings don't use gamma curve, we make encoding and
> + * decoding explicit by defining an enum list of transfer functions supported
> + * in terms of EOTF and inverse EOTF, where:
> + *
> + * - EOTF (electro-optical transfer function): is the transfer function to go
> + *   from the encoded value to an optical (linear) value. De-gamma functions
> + *   traditionally do this.
> + * - Inverse EOTF (simply the inverse of the EOTF): is usually intended to go
> + *   from an optical/linear space (which might have been used for blending)
> + *   back to the encoded values. Gamma functions traditionally do this.
> + */
>  static const char * const
>  amdgpu_transfer_function_names[] = {
>  	[AMDGPU_TRANSFER_FUNCTION_DEFAULT]		= "Default",


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 08/32] drm/amd/display: add plane HDR multiplier driver-specific property
  2023-10-05 17:15 ` [PATCH v4 08/32] drm/amd/display: add plane HDR multiplier driver-specific property Melissa Wen
@ 2023-11-15 18:26   ` Harry Wentland
  0 siblings, 0 replies; 47+ messages in thread
From: Harry Wentland @ 2023-11-15 18:26 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Rodrigo Siqueira, sunpeng.li, Alex Deucher,
	dri-devel, christian.koenig, Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim



On 2023-10-05 13:15, Melissa Wen wrote:
> From: Joshua Ashton <joshua@froggi.es>
> 
> Multiplier to 'gain' the plane. When PQ is decoded using the fixed func
> transfer function to the internal FP16 fb, 1.0 -> 80 nits (on AMD at
> least) When sRGB is decoded, 1.0 -> 1.0.  Therefore, 1.0 multiplier = 80
> nits for SDR content. So if you want, 203 nits for SDR content, pass in
> (203.0 / 80.0).
> 
> v4:
> - comment about the PQ TF need for L-to-NL (from Harry's review)
> 
> Signed-off-by: Joshua Ashton <joshua@froggi.es>
> Co-developed-by: Melissa Wen <mwen@igalia.com>
> Signed-off-by: Melissa Wen <mwen@igalia.com>

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h        |  4 ++++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h   | 17 +++++++++++++++++
>  .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c |  6 ++++++
>  .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 13 +++++++++++++
>  4 files changed, 40 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 9b6fab86c6c3..62044d41da75 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -359,6 +359,10 @@ struct amdgpu_mode_info {
>  	 * to go from scanout/encoded values to linear values.
>  	 */
>  	struct drm_property *plane_degamma_tf_property;
> +	/**
> +	 * @plane_hdr_mult_property:
> +	 */
> +	struct drm_property *plane_hdr_mult_property;
>  };
>  
>  #define AMDGPU_MAX_BL_LEVEL 0xFF
> 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 fc4f188d397e..bb2ce843369d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -55,6 +55,9 @@
>  #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
>  #define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
>  #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
> +
> +#define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL)
> +
>  /*
>  #include "include/amdgpu_dal_power_if.h"
>  #include "amdgpu_dm_irq.h"
> @@ -767,6 +770,20 @@ struct dm_plane_state {
>  	 * linearize.
>  	 */
>  	enum amdgpu_transfer_function degamma_tf;
> +	/**
> +	 * @hdr_mult:
> +	 *
> +	 * Multiplier to 'gain' the plane.  When PQ is decoded using the fixed
> +	 * func transfer function to the internal FP16 fb, 1.0 -> 80 nits (on
> +	 * AMD at least). When sRGB is decoded, 1.0 -> 1.0, obviously.
> +	 * Therefore, 1.0 multiplier = 80 nits for SDR content.  So if you
> +	 * want, 203 nits for SDR content, pass in (203.0 / 80.0).  Format is
> +	 * S31.32 sign-magnitude.
> +	 *
> +	 * HDR multiplier can wide range beyond [0.0, 1.0]. This means that PQ
> +	 * TF is needed for any subsequent linear-to-non-linear transforms.
> +	 */
> +	__u64 hdr_mult;
>  };
>  
>  struct dm_crtc_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 d5dbd20a6766..caf49a044ab4 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
> @@ -224,6 +224,12 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>  		return -ENOMEM;
>  	adev->mode_info.plane_degamma_tf_property = prop;
>  
> +	prop = drm_property_create_range(adev_to_drm(adev),
> +					 0, "AMD_PLANE_HDR_MULT", 0, U64_MAX);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_hdr_mult_property = prop;
> +
>  	return 0;
>  }
>  #endif
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index 04af6db8cffd..ae64d4b73360 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1337,6 +1337,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
>  
>  	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
>  	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
> +	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
>  }
>  
>  static struct drm_plane_state *
> @@ -1360,6 +1361,7 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
>  		drm_property_blob_get(dm_plane_state->degamma_lut);
>  
>  	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
> +	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
>  
>  	return &dm_plane_state->base;
>  }
> @@ -1456,6 +1458,10 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
>  					   dm->adev->mode_info.plane_degamma_tf_property,
>  					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
>  	}
> +	/* HDR MULT is always available */
> +	drm_object_attach_property(&plane->base,
> +				   dm->adev->mode_info.plane_hdr_mult_property,
> +				   AMDGPU_HDR_MULT_DEFAULT);
>  }
>  
>  static int
> @@ -1482,6 +1488,11 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
>  			dm_plane_state->degamma_tf = val;
>  			dm_plane_state->base.color_mgmt_changed = 1;
>  		}
> +	} else if (property == adev->mode_info.plane_hdr_mult_property) {
> +		if (dm_plane_state->hdr_mult != val) {
> +			dm_plane_state->hdr_mult = val;
> +			dm_plane_state->base.color_mgmt_changed = 1;
> +		}
>  	} else {
>  		drm_dbg_atomic(plane->dev,
>  			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> @@ -1507,6 +1518,8 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
>  			dm_plane_state->degamma_lut->base.id : 0;
>  	} else if (property == adev->mode_info.plane_degamma_tf_property) {
>  		*val = dm_plane_state->degamma_tf;
> +	} else if (property == adev->mode_info.plane_hdr_mult_property) {
> +		*val = dm_plane_state->hdr_mult;
>  	} else {
>  		return -EINVAL;
>  	}


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 10/32] drm/amd/display: add plane shaper LUT and TF driver-specific properties
  2023-10-05 17:15 ` [PATCH v4 10/32] drm/amd/display: add plane shaper LUT and TF " Melissa Wen
@ 2023-11-15 18:27   ` Harry Wentland
  0 siblings, 0 replies; 47+ messages in thread
From: Harry Wentland @ 2023-11-15 18:27 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Rodrigo Siqueira, sunpeng.li, Alex Deucher,
	dri-devel, christian.koenig, Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim



On 2023-10-05 13:15, Melissa Wen wrote:
> On AMD HW, 3D LUT always assumes a preceding shaper 1D LUT used for
> delinearizing and/or normalizing the color space before applying a 3D
> LUT. Add pre-defined transfer function to enable delinearizing content
> with or without shaper LUT, where AMD color module calculates the
> resulted shaper curve. We apply an inverse EOTF to go from linear
> values to encoded values. If we are already in a non-linear space and/or
> don't need to normalize values, we can bypass shaper LUT with a linear
> transfer function that is also the default TF value.
> 
> There is no shaper ROM. When setting shaper TF (!= Identity) and LUT at
> the same time, the color module will combine the pre-defined TF and the
> custom LUT values into the LUT that's actually programmed.
> 
> v2:
> - squash commits for shaper LUT and shaper TF
> - define inverse EOTF as supported shaper TFs
> 
> v3:
> - spell out TF+LUT behavior in the commit and comments (Harry)
> - replace BT709 EOTF by inv OETF
> 
> Signed-off-by: Melissa Wen <mwen@igalia.com>

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 21 ++++++++++++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 11 +++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 29 +++++++++++++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 32 +++++++++++++++++++
>  4 files changed, 93 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index f7adaa52c23f..af70db4f6b4b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -363,6 +363,27 @@ struct amdgpu_mode_info {
>  	 * @plane_hdr_mult_property:
>  	 */
>  	struct drm_property *plane_hdr_mult_property;
> +	/**
> +	 * @shaper_lut_property: Plane property to set pre-blending shaper LUT
> +	 * that converts color content before 3D LUT. If
> +	 * plane_shaper_tf_property != Identity TF, AMD color module will
> +	 * combine the user LUT values with pre-defined TF into the LUT
> +	 * parameters to be programmed.
> +	 */
> +	struct drm_property *plane_shaper_lut_property;
> +	/**
> +	 * @shaper_lut_size_property: Plane property for the size of
> +	 * pre-blending shaper LUT as supported by the driver (read-only).
> +	 */
> +	struct drm_property *plane_shaper_lut_size_property;
> +	/**
> +	 * @plane_shaper_tf_property: Plane property to set a predefined
> +	 * transfer function for pre-blending shaper (before applying 3D LUT)
> +	 * with or without LUT. There is no shaper ROM, but we can use AMD
> +	 * color modules to program LUT parameters from predefined TF (or
> +	 * from a combination of pre-defined TF and the custom 1D LUT).
> +	 */
> +	struct drm_property *plane_shaper_tf_property;
>  	/**
>  	 * @plane_lut3d_property: Plane property for color transformation using
>  	 * a 3D LUT (pre-blending), a three-dimensional array where each
> 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 7a2350c62cf1..0e2a04a3caf3 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -784,6 +784,17 @@ struct dm_plane_state {
>  	 * TF is needed for any subsequent linear-to-non-linear transforms.
>  	 */
>  	__u64 hdr_mult;
> +	/**
> +	 * @shaper_lut: shaper lookup table blob. The blob (if not NULL) is an
> +	 * array of &struct drm_color_lut.
> +	 */
> +	struct drm_property_blob *shaper_lut;
> +	/**
> +	 * @shaper_tf:
> +	 *
> +	 * Predefined transfer function to delinearize color space.
> +	 */
> +	enum amdgpu_transfer_function shaper_tf;
>  	/**
>  	 * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
>  	 * &struct drm_color_lut.
> 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 011f2f9ec890..d3c7f9a13a61 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
> @@ -173,6 +173,14 @@ static const u32 amdgpu_eotf =
>  	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF) |
>  	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF);
>  
> +static const u32 amdgpu_inv_eotf =
> +	BIT(AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_BT709_OETF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF) |
> +	BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF);
> +
>  static struct drm_property *
>  amdgpu_create_tf_property(struct drm_device *dev,
>  			  const char *name,
> @@ -230,6 +238,27 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>  		return -ENOMEM;
>  	adev->mode_info.plane_hdr_mult_property = prop;
>  
> +	prop = drm_property_create(adev_to_drm(adev),
> +				   DRM_MODE_PROP_BLOB,
> +				   "AMD_PLANE_SHAPER_LUT", 0);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_shaper_lut_property = prop;
> +
> +	prop = drm_property_create_range(adev_to_drm(adev),
> +					 DRM_MODE_PROP_IMMUTABLE,
> +					 "AMD_PLANE_SHAPER_LUT_SIZE", 0, UINT_MAX);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_shaper_lut_size_property = prop;
> +
> +	prop = amdgpu_create_tf_property(adev_to_drm(adev),
> +					 "AMD_PLANE_SHAPER_TF",
> +					 amdgpu_inv_eotf);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_shaper_tf_property = prop;
> +
>  	prop = drm_property_create(adev_to_drm(adev),
>  				   DRM_MODE_PROP_BLOB,
>  				   "AMD_PLANE_LUT3D", 0);
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index 068798ffdd56..a381b3558bd1 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1338,6 +1338,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
>  	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
>  	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
>  	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
> +	amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
>  }
>  
>  static struct drm_plane_state *
> @@ -1359,11 +1360,14 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
>  
>  	if (dm_plane_state->degamma_lut)
>  		drm_property_blob_get(dm_plane_state->degamma_lut);
> +	if (dm_plane_state->shaper_lut)
> +		drm_property_blob_get(dm_plane_state->shaper_lut);
>  	if (dm_plane_state->lut3d)
>  		drm_property_blob_get(dm_plane_state->lut3d);
>  
>  	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
>  	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
> +	dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf;
>  
>  	return &dm_plane_state->base;
>  }
> @@ -1436,6 +1440,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
>  		drm_property_blob_put(dm_plane_state->degamma_lut);
>  	if (dm_plane_state->lut3d)
>  		drm_property_blob_put(dm_plane_state->lut3d);
> +	if (dm_plane_state->shaper_lut)
> +		drm_property_blob_put(dm_plane_state->shaper_lut);
>  
>  	if (dm_plane_state->dc_state)
>  		dc_plane_state_release(dm_plane_state->dc_state);
> @@ -1468,6 +1474,14 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
>  				   AMDGPU_HDR_MULT_DEFAULT);
>  
>  	if (dpp_color_caps.hw_3d_lut) {
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_shaper_lut_property, 0);
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_shaper_lut_size_property,
> +					   MAX_COLOR_LUT_ENTRIES);
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_shaper_tf_property,
> +					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
>  		drm_object_attach_property(&plane->base,
>  					   mode_info.plane_lut3d_property, 0);
>  		drm_object_attach_property(&plane->base,
> @@ -1505,6 +1519,19 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
>  			dm_plane_state->hdr_mult = val;
>  			dm_plane_state->base.color_mgmt_changed = 1;
>  		}
> +	} else if (property == adev->mode_info.plane_shaper_lut_property) {
> +		ret = drm_property_replace_blob_from_id(plane->dev,
> +							&dm_plane_state->shaper_lut,
> +							val, -1,
> +							sizeof(struct drm_color_lut),
> +							&replaced);
> +		dm_plane_state->base.color_mgmt_changed |= replaced;
> +		return ret;
> +	} else if (property == adev->mode_info.plane_shaper_tf_property) {
> +		if (dm_plane_state->shaper_tf != val) {
> +			dm_plane_state->shaper_tf = val;
> +			dm_plane_state->base.color_mgmt_changed = 1;
> +		}
>  	} else if (property == adev->mode_info.plane_lut3d_property) {
>  		ret = drm_property_replace_blob_from_id(plane->dev,
>  							&dm_plane_state->lut3d,
> @@ -1540,6 +1567,11 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
>  		*val = dm_plane_state->degamma_tf;
>  	} else if (property == adev->mode_info.plane_hdr_mult_property) {
>  		*val = dm_plane_state->hdr_mult;
> +	} else 	if (property == adev->mode_info.plane_shaper_lut_property) {
> +		*val = (dm_plane_state->shaper_lut) ?
> +			dm_plane_state->shaper_lut->base.id : 0;
> +	} else if (property == adev->mode_info.plane_shaper_tf_property) {
> +		*val = dm_plane_state->shaper_tf;
>  	} else 	if (property == adev->mode_info.plane_lut3d_property) {
>  		*val = (dm_plane_state->lut3d) ?
>  			dm_plane_state->lut3d->base.id : 0;


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 11/32] drm/amd/display: add plane blend LUT and TF driver-specific properties
  2023-10-05 17:15 ` [PATCH v4 11/32] drm/amd/display: add plane blend " Melissa Wen
@ 2023-11-15 18:27   ` Harry Wentland
  0 siblings, 0 replies; 47+ messages in thread
From: Harry Wentland @ 2023-11-15 18:27 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Rodrigo Siqueira, sunpeng.li, Alex Deucher,
	dri-devel, christian.koenig, Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim



On 2023-10-05 13:15, Melissa Wen wrote:
> From: Joshua Ashton <joshua@froggi.es>
> 
> Blend 1D LUT or a pre-defined transfer function (TF) can be set to
> linearize content before blending, so that it's positioned just before
> blending planes in the AMD color mgmt pipeline, and after 3D LUT
> (non-linear space). Shaper and Blend LUTs are 1D LUTs that sandwich 3D
> LUT. Drivers should advertize blend properties according to HW caps.
> 
> There is no blend ROM for pre-defined TF. When setting blend TF (!=
> Identity) and LUT at the same time, the color module will combine the
> pre-defined TF and the custom LUT values into the LUT that's actually
> programmed.
> 
> v3:
> - spell out TF+LUT behavior in the commit and comments (Harry)
> 
> Signed-off-by: Joshua Ashton <joshua@froggi.es>
> Signed-off-by: Melissa Wen <mwen@igalia.com>

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 22 ++++++++++++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 12 +++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 21 +++++++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 36 +++++++++++++++++++
>  4 files changed, 91 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index af70db4f6b4b..dee35d208493 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -402,6 +402,28 @@ struct amdgpu_mode_info {
>  	 * entries for 3D LUT array is the 3D LUT size cubed;
>  	 */
>  	struct drm_property *plane_lut3d_size_property;
> +	/**
> +	 * @plane_blend_lut_property: Plane property for output gamma before
> +	 * blending. Userspace set a blend LUT to convert colors after 3D LUT
> +	 * conversion. It works as a post-3DLUT 1D LUT. With shaper LUT, they
> +	 * are sandwiching 3D LUT with two 1D LUT. If plane_blend_tf_property
> +	 * != Identity TF, AMD color module will combine the user LUT values
> +	 * with pre-defined TF into the LUT parameters to be programmed.
> +	 */
> +	struct drm_property *plane_blend_lut_property;
> +	/**
> +	 * @plane_blend_lut_size_property: Plane property to define the max
> +	 * size of blend LUT as supported by the driver (read-only).
> +	 */
> +	struct drm_property *plane_blend_lut_size_property;
> +	/**
> +	 * @plane_blend_tf_property: Plane property to set a predefined
> +	 * transfer function for pre-blending blend/out_gamma (after applying
> +	 * 3D LUT) with or without LUT. There is no blend ROM, but we can use
> +	 * AMD color modules to program LUT parameters from predefined TF (or
> +	 * from a combination of pre-defined TF and the custom 1D LUT).
> +	 */
> +	struct drm_property *plane_blend_tf_property;
>  };
>  
>  #define AMDGPU_MAX_BL_LEVEL 0xFF
> 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 0e2a04a3caf3..1b96c742d747 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -800,6 +800,18 @@ struct dm_plane_state {
>  	 * &struct drm_color_lut.
>  	 */
>  	struct drm_property_blob *lut3d;
> +	/**
> +	 * @blend_lut: blend lut lookup table blob. The blob (if not NULL) is an
> +	 * array of &struct drm_color_lut.
> +	 */
> +	struct drm_property_blob *blend_lut;
> +	/**
> +	 * @blend_tf:
> +	 *
> +	 * Pre-defined transfer function for converting plane pixel data before
> +	 * applying blend LUT.
> +	 */
> +	enum amdgpu_transfer_function blend_tf;
>  };
>  
>  struct dm_crtc_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 d3c7f9a13a61..82c554662faa 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
> @@ -273,6 +273,27 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>  		return -ENOMEM;
>  	adev->mode_info.plane_lut3d_size_property = prop;
>  
> +	prop = drm_property_create(adev_to_drm(adev),
> +				   DRM_MODE_PROP_BLOB,
> +				   "AMD_PLANE_BLEND_LUT", 0);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_blend_lut_property = prop;
> +
> +	prop = drm_property_create_range(adev_to_drm(adev),
> +					 DRM_MODE_PROP_IMMUTABLE,
> +					 "AMD_PLANE_BLEND_LUT_SIZE", 0, UINT_MAX);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_blend_lut_size_property = prop;
> +
> +	prop = amdgpu_create_tf_property(adev_to_drm(adev),
> +					 "AMD_PLANE_BLEND_TF",
> +					 amdgpu_eotf);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.plane_blend_tf_property = prop;
> +
>  	return 0;
>  }
>  #endif
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index a381b3558bd1..f1070ca7076a 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1339,6 +1339,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
>  	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
>  	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
>  	amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
> +	amdgpu_state->blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
>  }
>  
>  static struct drm_plane_state *
> @@ -1364,10 +1365,13 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
>  		drm_property_blob_get(dm_plane_state->shaper_lut);
>  	if (dm_plane_state->lut3d)
>  		drm_property_blob_get(dm_plane_state->lut3d);
> +	if (dm_plane_state->blend_lut)
> +		drm_property_blob_get(dm_plane_state->blend_lut);
>  
>  	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
>  	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
>  	dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf;
> +	dm_plane_state->blend_tf = old_dm_plane_state->blend_tf;
>  
>  	return &dm_plane_state->base;
>  }
> @@ -1442,6 +1446,8 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
>  		drm_property_blob_put(dm_plane_state->lut3d);
>  	if (dm_plane_state->shaper_lut)
>  		drm_property_blob_put(dm_plane_state->shaper_lut);
> +	if (dm_plane_state->blend_lut)
> +		drm_property_blob_put(dm_plane_state->blend_lut);
>  
>  	if (dm_plane_state->dc_state)
>  		dc_plane_state_release(dm_plane_state->dc_state);
> @@ -1488,6 +1494,17 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
>  					   mode_info.plane_lut3d_size_property,
>  					   MAX_COLOR_3DLUT_SIZE);
>  	}
> +
> +	if (dpp_color_caps.ogam_ram) {
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_blend_lut_property, 0);
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_blend_lut_size_property,
> +					   MAX_COLOR_LUT_ENTRIES);
> +		drm_object_attach_property(&plane->base,
> +					   mode_info.plane_blend_tf_property,
> +					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
> +	}
>  }
>  
>  static int
> @@ -1540,6 +1557,19 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
>  							&replaced);
>  		dm_plane_state->base.color_mgmt_changed |= replaced;
>  		return ret;
> +	} else if (property == adev->mode_info.plane_blend_lut_property) {
> +		ret = drm_property_replace_blob_from_id(plane->dev,
> +							&dm_plane_state->blend_lut,
> +							val, -1,
> +							sizeof(struct drm_color_lut),
> +							&replaced);
> +		dm_plane_state->base.color_mgmt_changed |= replaced;
> +		return ret;
> +	} else if (property == adev->mode_info.plane_blend_tf_property) {
> +		if (dm_plane_state->blend_tf != val) {
> +			dm_plane_state->blend_tf = val;
> +			dm_plane_state->base.color_mgmt_changed = 1;
> +		}
>  	} else {
>  		drm_dbg_atomic(plane->dev,
>  			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> @@ -1575,6 +1605,12 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
>  	} else 	if (property == adev->mode_info.plane_lut3d_property) {
>  		*val = (dm_plane_state->lut3d) ?
>  			dm_plane_state->lut3d->base.id : 0;
> +	} else 	if (property == adev->mode_info.plane_blend_lut_property) {
> +		*val = (dm_plane_state->blend_lut) ?
> +			dm_plane_state->blend_lut->base.id : 0;
> +	} else if (property == adev->mode_info.plane_blend_tf_property) {
> +		*val = dm_plane_state->blend_tf;
> +
>  	} else {
>  		return -EINVAL;
>  	}


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH v4 12/32] drm/amd/display: add CRTC gamma TF driver-specific property
  2023-10-05 17:15 ` [PATCH v4 12/32] drm/amd/display: add CRTC gamma TF driver-specific property Melissa Wen
@ 2023-11-15 18:27   ` Harry Wentland
  0 siblings, 0 replies; 47+ messages in thread
From: Harry Wentland @ 2023-11-15 18:27 UTC (permalink / raw)
  To: Melissa Wen, amd-gfx, Rodrigo Siqueira, sunpeng.li, Alex Deucher,
	dri-devel, christian.koenig, Xinhui.Pan, airlied, daniel
  Cc: Sebastian Wick, Pekka Paalanen, Shashank Sharma, Alex Hung,
	Xaver Hugl, kernel-dev, Nicholas Kazlauskas, Joshua Ashton,
	sungjoon.kim



On 2023-10-05 13:15, Melissa Wen wrote:
> Add AMD pre-defined transfer function property to default DRM CRTC gamma
> to convert to wire encoding with or without a user gamma LUT. There is
> no post-blending regamma ROM for pre-defined TF. When setting Gamma TF
> (!= Identity) and LUT at the same time, the color module will combine
> the pre-defined TF and the custom LUT values into the LUT that's
> actually programmed.
> 
> v2:
> - enable CRTC prop in the end of driver-specific prop sequence
> - define inverse EOTFs as supported regamma TFs
> - reword driver-specific function doc to remove shaper/3D LUT
> 
> v3:
> - spell out TF+LUT behavior in the commit and comments (Harry)
> 
> Co-developed-by: Joshua Ashton <joshua@froggi.es>
> Signed-off-by: Joshua Ashton <joshua@froggi.es>
> Signed-off-by: Melissa Wen <mwen@igalia.com>

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  7 ++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  8 +++
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   |  7 ++
>  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    | 72 +++++++++++++++++++
>  4 files changed, 94 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index dee35d208493..071cc10bfd90 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -424,6 +424,13 @@ struct amdgpu_mode_info {
>  	 * from a combination of pre-defined TF and the custom 1D LUT).
>  	 */
>  	struct drm_property *plane_blend_tf_property;
> +	/* @regamma_tf_property: Transfer function for CRTC regamma
> +	 * (post-blending). Possible values are defined by `enum
> +	 * amdgpu_transfer_function`. There is no regamma ROM, but we can use
> +	 * AMD color modules to program LUT parameters from predefined TF (or
> +	 * from a combination of pre-defined TF and the custom 1D LUT).
> +	 */
> +	struct drm_property *regamma_tf_property;
>  };
>  
>  #define AMDGPU_MAX_BL_LEVEL 0xFF
> 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 1b96c742d747..c138457ff12e 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -836,6 +836,14 @@ struct dm_crtc_state {
>  	struct dc_info_packet vrr_infopacket;
>  
>  	int abm_level;
> +
> +        /**
> +	 * @regamma_tf:
> +	 *
> +	 * Pre-defined transfer function for converting internal FB -> wire
> +	 * encoding.
> +	 */
> +	enum amdgpu_transfer_function regamma_tf;
>  };
>  
>  #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
> 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 82c554662faa..2ecfa0e886e8 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
> @@ -294,6 +294,13 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
>  		return -ENOMEM;
>  	adev->mode_info.plane_blend_tf_property = prop;
>  
> +	prop = amdgpu_create_tf_property(adev_to_drm(adev),
> +					 "AMD_CRTC_REGAMMA_TF",
> +					 amdgpu_inv_eotf);
> +	if (!prop)
> +		return -ENOMEM;
> +	adev->mode_info.regamma_tf_property = prop;
> +
>  	return 0;
>  }
>  #endif
> 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 440fc0869a34..d746f0aa0f11 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
> @@ -253,6 +253,7 @@ static struct drm_crtc_state *dm_crtc_duplicate_state(struct drm_crtc *crtc)
>  	state->freesync_config = cur->freesync_config;
>  	state->cm_has_degamma = cur->cm_has_degamma;
>  	state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
> +	state->regamma_tf = cur->regamma_tf;
>  	state->crc_skip_count = cur->crc_skip_count;
>  	state->mpo_requested = cur->mpo_requested;
>  	/* TODO Duplicate dc_stream after objects are stream object is flattened */
> @@ -289,6 +290,70 @@ static int amdgpu_dm_crtc_late_register(struct drm_crtc *crtc)
>  }
>  #endif
>  
> +#ifdef AMD_PRIVATE_COLOR
> +/**
> + * drm_crtc_additional_color_mgmt - enable additional color properties
> + * @crtc: DRM CRTC
> + *
> + * This function lets the driver enable post-blending CRTC regamma transfer
> + * function property in addition to DRM CRTC gamma LUT. Default value means
> + * linear transfer function, which is the default CRTC gamma LUT behaviour
> + * without this property.
> + */
> +static void
> +dm_crtc_additional_color_mgmt(struct drm_crtc *crtc)
> +{
> +	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
> +
> +	if(adev->dm.dc->caps.color.mpc.ogam_ram)
> +		drm_object_attach_property(&crtc->base,
> +					   adev->mode_info.regamma_tf_property,
> +					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
> +}
> +
> +static int
> +amdgpu_dm_atomic_crtc_set_property(struct drm_crtc *crtc,
> +				   struct drm_crtc_state *state,
> +				   struct drm_property *property,
> +				   uint64_t val)
> +{
> +	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
> +	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state);
> +
> +	if (property == adev->mode_info.regamma_tf_property) {
> +		if (acrtc_state->regamma_tf != val) {
> +			acrtc_state->regamma_tf = val;
> +			acrtc_state->base.color_mgmt_changed |= 1;
> +		}
> +	} else {
> +		drm_dbg_atomic(crtc->dev,
> +			       "[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
> +			       crtc->base.id, crtc->name,
> +			       property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +amdgpu_dm_atomic_crtc_get_property(struct drm_crtc *crtc,
> +				   const struct drm_crtc_state *state,
> +				   struct drm_property *property,
> +				   uint64_t *val)
> +{
> +	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
> +	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state);
> +
> +	if (property == adev->mode_info.regamma_tf_property)
> +		*val = acrtc_state->regamma_tf;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +#endif
> +
>  /* Implemented only the options currently available for the driver */
>  static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
>  	.reset = dm_crtc_reset_state,
> @@ -307,6 +372,10 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
>  #if defined(CONFIG_DEBUG_FS)
>  	.late_register = amdgpu_dm_crtc_late_register,
>  #endif
> +#ifdef AMD_PRIVATE_COLOR
> +	.atomic_set_property = amdgpu_dm_atomic_crtc_set_property,
> +	.atomic_get_property = amdgpu_dm_atomic_crtc_get_property,
> +#endif
>  };
>  
>  static void dm_crtc_helper_disable(struct drm_crtc *crtc)
> @@ -470,6 +539,9 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
>  
>  	drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
>  
> +#ifdef AMD_PRIVATE_COLOR
> +	dm_crtc_additional_color_mgmt(&acrtc->base);
> +#endif
>  	return 0;
>  
>  fail:


^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2023-11-15 18:27 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-05 17:14 [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Melissa Wen
2023-10-05 17:14 ` [PATCH v4 01/32] drm/drm_mode_object: increase max objects to accommodate new color props Melissa Wen
2023-10-05 17:14 ` [PATCH v4 02/32] drm/drm_property: make replace_property_blob_from_id a DRM helper Melissa Wen
2023-10-05 17:14 ` [PATCH v4 03/32] drm/drm_plane: track color mgmt changes per plane Melissa Wen
2023-10-05 17:14 ` [PATCH v4 04/32] drm/amd/display: add driver-specific property for plane degamma LUT Melissa Wen
2023-10-05 17:15 ` [PATCH v4 05/32] drm/amd/display: add plane degamma TF driver-specific property Melissa Wen
2023-10-05 17:15 ` [PATCH v4 06/32] drm/amd/display: explicitly define EOTF and inverse EOTF Melissa Wen
2023-11-15 18:25   ` Harry Wentland
2023-10-05 17:15 ` [PATCH v4 07/32] drm/amd/display: document AMDGPU pre-defined transfer functions Melissa Wen
2023-11-15 18:26   ` Harry Wentland
2023-10-05 17:15 ` [PATCH v4 08/32] drm/amd/display: add plane HDR multiplier driver-specific property Melissa Wen
2023-11-15 18:26   ` Harry Wentland
2023-10-05 17:15 ` [PATCH v4 09/32] drm/amd/display: add plane 3D LUT driver-specific properties Melissa Wen
2023-10-06  9:09   ` Sebastian Wick
2023-11-06 18:46     ` Melissa Wen
2023-11-02  3:48   ` Joshua Ashton
2023-11-02  7:31     ` Joshua Ashton
2023-11-06 18:52       ` Melissa Wen
2023-11-06 18:49     ` Melissa Wen
2023-10-05 17:15 ` [PATCH v4 10/32] drm/amd/display: add plane shaper LUT and TF " Melissa Wen
2023-11-15 18:27   ` Harry Wentland
2023-10-05 17:15 ` [PATCH v4 11/32] drm/amd/display: add plane blend " Melissa Wen
2023-11-15 18:27   ` Harry Wentland
2023-10-05 17:15 ` [PATCH v4 12/32] drm/amd/display: add CRTC gamma TF driver-specific property Melissa Wen
2023-11-15 18:27   ` Harry Wentland
2023-10-05 17:15 ` [PATCH v4 13/32] drm/amd/display: add comments to describe DM crtc color mgmt behavior Melissa Wen
2023-10-05 17:15 ` [PATCH v4 14/32] drm/amd/display: encapsulate atomic regamma operation Melissa Wen
2023-10-05 17:15 ` [PATCH v4 15/32] drm/amd/display: add CRTC gamma TF support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 16/32] drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func Melissa Wen
2023-10-05 17:15 ` [PATCH v4 17/32] drm/amd/display: mark plane as needing reset if color props change Melissa Wen
2023-10-05 17:15 ` [PATCH v4 18/32] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane Melissa Wen
2023-10-05 17:15 ` [PATCH v4 19/32] drm/amd/display: add plane degamma TF and LUT support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 20/32] drm/amd/display: reject atomic commit if setting both plane and CRTC degamma Melissa Wen
2023-10-05 17:15 ` [PATCH v4 21/32] drm/amd/display: add dc_fixpt_from_s3132 helper Melissa Wen
2023-10-05 17:15 ` [PATCH v4 22/32] drm/amd/display: add HDR multiplier support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 23/32] drm/amd/display: add plane shaper LUT support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 24/32] drm/amd/display: add plane shaper TF support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 25/32] drm/amd/display: add plane 3D LUT support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 26/32] drm/amd/display: handle empty LUTs in __set_input_tf Melissa Wen
2023-10-05 17:15 ` [PATCH v4 27/32] drm/amd/display: add plane blend LUT and TF support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 28/32] drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG Melissa Wen
2023-10-05 17:15 ` [PATCH v4 29/32] drm/amd/display: copy 3D LUT settings from crtc state to stream_update Melissa Wen
2023-10-05 17:15 ` [PATCH v4 30/32] drm/amd/display: add plane CTM driver-specific property Melissa Wen
2023-10-05 17:15 ` [PATCH v4 31/32] drm/amd/display: add plane CTM support Melissa Wen
2023-10-05 17:15 ` [PATCH v4 32/32] drm/amd/display: Add 3x4 CTM support for plane CTM Melissa Wen
2023-10-06  9:28 ` [PATCH v4 00/32] drm/amd/display: add AMD driver-specific properties for color mgmt Sebastian Wick
2023-11-06 19:33   ` Melissa Wen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).