]> Gentwo Git Trees - linux/.git/commitdiff
drm/plane: Add COLOR PIPELINE property
authorHarry Wentland <harry.wentland@amd.com>
Sat, 15 Nov 2025 00:01:35 +0000 (17:01 -0700)
committerSimon Ser <contact@emersion.fr>
Wed, 26 Nov 2025 22:03:32 +0000 (23:03 +0100)
We're adding a new enum COLOR PIPELINE property. This
property will have entries for each COLOR PIPELINE by
referencing the DRM object ID of the first drm_colorop
of the pipeline. 0 disables the entire COLOR PIPELINE.

Userspace can use this to discover the available color
pipelines, as well as set the desired one. The color
pipelines are programmed via properties on the actual
drm_colorop objects.

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Melissa Wen <mwen@igalia.com>
Reviewed-by: Sebastian Wick <sebastian.wick@redhat.com>
Signed-off-by: Simon Ser <contact@emersion.fr>
Link: https://patch.msgid.link/20251115000237.3561250-11-alex.hung@amd.com
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_state_helper.c
drivers/gpu/drm/drm_atomic_uapi.c
drivers/gpu/drm/drm_plane.c
include/drm/drm_atomic.h
include/drm/drm_atomic_uapi.h
include/drm/drm_plane.h

index b996fa1c27b81235f67888bc01b745fce4a2701e..95111f9a8635ec000a2594b187dce499a12698f9 100644 (file)
@@ -1536,6 +1536,52 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_add_affected_planes);
 
