Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline
@ 2025-12-23 18:01 Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 01/21] drm/crtc: Add color pipeline to CRTC state Ariel D'Alessandro
                   ` (20 more replies)
  0 siblings, 21 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro,
	Harry Wentland

This series is based on "Color Pipeline API w/ VKMS" [1]. It reuses the
same concept of a color pipeline API but for the post-blend stage
instead of pre-blend, by attaching the COLOR_PIPELINE property to the
CRTC rather than a plane.

The patches in the series first implement the necessary changes in the
DRM core to allow for CRTC (post-blend) color pipelines and expose it 
through the uAPI, and then implement support in both the MediaTek KMS
driver and in VKMS.

This series has been tested with IGT, with the latest revision of patch
series "Support post-blend color pipeline API" [2] applied, on top of
VKMS, as well as with Weston, with a WIP branch [3], on a MT8195-Tomato
Chromebook and a MT8188 Genio 700 EVK, where both gamma LUT and CTM
color transformations have been simultaneously configured in hardware
through the API and validated (test commits for weston at [4]).

[1] https://lore.kernel.org/all/20251115000237.3561250-1-alex.hung@amd.com/
[2] https://lore.kernel.org/igt-dev/20250912-post-blend-colorops-v1-0-83fc62420cba@collabora.com/T/#t
[3] https://gitlab.collabora.com/nfraprado/weston/-/tree/post-blend-colorops?ref_type=heads
[4] https://gitlab.collabora.com/nfraprado/weston/-/tree/post-blend-color-pipeline-lut-ctm-test?ref_type=tags

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
Changes in v3:
- Aligned terminology between plane (pre-blend) and crtc (post-blend)
  color pipeline (Harry Wentland). Replaced all naming s/post-blend/crtc
- Reworked cleanup in vkms_initialize_post_blend_color_pipeline (Louis
  Chauvet).
- Added check on CLIENT_CAP while setting COLOR_PIPELINE property (Louis
  Chauvet).
- Moved common color_pipeline property initialization code to
  drivers/gpu/drm/drm_property.c
- Added missing support for CRTC (post-blend) color pipeline
  configuration in VKMS.
- Added missing return value checks in mtk_crtc_create()
- Added drm_color_lut_to_lut32() and made use of it in mtk_disp_gamma.c
- Added drm_color_ctm_to_ctm_3x4() and made use of it in mtk_disp_ccorr.c
- Split plane and crtc fields descriptions in struct drm_colorop
- Link to v2: https://lore.kernel.org/r/20250917-mtk-post-blend-color-pipeline-v2-0-ac4471b44758@collabora.com

Changes in v2:
- Split core DRM changes for post-blend color pipelines from single
  commit into smaller changes
- Added post-blend color pipeline support in VKMS
- Introduced driver cap, and made client cap depend on it (daniels)
- Made deprecated color props (GAMMA_LUT, DEGAMMA_LUT, CTM) available as
  read-only when post-blend color pipelines are enabled (daniels)
- Created colorop_modeset_lock/unlock to commonize locking pattern for
  colorops (louis.chauvet)
- Added helper for post-blend 1D curve colorop creation
- Link to v1: https://lore.kernel.org/r/20250822-mtk-post-blend-color-pipeline-v1-0-a9446d4aca82@collabora.com

---
Ariel D'Alessandro (2):
      drm: Add helper to extract a 3x4 matrix from any CTM matrix dimensions
      drm: Add helper to extract a LUT entry from either 16-bit or 32-bit LUT

Nícolas F. R. A. Prado (19):
      drm/crtc: Add color pipeline to CRTC state
      drm/colorop: Allow parenting colorop to CRTC
      drm: Factor out common color_pipeline property initialization code
      drm/crtc: Add COLOR_PIPELINE property
      drm: Introduce DRM_CAP_CRTC_COLOR_PIPELINE
      drm: Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE
      drm/atomic: Pass crtc_color_pipeline client cap to atomic check
      drm/atomic: Print the color pipeline as part of the CRTC state print
      drm/colorop: Factor out common paths from colorops helpers
      drm/colorop: Introduce colorop helpers for crtc
      drm/crtc: Track crtc color pipeline client cap in drm_crtc_state
      drm/mediatek: Support CRTC colorops for gamma and ctm
      drm/mediatek: ccorr: Support CRTC color pipeline API
      drm/mediatek: gamma: Support CRTC color pipeline API
      drm/mediatek: Set CRTC color pipeline driver cap
      drm/vkms: Rename existing color pipeline helpers to contain "plane"
      drm/vkms: Prepare pre_blend_color_transform() for CRTC color pipelines
      drm/vkms: Introduce support for post-blend color pipeline
      drm/vkms: Set CRTC color pipeline driver cap

 drivers/gpu/drm/drm_atomic.c                  |   9 +-
 drivers/gpu/drm/drm_atomic_uapi.c             |  71 +++++++-
 drivers/gpu/drm/drm_colorop.c                 | 242 +++++++++++++++++++++-----
 drivers/gpu/drm/drm_connector.c               |   1 +
 drivers/gpu/drm/drm_crtc.c                    |  31 ++++
 drivers/gpu/drm/drm_crtc_internal.h           |   1 +
 drivers/gpu/drm/drm_ioctl.c                   |  12 ++
 drivers/gpu/drm/drm_mode_object.c             |   9 +
 drivers/gpu/drm/drm_plane.c                   |  35 +---
 drivers/gpu/drm/drm_property.c                |  44 +++++
 drivers/gpu/drm/mediatek/mtk_crtc.c           | 222 ++++++++++++++++++++++-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c       |   6 +-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h       |   2 +
 drivers/gpu/drm/mediatek/mtk_disp_ccorr.c     |  88 ++++++++--
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |   6 +-
 drivers/gpu/drm/mediatek/mtk_disp_gamma.c     |  68 ++++++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        |   3 +-
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |  70 +++++---
 drivers/gpu/drm/vkms/vkms_colorop.c           | 110 +++++++++++-
 drivers/gpu/drm/vkms/vkms_composer.c          |  13 +-
 drivers/gpu/drm/vkms/vkms_config.c            |   5 +-
 drivers/gpu/drm/vkms/vkms_config.h            |  29 ++-
 drivers/gpu/drm/vkms/vkms_crtc.c              |   6 +-
 drivers/gpu/drm/vkms/vkms_drv.c               |  10 +-
 drivers/gpu/drm/vkms/vkms_drv.h               |   8 +-
 drivers/gpu/drm/vkms/vkms_output.c            |   3 +-
 drivers/gpu/drm/vkms/vkms_plane.c             |   2 +-
 include/drm/drm_atomic.h                      |  20 +++
 include/drm/drm_atomic_uapi.h                 |   2 +
 include/drm/drm_color_mgmt.h                  |  61 +++++++
 include/drm/drm_colorop.h                     |  25 ++-
 include/drm/drm_crtc.h                        |  27 +++
 include/drm/drm_drv.h                         |   6 +
 include/drm/drm_file.h                        |   7 +
 include/drm/drm_property.h                    |   5 +
 include/uapi/drm/drm.h                        |  25 +++
 36 files changed, 1109 insertions(+), 175 deletions(-)
---
base-commit: b96bcfba104c65db41378a04f5ccac186f79578f
change-id: 20250730-mtk-post-blend-color-pipeline-498e1a9cc53e

Best regards,
-- 
Ariel D'Alessandro <ariel.dalessandro@collabora.com>



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

* [PATCH v3 01/21] drm/crtc: Add color pipeline to CRTC state
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 02/21] drm/colorop: Allow parenting colorop to CRTC Ariel D'Alessandro
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro,
	Harry Wentland

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Add a color pipeline to the CRTC state to allow post-blend color
pipelines.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 include/drm/drm_crtc.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 66278ffeebd68..8490f4bc31260 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -274,6 +274,14 @@ struct drm_crtc_state {
 	 */
 	struct drm_property_blob *gamma_lut;
 
+	/**
+	 * @color_pipeline:
+	 *
+	 * The first colorop of the active color pipeline, or NULL, if no
+	 * color pipeline is active.
+	 */
+	struct drm_colorop *color_pipeline;
+
 	/**
 	 * @target_vblank:
 	 *

-- 
2.51.0



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

* [PATCH v3 02/21] drm/colorop: Allow parenting colorop to CRTC
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 01/21] drm/crtc: Add color pipeline to CRTC state Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 03/21] drm: Factor out common color_pipeline property initialization code Ariel D'Alessandro
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro,
	Harry Wentland

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

In order to allow for post-blend color pipelines, colorops need to be
assigned to a crtc rather than a plane. Add a crtc to the colorop
struct to enable this. Either the plane or the crtc will be set for any
given colorop depending on whether it is part of a pre- or post-blend
color pipeline.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_atomic.c  |  6 +++---
 drivers/gpu/drm/drm_colorop.c | 25 +++++++++++++++++++++++++
 include/drm/drm_colorop.h     | 17 +++++++++++++++--
 3 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 6d3ea8056b603..e9022d7ad04b0 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -620,7 +620,7 @@ drm_atomic_get_colorop_state(struct drm_atomic_state *state,
 	if (colorop_state)
 		return colorop_state;
 
-	ret = drm_modeset_lock(&colorop->plane->mutex, state->acquire_ctx);
+	ret = drm_colorop_modeset_lock(colorop, state->acquire_ctx);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -2012,10 +2012,10 @@ static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
 
 	list_for_each_entry(colorop, &config->colorop_list, head) {
 		if (take_locks)
-			drm_modeset_lock(&colorop->plane->mutex, NULL);
+			drm_colorop_modeset_lock(colorop, NULL);
 		drm_atomic_colorop_print_state(p, colorop->state);
 		if (take_locks)
-			drm_modeset_unlock(&colorop->plane->mutex);
+			drm_colorop_modeset_unlock(colorop);
 	}
 
 	list_for_each_entry(plane, &config->plane_list, head) {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 44eb823585d2e..bf3b8ff51571b 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -24,6 +24,7 @@
  *
  */
 
+#include <drm/drm_crtc.h>
 #include <drm/drm_colorop.h>
 #include <drm/drm_print.h>
 #include <drm/drm_drv.h>
@@ -597,3 +598,27 @@ void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_color
 	colorop->next = next;
 }
 EXPORT_SYMBOL(drm_colorop_set_next_property);
+
+int drm_colorop_modeset_lock(struct drm_colorop *colorop, struct drm_modeset_acquire_ctx *ctx)
+{
+	if (colorop->plane)
+		return drm_modeset_lock(&colorop->plane->mutex, ctx);
+
+	if (colorop->crtc)
+		return drm_modeset_lock(&colorop->crtc->mutex, ctx);
+
+	drm_err(colorop->dev, "Dangling colorop, it must be attached to a plane or a CRTC\n");
+	return -EINVAL;
+}
+EXPORT_SYMBOL(drm_colorop_modeset_lock);
+
+void drm_colorop_modeset_unlock(struct drm_colorop *colorop)
+{
+	if (colorop->plane)
+		drm_modeset_unlock(&colorop->plane->mutex);
+	else if (colorop->crtc)
+		drm_modeset_unlock(&colorop->crtc->mutex);
+	else
+		drm_err(colorop->dev, "Dangling colorop, it must be attached to a plane or a CRTC\n");
+}
+EXPORT_SYMBOL(drm_colorop_modeset_unlock);
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index a3a32f9f918c7..49d342b7f8b0b 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -29,6 +29,7 @@
 
 #include <drm/drm_mode_object.h>
 #include <drm/drm_mode.h>
+#include <drm/drm_modeset_lock.h>
 #include <drm/drm_property.h>
 
 /* DRM colorop flags */
@@ -223,11 +224,21 @@ struct drm_colorop {
 	/**
 	 * @plane:
 	 *
-	 * The plane on which the colorop sits. A drm_colorop is always unique
-	 * to a plane.
+	 * The plane on which the colorop sits if it is a pre-blend colorop.
+	 * In this case it is unique to the plane.
+	 * NOTE: plane and crtc are mutually exclusive.
 	 */
 	struct drm_plane *plane;
 
+	/**
+	 * @crtc:
+	 *
+	 * The CRTC on which the colorop sits if it is a post-blend colorop.
+	 * In this case it is unique to the CRTC.
+	 * NOTE: plane and crtc are mutually exclusive.
+	 */
+	struct drm_crtc *crtc;
+
 	/**
 	 * @state:
 	 *
@@ -460,5 +471,7 @@ const char *
 drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type);
 
 void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
+int drm_colorop_modeset_lock(struct drm_colorop *colorop, struct drm_modeset_acquire_ctx *ctx);
+void drm_colorop_modeset_unlock(struct drm_colorop *colorop);
 
 #endif /* __DRM_COLOROP_H__ */

-- 
2.51.0



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

* [PATCH v3 03/21] drm: Factor out common color_pipeline property initialization code
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 01/21] drm/crtc: Add color pipeline to CRTC state Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 02/21] drm/colorop: Allow parenting colorop to CRTC Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 04/21] drm/crtc: Add COLOR_PIPELINE property Ariel D'Alessandro
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

In preparation for sharing the initialization code for the color
pipeline property between pre-blend (plane) and post-blend (crtc) color
pipelines, factor out the common initialization to a separate function.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/drm_plane.c    | 35 ++++-----------------------------
 drivers/gpu/drm/drm_property.c | 44 ++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_property.h     |  5 +++++
 3 files changed, 53 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index bed2562bf911b..3d7324757d7b2 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -1839,43 +1839,16 @@ int drm_plane_create_color_pipeline_property(struct drm_plane *plane,
 					     const struct drm_prop_enum_list *pipelines,
 					     int num_pipelines)
 {
-	struct drm_prop_enum_list *all_pipelines;
 	struct drm_property *prop;
-	int len = 0;
-	int i;
-
-	all_pipelines = kcalloc(num_pipelines + 1,
-				sizeof(*all_pipelines),
-				GFP_KERNEL);
-
-	if (!all_pipelines) {
-		drm_err(plane->dev, "failed to allocate color pipeline\n");
-		return -ENOMEM;
-	}
-
-	/* Create default Bypass color pipeline */
-	all_pipelines[len].type = 0;
-	all_pipelines[len].name = "Bypass";
-	len++;
 
-	/* Add all other color pipelines */
-	for (i = 0; i < num_pipelines; i++, len++) {
-		all_pipelines[len].type = pipelines[i].type;
-		all_pipelines[len].name = pipelines[i].name;
-	}
+	prop = drm_property_create_color_pipeline(plane->dev, &plane->base,
+						  pipelines, num_pipelines);
+	if (IS_ERR(prop))
+		return PTR_ERR(prop);
 
-	prop = drm_property_create_enum(plane->dev, DRM_MODE_PROP_ATOMIC,
-					"COLOR_PIPELINE",
-					all_pipelines, len);
-	if (!prop) {
-		kfree(all_pipelines);
-		return -ENOMEM;
-	}
 
-	drm_object_attach_property(&plane->base, prop, 0);
 	plane->color_pipeline_property = prop;
 
-	kfree(all_pipelines);
 	return 0;
 }
 EXPORT_SYMBOL(drm_plane_create_color_pipeline_property);
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index 596272149a359..cc2a1422599ac 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -997,3 +997,47 @@ void drm_property_change_valid_put(struct drm_property *property,
 	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
 		drm_property_blob_put(obj_to_blob(ref));
 }
+
+struct drm_property *
+drm_property_create_color_pipeline(struct drm_device *dev, struct drm_mode_object *obj,
+				   const struct drm_prop_enum_list *pipelines,
+				   int num_pipelines)
+{
+	struct drm_prop_enum_list *all_pipelines;
+	struct drm_property *prop;
+	int len = 0;
+	int i;
+
+	all_pipelines = kcalloc(num_pipelines + 1,
+				sizeof(*all_pipelines),
+				GFP_KERNEL);
+
+	if (!all_pipelines) {
+		drm_err(dev, "failed to allocate color pipeline\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Create default Bypass color pipeline */
+	all_pipelines[len].type = 0;
+	all_pipelines[len].name = "Bypass";
+	len++;
+
+	/* Add all other color pipelines */
+	for (i = 0; i < num_pipelines; i++, len++) {
+		all_pipelines[len].type = pipelines[i].type;
+		all_pipelines[len].name = pipelines[i].name;
+	}
+
+	prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC,
+					"COLOR_PIPELINE",
+					all_pipelines, len);
+	if (!prop) {
+		kfree(all_pipelines);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	drm_object_attach_property(obj, prop, 0);
+
+	kfree(all_pipelines);
+	return prop;
+}
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
index 082f29156b3e3..3acf340635226 100644
--- a/include/drm/drm_property.h
+++ b/include/drm/drm_property.h
@@ -296,6 +296,11 @@ bool drm_property_replace_blob(struct drm_property_blob **blob,
 struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob);
 void drm_property_blob_put(struct drm_property_blob *blob);
 
+struct drm_property *
+drm_property_create_color_pipeline(struct drm_device *dev, struct drm_mode_object *obj,
+				   const struct drm_prop_enum_list *pipelines,
+				   int num_pipelines);
+
 /**
  * drm_property_find - find property object
  * @dev: DRM device

-- 
2.51.0



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

* [PATCH v3 04/21] drm/crtc: Add COLOR_PIPELINE property
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (2 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 03/21] drm: Factor out common color_pipeline property initialization code Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 05/21] drm: Introduce DRM_CAP_CRTC_COLOR_PIPELINE Ariel D'Alessandro
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Add a COLOR_PIPELINE property to the CRTC to allow userspace to set a
post-blend color pipeline analogously to how pre-blend color pipelines
are set on planes.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 drivers/gpu/drm/drm_atomic_uapi.c | 50 +++++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/drm_crtc.c        | 31 ++++++++++++++++++++++++
 include/drm/drm_atomic_uapi.h     |  2 ++
 include/drm/drm_crtc.h            | 11 +++++++++
 4 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 7320db4b8489f..07d0d224fe58c 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -286,6 +286,34 @@ drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
 }
 EXPORT_SYMBOL(drm_atomic_set_colorop_for_plane);
 
+/**
+ * drm_atomic_set_colorop_for_crtc - set colorop for crtc
+ * @crtc_state: atomic state object for the crtc
+ * @colorop: colorop to use for the crtc
+ *
+ * Helper function to select the color pipeline on a crtc by setting
+ * it to the first drm_colorop element of the pipeline.
+ */
+void
+drm_atomic_set_colorop_for_crtc(struct drm_crtc_state *crtc_state,
+				 struct drm_colorop *colorop)
+{
+	struct drm_crtc *crtc = crtc_state->crtc;
+
+	if (colorop)
+		drm_dbg_atomic(crtc->dev,
+			       "Set [COLOROP:%d] for [CRTC:%d:%s] state %p\n",
+			       colorop->base.id, crtc->base.id, crtc->name,
+			       crtc_state);
+	else
+		drm_dbg_atomic(crtc->dev,
+			       "Set [NOCOLOROP] for [CRTC:%d:%s] state %p\n",
+			       crtc->base.id, crtc->name, crtc_state);
+
+	crtc_state->color_pipeline = colorop;
+}
+EXPORT_SYMBOL(drm_atomic_set_colorop_for_crtc);
+
 /**
  * drm_atomic_set_crtc_for_connector - set CRTC for connector
  * @conn_state: atomic state object for the connector
@@ -394,8 +422,8 @@ static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
 }
 
 static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
-		struct drm_crtc_state *state, struct drm_property *property,
-		uint64_t val)
+		struct drm_crtc_state *state, struct drm_file *file_priv,
+		struct drm_property *property, uint64_t val)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_mode_config *config = &dev->mode_config;
@@ -404,7 +432,17 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 
 	if (property == config->prop_active)
 		state->active = val;
-	else if (property == config->prop_mode_id) {
+	else if (property == crtc->color_pipeline_property) {
+		/* find DRM colorop object */
+		struct drm_colorop *colorop = NULL;
+
+		colorop = drm_colorop_find(dev, file_priv, val);
+
+		if (val && !colorop)
+			return -EACCES;
+
+		drm_atomic_set_colorop_for_crtc(state, colorop);
+	} else if (property == config->prop_mode_id) {
 		struct drm_property_blob *mode =
 			drm_property_lookup_blob(dev, val);
 		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
@@ -489,6 +527,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
 		*val = state->scaling_filter;
 	else if (property == crtc->sharpness_strength_property)
 		*val = state->sharpness_strength;
+	else if (property == crtc->color_pipeline_property)
+		*val = (state->color_pipeline) ? state->color_pipeline->base.id : 0;
 	else if (crtc->funcs->atomic_get_property)
 		return crtc->funcs->atomic_get_property(crtc, state, property, val);
 	else {
@@ -1050,6 +1090,8 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
 
 		if (colorop->plane)
 			WARN_ON(!drm_modeset_is_locked(&colorop->plane->mutex));
+		else if (colorop->crtc)
+			WARN_ON(!drm_modeset_is_locked(&colorop->crtc->mutex));
 
 		ret = drm_atomic_colorop_get_property(colorop, colorop->state, property, val);
 		break;
@@ -1206,7 +1248,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
 		}
 
 		ret = drm_atomic_crtc_set_property(crtc,
-				crtc_state, prop, prop_value);
+				crtc_state, file_priv, prop, prop_value);
 		break;
 	}
 	case DRM_MODE_OBJECT_PLANE: {
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index a7797d260f1e2..133ff9212fbc4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -994,3 +994,34 @@ bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state)
 	return hweight32(crtc_state->encoder_mask) > 1;
 }
 EXPORT_SYMBOL(drm_crtc_in_clone_mode);
+
+/**
+ * drm_crtc_create_color_pipeline_property - create a new color pipeline
+ * property
+ *
+ * @crtc: drm CRTC
+ * @pipelines: list of pipelines
+ * @num_pipelines: number of pipelines
+ *
+ * Create the COLOR_PIPELINE CRTC property to specify color pipelines on
+ * the CRTC.
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+int drm_crtc_create_color_pipeline_property(struct drm_crtc *crtc,
+					    const struct drm_prop_enum_list *pipelines,
+					    int num_pipelines)
+{
+	struct drm_property *prop;
+
+	prop = drm_property_create_color_pipeline(crtc->dev, &crtc->base,
+						  pipelines, num_pipelines);
+	if (IS_ERR(prop))
+		return PTR_ERR(prop);
+
+	crtc->color_pipeline_property = prop;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_crtc_create_color_pipeline_property);
diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h
index 4363155233267..4dc191f6f929d 100644
--- a/include/drm/drm_atomic_uapi.h
+++ b/include/drm/drm_atomic_uapi.h
@@ -52,6 +52,8 @@ void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
 				 struct drm_framebuffer *fb);
 void drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
 				      struct drm_colorop *colorop);
+void drm_atomic_set_colorop_for_crtc(struct drm_crtc_state *crtc_state,
+				     struct drm_colorop *colorop);
 int __must_check
 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
 				  struct drm_crtc *crtc);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8490f4bc31260..b3c9818715851 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1113,6 +1113,14 @@ struct drm_crtc {
 	 */
 	struct drm_property *sharpness_strength_property;
 
+	/**
+	 * @color_pipeline_property:
+	 *
+	 * Optional "COLOR_PIPELINE" enum property for specifying
+	 * a color pipeline to use on the CRTC.
+	 */
+	struct drm_property *color_pipeline_property;
+
 	/**
 	 * @state:
 	 *
@@ -1348,6 +1356,9 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
 
 int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
 					    unsigned int supported_filters);
+int drm_crtc_create_color_pipeline_property(struct drm_crtc *crtc,
+					     const struct drm_prop_enum_list *pipelines,
+					     int num_pipelines);
 bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state);
 int drm_crtc_create_sharpness_strength_property(struct drm_crtc *crtc);
 #endif /* __DRM_CRTC_H__ */

-- 
2.51.0



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

* [PATCH v3 05/21] drm: Introduce DRM_CAP_CRTC_COLOR_PIPELINE
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (3 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 04/21] drm/crtc: Add COLOR_PIPELINE property Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 06/21] drm: Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE Ariel D'Alessandro
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Add a new cap that drivers can set to signal they support CRTC (a.k.a.
post-blend) color pipelines.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/drm_ioctl.c | 3 +++
 include/drm/drm_drv.h       | 6 ++++++
 include/uapi/drm/drm.h      | 6 ++++++
 3 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index ff193155129e7..2884075660ddd 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -304,6 +304,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
 		req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) &&
 			     dev->mode_config.async_page_flip;
 		break;
+	case DRM_CAP_CRTC_COLOR_PIPELINE:
+		req->value = drm_core_check_feature(dev, DRIVER_CRTC_COLOR_PIPELINE);
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 42fc085f986de..2a57c50b4223e 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -122,6 +122,12 @@ enum drm_driver_feature {
 	 * the cursor planes to work correctly).
 	 */
 	DRIVER_CURSOR_HOTSPOT           = BIT(9),
+	/**
+	 * @DRIVER_CRTC_COLOR_PIPELINE:
+	 *
+	 * Driver supports CRTC (post-blend) color pipeline.
+	 */
+	DRIVER_CRTC_COLOR_PIPELINE	= BIT(10),
 
 	/* IMPORTANT: Below are all the legacy flags, add new ones above. */
 
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 27cc159c1d275..d726828bdf408 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -812,6 +812,12 @@ struct drm_gem_change_handle {
  * commits.
  */
 #define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP	0x15
+/**
+ * DRM_CAP_CRTC_COLOR_PIPELINE
+ *
+ * If set to 1, the driver supports CRTC (post-blend) color pipelines.
+ */
+#define DRM_CAP_CRTC_COLOR_PIPELINE	0x16
 
 /* DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {

-- 
2.51.0



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

* [PATCH v3 06/21] drm: Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (4 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 05/21] drm: Introduce DRM_CAP_CRTC_COLOR_PIPELINE Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2026-07-08  7:28   ` Robert Mader
  2025-12-23 18:01 ` [PATCH v3 07/21] drm/atomic: Pass crtc_color_pipeline client cap to atomic check Ariel D'Alessandro
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE which a DRM client can set
to enable the usage of CRTC (post-blend) color pipelines instead of the
now deprecated CRTC color management properties: "GAMMA_LUT",
"DEGAMMA_LUT" and "CTM".

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/drm_atomic_uapi.c   | 20 ++++++++++++++++++++
 drivers/gpu/drm/drm_connector.c     |  1 +
 drivers/gpu/drm/drm_crtc_internal.h |  1 +
 drivers/gpu/drm/drm_ioctl.c         |  9 +++++++++
 drivers/gpu/drm/drm_mode_object.c   |  9 +++++++++
 include/drm/drm_file.h              |  7 +++++++
 include/uapi/drm/drm.h              | 19 +++++++++++++++++++
 7 files changed, 66 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 07d0d224fe58c..d1bc78b2567a9 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -433,6 +433,11 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 	if (property == config->prop_active)
 		state->active = val;
 	else if (property == crtc->color_pipeline_property) {
+		if (!file_priv->crtc_color_pipeline) {
+			drm_dbg_atomic(dev,
+				"Setting COLOR_PIPELINE CRTC property not permitted without DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
+			return -EINVAL;
+		}
 		/* find DRM colorop object */
 		struct drm_colorop *colorop = NULL;
 
@@ -451,6 +456,11 @@ 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) {
+		if (file_priv->crtc_color_pipeline) {
+			drm_dbg_atomic(dev,
+				"Setting DEGAMMA_LUT CRTC property not permitted with DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
+			return -EINVAL;
+		}
 		ret = drm_property_replace_blob_from_id(dev,
 					&state->degamma_lut,
 					val,
@@ -459,6 +469,11 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 		state->color_mgmt_changed |= replaced;
 		return ret;
 	} else if (property == config->ctm_property) {
+		if (file_priv->crtc_color_pipeline) {
+			drm_dbg_atomic(dev,
+				"Setting CTM CRTC property not permitted with DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
+			return -EINVAL;
+		}
 		ret = drm_property_replace_blob_from_id(dev,
 					&state->ctm,
 					val,
@@ -467,6 +482,11 @@ 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) {
+		if (file_priv->crtc_color_pipeline) {
+			drm_dbg_atomic(dev,
+				"Setting GAMMA_LUT CRTC property not permitted with DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
+			return -EINVAL;
+		}
 		ret = drm_property_replace_blob_from_id(dev,
 					&state->gamma_lut,
 					val,
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 4d6dc9ebfdb5b..aec8a5c0d593a 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -3440,6 +3440,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 	 */
 	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
 			file_priv->plane_color_pipeline,
+			file_priv->crtc_color_pipeline,
 			(uint32_t __user *)(unsigned long)(out_resp->props_ptr),
 			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
 			&out_resp->count_props);
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index c094092296448..ab02e6295271d 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -164,6 +164,7 @@ void drm_mode_object_unregister(struct drm_device *dev,
 				struct drm_mode_object *object);
 int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
 				   bool plane_color_pipeline,
+				   bool crtc_color_pipeline,
 				   uint32_t __user *prop_ptr,
 				   uint64_t __user *prop_values,
 				   uint32_t *arg_count_props);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 2884075660ddd..14746afd82783 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -383,6 +383,15 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 			return -EINVAL;
 		file_priv->plane_color_pipeline = req->value;
 		break;
+	case DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE:
+		if (!file_priv->atomic)
+			return -EINVAL;
+		if (req->value > 1)
+			return -EINVAL;
+		if (!drm_core_check_feature(dev, DRIVER_CRTC_COLOR_PIPELINE))
+			return -EINVAL;
+		file_priv->crtc_color_pipeline = req->value;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index b45d501b10c86..ea4508f6a09a6 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -388,6 +388,7 @@ EXPORT_SYMBOL(drm_object_property_get_default_value);
 /* helper for getconnector and getproperties ioctls */
 int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
 				   bool plane_color_pipeline,
+				   bool crtc_color_pipeline,
 				   uint32_t __user *prop_ptr,
 				   uint64_t __user *prop_values,
 				   uint32_t *arg_count_props)
@@ -416,6 +417,13 @@ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
 				continue;
 		}
 
+		if (!crtc_color_pipeline && obj->type == DRM_MODE_OBJECT_CRTC) {
+			struct drm_crtc *crtc = obj_to_crtc(obj);
+
+			if (prop == crtc->color_pipeline_property)
+				continue;
+		}
+
 		if (*arg_count_props > count) {
 			ret = __drm_object_property_get_value(obj, prop, &val);
 			if (ret)
@@ -475,6 +483,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
 
 	ret = drm_mode_object_get_properties(obj, file_priv->atomic,
 			file_priv->plane_color_pipeline,
+			file_priv->crtc_color_pipeline,
 			(uint32_t __user *)(unsigned long)(arg->props_ptr),
 			(uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
 			&arg->count_props);
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index 6ee70ad65e1fd..d0c323378ae46 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -214,6 +214,13 @@ struct drm_file {
 	 */
 	bool plane_color_pipeline;
 
+	/**
+	 * @crtc_color_pipeline:
+	 *
+	 * True if client understands CRTC (post-blend) color pipelines
+	 */
+	bool crtc_color_pipeline;
+
 	/**
 	 * @was_master:
 	 *
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index d726828bdf408..991ef14c5377c 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -927,6 +927,25 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE	7
 
+/**
+ * DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE
+ *
+ * If set to 1 the DRM core will allow setting the COLOR_PIPELINE
+ * property on a &drm_crtc, as well as drm_colorop properties.
+ *
+ * Setting of these crtc properties will be rejected when this client
+ * cap is set:
+ * - GAMMA_LUT
+ * - DEGAMMA_LUT
+ * - CTM
+ *
+ * The client must enable &DRM_CLIENT_CAP_ATOMIC first.
+ *
+ * This client cap can only be set if the driver sets the corresponding driver
+ * cap &DRM_CAP_CRTC_COLOR_PIPELINE.
+ */
+#define DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE	8
+
 /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
 	__u64 capability;

-- 
2.51.0



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

* [PATCH v3 07/21] drm/atomic: Pass crtc_color_pipeline client cap to atomic check
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (5 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 06/21] drm: Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 08/21] drm/atomic: Print the color pipeline as part of the CRTC state print Ariel D'Alessandro
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Pass the state of the CRTC (post-blend) color pipeline client cap to the
atomic state so that drivers can rely on it to enable color pipeline
functionality and ignore the deprecated color management CRTC
properties.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/drm_atomic_uapi.c |  1 +
 include/drm/drm_atomic.h          | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index d1bc78b2567a9..03f5a80448d10 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1668,6 +1668,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 	state->acquire_ctx = &ctx;
 	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
 	state->plane_color_pipeline = file_priv->plane_color_pipeline;
+	state->crtc_color_pipeline = file_priv->crtc_color_pipeline;
 
 retry:
 	copied_objs = 0;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 74ce26fa8838b..7eb21c0426105 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -560,6 +560,26 @@ struct drm_atomic_state {
 	 */
 	bool plane_color_pipeline : 1;
 
+	/**
+	 * @crtc_color_pipeline:
+	 *
+	 * Indicates whether this atomic state originated with a client that
+	 * set the DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE.
+	 *
+	 * Drivers and helper functions should use this to ignore legacy
+	 * properties that are incompatible with the drm_crtc COLOR_PIPELINE
+	 * behavior, such as:
+	 *
+	 *  - GAMMA_LUT
+	 *  - DEGAMMA_LUT
+	 *  - GAMMA_LUT_SIZE
+	 *  - CTM
+	 *
+	 * or any other driver-specific properties that might affect pixel
+	 * values.
+	 */
+	bool crtc_color_pipeline : 1;
+
 	/**
 	 * @colorops:
 	 *

-- 
2.51.0



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

* [PATCH v3 08/21] drm/atomic: Print the color pipeline as part of the CRTC state print
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (6 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 07/21] drm/atomic: Pass crtc_color_pipeline client cap to atomic check Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 09/21] drm/colorop: Factor out common paths from colorops helpers Ariel D'Alessandro
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro,
	Harry Wentland

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Print the value of the color pipeline in the CRTC state as part of the
CRTC state print.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_atomic.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index e9022d7ad04b0..aa4aa2f589b3d 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -475,6 +475,8 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
 	drm_printf(p, "\tplane_mask=%x\n", state->plane_mask);
 	drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
 	drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
+	drm_printf(p, "\tcolor-pipeline=%d\n",
+		   state->color_pipeline ? state->color_pipeline->base.id : 0);
 	drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
 
 	if (crtc->funcs->atomic_print_state)

-- 
2.51.0



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

* [PATCH v3 09/21] drm/colorop: Factor out common paths from colorops helpers
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (7 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 08/21] drm/atomic: Print the color pipeline as part of the CRTC state print Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-25  6:26   ` kernel test robot
  2025-12-23 18:01 ` [PATCH v3 10/21] drm/colorop: Introduce colorop helpers for crtc Ariel D'Alessandro
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro,
	Harry Wentland

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Factor out the common code paths from the colorop helpers so they can be
reused by the post-blend colorop helpers.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_colorop.c | 146 ++++++++++++++++++++++++++++--------------
 1 file changed, 99 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index bf3b8ff51571b..6a285cdb0a354 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -93,9 +93,9 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
 
 /* Init Helpers */
 
-static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
-				  struct drm_plane *plane, enum drm_colorop_type type,
-				  uint32_t flags)
+static int drm_common_colorop_init(struct drm_device *dev,
+				   struct drm_colorop *colorop,
+				   enum drm_colorop_type type, uint32_t flags)
 {
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_property *prop;
@@ -108,7 +108,6 @@ static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *co
 	colorop->base.properties = &colorop->properties;
 	colorop->dev = dev;
 	colorop->type = type;
-	colorop->plane = plane;
 	colorop->next = NULL;
 
 	list_add_tail(&colorop->head, &config->colorop_list);
@@ -157,6 +156,20 @@ static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *co
 	return ret;
 }
 
+static int drm_plane_colorop_init(struct drm_device *dev,
+				  struct drm_colorop *colorop,
+				  struct drm_plane *plane,
+				  enum drm_colorop_type type, uint32_t flags)
+{
+	int ret;
+
+	ret = drm_common_colorop_init(dev, colorop, type, flags);
+
+	colorop->plane = plane;
+
+	return ret;
+}
+
 /**
  * drm_colorop_cleanup - Cleanup a drm_colorop object in color_pipeline
  *
@@ -210,31 +223,13 @@ EXPORT_SYMBOL(drm_colorop_pipeline_destroy);
  * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines.
  * @return zero on success, -E value on failure
  */
-int drm_plane_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
-				    struct drm_plane *plane, u64 supported_tfs, uint32_t flags)
+static int drm_common_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
+					    u64 supported_tfs, uint32_t flags)
 {
 	struct drm_prop_enum_list enum_list[DRM_COLOROP_1D_CURVE_COUNT];
 	int i, len;
 
 	struct drm_property *prop;
-	int ret;
-
-	if (!supported_tfs) {
-		drm_err(dev,
-			"No supported TFs for new 1D curve colorop on [PLANE:%d:%s]\n",
-			plane->base.id, plane->name);
-		return -EINVAL;
-	}
-
-	if ((supported_tfs & -BIT(DRM_COLOROP_1D_CURVE_COUNT)) != 0) {
-		drm_err(dev, "Unknown TF provided on [PLANE:%d:%s]\n",
-			plane->base.id, plane->name);
-		return -EINVAL;
-	}
-
-	ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_CURVE, flags);
-	if (ret)
-		return ret;
 
 	len = 0;
 	for (i = 0; i < DRM_COLOROP_1D_CURVE_COUNT; i++) {
@@ -263,6 +258,41 @@ int drm_plane_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *
 
 	return 0;
 }
+
+static int drm_colorop_has_supported_tf(struct drm_device *dev, struct drm_mode_object *obj,
+					const char *name, u64 supported_tfs)
+{
+	if (!supported_tfs) {
+		drm_err(dev,
+			"No supported TFs for new 1D curve colorop on [PLANE:%d:%s]\n",
+			obj->id, name);
+		return -EINVAL;
+	}
+
+	if ((supported_tfs & -BIT(DRM_COLOROP_1D_CURVE_COUNT)) != 0) {
+		drm_err(dev, "Unknown TF provided on [PLANE:%d:%s]\n",
+			obj->id, name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int drm_plane_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
+				    struct drm_plane *plane, u64 supported_tfs, uint32_t flags)
+{
+	int ret;
+
+	ret = drm_colorop_has_supported_tf(dev, &plane->base, plane->name, supported_tfs);
+	if (ret)
+		return ret;
+
+	ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_CURVE, flags);
+	if (ret)
+		return ret;
+
+	return drm_common_colorop_curve_1d_init(dev, colorop, supported_tfs, flags);
+}
 EXPORT_SYMBOL(drm_plane_colorop_curve_1d_init);
 
 static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_colorop *colorop)
@@ -283,29 +313,16 @@ static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_color
 	return 0;
 }
 
-/**
- * drm_plane_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT
- *
- * @dev: DRM device
- * @colorop: The drm_colorop object to initialize
- * @plane: The associated drm_plane
- * @lut_size: LUT size supported by driver
- * @interpolation: 1D LUT interpolation type
- * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines.
- * @return zero on success, -E value on failure
- */
-int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
-					struct drm_plane *plane, uint32_t lut_size,
-					enum drm_colorop_lut1d_interpolation_type interpolation,
-					uint32_t flags)
+static int
+drm_common_colorop_curve_1d_lut_init(struct drm_device *dev,
+				     struct drm_colorop *colorop,
+				     uint32_t lut_size,
+				     enum drm_colorop_lut1d_interpolation_type interpolation,
+				     uint32_t flags)
 {
 	struct drm_property *prop;
 	int ret;
 
-	ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT, flags);
-	if (ret)
-		return ret;
-
 	/* initialize 1D LUT only attribute */
 	/* LUT size */
 	prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC,
@@ -337,17 +354,40 @@ int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_color
 
 	return 0;
 }
-EXPORT_SYMBOL(drm_plane_colorop_curve_1d_lut_init);
 
-int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
-				   struct drm_plane *plane, uint32_t flags)
+/**
+ * drm_plane_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT
+ *
+ * @dev: DRM device
+ * @colorop: The drm_colorop object to initialize
+ * @plane: The associated drm_plane
+ * @lut_size: LUT size supported by driver
+ * @lut1d_interpolation: 1D LUT interpolation type
+ * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines.
+ * @return zero on success, -E value on failure
+ */
+int
+drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
+				    struct drm_plane *plane, uint32_t lut_size,
+				    enum drm_colorop_lut1d_interpolation_type lut1d_interpolation,
+				    uint32_t flags)
 {
 	int ret;
 
-	ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_CTM_3X4, flags);
+	ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT, flags);
 	if (ret)
 		return ret;
 
+	return drm_common_colorop_curve_1d_lut_init(dev, colorop, lut_size,
+						    lut1d_interpolation, flags);
+}
+EXPORT_SYMBOL(drm_plane_colorop_curve_1d_lut_init);
+
+static int drm_common_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
+					   uint32_t flags)
+{
+	int ret;
+
 	ret = drm_colorop_create_data_prop(dev, colorop);
 	if (ret)
 		return ret;
@@ -356,6 +396,18 @@ int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *c
 
 	return 0;
 }
+
+int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
+				   struct drm_plane *plane, uint32_t flags)
+{
+	int ret;
+
+	ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_CTM_3X4, flags);
+	if (ret)
+		return ret;
+
+	return drm_common_colorop_ctm_3x4_init(dev, colorop, flags);
+}
 EXPORT_SYMBOL(drm_plane_colorop_ctm_3x4_init);
 
 /**

-- 
2.51.0



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

* [PATCH v3 10/21] drm/colorop: Introduce colorop helpers for crtc
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (8 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 09/21] drm/colorop: Factor out common paths from colorops helpers Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 11/21] drm/crtc: Track crtc color pipeline client cap in drm_crtc_state Ariel D'Alessandro
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro,
	Harry Wentland

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Introduce colorop helper counterparts for post-blend color pipelines
that take a CRTC instead of a plane.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_colorop.c | 73 +++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_colorop.h     |  8 +++++
 2 files changed, 81 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 6a285cdb0a354..4ce93807ea565 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -170,6 +170,20 @@ static int drm_plane_colorop_init(struct drm_device *dev,
 	return ret;
 }
 
+static int drm_crtc_colorop_init(struct drm_device *dev,
+				 struct drm_colorop *colorop,
+				 struct drm_crtc *crtc,
+				 enum drm_colorop_type type, uint32_t flags)
+{
+	int ret;
+
+	ret = drm_common_colorop_init(dev, colorop, type, flags);
+
+	colorop->crtc = crtc;
+
+	return ret;
+}
+
 /**
  * drm_colorop_cleanup - Cleanup a drm_colorop object in color_pipeline
  *
@@ -295,6 +309,23 @@ int drm_plane_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *
 }
 EXPORT_SYMBOL(drm_plane_colorop_curve_1d_init);
 
+int drm_crtc_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
+				   struct drm_crtc *crtc, u64 supported_tfs, uint32_t flags)
+{
+	int ret;
+
+	ret = drm_colorop_has_supported_tf(dev, &crtc->base, crtc->name, supported_tfs);
+	if (ret)
+		return ret;
+
+	ret = drm_crtc_colorop_init(dev, colorop, crtc, DRM_COLOROP_1D_CURVE, flags);
+	if (ret)
+		return ret;
+
+	return drm_common_colorop_curve_1d_init(dev, colorop, supported_tfs, flags);
+}
+EXPORT_SYMBOL(drm_crtc_colorop_curve_1d_init);
+
 static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_colorop *colorop)
 {
 	struct drm_property *prop;
@@ -383,6 +414,35 @@ drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *
 }
 EXPORT_SYMBOL(drm_plane_colorop_curve_1d_lut_init);
 
+/**
+ * drm_crtc_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT
+ *
+ * @dev: DRM device
+ * @colorop: The drm_colorop object to initialize
+ * @crtc: The associated drm_crtc
+ * @lut_size: LUT size supported by driver
+ * @interpolation: 1D LUT interpolation type
+ * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines.
+ * @return zero on success, -E value on failure
+ */
+int
+drm_crtc_colorop_curve_1d_lut_init(struct drm_device *dev,
+				   struct drm_colorop *colorop,
+				   struct drm_crtc *crtc, uint32_t lut_size,
+				   enum drm_colorop_lut1d_interpolation_type interpolation,
+				   uint32_t flags)
+{
+	int ret;
+
+	ret = drm_crtc_colorop_init(dev, colorop, crtc, DRM_COLOROP_1D_LUT, flags);
+	if (ret)
+		return ret;
+
+	return drm_common_colorop_curve_1d_lut_init(dev, colorop, lut_size,
+						    interpolation, flags);
+}
+EXPORT_SYMBOL(drm_crtc_colorop_curve_1d_lut_init);
+
 static int drm_common_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
 					   uint32_t flags)
 {
@@ -410,6 +470,19 @@ int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *c
 }
 EXPORT_SYMBOL(drm_plane_colorop_ctm_3x4_init);
 
+int drm_crtc_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
+				   struct drm_crtc *crtc, uint32_t flags)
+{
+	int ret;
+
+	ret = drm_crtc_colorop_init(dev, colorop, crtc, DRM_COLOROP_CTM_3X4, flags);
+	if (ret)
+		return ret;
+
+	return drm_common_colorop_ctm_3x4_init(dev, colorop, flags);
+}
+EXPORT_SYMBOL(drm_crtc_colorop_ctm_3x4_init);
+
 /**
  * drm_plane_colorop_mult_init - Initialize a DRM_COLOROP_MULTIPLIER
  *
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 49d342b7f8b0b..a1f81fa96f66b 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -400,14 +400,22 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
 void drm_colorop_pipeline_destroy(struct drm_device *dev);
 void drm_colorop_cleanup(struct drm_colorop *colorop);
 
+int drm_crtc_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
+				       struct drm_crtc *crtc, uint32_t lut_size,
+				       enum drm_colorop_lut1d_interpolation_type interpolation,
+				       uint32_t flags);
 int drm_plane_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
 				    struct drm_plane *plane, u64 supported_tfs, uint32_t flags);
+int drm_crtc_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
+				   struct drm_crtc *crtc, u64 supported_tfs, uint32_t flags);
 int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
 					struct drm_plane *plane, uint32_t lut_size,
 					enum drm_colorop_lut1d_interpolation_type interpolation,
 					uint32_t flags);
 int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
 				   struct drm_plane *plane, uint32_t flags);
+int drm_crtc_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
+				   struct drm_crtc *crtc, uint32_t flags);
 int drm_plane_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
 				struct drm_plane *plane, uint32_t flags);
 int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,

-- 
2.51.0



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

* [PATCH v3 11/21] drm/crtc: Track crtc color pipeline client cap in drm_crtc_state
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (9 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 10/21] drm/colorop: Introduce colorop helpers for crtc Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 12/21] drm/mediatek: Support CRTC colorops for gamma and ctm Ariel D'Alessandro
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro,
	Harry Wentland

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Some drivers, like VKMS, only have access to the drm_crtc_state but not
the drm_atomic_state during composition of the output framebuffer. Store
the state of the CRTC (post-blend) color pipeline client cap in the
drm_crtc_state so those drivers can decide whether to look at the color
pipeline or the legacy properties for the color management settings to
apply.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_atomic.c | 1 +
 include/drm/drm_crtc.h       | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index aa4aa2f589b3d..f2028e6cdd62f 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -389,6 +389,7 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 	state->crtcs[index].new_state = crtc_state;
 	state->crtcs[index].ptr = crtc;
 	crtc_state->state = state;
+	crtc_state->color_pipeline_enabled = state->crtc_color_pipeline;
 
 	drm_dbg_atomic(state->dev, "Added [CRTC:%d:%s] %p state to %p\n",
 		       crtc->base.id, crtc->name, crtc_state, state);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index b3c9818715851..888a3a5aa3a27 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -282,6 +282,14 @@ struct drm_crtc_state {
 	 */
 	struct drm_colorop *color_pipeline;
 
+	/**
+	 * @color_pipeline_enabled:
+	 *
+	 * Whether color management should be done based on the &color_pipeline
+	 * or the legacy color properties (&ctm, &gamma_lut and &degamma_lut).
+	 */
+	bool color_pipeline_enabled;
+
 	/**
 	 * @target_vblank:
 	 *

-- 
2.51.0



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

* [PATCH v3 12/21] drm/mediatek: Support CRTC colorops for gamma and ctm
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (10 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 11/21] drm/crtc: Track crtc color pipeline client cap in drm_crtc_state Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 13/21] drm: Add helper to extract a 3x4 matrix from any CTM matrix dimensions Ariel D'Alessandro
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Allow configuring the gamma and ccorr blocks through the CRTC color
pipeline API instead of the GAMMA_LUT and CTM properties.

In order to achieve this, initialize the color pipeline property and
colorops on the CRTC based on the DDP components available in the CRTC
path. Then introduce a struct mtk_drm_colorop that extends drm_colorop
and tracks the mtk_ddp_comp that implements it in hardware, and include
new ddp_comp helper functions for setting gamma and ctm through the new
API. These helpers will then be called during commit flush for every
updated colorop if the DRM client supports the CRTC (post-blend) color
pipeline API.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_crtc.c     | 222 +++++++++++++++++++++++++++++++-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h |   2 +
 2 files changed, 219 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index 991cdb3d7d5fd..1ed3157fa91f0 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
@@ -83,6 +83,12 @@ struct mtk_crtc_state {
 	unsigned int			pending_vrefresh;
 };
 
+struct mtk_drm_colorop {
+	struct drm_colorop colorop;
+	struct mtk_ddp_comp *comp;
+	uint32_t data_id;
+};
+
 static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
 {
 	return container_of(c, struct mtk_crtc, base);
@@ -93,6 +99,11 @@ static inline struct mtk_crtc_state *to_mtk_crtc_state(struct drm_crtc_state *s)
 	return container_of(s, struct mtk_crtc_state, base);
 }
 
+static inline struct mtk_drm_colorop *to_mtk_colorop(struct drm_colorop *colorop)
+{
+	return container_of(colorop, struct mtk_drm_colorop, colorop);
+}
+
 static void mtk_crtc_finish_page_flip(struct mtk_crtc *mtk_crtc)
 {
 	struct drm_crtc *crtc = &mtk_crtc->base;
@@ -126,6 +137,19 @@ static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc)
 	spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
 }
 
+static void mtk_drm_colorop_pipeline_destroy(struct drm_device *dev)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_colorop *colorop, *next;
+	struct mtk_drm_colorop *mtk_colorop;
+
+	list_for_each_entry_safe(colorop, next, &config->colorop_list, head) {
+		drm_colorop_cleanup(colorop);
+		mtk_colorop = to_mtk_colorop(colorop);
+		kfree(mtk_colorop);
+	}
+}
+
 static void mtk_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -147,6 +171,8 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
 		mtk_ddp_comp_unregister_vblank_cb(comp);
 	}
 
+	mtk_drm_colorop_pipeline_destroy(crtc->dev);
+
 	drm_crtc_cleanup(crtc);
 }
 
@@ -862,20 +888,103 @@ static void mtk_crtc_atomic_begin(struct drm_crtc *crtc,
 	}
 }
 
+static bool colorop_data_update_flush_status(struct drm_colorop_state *colorop_state)
+{
+	struct drm_colorop *colorop = colorop_state->colorop;
+	struct mtk_drm_colorop *mtk_colorop = to_mtk_colorop(colorop);
+	struct drm_property_blob *data_blob = colorop_state->data;
+	uint32_t data_id = colorop_state->bypass ? 0 : data_blob->base.id;
+	bool needs_flush = mtk_colorop->data_id != data_id;
+
+	mtk_colorop->data_id = data_id;
+
+	return needs_flush;
+}
+
+static void mtk_crtc_ddp_comp_apply_colorop(struct drm_colorop_state *colorop_state)
+{
+	struct drm_colorop *colorop = colorop_state->colorop;
+	struct mtk_drm_colorop *mtk_colorop = to_mtk_colorop(colorop);
+	struct drm_property_blob *data_blob = colorop_state->data;
+	struct mtk_ddp_comp *ddp_comp = mtk_colorop->comp;
+	struct drm_color_ctm_3x4 *ctm = NULL;
+	struct drm_color_lut32 *lut = NULL;
+
+	switch (colorop->type) {
+	case DRM_COLOROP_1D_LUT:
+		if (!colorop_data_update_flush_status(colorop_state))
+			return;
+
+		if (!colorop_state->bypass)
+			lut = (struct drm_color_lut32 *)data_blob->data;
+
+		ddp_comp->funcs->gamma_set_color_pipeline(ddp_comp->dev, lut);
+		break;
+	case DRM_COLOROP_CTM_3X4:
+		if (!colorop_data_update_flush_status(colorop_state))
+			return;
+
+		if (!colorop_state->bypass)
+			ctm = (struct drm_color_ctm_3x4 *)data_blob->data;
+
+		ddp_comp->funcs->ctm_set_color_pipeline(ddp_comp->dev, ctm);
+		break;
+	default:
+		/* If this happens the driver is broken */
+		drm_WARN(colorop->dev, 1,
+			 "Trying to atomic flush COLOROP of type unsupported by driver: %d\n",
+			 colorop->type);
+		break;
+	}
+}
+
 static void mtk_crtc_atomic_flush(struct drm_crtc *crtc,
 				  struct drm_atomic_state *state)
 {
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct drm_colorop_state *new_colorop_state;
+	struct drm_colorop *colorop;
 	int i;
 
-	if (crtc->state->color_mgmt_changed)
-		for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
-			mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
-			mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state);
-		}
+	if (state->crtc_color_pipeline) {
+		for_each_new_colorop_in_state(state, colorop, new_colorop_state, i)
+			mtk_crtc_ddp_comp_apply_colorop(new_colorop_state);
+	} else {
+		if (crtc->state->color_mgmt_changed)
+			for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+				mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
+				mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state);
+			}
+	}
 	mtk_crtc_update_config(mtk_crtc, !!mtk_crtc->event);
 }
 
+static int mtk_crtc_atomic_check(struct drm_crtc *crtc,
+				 struct drm_atomic_state *state)
+{
+	struct drm_colorop_state *new_colorop_state;
+	struct drm_colorop *colorop;
+	int i;
+
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		switch (colorop->type) {
+		case DRM_COLOROP_1D_LUT:
+		case DRM_COLOROP_CTM_3X4:
+			if (!new_colorop_state->bypass && !new_colorop_state->data) {
+				drm_dbg_atomic(crtc->dev,
+					       "Missing required DATA property for COLOROP:%d\n",
+					       colorop->base.id);
+				return -EINVAL;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
 static const struct drm_crtc_funcs mtk_crtc_funcs = {
 	.set_config		= drm_atomic_helper_set_config,
 	.page_flip		= drm_atomic_helper_page_flip,
@@ -893,6 +1002,7 @@ static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
 	.mode_valid	= mtk_crtc_mode_valid,
 	.atomic_begin	= mtk_crtc_atomic_begin,
 	.atomic_flush	= mtk_crtc_atomic_flush,
+	.atomic_check   = mtk_crtc_atomic_check,
 	.atomic_enable	= mtk_crtc_atomic_enable,
 	.atomic_disable	= mtk_crtc_atomic_disable,
 };
@@ -995,6 +1105,100 @@ struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc)
 	return mtk_crtc->dma_dev;
 }
 
+#define MAX_COLOR_PIPELINE_OPS 2
+#define MAX_COLOR_PIPELINES 1
+
+static int mtk_colorop_init(struct mtk_crtc *mtk_crtc,
+			    struct mtk_drm_colorop *mtk_colorop,
+			    struct mtk_ddp_comp *ddp_comp)
+{
+	struct drm_colorop *colorop = &mtk_colorop->colorop;
+	int ret = 0;
+
+	if (ddp_comp->funcs->gamma_set_color_pipeline) {
+		unsigned int lut_sz = mtk_ddp_gamma_get_lut_size(ddp_comp);
+
+		ret = drm_crtc_colorop_curve_1d_lut_init(mtk_crtc->base.dev, colorop,
+							 &mtk_crtc->base,
+							 lut_sz,
+							 DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
+							 DRM_COLOROP_FLAG_ALLOW_BYPASS);
+	} else if (ddp_comp->funcs->ctm_set_color_pipeline) {
+		ret = drm_crtc_colorop_ctm_3x4_init(mtk_crtc->base.dev,
+						    colorop,
+						    &mtk_crtc->base,
+						    DRM_COLOROP_FLAG_ALLOW_BYPASS);
+	}
+
+	mtk_colorop->comp = ddp_comp;
+
+	return ret;
+}
+
+static int mtk_crtc_init_crtc_color_pipeline(struct mtk_crtc *mtk_crtc,
+					     unsigned int gamma_lut_size)
+{
+	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
+	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
+	struct mtk_drm_colorop *mtk_colorop;
+	unsigned int num_pipelines = 0;
+	unsigned int op_idx = 0;
+	int ret;
+	int j;
+
+	memset(ops, 0, sizeof(ops));
+
+	for (unsigned int i = 0;
+	     i < mtk_crtc->ddp_comp_nr && op_idx < MAX_COLOR_PIPELINE_OPS;
+	     i++) {
+		struct mtk_ddp_comp *ddp_comp = mtk_crtc->ddp_comp[i];
+
+		if (!(ddp_comp->funcs->gamma_set_color_pipeline ||
+		      ddp_comp->funcs->ctm_set_color_pipeline))
+			continue;
+
+		mtk_colorop = kzalloc(sizeof(struct mtk_drm_colorop), GFP_KERNEL);
+		if (!mtk_colorop) {
+			ret = -ENOMEM;
+			goto cleanup;
+		}
+
+		ops[op_idx] = &mtk_colorop->colorop;
+
+		ret = mtk_colorop_init(mtk_crtc, mtk_colorop, ddp_comp);
+		if (ret)
+			goto cleanup;
+
+		if (op_idx > 0)
+			drm_colorop_set_next_property(ops[op_idx-1], ops[op_idx]);
+
+		op_idx++;
+	}
+
+	if (op_idx > 0) {
+		pipelines[0].type = ops[0]->base.id;
+		pipelines[0].name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
+		num_pipelines = 1;
+	}
+
+	/* Create COLOR_PIPELINE property and attach */
+	drm_crtc_create_color_pipeline_property(&mtk_crtc->base, pipelines, num_pipelines);
+
+	return 0;
+
+cleanup:
+	for (j = 0; j < op_idx; j++) {
+		if (ops[j]) {
+			drm_colorop_cleanup(ops[j]);
+			mtk_colorop = to_mtk_colorop(ops[j]);
+			kfree(mtk_colorop);
+			kfree(ops[j]);
+		}
+	}
+
+	return ret;
+}
+
 int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 		    unsigned int path_len, int priv_data_index,
 		    const struct mtk_drm_route *conn_routes,
@@ -1111,6 +1315,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	if (ret < 0)
 		return ret;
 
+	ret = mtk_crtc_init_crtc_color_pipeline(mtk_crtc, gamma_lut_size);
+	if (ret < 0)
+		goto err_cleanup_crtc;
+
 	if (gamma_lut_size)
 		drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
 	drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
@@ -1183,4 +1391,8 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	}
 
 	return 0;
+
+err_cleanup_crtc:
+	drm_crtc_cleanup(&mtk_crtc->base);
+	return ret;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 3f3d43f4330da..93665b5d5358c 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -75,10 +75,12 @@ struct mtk_ddp_comp_funcs {
 	unsigned int (*gamma_get_lut_size)(struct device *dev);
 	void (*gamma_set)(struct device *dev,
 			  struct drm_crtc_state *state);
+	void (*gamma_set_color_pipeline)(struct device *dev, struct drm_color_lut32 *lut);
 	void (*bgclr_in_on)(struct device *dev);
 	void (*bgclr_in_off)(struct device *dev);
 	void (*ctm_set)(struct device *dev,
 			struct drm_crtc_state *state);
+	void (*ctm_set_color_pipeline)(struct device *dev, struct drm_color_ctm_3x4 *ctm);
 	struct device * (*dma_dev_get)(struct device *dev);
 	u32 (*get_blend_modes)(struct device *dev);
 	const u32 *(*get_formats)(struct device *dev);

-- 
2.51.0



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

* [PATCH v3 13/21] drm: Add helper to extract a 3x4 matrix from any CTM matrix dimensions
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (11 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 12/21] drm/mediatek: Support CRTC colorops for gamma and ctm Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 14/21] drm/mediatek: ccorr: Support CRTC color pipeline API Ariel D'Alessandro
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

Add a common helper to ease the conversion from both 3x3 or 3x4 matrices
to a CTM 3x4 matrix. This is handy for code that needs to handle both
dimensions.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 include/drm/drm_color_mgmt.h | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 5140691f476a9..51279267ed3fd 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -66,6 +66,40 @@ static inline u32 drm_color_lut32_extract(u32 user_input, int bit_precision)
 				     (1ULL << 32) - 1);
 }
 
+/**
+ * drm_color_ctm_to_ctm_3x4 - Copy CTM matrix contents to 3x4 dimensions matrix
+ *
+ * @dest: The destination CTM 3x4 dimensions matrix
+ * @src: The source CTM matrix (3x3 or 3x4 dimensions depending on @ctm_3x4)
+ * @ctm_3x4: Boolean indicating the source CTM matrix dimensions
+ *
+ * Copy the contents of a CTM matrix from @src, to a CTM 3x4 dimensions matrix.
+ * The source matrix can be 3x3 or 3x4 dimensions depending on the @ctm_3x4
+ * boolean argument.
+ */
+static inline void drm_color_ctm_to_ctm_3x4(struct drm_color_ctm_3x4 *dest,
+					    void *src, bool ctm_3x4)
+{
+	if (ctm_3x4) {
+		*dest = *(struct drm_color_ctm_3x4 *)src;
+	} else {
+		struct drm_color_ctm *ctm = (struct drm_color_ctm *)src;
+
+		dest->matrix[0] = ctm->matrix[0];
+		dest->matrix[1] = ctm->matrix[1];
+		dest->matrix[2] = ctm->matrix[2];
+		dest->matrix[3] = 0;
+		dest->matrix[4] = ctm->matrix[3];
+		dest->matrix[5] = ctm->matrix[4];
+		dest->matrix[6] = ctm->matrix[5];
+		dest->matrix[7] = 0;
+		dest->matrix[8] = ctm->matrix[6];
+		dest->matrix[9] = ctm->matrix[7];
+		dest->matrix[10] = ctm->matrix[8];
+		dest->matrix[11] = 0;
+	}
+}
+
 u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n);
 
 void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,

-- 
2.51.0



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

* [PATCH v3 14/21] drm/mediatek: ccorr: Support CRTC color pipeline API
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (12 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 13/21] drm: Add helper to extract a 3x4 matrix from any CTM matrix dimensions Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 15/21] drm: Add helper to extract a LUT entry from either 16-bit or 32-bit LUT Ariel D'Alessandro
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Implement the ctm_set_color_pipeline DDP component function to allow
configuring the CTM through the color pipeline API.

The color pipeline API only defines a 3x4 matrix, while the driver
currently only supports setting the coefficients for a 3x3 matrix.
However the underlying hardware does support setting the offset
coefficients that make up a 3x4 matrix, so implement support for setting
them so the 3x4 matrix structure for the API can be used as is.

Also make sure to enable or disable the CTM function depending on
whether the block should be bypassed or not.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c   |  3 +-
 drivers/gpu/drm/mediatek/mtk_disp_ccorr.c | 88 ++++++++++++++++++++++++-------
 drivers/gpu/drm/mediatek/mtk_disp_drv.h   |  3 +-
 3 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index 9672ea1f91a2b..69eeb36609584 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -284,7 +284,8 @@ static const struct mtk_ddp_comp_funcs ddp_ccorr = {
 	.config = mtk_ccorr_config,
 	.start = mtk_ccorr_start,
 	.stop = mtk_ccorr_stop,
-	.ctm_set = mtk_ccorr_ctm_set,
+	.ctm_set = mtk_ccorr_ctm_set_legacy,
+	.ctm_set_color_pipeline = mtk_ccorr_ctm_set_color_pipeline,
 };
 
 static const struct mtk_ddp_comp_funcs ddp_color = {
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
index 6d7bf4afa78d3..e2bd8010d22e5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
@@ -28,6 +28,11 @@
 #define DISP_CCORR_COEF_2			0x0088
 #define DISP_CCORR_COEF_3			0x008C
 #define DISP_CCORR_COEF_4			0x0090
+#define DISP_CCORR_OFFSET_0			0x0100
+#define CCORR_OFFSET_EN					BIT(31)
+#define DISP_CCORR_OFFSET_1			0x0104
+#define DISP_CCORR_OFFSET_2			0x0108
+#define DISP_CCORR_OFFSET_MASK				GENMASK(26, 14)
 
 struct mtk_disp_ccorr_data {
 	u32 matrix_bits;
@@ -80,36 +85,81 @@ void mtk_ccorr_stop(struct device *dev)
 	writel_relaxed(0x0, ccorr->regs + DISP_CCORR_EN);
 }
 
-void mtk_ccorr_ctm_set(struct device *dev, struct drm_crtc_state *state)
+static void mtk_ccorr_ctm_set(struct device *dev, struct cmdq_pkt *cmdq_pkt,
+			      void *ctm, bool ctm_3x4)
 {
 	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
-	struct drm_property_blob *blob = state->ctm;
-	struct drm_color_ctm *ctm;
-	const u64 *input;
-	uint16_t coeffs[9] = { 0 };
-	int i;
-	struct cmdq_pkt *cmdq_pkt = NULL;
 	u32 matrix_bits = ccorr->data->matrix_bits;
+	struct drm_color_ctm_3x4 coeffs;
+	u32 val;
+	int i;
 
-	if (!blob)
-		return;
+	drm_color_ctm_to_ctm_3x4(&coeffs, ctm, ctm_3x4);
 
-	ctm = (struct drm_color_ctm *)blob->data;
-	input = ctm->matrix;
+	for (i = 0; i < ARRAY_SIZE(coeffs.matrix); i++)
+		coeffs.matrix[i] =
+			drm_color_ctm_s31_32_to_qm_n(coeffs.matrix[i], 2, matrix_bits);
 
-	for (i = 0; i < ARRAY_SIZE(coeffs); i++)
-		coeffs[i] = drm_color_ctm_s31_32_to_qm_n(input[i], 2, matrix_bits);
-
-	mtk_ddp_write(cmdq_pkt, coeffs[0] << 16 | coeffs[1],
+	mtk_ddp_write(cmdq_pkt, coeffs.matrix[0] << 16 | coeffs.matrix[1],
 		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_0);
-	mtk_ddp_write(cmdq_pkt, coeffs[2] << 16 | coeffs[3],
+	mtk_ddp_write(cmdq_pkt, coeffs.matrix[2] << 16 | coeffs.matrix[4],
 		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_1);
-	mtk_ddp_write(cmdq_pkt, coeffs[4] << 16 | coeffs[5],
+	mtk_ddp_write(cmdq_pkt, coeffs.matrix[5] << 16 | coeffs.matrix[6],
 		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_2);
-	mtk_ddp_write(cmdq_pkt, coeffs[6] << 16 | coeffs[7],
+	mtk_ddp_write(cmdq_pkt, coeffs.matrix[8] << 16 | coeffs.matrix[9],
 		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_3);
-	mtk_ddp_write(cmdq_pkt, coeffs[8] << 16,
+	mtk_ddp_write(cmdq_pkt, coeffs.matrix[10] << 16,
 		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_4);
+
+	if (ctm_3x4) {
+		val = CCORR_OFFSET_EN;
+		val |= FIELD_PREP(DISP_CCORR_OFFSET_MASK, coeffs.matrix[3]);
+		mtk_ddp_write(cmdq_pkt, val, &ccorr->cmdq_reg,
+			      ccorr->regs, DISP_CCORR_OFFSET_0);
+		val = FIELD_PREP(DISP_CCORR_OFFSET_MASK, coeffs.matrix[7]);
+		mtk_ddp_write(cmdq_pkt, val, &ccorr->cmdq_reg,
+			      ccorr->regs, DISP_CCORR_OFFSET_1);
+		val = FIELD_PREP(DISP_CCORR_OFFSET_MASK, coeffs.matrix[11]);
+		mtk_ddp_write(cmdq_pkt, val, &ccorr->cmdq_reg,
+			      ccorr->regs, DISP_CCORR_OFFSET_2);
+	} else {
+		mtk_ddp_write_mask(cmdq_pkt, 0, &ccorr->cmdq_reg,
+				   ccorr->regs, DISP_CCORR_OFFSET_0,
+				   CCORR_OFFSET_EN);
+	}
+
+	mtk_ddp_write(cmdq_pkt, CCORR_ENGINE_EN, &ccorr->cmdq_reg,
+		      ccorr->regs, DISP_CCORR_CFG);
+}
+
+void mtk_ccorr_ctm_set_legacy(struct device *dev, struct drm_crtc_state *state)
+{
+	struct drm_property_blob *blob = state->ctm;
+	struct cmdq_pkt *cmdq_pkt = NULL;
+	struct drm_color_ctm *ctm;
+
+	if (!blob)
+		return;
+
+	ctm = (struct drm_color_ctm *)blob->data;
+
+	mtk_ccorr_ctm_set(dev, cmdq_pkt, ctm, false);
+}
+
+void mtk_ccorr_ctm_set_color_pipeline(struct device *dev, struct drm_color_ctm_3x4 *ctm)
+{
+	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
+	struct cmdq_pkt *cmdq_pkt = NULL;
+
+	/* Configure block to be bypassed */
+	if (!ctm) {
+		mtk_ddp_write_mask(cmdq_pkt, CCORR_RELAY_MODE, &ccorr->cmdq_reg,
+				   ccorr->regs, DISP_CCORR_CFG,
+				   CCORR_RELAY_MODE | CCORR_ENGINE_EN);
+		return;
+	}
+
+	mtk_ccorr_ctm_set(dev, cmdq_pkt, ctm, true);
 }
 
 static int mtk_disp_ccorr_bind(struct device *dev, struct device *master,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 679d413bf10be..ac84cf579150f 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -22,7 +22,8 @@ void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state);
 void mtk_aal_start(struct device *dev);
 void mtk_aal_stop(struct device *dev);
 
-void mtk_ccorr_ctm_set(struct device *dev, struct drm_crtc_state *state);
+void mtk_ccorr_ctm_set_legacy(struct device *dev, struct drm_crtc_state *state);
+void mtk_ccorr_ctm_set_color_pipeline(struct device *dev, struct drm_color_ctm_3x4 *ctm);
 int mtk_ccorr_clk_enable(struct device *dev);
 void mtk_ccorr_clk_disable(struct device *dev);
 void mtk_ccorr_config(struct device *dev, unsigned int w,

-- 
2.51.0



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

* [PATCH v3 15/21] drm: Add helper to extract a LUT entry from either 16-bit or 32-bit LUT
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (13 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 14/21] drm/mediatek: ccorr: Support CRTC color pipeline API Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 16/21] drm/mediatek: gamma: Support CRTC color pipeline API Ariel D'Alessandro
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

Add a common helper to ease extracting a 32-bit LUT entry from either
16-bit or 32-bit LUT entry. This is handy for code that needs to handle
both bit widths.

Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Co-developed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
---
 include/drm/drm_color_mgmt.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 51279267ed3fd..3d0117aae342d 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -66,6 +66,33 @@ static inline u32 drm_color_lut32_extract(u32 user_input, int bit_precision)
 				     (1ULL << 32) - 1);
 }
 
+/**
+ * drm_color_lut_to_lut32 - Copy LUT entry contents to 32-bit channel color LUT
+ *
+ * @dest: The destination 32-bit per channel color LUT entry
+ * @src: The source array of LUT entries (16-bit or 32-bit depending on @bits32)
+ * @index: LUT entry array index
+ * @bits32: Boolean indicating the source LUT entry bit-witdh
+ *
+ * Copy the contents of a LUT entry from the source array, to a 32-bit channel
+ * color LUT. The source array of LUT entries can be 16-bit or 32-bit width
+ * depending on the @bits32 boolean argument.
+ */
+static inline void drm_color_lut_to_lut32(struct drm_color_lut32 *dest,
+					  void *src, int index, bool bits32)
+{
+	if (bits32) {
+		*dest = ((struct drm_color_lut32 *)src)[index];
+	} else {
+		struct drm_color_lut *lut =
+			&((struct drm_color_lut *)src)[index];
+		dest->red = lut->red;
+		dest->green = lut->green;
+		dest->blue = lut->blue;
+		dest->reserved = lut->reserved;
+	}
+}
+
 /**
  * drm_color_ctm_to_ctm_3x4 - Copy CTM matrix contents to 3x4 dimensions matrix
  *

-- 
2.51.0



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

* [PATCH v3 16/21] drm/mediatek: gamma: Support CRTC color pipeline API
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (14 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 15/21] drm: Add helper to extract a LUT entry from either 16-bit or 32-bit LUT Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 17/21] drm/mediatek: Set CRTC color pipeline driver cap Ariel D'Alessandro
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Implement the gamma_set_color_pipeline DDP component function to allow
configuring the gamma LUT through the CRTC color pipeline API.

The color pipeline API uses a 32-bit long, rather than 16-bit long, LUT,
so also update the functions to handle both cases.

Also make sure to enable or disable the LUT function depending on
whether the block should be bypassed or not.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c   |  3 +-
 drivers/gpu/drm/mediatek/mtk_disp_drv.h   |  3 +-
 drivers/gpu/drm/mediatek/mtk_disp_gamma.c | 68 +++++++++++++++++++++++--------
 3 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index 69eeb36609584..cf456ab3cf70f 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -327,7 +327,8 @@ static const struct mtk_ddp_comp_funcs ddp_gamma = {
 	.clk_enable = mtk_gamma_clk_enable,
 	.clk_disable = mtk_gamma_clk_disable,
 	.gamma_get_lut_size = mtk_gamma_get_lut_size,
-	.gamma_set = mtk_gamma_set,
+	.gamma_set = mtk_gamma_set_legacy,
+	.gamma_set_color_pipeline = mtk_gamma_set_color_pipeline,
 	.config = mtk_gamma_config,
 	.start = mtk_gamma_start,
 	.stop = mtk_gamma_stop,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index ac84cf579150f..7795aa5bc057f 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -58,7 +58,8 @@ void mtk_gamma_config(struct device *dev, unsigned int w,
 		      unsigned int h, unsigned int vrefresh,
 		      unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
 unsigned int mtk_gamma_get_lut_size(struct device *dev);
-void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state);
+void mtk_gamma_set_legacy(struct device *dev, struct drm_crtc_state *state);
+void mtk_gamma_set_color_pipeline(struct device *dev, struct drm_color_lut32 *lut);
 void mtk_gamma_start(struct device *dev);
 void mtk_gamma_stop(struct device *dev);
 
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
index 8afd15006df2a..efda0bbb0b09d 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
@@ -87,13 +87,17 @@ unsigned int mtk_gamma_get_lut_size(struct device *dev)
 	return 0;
 }
 
-static bool mtk_gamma_lut_is_descending(struct drm_color_lut *lut, u32 lut_size)
+static bool mtk_gamma_lut_is_descending(void *lut, bool bits32, u32 lut_size)
 {
 	u64 first, last;
 	int last_entry = lut_size - 1;
+	struct drm_color_lut32 lut_first, lut_last;
 
-	first = lut[0].red + lut[0].green + lut[0].blue;
-	last = lut[last_entry].red + lut[last_entry].green + lut[last_entry].blue;
+	drm_color_lut_to_lut32(&lut_first, lut, 0, bits32);
+	drm_color_lut_to_lut32(&lut_last, lut, last_entry, bits32);
+
+	first = lut_first.red + lut_first.green + lut_first.blue;
+	last = lut_last.red + lut_last.green + lut_last.blue;
 
 	return !!(first > last);
 }
@@ -113,7 +117,7 @@ static bool mtk_gamma_lut_is_descending(struct drm_color_lut *lut, u32 lut_size)
  *     - 12-bits LUT supported
  *     - 10-its LUT not supported
  */
-void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
+static void mtk_gamma_set(struct device *dev, void *lut, bool bits32)
 {
 	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
 	void __iomem *lut0_base = gamma->regs + DISP_GAMMA_LUT;
@@ -121,15 +125,9 @@ void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
 	u32 cfg_val, data_mode, lbank_val, word[2];
 	u8 lut_bits = gamma->data->lut_bits;
 	int cur_bank, num_lut_banks;
-	struct drm_color_lut *lut;
 	unsigned int i;
 
-	/* If there's no gamma lut there's nothing to do here. */
-	if (!state->gamma_lut)
-		return;
-
 	num_lut_banks = gamma->data->lut_size / gamma->data->lut_bank_size;
-	lut = (struct drm_color_lut *)state->gamma_lut->data;
 
 	/* Switch to 12 bits data mode if supported */
 	data_mode = FIELD_PREP(DISP_GAMMA_BANK_DATA_MODE, !!(lut_bits == 12));
@@ -145,11 +143,13 @@ void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
 
 		for (i = 0; i < gamma->data->lut_bank_size; i++) {
 			int n = cur_bank * gamma->data->lut_bank_size + i;
-			struct drm_color_lut diff, hwlut;
+			struct drm_color_lut32 diff, hwlut, lut32;
+
+			drm_color_lut_to_lut32(&lut32, lut, n, bits32);
 
-			hwlut.red = drm_color_lut_extract(lut[n].red, lut_bits);
-			hwlut.green = drm_color_lut_extract(lut[n].green, lut_bits);
-			hwlut.blue = drm_color_lut_extract(lut[n].blue, lut_bits);
+			hwlut.red = drm_color_lut_extract(lut32.red, lut_bits);
+			hwlut.green = drm_color_lut_extract(lut32.green, lut_bits);
+			hwlut.blue = drm_color_lut_extract(lut32.blue, lut_bits);
 
 			if (!gamma->data->lut_diff || (i % 2 == 0)) {
 				if (lut_bits == 12) {
@@ -162,13 +162,17 @@ void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
 					word[0] |= FIELD_PREP(DISP_GAMMA_LUT_10BIT_B, hwlut.blue);
 				}
 			} else {
-				diff.red = lut[n].red - lut[n - 1].red;
+				struct drm_color_lut32 lut_prev;
+
+				drm_color_lut_to_lut32(&lut_prev, lut, n-1, bits32);
+
+				diff.red = lut32.red - lut_prev.red;
 				diff.red = drm_color_lut_extract(diff.red, lut_bits);
 
-				diff.green = lut[n].green - lut[n - 1].green;
+				diff.green = lut32.green - lut_prev.green;
 				diff.green = drm_color_lut_extract(diff.green, lut_bits);
 
-				diff.blue = lut[n].blue - lut[n - 1].blue;
+				diff.blue = lut32.blue - lut_prev.blue;
 				diff.blue = drm_color_lut_extract(diff.blue, lut_bits);
 
 				if (lut_bits == 12) {
@@ -191,7 +195,7 @@ void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
 
 	if (!gamma->data->has_dither) {
 		/* Descending or Rising LUT */
-		if (mtk_gamma_lut_is_descending(lut, gamma->data->lut_size - 1))
+		if (mtk_gamma_lut_is_descending(lut, bits32, gamma->data->lut_size - 1))
 			cfg_val |= FIELD_PREP(GAMMA_LUT_TYPE, 1);
 		else
 			cfg_val &= ~GAMMA_LUT_TYPE;
@@ -206,6 +210,34 @@ void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
 	writel(cfg_val, gamma->regs + DISP_GAMMA_CFG);
 }
 
+void mtk_gamma_set_legacy(struct device *dev, struct drm_crtc_state *state)
+{
+	struct drm_color_lut *lut = (struct drm_color_lut *)state->gamma_lut->data;
+
+	/* If there's no gamma lut there's nothing to do here. */
+	if (!state->gamma_lut)
+		return;
+
+	mtk_gamma_set(dev, lut, false);
+}
+
+void mtk_gamma_set_color_pipeline(struct device *dev, struct drm_color_lut32 *lut)
+{
+	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
+	u32 cfg_val;
+
+	/* Configure block to be bypassed */
+	if (!lut) {
+		cfg_val = readl(gamma->regs + DISP_GAMMA_CFG);
+		cfg_val &= ~GAMMA_LUT_EN;
+		cfg_val |= GAMMA_RELAY_MODE;
+		writel(cfg_val, gamma->regs + DISP_GAMMA_CFG);
+		return;
+	}
+
+	mtk_gamma_set(dev, lut, true);
+}
+
 void mtk_gamma_config(struct device *dev, unsigned int w,
 		      unsigned int h, unsigned int vrefresh,
 		      unsigned int bpc, struct cmdq_pkt *cmdq_pkt)

-- 
2.51.0



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

* [PATCH v3 17/21] drm/mediatek: Set CRTC color pipeline driver cap
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (15 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 16/21] drm/mediatek: gamma: Support CRTC color pipeline API Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 18/21] drm/vkms: Rename existing color pipeline helpers to contain "plane" Ariel D'Alessandro
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Now that the driver implements CRTC (post-blend) color pipelines, set
the driver cap so they can be used from userspace.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index a94c51a832616..554b310ca11a5 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -613,7 +613,8 @@ static struct drm_gem_object *mtk_gem_prime_import(struct drm_device *dev,
 }
 
 static const struct drm_driver mtk_drm_driver = {
-	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC |
+			   DRIVER_CRTC_COLOR_PIPELINE,
 
 	.dumb_create = mtk_gem_dumb_create,
 	DRM_FBDEV_DMA_DRIVER_OPS,

-- 
2.51.0



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

* [PATCH v3 18/21] drm/vkms: Rename existing color pipeline helpers to contain "plane"
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (16 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 17/21] drm/mediatek: Set CRTC color pipeline driver cap Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 19/21] drm/vkms: Prepare pre_blend_color_transform() for CRTC color pipelines Ariel D'Alessandro
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Rename the existing color pipeline helpers so they contain "plane" in
the name to make them clearly distinguishable from the crtc helpers when
they're introduced.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_colorop.c | 7 ++++---
 drivers/gpu/drm/vkms/vkms_drv.h     | 2 +-
 drivers/gpu/drm/vkms/vkms_plane.c   | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
index 5c3ffc78aea06..dd6120434690e 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -14,7 +14,8 @@ static const u64 supported_tfs =
 
 #define MAX_COLOR_PIPELINE_OPS 4
 
-static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
+static int vkms_initialize_plane_color_pipeline(struct drm_plane *plane,
+						struct drm_prop_enum_list *list)
 {
 	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
 	struct drm_device *dev = plane->dev;
@@ -101,13 +102,13 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
 	return ret;
 }
 
-int vkms_initialize_colorops(struct drm_plane *plane)
+int vkms_initialize_plane_colorops(struct drm_plane *plane)
 {
 	struct drm_prop_enum_list pipeline;
 	int ret;
 
 	/* Add color pipeline */
-	ret = vkms_initialize_color_pipeline(plane, &pipeline);
+	ret = vkms_initialize_plane_color_pipeline(plane, &pipeline);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 0933e4ce0ff03..bdeb52623f4d6 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -324,6 +324,6 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer
 int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_output *vkms_out);
 
 /* Colorops */
-int vkms_initialize_colorops(struct drm_plane *plane);
+int vkms_initialize_plane_colorops(struct drm_plane *plane);
 
 #endif /* _VKMS_DRV_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 19fe6acad306e..82be1b862c1da 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -247,7 +247,7 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 					  DRM_COLOR_YCBCR_FULL_RANGE);
 
 	if (vkms_config_plane_get_default_pipeline(plane_cfg))
-		vkms_initialize_colorops(&plane->base);
+		vkms_initialize_plane_colorops(&plane->base);
 
 	return plane;
 }

-- 
2.51.0



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

* [PATCH v3 19/21] drm/vkms: Prepare pre_blend_color_transform() for CRTC color pipelines
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (17 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 18/21] drm/vkms: Rename existing color pipeline helpers to contain "plane" Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 20/21] drm/vkms: Introduce support for post-blend color pipeline Ariel D'Alessandro
  2025-12-23 18:01 ` [PATCH v3 21/21] drm/vkms: Set CRTC color pipeline driver cap Ariel D'Alessandro
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

