On Mon, Jan 15, 2024 at 03:33:08PM +0100, Sebastian Wick wrote:
> On Thu, Dec 07, 2023 at 04:49:31PM +0100, Maxime Ripard wrote:
> > The i915 driver has a property to force the RGB range of an HDMI output.
> > The vc4 driver then implemented the same property with the same
> > semantics. KWin has support for it, and a PR for mutter is also there to
> > support it.
> > 
> > Both drivers implementing the same property with the same semantics,
> > plus the userspace having support for it, is proof enough that it's
> > pretty much a de-facto standard now and we can provide helpers for it.
> > 
> > Let's plumb it into the newly created HDMI connector.
> > 
> > Signed-off-by: Maxime Ripard <[email protected]>
> > ---
> >  Documentation/gpu/kms-properties.csv               |   1 -
> >  drivers/gpu/drm/drm_atomic.c                       |   5 +
> >  drivers/gpu/drm/drm_atomic_state_helper.c          |  17 +
> >  drivers/gpu/drm/drm_atomic_uapi.c                  |   4 +
> >  drivers/gpu/drm/drm_connector.c                    |  76 +++++
> >  drivers/gpu/drm/tests/Makefile                     |   1 +
> >  .../gpu/drm/tests/drm_atomic_state_helper_test.c   | 376 
> > +++++++++++++++++++++
> >  drivers/gpu/drm/tests/drm_connector_test.c         | 117 ++++++-
> >  drivers/gpu/drm/tests/drm_kunit_edid.h             | 106 ++++++
> >  include/drm/drm_connector.h                        |  36 ++
> >  10 files changed, 737 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/gpu/kms-properties.csv 
> > b/Documentation/gpu/kms-properties.csv
> > index 0f9590834829..caef14c532d4 100644
> > --- a/Documentation/gpu/kms-properties.csv
> > +++ b/Documentation/gpu/kms-properties.csv
> > @@ -17,7 +17,6 @@ Owner Module/Drivers,Group,Property Name,Type,Property 
> > Values,Object attached,De
> >  ,Virtual GPU,“suggested X”,RANGE,"Min=0, 
> > Max=0xffffffff",Connector,property to suggest an X offset for a connector
> >  ,,“suggested Y”,RANGE,"Min=0, Max=0xffffffff",Connector,property to 
> > suggest an Y offset for a connector
> >  ,Optional,"""aspect ratio""",ENUM,"{ ""None"", ""4:3"", ""16:9"" 
> > }",Connector,TDB
> > -i915,Generic,"""Broadcast RGB""",ENUM,"{ ""Automatic"", ""Full"", 
> > ""Limited 16:235"" }",Connector,"When this property is set to Limited 
> > 16:235 and CTM is set, the hardware will be programmed with the result of 
> > the multiplication of CTM by the limited range matrix to ensure the pixels 
> > normally in the range 0..1.0 are remapped to the range 16/255..235/255."
> >  ,,“audio”,ENUM,"{ ""force-dvi"", ""off"", ""auto"", ""on"" }",Connector,TBD
> >  ,SDVO-TV,“mode”,ENUM,"{ ""NTSC_M"", ""NTSC_J"", ""NTSC_443"", ""PAL_B"" } 
> > etc.",Connector,TBD
> >  ,,"""left_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
> > diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> > index c31fc0b48c31..1465a7f09a0b 100644
> > --- a/drivers/gpu/drm/drm_atomic.c
> > +++ b/drivers/gpu/drm/drm_atomic.c
> > @@ -1142,6 +1142,11 @@ static void drm_atomic_connector_print_state(struct 
> > drm_printer *p,
> >     drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
> >     drm_printf(p, "\tcolorspace=%s\n", 
> > drm_get_colorspace_name(state->colorspace));
> >  
> > +   if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
> > +       connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
> > +           drm_printf(p, "\tbroadcast_rgb=%s\n",
> > +                      
> > drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb));
> > +
> >     if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
> >             if (state->writeback_job && state->writeback_job->fb)
> >                     drm_printf(p, "\tfb=%d\n", 
> > state->writeback_job->fb->base.id);
> > diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> > b/drivers/gpu/drm/drm_atomic_state_helper.c
> > index e69c0cc1c6da..10d98620a358 100644
> > --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> > +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> > @@ -583,6 +583,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
> >  void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector 
> > *connector,
> >                                           struct drm_connector_state 
> > *new_state)
> >  {
> > +   new_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;
> >  }
> >  EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);
> >  
> > @@ -650,6 +651,22 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
> >  int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
> >                                        struct drm_atomic_state *state)
> >  {
> > +   struct drm_connector_state *old_state =
> > +           drm_atomic_get_old_connector_state(state, connector);
> > +   struct drm_connector_state *new_state =
> > +           drm_atomic_get_new_connector_state(state, connector);
> > +
> > +   if (old_state->hdmi.broadcast_rgb != new_state->hdmi.broadcast_rgb) {
> > +           struct drm_crtc *crtc = new_state->crtc;
> > +           struct drm_crtc_state *crtc_state;
> > +
> > +           crtc_state = drm_atomic_get_crtc_state(state, crtc);
> > +           if (IS_ERR(crtc_state))
> > +                   return PTR_ERR(crtc_state);
> > +
> > +           crtc_state->mode_changed = true;
> > +   }
> > +
> >     return 0;
> >  }
> >  EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);
> > diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
> > b/drivers/gpu/drm/drm_atomic_uapi.c
> > index aee4a65d4959..3eb4f4bc8b71 100644
> > --- a/drivers/gpu/drm/drm_atomic_uapi.c
> > +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> > @@ -818,6 +818,8 @@ static int drm_atomic_connector_set_property(struct 
> > drm_connector *connector,
> >             state->max_requested_bpc = val;
> >     } else if (property == connector->privacy_screen_sw_state_property) {
> >             state->privacy_screen_sw_state = val;
> > +   } else if (property == connector->broadcast_rgb_property) {
> > +           state->hdmi.broadcast_rgb = val;
> >     } else if (connector->funcs->atomic_set_property) {
> >             return connector->funcs->atomic_set_property(connector,
> >                             state, property, val);
> > @@ -901,6 +903,8 @@ drm_atomic_connector_get_property(struct drm_connector 
> > *connector,
> >             *val = state->max_requested_bpc;
> >     } else if (property == connector->privacy_screen_sw_state_property) {
> >             *val = state->privacy_screen_sw_state;
> > +   } else if (property == connector->broadcast_rgb_property) {
> > +           *val = state->hdmi.broadcast_rgb;
> >     } 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 d9961cce8245..929b0a911f62 100644
> > --- a/drivers/gpu/drm/drm_connector.c
> > +++ b/drivers/gpu/drm/drm_connector.c
> > @@ -1183,6 +1183,29 @@ static const u32 dp_colorspaces =
> >     BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) |
> >     BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
> >  
> > +static const struct drm_prop_enum_list broadcast_rgb_names[] = {
> > +   { DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic" },
> > +   { DRM_HDMI_BROADCAST_RGB_FULL, "Full" },
> > +   { DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" },
> > +};
> > +
> > +/*
> > + * drm_hdmi_connector_get_broadcast_rgb_name - Return a string for HDMI 
> > connector RGB broadcast selection
> > + * @broadcast_rgb: Broadcast RGB selection to compute name of
> > + *
> > + * Returns: the name of the Broadcast RGB selection, or NULL if the type
> > + * is not valid.
> > + */
> > +const char *
> > +drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb 
> > broadcast_rgb)
> > +{
> > +   if (broadcast_rgb > DRM_HDMI_BROADCAST_RGB_LIMITED)
> > +           return NULL;
> > +
> > +   return broadcast_rgb_names[broadcast_rgb].name;
> > +}
> > +EXPORT_SYMBOL(drm_hdmi_connector_get_broadcast_rgb_name);
> > +
> >  /**
> >   * DOC: standard connector properties
> >   *
> > @@ -1655,6 +1678,26 @@ 
> > EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
> >  /**
> >   * DOC: HDMI connector properties
> >   *
> > + * Broadcast RGB
> > + *      Indicates the RGB Quantization Range (Full vs Limited) used.
> > + *      Infoframes will be generated according to that value.
> > + *
> > + *      The value of this property can be one of the following:
> > + *
> > + *      Automatic:
> > + *              RGB Range is selected automatically based on the mode
> > + *              according to the HDMI specifications.
> > + *
> > + *      Full:
> > + *              Full RGB Range is forced.
> > + *
> > + *      Limited 16:235:
> > + *              Limited RGB Range is forced. Unlike the name suggests,
> > + *              this works for any number of bits-per-component.
> > + *
> > + *      Drivers can set up this property by calling
> > + *      drm_connector_attach_broadcast_rgb_property().
> > + *
> 
> This is a good time to document this in more detail. There might be two
> different things being affected:
> 
> 1. The signalling (InfoFrame/SDP/...)
> 2. The color pipeline processing
> 
> All values of Broadcast RGB always affect the color pipeline processing
> such that a full-range input to the CRTC is converted to either full- or
> limited-range, depending on what the monitor is supposed to accept.
> 
> When automatic is selected, does that mean that there is no signalling,
> or that the signalling matches what the monitor is supposed to accept
> according to the spec? Also, is this really HDMI specific?
> 
> When full or limited is selected and the monitor doesn't support the
> signalling, what happens?

Forgot to mention: user-space still has no control over RGB vs YCbCr on
the cable, so is this only affecting RGB? If not, how does it affect
YCbCr?

> 
> >   * content type (HDMI specific):
> >   * Indicates content type setting to be used in HDMI infoframes to indicate
> >   * content type for the external device, so that it adjusts its display
> > @@ -2517,6 +2560,39 @@ int 
> > drm_connector_attach_hdr_output_metadata_property(struct drm_connector *conn
> >  }
> >  EXPORT_SYMBOL(drm_connector_attach_hdr_output_metadata_property);
> >  
> > +/**
> > + * drm_connector_attach_broadcast_rgb_property - attach "Broadcast RGB" 
> > property
> > + * @connector: connector to attach the property on.
> > + *
> > + * This is used to add support for forcing the RGB range on a connector
> > + *
> > + * Returns:
> > + * Zero on success, negative errno on failure.
> > + */
> > +int drm_connector_attach_broadcast_rgb_property(struct drm_connector 
> > *connector)
> > +{
> > +   struct drm_device *dev = connector->dev;
> > +   struct drm_property *prop;
> > +
> > +   prop = connector->broadcast_rgb_property;
> > +   if (!prop) {
> > +           prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
> > +                                           "Broadcast RGB",
> > +                                           broadcast_rgb_names,
> > +                                           
> > ARRAY_SIZE(broadcast_rgb_names));
> > +           if (!prop)
> > +                   return -EINVAL;
> > +
> > +           connector->broadcast_rgb_property = prop;
> > +   }
> > +
> > +   drm_object_attach_property(&connector->base, prop,
> > +                              DRM_HDMI_BROADCAST_RGB_AUTO);
> > +
> > +   return 0;
> > +}
> > +EXPORT_SYMBOL(drm_connector_attach_broadcast_rgb_property);
> > +
> >  /**
> >   * drm_connector_attach_colorspace_property - attach "Colorspace" property
> >   * @connector: connector to attach the property on.
> > diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
> > index d6183b3d7688..b29ddfd90596 100644
> > --- a/drivers/gpu/drm/tests/Makefile
> > +++ b/drivers/gpu/drm/tests/Makefile
> > @@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST_HELPERS) += \
> >     drm_kunit_helpers.o
> >  
> >  obj-$(CONFIG_DRM_KUNIT_TEST) += \
> > +   drm_atomic_state_helper_test.o \
> >     drm_buddy_test.o \
> >     drm_cmdline_parser_test.o \
> >     drm_connector_test.o \
> > diff --git a/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c 
> > b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> > new file mode 100644
> > index 000000000000..21e6f796ee13
> > --- /dev/null
> > +++ b/drivers/gpu/drm/tests/drm_atomic_state_helper_test.c
> > @@ -0,0 +1,376 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +/*
> > + * Kunit test for drm_atomic_state_helper functions
> > + */
> > +
> > +#include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_state_helper.h>
> > +#include <drm/drm_atomic_uapi.h>
> > +#include <drm/drm_drv.h>
> > +#include <drm/drm_edid.h>
> > +#include <drm/drm_connector.h>
> > +#include <drm/drm_fourcc.h>
> > +#include <drm/drm_kunit_helpers.h>
> > +#include <drm/drm_managed.h>
> > +#include <drm/drm_modeset_helper_vtables.h>
> > +#include <drm/drm_probe_helper.h>
> > +
> > +#include <drm/drm_print.h>
> > +#include "../drm_crtc_internal.h"
> > +
> > +#include <kunit/test.h>
> > +
> > +#include "drm_kunit_edid.h"
> > +
> > +struct drm_atomic_helper_connector_hdmi_priv {
> > +   struct drm_device drm;
> > +   struct drm_plane *plane;
> > +   struct drm_crtc *crtc;
> > +   struct drm_encoder encoder;
> > +   struct drm_connector connector;
> > +
> > +   const char *current_edid;
> > +   size_t current_edid_len;
> > +};
> > +
> > +#define connector_to_priv(c) \
> > +   container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, 
> > connector)
> > +
> > +static struct drm_display_mode *find_preferred_mode(struct drm_connector 
> > *connector)
> > +{
> > +   struct drm_device *drm = connector->dev;
> > +   struct drm_display_mode *mode, *preferred;
> > +
> > +   mutex_lock(&drm->mode_config.mutex);
> > +   preferred = list_first_entry(&connector->modes, struct 
> > drm_display_mode, head);
> > +   list_for_each_entry(mode, &connector->modes, head)
> > +           if (mode->type & DRM_MODE_TYPE_PREFERRED)
> > +                   preferred = mode;
> > +   mutex_unlock(&drm->mode_config.mutex);
> > +
> > +   return preferred;
> > +}
> > +
> > +static int light_up_connector(struct kunit *test,
> > +                         struct drm_device *drm,
> > +                         struct drm_crtc *crtc,
> > +                         struct drm_connector *connector,
> > +                         struct drm_display_mode *mode,
> > +                         struct drm_modeset_acquire_ctx *ctx)
> > +{
> > +   struct drm_atomic_state *state;
> > +   struct drm_connector_state *conn_state;
> > +   struct drm_crtc_state *crtc_state;
> > +   int ret;
> > +
> > +   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> > +
> > +   conn_state = drm_atomic_get_connector_state(state, connector);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
> > +
> > +   ret = drm_atomic_set_crtc_for_connector(conn_state, crtc);
> > +   KUNIT_EXPECT_EQ(test, ret, 0);
> > +
> > +   crtc_state = drm_atomic_get_crtc_state(state, crtc);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
> > +
> > +   ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
> > +   KUNIT_EXPECT_EQ(test, ret, 0);
> > +
> > +   crtc_state->enable = true;
> > +   crtc_state->active = true;
> > +
> > +   ret = drm_atomic_commit(state);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   return 0;
> > +}
> > +
> > +static int set_connector_edid(struct kunit *test, struct drm_connector 
> > *connector,
> > +                         const char *edid, size_t edid_len)
> > +{
> > +   struct drm_atomic_helper_connector_hdmi_priv *priv =
> > +           connector_to_priv(connector);
> > +   struct drm_device *drm = connector->dev;
> > +   int ret;
> > +
> > +   priv->current_edid = edid;
> > +   priv->current_edid_len = edid_len;
> > +
> > +   mutex_lock(&drm->mode_config.mutex);
> > +   ret = connector->funcs->fill_modes(connector, 4096, 4096);
> > +   mutex_unlock(&drm->mode_config.mutex);
> > +   KUNIT_ASSERT_GT(test, ret, 0);
> > +
> > +   return 0;
> > +}
> > +
> > +static int dummy_connector_get_modes(struct drm_connector *connector)
> > +{
> > +   struct drm_atomic_helper_connector_hdmi_priv *priv =
> > +           connector_to_priv(connector);
> > +   const struct drm_edid *edid;
> > +   unsigned int num_modes;
> > +
> > +   edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len);
> > +   if (!edid)
> > +           return -EINVAL;
> > +
> > +   drm_edid_connector_update(connector, edid);
> > +   num_modes = drm_edid_connector_add_modes(connector);
> > +
> > +   drm_edid_free(edid);
> > +
> > +   return num_modes;
> > +}
> > +
> > +static const struct drm_connector_helper_funcs 
> > dummy_connector_helper_funcs = {
> > +   .atomic_check   = drm_atomic_helper_connector_hdmi_check,
> > +   .get_modes      = dummy_connector_get_modes,
> > +};
> > +
> > +static void dummy_hdmi_connector_reset(struct drm_connector *connector)
> > +{
> > +   drm_atomic_helper_connector_reset(connector);
> > +   __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
> > +}
> > +
> > +static const struct drm_connector_funcs dummy_connector_funcs = {
> > +   .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
> > +   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > +   .fill_modes             = drm_helper_probe_single_connector_modes,
> > +   .reset                  = dummy_hdmi_connector_reset,
> > +};
> > +
> > +static
> > +struct drm_atomic_helper_connector_hdmi_priv *
> > +drm_atomic_helper_connector_hdmi_init(struct kunit *test)
> > +{
> > +   struct drm_atomic_helper_connector_hdmi_priv *priv;
> > +   struct drm_connector *conn;
> > +   struct drm_encoder *enc;
> > +   struct drm_device *drm;
> > +   struct device *dev;
> > +   int ret;
> > +
> > +   dev = drm_kunit_helper_alloc_device(test);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
> > +
> > +   priv = drm_kunit_helper_alloc_drm_device(test, dev,
> > +                                            struct 
> > drm_atomic_helper_connector_hdmi_priv, drm,
> > +                                            DRIVER_MODESET | 
> > DRIVER_ATOMIC);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
> > +   test->priv = priv;
> > +
> > +   drm = &priv->drm;
> > +   priv->plane = drm_kunit_helper_create_primary_plane(test, drm,
> > +                                                       NULL,
> > +                                                       NULL,
> > +                                                       NULL, 0,
> > +                                                       NULL);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane);
> > +
> > +   priv->crtc = drm_kunit_helper_create_crtc(test, drm,
> > +                                             priv->plane, NULL,
> > +                                             NULL,
> > +                                             NULL);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc);
> > +
> > +   enc = &priv->encoder;
> > +   ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   enc->possible_crtcs = drm_crtc_mask(priv->crtc);
> > +
> > +   conn = &priv->connector;
> > +   ret = drmm_connector_hdmi_init(drm, conn,
> > +                                  &dummy_connector_funcs,
> > +                                  DRM_MODE_CONNECTOR_HDMIA,
> > +                                  NULL);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   drm_connector_helper_add(conn, &dummy_connector_helper_funcs);
> > +   drm_connector_attach_encoder(conn, enc);
> > +
> > +   drm_mode_config_reset(drm);
> > +
> > +   ret = set_connector_edid(test, conn,
> > +                            test_edid_hdmi_1080p_rgb_max_200mhz,
> > +                            
> > ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   return priv;
> > +}
> > +
> > +/*
> > + * Test that if we change the RGB quantization property to a different
> > + * value, we trigger a mode change on the connector's CRTC, which will
> > + * in turn disable/enable the connector.
> > + */
> > +static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit 
> > *test)
> > +{
> > +   struct drm_atomic_helper_connector_hdmi_priv *priv;
> > +   struct drm_modeset_acquire_ctx *ctx;
> > +   struct drm_connector_state *old_conn_state;
> > +   struct drm_connector_state *new_conn_state;
> > +   struct drm_crtc_state *crtc_state;
> > +   struct drm_atomic_state *state;
> > +   struct drm_display_mode *preferred;
> > +   struct drm_connector *conn;
> > +   struct drm_device *drm;
> > +   struct drm_crtc *crtc;
> > +   int ret;
> > +
> > +   priv = drm_atomic_helper_connector_hdmi_init(test);
> > +   KUNIT_ASSERT_NOT_NULL(test, priv);
> > +
> > +   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
> > +
> > +   conn = &priv->connector;
> > +   preferred = find_preferred_mode(conn);
> > +   KUNIT_ASSERT_NOT_NULL(test, preferred);
> > +
> > +   drm = &priv->drm;
> > +   crtc = priv->crtc;
> > +   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> > +
> > +   new_conn_state = drm_atomic_get_connector_state(state, conn);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
> > +
> > +   old_conn_state = drm_atomic_get_old_connector_state(state, conn);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
> > +
> > +   new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
> > +
> > +   KUNIT_ASSERT_NE(test,
> > +                   old_conn_state->hdmi.broadcast_rgb,
> > +                   new_conn_state->hdmi.broadcast_rgb);
> > +
> > +   ret = drm_atomic_check_only(state);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   new_conn_state = drm_atomic_get_new_connector_state(state, conn);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
> > +   KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, 
> > DRM_HDMI_BROADCAST_RGB_FULL);
> > +
> > +   crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
> > +   KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
> > +}
> > +
> > +/*
> > + * Test that if we set the RGB quantization property to the same value,
> > + * we don't trigger a mode change on the connector's CRTC and leave the
> > + * connector unaffected.
> > + */
> > +static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct 
> > kunit *test)
> > +{
> > +   struct drm_atomic_helper_connector_hdmi_priv *priv;
> > +   struct drm_modeset_acquire_ctx *ctx;
> > +   struct drm_connector_state *old_conn_state;
> > +   struct drm_connector_state *new_conn_state;
> > +   struct drm_crtc_state *crtc_state;
> > +   struct drm_atomic_state *state;
> > +   struct drm_display_mode *preferred;
> > +   struct drm_connector *conn;
> > +   struct drm_device *drm;
> > +   struct drm_crtc *crtc;
> > +   int ret;
> > +
> > +   priv = drm_atomic_helper_connector_hdmi_init(test);
> > +   KUNIT_ASSERT_NOT_NULL(test, priv);
> > +
> > +   ctx = drm_kunit_helper_acquire_ctx_alloc(test);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
> > +
> > +   conn = &priv->connector;
> > +   preferred = find_preferred_mode(conn);
> > +   KUNIT_ASSERT_NOT_NULL(test, preferred);
> > +
> > +   drm = &priv->drm;
> > +   crtc = priv->crtc;
> > +   ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
> > +
> > +   new_conn_state = drm_atomic_get_connector_state(state, conn);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
> > +
> > +   old_conn_state = drm_atomic_get_old_connector_state(state, conn);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
> > +
> > +   new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb;
> > +
> > +   ret = drm_atomic_check_only(state);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   old_conn_state = drm_atomic_get_old_connector_state(state, conn);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
> > +
> > +   new_conn_state = drm_atomic_get_new_connector_state(state, conn);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
> > +
> > +   KUNIT_EXPECT_EQ(test,
> > +                   old_conn_state->hdmi.broadcast_rgb,
> > +                   new_conn_state->hdmi.broadcast_rgb);
> > +
> > +   crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> > +   KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
> > +   KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
> > +}
> > +
> > +static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = {
> > +   KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed),
> > +   KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed),
> > +   { }
> > +};
> > +
> > +static struct kunit_suite 
> > drm_atomic_helper_connector_hdmi_check_test_suite = {
> > +   .name           = "drm_atomic_helper_connector_hdmi_check",
> > +   .test_cases     = drm_atomic_helper_connector_hdmi_check_tests,
> > +};
> > +
> > +/*
> > + * Test that the value of the Broadcast RGB property out of reset is set
> > + * to auto.
> > + */
> > +static void drm_test_check_broadcast_rgb_value(struct kunit *test)
> > +{
> > +   struct drm_atomic_helper_connector_hdmi_priv *priv;
> > +   struct drm_connector_state *conn_state;
> > +   struct drm_connector *conn;
> > +
> > +   priv = drm_atomic_helper_connector_hdmi_init(test);
> > +   KUNIT_ASSERT_NOT_NULL(test, priv);
> > +
> > +   conn = &priv->connector;
> > +   conn_state = conn->state;
> > +   KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, 
> > DRM_HDMI_BROADCAST_RGB_AUTO);
> > +}
> > +
> > +static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = {
> > +   KUNIT_CASE(drm_test_check_broadcast_rgb_value),
> > +   { }
> > +};
> > +
> > +static struct kunit_suite 
> > drm_atomic_helper_connector_hdmi_reset_test_suite = {
> > +   .name           = "drm_atomic_helper_connector_hdmi_reset",
> > +   .test_cases     = drm_atomic_helper_connector_hdmi_reset_tests,
> > +};
> > +
> > +kunit_test_suites(
> > +   &drm_atomic_helper_connector_hdmi_check_test_suite,
> > +   &drm_atomic_helper_connector_hdmi_reset_test_suite,
> > +);
> > +
> > +MODULE_AUTHOR("Maxime Ripard <[email protected]>");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/tests/drm_connector_test.c 
> > b/drivers/gpu/drm/tests/drm_connector_test.c
> > index 8f070cacab3b..41d33dea30af 100644
> > --- a/drivers/gpu/drm/tests/drm_connector_test.c
> > +++ b/drivers/gpu/drm/tests/drm_connector_test.c
> > @@ -12,6 +12,8 @@
> >  
> >  #include <kunit/test.h>
> >  
> > +#include "../drm_crtc_internal.h"
> > +
> >  struct drm_connector_init_priv {
> >     struct drm_device drm;
> >     struct drm_connector connector;
> > @@ -357,10 +359,123 @@ static struct kunit_suite 
> > drm_get_tv_mode_from_name_test_suite = {
> >     .test_cases = drm_get_tv_mode_from_name_tests,
> >  };
> >  
> > +struct drm_hdmi_connector_get_broadcast_rgb_name_test {
> > +   unsigned int kind;
> > +   const char *expected_name;
> > +};
> > +
> > +#define BROADCAST_RGB_TEST(_kind, _name)   \
> > +   {                                       \
> > +           .kind = _kind,                  \
> > +           .expected_name = _name,         \
> > +   }
> > +
> > +static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct 
> > kunit *test)
> > +{
> > +   const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
> > +           test->param_value;
> > +
> > +   KUNIT_EXPECT_STREQ(test,
> > +                      
> > drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
> > +                      params->expected_name);
> > +}
> > +
> > +static const
> > +struct drm_hdmi_connector_get_broadcast_rgb_name_test
> > +drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
> > +   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
> > +   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
> > +   BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
> > +};
> > +
> > +static void
> > +drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct 
> > drm_hdmi_connector_get_broadcast_rgb_name_test *t,
> > +                                                char *desc)
> > +{
> > +   sprintf(desc, "%s", t->expected_name);
> > +}
> > +
> > +KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
> > +             drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
> > +             drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
> > +
> > +static void 
> > drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit 
> > *test)
> > +{
> > +   KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
> > +};
> > +
> > +static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] 
> > = {
> > +   KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
> > +                    
> > drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
> > +   KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
> > +   { }
> > +};
> > +
> > +static struct kunit_suite 
> > drm_hdmi_connector_get_broadcast_rgb_name_test_suite = {
> > +   .name = "drm_hdmi_connector_get_broadcast_rgb_name",
> > +   .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
> > +};
> > +
> > +static void drm_test_drm_connector_attach_broadcast_rgb_property(struct 
> > kunit *test)
> > +{
> > +   struct drm_connector_init_priv *priv = test->priv;
> > +   struct drm_connector *connector = &priv->connector;
> > +   struct drm_property *prop;
> > +   int ret;
> > +
> > +   ret = drmm_connector_init(&priv->drm, connector,
> > +                             &dummy_funcs,
> > +                             DRM_MODE_CONNECTOR_HDMIA,
> > +                             &priv->ddc);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   ret = drm_connector_attach_broadcast_rgb_property(connector);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   prop = connector->broadcast_rgb_property;
> > +   KUNIT_ASSERT_NOT_NULL(test, prop);
> > +   KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, 
> > prop->base.id));
> > +}
> > +
> > +static void 
> > drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct 
> > kunit *test)
> > +{
> > +   struct drm_connector_init_priv *priv = test->priv;
> > +   struct drm_connector *connector = &priv->connector;
> > +   struct drm_property *prop;
> > +   int ret;
> > +
> > +   ret = drmm_connector_hdmi_init(&priv->drm, connector,
> > +                                  &dummy_funcs,
> > +                                  DRM_MODE_CONNECTOR_HDMIA,
> > +                                  &priv->ddc);
> > +   KUNIT_EXPECT_EQ(test, ret, 0);
> > +
> > +   ret = drm_connector_attach_broadcast_rgb_property(connector);
> > +   KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > +   prop = connector->broadcast_rgb_property;
> > +   KUNIT_ASSERT_NOT_NULL(test, prop);
> > +   KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, 
> > prop->base.id));
> > +}
> > +
> > +static struct kunit_case 
> > drm_connector_attach_broadcast_rgb_property_tests[] = {
> > +   KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property),
> > +   
> > KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector),
> > +   { }
> > +};
> > +
> > +static struct kunit_suite 
> > drm_connector_attach_broadcast_rgb_property_test_suite = {
> > +   .name = "drm_connector_attach_broadcast_rgb_property",
> > +   .init = drm_test_connector_init,
> > +   .test_cases = drm_connector_attach_broadcast_rgb_property_tests,
> > +};
> > +
> >  kunit_test_suites(
> >     &drmm_connector_hdmi_init_test_suite,
> >     &drmm_connector_init_test_suite,
> > -   &drm_get_tv_mode_from_name_test_suite
> > +   &drm_connector_attach_broadcast_rgb_property_test_suite,
> > +   &drm_get_tv_mode_from_name_test_suite,
> > +   &drm_hdmi_connector_get_broadcast_rgb_name_test_suite
> >  );
> >  
> >  MODULE_AUTHOR("Maxime Ripard <[email protected]>");
> > diff --git a/drivers/gpu/drm/tests/drm_kunit_edid.h 
> > b/drivers/gpu/drm/tests/drm_kunit_edid.h
> > new file mode 100644
> > index 000000000000..2bba316de064
> > --- /dev/null
> > +++ b/drivers/gpu/drm/tests/drm_kunit_edid.h
> > @@ -0,0 +1,106 @@
> > +#ifndef DRM_KUNIT_EDID_H_
> > +#define DRM_KUNIT_EDID_H_
> > +
> > +/*
> > + * edid-decode (hex):
> > + *
> > + * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00
> > + * 00 21 01 03 81 a0 5a 78 02 00 00 00 00 00 00 00
> > + * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01
> > + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
> > + * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73
> > + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32
> > + * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10
> > + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 92
> > + *
> > + * 02 03 1b 81 e3 05 00 20 41 10 e2 00 4a 6d 03 0c
> > + * 00 12 34 00 28 20 00 00 00 00 00 00 00 00 00 00
> > + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> > + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0
> > + *
> > + * ----------------
> > + *
> > + * Block 0, Base EDID:
> > + *   EDID Structure Version & Revision: 1.3
> > + *   Vendor & Product Identification:
> > + *     Manufacturer: LNX
> > + *     Model: 42
> > + *     Made in: 2023
> > + *   Basic Display Parameters & Features:
> > + *     Digital display
> > + *     DFP 1.x compatible TMDS
> > + *     Maximum image size: 160 cm x 90 cm
> > + *     Gamma: 2.20
> > + *     Monochrome or grayscale display
> > + *     First detailed timing is the preferred timing
> > + *   Color Characteristics:
> > + *     Red  : 0.0000, 0.0000
> > + *     Green: 0.0000, 0.0000
> > + *     Blue : 0.0000, 0.0000
> > + *     White: 0.0000, 0.0000
> > + *   Established Timings I & II:
> > + *     DMT 0x04:   640x480    59.940476 Hz   4:3     31.469 kHz     
> > 25.175000 MHz
> > + *   Standard Timings: none
> > + *   Detailed Timing Descriptors:
> > + *     DTD 1:  1920x1080   60.000000 Hz  16:9     67.500 kHz    148.500000 
> > MHz (1600 mm x 900 mm)
> > + *                  Hfront   88 Hsync  44 Hback  148 Hpol P
> > + *                  Vfront    4 Vsync   5 Vback   36 Vpol P
> > + *     Display Product Name: 'Test EDID'
> > + *     Display Range Limits:
> > + *       Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 
> > MHz
> > + *     Dummy Descriptor:
> > + *   Extension blocks: 1
> > + * Checksum: 0x92
> > + *
> > + * ----------------
> > + *
> > + * Block 1, CTA-861 Extension Block:
> > + *   Revision: 3
> > + *   Underscans IT Video Formats by default
> > + *   Native detailed modes: 1
> > + *   Colorimetry Data Block:
> > + *     sRGB
> > + *   Video Data Block:
> > + *     VIC  16:  1920x1080   60.000000 Hz  16:9     67.500 kHz    
> > 148.500000 MHz
> > + *   Video Capability Data Block:
> > + *     YCbCr quantization: No Data
> > + *     RGB quantization: Selectable (via AVI Q)
> > + *     PT scan behavior: No Data
> > + *     IT scan behavior: Always Underscanned
> > + *     CE scan behavior: Always Underscanned
> > + *   Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
> > + *     Source physical address: 1.2.3.4
> > + *     Maximum TMDS clock: 200 MHz
> > + *     Extended HDMI video details:
> > + * Checksum: 0xd0  Unused space in Extension Block: 100 bytes
> > + */
> > +const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz[] = {
> > +  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78,
> > +  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
> > +  0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
> > +  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
> > +  0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
> > +  0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44,
> > +  0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
> > +  0x46, 0x00, 0x00, 0xc4, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
> > +  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x02, 0x03, 0x1b, 0x81,
> > +  0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0x4a, 0x6d, 0x03, 0x0c,
> > +  0x00, 0x12, 0x34, 0x00, 0x28, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +  0x00, 0x00, 0x00, 0xd0
> > +};
> > +
> > +#endif // DRM_KUNIT_EDID_H_
> > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> > index 000a2a156619..3867a4c01b78 100644
> > --- a/include/drm/drm_connector.h
> > +++ b/include/drm/drm_connector.h
> > @@ -368,6 +368,30 @@ enum drm_panel_orientation {
> >     DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
> >  };
> >  
> > +/**
> > + * enum drm_hdmi_broadcast_rgb - Broadcast RGB Selection for an HDMI 
> > @drm_connector
> > + */
> > +enum drm_hdmi_broadcast_rgb {
> > +   /**
> > +    * @DRM_HDMI_BROADCAST_RGB_AUTO: The RGB range is selected
> > +    * automatically based on the mode.
> > +    */
> > +   DRM_HDMI_BROADCAST_RGB_AUTO,
> > +
> > +   /**
> > +    * @DRM_HDMI_BROADCAST_RGB_FULL: Full range RGB is forced.
> > +    */
> > +   DRM_HDMI_BROADCAST_RGB_FULL,
> > +
> > +   /**
> > +    * @DRM_HDMI_BROADCAST_RGB_LIMITED: Limited range RGB is forced.
> > +    */
> > +   DRM_HDMI_BROADCAST_RGB_LIMITED,
> > +};
> > +
> > +const char *
> > +drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb 
> > broadcast_rgb);
> > +
> >  /**
> >   * struct drm_monitor_range_info - Panel's Monitor range in EDID for
> >   * &drm_display_info
> > @@ -1037,6 +1061,11 @@ struct drm_connector_state {
> >      * @drm_atomic_helper_connector_hdmi_check().
> >      */
> >     struct {
> > +           /**
> > +            * @broadcast_rgb: Connector property to pass the
> > +            * Broadcast RGB selection value.
> > +            */
> > +           enum drm_hdmi_broadcast_rgb broadcast_rgb;
> >     } hdmi;
> >  };
> >  
> > @@ -1706,6 +1735,12 @@ struct drm_connector {
> >      */
> >     struct drm_property *privacy_screen_hw_state_property;
> >  
> > +   /**
> > +    * @broadcast_rgb_property: Connector property to set the
> > +    * Broadcast RGB selection to output with.
> > +    */
> > +   struct drm_property *broadcast_rgb_property;
> > +
> >  #define DRM_CONNECTOR_POLL_HPD (1 << 0)
> >  #define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
> >  #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
> > @@ -2026,6 +2061,7 @@ int drm_connector_attach_scaling_mode_property(struct 
> > drm_connector *connector,
> >                                            u32 scaling_mode_mask);
> >  int drm_connector_attach_vrr_capable_property(
> >             struct drm_connector *connector);
> > +int drm_connector_attach_broadcast_rgb_property(struct drm_connector 
> > *connector);
> >  int drm_connector_attach_colorspace_property(struct drm_connector 
> > *connector);
> >  int drm_connector_attach_hdr_output_metadata_property(struct drm_connector 
> > *connector);
> >  bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state 
> > *old_state,
> > 
> > -- 
> > 2.43.0
> > 

Reply via email to