* [RFC PATCH v2 1/9] drm/colorop: Add DRM_COLOROP_CSC_FF
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-08 11:31 ` Borah, Chaitanya Kumar
2026-03-30 15:34 ` [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values Harry Wentland
` (8 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Chaitanya Kumar Borah
From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
Introduce DRM_COLOROP_CSC_FF, a new colorop type representing a
fixed-function Color Space Conversion (CSC) block.
Unlike CTM-based colorops, this block does not expose programmable
coefficients. Instead, userspace selects one of the predefined
hardware modes via a new CSC_FF_TYPE enum property. Supported modes
include common YUV->RGB and RGB709->RGB2020 conversions.
Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
---
drivers/gpu/drm/drm_atomic.c | 4 ++
drivers/gpu/drm/drm_atomic_uapi.c | 4 ++
drivers/gpu/drm/drm_colorop.c | 105 ++++++++++++++++++++++++++++++
include/drm/drm_colorop.h | 72 ++++++++++++++++++++
include/uapi/drm/drm_mode.h | 13 ++++
5 files changed, 198 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 41c57063f3b4..5bff85576e6b 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -845,6 +845,10 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
break;
+ case DRM_COLOROP_CSC_FF:
+ drm_printf(p, "\tcsc_ff_type=%s\n",
+ drm_get_colorop_csc_ff_type_name(state->csc_ff_type));
+ break;
default:
break;
}
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 5bd5bf6661df..39b0dd1ec348 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -761,6 +761,8 @@ static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
} else if (property == colorop->data_property) {
return drm_atomic_color_set_data_property(colorop, state,
property, val);
+ } else if (property == colorop->csc_ff_type_property) {
+ state->csc_ff_type = val;
} else {
drm_dbg_atomic(colorop->dev,
"[COLOROP:%d:%d] unknown property [PROP:%d:%s]\n",
@@ -793,6 +795,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
*val = colorop->lut3d_interpolation;
else if (property == colorop->data_property)
*val = (state->data) ? state->data->base.id : 0;
+ else if (property == colorop->csc_ff_type_property)
+ *val = state->csc_ff_type;
else
return -EINVAL;
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 566816e3c6f0..6a345e2e8b15 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -68,6 +68,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
{ DRM_COLOROP_MULTIPLIER, "Multiplier"},
{ DRM_COLOROP_3D_LUT, "3D LUT"},
+ { DRM_COLOROP_CSC_FF, "CSC Fixed-Function"},
};
static const char * const colorop_curve_1d_type_names[] = {
@@ -90,6 +91,13 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
{ DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
};
+static const char * const colorop_csc_ff_type_names[] = {
+ [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
+ [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
+ [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
+ [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
+};
+
/* Init Helpers */
static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
@@ -455,6 +463,80 @@ int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *col
}
EXPORT_SYMBOL(drm_plane_colorop_3dlut_init);
+/**
+ * drm_plane_colorop_csc_ff_init - Initialize a DRM_COLOROP_CSC_FF
+ *
+ * @dev: DRM device
+ * @colorop: The drm_colorop object to initialize
+ * @plane: The associated drm_plane
+ * @funcs: control functions for the new colorop
+ * @supported_csc_ff: A bitfield of supported drm_plane_colorop_csc_ff_type enum values,
+ * created using BIT(csc_ff_type) and combined with the OR '|'
+ * operator.
+ * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines.
+ * @return zero on success, -E value on failure
+ */
+int drm_plane_colorop_csc_ff_init(struct drm_device *dev, struct drm_colorop *colorop,
+ struct drm_plane *plane, const struct drm_colorop_funcs *funcs,
+ u64 supported_csc_ff, uint32_t flags)
+{
+ struct drm_prop_enum_list enum_list[DRM_COLOROP_CSC_FF_COUNT];
+ int i, len;
+
+ struct drm_property *prop;
+ int ret;
+
+ if (!supported_csc_ff) {
+ drm_err(dev,
+ "No supported CSC op for new CSC FF colorop on [PLANE:%d:%s]\n",
+ plane->base.id, plane->name);
+ return -EINVAL;
+ }
+
+ if ((supported_csc_ff & -BIT(DRM_COLOROP_CSC_FF_COUNT)) != 0) {
+ drm_err(dev, "Unknown CSC provided on [PLANE:%d:%s]\n",
+ plane->base.id, plane->name);
+ return -EINVAL;
+ }
+
+ ret = drm_plane_colorop_init(dev, colorop, plane, funcs, DRM_COLOROP_CSC_FF, flags);
+ if (ret)
+ return ret;
+
+ len = 0;
+ for (i = 0; i < DRM_COLOROP_CSC_FF_COUNT; i++) {
+ if ((supported_csc_ff & BIT(i)) == 0)
+ continue;
+
+ enum_list[len].type = i;
+ enum_list[len].name = colorop_csc_ff_type_names[i];
+ len++;
+ }
+
+ if (WARN_ON(len <= 0))
+ return -EINVAL;
+
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, "CSC_FF_TYPE",
+ enum_list, len);
+
+ if (!prop)
+ return -ENOMEM;
+
+ colorop->csc_ff_type_property = prop;
+ /*
+ * Default to the first supported CSC mode as provided by the driver.
+ * Intuitively this should be something that keeps the colorop in pixel bypass
+ * mode but that is already handled via the standard colorop bypass
+ * property.
+ */
+ drm_object_attach_property(&colorop->base, colorop->csc_ff_type_property,
+ enum_list[0].type);
+ drm_colorop_reset(colorop);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_plane_colorop_csc_ff_init);
+
static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
struct drm_colorop_state *state)
{
@@ -521,6 +603,13 @@ static void __drm_colorop_state_reset(struct drm_colorop_state *colorop_state,
&val);
colorop_state->curve_1d_type = val;
}
+
+ if (colorop->csc_ff_type_property) {
+ drm_object_property_get_default_value(&colorop->base,
+ colorop->csc_ff_type_property,
+ &val);
+ colorop_state->csc_ff_type = val;
+ }
}
/**
@@ -561,6 +650,7 @@ static const char * const colorop_type_name[] = {
[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
[DRM_COLOROP_MULTIPLIER] = "Multiplier",
[DRM_COLOROP_3D_LUT] = "3D LUT",
+ [DRM_COLOROP_CSC_FF] = "CSC Fixed-Function",
};
static const char * const colorop_lu3d_interpolation_name[] = {
@@ -617,6 +707,21 @@ const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_inte
return colorop_lu3d_interpolation_name[type];
}
+/**
+ * drm_get_colorop_csc_ff_type_name: return a string for interpolation type
+ * @type: csc ff 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_csc_ff_type_name(enum drm_colorop_csc_ff_type type)
+{
+ if (WARN_ON(type >= ARRAY_SIZE(colorop_csc_ff_type_names)))
+ return "unknown";
+
+ return colorop_csc_ff_type_names[type];
+}
+
/**
* drm_colorop_set_next_property - sets the next pointer
* @colorop: drm colorop
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index bd082854ca74..2cd8e0779c2a 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -134,6 +134,60 @@ enum drm_colorop_curve_1d_type {
DRM_COLOROP_1D_CURVE_COUNT
};
+/**
+ * enum drm_colorop_csc_ff_type - type of CSC Fixed-Function
+ *
+ * Describes a CSC operation to be applied by the DRM_COLOROP_CSC_FF colorop.
+ */
+enum drm_colorop_csc_ff_type {
+ /**
+ * @DRM_COLOROP_CSC_FF_YUV601_RGB601
+ *
+ * enum string "YUV601 to RGB601"
+ *
+ * Selects the fixed-function CSC preset that converts YUV
+ * (BT.601) colorimetry to RGB (BT.601).
+ */
+ DRM_COLOROP_CSC_FF_YUV601_RGB601,
+
+ /**
+ * @DRM_COLOROP_CSC_FF_YUV709_RGB709:
+ *
+ * enum string "YUV709 to RGB709"
+ *
+ * Selects the fixed-function CSC preset that converts YUV
+ * (BT.709) colorimetry to RGB (BT.709).
+ */
+ DRM_COLOROP_CSC_FF_YUV709_RGB709,
+
+ /**
+ * @DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
+ *
+ * enum string "YUV2020 to RGB2020"
+ *
+ * Selects the fixed-function CSC preset that converts YUV
+ * (BT.2020) colorimetry to RGB (BT.2020).
+ */
+ DRM_COLOROP_CSC_FF_YUV2020_RGB2020,
+
+ /**
+ * @DRM_COLOROP_CSC_FF_RGB709_RGB2020:
+ *
+ * enum string "RGB709 to RGB2020"
+ *
+ * Selects the fixed-function CSC preset that converts RGB
+ * (BT.709) colorimetry to RGB (BT.2020).
+ */
+ DRM_COLOROP_CSC_FF_RGB709_RGB2020,
+
+ /**
+ * @DRM_COLOROP_CSC_FF_COUNT:
+ *
+ * enum value denoting the size of the enum
+ */
+ DRM_COLOROP_CSC_FF_COUNT
+};
+
/**
* struct drm_colorop_state - mutable colorop state
*/
@@ -183,6 +237,13 @@ struct drm_colorop_state {
*/
struct drm_property_blob *data;
+ /**
+ * @csc_ff_type:
+ *
+ * Type of Fixed function CSC.
+ */
+ enum drm_colorop_csc_ff_type csc_ff_type;
+
/** @state: backpointer to global drm_atomic_state */
struct drm_atomic_state *state;
};
@@ -368,6 +429,13 @@ struct drm_colorop {
*/
struct drm_property *data_property;
+ /**
+ * @csc_ff_type_property:
+ *
+ * Sub-type for DRM_COLOROP_CSC_FF type.
+ */
+ struct drm_property *csc_ff_type_property;
+
/**
* @next_property:
*
@@ -424,6 +492,9 @@ int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *col
uint32_t lut_size,
enum drm_colorop_lut3d_interpolation_type interpolation,
uint32_t flags);
+int drm_plane_colorop_csc_ff_init(struct drm_device *dev, struct drm_colorop *colorop,
+ struct drm_plane *plane, const struct drm_colorop_funcs *funcs,
+ u64 supported_csc_ff, uint32_t flags);
struct drm_colorop_state *
drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
@@ -480,6 +551,7 @@ drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_ty
const char *
drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type);
+const char *drm_get_colorop_csc_ff_type_name(enum drm_colorop_csc_ff_type type);
void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index a4bdc4bd11bc..5d21f73c3d76 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -971,6 +971,19 @@ enum drm_colorop_type {
* color = lut3d[index]
*/
DRM_COLOROP_3D_LUT,
+
+ /**
+ * @DRM_COLOROP_CSC_FF:
+ *
+ * enum string "CSC Fixed-Function"
+ *
+ * A fixed-function Color Space Conversion block where the coefficients
+ * are not programmable but selected from predefined hardware modes via
+ * the CSC_FF_TYPE enum property. The driver advertises the supported
+ * CSC modes through this property.
+ */
+ DRM_COLOROP_CSC_FF,
+
};
/**
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 1/9] drm/colorop: Add DRM_COLOROP_CSC_FF
2026-03-30 15:34 ` [RFC PATCH v2 1/9] drm/colorop: Add DRM_COLOROP_CSC_FF Harry Wentland
@ 2026-04-08 11:31 ` Borah, Chaitanya Kumar
0 siblings, 0 replies; 26+ messages in thread
From: Borah, Chaitanya Kumar @ 2026-04-08 11:31 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
Hello Harry,
On 3/30/2026 9:04 PM, Harry Wentland wrote:
> From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
>
> Introduce DRM_COLOROP_CSC_FF, a new colorop type representing a
> fixed-function Color Space Conversion (CSC) block.
>
> Unlike CTM-based colorops, this block does not expose programmable
> coefficients. Instead, userspace selects one of the predefined
> hardware modes via a new CSC_FF_TYPE enum property. Supported modes
> include common YUV->RGB and RGB709->RGB2020 conversions.
>
Thank you for incorporating this into your series. I believe this
approach should work for both Intel and AMD hardware. I've posted a
v2[1] of the patch addressing Pekka's comments. Please let me know if it
looks good.
==
Chaitanya
[1] https://patchwork.freedesktop.org/patch/716856/?series=162787&rev=2
> Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
> ---
> drivers/gpu/drm/drm_atomic.c | 4 ++
> drivers/gpu/drm/drm_atomic_uapi.c | 4 ++
> drivers/gpu/drm/drm_colorop.c | 105 ++++++++++++++++++++++++++++++
> include/drm/drm_colorop.h | 72 ++++++++++++++++++++
> include/uapi/drm/drm_mode.h | 13 ++++
> 5 files changed, 198 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 41c57063f3b4..5bff85576e6b 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -845,6 +845,10 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
> drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
> drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
> break;
> + case DRM_COLOROP_CSC_FF:
> + drm_printf(p, "\tcsc_ff_type=%s\n",
> + drm_get_colorop_csc_ff_type_name(state->csc_ff_type));
> + break;
> default:
> break;
> }
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index 5bd5bf6661df..39b0dd1ec348 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -761,6 +761,8 @@ static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
> } else if (property == colorop->data_property) {
> return drm_atomic_color_set_data_property(colorop, state,
> property, val);
> + } else if (property == colorop->csc_ff_type_property) {
> + state->csc_ff_type = val;
> } else {
> drm_dbg_atomic(colorop->dev,
> "[COLOROP:%d:%d] unknown property [PROP:%d:%s]\n",
> @@ -793,6 +795,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
> *val = colorop->lut3d_interpolation;
> else if (property == colorop->data_property)
> *val = (state->data) ? state->data->base.id : 0;
> + else if (property == colorop->csc_ff_type_property)
> + *val = state->csc_ff_type;
> else
> return -EINVAL;
>
> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
> index 566816e3c6f0..6a345e2e8b15 100644
> --- a/drivers/gpu/drm/drm_colorop.c
> +++ b/drivers/gpu/drm/drm_colorop.c
> @@ -68,6 +68,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
> { DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
> { DRM_COLOROP_MULTIPLIER, "Multiplier"},
> { DRM_COLOROP_3D_LUT, "3D LUT"},
> + { DRM_COLOROP_CSC_FF, "CSC Fixed-Function"},
> };
>
> static const char * const colorop_curve_1d_type_names[] = {
> @@ -90,6 +91,13 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
> { DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
> };
>
> +static const char * const colorop_csc_ff_type_names[] = {
> + [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
> + [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
> + [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
> + [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
> +};
> +
> /* Init Helpers */
>
> static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
> @@ -455,6 +463,80 @@ int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *col
> }
> EXPORT_SYMBOL(drm_plane_colorop_3dlut_init);
>
> +/**
> + * drm_plane_colorop_csc_ff_init - Initialize a DRM_COLOROP_CSC_FF
> + *
> + * @dev: DRM device
> + * @colorop: The drm_colorop object to initialize
> + * @plane: The associated drm_plane
> + * @funcs: control functions for the new colorop
> + * @supported_csc_ff: A bitfield of supported drm_plane_colorop_csc_ff_type enum values,
> + * created using BIT(csc_ff_type) and combined with the OR '|'
> + * operator.
> + * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines.
> + * @return zero on success, -E value on failure
> + */
> +int drm_plane_colorop_csc_ff_init(struct drm_device *dev, struct drm_colorop *colorop,
> + struct drm_plane *plane, const struct drm_colorop_funcs *funcs,
> + u64 supported_csc_ff, uint32_t flags)
> +{
> + struct drm_prop_enum_list enum_list[DRM_COLOROP_CSC_FF_COUNT];
> + int i, len;
> +
> + struct drm_property *prop;
> + int ret;
> +
> + if (!supported_csc_ff) {
> + drm_err(dev,
> + "No supported CSC op for new CSC FF colorop on [PLANE:%d:%s]\n",
> + plane->base.id, plane->name);
> + return -EINVAL;
> + }
> +
> + if ((supported_csc_ff & -BIT(DRM_COLOROP_CSC_FF_COUNT)) != 0) {
> + drm_err(dev, "Unknown CSC provided on [PLANE:%d:%s]\n",
> + plane->base.id, plane->name);
> + return -EINVAL;
> + }
> +
> + ret = drm_plane_colorop_init(dev, colorop, plane, funcs, DRM_COLOROP_CSC_FF, flags);
> + if (ret)
> + return ret;
> +
> + len = 0;
> + for (i = 0; i < DRM_COLOROP_CSC_FF_COUNT; i++) {
> + if ((supported_csc_ff & BIT(i)) == 0)
> + continue;
> +
> + enum_list[len].type = i;
> + enum_list[len].name = colorop_csc_ff_type_names[i];
> + len++;
> + }
> +
> + if (WARN_ON(len <= 0))
> + return -EINVAL;
> +
> + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, "CSC_FF_TYPE",
> + enum_list, len);
> +
> + if (!prop)
> + return -ENOMEM;
> +
> + colorop->csc_ff_type_property = prop;
> + /*
> + * Default to the first supported CSC mode as provided by the driver.
> + * Intuitively this should be something that keeps the colorop in pixel bypass
> + * mode but that is already handled via the standard colorop bypass
> + * property.
> + */
> + drm_object_attach_property(&colorop->base, colorop->csc_ff_type_property,
> + enum_list[0].type);
> + drm_colorop_reset(colorop);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(drm_plane_colorop_csc_ff_init);
> +
> static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
> struct drm_colorop_state *state)
> {
> @@ -521,6 +603,13 @@ static void __drm_colorop_state_reset(struct drm_colorop_state *colorop_state,
> &val);
> colorop_state->curve_1d_type = val;
> }
> +
> + if (colorop->csc_ff_type_property) {
> + drm_object_property_get_default_value(&colorop->base,
> + colorop->csc_ff_type_property,
> + &val);
> + colorop_state->csc_ff_type = val;
> + }
> }
>
> /**
> @@ -561,6 +650,7 @@ static const char * const colorop_type_name[] = {
> [DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
> [DRM_COLOROP_MULTIPLIER] = "Multiplier",
> [DRM_COLOROP_3D_LUT] = "3D LUT",
> + [DRM_COLOROP_CSC_FF] = "CSC Fixed-Function",
> };
>
> static const char * const colorop_lu3d_interpolation_name[] = {
> @@ -617,6 +707,21 @@ const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_inte
> return colorop_lu3d_interpolation_name[type];
> }
>
> +/**
> + * drm_get_colorop_csc_ff_type_name: return a string for interpolation type
> + * @type: csc ff 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_csc_ff_type_name(enum drm_colorop_csc_ff_type type)
> +{
> + if (WARN_ON(type >= ARRAY_SIZE(colorop_csc_ff_type_names)))
> + return "unknown";
> +
> + return colorop_csc_ff_type_names[type];
> +}
> +
> /**
> * drm_colorop_set_next_property - sets the next pointer
> * @colorop: drm colorop
> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
> index bd082854ca74..2cd8e0779c2a 100644
> --- a/include/drm/drm_colorop.h
> +++ b/include/drm/drm_colorop.h
> @@ -134,6 +134,60 @@ enum drm_colorop_curve_1d_type {
> DRM_COLOROP_1D_CURVE_COUNT
> };
>
> +/**
> + * enum drm_colorop_csc_ff_type - type of CSC Fixed-Function
> + *
> + * Describes a CSC operation to be applied by the DRM_COLOROP_CSC_FF colorop.
> + */
> +enum drm_colorop_csc_ff_type {
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV601_RGB601
> + *
> + * enum string "YUV601 to RGB601"
> + *
> + * Selects the fixed-function CSC preset that converts YUV
> + * (BT.601) colorimetry to RGB (BT.601).
> + */
> + DRM_COLOROP_CSC_FF_YUV601_RGB601,
> +
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV709_RGB709:
> + *
> + * enum string "YUV709 to RGB709"
> + *
> + * Selects the fixed-function CSC preset that converts YUV
> + * (BT.709) colorimetry to RGB (BT.709).
> + */
> + DRM_COLOROP_CSC_FF_YUV709_RGB709,
> +
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
> + *
> + * enum string "YUV2020 to RGB2020"
> + *
> + * Selects the fixed-function CSC preset that converts YUV
> + * (BT.2020) colorimetry to RGB (BT.2020).
> + */
> + DRM_COLOROP_CSC_FF_YUV2020_RGB2020,
> +
> + /**
> + * @DRM_COLOROP_CSC_FF_RGB709_RGB2020:
> + *
> + * enum string "RGB709 to RGB2020"
> + *
> + * Selects the fixed-function CSC preset that converts RGB
> + * (BT.709) colorimetry to RGB (BT.2020).
> + */
> + DRM_COLOROP_CSC_FF_RGB709_RGB2020,
> +
> + /**
> + * @DRM_COLOROP_CSC_FF_COUNT:
> + *
> + * enum value denoting the size of the enum
> + */
> + DRM_COLOROP_CSC_FF_COUNT
> +};
> +
> /**
> * struct drm_colorop_state - mutable colorop state
> */
> @@ -183,6 +237,13 @@ struct drm_colorop_state {
> */
> struct drm_property_blob *data;
>
> + /**
> + * @csc_ff_type:
> + *
> + * Type of Fixed function CSC.
> + */
> + enum drm_colorop_csc_ff_type csc_ff_type;
> +
> /** @state: backpointer to global drm_atomic_state */
> struct drm_atomic_state *state;
> };
> @@ -368,6 +429,13 @@ struct drm_colorop {
> */
> struct drm_property *data_property;
>
> + /**
> + * @csc_ff_type_property:
> + *
> + * Sub-type for DRM_COLOROP_CSC_FF type.
> + */
> + struct drm_property *csc_ff_type_property;
> +
> /**
> * @next_property:
> *
> @@ -424,6 +492,9 @@ int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *col
> uint32_t lut_size,
> enum drm_colorop_lut3d_interpolation_type interpolation,
> uint32_t flags);
> +int drm_plane_colorop_csc_ff_init(struct drm_device *dev, struct drm_colorop *colorop,
> + struct drm_plane *plane, const struct drm_colorop_funcs *funcs,
> + u64 supported_csc_ff, uint32_t flags);
>
> struct drm_colorop_state *
> drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
> @@ -480,6 +551,7 @@ drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_ty
>
> const char *
> drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type);
> +const char *drm_get_colorop_csc_ff_type_name(enum drm_colorop_csc_ff_type type);
>
> void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
>
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index a4bdc4bd11bc..5d21f73c3d76 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -971,6 +971,19 @@ enum drm_colorop_type {
> * color = lut3d[index]
> */
> DRM_COLOROP_3D_LUT,
> +
> + /**
> + * @DRM_COLOROP_CSC_FF:
> + *
> + * enum string "CSC Fixed-Function"
> + *
> + * A fixed-function Color Space Conversion block where the coefficients
> + * are not programmable but selected from predefined hardware modes via
> + * the CSC_FF_TYPE enum property. The driver advertises the supported
> + * CSC modes through this property.
> + */
> + DRM_COLOROP_CSC_FF,
> +
> };
>
> /**
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
2026-03-30 15:34 ` [RFC PATCH v2 1/9] drm/colorop: Add DRM_COLOROP_CSC_FF Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:22 ` Alex Hung
2026-04-23 9:34 ` Borah, Chaitanya Kumar
2026-03-30 15:34 ` [RFC PATCH v2 3/9] drm/vkms: Add CSC FF colorop to color pipeline Harry Wentland
` (7 subsequent siblings)
9 siblings, 2 replies; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
Add three new limited-range YUV-to-RGB conversion presets to the
CSC Fixed-Function colorop enum:
- DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601
- DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709
- DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020
The existing full-range enums (YUV601_RGB601, YUV709_RGB709,
YUV2020_RGB2020) are kept as-is. The limited-range variants are
inserted after their corresponding full-range entries.
This gives drivers the ability to advertise support for both full
and limited range YCbCr framebuffers via the color pipeline,
replacing the need for separate COLOR_ENCODING and COLOR_RANGE
properties on the CSC colorop.
Assisted-by Claude:claude-opus-4.6
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
drivers/gpu/drm/drm_colorop.c | 11 +++++----
include/drm/drm_colorop.h | 42 ++++++++++++++++++++++++++++++-----
2 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 6a345e2e8b15..f0d11cf7e3cd 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -92,10 +92,13 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
};
static const char * const colorop_csc_ff_type_names[] = {
- [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
- [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
- [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
- [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
+ [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
+ [DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601] = "YUV601 Limited to RGB601",
+ [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
+ [DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709] = "YUV709 Limited to RGB709",
+ [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
+ [DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020] = "YUV2020 Limited to RGB2020",
+ [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
};
/* Init Helpers */
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 2cd8e0779c2a..c414b9070afb 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -145,31 +145,61 @@ enum drm_colorop_csc_ff_type {
*
* enum string "YUV601 to RGB601"
*
- * Selects the fixed-function CSC preset that converts YUV
- * (BT.601) colorimetry to RGB (BT.601).
+ * Selects the fixed-function CSC preset that converts full-range
+ * YUV (BT.601) colorimetry to RGB (BT.601).
*/
DRM_COLOROP_CSC_FF_YUV601_RGB601,
+ /**
+ * @DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
+ *
+ * enum string "YUV601 Limited to RGB601"
+ *
+ * Selects the fixed-function CSC preset that converts limited-range
+ * YUV (BT.601) colorimetry to RGB (BT.601).
+ */
+ DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601,
+
/**
* @DRM_COLOROP_CSC_FF_YUV709_RGB709:
*
* enum string "YUV709 to RGB709"
*
- * Selects the fixed-function CSC preset that converts YUV
- * (BT.709) colorimetry to RGB (BT.709).
+ * Selects the fixed-function CSC preset that converts full-range
+ * YUV (BT.709) colorimetry to RGB (BT.709).
*/
DRM_COLOROP_CSC_FF_YUV709_RGB709,
+ /**
+ * @DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
+ *
+ * enum string "YUV709 Limited to RGB709"
+ *
+ * Selects the fixed-function CSC preset that converts limited-range
+ * YUV (BT.709) colorimetry to RGB (BT.709).
+ */
+ DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709,
+
/**
* @DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
*
* enum string "YUV2020 to RGB2020"
*
- * Selects the fixed-function CSC preset that converts YUV
- * (BT.2020) colorimetry to RGB (BT.2020).
+ * Selects the fixed-function CSC preset that converts full-range
+ * YUV (BT.2020) colorimetry to RGB (BT.2020).
*/
DRM_COLOROP_CSC_FF_YUV2020_RGB2020,
+ /**
+ * @DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
+ *
+ * enum string "YUV2020 Limited to RGB2020"
+ *
+ * Selects the fixed-function CSC preset that converts limited-range
+ * YUV (BT.2020) colorimetry to RGB (BT.2020).
+ */
+ DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020,
+
/**
* @DRM_COLOROP_CSC_FF_RGB709_RGB2020:
*
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values
2026-03-30 15:34 ` [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values Harry Wentland
@ 2026-04-21 21:22 ` Alex Hung
2026-04-23 9:34 ` Borah, Chaitanya Kumar
1 sibling, 0 replies; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:22 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 3/30/26 09:34, Harry Wentland wrote:
> Add three new limited-range YUV-to-RGB conversion presets to the
> CSC Fixed-Function colorop enum:
>
> - DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601
> - DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709
> - DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020
>
> The existing full-range enums (YUV601_RGB601, YUV709_RGB709,
> YUV2020_RGB2020) are kept as-is. The limited-range variants are
> inserted after their corresponding full-range entries.
>
> This gives drivers the ability to advertise support for both full
> and limited range YCbCr framebuffers via the color pipeline,
> replacing the need for separate COLOR_ENCODING and COLOR_RANGE
> properties on the CSC colorop.
>
> Assisted-by Claude:claude-opus-4.6
Missing ":" after Assisted-by above
Reviewed-by: Alex Hung <alex.hung@amd.com>
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> drivers/gpu/drm/drm_colorop.c | 11 +++++----
> include/drm/drm_colorop.h | 42 ++++++++++++++++++++++++++++++-----
> 2 files changed, 43 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
> index 6a345e2e8b15..f0d11cf7e3cd 100644
> --- a/drivers/gpu/drm/drm_colorop.c
> +++ b/drivers/gpu/drm/drm_colorop.c
> @@ -92,10 +92,13 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
> };
>
> static const char * const colorop_csc_ff_type_names[] = {
> - [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
> - [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
> - [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
> - [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
> + [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
> + [DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601] = "YUV601 Limited to RGB601",
> + [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
> + [DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709] = "YUV709 Limited to RGB709",
> + [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
> + [DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020] = "YUV2020 Limited to RGB2020",
> + [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
> };
>
> /* Init Helpers */
> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
> index 2cd8e0779c2a..c414b9070afb 100644
> --- a/include/drm/drm_colorop.h
> +++ b/include/drm/drm_colorop.h
> @@ -145,31 +145,61 @@ enum drm_colorop_csc_ff_type {
> *
> * enum string "YUV601 to RGB601"
> *
> - * Selects the fixed-function CSC preset that converts YUV
> - * (BT.601) colorimetry to RGB (BT.601).
> + * Selects the fixed-function CSC preset that converts full-range
> + * YUV (BT.601) colorimetry to RGB (BT.601).
> */
> DRM_COLOROP_CSC_FF_YUV601_RGB601,
>
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
> + *
> + * enum string "YUV601 Limited to RGB601"
> + *
> + * Selects the fixed-function CSC preset that converts limited-range
> + * YUV (BT.601) colorimetry to RGB (BT.601).
> + */
> + DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601,
> +
> /**
> * @DRM_COLOROP_CSC_FF_YUV709_RGB709:
> *
> * enum string "YUV709 to RGB709"
> *
> - * Selects the fixed-function CSC preset that converts YUV
> - * (BT.709) colorimetry to RGB (BT.709).
> + * Selects the fixed-function CSC preset that converts full-range
> + * YUV (BT.709) colorimetry to RGB (BT.709).
> */
> DRM_COLOROP_CSC_FF_YUV709_RGB709,
>
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
> + *
> + * enum string "YUV709 Limited to RGB709"
> + *
> + * Selects the fixed-function CSC preset that converts limited-range
> + * YUV (BT.709) colorimetry to RGB (BT.709).
> + */
> + DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709,
> +
> /**
> * @DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
> *
> * enum string "YUV2020 to RGB2020"
> *
> - * Selects the fixed-function CSC preset that converts YUV
> - * (BT.2020) colorimetry to RGB (BT.2020).
> + * Selects the fixed-function CSC preset that converts full-range
> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
> */
> DRM_COLOROP_CSC_FF_YUV2020_RGB2020,
>
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
> + *
> + * enum string "YUV2020 Limited to RGB2020"
> + *
> + * Selects the fixed-function CSC preset that converts limited-range
> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
> + */
> + DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020,
> +
> /**
> * @DRM_COLOROP_CSC_FF_RGB709_RGB2020:
> *
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values
2026-03-30 15:34 ` [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values Harry Wentland
2026-04-21 21:22 ` Alex Hung
@ 2026-04-23 9:34 ` Borah, Chaitanya Kumar
2026-04-30 18:19 ` Harry Wentland
1 sibling, 1 reply; 26+ messages in thread
From: Borah, Chaitanya Kumar @ 2026-04-23 9:34 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 3/30/2026 9:04 PM, Harry Wentland wrote:
> Add three new limited-range YUV-to-RGB conversion presets to the
> CSC Fixed-Function colorop enum:
>
> - DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601
> - DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709
> - DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020
>
> The existing full-range enums (YUV601_RGB601, YUV709_RGB709,
> YUV2020_RGB2020) are kept as-is. The limited-range variants are
> inserted after their corresponding full-range entries.
>
> This gives drivers the ability to advertise support for both full
> and limited range YCbCr framebuffers via the color pipeline,
> replacing the need for separate COLOR_ENCODING and COLOR_RANGE
> properties on the CSC colorop.
>
> Assisted-by Claude:claude-opus-4.6
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> drivers/gpu/drm/drm_colorop.c | 11 +++++----
> include/drm/drm_colorop.h | 42 ++++++++++++++++++++++++++++++-----
> 2 files changed, 43 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
> index 6a345e2e8b15..f0d11cf7e3cd 100644
> --- a/drivers/gpu/drm/drm_colorop.c
> +++ b/drivers/gpu/drm/drm_colorop.c
> @@ -92,10 +92,13 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
> };
>
> static const char * const colorop_csc_ff_type_names[] = {
> - [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
> - [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
> - [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
> - [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
> + [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
> + [DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601] = "YUV601 Limited to RGB601",
> + [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
> + [DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709] = "YUV709 Limited to RGB709",
> + [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
> + [DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020] = "YUV2020 Limited to RGB2020",
> + [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
As I understand, all combinations of input/output ranges are
mathematically valid (e.g., “YCbCr XXX Limited → RGB Limited” or “YCbCr
XXX Full → RGB Limited”).
I am not sure how widespread such use-cases are but will it be prudent
to have the enums be named as "YCbCrXXX <range> to RGB <range>"?
==
Chaitanya
> };
>
> /* Init Helpers */
> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
> index 2cd8e0779c2a..c414b9070afb 100644
> --- a/include/drm/drm_colorop.h
> +++ b/include/drm/drm_colorop.h
> @@ -145,31 +145,61 @@ enum drm_colorop_csc_ff_type {
> *
> * enum string "YUV601 to RGB601"
> *
> - * Selects the fixed-function CSC preset that converts YUV
> - * (BT.601) colorimetry to RGB (BT.601).
> + * Selects the fixed-function CSC preset that converts full-range
> + * YUV (BT.601) colorimetry to RGB (BT.601).
> */
> DRM_COLOROP_CSC_FF_YUV601_RGB601,
>
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
> + *
> + * enum string "YUV601 Limited to RGB601"
> + *
> + * Selects the fixed-function CSC preset that converts limited-range
> + * YUV (BT.601) colorimetry to RGB (BT.601).
> + */
> + DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601,
> +
> /**
> * @DRM_COLOROP_CSC_FF_YUV709_RGB709:
> *
> * enum string "YUV709 to RGB709"
> *
> - * Selects the fixed-function CSC preset that converts YUV
> - * (BT.709) colorimetry to RGB (BT.709).
> + * Selects the fixed-function CSC preset that converts full-range
> + * YUV (BT.709) colorimetry to RGB (BT.709).
> */
> DRM_COLOROP_CSC_FF_YUV709_RGB709,
>
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
> + *
> + * enum string "YUV709 Limited to RGB709"
> + *
> + * Selects the fixed-function CSC preset that converts limited-range
> + * YUV (BT.709) colorimetry to RGB (BT.709).
> + */
> + DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709,
> +
> /**
> * @DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
> *
> * enum string "YUV2020 to RGB2020"
> *
> - * Selects the fixed-function CSC preset that converts YUV
> - * (BT.2020) colorimetry to RGB (BT.2020).
> + * Selects the fixed-function CSC preset that converts full-range
> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
> */
> DRM_COLOROP_CSC_FF_YUV2020_RGB2020,
>
> + /**
> + * @DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
> + *
> + * enum string "YUV2020 Limited to RGB2020"
> + *
> + * Selects the fixed-function CSC preset that converts limited-range
> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
> + */
> + DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020,
> +
> /**
> * @DRM_COLOROP_CSC_FF_RGB709_RGB2020:
> *
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values
2026-04-23 9:34 ` Borah, Chaitanya Kumar
@ 2026-04-30 18:19 ` Harry Wentland
2026-05-05 10:17 ` Borah, Chaitanya Kumar
0 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-04-30 18:19 UTC (permalink / raw)
To: Borah, Chaitanya Kumar, dri-devel, amd-gfx
On 2026-04-23 05:34, Borah, Chaitanya Kumar wrote:
>
>
> On 3/30/2026 9:04 PM, Harry Wentland wrote:
>> Add three new limited-range YUV-to-RGB conversion presets to the
>> CSC Fixed-Function colorop enum:
>>
>> - DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601
>> - DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709
>> - DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020
>>
>> The existing full-range enums (YUV601_RGB601, YUV709_RGB709,
>> YUV2020_RGB2020) are kept as-is. The limited-range variants are
>> inserted after their corresponding full-range entries.
>>
>> This gives drivers the ability to advertise support for both full
>> and limited range YCbCr framebuffers via the color pipeline,
>> replacing the need for separate COLOR_ENCODING and COLOR_RANGE
>> properties on the CSC colorop.
>>
>> Assisted-by Claude:claude-opus-4.6
>>
>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>> ---
>> drivers/gpu/drm/drm_colorop.c | 11 +++++----
>> include/drm/drm_colorop.h | 42 ++++++++++++++++++++++++++++++-----
>> 2 files changed, 43 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
>> index 6a345e2e8b15..f0d11cf7e3cd 100644
>> --- a/drivers/gpu/drm/drm_colorop.c
>> +++ b/drivers/gpu/drm/drm_colorop.c
>> @@ -92,10 +92,13 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
>> };
>> static const char * const colorop_csc_ff_type_names[] = {
>> - [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
>> - [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
>> - [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
>> - [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
>> + [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
>> + [DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601] = "YUV601 Limited to RGB601",
>> + [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
>> + [DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709] = "YUV709 Limited to RGB709",
>> + [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
>> + [DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020] = "YUV2020 Limited to RGB2020",
>> + [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
>
> As I understand, all combinations of input/output ranges are mathematically valid (e.g., “YCbCr XXX Limited → RGB Limited” or “YCbCr XXX Full → RGB Limited”).
>
> I am not sure how widespread such use-cases are but will it be prudent to have the enums be named as "YCbCrXXX <range> to RGB <range>"?
I'm not sure how likely it would be that anyone would need to convert to RGB limited. I'd prefer to keep things simpler for now. If anyone does need to add enums for conversion to limited RGB they could always add _RGB_LIMITED variations of the enums in the future.
Harry
>
> ==
> Chaitanya
>
>> };
>> /* Init Helpers */
>> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
>> index 2cd8e0779c2a..c414b9070afb 100644
>> --- a/include/drm/drm_colorop.h
>> +++ b/include/drm/drm_colorop.h
>> @@ -145,31 +145,61 @@ enum drm_colorop_csc_ff_type {
>> *
>> * enum string "YUV601 to RGB601"
>> *
>> - * Selects the fixed-function CSC preset that converts YUV
>> - * (BT.601) colorimetry to RGB (BT.601).
>> + * Selects the fixed-function CSC preset that converts full-range
>> + * YUV (BT.601) colorimetry to RGB (BT.601).
>> */
>> DRM_COLOROP_CSC_FF_YUV601_RGB601,
>> + /**
>> + * @DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
>> + *
>> + * enum string "YUV601 Limited to RGB601"
>> + *
>> + * Selects the fixed-function CSC preset that converts limited-range
>> + * YUV (BT.601) colorimetry to RGB (BT.601).
>> + */
>> + DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601,
>> +
>> /**
>> * @DRM_COLOROP_CSC_FF_YUV709_RGB709:
>> *
>> * enum string "YUV709 to RGB709"
>> *
>> - * Selects the fixed-function CSC preset that converts YUV
>> - * (BT.709) colorimetry to RGB (BT.709).
>> + * Selects the fixed-function CSC preset that converts full-range
>> + * YUV (BT.709) colorimetry to RGB (BT.709).
>> */
>> DRM_COLOROP_CSC_FF_YUV709_RGB709,
>> + /**
>> + * @DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
>> + *
>> + * enum string "YUV709 Limited to RGB709"
>> + *
>> + * Selects the fixed-function CSC preset that converts limited-range
>> + * YUV (BT.709) colorimetry to RGB (BT.709).
>> + */
>> + DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709,
>> +
>> /**
>> * @DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
>> *
>> * enum string "YUV2020 to RGB2020"
>> *
>> - * Selects the fixed-function CSC preset that converts YUV
>> - * (BT.2020) colorimetry to RGB (BT.2020).
>> + * Selects the fixed-function CSC preset that converts full-range
>> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
>> */
>> DRM_COLOROP_CSC_FF_YUV2020_RGB2020,
>> + /**
>> + * @DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
>> + *
>> + * enum string "YUV2020 Limited to RGB2020"
>> + *
>> + * Selects the fixed-function CSC preset that converts limited-range
>> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
>> + */
>> + DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020,
>> +
>> /**
>> * @DRM_COLOROP_CSC_FF_RGB709_RGB2020:
>> *
>
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values
2026-04-30 18:19 ` Harry Wentland
@ 2026-05-05 10:17 ` Borah, Chaitanya Kumar
0 siblings, 0 replies; 26+ messages in thread
From: Borah, Chaitanya Kumar @ 2026-05-05 10:17 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 4/30/2026 11:49 PM, Harry Wentland wrote:
>
>
> On 2026-04-23 05:34, Borah, Chaitanya Kumar wrote:
>>
>>
>> On 3/30/2026 9:04 PM, Harry Wentland wrote:
>>> Add three new limited-range YUV-to-RGB conversion presets to the
>>> CSC Fixed-Function colorop enum:
>>>
>>> - DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601
>>> - DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709
>>> - DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020
>>>
>>> The existing full-range enums (YUV601_RGB601, YUV709_RGB709,
>>> YUV2020_RGB2020) are kept as-is. The limited-range variants are
>>> inserted after their corresponding full-range entries.
>>>
>>> This gives drivers the ability to advertise support for both full
>>> and limited range YCbCr framebuffers via the color pipeline,
>>> replacing the need for separate COLOR_ENCODING and COLOR_RANGE
>>> properties on the CSC colorop.
>>>
>>> Assisted-by Claude:claude-opus-4.6
>>>
>>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>>> ---
>>> drivers/gpu/drm/drm_colorop.c | 11 +++++----
>>> include/drm/drm_colorop.h | 42 ++++++++++++++++++++++++++++++-----
>>> 2 files changed, 43 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
>>> index 6a345e2e8b15..f0d11cf7e3cd 100644
>>> --- a/drivers/gpu/drm/drm_colorop.c
>>> +++ b/drivers/gpu/drm/drm_colorop.c
>>> @@ -92,10 +92,13 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
>>> };
>>> static const char * const colorop_csc_ff_type_names[] = {
>>> - [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
>>> - [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
>>> - [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
>>> - [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
>>> + [DRM_COLOROP_CSC_FF_YUV601_RGB601] = "YUV601 to RGB601",
>>> + [DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601] = "YUV601 Limited to RGB601",
>>> + [DRM_COLOROP_CSC_FF_YUV709_RGB709] = "YUV709 to RGB709",
>>> + [DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709] = "YUV709 Limited to RGB709",
>>> + [DRM_COLOROP_CSC_FF_YUV2020_RGB2020] = "YUV2020 to RGB2020",
>>> + [DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020] = "YUV2020 Limited to RGB2020",
>>> + [DRM_COLOROP_CSC_FF_RGB709_RGB2020] = "RGB709 to RGB2020",
>>
>> As I understand, all combinations of input/output ranges are mathematically valid (e.g., “YCbCr XXX Limited → RGB Limited” or “YCbCr XXX Full → RGB Limited”).
>>
>> I am not sure how widespread such use-cases are but will it be prudent to have the enums be named as "YCbCrXXX <range> to RGB <range>"?
>
> I'm not sure how likely it would be that anyone would need to convert to RGB limited. I'd prefer to keep things simpler for now. If anyone does need to add enums for conversion to limited RGB they could always add _RGB_LIMITED variations of the enums in the future.
>
Alright makes sense, I will stick to the "RGB" == "RGB Full" nomencature.
Thank you.
==
Chaitanya
> Harry
>
>>
>> ==
>> Chaitanya
>>
>>> };
>>> /* Init Helpers */
>>> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
>>> index 2cd8e0779c2a..c414b9070afb 100644
>>> --- a/include/drm/drm_colorop.h
>>> +++ b/include/drm/drm_colorop.h
>>> @@ -145,31 +145,61 @@ enum drm_colorop_csc_ff_type {
>>> *
>>> * enum string "YUV601 to RGB601"
>>> *
>>> - * Selects the fixed-function CSC preset that converts YUV
>>> - * (BT.601) colorimetry to RGB (BT.601).
>>> + * Selects the fixed-function CSC preset that converts full-range
>>> + * YUV (BT.601) colorimetry to RGB (BT.601).
>>> */
>>> DRM_COLOROP_CSC_FF_YUV601_RGB601,
>>> + /**
>>> + * @DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
>>> + *
>>> + * enum string "YUV601 Limited to RGB601"
>>> + *
>>> + * Selects the fixed-function CSC preset that converts limited-range
>>> + * YUV (BT.601) colorimetry to RGB (BT.601).
>>> + */
>>> + DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601,
>>> +
>>> /**
>>> * @DRM_COLOROP_CSC_FF_YUV709_RGB709:
>>> *
>>> * enum string "YUV709 to RGB709"
>>> *
>>> - * Selects the fixed-function CSC preset that converts YUV
>>> - * (BT.709) colorimetry to RGB (BT.709).
>>> + * Selects the fixed-function CSC preset that converts full-range
>>> + * YUV (BT.709) colorimetry to RGB (BT.709).
>>> */
>>> DRM_COLOROP_CSC_FF_YUV709_RGB709,
>>> + /**
>>> + * @DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
>>> + *
>>> + * enum string "YUV709 Limited to RGB709"
>>> + *
>>> + * Selects the fixed-function CSC preset that converts limited-range
>>> + * YUV (BT.709) colorimetry to RGB (BT.709).
>>> + */
>>> + DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709,
>>> +
>>> /**
>>> * @DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
>>> *
>>> * enum string "YUV2020 to RGB2020"
>>> *
>>> - * Selects the fixed-function CSC preset that converts YUV
>>> - * (BT.2020) colorimetry to RGB (BT.2020).
>>> + * Selects the fixed-function CSC preset that converts full-range
>>> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
>>> */
>>> DRM_COLOROP_CSC_FF_YUV2020_RGB2020,
>>> + /**
>>> + * @DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
>>> + *
>>> + * enum string "YUV2020 Limited to RGB2020"
>>> + *
>>> + * Selects the fixed-function CSC preset that converts limited-range
>>> + * YUV (BT.2020) colorimetry to RGB (BT.2020).
>>> + */
>>> + DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020,
>>> +
>>> /**
>>> * @DRM_COLOROP_CSC_FF_RGB709_RGB2020:
>>> *
>>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 3/9] drm/vkms: Add CSC FF colorop to color pipeline
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
2026-03-30 15:34 ` [RFC PATCH v2 1/9] drm/colorop: Add DRM_COLOROP_CSC_FF Harry Wentland
2026-03-30 15:34 ` [RFC PATCH v2 2/9] drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:21 ` Alex Hung
2026-03-30 15:34 ` [RFC PATCH v2 4/9] drm/vkms: Add atomic check and matrix handling for CSC FF colorop Harry Wentland
` (6 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
Insert a CSC Fixed-Function colorop as the first operation in the
VKMS color pipeline, before the existing 1D curve. This allows
userspace to select YUV-to-RGB conversion via the color pipeline
for YCbCr framebuffers.
The CSC FF colorop advertises support for all six YUV-to-RGB
conversion presets:
- YUV601/709/2020 full-range to RGB
- YUV601/709/2020 limited-range to RGB
Bump MAX_COLOR_PIPELINE_OPS from 4 to 5 to accommodate the new op.
Assisted-by Claude:claude-opus-4.6
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
drivers/gpu/drm/vkms/vkms_colorop.c | 66 ++++++++++++++++++++---------
1 file changed, 46 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
index 071f3a8d2e7c..fa78ac7be36e 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -12,11 +12,19 @@ static const u64 supported_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
+static const u64 supported_csc_ff =
+ BIT(DRM_COLOROP_CSC_FF_YUV601_RGB601) |
+ BIT(DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601) |
+ BIT(DRM_COLOROP_CSC_FF_YUV709_RGB709) |
+ BIT(DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709) |
+ BIT(DRM_COLOROP_CSC_FF_YUV2020_RGB2020) |
+ BIT(DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020);
+
static const struct drm_colorop_funcs vkms_colorop_funcs = {
.destroy = drm_colorop_destroy,
};
-#define MAX_COLOR_PIPELINE_OPS 4
+#define MAX_COLOR_PIPELINE_OPS 5
static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
{
@@ -27,7 +35,25 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
memset(ops, 0, sizeof(ops));
- /* 1st op: 1d curve */
+ /* 1st op: CSC Fixed-Function (YUV to RGB) */
+ ops[i] = kzalloc_obj(*ops[i]);
+ if (!ops[i]) {
+ drm_err(dev, "KMS: Failed to allocate colorop\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ ret = drm_plane_colorop_csc_ff_init(dev, ops[i], plane, &vkms_colorop_funcs,
+ supported_csc_ff,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ if (ret)
+ goto cleanup;
+
+ list->type = ops[i]->base.id;
+
+ i++;
+
+ /* 2nd op: 1d curve */
ops[i] = kzalloc_obj(*ops[i]);
if (!ops[i]) {
drm_err(dev, "KMS: Failed to allocate colorop\n");
@@ -41,23 +67,6 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
if (ret)
goto cleanup;
- list->type = ops[i]->base.id;
-
- i++;
-
- /* 2nd op: 3x4 matrix */
- ops[i] = kzalloc_obj(*ops[i]);
- if (!ops[i]) {
- drm_err(dev, "KMS: Failed to allocate colorop\n");
- ret = -ENOMEM;
- goto cleanup;
- }
-
- ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, &vkms_colorop_funcs,
- DRM_COLOROP_FLAG_ALLOW_BYPASS);
- if (ret)
- goto cleanup;
-
drm_colorop_set_next_property(ops[i - 1], ops[i]);
i++;
@@ -79,7 +88,24 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
i++;
- /* 4th op: 1d curve */
+ /* 4th op: 3x4 matrix */
+ ops[i] = kzalloc_obj(*ops[i]);
+ if (!ops[i]) {
+ drm_err(dev, "KMS: Failed to allocate colorop\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, &vkms_colorop_funcs,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ if (ret)
+ goto cleanup;
+
+ drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+ i++;
+
+ /* 5th op: 1d curve */
ops[i] = kzalloc_obj(*ops[i]);
if (!ops[i]) {
drm_err(dev, "KMS: Failed to allocate colorop\n");
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 3/9] drm/vkms: Add CSC FF colorop to color pipeline
2026-03-30 15:34 ` [RFC PATCH v2 3/9] drm/vkms: Add CSC FF colorop to color pipeline Harry Wentland
@ 2026-04-21 21:21 ` Alex Hung
0 siblings, 0 replies; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:21 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
Reviewed-by: Alex Hung <alex.hung@amd.com>
On 3/30/26 09:34, Harry Wentland wrote:
> Insert a CSC Fixed-Function colorop as the first operation in the
> VKMS color pipeline, before the existing 1D curve. This allows
> userspace to select YUV-to-RGB conversion via the color pipeline
> for YCbCr framebuffers.
>
> The CSC FF colorop advertises support for all six YUV-to-RGB
> conversion presets:
> - YUV601/709/2020 full-range to RGB
> - YUV601/709/2020 limited-range to RGB
>
> Bump MAX_COLOR_PIPELINE_OPS from 4 to 5 to accommodate the new op.
>
> Assisted-by Claude:claude-opus-4.6
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> drivers/gpu/drm/vkms/vkms_colorop.c | 66 ++++++++++++++++++++---------
> 1 file changed, 46 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
> index 071f3a8d2e7c..fa78ac7be36e 100644
> --- a/drivers/gpu/drm/vkms/vkms_colorop.c
> +++ b/drivers/gpu/drm/vkms/vkms_colorop.c
> @@ -12,11 +12,19 @@ static const u64 supported_tfs =
> BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
> BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
>
> +static const u64 supported_csc_ff =
> + BIT(DRM_COLOROP_CSC_FF_YUV601_RGB601) |
> + BIT(DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601) |
> + BIT(DRM_COLOROP_CSC_FF_YUV709_RGB709) |
> + BIT(DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709) |
> + BIT(DRM_COLOROP_CSC_FF_YUV2020_RGB2020) |
> + BIT(DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020);
> +
> static const struct drm_colorop_funcs vkms_colorop_funcs = {
> .destroy = drm_colorop_destroy,
> };
>
> -#define MAX_COLOR_PIPELINE_OPS 4
> +#define MAX_COLOR_PIPELINE_OPS 5
>
> static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
> {
> @@ -27,7 +35,25 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
>
> memset(ops, 0, sizeof(ops));
>
> - /* 1st op: 1d curve */
> + /* 1st op: CSC Fixed-Function (YUV to RGB) */
> + ops[i] = kzalloc_obj(*ops[i]);
> + if (!ops[i]) {
> + drm_err(dev, "KMS: Failed to allocate colorop\n");
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> +
> + ret = drm_plane_colorop_csc_ff_init(dev, ops[i], plane, &vkms_colorop_funcs,
> + supported_csc_ff,
> + DRM_COLOROP_FLAG_ALLOW_BYPASS);
> + if (ret)
> + goto cleanup;
> +
> + list->type = ops[i]->base.id;
> +
> + i++;
> +
> + /* 2nd op: 1d curve */
> ops[i] = kzalloc_obj(*ops[i]);
> if (!ops[i]) {
> drm_err(dev, "KMS: Failed to allocate colorop\n");
> @@ -41,23 +67,6 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
> if (ret)
> goto cleanup;
>
> - list->type = ops[i]->base.id;
> -
> - i++;
> -
> - /* 2nd op: 3x4 matrix */
> - ops[i] = kzalloc_obj(*ops[i]);
> - if (!ops[i]) {
> - drm_err(dev, "KMS: Failed to allocate colorop\n");
> - ret = -ENOMEM;
> - goto cleanup;
> - }
> -
> - ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, &vkms_colorop_funcs,
> - DRM_COLOROP_FLAG_ALLOW_BYPASS);
> - if (ret)
> - goto cleanup;
> -
> drm_colorop_set_next_property(ops[i - 1], ops[i]);
>
> i++;
> @@ -79,7 +88,24 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
>
> i++;
>
> - /* 4th op: 1d curve */
> + /* 4th op: 3x4 matrix */
> + ops[i] = kzalloc_obj(*ops[i]);
> + if (!ops[i]) {
> + drm_err(dev, "KMS: Failed to allocate colorop\n");
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> +
> + ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, &vkms_colorop_funcs,
> + DRM_COLOROP_FLAG_ALLOW_BYPASS);
> + if (ret)
> + goto cleanup;
> +
> + drm_colorop_set_next_property(ops[i - 1], ops[i]);
> +
> + i++;
> +
> + /* 5th op: 1d curve */
> ops[i] = kzalloc_obj(*ops[i]);
> if (!ops[i]) {
> drm_err(dev, "KMS: Failed to allocate colorop\n");
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 4/9] drm/vkms: Add atomic check and matrix handling for CSC FF colorop
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
` (2 preceding siblings ...)
2026-03-30 15:34 ` [RFC PATCH v2 3/9] drm/vkms: Add CSC FF colorop to color pipeline Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:20 ` Alex Hung
2026-03-30 15:34 ` [RFC PATCH v2 5/9] drm/amd/display: Add CSC FF colorop to color pipeline Harry Wentland
` (5 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
In vkms_plane_atomic_check(), validate that when a color pipeline
is active and the framebuffer format is YUV:
- The first colorop must be DRM_COLOROP_CSC_FF
- The CSC FF colorop must not be bypassed
In vkms_plane_atomic_update(), when a color pipeline is active,
read the csc_ff_type from the first colorop state and map it to
the appropriate (color_encoding, color_range) pair for the existing
get_conversion_matrix_to_argb_u16() function.
In apply_colorop(), add a no-op case for DRM_COLOROP_CSC_FF since
the actual YUV-to-RGB conversion is already performed at format
read time via the conversion matrix.
Assisted-by Claude:claude-opus-4.6
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
drivers/gpu/drm/vkms/vkms_composer.c | 6 +++
drivers/gpu/drm/vkms/vkms_plane.c | 70 +++++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 83d217085ad0..e29376f1cbd7 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -187,6 +187,12 @@ static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colo
if (colorop_state->data)
apply_3x4_matrix(pixel,
(struct drm_color_ctm_3x4 *)colorop_state->data->data);
+ } else if (colorop->type == DRM_COLOROP_CSC_FF) {
+ /*
+ * CSC FF is a no-op here. YUV-to-RGB conversion is handled
+ * at format read time via the conversion_matrix set in
+ * vkms_plane_atomic_update().
+ */
}
}
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index ca7aee101a95..0f1ebdd9e391 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -6,6 +6,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
+#include <drm/drm_colorop.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -148,8 +149,58 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
frame_info->rotation = new_state->rotation;
vkms_plane_state->pixel_read_line = get_pixel_read_line_function(fmt);
- get_conversion_matrix_to_argb_u16(fmt, new_state->color_encoding, new_state->color_range,
- &vkms_plane_state->conversion_matrix);
+
+ if (new_state->color_pipeline) {
+ struct drm_colorop *colorop = new_state->color_pipeline;
+ struct drm_colorop_state *colorop_state;
+
+ drm_WARN_ON(plane->dev, colorop->type != DRM_COLOROP_CSC_FF);
+
+ colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
+
+ if (colorop_state && !colorop_state->bypass) {
+ enum drm_color_encoding encoding;
+ enum drm_color_range range;
+
+ switch (colorop_state->csc_ff_type) {
+ case DRM_COLOROP_CSC_FF_YUV601_RGB601:
+ encoding = DRM_COLOR_YCBCR_BT601;
+ range = DRM_COLOR_YCBCR_FULL_RANGE;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
+ encoding = DRM_COLOR_YCBCR_BT601;
+ range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV709_RGB709:
+ encoding = DRM_COLOR_YCBCR_BT709;
+ range = DRM_COLOR_YCBCR_FULL_RANGE;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
+ encoding = DRM_COLOR_YCBCR_BT709;
+ range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
+ encoding = DRM_COLOR_YCBCR_BT2020;
+ range = DRM_COLOR_YCBCR_FULL_RANGE;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
+ encoding = DRM_COLOR_YCBCR_BT2020;
+ range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+ break;
+ default:
+ encoding = DRM_COLOR_YCBCR_BT709;
+ range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+ break;
+ }
+
+ get_conversion_matrix_to_argb_u16(fmt, encoding, range,
+ &vkms_plane_state->conversion_matrix);
+ }
+ } else {
+ get_conversion_matrix_to_argb_u16(fmt, new_state->color_encoding,
+ new_state->color_range,
+ &vkms_plane_state->conversion_matrix);
+ }
}
static int vkms_plane_atomic_check(struct drm_plane *plane,
@@ -175,6 +226,21 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
if (ret != 0)
return ret;
+ if (new_plane_state->color_pipeline && new_plane_state->fb->format->is_yuv) {
+ struct drm_colorop *colorop = new_plane_state->color_pipeline;
+ struct drm_colorop_state *colorop_state;
+
+ if (colorop->type != DRM_COLOROP_CSC_FF)
+ return -EINVAL;
+
+ colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
+ if (!colorop_state)
+ return -EINVAL;
+
+ if (colorop_state->bypass)
+ return -EINVAL;
+ }
+
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 4/9] drm/vkms: Add atomic check and matrix handling for CSC FF colorop
2026-03-30 15:34 ` [RFC PATCH v2 4/9] drm/vkms: Add atomic check and matrix handling for CSC FF colorop Harry Wentland
@ 2026-04-21 21:20 ` Alex Hung
0 siblings, 0 replies; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:20 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 3/30/26 09:34, Harry Wentland wrote:
> In vkms_plane_atomic_check(), validate that when a color pipeline
> is active and the framebuffer format is YUV:
> - The first colorop must be DRM_COLOROP_CSC_FF
> - The CSC FF colorop must not be bypassed
>
> In vkms_plane_atomic_update(), when a color pipeline is active,
> read the csc_ff_type from the first colorop state and map it to
> the appropriate (color_encoding, color_range) pair for the existing
> get_conversion_matrix_to_argb_u16() function.
>
> In apply_colorop(), add a no-op case for DRM_COLOROP_CSC_FF since
> the actual YUV-to-RGB conversion is already performed at format
> read time via the conversion matrix.
>
> Assisted-by Claude:claude-opus-4.6
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> drivers/gpu/drm/vkms/vkms_composer.c | 6 +++
> drivers/gpu/drm/vkms/vkms_plane.c | 70 +++++++++++++++++++++++++++-
> 2 files changed, 74 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
> index 83d217085ad0..e29376f1cbd7 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -187,6 +187,12 @@ static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colo
> if (colorop_state->data)
> apply_3x4_matrix(pixel,
> (struct drm_color_ctm_3x4 *)colorop_state->data->data);
> + } else if (colorop->type == DRM_COLOROP_CSC_FF) {
> + /*
> + * CSC FF is a no-op here. YUV-to-RGB conversion is handled
> + * at format read time via the conversion_matrix set in
> + * vkms_plane_atomic_update().
> + */
> }
> }
>
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index ca7aee101a95..0f1ebdd9e391 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -6,6 +6,7 @@
> #include <drm/drm_atomic.h>
> #include <drm/drm_atomic_helper.h>
> #include <drm/drm_blend.h>
> +#include <drm/drm_colorop.h>
> #include <drm/drm_fourcc.h>
> #include <drm/drm_gem_atomic_helper.h>
> #include <drm/drm_gem_framebuffer_helper.h>
> @@ -148,8 +149,58 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
> frame_info->rotation = new_state->rotation;
>
> vkms_plane_state->pixel_read_line = get_pixel_read_line_function(fmt);
> - get_conversion_matrix_to_argb_u16(fmt, new_state->color_encoding, new_state->color_range,
> - &vkms_plane_state->conversion_matrix);
> +
> + if (new_state->color_pipeline) {
> + struct drm_colorop *colorop = new_state->color_pipeline;
> + struct drm_colorop_state *colorop_state;
> +
> + drm_WARN_ON(plane->dev, colorop->type != DRM_COLOROP_CSC_FF);
Is this drm_WARN_ON necessary? How about a drm_dbg?
Either way, this patch is
Reviewed-by: Alex Hung <alex.hung@amd.com>
> +
> + colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
> +
> + if (colorop_state && !colorop_state->bypass) {
> + enum drm_color_encoding encoding;
> + enum drm_color_range range;
> +
> + switch (colorop_state->csc_ff_type) {
> + case DRM_COLOROP_CSC_FF_YUV601_RGB601:
> + encoding = DRM_COLOR_YCBCR_BT601;
> + range = DRM_COLOR_YCBCR_FULL_RANGE;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
> + encoding = DRM_COLOR_YCBCR_BT601;
> + range = DRM_COLOR_YCBCR_LIMITED_RANGE;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV709_RGB709:
> + encoding = DRM_COLOR_YCBCR_BT709;
> + range = DRM_COLOR_YCBCR_FULL_RANGE;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
> + encoding = DRM_COLOR_YCBCR_BT709;
> + range = DRM_COLOR_YCBCR_LIMITED_RANGE;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
> + encoding = DRM_COLOR_YCBCR_BT2020;
> + range = DRM_COLOR_YCBCR_FULL_RANGE;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
> + encoding = DRM_COLOR_YCBCR_BT2020;
> + range = DRM_COLOR_YCBCR_LIMITED_RANGE;
> + break;
> + default:
> + encoding = DRM_COLOR_YCBCR_BT709;
> + range = DRM_COLOR_YCBCR_LIMITED_RANGE;
> + break;
> + }
> +
> + get_conversion_matrix_to_argb_u16(fmt, encoding, range,
> + &vkms_plane_state->conversion_matrix);
> + }
> + } else {
> + get_conversion_matrix_to_argb_u16(fmt, new_state->color_encoding,
> + new_state->color_range,
> + &vkms_plane_state->conversion_matrix);
> + }
> }
>
> static int vkms_plane_atomic_check(struct drm_plane *plane,
> @@ -175,6 +226,21 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
> if (ret != 0)
> return ret;
>
> + if (new_plane_state->color_pipeline && new_plane_state->fb->format->is_yuv) {
> + struct drm_colorop *colorop = new_plane_state->color_pipeline;
> + struct drm_colorop_state *colorop_state;
> +
> + if (colorop->type != DRM_COLOROP_CSC_FF)
> + return -EINVAL;
> +
> + colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
> + if (!colorop_state)
> + return -EINVAL;
> +
> + if (colorop_state->bypass)
> + return -EINVAL;
> + }
> +
> return 0;
> }
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 5/9] drm/amd/display: Add CSC FF colorop to color pipeline
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
` (3 preceding siblings ...)
2026-03-30 15:34 ` [RFC PATCH v2 4/9] drm/vkms: Add atomic check and matrix handling for CSC FF colorop Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:14 ` Alex Hung
2026-03-30 15:34 ` [RFC PATCH v2 6/9] drm/amd/display: Implement CSC FF colorop color space mapping Harry Wentland
` (4 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
Insert a CSC Fixed-Function colorop as the first operation in the
amdgpu color pipeline, before the existing DEGAM 1D curve. This
allows userspace to select YUV-to-RGB conversion via the color
pipeline for YCbCr framebuffers.
The CSC FF colorop advertises support for all six YUV-to-RGB
conversion presets:
- YUV601/709/2020 full-range to RGB
- YUV601/709/2020 limited-range to RGB
Assisted-by Claude:claude-opus-4.6
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 27 ++++++++++++++++++-
.../amd/display/amdgpu_dm/amdgpu_dm_colorop.h | 1 +
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 3e05e48a8792..13521095e021 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -51,6 +51,14 @@ const u64 amdgpu_dm_supported_blnd_tfs =
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
+const u64 amdgpu_dm_supported_csc_ff =
+ BIT(DRM_COLOROP_CSC_FF_YUV601_RGB601) |
+ BIT(DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601) |
+ BIT(DRM_COLOROP_CSC_FF_YUV709_RGB709) |
+ BIT(DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709) |
+ BIT(DRM_COLOROP_CSC_FF_YUV2020_RGB2020) |
+ BIT(DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020);
+
#define MAX_COLOR_PIPELINE_OPS 10
#define LUT3D_SIZE 17
@@ -70,6 +78,23 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
memset(ops, 0, sizeof(ops));
+ /* CSC Fixed-Function (YUV to RGB) */
+ ops[i] = kzalloc_obj(*ops[0]);
+ if (!ops[i]) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ ret = drm_plane_colorop_csc_ff_init(dev, ops[i], plane, &dm_colorop_funcs,
+ amdgpu_dm_supported_csc_ff,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ if (ret)
+ goto cleanup;
+
+ list->type = ops[i]->base.id;
+
+ i++;
+
/* 1D curve - DEGAM TF */
ops[i] = kzalloc_obj(*ops[0]);
if (!ops[i]) {
@@ -83,7 +108,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
if (ret)
goto cleanup;
- list->type = ops[i]->base.id;
+ drm_colorop_set_next_property(ops[i - 1], ops[i]);
i++;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
index 2e1617ffc8ee..e509646b5567 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
@@ -30,6 +30,7 @@
extern const u64 amdgpu_dm_supported_degam_tfs;
extern const u64 amdgpu_dm_supported_shaper_tfs;
extern const u64 amdgpu_dm_supported_blnd_tfs;
+extern const u64 amdgpu_dm_supported_csc_ff;
int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 5/9] drm/amd/display: Add CSC FF colorop to color pipeline
2026-03-30 15:34 ` [RFC PATCH v2 5/9] drm/amd/display: Add CSC FF colorop to color pipeline Harry Wentland
@ 2026-04-21 21:14 ` Alex Hung
0 siblings, 0 replies; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:14 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
Reviewed-by: Alex Hung <alex.hung@amd.com>
On 3/30/26 09:34, Harry Wentland wrote:
> Insert a CSC Fixed-Function colorop as the first operation in the
> amdgpu color pipeline, before the existing DEGAM 1D curve. This
> allows userspace to select YUV-to-RGB conversion via the color
> pipeline for YCbCr framebuffers.
>
> The CSC FF colorop advertises support for all six YUV-to-RGB
> conversion presets:
> - YUV601/709/2020 full-range to RGB
> - YUV601/709/2020 limited-range to RGB
>
> Assisted-by Claude:claude-opus-4.6
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 27 ++++++++++++++++++-
> .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h | 1 +
> 2 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
> index 3e05e48a8792..13521095e021 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
> @@ -51,6 +51,14 @@ const u64 amdgpu_dm_supported_blnd_tfs =
> BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
> BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
>
> +const u64 amdgpu_dm_supported_csc_ff =
> + BIT(DRM_COLOROP_CSC_FF_YUV601_RGB601) |
> + BIT(DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601) |
> + BIT(DRM_COLOROP_CSC_FF_YUV709_RGB709) |
> + BIT(DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709) |
> + BIT(DRM_COLOROP_CSC_FF_YUV2020_RGB2020) |
> + BIT(DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020);
> +
> #define MAX_COLOR_PIPELINE_OPS 10
>
> #define LUT3D_SIZE 17
> @@ -70,6 +78,23 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
>
> memset(ops, 0, sizeof(ops));
>
> + /* CSC Fixed-Function (YUV to RGB) */
> + ops[i] = kzalloc_obj(*ops[0]);
> + if (!ops[i]) {
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> +
> + ret = drm_plane_colorop_csc_ff_init(dev, ops[i], plane, &dm_colorop_funcs,
> + amdgpu_dm_supported_csc_ff,
> + DRM_COLOROP_FLAG_ALLOW_BYPASS);
> + if (ret)
> + goto cleanup;
> +
> + list->type = ops[i]->base.id;
> +
> + i++;
> +
> /* 1D curve - DEGAM TF */
> ops[i] = kzalloc_obj(*ops[0]);
> if (!ops[i]) {
> @@ -83,7 +108,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
> if (ret)
> goto cleanup;
>
> - list->type = ops[i]->base.id;
> + drm_colorop_set_next_property(ops[i - 1], ops[i]);
>
> i++;
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
> index 2e1617ffc8ee..e509646b5567 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
> @@ -30,6 +30,7 @@
> extern const u64 amdgpu_dm_supported_degam_tfs;
> extern const u64 amdgpu_dm_supported_shaper_tfs;
> extern const u64 amdgpu_dm_supported_blnd_tfs;
> +extern const u64 amdgpu_dm_supported_csc_ff;
>
> int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 6/9] drm/amd/display: Implement CSC FF colorop color space mapping
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
` (4 preceding siblings ...)
2026-03-30 15:34 ` [RFC PATCH v2 5/9] drm/amd/display: Add CSC FF colorop to color pipeline Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:13 ` Alex Hung
2026-03-30 15:34 ` [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used Harry Wentland
` (3 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
Add __set_dm_plane_colorop_csc_ff() which maps the CSC FF type
enum to the appropriate dc_color_space for DC programming:
YUV601_RGB601 -> COLOR_SPACE_YCBCR601
YUV601_LIMITED_RGB601 -> COLOR_SPACE_YCBCR601_LIMITED
YUV709_RGB709 -> COLOR_SPACE_YCBCR709
YUV709_LIMITED_RGB709 -> COLOR_SPACE_YCBCR709_LIMITED
YUV2020_RGB2020 -> COLOR_SPACE_2020_YCBCR_FULL
YUV2020_LIMITED_RGB2020 -> COLOR_SPACE_2020_YCBCR_LIMITED
When CSC FF is bypassed, color_space is set to COLOR_SPACE_UNKNOWN.
Update amdgpu_dm_plane_set_colorop_properties() to process the
CSC FF colorop first (before DEGAM), matching the new pipeline
order.
Assisted-by Claude:claude-opus-4.6
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_color.c | 68 ++++++++++++++++++-
1 file changed, 67 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index cd1e58b8defc..d5b4190e635c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1492,6 +1492,61 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
return 0;
}
+static int
+__set_dm_plane_colorop_csc_ff(struct drm_plane_state *plane_state,
+ struct dc_plane_state *dc_plane_state,
+ struct drm_colorop *colorop)
+{
+ struct drm_colorop *old_colorop;
+ struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+ struct drm_atomic_state *state = plane_state->state;
+ int i = 0;
+
+ old_colorop = colorop;
+
+ for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+ if (new_colorop_state->colorop == old_colorop) {
+ colorop_state = new_colorop_state;
+ break;
+ }
+ }
+
+ if (!colorop_state)
+ return -EINVAL;
+
+ if (colorop_state->bypass) {
+ dc_plane_state->color_space = COLOR_SPACE_UNKNOWN;
+ return 0;
+ }
+
+ switch (colorop_state->csc_ff_type) {
+ case DRM_COLOROP_CSC_FF_YUV601_RGB601:
+ dc_plane_state->color_space = COLOR_SPACE_YCBCR601;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
+ dc_plane_state->color_space = COLOR_SPACE_YCBCR601_LIMITED;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV709_RGB709:
+ dc_plane_state->color_space = COLOR_SPACE_YCBCR709;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
+ dc_plane_state->color_space = COLOR_SPACE_YCBCR709_LIMITED;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
+ dc_plane_state->color_space = COLOR_SPACE_2020_YCBCR_FULL;
+ break;
+ case DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
+ dc_plane_state->color_space = COLOR_SPACE_2020_YCBCR_LIMITED;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dc_plane_state->update_flags.bits.full_update = 1;
+
+ return 0;
+}
+
static int
__set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
@@ -1879,10 +1934,21 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
int ret;
- /* 1D Curve - DEGAM TF */
+ /* CSC Fixed-Function (YUV to RGB) */
if (!colorop)
return -EINVAL;
+ ret = __set_dm_plane_colorop_csc_ff(plane_state, dc_plane_state, colorop);
+ if (ret)
+ return ret;
+
+ /* 1D Curve - DEGAM TF */
+ colorop = colorop->next;
+ if (!colorop) {
+ drm_dbg(dev, "no degamma colorop found\n");
+ return -EINVAL;
+ }
+
ret = __set_dm_plane_colorop_degamma(plane_state, dc_plane_state, colorop);
if (ret)
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 6/9] drm/amd/display: Implement CSC FF colorop color space mapping
2026-03-30 15:34 ` [RFC PATCH v2 6/9] drm/amd/display: Implement CSC FF colorop color space mapping Harry Wentland
@ 2026-04-21 21:13 ` Alex Hung
0 siblings, 0 replies; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:13 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
Reviewed-by: Alex Hung <alex.hung@amd.com>
On 3/30/26 09:34, Harry Wentland wrote:
> Add __set_dm_plane_colorop_csc_ff() which maps the CSC FF type
> enum to the appropriate dc_color_space for DC programming:
>
> YUV601_RGB601 -> COLOR_SPACE_YCBCR601
> YUV601_LIMITED_RGB601 -> COLOR_SPACE_YCBCR601_LIMITED
> YUV709_RGB709 -> COLOR_SPACE_YCBCR709
> YUV709_LIMITED_RGB709 -> COLOR_SPACE_YCBCR709_LIMITED
> YUV2020_RGB2020 -> COLOR_SPACE_2020_YCBCR_FULL
> YUV2020_LIMITED_RGB2020 -> COLOR_SPACE_2020_YCBCR_LIMITED
>
> When CSC FF is bypassed, color_space is set to COLOR_SPACE_UNKNOWN.
>
> Update amdgpu_dm_plane_set_colorop_properties() to process the
> CSC FF colorop first (before DEGAM), matching the new pipeline
> order.
>
> Assisted-by Claude:claude-opus-4.6
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 68 ++++++++++++++++++-
> 1 file changed, 67 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> index cd1e58b8defc..d5b4190e635c 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> @@ -1492,6 +1492,61 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
> return 0;
> }
>
> +static int
> +__set_dm_plane_colorop_csc_ff(struct drm_plane_state *plane_state,
> + struct dc_plane_state *dc_plane_state,
> + struct drm_colorop *colorop)
> +{
> + struct drm_colorop *old_colorop;
> + struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
> + struct drm_atomic_state *state = plane_state->state;
> + int i = 0;
> +
> + old_colorop = colorop;
> +
> + for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
> + if (new_colorop_state->colorop == old_colorop) {
> + colorop_state = new_colorop_state;
> + break;
> + }
> + }
> +
> + if (!colorop_state)
> + return -EINVAL;
> +
> + if (colorop_state->bypass) {
> + dc_plane_state->color_space = COLOR_SPACE_UNKNOWN;
> + return 0;
> + }
> +
> + switch (colorop_state->csc_ff_type) {
> + case DRM_COLOROP_CSC_FF_YUV601_RGB601:
> + dc_plane_state->color_space = COLOR_SPACE_YCBCR601;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV601_LIMITED_RGB601:
> + dc_plane_state->color_space = COLOR_SPACE_YCBCR601_LIMITED;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV709_RGB709:
> + dc_plane_state->color_space = COLOR_SPACE_YCBCR709;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV709_LIMITED_RGB709:
> + dc_plane_state->color_space = COLOR_SPACE_YCBCR709_LIMITED;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV2020_RGB2020:
> + dc_plane_state->color_space = COLOR_SPACE_2020_YCBCR_FULL;
> + break;
> + case DRM_COLOROP_CSC_FF_YUV2020_LIMITED_RGB2020:
> + dc_plane_state->color_space = COLOR_SPACE_2020_YCBCR_LIMITED;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + dc_plane_state->update_flags.bits.full_update = 1;
> +
> + return 0;
> +}
> +
> static int
> __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
> struct dc_plane_state *dc_plane_state,
> @@ -1879,10 +1934,21 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
> bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
> int ret;
>
> - /* 1D Curve - DEGAM TF */
> + /* CSC Fixed-Function (YUV to RGB) */
> if (!colorop)
> return -EINVAL;
>
> + ret = __set_dm_plane_colorop_csc_ff(plane_state, dc_plane_state, colorop);
> + if (ret)
> + return ret;
> +
> + /* 1D Curve - DEGAM TF */
> + colorop = colorop->next;
> + if (!colorop) {
> + drm_dbg(dev, "no degamma colorop found\n");
> + return -EINVAL;
> + }
> +
> ret = __set_dm_plane_colorop_degamma(plane_state, dc_plane_state, colorop);
> if (ret)
> return ret;
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
` (5 preceding siblings ...)
2026-03-30 15:34 ` [RFC PATCH v2 6/9] drm/amd/display: Implement CSC FF colorop color space mapping Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:08 ` Alex Hung
2026-04-24 14:48 ` Melissa Wen
2026-03-30 15:34 ` [RFC PATCH v2 8/9] drm/amd/display: Check actual state during commit_tail Harry Wentland
` (2 subsequent siblings)
9 siblings, 2 replies; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
For subsampled formats we need to use GAMCOR instead of
the DEGAM block. The color module can create a LUT for
that if we set map_user_ramp to true. So do that when
we have subsampled formats.
Co-developed by Claude Sonnet 4.5.
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_color.c | 34 ++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index d5b4190e635c..6403dfe4ee10 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1471,6 +1471,8 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
struct dc_transfer_func *tf = &dc_plane_state->in_transfer_func;
struct drm_colorop *colorop = colorop_state->colorop;
struct drm_device *drm = colorop->dev;
+ struct dc_color_caps *color_caps = NULL;
+ bool is_subsampled_format;
if (colorop->type != DRM_COLOROP_1D_CURVE)
return -EINVAL;
@@ -1486,9 +1488,39 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
drm_dbg(drm, "Degamma colorop with ID: %d\n", colorop->base.id);
- tf->type = TF_TYPE_PREDEFINED;
+ /* Check if format requires post-scale color processing (subsampled formats) */
+ is_subsampled_format = (dc_plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN &&
+ dc_plane_state->format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END);
+
tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+ if (is_subsampled_format) {
+ /*
+ * For subsampled formats (P010, NV12), we need color processing
+ * to happen AFTER scaling (to expand UV channels first).
+ * Convert predefined TF to PWL so DC will use GAMCOR (post-scale)
+ * instead of PRE_DEGAM (pre-scale).
+ *
+ * IMPORTANT: We must pass map_user_ramp=true to force PWL conversion.
+ * Without it, mod_color_calculate_degamma_params() returns early for
+ * SRGB/Linear TFs without converting to TF_TYPE_DISTRIBUTED_POINTS.
+ */
+ tf->type = TF_TYPE_PREDEFINED;
+
+ if (dc_plane_state->ctx && dc_plane_state->ctx->dc)
+ color_caps = &dc_plane_state->ctx->dc->caps.color;
+
+ if (!mod_color_calculate_degamma_params(color_caps, tf, NULL, true)) {
+ drm_err(drm, "Failed to calculate degamma params for subsampled format\n");
+ return -EINVAL;
+ }
+
+ /* mod_color_calculate_degamma_params sets tf->type to TF_TYPE_DISTRIBUTED_POINTS */
+ } else {
+ /* For non-subsampled formats (RGB, XR30), use predefined ROM LUT (PRE_DEGAM) */
+ tf->type = TF_TYPE_PREDEFINED;
+ }
+
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used
2026-03-30 15:34 ` [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used Harry Wentland
@ 2026-04-21 21:08 ` Alex Hung
2026-04-30 20:43 ` Harry Wentland
2026-04-24 14:48 ` Melissa Wen
1 sibling, 1 reply; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:08 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 3/30/26 09:34, Harry Wentland wrote:
> For subsampled formats we need to use GAMCOR instead of
> the DEGAM block. The color module can create a LUT for
> that if we set map_user_ramp to true. So do that when
> we have subsampled formats.
>
> Co-developed by Claude Sonnet 4.5.
This should be updated to "Assisted-by Claude:claude-Sonnet-4.5"
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 34 ++++++++++++++++++-
> 1 file changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> index d5b4190e635c..6403dfe4ee10 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> @@ -1471,6 +1471,8 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
> struct dc_transfer_func *tf = &dc_plane_state->in_transfer_func;
> struct drm_colorop *colorop = colorop_state->colorop;
> struct drm_device *drm = colorop->dev;
> + struct dc_color_caps *color_caps = NULL;
> + bool is_subsampled_format;
>
> if (colorop->type != DRM_COLOROP_1D_CURVE)
> return -EINVAL;
> @@ -1486,9 +1488,39 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
>
> drm_dbg(drm, "Degamma colorop with ID: %d\n", colorop->base.id);
>
> - tf->type = TF_TYPE_PREDEFINED;
Setting tf-type is moved to the below if-else branch, but both set
tf->type = TF_TYPE_PREDEFINED. Is this done intentionally to improve
readability or for other purposes?
> + /* Check if format requires post-scale color processing (subsampled formats) */
> + is_subsampled_format = (dc_plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN &&
> + dc_plane_state->format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END);
> +
> tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
>
> + if (is_subsampled_format) {
> + /*
> + * For subsampled formats (P010, NV12), we need color processing
> + * to happen AFTER scaling (to expand UV channels first).
> + * Convert predefined TF to PWL so DC will use GAMCOR (post-scale)
> + * instead of PRE_DEGAM (pre-scale).
> + *
> + * IMPORTANT: We must pass map_user_ramp=true to force PWL conversion.
> + * Without it, mod_color_calculate_degamma_params() returns early for
> + * SRGB/Linear TFs without converting to TF_TYPE_DISTRIBUTED_POINTS.
> + */
> + tf->type = TF_TYPE_PREDEFINED;
> +
> + if (dc_plane_state->ctx && dc_plane_state->ctx->dc)
> + color_caps = &dc_plane_state->ctx->dc->caps.color;
> +
> + if (!mod_color_calculate_degamma_params(color_caps, tf, NULL, true)) {
> + drm_err(drm, "Failed to calculate degamma params for subsampled format\n");
> + return -EINVAL;
> + }
> +
> + /* mod_color_calculate_degamma_params sets tf->type to TF_TYPE_DISTRIBUTED_POINTS */
> + } else {
> + /* For non-subsampled formats (RGB, XR30), use predefined ROM LUT (PRE_DEGAM) */
> + tf->type = TF_TYPE_PREDEFINED;
> + }
> +
> return 0;
> }
>
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used
2026-04-21 21:08 ` Alex Hung
@ 2026-04-30 20:43 ` Harry Wentland
0 siblings, 0 replies; 26+ messages in thread
From: Harry Wentland @ 2026-04-30 20:43 UTC (permalink / raw)
To: Alex Hung, dri-devel, amd-gfx
On 2026-04-21 17:08, Alex Hung wrote:
>
>
> On 3/30/26 09:34, Harry Wentland wrote:
>> For subsampled formats we need to use GAMCOR instead of
>> the DEGAM block. The color module can create a LUT for
>> that if we set map_user_ramp to true. So do that when
>> we have subsampled formats.
>>
>> Co-developed by Claude Sonnet 4.5.
>
> This should be updated to "Assisted-by Claude:claude-Sonnet-4.5"
>
>>
>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>> ---
>> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 34 ++++++++++++++++++-
>> 1 file changed, 33 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
>> index d5b4190e635c..6403dfe4ee10 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
>> @@ -1471,6 +1471,8 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
>> struct dc_transfer_func *tf = &dc_plane_state->in_transfer_func;
>> struct drm_colorop *colorop = colorop_state->colorop;
>> struct drm_device *drm = colorop->dev;
>> + struct dc_color_caps *color_caps = NULL;
>> + bool is_subsampled_format;
>> if (colorop->type != DRM_COLOROP_1D_CURVE)
>> return -EINVAL;
>> @@ -1486,9 +1488,39 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
>> drm_dbg(drm, "Degamma colorop with ID: %d\n", colorop->base.id);
>> - tf->type = TF_TYPE_PREDEFINED;
>
>
> Setting tf-type is moved to the below if-else branch, but both set tf->type = TF_TYPE_PREDEFINED. Is this done intentionally to improve readability or for other purposes?
>
Good catch. I should've noticed this senseless change
by the LLM. I'll also clean up the comments for v3.
Harry
>> + /* Check if format requires post-scale color processing (subsampled formats) */
>> + is_subsampled_format = (dc_plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN &&
>> + dc_plane_state->format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END);
>> +
>> tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
>> + if (is_subsampled_format) {
>> + /*
>> + * For subsampled formats (P010, NV12), we need color processing
>> + * to happen AFTER scaling (to expand UV channels first).
>> + * Convert predefined TF to PWL so DC will use GAMCOR (post-scale)
>> + * instead of PRE_DEGAM (pre-scale).
>> + *
>> + * IMPORTANT: We must pass map_user_ramp=true to force PWL conversion.
>> + * Without it, mod_color_calculate_degamma_params() returns early for
>> + * SRGB/Linear TFs without converting to TF_TYPE_DISTRIBUTED_POINTS.
>> + */
>> + tf->type = TF_TYPE_PREDEFINED;
>> +
>> + if (dc_plane_state->ctx && dc_plane_state->ctx->dc)
>> + color_caps = &dc_plane_state->ctx->dc->caps.color;
>> +
>> + if (!mod_color_calculate_degamma_params(color_caps, tf, NULL, true)) {
>> + drm_err(drm, "Failed to calculate degamma params for subsampled format\n");
>> + return -EINVAL;
>> + }
>> +
>> + /* mod_color_calculate_degamma_params sets tf->type to TF_TYPE_DISTRIBUTED_POINTS */
>> + } else {
>> + /* For non-subsampled formats (RGB, XR30), use predefined ROM LUT (PRE_DEGAM) */
>> + tf->type = TF_TYPE_PREDEFINED;
>> + }
>> +
>> return 0;
>> }
>>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used
2026-03-30 15:34 ` [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used Harry Wentland
2026-04-21 21:08 ` Alex Hung
@ 2026-04-24 14:48 ` Melissa Wen
1 sibling, 0 replies; 26+ messages in thread
From: Melissa Wen @ 2026-04-24 14:48 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 30/03/2026 12:34, Harry Wentland wrote:
> For subsampled formats we need to use GAMCOR instead of
> the DEGAM block. The color module can create a LUT for
> that if we set map_user_ramp to true. So do that when
> we have subsampled formats.
>
> Co-developed by Claude Sonnet 4.5.
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 34 ++++++++++++++++++-
> 1 file changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> index d5b4190e635c..6403dfe4ee10 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> @@ -1471,6 +1471,8 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
> struct dc_transfer_func *tf = &dc_plane_state->in_transfer_func;
> struct drm_colorop *colorop = colorop_state->colorop;
> struct drm_device *drm = colorop->dev;
> + struct dc_color_caps *color_caps = NULL;
> + bool is_subsampled_format;
>
> if (colorop->type != DRM_COLOROP_1D_CURVE)
> return -EINVAL;
> @@ -1486,9 +1488,39 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
>
> drm_dbg(drm, "Degamma colorop with ID: %d\n", colorop->base.id);
>
> - tf->type = TF_TYPE_PREDEFINED;
> + /* Check if format requires post-scale color processing (subsampled formats) */
> + is_subsampled_format = (dc_plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN &&
> + dc_plane_state->format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END);
> +
> tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
>
> + if (is_subsampled_format) {
Hi,
I'm checking this fix and I think current __set_dm_plane_degamma() with
AMD driver-specific properties also needs it, right?
> + /*
> + * For subsampled formats (P010, NV12), we need color processing
> + * to happen AFTER scaling (to expand UV channels first).
> + * Convert predefined TF to PWL so DC will use GAMCOR (post-scale)
> + * instead of PRE_DEGAM (pre-scale).
> + *
> + * IMPORTANT: We must pass map_user_ramp=true to force PWL conversion.
> + * Without it, mod_color_calculate_degamma_params() returns early for
> + * SRGB/Linear TFs without converting to TF_TYPE_DISTRIBUTED_POINTS.
> + */
> + tf->type = TF_TYPE_PREDEFINED;
> +
> + if (dc_plane_state->ctx && dc_plane_state->ctx->dc)
> + color_caps = &dc_plane_state->ctx->dc->caps.color;
> +
> + if (!mod_color_calculate_degamma_params(color_caps, tf, NULL, true)) {
> + drm_err(drm, "Failed to calculate degamma params for subsampled format\n");
> + return -EINVAL;
> + }
> +
> + /* mod_color_calculate_degamma_params sets tf->type to TF_TYPE_DISTRIBUTED_POINTS */
> + } else {
> + /* For non-subsampled formats (RGB, XR30), use predefined ROM LUT (PRE_DEGAM) */
> + tf->type = TF_TYPE_PREDEFINED;
I understand we don't need to check DPP color caps here because colorop
is currently only supported by DCN3 and newer, and I guess they all
support full range of predefined ROM LUT, right?
But checking `dc_caps->dpp.dgam_rom_caps` as
mod_color_calculate_degamma_params() does before fallback to GAM_COR
looks more robust to me.
Melissa
> + }
> +
> return 0;
> }
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 8/9] drm/amd/display: Check actual state during commit_tail
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
` (6 preceding siblings ...)
2026-03-30 15:34 ` [RFC PATCH v2 7/9] drm/amd/display: Use GAMCOR for first TF if CSC is used Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:12 ` Alex Hung
2026-03-30 15:34 ` [RFC PATCH v2 9/9] drm/amd/display: Set color_space to plane_infos Harry Wentland
2026-04-22 21:40 ` [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Melissa Wen
9 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
Previously we checked the plane_state->state's plane_color_pipeline
client config when determining whether fill_plane_color_attributes
should run, i.e., whether we had a plane color pipeline and should
use that code for handling CSC properties, or whether we should
look at legacy plane encoding and range.
The problem is that we also call this during commit_tail, during
which plane_state doesn't have the state backpointer. This meant
that during commit_tail we'd look at the legacy plane COLOR_RANGE
and COLOR_ENCODING values and overwrite what we pulled from the
CSC colorop in atomic_check previously.
Instead pass the drm_atomic_state in explicitly and check that.
Co-developed by Claude Sonnet 4.5.
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a0d4ab4590e1..c3c6211d15cd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6006,7 +6006,8 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
};
static int
-fill_plane_color_attributes(const struct drm_plane_state *plane_state,
+fill_plane_color_attributes(struct drm_atomic_state *state,
+ const struct drm_plane_state *plane_state,
const enum surface_pixel_format format,
enum dc_color_space *color_space)
{
@@ -6015,7 +6016,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
*color_space = COLOR_SPACE_SRGB;
/* Ignore properties when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set */
- if (plane_state->state && plane_state->state->plane_color_pipeline)
+ if (state && state->plane_color_pipeline)
return 0;
/* DRM color properties only affect non-RGB formats. */
@@ -6055,6 +6056,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
static int
fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
+ struct drm_atomic_state *state,
const struct drm_plane_state *plane_state,
const u64 tiling_flags,
struct dc_plane_info *plane_info,
@@ -6148,7 +6150,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
plane_info->layer_index = plane_state->normalized_zpos;
- ret = fill_plane_color_attributes(plane_state, plane_info->format,
+ ret = fill_plane_color_attributes(state, plane_state, plane_info->format,
&plane_info->color_space);
if (ret)
return ret;
@@ -6189,7 +6191,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
dc_plane_state->clip_rect = scaling_info.clip_rect;
dc_plane_state->scaling_quality = scaling_info.scaling_quality;
- ret = fill_dc_plane_info_and_addr(adev, plane_state,
+ ret = fill_dc_plane_info_and_addr(adev, plane_state->state, plane_state,
afb->tiling_flags,
&plane_info,
&dc_plane_state->address,
@@ -9984,7 +9986,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
}
fill_dc_plane_info_and_addr(
- dm->adev, new_plane_state,
+ dm->adev, state, new_plane_state,
afb->tiling_flags,
&bundle->plane_infos[planes_count],
&bundle->flip_addrs[planes_count].address,
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 8/9] drm/amd/display: Check actual state during commit_tail
2026-03-30 15:34 ` [RFC PATCH v2 8/9] drm/amd/display: Check actual state during commit_tail Harry Wentland
@ 2026-04-21 21:12 ` Alex Hung
2026-05-01 16:03 ` Harry Wentland
0 siblings, 1 reply; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:12 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 3/30/26 09:34, Harry Wentland wrote:
> Previously we checked the plane_state->state's plane_color_pipeline
> client config when determining whether fill_plane_color_attributes
> should run, i.e., whether we had a plane color pipeline and should
> use that code for handling CSC properties, or whether we should
> look at legacy plane encoding and range.
>
> The problem is that we also call this during commit_tail, during
> which plane_state doesn't have the state backpointer. This meant
> that during commit_tail we'd look at the legacy plane COLOR_RANGE
> and COLOR_ENCODING values and overwrite what we pulled from the
> CSC colorop in atomic_check previously.
A nitpick - should this patch be squashed into earlier patch to address
the problem earlier?
But that's not a real problem since the entire patchset will be merged
together.
Reviewed-by: Alex Hung <alex.hung@amd.com>
>
> Instead pass the drm_atomic_state in explicitly and check that.
>
> Co-developed by Claude Sonnet 4.5.
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++++-----
> 1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index a0d4ab4590e1..c3c6211d15cd 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6006,7 +6006,8 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
> };
>
> static int
> -fill_plane_color_attributes(const struct drm_plane_state *plane_state,
> +fill_plane_color_attributes(struct drm_atomic_state *state,
> + const struct drm_plane_state *plane_state,
> const enum surface_pixel_format format,
> enum dc_color_space *color_space)
> {
> @@ -6015,7 +6016,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
> *color_space = COLOR_SPACE_SRGB;
>
> /* Ignore properties when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set */
> - if (plane_state->state && plane_state->state->plane_color_pipeline)
> + if (state && state->plane_color_pipeline)
> return 0;
>
> /* DRM color properties only affect non-RGB formats. */
> @@ -6055,6 +6056,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
>
> static int
> fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
> + struct drm_atomic_state *state,
> const struct drm_plane_state *plane_state,
> const u64 tiling_flags,
> struct dc_plane_info *plane_info,
> @@ -6148,7 +6150,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
>
> plane_info->layer_index = plane_state->normalized_zpos;
>
> - ret = fill_plane_color_attributes(plane_state, plane_info->format,
> + ret = fill_plane_color_attributes(state, plane_state, plane_info->format,
> &plane_info->color_space);
> if (ret)
> return ret;
> @@ -6189,7 +6191,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
> dc_plane_state->clip_rect = scaling_info.clip_rect;
> dc_plane_state->scaling_quality = scaling_info.scaling_quality;
>
> - ret = fill_dc_plane_info_and_addr(adev, plane_state,
> + ret = fill_dc_plane_info_and_addr(adev, plane_state->state, plane_state,
> afb->tiling_flags,
> &plane_info,
> &dc_plane_state->address,
> @@ -9984,7 +9986,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
> }
>
> fill_dc_plane_info_and_addr(
> - dm->adev, new_plane_state,
> + dm->adev, state, new_plane_state,
> afb->tiling_flags,
> &bundle->plane_infos[planes_count],
> &bundle->flip_addrs[planes_count].address,
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 8/9] drm/amd/display: Check actual state during commit_tail
2026-04-21 21:12 ` Alex Hung
@ 2026-05-01 16:03 ` Harry Wentland
0 siblings, 0 replies; 26+ messages in thread
From: Harry Wentland @ 2026-05-01 16:03 UTC (permalink / raw)
To: Alex Hung, dri-devel, amd-gfx
On 2026-04-21 17:12, Alex Hung wrote:
>
>
> On 3/30/26 09:34, Harry Wentland wrote:
>> Previously we checked the plane_state->state's plane_color_pipeline
>> client config when determining whether fill_plane_color_attributes
>> should run, i.e., whether we had a plane color pipeline and should
>> use that code for handling CSC properties, or whether we should
>> look at legacy plane encoding and range.
>>
>> The problem is that we also call this during commit_tail, during
>> which plane_state doesn't have the state backpointer. This meant
>> that during commit_tail we'd look at the legacy plane COLOR_RANGE
>> and COLOR_ENCODING values and overwrite what we pulled from the
>> CSC colorop in atomic_check previously.
>
> A nitpick - should this patch be squashed into earlier patch to address the problem earlier?
>
That previous patch was merged with the initial color pipeline
patchset. The problem only became apparent now when enabling
YUV content.
> But that's not a real problem since the entire patchset will be merged together.
>
> Reviewed-by: Alex Hung <alex.hung@amd.com>
>
Thanks,
Harry
>>
>> Instead pass the drm_atomic_state in explicitly and check that.
>>
>> Co-developed by Claude Sonnet 4.5.
>>
>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>> ---
>> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++++-----
>> 1 file changed, 7 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index a0d4ab4590e1..c3c6211d15cd 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -6006,7 +6006,8 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
>> };
>> static int
>> -fill_plane_color_attributes(const struct drm_plane_state *plane_state,
>> +fill_plane_color_attributes(struct drm_atomic_state *state,
>> + const struct drm_plane_state *plane_state,
>> const enum surface_pixel_format format,
>> enum dc_color_space *color_space)
>> {
>> @@ -6015,7 +6016,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
>> *color_space = COLOR_SPACE_SRGB;
>> /* Ignore properties when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set */
>> - if (plane_state->state && plane_state->state->plane_color_pipeline)
>> + if (state && state->plane_color_pipeline)
>> return 0;
>> /* DRM color properties only affect non-RGB formats. */
>> @@ -6055,6 +6056,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
>> static int
>> fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
>> + struct drm_atomic_state *state,
>> const struct drm_plane_state *plane_state,
>> const u64 tiling_flags,
>> struct dc_plane_info *plane_info,
>> @@ -6148,7 +6150,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
>> plane_info->layer_index = plane_state->normalized_zpos;
>> - ret = fill_plane_color_attributes(plane_state, plane_info->format,
>> + ret = fill_plane_color_attributes(state, plane_state, plane_info->format,
>> &plane_info->color_space);
>> if (ret)
>> return ret;
>> @@ -6189,7 +6191,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
>> dc_plane_state->clip_rect = scaling_info.clip_rect;
>> dc_plane_state->scaling_quality = scaling_info.scaling_quality;
>> - ret = fill_dc_plane_info_and_addr(adev, plane_state,
>> + ret = fill_dc_plane_info_and_addr(adev, plane_state->state, plane_state,
>> afb->tiling_flags,
>> &plane_info,
>> &dc_plane_state->address,
>> @@ -9984,7 +9986,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>> }
>> fill_dc_plane_info_and_addr(
>> - dm->adev, new_plane_state,
>> + dm->adev, state, new_plane_state,
>> afb->tiling_flags,
>> &bundle->plane_infos[planes_count],
>> &bundle->flip_addrs[planes_count].address,
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC PATCH v2 9/9] drm/amd/display: Set color_space to plane_infos
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
` (7 preceding siblings ...)
2026-03-30 15:34 ` [RFC PATCH v2 8/9] drm/amd/display: Check actual state during commit_tail Harry Wentland
@ 2026-03-30 15:34 ` Harry Wentland
2026-04-21 21:23 ` Alex Hung
2026-04-22 21:40 ` [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Melissa Wen
9 siblings, 1 reply; 26+ messages in thread
From: Harry Wentland @ 2026-03-30 15:34 UTC (permalink / raw)
To: dri-devel, amd-gfx; +Cc: Harry Wentland
DC looks at plane_info structs.
For legacy drm_plane COLOR_ENCODING and COLOR_RANGE this was
done in fill_dc_plane_info_and_addr's call to
fill_plane_color_attributes.
Co-developed by Claude Sonnet 4.5.
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c3c6211d15cd..43bed6b37e35 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9992,6 +9992,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
&bundle->flip_addrs[planes_count].address,
afb->tmz_surface);
+ bundle->plane_infos[planes_count].color_space = dc_plane->color_space;
+
drm_dbg_state(state->dev, "plane: id=%d dcc_en=%d\n",
new_plane_state->plane->index,
bundle->plane_infos[planes_count].dcc.enable);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [RFC PATCH v2 9/9] drm/amd/display: Set color_space to plane_infos
2026-03-30 15:34 ` [RFC PATCH v2 9/9] drm/amd/display: Set color_space to plane_infos Harry Wentland
@ 2026-04-21 21:23 ` Alex Hung
0 siblings, 0 replies; 26+ messages in thread
From: Alex Hung @ 2026-04-21 21:23 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
On 3/30/26 09:34, Harry Wentland wrote:
> DC looks at plane_info structs.
>
> For legacy drm_plane COLOR_ENCODING and COLOR_RANGE this was
> done in fill_dc_plane_info_and_addr's call to
> fill_plane_color_attributes.
>
> Co-developed by Claude Sonnet 4.5.
To be replaced by "Assisted-by Claude:claude-Sonnet-4.5"
Reviewed-by: Alex Hung <alex.hung@amd.com>
>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index c3c6211d15cd..43bed6b37e35 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -9992,6 +9992,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
> &bundle->flip_addrs[planes_count].address,
> afb->tmz_surface);
>
> + bundle->plane_infos[planes_count].color_space = dc_plane->color_space;
> +
> drm_dbg_state(state->dev, "plane: id=%d dcc_en=%d\n",
> new_plane_state->plane->index,
> bundle->plane_infos[planes_count].dcc.enable);
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS
2026-03-30 15:34 [RFC PATCH v2 0/9] YUV conversion colorop with amdgpu and VKMS Harry Wentland
` (8 preceding siblings ...)
2026-03-30 15:34 ` [RFC PATCH v2 9/9] drm/amd/display: Set color_space to plane_infos Harry Wentland
@ 2026-04-22 21:40 ` Melissa Wen
9 siblings, 0 replies; 26+ messages in thread
From: Melissa Wen @ 2026-04-22 21:40 UTC (permalink / raw)
To: Harry Wentland, dri-devel, amd-gfx
Cc: Alex Hung, Daniel Stone, Chaitanya Kumar Borah, Uma Shankar,
Louis Chauvet, Simon Ser
On 30/03/2026 12:34, Harry Wentland wrote:
> When we merged the drm_plane color pipeline API the major gap
> that existed was the lack of a YUV to RGB conversion colorop.
> We deprecated any legacy drm_plane color properties, which
> means that the COLOR_RANGE and COLOR_ENCODING properties can't
> be used with the COLOR_PIPELINE property on a drm_plane. In
> practice this means that we can't use a COLOR_PIPELINE on
> YCbCr encoded framebuffers.
>
> This patchset expands on the CSC_FF colorop proposed by Chaitanya
> and adds limited range variants of the YCbCr to RGB conversions.
>
> His full patchset can be found at
> https://patchwork.freedesktop.org/patch/709860
>
> This code has been tested with IGT and an experimental KWin branch.
>
> IGT branch:
> https://gitlab.freedesktop.org/hwentland/igt-gpu-tools/-/tree/csc-ff-colorop
>
> KWin branch:
> https://invent.kde.org/hwentlan/kwin/-/tree/csc-3dlut
>
> The kernel branch containing these changes, based on drm-misc-next
> can be found at:
> https://gitlab.freedesktop.org/hwentland/linux/-/tree/csc-ff-colorop
>
> In order to successfully use this branch you might need a few
> bugfixes. The kernel tree containing those fixes plus these patches
> can be found at:
> https://gitlab.freedesktop.org/hwentland/linux/-/tree/csc-ff-colorop-all
>
> Further background on this work can be found at:
> https://hwentland.github.io/2026/03/10/plane-color-pipeline-csc-3d-lut-kwin.html
>
> v2:
> - use Chaitanya's CSC_FF block for named matrices
Hi,
I just renamed CSC_FF to Fixed Matrix [1] and verified with
gamescope/SteamDeck [2] and it works as expected.
FWIW here is the drm_info output for the subsampled case (primary plane):
│ └───"COLOR_PIPELINE" (atomic): enum {Bypass, Color Pipeline
225} = Color Pipeline 225
│ ├───Bypass
│ └───Color Pipeline 225
│ ├───Color Operation 225
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = Fixed Matrix
│ │ ├───"BYPASS" (atomic): range [0, 1] = 0
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 230
│ │ └───"FIXED_MATRIX_TYPE" (atomic): enum
{YCbCr 601 Full to RGB, YCbCr 601 Limited to RGB, YCbCr 709 Full to RGB,
YCbCr 709 Limited to RGB, YCbCr 2020 Full to RGB NC, YCbCr 2020 Limited
to RGB NC} = YCbCr 601 Limited to RGB
│ ├───Color Operation 230
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ │ ├───"BYPASS" (atomic): range [0, 1] = 0
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 235
│ │ └───"CURVE_1D_TYPE" (atomic): enum {sRGB
EOTF, PQ 125 EOTF, BT.2020 Inverse OETF, Gamma 2.2} = BT.2020 Inverse OETF
│ ├───Color Operation 235
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = Multiplier
│ │ ├───"BYPASS" (atomic): range [0, 1] = 0
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 240
│ │ └───"MULTIPLIER" (atomic): range [0,
UINT64_MAX] = 4294967296
│ ├───Color Operation 240
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 3x4 Matrix
│ │ ├───"BYPASS" (atomic): range [0, 1] = 1
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 245
│ │ └───"DATA" (atomic): blob = 0
│ ├───Color Operation 245
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ │ ├───"BYPASS" (atomic): range [0, 1] = 0
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 250
│ │ └───"CURVE_1D_TYPE" (atomic): enum {sRGB
Inverse EOTF, PQ 125 Inverse EOTF, BT.2020 OETF, Gamma 2.2 Inverse} =
BT.2020 OETF
│ ├───Color Operation 250
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D LUT
│ │ ├───"BYPASS" (atomic): range [0, 1] = 0
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 257
│ │ ├───"SIZE" (atomic, immutable): range [0,
UINT32_MAX] = 4096
│ │ ├───"LUT1D_INTERPOLATION": enum {Linear} =
Linear
│ │ └───"DATA" (atomic): blob = 455
│ ├───Color Operation 257
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 3D LUT
│ │ ├───"BYPASS" (atomic): range [0, 1] = 0
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 264
│ │ ├───"SIZE" (atomic, immutable): range [0,
UINT32_MAX] = 17
│ │ ├───"LUT3D_INTERPOLATION": enum
{Tetrahedral} = Tetrahedral
│ │ └───"DATA" (atomic): blob = 456
│ ├───Color Operation 264
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ │ ├───"BYPASS" (atomic): range [0, 1] = 0
│ │ ├───"NEXT" (atomic, immutable): object
colorop = 269
│ │ └───"CURVE_1D_TYPE" (atomic): enum {sRGB
EOTF, PQ 125 EOTF, BT.2020 Inverse OETF, Gamma 2.2} = PQ 125 EOTF
│ └───Color Operation 269
│ └───Properties
│ ├───"TYPE" (immutable): enum {1D Curve, 1D
LUT, 3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D LUT
│ ├───"BYPASS" (atomic): range [0, 1] = 1
│ ├───"NEXT" (atomic, immutable): object
colorop = 0
│ ├───"SIZE" (atomic, immutable): range [0,
UINT32_MAX] = 4096
│ ├───"LUT1D_INTERPOLATION": enum {Linear} =
Linear
│ └───"DATA" (atomic): blob = 0
[1] https://gitlab.freedesktop.org/mwen/drm-misc/-/commits/amd_fm_colorop
[2]
https://github.com/melissawen/gamescope/commit/c49e8b78e28a144b8a9f908e20430b3b7b832179
I didn't review the VKMS patches. After renaming, AMD part LGTM.
Melissa
>
> Cc: Alex Hung <alex.hung@amd.com>
> Cc: Daniel Stone <daniels@collabora.com>
> Cc: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
> Cc: Uma Shankar <uma.shankar@intel.com>
> Cc: Louis Chauvet <louis.chauvet@bootlin.com>
> Cc: Melissa Wen <mwen@igalia.com>
> Cc: Simon Ser <contact@emersion.fr>
>
> Chaitanya Kumar Borah (1):
> drm/colorop: Add DRM_COLOROP_CSC_FF
>
> Harry Wentland (8):
> drm/colorop: Add limited-range YUV-to-RGB CSC FF enum values
> drm/vkms: Add CSC FF colorop to color pipeline
> drm/vkms: Add atomic check and matrix handling for CSC FF colorop
> drm/amd/display: Add CSC FF colorop to color pipeline
> drm/amd/display: Implement CSC FF colorop color space mapping
> drm/amd/display: Use GAMCOR for first TF if CSC is used
> drm/amd/display: Check actual state during commit_tail
> drm/amd/display: Set color_space to plane_infos
>
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 ++-
> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 102 ++++++++++++++++-
> .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 27 ++++-
> .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h | 1 +
> drivers/gpu/drm/drm_atomic.c | 4 +
> drivers/gpu/drm/drm_atomic_uapi.c | 4 +
> drivers/gpu/drm/drm_colorop.c | 108 ++++++++++++++++++
> drivers/gpu/drm/vkms/vkms_colorop.c | 66 +++++++----
> drivers/gpu/drm/vkms/vkms_composer.c | 6 +
> drivers/gpu/drm/vkms/vkms_plane.c | 70 +++++++++++-
> include/drm/drm_colorop.h | 102 +++++++++++++++++
> include/uapi/drm/drm_mode.h | 13 +++
> 12 files changed, 487 insertions(+), 30 deletions(-)
>
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 26+ messages in thread