Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/connector: hdmi: Add Broadcast RGB property

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.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Acked-by: Pekka Paalanen <pekka.paalanen@collabora.com>
Reviewed-by: Sebastian Wick <sebastian.wick@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240527-kms-hdmi-connector-state-v15-18-c5af16c3aae2@kernel.org
Signed-off-by: Maxime Ripard <mripard@kernel.org>

+133 -2
-1
Documentation/gpu/kms-properties.csv
··· 17 17 ,Virtual GPU,“suggested X”,RANGE,"Min=0, Max=0xffffffff",Connector,property to suggest an X offset for a connector 18 18 ,,“suggested Y”,RANGE,"Min=0, Max=0xffffffff",Connector,property to suggest an Y offset for a connector 19 19 ,Optional,"""aspect ratio""",ENUM,"{ ""None"", ""4:3"", ""16:9"" }",Connector,TDB 20 - 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." 21 20 ,,“audio”,ENUM,"{ ""force-dvi"", ""off"", ""auto"", ""on"" }",Connector,TBD 22 21 ,SDVO-TV,“mode”,ENUM,"{ ""NTSC_M"", ""NTSC_J"", ""NTSC_443"", ""PAL_B"" } etc.",Connector,TBD 23 22 ,,"""left_margin""",RANGE,"Min=0, Max= SDVO dependent",Connector,TBD
+3 -1
drivers/gpu/drm/display/drm_hdmi_state_helper.c
··· 25 25 26 26 new_conn_state->max_bpc = max_bpc; 27 27 new_conn_state->max_requested_bpc = max_bpc; 28 + new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO; 28 29 } 29 30 EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset); 30 31 ··· 333 332 if (ret) 334 333 return ret; 335 334 336 - if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc || 335 + if (old_conn_state->hdmi.broadcast_rgb != new_conn_state->hdmi.broadcast_rgb || 336 + old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc || 337 337 old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) { 338 338 struct drm_crtc *crtc = new_conn_state->crtc; 339 339 struct drm_crtc_state *crtc_state;
+2
drivers/gpu/drm/drm_atomic.c
··· 1145 1145 1146 1146 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || 1147 1147 connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) { 1148 + drm_printf(p, "\tbroadcast_rgb=%s\n", 1149 + drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb)); 1148 1150 drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc); 1149 1151 drm_printf(p, "\toutput_format=%s\n", 1150 1152 drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
+4
drivers/gpu/drm/drm_atomic_uapi.c
··· 776 776 state->max_requested_bpc = val; 777 777 } else if (property == connector->privacy_screen_sw_state_property) { 778 778 state->privacy_screen_sw_state = val; 779 + } else if (property == connector->broadcast_rgb_property) { 780 + state->hdmi.broadcast_rgb = val; 779 781 } else if (connector->funcs->atomic_set_property) { 780 782 return connector->funcs->atomic_set_property(connector, 781 783 state, property, val); ··· 861 859 *val = state->max_requested_bpc; 862 860 } else if (property == connector->privacy_screen_sw_state_property) { 863 861 *val = state->privacy_screen_sw_state; 862 + } else if (property == connector->broadcast_rgb_property) { 863 + *val = state->hdmi.broadcast_rgb; 864 864 } else if (connector->funcs->atomic_get_property) { 865 865 return connector->funcs->atomic_get_property(connector, 866 866 state, property, val);
+88
drivers/gpu/drm/drm_connector.c
··· 1212 1212 BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) | 1213 1213 BIT(DRM_MODE_COLORIMETRY_BT2020_YCC); 1214 1214 1215 + static const struct drm_prop_enum_list broadcast_rgb_names[] = { 1216 + { DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic" }, 1217 + { DRM_HDMI_BROADCAST_RGB_FULL, "Full" }, 1218 + { DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" }, 1219 + }; 1220 + 1221 + /* 1222 + * drm_hdmi_connector_get_broadcast_rgb_name - Return a string for HDMI connector RGB broadcast selection 1223 + * @broadcast_rgb: Broadcast RGB selection to compute name of 1224 + * 1225 + * Returns: the name of the Broadcast RGB selection, or NULL if the type 1226 + * is not valid. 1227 + */ 1228 + const char * 1229 + drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_rgb) 1230 + { 1231 + if (broadcast_rgb >= ARRAY_SIZE(broadcast_rgb_names)) 1232 + return NULL; 1233 + 1234 + return broadcast_rgb_names[broadcast_rgb].name; 1235 + } 1236 + EXPORT_SYMBOL(drm_hdmi_connector_get_broadcast_rgb_name); 1237 + 1215 1238 static const char * const output_format_str[] = { 1216 1239 [HDMI_COLORSPACE_RGB] = "RGB", 1217 1240 [HDMI_COLORSPACE_YUV420] = "YUV 4:2:0", ··· 1730 1707 1731 1708 /** 1732 1709 * DOC: HDMI connector properties 1710 + * 1711 + * Broadcast RGB (HDMI specific) 1712 + * Indicates the Quantization Range (Full vs Limited) used. The color 1713 + * processing pipeline will be adjusted to match the value of the 1714 + * property, and the Infoframes will be generated and sent accordingly. 1715 + * 1716 + * This property is only relevant if the HDMI output format is RGB. If 1717 + * it's one of the YCbCr variant, it will be ignored. 1718 + * 1719 + * The CRTC attached to the connector must be configured by user-space to 1720 + * always produce full-range pixels. 1721 + * 1722 + * The value of this property can be one of the following: 1723 + * 1724 + * Automatic: 1725 + * The quantization range is selected automatically based on the 1726 + * mode according to the HDMI specifications (HDMI 1.4b - Section 1727 + * 6.6 - Video Quantization Ranges). 1728 + * 1729 + * Full: 1730 + * Full quantization range is forced. 1731 + * 1732 + * Limited 16:235: 1733 + * Limited quantization range is forced. Unlike the name suggests, 1734 + * this works for any number of bits-per-component. 1735 + * 1736 + * Property values other than Automatic can result in colors being off (if 1737 + * limited is selected but the display expects full), or a black screen 1738 + * (if full is selected but the display expects limited). 1739 + * 1740 + * Drivers can set up this property by calling 1741 + * drm_connector_attach_broadcast_rgb_property(). 1733 1742 * 1734 1743 * content type (HDMI specific): 1735 1744 * Indicates content type setting to be used in HDMI infoframes to indicate ··· 2624 2569 return 0; 2625 2570 } 2626 2571 EXPORT_SYMBOL(drm_connector_attach_hdr_output_metadata_property); 2572 + 2573 + /** 2574 + * drm_connector_attach_broadcast_rgb_property - attach "Broadcast RGB" property 2575 + * @connector: connector to attach the property on. 2576 + * 2577 + * This is used to add support for forcing the RGB range on a connector 2578 + * 2579 + * Returns: 2580 + * Zero on success, negative errno on failure. 2581 + */ 2582 + int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector) 2583 + { 2584 + struct drm_device *dev = connector->dev; 2585 + struct drm_property *prop; 2586 + 2587 + prop = connector->broadcast_rgb_property; 2588 + if (!prop) { 2589 + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, 2590 + "Broadcast RGB", 2591 + broadcast_rgb_names, 2592 + ARRAY_SIZE(broadcast_rgb_names)); 2593 + if (!prop) 2594 + return -EINVAL; 2595 + 2596 + connector->broadcast_rgb_property = prop; 2597 + } 2598 + 2599 + drm_object_attach_property(&connector->base, prop, 2600 + DRM_HDMI_BROADCAST_RGB_AUTO); 2601 + 2602 + return 0; 2603 + } 2604 + EXPORT_SYMBOL(drm_connector_attach_broadcast_rgb_property); 2627 2605 2628 2606 /** 2629 2607 * drm_connector_attach_colorspace_property - attach "Colorspace" property
+36
include/drm/drm_connector.h
··· 369 369 DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, 370 370 }; 371 371 372 + /** 373 + * enum drm_hdmi_broadcast_rgb - Broadcast RGB Selection for an HDMI @drm_connector 374 + */ 375 + enum drm_hdmi_broadcast_rgb { 376 + /** 377 + * @DRM_HDMI_BROADCAST_RGB_AUTO: The RGB range is selected 378 + * automatically based on the mode. 379 + */ 380 + DRM_HDMI_BROADCAST_RGB_AUTO, 381 + 382 + /** 383 + * @DRM_HDMI_BROADCAST_RGB_FULL: Full range RGB is forced. 384 + */ 385 + DRM_HDMI_BROADCAST_RGB_FULL, 386 + 387 + /** 388 + * @DRM_HDMI_BROADCAST_RGB_LIMITED: Limited range RGB is forced. 389 + */ 390 + DRM_HDMI_BROADCAST_RGB_LIMITED, 391 + }; 392 + 393 + const char * 394 + drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_rgb); 372 395 const char * 373 396 drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt); 374 397 ··· 1064 1041 * @drm_atomic_helper_connector_hdmi_check(). 1065 1042 */ 1066 1043 struct { 1044 + /** 1045 + * @broadcast_rgb: Connector property to pass the 1046 + * Broadcast RGB selection value. 1047 + */ 1048 + enum drm_hdmi_broadcast_rgb broadcast_rgb; 1049 + 1067 1050 /** 1068 1051 * @output_bpc: Bits per color channel to output. 1069 1052 */ ··· 1786 1757 */ 1787 1758 struct drm_property *privacy_screen_hw_state_property; 1788 1759 1760 + /** 1761 + * @broadcast_rgb_property: Connector property to set the 1762 + * Broadcast RGB selection to output with. 1763 + */ 1764 + struct drm_property *broadcast_rgb_property; 1765 + 1789 1766 #define DRM_CONNECTOR_POLL_HPD (1 << 0) 1790 1767 #define DRM_CONNECTOR_POLL_CONNECT (1 << 1) 1791 1768 #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2) ··· 2131 2096 u32 scaling_mode_mask); 2132 2097 int drm_connector_attach_vrr_capable_property( 2133 2098 struct drm_connector *connector); 2099 + int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector); 2134 2100 int drm_connector_attach_colorspace_property(struct drm_connector *connector); 2135 2101 int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector); 2136 2102 bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state,