+/**
+ * drm_atomic_add_affected_colorops - add colorops for plane
+ * @state: atomic state
+ * @plane: DRM plane
+ *
+ * This function walks the current configuration and adds all colorops
+ * currently used by @plane to the atomic configuration @state. This is useful
+ * when an atomic commit also needs to check all currently enabled colorop on
+ * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane
+ * to avoid special code to force-enable all colorops.
+ *
+ * Since acquiring a colorop state will always also acquire the w/w mutex of the
+ * current plane for that colorop (if there is any) adding all the colorop states for
+ * a plane will not reduce parallelism of atomic updates.
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_add_affected_colorops(struct drm_atomic_state *state,
+                                struct drm_plane *plane)
+{
+       struct drm_colorop *colorop;
+       struct drm_colorop_state *colorop_state;
+
+       WARN_ON(!drm_atomic_get_new_plane_state(state, plane));
+
+       drm_dbg_atomic(plane->dev,
+                      "Adding all current colorops for [PLANE:%d:%s] to %p\n",
+                      plane->base.id, plane->name, state);
+
+       drm_for_each_colorop(colorop, plane->dev) {
+               if (colorop->plane != plane)
+                       continue;
+
+               colorop_state = drm_atomic_get_colorop_state(state, colorop);
+               if (IS_ERR(colorop_state))
+                       return PTR_ERR(colorop_state);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_atomic_add_affected_colorops);
+
 /**
  * drm_atomic_check_only - check whether a given config would work
  * @state: atomic configuration to check
index 7142e163e618ea0d7d9d828e1bd9ff2a6ec0dfeb..cee6d8fc44adda6895542d33157d965a2d3c815f 100644 (file)
@@ -268,6 +268,11 @@ void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state,
                        plane_state->color_range = val;
        }
 
+       if (plane->color_pipeline_property) {
+               /* default is always NULL, i.e., bypass */
+               plane_state->color_pipeline = NULL;
+       }
+
        if (plane->zpos_property) {
                if (!drm_object_property_get_default_value(&plane->base,
                                                           plane->zpos_property,
index 25a898090fd9a1521448216c9307328392088557..608b0b571c2e8c6460d1ee90a2b82e2186acb73e 100644 (file)
@@ -258,6 +258,34 @@ drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
 }
 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
 
+/**
+ * drm_atomic_set_colorop_for_plane - set colorop for plane
+ * @plane_state: atomic state object for the plane
+ * @colorop: colorop to use for the plane
+ *
+ * Helper function to select the color pipeline on a plane by setting
+ * it to the first drm_colorop element of the pipeline.
+ */
+void
+drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
+                                struct drm_colorop *colorop)
+{
+       struct drm_plane *plane = plane_state->plane;
+
+       if (colorop)
+               drm_dbg_atomic(plane->dev,
+                              "Set [COLOROP:%d] for [PLANE:%d:%s] state %p\n",
+                              colorop->base.id, plane->base.id, plane->name,
+                              plane_state);
+       else
+               drm_dbg_atomic(plane->dev,
+                              "Set [NOCOLOROP] for [PLANE:%d:%s] state %p\n",
+                              plane->base.id, plane->name, plane_state);
+
+       plane_state->color_pipeline = colorop;
+}
+EXPORT_SYMBOL(drm_atomic_set_colorop_for_plane);
+
 /**
  * drm_atomic_set_crtc_for_connector - set CRTC for connector
  * @conn_state: atomic state object for the connector
@@ -545,6 +573,16 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
                state->color_encoding = val;
        } else if (property == plane->color_range_property) {
                state->color_range = val;
+       } else if (property == plane->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_plane(state, colorop);
        } else if (property == config->prop_fb_damage_clips) {
                ret = drm_property_replace_blob_from_id(dev,
                                        &state->fb_damage_clips,
@@ -627,6 +665,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
                *val = state->color_encoding;
        } else if (property == plane->color_range_property) {
                *val = state->color_range;
+       } else if (property == plane->color_pipeline_property) {
+               *val = (state->color_pipeline) ? state->color_pipeline->base.id : 0;
        } else if (property == config->prop_fb_damage_clips) {
                *val = (state->fb_damage_clips) ?
                        state->fb_damage_clips->base.id : 0;
index 38f82391bfda578d532499585066dd85ff573910..f6cfa8ac090c7bc49c7f276993bba7e9800da140 100644 (file)
@@ -1820,3 +1820,62 @@ int drm_plane_add_size_hints_property(struct drm_plane *plane,
        return 0;
 }
 EXPORT_SYMBOL(drm_plane_add_size_hints_property);
+
+/**
+ * drm_plane_create_color_pipeline_property - create a new color pipeline
+ * property
+ *
+ * @plane: drm plane
+ * @pipelines: list of pipelines
+ * @num_pipelines: number of pipelines
+ *
+ * Create the COLOR_PIPELINE plane property to specific color pipelines on
+ * the plane.
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+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_enum(plane->dev, DRM_MODE_PROP_ATOMIC,
+                                       "COLOR_PIPELINE",
+                                       all_pipelines, len);
+       if (IS_ERR(prop)) {
+               kfree(all_pipelines);
+               return PTR_ERR(prop);
+       }
+
+       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);
index 895529337d7e956e38147950f125d1399679bdaa..faeb5de74d50ca212e277c541a6063177640797b 100644 (file)
@@ -906,6 +906,9 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
 int __must_check
 drm_atomic_add_affected_planes(struct drm_atomic_state *state,
                               struct drm_crtc *crtc);
+int __must_check
+drm_atomic_add_affected_colorops(struct drm_atomic_state *state,
+                                struct drm_plane *plane);
 
 int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
 int __must_check drm_atomic_commit(struct drm_atomic_state *state);
index 70a115d523cdf9169bb013073f3ab63a90f217fd..4363155233267b93767c895fa6085544e2277442 100644 (file)
@@ -50,6 +50,8 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
                              struct drm_crtc *crtc);
 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);
 int __must_check
 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
                                  struct drm_crtc *crtc);
index 61fedd4e253ca584953a9bcb1aa2c3b5d0e16363..703ef4d1bbbcf084c43aa5e127d28691878061c4 100644 (file)
@@ -791,6 +791,14 @@ struct drm_plane {
         */
        struct drm_property *color_range_property;
 
+       /**
+        * @color_pipeline_property:
+        *
+        * Optional "COLOR_PIPELINE" enum property for specifying
+        * a color pipeline to use on the plane.
+        */
+       struct drm_property *color_pipeline_property;
+
        /**
         * @scaling_filter_property: property to apply a particular filter while
         * scaling.
@@ -1014,4 +1022,7 @@ int drm_plane_add_size_hints_property(struct drm_plane *plane,
                                      const struct drm_plane_size_hint *hints,
                                      int num_hints);
 
+int drm_plane_create_color_pipeline_property(struct drm_plane *plane,
+                                            const struct drm_prop_enum_list *pipelines,
+                                            int num_pipelines);
 #endif