As a preparatory step for supporting CRTC (post-blend) color pipelines
in VKMS, rename pre_blend_color_transform() to color_transform() and
make it take the first colorop instead of a plane state, so it can be
shared by both plane (pre-blend) and CRTC (post-blend) color pipeline
code paths.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 drivers/gpu/drm/vkms/vkms_composer.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 3cf3f26e0d8ea..d4f87a2aa3359 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -189,13 +189,13 @@ static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colo
 	}
 }
 
-static void pre_blend_color_transform(const struct vkms_plane_state *plane_state,
-				      struct line_buffer *output_buffer)
+static void color_transform(struct drm_colorop *first_colorop,
+			    struct line_buffer *output_buffer)
 {
 	struct pixel_argb_s32 pixel;
 
 	for (size_t x = 0; x < output_buffer->n_pixels; x++) {
-		struct drm_colorop *colorop = plane_state->base.base.color_pipeline;
+		struct drm_colorop *colorop = first_colorop;
 
 		/*
 		 * Some operations, such as applying a BT709 encoding matrix,
@@ -449,7 +449,7 @@ static void blend_line(struct vkms_plane_state *current_plane, int y,
 	 */
 	current_plane->pixel_read_line(current_plane, src_x_start, src_y_start, direction,
 				       pixel_count, &stage_buffer->pixels[dst_x_start]);
-	pre_blend_color_transform(current_plane, stage_buffer);
+	color_transform(current_plane->base.base.color_pipeline, stage_buffer);
 	pre_mul_alpha_blend(stage_buffer, output_buffer,
 			    dst_x_start, pixel_count);
 }

-- 
2.51.0



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

* [PATCH v3 20/21] drm/vkms: Introduce support for post-blend color pipeline
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (18 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 19/21] drm/vkms: Prepare pre_blend_color_transform() for CRTC color pipelines Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  2026-07-08 17:35   ` Robert Mader
  2025-12-23 18:01 ` [PATCH v3 21/21] drm/vkms: Set CRTC color pipeline driver cap Ariel D'Alessandro
  20 siblings, 1 reply; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Introduce a post-blend color pipeline with the same colorop blocks as
the pre-blend color pipeline.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
---
 drivers/gpu/drm/vkms/tests/vkms_config_test.c |  70 ++++++++++-------
 drivers/gpu/drm/vkms/vkms_colorop.c           | 103 ++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_composer.c          |   5 +-
 drivers/gpu/drm/vkms/vkms_config.c            |   5 +-
 drivers/gpu/drm/vkms/vkms_config.h            |  29 +++++++-
 drivers/gpu/drm/vkms/vkms_crtc.c              |   6 +-
 drivers/gpu/drm/vkms/vkms_drv.c               |   7 +-
 drivers/gpu/drm/vkms/vkms_drv.h               |   6 +-
 drivers/gpu/drm/vkms/vkms_output.c            |   3 +-
 9 files changed, 202 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
index 1e4ea1863420f..ec1d84ae508ad 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
@@ -84,6 +84,7 @@ struct default_config_case {
 	bool enable_writeback;
 	bool enable_overlay;
 	bool enable_plane_pipeline;
+	bool enable_crtc_pipeline;
 };
 
 static void vkms_config_test_empty_config(struct kunit *test)
@@ -109,22 +110,38 @@ static void vkms_config_test_empty_config(struct kunit *test)
 }
 
 static struct default_config_case default_config_cases[] = {
-	{ false, false, false, false },
-	{ true, false, false, false },
-	{ true, true, false, false },
-	{ true, false, true, false },
-	{ false, true, false, false },
-	{ false, true, true, false },
-	{ false, false, true, false },
-	{ true, true, true, false },
-	{ false, false, false, true },
-	{ true, false, false, true },
-	{ true, true, false, true },
-	{ true, false, true, true },
-	{ false, true, false, true },
-	{ false, true, true, true },
-	{ false, false, true, true },
-	{ true, true, true, true },
+	{ false, false, false, false, false },
+	{ true, false, false, false, false },
+	{ true, true, false, false, false },
+	{ true, false, true, false, false },
+	{ false, true, false, false, false },
+	{ false, true, true, false, false },
+	{ false, false, true, false, false },
+	{ true, true, true, false, false },
+	{ false, false, false, true, false },
+	{ true, false, false, true, false },
+	{ true, true, false, true, false },
+	{ true, false, true, true, false },
+	{ false, true, false, true, false },
+	{ false, true, true, true, false },
+	{ false, false, true, true, false },
+	{ true, true, true, true, false },
+	{ false, false, false, false, true },
+	{ true, false, false, false, true },
+	{ true, true, false, false, true },
+	{ true, false, true, false, true },
+	{ false, true, false, false, true },
+	{ false, true, true, false, true },
+	{ false, false, true, false, true },
+	{ true, true, true, false, true },
+	{ false, false, false, true, true },
+	{ true, false, false, true, true },
+	{ true, true, false, true, true },
+	{ true, false, true, true, true },
+	{ false, true, false, true, true },
+	{ false, true, true, true, true },
+	{ false, false, true, true, true },
+	{ true, true, true, true, true },
 };
 
 KUNIT_ARRAY_PARAM(default_config, default_config_cases, NULL);
