On Fri Aug 15, 2025 at 5:49 AM CEST, Alex Hung wrote: > From: Harry Wentland <harry.wentl...@amd.com> > > Add a new drm_colorop with DRM_COLOROP_1D_CURVE with two subtypes: > DRM_COLOROP_1D_CURVE_SRGB_EOTF and DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF. > > Reviewed-by: Simon Ser <cont...@emersion.fr> > Reviewed-by: Louis Chauvet <louis.chau...@bootlin.com> > Signed-off-by: Harry Wentland <harry.wentl...@amd.com> > Co-developed-by: Alex Hung <alex.h...@amd.com> > Signed-off-by: Alex Hung <alex.h...@amd.com> > Reviewed-by: Daniel Stone <dani...@collabora.com> > Reviewed-by: Melissa Wen <m...@igalia.com> > --- > V9: Specify function names by _plane_ (Chaitanya Kumar Borah) > > v5: > - Add drm_get_colorop_curve_1d_type_name in header > - Add drm_colorop_init > - Set default curve > - Add kernel docs > > v4: > - Use drm_colorop_curve_1d_type_enum_list to get name (Pekka) > - Create separate init function for 1D curve > - Pass supported TFs into 1D curve init function > > drivers/gpu/drm/drm_atomic_uapi.c | 18 ++-- > drivers/gpu/drm/drm_colorop.c | 134 ++++++++++++++++++++++++++++++ > include/drm/drm_colorop.h | 63 ++++++++++++++ > 3 files changed, 210 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c > b/drivers/gpu/drm/drm_atomic_uapi.c > index ad2043f16268..52b5a9b5523e 100644 > --- a/drivers/gpu/drm/drm_atomic_uapi.c > +++ b/drivers/gpu/drm/drm_atomic_uapi.c > @@ -650,11 +650,17 @@ static int drm_atomic_colorop_set_property(struct > drm_colorop *colorop, > struct drm_colorop_state *state, struct drm_file *file_priv, > struct drm_property *property, uint64_t val) > { > - drm_dbg_atomic(colorop->dev, > - "[COLOROP:%d] unknown property [PROP:%d:%s]]\n", > - colorop->base.id, > - property->base.id, property->name); > - return -EINVAL; > + if (property == colorop->curve_1d_type_property) { > + state->curve_1d_type = val; > + } else { > + drm_dbg_atomic(colorop->dev, > + "[COLOROP:%d:%d] unknown property > [PROP:%d:%s]]\n", > + colorop->base.id, colorop->type, > + property->base.id, property->name); > + return -EINVAL; > + } > + > + return 0; > } > > static int > @@ -664,6 +670,8 @@ drm_atomic_colorop_get_property(struct drm_colorop > *colorop, > { > if (property == colorop->type_property) { > *val = colorop->type; > + } else if (property == colorop->curve_1d_type_property) { > + *val = state->curve_1d_type; > } else { > return -EINVAL; > } > diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c > index 1459a28c7e7b..6fbc3c284d33 100644 > --- a/drivers/gpu/drm/drm_colorop.c > +++ b/drivers/gpu/drm/drm_colorop.c > @@ -31,6 +31,123 @@ > > #include "drm_crtc_internal.h" > > +static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = { > + { DRM_COLOROP_1D_CURVE, "1D Curve" }, > +}; > + > +static const char * const colorop_curve_1d_type_names[] = { > + [DRM_COLOROP_1D_CURVE_SRGB_EOTF] = "sRGB EOTF", > + [DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF] = "sRGB Inverse EOTF", > +}; > + > + > +/* 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) > +{ > + struct drm_mode_config *config = &dev->mode_config; > + struct drm_property *prop; > + int ret = 0; > + > + ret = drm_mode_object_add(dev, &colorop->base, DRM_MODE_OBJECT_COLOROP); > + if (ret) > + return ret; > + > + colorop->base.properties = &colorop->properties; > + colorop->dev = dev; > + colorop->type = type; > + colorop->plane = plane; > + > + list_add_tail(&colorop->head, &config->colorop_list); > + colorop->index = config->num_colorop++; > + > + /* add properties */ > + > + /* type */ > + prop = drm_property_create_enum(dev, > + DRM_MODE_PROP_IMMUTABLE, > + "TYPE", drm_colorop_type_enum_list, > + ARRAY_SIZE(drm_colorop_type_enum_list)); > + > + if (!prop) > + return -ENOMEM; > + > + colorop->type_property = prop; > + > + drm_object_attach_property(&colorop->base, > + colorop->type_property, > + colorop->type); > + > + return ret; > +} > + > +/** > + * drm_plane_colorop_curve_1d_init - Initialize a DRM_COLOROP_1D_CURVE > + * > + * @dev: DRM device > + * @colorop: The drm_colorop object to initialize > + * @plane: The associated drm_plane > + * @supported_tfs: A bitfield of supported drm_plane_colorop_curve_1d_init > enum values, > + * created using BIT(curve_type) and combined with the OR '|' > + * operator. > + * @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) > +{ > + 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); > + if (ret) > + return ret; > + > + len = 0; > + for (i = 0; i < DRM_COLOROP_1D_CURVE_COUNT; i++) { > + if ((supported_tfs & BIT(i)) == 0) > + continue; > + > + enum_list[len].type = i; > + enum_list[len].name = colorop_curve_1d_type_names[i]; > + len++; > + } > + > + if (WARN_ON(len <= 0)) > + return -EINVAL; > + > + > + /* initialize 1D curve only attribute */ > + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, > "CURVE_1D_TYPE", > + enum_list, len); > + if (!prop) > + return -ENOMEM; > + > + colorop->curve_1d_type_property = prop; > + drm_object_attach_property(&colorop->base, > colorop->curve_1d_type_property, > + enum_list[0].type); > + drm_colorop_reset(colorop); > + > + return 0; > +} > +EXPORT_SYMBOL(drm_plane_colorop_curve_1d_init); > + > static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop > *colorop, > struct > drm_colorop_state *state) > { > @@ -70,7 +187,16 @@ void drm_colorop_atomic_destroy_state(struct drm_colorop > *colorop, > static void __drm_colorop_state_reset(struct drm_colorop_state > *colorop_state, > struct drm_colorop *colorop) > { > + u64 val; > + > colorop_state->colorop = colorop; > + > + if (colorop->curve_1d_type_property) { > + drm_object_property_get_default_value(&colorop->base, > + colorop->curve_1d_type_property, > + &val); > + colorop_state->curve_1d_type = val; > + } > } > > /** > @@ -114,3 +240,11 @@ const char *drm_get_colorop_type_name(enum > drm_colorop_type type) > > return colorop_type_name[type]; > } > + > +const char *drm_get_colorop_curve_1d_type_name(enum > drm_colorop_curve_1d_type type) > +{ > + if (WARN_ON(type >= ARRAY_SIZE(colorop_curve_1d_type_names))) > + return "unknown"; > + > + return colorop_curve_1d_type_names[type]; > +} > diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h > index 9c9698545f63..fa167e642e0d 100644 > --- a/include/drm/drm_colorop.h > +++ b/include/drm/drm_colorop.h > @@ -31,6 +31,42 @@ > #include <drm/drm_mode.h> > #include <drm/drm_property.h> > > + > +/** > + * enum drm_colorop_curve_1d_type - type of 1D curve > + * > + * Describes a 1D curve to be applied by the DRM_COLOROP_1D_CURVE colorop. > + */ > +enum drm_colorop_curve_1d_type { > + /** > + * @DRM_COLOROP_1D_CURVE_SRGB_EOTF: > + * > + * enum string "sRGB EOTF" > + * > + * sRGB piece-wise electro-optical transfer function. Transfer > + * characteristics as defined by IEC 61966-2-1 sRGB. Equivalent > + * to H.273 TransferCharacteristics code point 13 with > + * MatrixCoefficients set to 0. > + */
We user space folks have been convinced at this point that the sRGB EOTF is actually gamma 2.2, and not the piece-wise function. Now, if the hardware is actually the piece-wise, then that's what should be exposed, but I'm a bit unsure if we should do that under the name sRGB EOTF. Maybe any other alternative is even worse. At least this is clearly documented to be the piece-wise function, so it's only about the naming. > + DRM_COLOROP_1D_CURVE_SRGB_EOTF, > + > + /** > + * @DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF: > + * > + * enum string "sRGB Inverse EOTF" > + * > + * The inverse of &DRM_COLOROP_1D_CURVE_SRGB_EOTF > + */ > + DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF, > + > + /** > + * @DRM_COLOROP_1D_CURVE_COUNT: > + * > + * enum value denoting the size of the enum > + */ > + DRM_COLOROP_1D_CURVE_COUNT > +}; > + > /** > * struct drm_colorop_state - mutable colorop state > */ > @@ -46,6 +82,13 @@ struct drm_colorop_state { > * information. > */ > > + /** > + * @curve_1d_type: > + * > + * Type of 1D curve. > + */ > + enum drm_colorop_curve_1d_type curve_1d_type; > + > /** @state: backpointer to global drm_atomic_state */ > struct drm_atomic_state *state; > }; > @@ -127,6 +170,14 @@ struct drm_colorop { > * this color operation. The type is enum drm_colorop_type. > */ > struct drm_property *type_property; > + > + /** > + * @curve_1d_type_property: > + * > + * Sub-type for DRM_COLOROP_1D_CURVE type. > + */ > + struct drm_property *curve_1d_type_property; > + > }; > > #define obj_to_colorop(x) container_of(x, struct drm_colorop, base) > @@ -151,6 +202,9 @@ static inline struct drm_colorop *drm_colorop_find(struct > drm_device *dev, > return mo ? obj_to_colorop(mo) : NULL; > } > > +int drm_plane_colorop_curve_1d_init(struct drm_device *dev, struct > drm_colorop *colorop, > + struct drm_plane *plane, u64 supported_tfs); > + > struct drm_colorop_state * > drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop); > > @@ -191,4 +245,13 @@ static inline unsigned int drm_colorop_index(const > struct drm_colorop *colorop) > */ > const char *drm_get_colorop_type_name(enum drm_colorop_type type); > > +/** > + * drm_get_colorop_curve_1d_type_name - return a string for 1D curve type > + * @type: 1d curve type to compute name of > + * > + * In contrast to the other drm_get_*_name functions this one here returns a > + * const pointer and hence is threadsafe. > + */ > +const char *drm_get_colorop_curve_1d_type_name(enum > drm_colorop_curve_1d_type type); > + > #endif /* __DRM_COLOROP_H__ */