From nobody Tue Dec 2 03:03:33 2025 Received: from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com [136.143.188.112]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1FEE3328617 for ; Mon, 17 Nov 2025 19:13:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.112 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763406828; cv=pass; b=J38Sy5+4BL5YDAfAHlXg6aQG2gXnO0weqq5ao81KvPQb9fZO1pkFYOlZ0QT4MmYstPoy1iFKwffQCAyjfbu3w+XZRGEEllOag8J6s2XrZUe5T/XOp7RCBoMbSiOb+q66rBOpgf7ONERfKTUsnDlpmvuMy0TrVKpsiP7OYRGyJXo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763406828; c=relaxed/simple; bh=Gy0a/qZqYqAXlBKXlgZiDA5X49q3sp00MIccEBrd+iU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jEh1KWmsqbtSDjoI1Qj8aJxZGCAJzT10UottGBjW6sJJl0KQG6IObOqn3QaxzKp7COWADQDkBAHvpGvNHhnuEwH4/9ABYoC49NkdMwkur+E0OGW3fPy8AnaZ/cmiaKm/2oaOl8VXl0VBRXQWKFlZkL26FKeHAfUjDu++t9uCXH8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (1024-bit key) header.d=collabora.com header.i=nicolas.frattaroli@collabora.com header.b=R2GDDudM; arc=pass smtp.client-ip=136.143.188.112 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=collabora.com header.i=nicolas.frattaroli@collabora.com header.b="R2GDDudM" ARC-Seal: i=1; a=rsa-sha256; t=1763406754; cv=none; d=zohomail.com; s=zohoarc; b=POVvlxYD/kw5kirO806RSeq3/x6kPHQXUz+Q0iQsAAemEyMzbPKwKmTb+N8EpH3dWIT9t6FgveFlLqhpNya6THOYJy2wX74l+xHr1uDzonm5RVisjjeeCaX+H1OBXmQjlZJctQNHfhdgqmVFDjGGHDfVuKMky3kaOy32Y2O/vUQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1763406754; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=JDm4LO5yWJTcfID7mSjaqMJXnPJYGF2W6cLE9Z+G7NE=; b=Z9kvcT4CmOvpgYrXY/w/Okp4fjmC+IyT4d5t+MmtdrQ7Uf1YSRohLJjJh8EBran71OXdKbKk25FtokP8epT+fFuclLwTSZVO7u6EBt7M3dRnXESQyKgBC3/bTmJQvGR7Wz32Um2eypo4Prb2Z0pGtRhutph/gvJA4CQKg6/7JVo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=collabora.com; spf=pass smtp.mailfrom=nicolas.frattaroli@collabora.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1763406754; s=zohomail; d=collabora.com; i=nicolas.frattaroli@collabora.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:References:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=JDm4LO5yWJTcfID7mSjaqMJXnPJYGF2W6cLE9Z+G7NE=; b=R2GDDudM34+KOSu+DJhACiYrzHUj81vcYt/fPc2mVrVfzlbjJ49h9MvP6Kq3pSXM 7TMc1hDSTDRV3paZcuqGIvocC25jMIO0ahlRKvSdWq26J/opy/e78UqlsG4GAgZNIft EpqMgrmtgr4BaHdc0aeH3woQtCrEGv2LmUplQDIw= Received: by mx.zohomail.com with SMTPS id 1763406753246694.750073819096; Mon, 17 Nov 2025 11:12:33 -0800 (PST) From: Nicolas Frattaroli Date: Mon, 17 Nov 2025 20:11:46 +0100 Subject: [PATCH v4 02/10] drm: Add new general DRM property "color format" Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251117-color-format-v4-2-0ded72bd1b00@collabora.com> References: <20251117-color-format-v4-0-0ded72bd1b00@collabora.com> In-Reply-To: <20251117-color-format-v4-0-0ded72bd1b00@collabora.com> To: Harry Wentland , Leo Li , Rodrigo Siqueira , Alex Deucher , =?utf-8?q?Christian_K=C3=B6nig?= , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Andy Yan , Jani Nikula , Rodrigo Vivi , Joonas Lahtinen , Tvrtko Ursulin Cc: kernel@collabora.com, amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org, Nicolas Frattaroli , Andri Yngvason , Werner Sembach , Marius Vlad X-Mailer: b4 0.14.3 From: Andri Yngvason Adds a new general DRM property named "color format" which can be used by userspace to force the display driver 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 the formats which 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. Signed-off-by: Werner Sembach Signed-off-by: Andri Yngvason Signed-off-by: Marius Vlad --- drivers/gpu/drm/drm_atomic_helper.c | 5 + drivers/gpu/drm/drm_atomic_uapi.c | 4 + drivers/gpu/drm/drm_connector.c | 180 ++++++++++++++++++++++++++++++++= ++++ include/drm/drm_connector.h | 54 ++++++++++- 4 files changed, 238 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atom= ic_helper.c index e641fcf8c568..25f354b2cc0d 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -736,6 +736,11 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, if (old_connector_state->max_requested_bpc !=3D new_connector_state->max_requested_bpc) new_crtc_state->connectors_changed =3D true; + + if (old_connector_state->color_format !=3D + new_connector_state->color_format) + new_crtc_state->connectors_changed =3D true; + } =20 if (funcs->atomic_check) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic= _uapi.c index b2cb5ae5a139..2f093b0d1628 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -784,6 +784,8 @@ static int drm_atomic_connector_set_property(struct drm= _connector *connector, state->privacy_screen_sw_state =3D val; } else if (property =3D=3D connector->broadcast_rgb_property) { state->hdmi.broadcast_rgb =3D val; + } else if (property =3D=3D connector->color_format_property) { + state->color_format =3D drm_color_format_enum_to_color_format(val); } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -869,6 +871,8 @@ drm_atomic_connector_get_property(struct drm_connector = *connector, *val =3D state->privacy_screen_sw_state; } else if (property =3D=3D connector->broadcast_rgb_property) { *val =3D state->hdmi.broadcast_rgb; + } else if (property =3D=3D connector->color_format_property) { + *val =3D drm_color_format_to_color_format_enum(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_connecto= r.c index 272d6254ea47..0ad7be0a2d09 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1348,6 +1348,55 @@ static const char * const colorspace_names[] =3D { [DRM_MODE_COLORIMETRY_BT601_YCC] =3D "BT601_YCC", }; =20 +u32 +drm_color_format_to_color_format_enum(enum drm_color_format fmt) +{ + switch (fmt) { + default: + case DRM_COLOR_FORMAT_AUTO: + return DRM_MODE_COLOR_FORMAT_AUTO; + case DRM_COLOR_FORMAT_RGB444: + return DRM_MODE_COLOR_FORMAT_RGB444; + case DRM_COLOR_FORMAT_YCBCR444: + return DRM_MODE_COLOR_FORMAT_YCBCR444; + case DRM_COLOR_FORMAT_YCBCR422: + return DRM_MODE_COLOR_FORMAT_YCBCR422; + case DRM_COLOR_FORMAT_YCBCR420: + return DRM_MODE_COLOR_FORMAT_YCBCR420; + } +} + +u32 +drm_color_format_enum_to_color_format(enum drm_color_format_enum fmt_enum) +{ + switch (fmt_enum) { + default: + case DRM_MODE_COLOR_FORMAT_RGB444: + return DRM_COLOR_FORMAT_RGB444; + case DRM_MODE_COLOR_FORMAT_AUTO: + return DRM_COLOR_FORMAT_AUTO; + case DRM_MODE_COLOR_FORMAT_YCBCR444: + return DRM_COLOR_FORMAT_YCBCR444; + case DRM_MODE_COLOR_FORMAT_YCBCR422: + return DRM_COLOR_FORMAT_YCBCR422; + case DRM_MODE_COLOR_FORMAT_YCBCR420: + return DRM_COLOR_FORMAT_YCBCR420; + } +} + +/** + * drm_get_color_format_name - return a string for color format + * @colorspace: color format to compute name of + * + */ +const char *drm_get_color_format_name(enum drm_color_format color_fmt) +{ + u32 conv_color_fmt =3D drm_color_format_to_color_format_enum(color_fmt); + + return drm_hdmi_connector_get_output_format_name(conv_color_fmt); +} +EXPORT_SYMBOL(drm_get_color_format_name); + /** * drm_get_colorspace_name - return a string for color encoding * @colorspace: color space to compute name of @@ -1377,6 +1426,22 @@ static const u32 hdmi_colorspaces =3D BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) | BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER); =20 +/* already bit-shifted */ +static const u32 hdmi_colorformats =3D + DRM_COLOR_FORMAT_AUTO | + DRM_COLOR_FORMAT_RGB444 | + DRM_COLOR_FORMAT_YCBCR444 | + DRM_COLOR_FORMAT_YCBCR422 | + DRM_COLOR_FORMAT_YCBCR420; + +/* already bit-shifted */ +static const u32 dp_colorformats =3D + DRM_COLOR_FORMAT_AUTO | + DRM_COLOR_FORMAT_RGB444 | + DRM_COLOR_FORMAT_YCBCR444 | + DRM_COLOR_FORMAT_YCBCR422 | + DRM_COLOR_FORMAT_YCBCR420; + /* * As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Color= imetry * Format Table 2-120 @@ -2628,6 +2693,101 @@ int drm_mode_create_hdmi_colorspace_property(struct= drm_connector *connector, } EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property); =20 +static int drm_mode_create_color_format_property(struct drm_connector *con= nector, + u32 supported_color_formats) +{ + struct drm_device *dev =3D connector->dev; + struct drm_prop_enum_list enum_list[DRM_MODE_COLOR_FORMAT_COUNT]; + int i, len; + + if (connector->color_format_property) + return 0; + + if (!supported_color_formats) { + drm_err(dev, "No supported color formats provded on [CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); + return -EINVAL; + } + + if ((supported_color_formats & -BIT(DRM_MODE_COLOR_FORMAT_COUNT)) !=3D 0)= { + drm_err(dev, "Unknown colorspace provded on [CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); + return -EINVAL; + } + + len =3D 0; + for (i =3D 0; i < DRM_MODE_COLOR_FORMAT_COUNT; i++) { + if (!(supported_color_formats & BIT(i))) + continue; + + enum_list[len].type =3D i; + if (i !=3D DRM_MODE_COLOR_FORMAT_AUTO) + enum_list[len].name =3D output_format_str[i]; + else + enum_list[len].name =3D "AUTO"; + len++; + } + + connector->color_format_property =3D + drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "color format", + enum_list, len); + + if (!connector->color_format_property) + return -ENOMEM; + + return 0; +} + +/** + * drm_mode_create_hdmi_color_format_property - create hdmi color format p= roperty + * @connector: connector to create the color format property on. + * @supported_color_formats: bitmap of supported color formats + * + * Called by a driver the first time it's needed, must be attached to desi= red + * HDMI connectors. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_mode_create_hdmi_color_format_property(struct drm_connector *conne= ctor, + u32 supported_color_formats) +{ + u32 color_formats; + + if (supported_color_formats) + color_formats =3D supported_color_formats & hdmi_colorformats; + else + color_formats =3D hdmi_colorformats; + + return drm_mode_create_color_format_property(connector, color_formats); +} +EXPORT_SYMBOL(drm_mode_create_hdmi_color_format_property); + +/** + * drm_mode_create_dp_color_format_property - create dp color format prope= rty + * @connector: connector to create the Colorspace property on. + * @supported_color_formats: bitmap of supported color formats + * + * Called by a driver the first time it's needed, must be attached to desi= red + * DP connectors. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_mode_create_dp_color_format_property(struct drm_connector *connect= or, + u32 supported_color_formats) +{ + u32 color_formats; + + if (supported_color_formats) + color_formats =3D supported_color_formats & dp_colorformats; + else + color_formats =3D dp_colorformats; + + return drm_mode_create_color_format_property(connector, color_formats); +} +EXPORT_SYMBOL(drm_mode_create_dp_color_format_property); + /** * drm_mode_create_dp_colorspace_property - create dp colorspace property * @connector: connector to create the Colorspace property on. @@ -2845,6 +3005,26 @@ int drm_connector_attach_max_bpc_property(struct drm= _connector *connector, } EXPORT_SYMBOL(drm_connector_attach_max_bpc_property); =20 +/** + * drm_connector_attach_color_format_property - attach "force color format= " property + * @connector: connector to attach force color format property on. + * + * This is used to add support for selecting a color format on a connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_attach_color_format_property(struct drm_connector *conne= ctor) +{ + struct drm_property *prop =3D connector->color_format_property; + + drm_object_attach_property(&connector->base, prop, DRM_COLOR_FORMAT_AUTO); + + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_color_format_property); + + /** * drm_connector_attach_hdr_output_metadata_property - attach "HDR_OUTPUT_= METADA" property * @connector: connector to attach the property on. diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 8f34f4b8183d..a071079fd3ad 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -556,6 +556,26 @@ enum drm_colorspace { DRM_MODE_COLORIMETRY_COUNT }; =20 +enum drm_color_format_enum { + DRM_MODE_COLOR_FORMAT_RGB444 =3D HDMI_COLORSPACE_RGB, + DRM_MODE_COLOR_FORMAT_YCBCR422 =3D HDMI_COLORSPACE_YUV422, + DRM_MODE_COLOR_FORMAT_YCBCR444 =3D HDMI_COLORSPACE_YUV444, + DRM_MODE_COLOR_FORMAT_YCBCR420 =3D HDMI_COLORSPACE_YUV420, + /* auto case, driver will set the color_format */ + DRM_MODE_COLOR_FORMAT_AUTO, + DRM_MODE_COLOR_FORMAT_COUNT +}; + +enum drm_color_format { + DRM_COLOR_FORMAT_NONE =3D 0, + DRM_COLOR_FORMAT_RGB444 =3D (1 << 0), + DRM_COLOR_FORMAT_YCBCR422 =3D (1 << 1), + DRM_COLOR_FORMAT_YCBCR444 =3D (1 << 2), + DRM_COLOR_FORMAT_YCBCR420 =3D (1 << 3), + /* auto case, driver will set the color_format */ + DRM_COLOR_FORMAT_AUTO =3D (1 << 4), +}; + /** * enum drm_bus_flags - bus_flags info for &drm_display_info * @@ -699,11 +719,6 @@ struct drm_display_info { */ enum subpixel_order subpixel_order; =20 -#define DRM_COLOR_FORMAT_RGB444 (1<<0) -#define DRM_COLOR_FORMAT_YCBCR444 (1<<1) -#define DRM_COLOR_FORMAT_YCBCR422 (1<<2) -#define DRM_COLOR_FORMAT_YCBCR420 (1<<3) - /** * @panel_orientation: Read only connector property for built-in panels, * indicating the orientation of the panel vs the device's casing. @@ -1107,6 +1122,13 @@ struct drm_connector_state { */ enum drm_colorspace colorspace; =20 + /** + * @color_format: State variable for Connector property to request + * color format change on Sink. This is most commonly used to switch + * between RGB to YUV and vice-versa. + */ + enum drm_color_format color_format; + /** * @writeback_job: Writeback job for writeback connectors * @@ -2060,6 +2082,12 @@ struct drm_connector { */ struct drm_property *colorspace_property; =20 + /** + * @color_format_property: Connector property to set the suitable + * color format supported by the sink. + */ + struct drm_property *color_format_property; + /** * @path_blob_ptr: * @@ -2461,6 +2489,12 @@ int drm_mode_create_dp_colorspace_property(struct dr= m_connector *connector, int drm_mode_create_content_type_property(struct drm_device *dev); int drm_mode_create_suggested_offset_properties(struct drm_device *dev); =20 +int drm_mode_create_hdmi_color_format_property(struct drm_connector *conne= ctor, + u32 supported_color_formats); + +int drm_mode_create_dp_color_format_property(struct drm_connector *connect= or, + u32 supported_color_formats); + int drm_connector_set_path_property(struct drm_connector *connector, const char *path); int drm_connector_set_tile_property(struct drm_connector *connector); @@ -2542,6 +2576,16 @@ bool drm_connector_has_possible_encoder(struct drm_c= onnector *connector, struct drm_encoder *encoder); const char *drm_get_colorspace_name(enum drm_colorspace colorspace); =20 +int drm_connector_attach_color_format_property(struct drm_connector *conne= ctor); + +const char *drm_get_color_format_name(enum drm_color_format color_fmt); + +u32 +drm_color_format_to_color_format_enum(enum drm_color_format fmt); + +u32 +drm_color_format_enum_to_color_format(enum drm_color_format_enum fmt_enum); + /** * drm_for_each_connector_iter - connector_list iterator macro * @connector: &struct drm_connector pointer used as cursor --=20 2.51.2