@@ -142,7 +159,8 @@ static void vkms_config_test_default_config(struct kunit *test)
 	config = vkms_config_default_create(params->enable_cursor,
 					    params->enable_writeback,
 					    params->enable_overlay,
-					    params->enable_plane_pipeline);
+					    params->enable_plane_pipeline,
+					    params->enable_crtc_pipeline);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	/* Planes */
@@ -174,6 +192,8 @@ static void vkms_config_test_default_config(struct kunit *test)
 	crtc_cfg = get_first_crtc(config);
 	KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_writeback(crtc_cfg),
 			params->enable_writeback);
+	KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_default_pipeline(crtc_cfg),
+			params->enable_crtc_pipeline);
 
 	vkms_config_for_each_plane(config, plane_cfg) {
 		struct vkms_config_crtc *possible_crtc;
@@ -381,7 +401,7 @@ static void vkms_config_test_invalid_plane_number(struct kunit *test)
 	struct vkms_config_plane *plane_cfg;
 	int n;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	/* Invalid: No planes */
@@ -406,7 +426,7 @@ static void vkms_config_test_valid_plane_type(struct kunit *test)
 	struct vkms_config_encoder *encoder_cfg;
 	int err;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	plane_cfg = get_first_plane(config);
@@ -487,7 +507,7 @@ static void vkms_config_test_valid_plane_possible_crtcs(struct kunit *test)
 	struct vkms_config_plane *plane_cfg;
 	struct vkms_config_crtc *crtc_cfg;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	plane_cfg = get_first_plane(config);
@@ -506,7 +526,7 @@ static void vkms_config_test_invalid_crtc_number(struct kunit *test)
 	struct vkms_config_crtc *crtc_cfg;
 	int n;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	/* Invalid: No CRTCs */
@@ -529,7 +549,7 @@ static void vkms_config_test_invalid_encoder_number(struct kunit *test)
 	struct vkms_config_encoder *encoder_cfg;
 	int n;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	/* Invalid: No encoders */
@@ -554,7 +574,7 @@ static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *test)
 	struct vkms_config_encoder *encoder_cfg;
 	int err;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	crtc_cfg1 = get_first_crtc(config);
