On Thursday, 26 March 2026 12:16:12 Central European Standard Time Dave Stevenson wrote: > On Wed, 25 Mar 2026 at 13:43, Ville Syrjälä > <[email protected]> wrote: > > > > On Wed, Mar 25, 2026 at 12:49:19PM +0000, Dave Stevenson wrote: > > > On Tue, 24 Mar 2026 at 16:02, Nicolas Frattaroli > > > <[email protected]> wrote: > > > > > > > > Add a new general DRM property named "color format" which can be used by > > > > userspace to request the display driver to output a particular color > > > > format. > > > > > > > > Possible options are: > > > > - auto (setup by default, driver internally picks the color format) > > > > - rgb > > > > - ycbcr444 > > > > - ycbcr422 > > > > - ycbcr420 > > > > > > > > Drivers should advertise from this list which formats they support. > > > > Together with this list and EDID data from the sink we should be able > > > > to relay a list of usable color formats to users to pick from. > > > > > > > > Co-developed-by: Werner Sembach <[email protected]> > > > > Signed-off-by: Werner Sembach <[email protected]> > > > > Co-developed-by: Andri Yngvason <[email protected]> > > > > Signed-off-by: Andri Yngvason <[email protected]> > > > > Signed-off-by: Marius Vlad <[email protected]> > > > > Reviewed-by: Maxime Ripard <[email protected]> > > > > Signed-off-by: Nicolas Frattaroli <[email protected]> > > > > --- > > > > drivers/gpu/drm/drm_atomic_helper.c | 5 ++ > > > > drivers/gpu/drm/drm_atomic_uapi.c | 11 ++++ > > > > drivers/gpu/drm/drm_connector.c | 108 > > > > ++++++++++++++++++++++++++++++++++++ > > > > include/drm/drm_connector.h | 104 > > > > ++++++++++++++++++++++++++++++++++ > > > > 4 files changed, 228 insertions(+) > > > > > > > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > > > > b/drivers/gpu/drm/drm_atomic_helper.c > > > > index 26953ed6b53e..b7753454b777 100644 > > > > --- a/drivers/gpu/drm/drm_atomic_helper.c > > > > +++ b/drivers/gpu/drm/drm_atomic_helper.c > > > > @@ -737,6 +737,11 @@ drm_atomic_helper_check_modeset(struct drm_device > > > > *dev, > > > > if (old_connector_state->max_requested_bpc != > > > > new_connector_state->max_requested_bpc) > > > > new_crtc_state->connectors_changed = > > > > true; > > > > + > > > > + if (old_connector_state->color_format != > > > > + new_connector_state->color_format) > > > > + new_crtc_state->connectors_changed = > > > > true; > > > > + > > > > } > > > > > > > > if (funcs->atomic_check) > > > > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c > > > > b/drivers/gpu/drm/drm_atomic_uapi.c > > > > index 5bd5bf6661df..dee510c85e59 100644 > > > > --- a/drivers/gpu/drm/drm_atomic_uapi.c > > > > +++ b/drivers/gpu/drm/drm_atomic_uapi.c > > > > @@ -935,6 +935,15 @@ static int > > > > drm_atomic_connector_set_property(struct drm_connector *connector, > > > > state->privacy_screen_sw_state = val; > > > > } else if (property == connector->broadcast_rgb_property) { > > > > state->hdmi.broadcast_rgb = val; > > > > + } else if (property == connector->color_format_property) { > > > > + if (val > INT_MAX || > > > > !drm_connector_color_format_valid(val)) { > > > > + drm_dbg_atomic(connector->dev, > > > > + "[CONNECTOR:%d:%s] unknown color > > > > format %llu\n", > > > > + connector->base.id, > > > > connector->name, val); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + state->color_format = val; > > > > } else if (connector->funcs->atomic_set_property) { > > > > return connector->funcs->atomic_set_property(connector, > > > > state, property, val); > > > > @@ -1020,6 +1029,8 @@ drm_atomic_connector_get_property(struct > > > > drm_connector *connector, > > > > *val = state->privacy_screen_sw_state; > > > > } else if (property == connector->broadcast_rgb_property) { > > > > *val = state->hdmi.broadcast_rgb; > > > > + } else if (property == connector->color_format_property) { > > > > + *val = state->color_format; > > > > } else if (connector->funcs->atomic_get_property) { > > > > return connector->funcs->atomic_get_property(connector, > > > > state, property, val); > > > > diff --git a/drivers/gpu/drm/drm_connector.c > > > > b/drivers/gpu/drm/drm_connector.c > > > > index 47dc53c4a738..e848374dee0b 100644 > > > > --- a/drivers/gpu/drm/drm_connector.c > > > > +++ b/drivers/gpu/drm/drm_connector.c > > > > @@ -1388,6 +1388,18 @@ static const u32 hdmi_colorspaces = > > > > BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) | > > > > BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER); > > > > > > > > +static const u32 hdmi_colorformats = > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) | > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420); > > > > + > > > > +static const u32 dp_colorformats = > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) | > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | > > > > + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420); > > > > + > > > > /* > > > > * As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel > > > > Encoding/Colorimetry > > > > * Format Table 2-120 > > > > @@ -2940,6 +2952,102 @@ int > > > > drm_connector_attach_colorspace_property(struct drm_connector > > > > *connector) > > > > } > > > > EXPORT_SYMBOL(drm_connector_attach_colorspace_property); > > > > > > > > +/** > > > > + * drm_connector_attach_color_format_property - create and attach > > > > color format property > > > > + * @connector: connector to create the color format property on > > > > + * @supported_color_formats: bitmask of bit-shifted &enum > > > > drm_output_color_format > > > > + * values the connector supports > > > > + * > > > > + * Called by a driver to create a color format property. The property > > > > is > > > > + * attached to the connector automatically on success. > > > > + * > > > > + * @supported_color_formats should only include color formats the > > > > connector > > > > + * type can actually support. > > > > + * > > > > + * Returns: > > > > + * 0 on success, negative errno on error > > > > + */ > > > > +int drm_connector_attach_color_format_property(struct drm_connector > > > > *connector, > > > > + unsigned long > > > > supported_color_formats) > > > > +{ > > > > + struct drm_device *dev = connector->dev; > > > > + struct drm_prop_enum_list > > > > enum_list[DRM_CONNECTOR_COLOR_FORMAT_COUNT]; > > > > + unsigned int i = 0; > > > > + unsigned long fmt; > > > > + > > > > + if (connector->color_format_property) > > > > + return 0; > > > > + > > > > + if (!supported_color_formats) { > > > > + drm_err(dev, "No supported color formats provided on > > > > [CONNECTOR:%d:%s]\n", > > > > + connector->base.id, connector->name); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + if (supported_color_formats & > > > > ~GENMASK(DRM_OUTPUT_COLOR_FORMAT_COUNT - 1, 0)) { > > > > + drm_err(dev, "Unknown color formats provided on > > > > [CONNECTOR:%d:%s]\n", > > > > + connector->base.id, connector->name); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + switch (connector->connector_type) { > > > > + case DRM_MODE_CONNECTOR_HDMIA: > > > > + case DRM_MODE_CONNECTOR_HDMIB: > > > > + if (supported_color_formats & ~hdmi_colorformats) { > > > > + drm_err(dev, "Color formats not allowed for > > > > HDMI on [CONNECTOR:%d:%s]\n", > > > > + connector->base.id, connector->name); > > > > + return -EINVAL; > > > > + } > > > > + break; > > > > + case DRM_MODE_CONNECTOR_DisplayPort: > > > > + case DRM_MODE_CONNECTOR_eDP: > > > > + if (supported_color_formats & ~dp_colorformats) { > > > > + drm_err(dev, "Color formats not allowed for DP > > > > on [CONNECTOR:%d:%s]\n", > > > > + connector->base.id, connector->name); > > > > + return -EINVAL; > > > > + } > > > > + break; > > > > + } > > > > + > > > > + enum_list[0].name = "AUTO"; > > > > + enum_list[0].type = DRM_CONNECTOR_COLOR_FORMAT_AUTO; > > > > + > > > > + for_each_set_bit(fmt, &supported_color_formats, > > > > DRM_OUTPUT_COLOR_FORMAT_COUNT) { > > > > + switch (fmt) { > > > > + case DRM_OUTPUT_COLOR_FORMAT_RGB444: > > > > + enum_list[++i].type = > > > > DRM_CONNECTOR_COLOR_FORMAT_RGB444; > > > > + break; > > > > + case DRM_OUTPUT_COLOR_FORMAT_YCBCR444: > > > > + enum_list[++i].type = > > > > DRM_CONNECTOR_COLOR_FORMAT_YCBCR444; > > > > + break; > > > > + case DRM_OUTPUT_COLOR_FORMAT_YCBCR422: > > > > + enum_list[++i].type = > > > > DRM_CONNECTOR_COLOR_FORMAT_YCBCR422; > > > > + break; > > > > + case DRM_OUTPUT_COLOR_FORMAT_YCBCR420: > > > > + enum_list[++i].type = > > > > DRM_CONNECTOR_COLOR_FORMAT_YCBCR420; > > > > + break; > > > > + default: > > > > + drm_warn(dev, "Unknown supported format %ld on > > > > [CONNECTOR:%d:%s]\n", > > > > + fmt, connector->base.id, > > > > connector->name); > > > > + continue; > > > > + } > > > > + enum_list[i].name = > > > > drm_hdmi_connector_get_output_format_name(fmt); > > > > + } > > > > + > > > > + connector->color_format_property = > > > > + drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, > > > > "color format", > > > > + enum_list, i + 1); > > > > + > > > > + if (!connector->color_format_property) > > > > + return -ENOMEM; > > > > + > > > > + drm_object_attach_property(&connector->base, > > > > connector->color_format_property, > > > > + DRM_CONNECTOR_COLOR_FORMAT_AUTO); > > > > + > > > > + return 0; > > > > +} > > > > +EXPORT_SYMBOL(drm_connector_attach_color_format_property); > > > > + > > > > /** > > > > * drm_connector_atomic_hdr_metadata_equal - checks if the hdr > > > > metadata changed > > > > * @old_state: old connector state to compare > > > > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h > > > > index af8b92d2d5b7..bd549f912b76 100644 > > > > --- a/include/drm/drm_connector.h > > > > +++ b/include/drm/drm_connector.h > > > > @@ -571,14 +571,102 @@ enum drm_colorspace { > > > > * YCbCr 4:2:2 output format (ie. with horizontal subsampling) > > > > * @DRM_OUTPUT_COLOR_FORMAT_YCBCR420: > > > > * YCbCr 4:2:0 output format (ie. with horizontal and vertical > > > > subsampling) > > > > + * @DRM_OUTPUT_COLOR_FORMAT_COUNT: > > > > + * Number of valid output color format values in this enum > > > > */ > > > > enum drm_output_color_format { > > > > DRM_OUTPUT_COLOR_FORMAT_RGB444 = 0, > > > > DRM_OUTPUT_COLOR_FORMAT_YCBCR444, > > > > DRM_OUTPUT_COLOR_FORMAT_YCBCR422, > > > > DRM_OUTPUT_COLOR_FORMAT_YCBCR420, > > > > + DRM_OUTPUT_COLOR_FORMAT_COUNT, > > > > }; > > > > > > > > +/** > > > > + * enum drm_connector_color_format - Connector Color Format Request > > > > + * > > > > + * This enum, unlike &enum drm_output_color_format, is used to specify > > > > requests > > > > + * for a specific color format on a connector through the DRM "color > > > > format" > > > > + * property. The difference is that it has an "AUTO" value to specify > > > > that > > > > + * no specific choice has been made. > > > > + */ > > > > +enum drm_connector_color_format { > > > > + /** > > > > + * @DRM_CONNECTOR_COLOR_FORMAT_AUTO: The driver or display > > > > protocol > > > > + * helpers should pick a suitable color format. All > > > > implementations of a > > > > + * specific display protocol must behave the same way with > > > > "AUTO", but > > > > + * different display protocols do not necessarily have the same > > > > "AUTO" > > > > + * semantics. > > > > + * > > > > + * For HDMI, "AUTO" picks RGB, but falls back to YCbCr 4:2:0 if > > > > the > > > > + * bandwidth required for full-scale RGB is not available, or > > > > the mode > > > > + * is YCbCr 4:2:0-only, as long as the mode and output both > > > > support > > > > + * YCbCr 4:2:0. > > > > > > Is there a reason you propose dropping back to YCbCr 4:2:0 without > > > trying YCbCr 4:2:2 first? Minimising the subsampling is surely > > > beneficial, and vc4 for one can do 4:2:2 but not 4:2:0. > > > > On HDMI 4:2:2 is always 12bpc, so it doesn't save any bandwidth > > compared to 8bpc 4:4:4. > > It does save bandwidth against 10 or 12bpc RGB 4:4:4. > > Or is the implication that max_bpc = 12 and > DRM_CONNECTOR_COLOR_FORMAT_AUTO should drop bpc down to 8 and select > RGB in preference to selecting 4:2:2?
Yes. Some people consider max-bpc to not be a legitimate way of requesting an actual bpc, and don't think drivers will choose the highest bpc <= max-bpc, and instead may negotiate a fantasy number anywhere below or equal to max-bpc. Of course this logic could be done in userspace which knows whether the less chroma for more bit depth trade-off is worth it, but userspace does not know the negotiated link bpc, and my attempts at adding a property for it are being blocked. > > Dave > > > -- > > Ville Syrjälä > > Intel >