@@ -600,7 +620,7 @@ static void vkms_config_test_invalid_connector_number(struct kunit *test)
 	struct vkms_config_connector *connector_cfg;
 	int n;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	/* Invalid: No connectors */
@@ -623,7 +643,7 @@ static void vkms_config_test_valid_connector_possible_encoders(struct kunit *tes
 	struct vkms_config_encoder *encoder_cfg;
 	struct vkms_config_connector *connector_cfg;
 
-	config = vkms_config_default_create(false, false, false, false);
+	config = vkms_config_default_create(false, false, false, false, false);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
 
 	encoder_cfg = get_first_encoder(config);
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
index dd6120434690e..6c4a6cb186564 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -102,6 +102,91 @@ static int vkms_initialize_plane_color_pipeline(struct drm_plane *plane,
 	return ret;
 }
 
+static int vkms_initialize_crtc_color_pipeline(struct drm_crtc *crtc,
+					       struct drm_prop_enum_list *list)
+{
+	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
+	struct drm_device *dev = crtc->dev;
+	int ret;
+	int i = 0, j = 0;
+
+	memset(ops, 0, sizeof(ops));
+
+	/* 1st op: 1d curve */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_crtc_colorop_curve_1d_init(dev, ops[i], crtc, supported_tfs,
+					     DRM_COLOROP_FLAG_ALLOW_BYPASS);
+	if (ret)
+		goto err_colorop_init;
+
+	list->type = ops[i]->base.id;
+	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
+
+	i++;
+
+	/* 2nd op: 3x4 matrix */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_crtc_colorop_ctm_3x4_init(dev, ops[i], crtc, DRM_COLOROP_FLAG_ALLOW_BYPASS);
+	if (ret)
+		goto err_colorop_init;
+
+	drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+	i++;
+
+	/* 3rd op: 3x4 matrix */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_crtc_colorop_ctm_3x4_init(dev, ops[i], crtc, DRM_COLOROP_FLAG_ALLOW_BYPASS);
+	if (ret)
+		goto err_colorop_init;
+
+	drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+	i++;
+
+	/* 4th op: 1d curve */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_crtc_colorop_curve_1d_init(dev, ops[i], crtc, supported_tfs,
+					     DRM_COLOROP_FLAG_ALLOW_BYPASS);
+	if (ret)
+		goto err_colorop_init;
+
+	drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+	return 0;
+
+err_colorop_init:
+	kfree(ops[i]);
+
+cleanup:
+	for (j = 0; j < i; j++) {
+		drm_colorop_cleanup(ops[j]);
+		kfree(ops[j]);
+	}
+
+	return ret;
+}
+
 int vkms_initialize_plane_colorops(struct drm_plane *plane)
 {
 	struct drm_prop_enum_list pipeline;
@@ -119,3 +204,21 @@ int vkms_initialize_plane_colorops(struct drm_plane *plane)
 
 	return 0;
 }
+
+int vkms_initialize_crtc_colorops(struct drm_crtc *crtc)
+{
+	struct drm_prop_enum_list pipeline;
+	int ret;
+
+	/* Add color pipeline */
+	ret = vkms_initialize_crtc_color_pipeline(crtc, &pipeline);
+	if (ret)
+		return ret;
+
+	/* Create COLOR_PIPELINE property and attach */
+	ret = drm_crtc_create_color_pipeline_property(crtc, &pipeline, 1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index d4f87a2aa3359..621f008b165a6 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -495,7 +495,10 @@ static void blend(struct vkms_writeback_job *wb,
 			blend_line(plane[i], y, crtc_x_limit, stage_buffer, output_buffer);
 		}
 
-		apply_lut(crtc_state, output_buffer);
+		if (crtc_state->base.color_pipeline_enabled)
+			color_transform(crtc_state->base.color_pipeline, output_buffer);
+		else
+			apply_lut(crtc_state, output_buffer);
 
 		*crc32 = crc32_le(*crc32, (void *)output_buffer->pixels, row_size);
 
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 8788df9edb7ca..a65c3638eff4d 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -34,7 +34,8 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create);
 struct vkms_config *vkms_config_default_create(bool enable_cursor,
 					       bool enable_writeback,
 					       bool enable_overlay,
-					       bool enable_plane_pipeline)
+					       bool enable_plane_pipeline,
+					       bool enable_crtc_pipeline)
 {
 	struct vkms_config *config;
 	struct vkms_config_plane *plane_cfg;
@@ -56,6 +57,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
 	if (IS_ERR(crtc_cfg))
 		goto err_alloc;
 	vkms_config_crtc_set_writeback(crtc_cfg, enable_writeback);
+	vkms_config_crtc_set_default_pipeline(crtc_cfg, enable_crtc_pipeline);
 
 	if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg))
 		goto err_alloc;
@@ -454,6 +456,7 @@ struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *config)
 
 	crtc_cfg->config = config;
 	vkms_config_crtc_set_writeback(crtc_cfg, false);
+	vkms_config_crtc_set_default_pipeline(crtc_cfg, false);
 
 	list_add_tail(&crtc_cfg->link, &config->crtcs);
 
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 8f7f286a4bdd7..e12e4065f01f0 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -61,6 +61,7 @@ struct vkms_config_plane {
  * @link: Link to the others CRTCs in vkms_config
  * @config: The vkms_config this CRTC belongs to
  * @writeback: If true, a writeback buffer can be attached to the CRTC
+ * @default_pipeline: If true, CRTC will be created with the default pipeline.
  * @crtc: Internal usage. This pointer should never be considered as valid.
  *        It can be used to store a temporary reference to a VKMS CRTC during
  *        device creation. This pointer is not managed by the configuration and
@@ -71,6 +72,7 @@ struct vkms_config_crtc {
 	struct vkms_config *config;
 
 	bool writeback;
+	bool default_pipeline;
 
 	/* Internal usage */
 	struct vkms_output *crtc;
@@ -205,7 +207,8 @@ struct vkms_config *vkms_config_create(const char *dev_name);
 struct vkms_config *vkms_config_default_create(bool enable_cursor,
 					       bool enable_writeback,
 					       bool enable_overlay,
-					       bool enable_plane_pipeline);
+					       bool enable_plane_pipeline,
+					       bool enable_crtc_pipeline);
 
 /**
  * vkms_config_destroy() - Free a VKMS configuration
@@ -314,6 +317,30 @@ vkms_config_plane_set_default_pipeline(struct vkms_config_plane *plane_cfg,
 	plane_cfg->default_pipeline = default_pipeline;
 }
 
+/**
+ * vkms_config_crtc_get_default_pipeline() - Return if the CRTC will
+ * be created with the default pipeline
+ * @crtc_cfg: CRTC to get the information from
+ */
+static inline bool
+vkms_config_crtc_get_default_pipeline(struct vkms_config_crtc *crtc_cfg)
+{
+	return crtc_cfg->default_pipeline;
+}
+
+/**
+ * vkms_config_crtc_set_default_pipeline() - Set if the CRTC will
+ * be created with the default pipeline
+ * @crtc_cfg: CRTC to configure the pipeline
+ * @default_pipeline: New default pipeline value
+ */
+static inline void
+vkms_config_crtc_set_default_pipeline(struct vkms_config_crtc *crtc_cfg,
+				      bool default_pipeline)
+{
+	crtc_cfg->default_pipeline = default_pipeline;
+}
+
 /**
  * vkms_config_plane_attach_crtc - Attach a plane to a CRTC
  * @plane_cfg: Plane to attach
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 9a7db1d510222..60c372c0ce2d8 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -10,6 +10,7 @@
 #include <drm/drm_vblank.h>
 #include <drm/drm_vblank_helper.h>
 
+#include "vkms_config.h"
 #include "vkms_drv.h"
 
 static bool vkms_crtc_handle_vblank_timeout(struct drm_crtc *crtc)
@@ -202,7 +203,7 @@ static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = {
 };
 
 struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *primary,
-				   struct drm_plane *cursor)
+				   struct drm_plane *cursor, struct vkms_config_crtc *crtc_cfg)
 {
 	struct vkms_output *vkms_out;
 	struct drm_crtc *crtc;
@@ -228,6 +229,9 @@ struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *pri
 
 	drm_crtc_enable_color_mgmt(crtc, 0, false, VKMS_LUT_SIZE);
 
+	if (vkms_config_crtc_get_default_pipeline(crtc_cfg))
+		vkms_initialize_crtc_colorops(crtc);
+
 	spin_lock_init(&vkms_out->lock);
 	spin_lock_init(&vkms_out->composer_lock);
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index dd1402f437736..39195540fe2b1 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -55,6 +55,10 @@ static bool enable_plane_pipeline;
 module_param_named(enable_plane_pipeline, enable_plane_pipeline, bool, 0444);
 MODULE_PARM_DESC(enable_plane_pipeline, "Enable/Disable plane pipeline support");
 
+static bool enable_crtc_pipeline;
+module_param_named(enable_crtc_pipeline, enable_crtc_pipeline, bool, 0444);
+MODULE_PARM_DESC(enable_crtc_pipeline, "Enable/Disable CRTC pipeline support");
+
 static bool create_default_dev = true;
 module_param_named(create_default_dev, create_default_dev, bool, 0444);
 MODULE_PARM_DESC(create_default_dev, "Create or not the default VKMS device");
@@ -232,7 +236,8 @@ static int __init vkms_init(void)
 		return 0;
 
 	config = vkms_config_default_create(enable_cursor, enable_writeback,
-					    enable_overlay, enable_plane_pipeline);
+					    enable_overlay, enable_plane_pipeline,
+					    enable_crtc_pipeline);
 	if (IS_ERR(config))
 		return PTR_ERR(config);
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index bdeb52623f4d6..1688c885f2285 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -229,6 +229,7 @@ struct vkms_output {
 };
 
 struct vkms_config;
+struct vkms_config_crtc;
 struct vkms_config_plane;
 
 /**
@@ -287,10 +288,12 @@ void vkms_destroy(struct vkms_config *config);
  * @crtc: uninitialized CRTC device
  * @primary: primary plane to attach to the CRTC
  * @cursor: plane to attach to the CRTC
+ * @crtc_cfg: CRTC configuration
  */
 struct vkms_output *vkms_crtc_init(struct drm_device *dev,
 				   struct drm_plane *primary,
-				   struct drm_plane *cursor);
+				   struct drm_plane *cursor,
+				   struct vkms_config_crtc *crtc_cfg);
 
 /**
  * vkms_output_init() - Initialize all sub-components needed for a VKMS device.
@@ -325,5 +328,6 @@ int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_out
 
 /* Colorops */
 int vkms_initialize_plane_colorops(struct drm_plane *plane);
+int vkms_initialize_crtc_colorops(struct drm_crtc *crtc);
 
 #endif /* _VKMS_DRV_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 86ce07a617f52..a0856ba90ac24 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -34,7 +34,8 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 		cursor = vkms_config_crtc_cursor_plane(vkmsdev->config, crtc_cfg);
 
 		crtc_cfg->crtc = vkms_crtc_init(dev, &primary->plane->base,
-						cursor ? &cursor->plane->base : NULL);
+						cursor ? &cursor->plane->base : NULL,
+						crtc_cfg);
 		if (IS_ERR(crtc_cfg->crtc)) {
 			DRM_ERROR("Failed to allocate CRTC\n");
 			return PTR_ERR(crtc_cfg->crtc);

-- 
2.51.0



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

* [PATCH v3 21/21] drm/vkms: Set CRTC color pipeline driver cap
  2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
                   ` (19 preceding siblings ...)
  2025-12-23 18:01 ` [PATCH v3 20/21] drm/vkms: Introduce support for post-blend color pipeline Ariel D'Alessandro
@ 2025-12-23 18:01 ` Ariel D'Alessandro
  20 siblings, 0 replies; 25+ messages in thread
From: Ariel D'Alessandro @ 2025-12-23 18:01 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno, Louis Chauvet, Haneen Mohammed,
	Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado, Ariel D'Alessandro

From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>

Now that the driver implements CRTC (post-blend) color pipelines, set
the driver cap so they can be used from userspace.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/vkms/vkms_drv.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 39195540fe2b1..62cd36c805e45 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -94,7 +94,8 @@ static void vkms_atomic_commit_tail(struct drm_atomic_state *old_state)
 }
 
 static const struct drm_driver vkms_driver = {
-	.driver_features	= DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM,
+	.driver_features	= DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM |
+				  DRIVER_CRTC_COLOR_PIPELINE,
 	.fops			= &vkms_driver_fops,
 	DRM_GEM_SHMEM_DRIVER_OPS,
 	DRM_FBDEV_SHMEM_DRIVER_OPS,

-- 
2.51.0



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

* Re: [PATCH v3 09/21] drm/colorop: Factor out common paths from colorops helpers
  2025-12-23 18:01 ` [PATCH v3 09/21] drm/colorop: Factor out common paths from colorops helpers Ariel D'Alessandro
@ 2025-12-25  6:26   ` kernel test robot
  0 siblings, 0 replies; 25+ messages in thread
From: kernel test robot @ 2025-12-25  6:26 UTC (permalink / raw)
  To: Ariel D'Alessandro, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Chun-Kuang Hu,
	Philipp Zabel, Matthias Brugger, AngeloGioacchino Del Regno,
	Louis Chauvet, Haneen Mohammed, Melissa Wen
  Cc: oe-kbuild-all, dri-devel, linux-kernel, linux-mediatek,
	linux-arm-kernel, kernel, Nícolas F. R. A. Prado,
	Ariel D'Alessandro, Harry Wentland

Hi Ariel,

kernel test robot noticed the following build warnings:

[auto build test WARNING on b96bcfba104c65db41378a04f5ccac186f79578f]

url:    https://github.com/intel-lab-lkp/linux/commits/Ariel-D-Alessandro/drm-crtc-Add-color-pipeline-to-CRTC-state/20251224-020551
base:   b96bcfba104c65db41378a04f5ccac186f79578f
patch link:    https://lore.kernel.org/r/20251223-mtk-post-blend-color-pipeline-v3-9-7d969f9a37a0%40collabora.com
patch subject: [PATCH v3 09/21] drm/colorop: Factor out common paths from colorops helpers
config: openrisc-randconfig-r073-20251225 (https://download.01.org/0day-ci/archive/20251225/202512251442.dLlbaNp3-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 12.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251225/202512251442.dLlbaNp3-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512251442.dLlbaNp3-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Warning: drivers/gpu/drm/drm_colorop.c:227 expecting prototype for drm_plane_colorop_curve_1d_init(). Prototype was for drm_common_colorop_curve_1d_init() instead

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


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

* Re: [PATCH v3 06/21] drm: Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE
  2025-12-23 18:01 ` [PATCH v3 06/21] drm: Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE Ariel D'Alessandro
@ 2026-07-08  7:28   ` Robert Mader
  0 siblings, 0 replies; 25+ messages in thread
From: Robert Mader @ 2026-07-08  7:28 UTC (permalink / raw)
  To: Ariel D'Alessandro, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Chun-Kuang Hu,
	Philipp Zabel, Matthias Brugger, AngeloGioacchino Del Regno,
	Louis Chauvet, Haneen Mohammed, Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado

Hi, thanks for the series!

On 23.12.25 19:01, Ariel D'Alessandro wrote:
> From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>
>
> Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE which a DRM client can set
> to enable the usage of CRTC (post-blend) color pipelines instead of the
> now deprecated CRTC color management properties: "GAMMA_LUT",
> "DEGAMMA_LUT" and "CTM".
>
> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
> Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
> Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
>   drivers/gpu/drm/drm_atomic_uapi.c   | 20 ++++++++++++++++++++
>   drivers/gpu/drm/drm_connector.c     |  1 +
>   drivers/gpu/drm/drm_crtc_internal.h |  1 +
>   drivers/gpu/drm/drm_ioctl.c         |  9 +++++++++
>   drivers/gpu/drm/drm_mode_object.c   |  9 +++++++++
>   include/drm/drm_file.h              |  7 +++++++
>   include/uapi/drm/drm.h              | 19 +++++++++++++++++++
>   7 files changed, 66 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index 07d0d224fe58c..d1bc78b2567a9 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -433,6 +433,11 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
>   	if (property == config->prop_active)
>   		state->active = val;
>   	else if (property == crtc->color_pipeline_property) {
> +		if (!file_priv->crtc_color_pipeline) {
> +			drm_dbg_atomic(dev,
> +				"Setting COLOR_PIPELINE CRTC property not permitted without DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
> +			return -EINVAL;
> +		}
>   		/* find DRM colorop object */
>   		struct drm_colorop *colorop = NULL;
>   
> @@ -451,6 +456,11 @@ 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) {
> +		if (file_priv->crtc_color_pipeline) {
> +			drm_dbg_atomic(dev,
> +				"Setting DEGAMMA_LUT CRTC property not permitted with DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
> +			return -EINVAL;
> +		}
>   		ret = drm_property_replace_blob_from_id(dev,
>   					&state->degamma_lut,
>   					val,
> @@ -459,6 +469,11 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
>   		state->color_mgmt_changed |= replaced;
>   		return ret;
>   	} else if (property == config->ctm_property) {
> +		if (file_priv->crtc_color_pipeline) {
> +			drm_dbg_atomic(dev,
> +				"Setting CTM CRTC property not permitted with DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
> +			return -EINVAL;
> +		}
>   		ret = drm_property_replace_blob_from_id(dev,
>   					&state->ctm,
>   					val,
> @@ -467,6 +482,11 @@ 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) {
> +		if (file_priv->crtc_color_pipeline) {
> +			drm_dbg_atomic(dev,
> +				"Setting GAMMA_LUT CRTC property not permitted with DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE client cap\n");
> +			return -EINVAL;
> +		}
>   		ret = drm_property_replace_blob_from_id(dev,
>   					&state->gamma_lut,
>   					val,
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 4d6dc9ebfdb5b..aec8a5c0d593a 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -3440,6 +3440,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
>   	 */
>   	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
>   			file_priv->plane_color_pipeline,
> +			file_priv->crtc_color_pipeline,
>   			(uint32_t __user *)(unsigned long)(out_resp->props_ptr),
>   			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
>   			&out_resp->count_props);
> diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
> index c094092296448..ab02e6295271d 100644
> --- a/drivers/gpu/drm/drm_crtc_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_internal.h
> @@ -164,6 +164,7 @@ void drm_mode_object_unregister(struct drm_device *dev,
>   				struct drm_mode_object *object);
>   int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
>   				   bool plane_color_pipeline,
> +				   bool crtc_color_pipeline,
>   				   uint32_t __user *prop_ptr,
>   				   uint64_t __user *prop_values,
>   				   uint32_t *arg_count_props);
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index 2884075660ddd..14746afd82783 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -383,6 +383,15 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
>   			return -EINVAL;
>   		file_priv->plane_color_pipeline = req->value;
>   		break;
> +	case DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE:
> +		if (!file_priv->atomic)
> +			return -EINVAL;
> +		if (req->value > 1)
> +			return -EINVAL;
> +		if (!drm_core_check_feature(dev, DRIVER_CRTC_COLOR_PIPELINE))
> +			return -EINVAL;

For DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE we just solved the equivalent 
problem by checking if drivers actually expose pipelines (see 
https://lore.kernel.org/dri-devel/20260703073230.19982-1-robert.mader@collabora.com/ 
which just landed drm-misc-fixes and is marked for backporting). I 
initially went with the same approach of using a driver feature (see 
https://lore.kernel.org/dri-devel/20260630084229.529682-2-robert.mader@collabora.com/), 
however the explicit check turned out to be both sufficient and simpler. 
Using that approach would allow you to drop the patches 5, 17 and 21.

Regards

> +		file_priv->crtc_color_pipeline = req->value;
> +		break;
>   	default:
>   		return -EINVAL;
>   	}
> diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
> index b45d501b10c86..ea4508f6a09a6 100644
> --- a/drivers/gpu/drm/drm_mode_object.c
> +++ b/drivers/gpu/drm/drm_mode_object.c
> @@ -388,6 +388,7 @@ EXPORT_SYMBOL(drm_object_property_get_default_value);
>   /* helper for getconnector and getproperties ioctls */
>   int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
>   				   bool plane_color_pipeline,
> +				   bool crtc_color_pipeline,
>   				   uint32_t __user *prop_ptr,
>   				   uint64_t __user *prop_values,
>   				   uint32_t *arg_count_props)
> @@ -416,6 +417,13 @@ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
>   				continue;
>   		}
>   
> +		if (!crtc_color_pipeline && obj->type == DRM_MODE_OBJECT_CRTC) {
> +			struct drm_crtc *crtc = obj_to_crtc(obj);
> +
> +			if (prop == crtc->color_pipeline_property)
> +				continue;
> +		}
> +
>   		if (*arg_count_props > count) {
>   			ret = __drm_object_property_get_value(obj, prop, &val);
>   			if (ret)
> @@ -475,6 +483,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
>   
>   	ret = drm_mode_object_get_properties(obj, file_priv->atomic,
>   			file_priv->plane_color_pipeline,
> +			file_priv->crtc_color_pipeline,
>   			(uint32_t __user *)(unsigned long)(arg->props_ptr),
>   			(uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
>   			&arg->count_props);
> diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
> index 6ee70ad65e1fd..d0c323378ae46 100644
> --- a/include/drm/drm_file.h
> +++ b/include/drm/drm_file.h
> @@ -214,6 +214,13 @@ struct drm_file {
>   	 */
>   	bool plane_color_pipeline;
>   
> +	/**
> +	 * @crtc_color_pipeline:
> +	 *
> +	 * True if client understands CRTC (post-blend) color pipelines
> +	 */
> +	bool crtc_color_pipeline;
> +
>   	/**
>   	 * @was_master:
>   	 *
> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> index d726828bdf408..991ef14c5377c 100644
> --- a/include/uapi/drm/drm.h
> +++ b/include/uapi/drm/drm.h
> @@ -927,6 +927,25 @@ struct drm_get_cap {
>    */
>   #define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE	7
>   
> +/**
> + * DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE
> + *
> + * If set to 1 the DRM core will allow setting the COLOR_PIPELINE
> + * property on a &drm_crtc, as well as drm_colorop properties.
> + *
> + * Setting of these crtc properties will be rejected when this client
> + * cap is set:
> + * - GAMMA_LUT
> + * - DEGAMMA_LUT
> + * - CTM
> + *
> + * The client must enable &DRM_CLIENT_CAP_ATOMIC first.
> + *
> + * This client cap can only be set if the driver sets the corresponding driver
> + * cap &DRM_CAP_CRTC_COLOR_PIPELINE.
> + */
> +#define DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE	8
> +
>   /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
>   struct drm_set_client_cap {
>   	__u64 capability;
>
-- 
Robert Mader
Consultant Software Developer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK
Registered in England & Wales, no. 5513718



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

* Re: [PATCH v3 20/21] drm/vkms: Introduce support for post-blend color pipeline
  2025-12-23 18:01 ` [PATCH v3 20/21] drm/vkms: Introduce support for post-blend color pipeline Ariel D'Alessandro
@ 2026-07-08 17:35   ` Robert Mader
  0 siblings, 0 replies; 25+ messages in thread
From: Robert Mader @ 2026-07-08 17:35 UTC (permalink / raw)
  To: Ariel D'Alessandro, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Chun-Kuang Hu,
	Philipp Zabel, Matthias Brugger, AngeloGioacchino Del Regno,
	Louis Chauvet, Haneen Mohammed, Melissa Wen
  Cc: dri-devel, linux-kernel, linux-mediatek, linux-arm-kernel, kernel,
	Nícolas F. R. A. Prado

Hi,

On 23.12.25 19:01, Ariel D'Alessandro wrote:
> From: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>
>
> Introduce a post-blend color pipeline with the same colorop blocks as
> the pre-blend color pipeline.
>
> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
> Co-developed-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
> Signed-off-by: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
> ---
>   drivers/gpu/drm/vkms/tests/vkms_config_test.c |  70 ++++++++++-------
>   drivers/gpu/drm/vkms/vkms_colorop.c           | 103 ++++++++++++++++++++++++++
>   drivers/gpu/drm/vkms/vkms_composer.c          |   5 +-
>   drivers/gpu/drm/vkms/vkms_config.c            |   5 +-
>   drivers/gpu/drm/vkms/vkms_config.h            |  29 +++++++-
>   drivers/gpu/drm/vkms/vkms_crtc.c              |   6 +-
>   drivers/gpu/drm/vkms/vkms_drv.c               |   7 +-
>   drivers/gpu/drm/vkms/vkms_drv.h               |   6 +-
>   drivers/gpu/drm/vkms/vkms_output.c            |   3 +-
>   9 files changed, 202 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index 1e4ea1863420f..ec1d84ae508ad 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -84,6 +84,7 @@ struct default_config_case {
>   	bool enable_writeback;
>   	bool enable_overlay;
>   	bool enable_plane_pipeline;
> +	bool enable_crtc_pipeline;
>   };
>   
>   static void vkms_config_test_empty_config(struct kunit *test)
> @@ -109,22 +110,38 @@ static void vkms_config_test_empty_config(struct kunit *test)
>   }
>   
>   static struct default_config_case default_config_cases[] = {
> -	{ false, false, false, false },
> -	{ true, false, false, false },
> -	{ true, true, false, false },
> -	{ true, false, true, false },
> -	{ false, true, false, false },
> -	{ false, true, true, false },
> -	{ false, false, true, false },
> -	{ true, true, true, false },
> -	{ false, false, false, true },
> -	{ true, false, false, true },
> -	{ true, true, false, true },
> -	{ true, false, true, true },
> -	{ false, true, false, true },
> -	{ false, true, true, true },
> -	{ false, false, true, true },
> -	{ true, true, true, true },
> +	{ false, false, false, false, false },
> +	{ true, false, false, false, false },
> +	{ true, true, false, false, false },
> +	{ true, false, true, false, false },
> +	{ false, true, false, false, false },
> +	{ false, true, true, false, false },
> +	{ false, false, true, false, false },
> +	{ true, true, true, false, false },
> +	{ false, false, false, true, false },
> +	{ true, false, false, true, false },
> +	{ true, true, false, true, false },
> +	{ true, false, true, true, false },
> +	{ false, true, false, true, false },
> +	{ false, true, true, true, false },
> +	{ false, false, true, true, false },
> +	{ true, true, true, true, false },
> +	{ false, false, false, false, true },
> +	{ true, false, false, false, true },
> +	{ true, true, false, false, true },
> +	{ true, false, true, false, true },
> +	{ false, true, false, false, true },
> +	{ false, true, true, false, true },
> +	{ false, false, true, false, true },
> +	{ true, true, true, false, true },
> +	{ false, false, false, true, true },
> +	{ true, false, false, true, true },
> +	{ true, true, false, true, true },
> +	{ true, false, true, true, true },
> +	{ false, true, false, true, true },
> +	{ false, true, true, true, true },
> +	{ false, false, true, true, true },
> +	{ true, true, true, true, true },
>   };
>   
>   KUNIT_ARRAY_PARAM(default_config, default_config_cases, NULL);
> @@ -142,7 +159,8 @@ static void vkms_config_test_default_config(struct kunit *test)
>   	config = vkms_config_default_create(params->enable_cursor,
>   					    params->enable_writeback,
>   					    params->enable_overlay,
> -					    params->enable_plane_pipeline);
> +					    params->enable_plane_pipeline,
> +					    params->enable_crtc_pipeline);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	/* Planes */
> @@ -174,6 +192,8 @@ static void vkms_config_test_default_config(struct kunit *test)
>   	crtc_cfg = get_first_crtc(config);
>   	KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_writeback(crtc_cfg),
>   			params->enable_writeback);
> +	KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_default_pipeline(crtc_cfg),
> +			params->enable_crtc_pipeline);
>   
>   	vkms_config_for_each_plane(config, plane_cfg) {
>   		struct vkms_config_crtc *possible_crtc;
> @@ -381,7 +401,7 @@ static void vkms_config_test_invalid_plane_number(struct kunit *test)
>   	struct vkms_config_plane *plane_cfg;
>   	int n;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	/* Invalid: No planes */
> @@ -406,7 +426,7 @@ static void vkms_config_test_valid_plane_type(struct kunit *test)
>   	struct vkms_config_encoder *encoder_cfg;
>   	int err;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	plane_cfg = get_first_plane(config);
> @@ -487,7 +507,7 @@ static void vkms_config_test_valid_plane_possible_crtcs(struct kunit *test)
>   	struct vkms_config_plane *plane_cfg;
>   	struct vkms_config_crtc *crtc_cfg;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	plane_cfg = get_first_plane(config);
> @@ -506,7 +526,7 @@ static void vkms_config_test_invalid_crtc_number(struct kunit *test)
>   	struct vkms_config_crtc *crtc_cfg;
>   	int n;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	/* Invalid: No CRTCs */
> @@ -529,7 +549,7 @@ static void vkms_config_test_invalid_encoder_number(struct kunit *test)
>   	struct vkms_config_encoder *encoder_cfg;
>   	int n;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	/* Invalid: No encoders */
> @@ -554,7 +574,7 @@ static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *test)
>   	struct vkms_config_encoder *encoder_cfg;
>   	int err;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	crtc_cfg1 = get_first_crtc(config);
> @@ -600,7 +620,7 @@ static void vkms_config_test_invalid_connector_number(struct kunit *test)
>   	struct vkms_config_connector *connector_cfg;
>   	int n;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	/* Invalid: No connectors */
> @@ -623,7 +643,7 @@ static void vkms_config_test_valid_connector_possible_encoders(struct kunit *tes
>   	struct vkms_config_encoder *encoder_cfg;
>   	struct vkms_config_connector *connector_cfg;
>   
> -	config = vkms_config_default_create(false, false, false, false);
> +	config = vkms_config_default_create(false, false, false, false, false);
>   	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
>   
>   	encoder_cfg = get_first_encoder(config);
> diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
> index dd6120434690e..6c4a6cb186564 100644
> --- a/drivers/gpu/drm/vkms/vkms_colorop.c
> +++ b/drivers/gpu/drm/vkms/vkms_colorop.c
> @@ -102,6 +102,91 @@ static int vkms_initialize_plane_color_pipeline(struct drm_plane *plane,
>   	return ret;
>   }
>   
> +static int vkms_initialize_crtc_color_pipeline(struct drm_crtc *crtc,
> +					       struct drm_prop_enum_list *list)
> +{
> +	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
> +	struct drm_device *dev = crtc->dev;
> +	int ret;
> +	int i = 0, j = 0;
> +
> +	memset(ops, 0, sizeof(ops));
> +
> +	/* 1st op: 1d curve */
> +	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
> +	if (!ops[i]) {
> +		ret = -ENOMEM;
> +		goto cleanup;
> +	}
> +
> +	ret = drm_crtc_colorop_curve_1d_init(dev, ops[i], crtc, supported_tfs,
> +					     DRM_COLOROP_FLAG_ALLOW_BYPASS);
> +	if (ret)
> +		goto err_colorop_init;
> +
> +	list->type = ops[i]->base.id;
> +	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
> +
> +	i++;
> +
> +	/* 2nd op: 3x4 matrix */
> +	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
> +	if (!ops[i]) {
> +		ret = -ENOMEM;
> +		goto cleanup;
> +	}
> +
> +	ret = drm_crtc_colorop_ctm_3x4_init(dev, ops[i], crtc, DRM_COLOROP_FLAG_ALLOW_BYPASS);
> +	if (ret)
> +		goto err_colorop_init;
> +
> +	drm_colorop_set_next_property(ops[i - 1], ops[i]);
> +
> +	i++;
> +
> +	/* 3rd op: 3x4 matrix */
> +	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
> +	if (!ops[i]) {
> +		ret = -ENOMEM;
> +		goto cleanup;
> +	}
> +
> +	ret = drm_crtc_colorop_ctm_3x4_init(dev, ops[i], crtc, DRM_COLOROP_FLAG_ALLOW_BYPASS);
> +	if (ret)
> +		goto err_colorop_init;
> +
> +	drm_colorop_set_next_property(ops[i - 1], ops[i]);
> +
> +	i++;
> +
> +	/* 4th op: 1d curve */
> +	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
> +	if (!ops[i]) {
> +		ret = -ENOMEM;
> +		goto cleanup;
> +	}
> +
> +	ret = drm_crtc_colorop_curve_1d_init(dev, ops[i], crtc, supported_tfs,
> +					     DRM_COLOROP_FLAG_ALLOW_BYPASS);
> +	if (ret)
> +		goto err_colorop_init;
> +
> +	drm_colorop_set_next_property(ops[i - 1], ops[i]);
> +
> +	return 0;
> +
> +err_colorop_init:
> +	kfree(ops[i]);
> +
> +cleanup:
> +	for (j = 0; j < i; j++) {
> +		drm_colorop_cleanup(ops[j]);
> +		kfree(ops[j]);
> +	}
> +
> +	return ret;
> +}
> +
>   int vkms_initialize_plane_colorops(struct drm_plane *plane)
>   {
>   	struct drm_prop_enum_list pipeline;
> @@ -119,3 +204,21 @@ int vkms_initialize_plane_colorops(struct drm_plane *plane)
>   
>   	return 0;
>   }
> +
> +int vkms_initialize_crtc_colorops(struct drm_crtc *crtc)
> +{
> +	struct drm_prop_enum_list pipeline;
> +	int ret;
> +
> +	/* Add color pipeline */
> +	ret = vkms_initialize_crtc_color_pipeline(crtc, &pipeline);
> +	if (ret)
> +		return ret;
> +
> +	/* Create COLOR_PIPELINE property and attach */
> +	ret = drm_crtc_create_color_pipeline_property(crtc, &pipeline, 1);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
> index d4f87a2aa3359..621f008b165a6 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -495,7 +495,10 @@ static void blend(struct vkms_writeback_job *wb,
>   			blend_line(plane[i], y, crtc_x_limit, stage_buffer, output_buffer);
>   		}
>   
> -		apply_lut(crtc_state, output_buffer);
> +		if (crtc_state->base.color_pipeline_enabled)

AFAICS you could just use crtc_state->base.state->plane_color_pipeline 
here - that should allow you to drop "[PATCH v3 11/21] drm/crtc: Track 
crtc color pipeline client cap in drm_crtc_state"

Regards

> +			color_transform(crtc_state->base.color_pipeline, output_buffer);
> +		else
> +			apply_lut(crtc_state, output_buffer);
>   
>   		*crc32 = crc32_le(*crc32, (void *)output_buffer->pixels, row_size);
>   
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index 8788df9edb7ca..a65c3638eff4d 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -34,7 +34,8 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create);
>   struct vkms_config *vkms_config_default_create(bool enable_cursor,
>   					       bool enable_writeback,
>   					       bool enable_overlay,
> -					       bool enable_plane_pipeline)
> +					       bool enable_plane_pipeline,
> +					       bool enable_crtc_pipeline)
>   {
>   	struct vkms_config *config;
>   	struct vkms_config_plane *plane_cfg;
> @@ -56,6 +57,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
>   	if (IS_ERR(crtc_cfg))
>   		goto err_alloc;
>   	vkms_config_crtc_set_writeback(crtc_cfg, enable_writeback);
> +	vkms_config_crtc_set_default_pipeline(crtc_cfg, enable_crtc_pipeline);
>   
>   	if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg))
>   		goto err_alloc;
> @@ -454,6 +456,7 @@ struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *config)
>   
>   	crtc_cfg->config = config;
>   	vkms_config_crtc_set_writeback(crtc_cfg, false);
> +	vkms_config_crtc_set_default_pipeline(crtc_cfg, false);
>   
>   	list_add_tail(&crtc_cfg->link, &config->crtcs);
>   
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 8f7f286a4bdd7..e12e4065f01f0 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -61,6 +61,7 @@ struct vkms_config_plane {
>    * @link: Link to the others CRTCs in vkms_config
>    * @config: The vkms_config this CRTC belongs to
>    * @writeback: If true, a writeback buffer can be attached to the CRTC
> + * @default_pipeline: If true, CRTC will be created with the default pipeline.
>    * @crtc: Internal usage. This pointer should never be considered as valid.
>    *        It can be used to store a temporary reference to a VKMS CRTC during
>    *        device creation. This pointer is not managed by the configuration and
> @@ -71,6 +72,7 @@ struct vkms_config_crtc {
>   	struct vkms_config *config;
>   
>   	bool writeback;
> +	bool default_pipeline;
>   
>   	/* Internal usage */
>   	struct vkms_output *crtc;
> @@ -205,7 +207,8 @@ struct vkms_config *vkms_config_create(const char *dev_name);
>   struct vkms_config *vkms_config_default_create(bool enable_cursor,
>   					       bool enable_writeback,
>   					       bool enable_overlay,
> -					       bool enable_plane_pipeline);
> +					       bool enable_plane_pipeline,
> +					       bool enable_crtc_pipeline);
>   
>   /**
>    * vkms_config_destroy() - Free a VKMS configuration
> @@ -314,6 +317,30 @@ vkms_config_plane_set_default_pipeline(struct vkms_config_plane *plane_cfg,
>   	plane_cfg->default_pipeline = default_pipeline;
>   }
>   
> +/**
> + * vkms_config_crtc_get_default_pipeline() - Return if the CRTC will
> + * be created with the default pipeline
> + * @crtc_cfg: CRTC to get the information from
> + */
> +static inline bool
> +vkms_config_crtc_get_default_pipeline(struct vkms_config_crtc *crtc_cfg)
> +{
> +	return crtc_cfg->default_pipeline;
> +}
> +
> +/**
> + * vkms_config_crtc_set_default_pipeline() - Set if the CRTC will
> + * be created with the default pipeline
> + * @crtc_cfg: CRTC to configure the pipeline
> + * @default_pipeline: New default pipeline value
> + */
> +static inline void
> +vkms_config_crtc_set_default_pipeline(struct vkms_config_crtc *crtc_cfg,
> +				      bool default_pipeline)
> +{
> +	crtc_cfg->default_pipeline = default_pipeline;
> +}
> +
>   /**
>    * vkms_config_plane_attach_crtc - Attach a plane to a CRTC
>    * @plane_cfg: Plane to attach
> diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
> index 9a7db1d510222..60c372c0ce2d8 100644
> --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> @@ -10,6 +10,7 @@
>   #include <drm/drm_vblank.h>
>   #include <drm/drm_vblank_helper.h>
>   
> +#include "vkms_config.h"
>   #include "vkms_drv.h"
>   
>   static bool vkms_crtc_handle_vblank_timeout(struct drm_crtc *crtc)
> @@ -202,7 +203,7 @@ static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = {
>   };
>   
>   struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *primary,
> -				   struct drm_plane *cursor)
> +				   struct drm_plane *cursor, struct vkms_config_crtc *crtc_cfg)
>   {
>   	struct vkms_output *vkms_out;
>   	struct drm_crtc *crtc;
> @@ -228,6 +229,9 @@ struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *pri
>   
>   	drm_crtc_enable_color_mgmt(crtc, 0, false, VKMS_LUT_SIZE);
>   
> +	if (vkms_config_crtc_get_default_pipeline(crtc_cfg))
> +		vkms_initialize_crtc_colorops(crtc);
> +
>   	spin_lock_init(&vkms_out->lock);
>   	spin_lock_init(&vkms_out->composer_lock);
>   
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
> index dd1402f437736..39195540fe2b1 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.c
> +++ b/drivers/gpu/drm/vkms/vkms_drv.c
> @@ -55,6 +55,10 @@ static bool enable_plane_pipeline;
>   module_param_named(enable_plane_pipeline, enable_plane_pipeline, bool, 0444);
>   MODULE_PARM_DESC(enable_plane_pipeline, "Enable/Disable plane pipeline support");
>   
> +static bool enable_crtc_pipeline;
> +module_param_named(enable_crtc_pipeline, enable_crtc_pipeline, bool, 0444);
> +MODULE_PARM_DESC(enable_crtc_pipeline, "Enable/Disable CRTC pipeline support");
> +
>   static bool create_default_dev = true;
>   module_param_named(create_default_dev, create_default_dev, bool, 0444);
>   MODULE_PARM_DESC(create_default_dev, "Create or not the default VKMS device");
> @@ -232,7 +236,8 @@ static int __init vkms_init(void)
>   		return 0;
>   
>   	config = vkms_config_default_create(enable_cursor, enable_writeback,
> -					    enable_overlay, enable_plane_pipeline);
> +					    enable_overlay, enable_plane_pipeline,
> +					    enable_crtc_pipeline);
>   	if (IS_ERR(config))
>   		return PTR_ERR(config);
>   
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index bdeb52623f4d6..1688c885f2285 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -229,6 +229,7 @@ struct vkms_output {
>   };
>   
>   struct vkms_config;
> +struct vkms_config_crtc;
>   struct vkms_config_plane;
>   
>   /**
> @@ -287,10 +288,12 @@ void vkms_destroy(struct vkms_config *config);
>    * @crtc: uninitialized CRTC device
>    * @primary: primary plane to attach to the CRTC
>    * @cursor: plane to attach to the CRTC
> + * @crtc_cfg: CRTC configuration
>    */
>   struct vkms_output *vkms_crtc_init(struct drm_device *dev,
>   				   struct drm_plane *primary,
> -				   struct drm_plane *cursor);
> +				   struct drm_plane *cursor,
> +				   struct vkms_config_crtc *crtc_cfg);
>   
>   /**
>    * vkms_output_init() - Initialize all sub-components needed for a VKMS device.
> @@ -325,5 +328,6 @@ int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_out
>   
>   /* Colorops */
>   int vkms_initialize_plane_colorops(struct drm_plane *plane);
> +int vkms_initialize_crtc_colorops(struct drm_crtc *crtc);
>   
>   #endif /* _VKMS_DRV_H_ */
> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
> index 86ce07a617f52..a0856ba90ac24 100644
> --- a/drivers/gpu/drm/vkms/vkms_output.c
> +++ b/drivers/gpu/drm/vkms/vkms_output.c
> @@ -34,7 +34,8 @@ int vkms_output_init(struct vkms_device *vkmsdev)
>   		cursor = vkms_config_crtc_cursor_plane(vkmsdev->config, crtc_cfg);
>   
>   		crtc_cfg->crtc = vkms_crtc_init(dev, &primary->plane->base,
> -						cursor ? &cursor->plane->base : NULL);
> +						cursor ? &cursor->plane->base : NULL,
> +						crtc_cfg);
>   		if (IS_ERR(crtc_cfg->crtc)) {
>   			DRM_ERROR("Failed to allocate CRTC\n");
>   			return PTR_ERR(crtc_cfg->crtc);
>
-- 
Robert Mader
Consultant Software Developer

Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK
Registered in England & Wales, no. 5513718



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

end of thread, other threads:[~2026-07-08 17:35 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-23 18:01 [PATCH v3 00/21] Introduce support for CRTC (post-blend) color pipeline Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 01/21] drm/crtc: Add color pipeline to CRTC state Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 02/21] drm/colorop: Allow parenting colorop to CRTC Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 03/21] drm: Factor out common color_pipeline property initialization code Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 04/21] drm/crtc: Add COLOR_PIPELINE property Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 05/21] drm: Introduce DRM_CAP_CRTC_COLOR_PIPELINE Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 06/21] drm: Introduce DRM_CLIENT_CAP_CRTC_COLOR_PIPELINE Ariel D'Alessandro
2026-07-08  7:28   ` Robert Mader
2025-12-23 18:01 ` [PATCH v3 07/21] drm/atomic: Pass crtc_color_pipeline client cap to atomic check Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 08/21] drm/atomic: Print the color pipeline as part of the CRTC state print Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 09/21] drm/colorop: Factor out common paths from colorops helpers Ariel D'Alessandro
2025-12-25  6:26   ` kernel test robot
2025-12-23 18:01 ` [PATCH v3 10/21] drm/colorop: Introduce colorop helpers for crtc Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 11/21] drm/crtc: Track crtc color pipeline client cap in drm_crtc_state Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 12/21] drm/mediatek: Support CRTC colorops for gamma and ctm Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 13/21] drm: Add helper to extract a 3x4 matrix from any CTM matrix dimensions Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 14/21] drm/mediatek: ccorr: Support CRTC color pipeline API Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 15/21] drm: Add helper to extract a LUT entry from either 16-bit or 32-bit LUT Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 16/21] drm/mediatek: gamma: Support CRTC color pipeline API Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 17/21] drm/mediatek: Set CRTC color pipeline driver cap Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 18/21] drm/vkms: Rename existing color pipeline helpers to contain "plane" Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 19/21] drm/vkms: Prepare pre_blend_color_transform() for CRTC color pipelines Ariel D'Alessandro
2025-12-23 18:01 ` [PATCH v3 20/21] drm/vkms: Introduce support for post-blend color pipeline Ariel D'Alessandro
2026-07-08 17:35   ` Robert Mader
2025-12-23 18:01 ` [PATCH v3 21/21] drm/vkms: Set CRTC color pipeline driver cap Ariel D'Alessandro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox