Essentially copying the COLOR_ENCODING and COLOR_RANGE plane properties, reusing the drm_color_encoding and drm_color_range enums. This allows us to advertise and configure the matrix coefficients and ranges used to convert between RGB and YCbCr formats and thus helps writeback connector implementations that want to advertise YCbCr formats.
Signed-off-by: Robert Mader <robert.ma...@collabora.com> --- drivers/gpu/drm/drm_atomic_uapi.c | 8 +++ drivers/gpu/drm/drm_color_mgmt.c | 90 +++++++++++++++++++++++++++++++ include/drm/drm_color_mgmt.h | 7 +++ include/drm/drm_connector.h | 17 ++++++ include/drm/drm_mode_config.h | 14 +++++ 5 files changed, 136 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index ecc73d52bfae..12379673dea1 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -774,6 +774,10 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, return set_out_fence_for_connector(state->state, connector, fence_ptr); + } else if (property == config->writeback_color_encoding) { + state->writeback_color_encoding = val; + } else if (property == config->writeback_color_range) { + state->writeback_color_range = val; } else if (property == connector->max_bpc_property) { state->max_requested_bpc = val; } else if (property == connector->privacy_screen_sw_state_property) { @@ -859,6 +863,10 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = 0; } else if (property == config->writeback_out_fence_ptr_property) { *val = 0; + } else if (property == config->writeback_color_encoding) { + *val = state->writeback_color_encoding; + } else if (property == config->writeback_color_range) { + *val = state->writeback_color_range; } else if (property == connector->max_bpc_property) { *val = state->max_requested_bpc; } else if (property == connector->privacy_screen_sw_state_property) { diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 37a3270bc3c2..04444c215bf4 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -29,6 +29,7 @@ #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_print.h> +#include <drm/drm_writeback.h> #include <kunit/visibility.h> #include "drm_crtc_internal.h" @@ -592,6 +593,95 @@ int drm_plane_create_color_properties(struct drm_plane *plane, } EXPORT_SYMBOL(drm_plane_create_color_properties); +/** + * drm_writeback_create_color_properties - color encoding related writeback connector properties + * @wb_connector: writeback connector object + * @supported_encodings: bitfield indicating supported color encodings + * @supported_ranges: bitfileld indicating supported color ranges + * @default_encoding: default color encoding + * @default_range: default color range + * + * Create and attach writeback connector specific WRITEBACK_COLOR_ENCODING and + * WRITEBACK_COLOR_RANGE properties to @wb_connector. The supported encodings + * and ranges should be provided in supported_encodings and supported_ranges + * bitmasks. Each bit set in the bitmask indicates that its number as enum + * value is supported. + */ +int drm_writeback_create_color_properties(struct drm_writeback_connector *wb_connector, + u32 supported_encodings, + u32 supported_ranges, + enum drm_color_encoding default_encoding, + enum drm_color_range default_range) +{ + struct drm_connector *connector = &wb_connector->base; + struct drm_device *dev = connector->dev; + struct drm_property *prop; + struct drm_prop_enum_list enum_list[MAX_T(int, DRM_COLOR_ENCODING_MAX, + DRM_COLOR_RANGE_MAX)]; + int i, len; + + if (WARN_ON(supported_encodings == 0 || + (supported_encodings & -BIT(DRM_COLOR_ENCODING_MAX)) != 0 || + (supported_encodings & BIT(default_encoding)) == 0)) + return -EINVAL; + + if (WARN_ON(supported_ranges == 0 || + (supported_ranges & -BIT(DRM_COLOR_RANGE_MAX)) != 0 || + (supported_ranges & BIT(default_range)) == 0)) + return -EINVAL; + + if (!dev->mode_config.writeback_color_encoding) { + len = 0; + for (i = 0; i < DRM_COLOR_ENCODING_MAX; i++) { + if ((supported_encodings & BIT(i)) == 0) + continue; + + enum_list[len].type = i; + enum_list[len].name = color_encoding_name[i]; + len++; + } + + prop = drm_property_create_enum(dev, 0, + "WRITEBACK_COLOR_ENCODING", + enum_list, len); + if (!prop) + return -ENOMEM; + dev->mode_config.writeback_color_encoding = prop; + } + + drm_object_attach_property(&connector->base, + dev->mode_config.writeback_color_encoding, + default_encoding); + if (connector->state) + connector->state->writeback_color_encoding = default_encoding; + + if (!dev->mode_config.writeback_color_range) { + len = 0; + for (i = 0; i < DRM_COLOR_RANGE_MAX; i++) { + if ((supported_ranges & BIT(i)) == 0) + continue; + + enum_list[len].type = i; + enum_list[len].name = color_range_name[i]; + len++; + } + + prop = drm_property_create_enum(dev, 0, "WRITEBACK_COLOR_RANGE", + enum_list, len); + if (!prop) + return -ENOMEM; + dev->mode_config.writeback_color_range = prop; + } + drm_object_attach_property(&connector->base, + dev->mode_config.writeback_color_range, + default_range); + if (connector->state) + connector->state->writeback_color_range = default_range; + + return 0; +} +EXPORT_SYMBOL(drm_writeback_create_color_properties); + /** * drm_color_lut_check - check validity of lookup table * @lut: property blob containing LUT to check diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 6cb577f6dba6..60146e3063fd 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -29,6 +29,7 @@ struct drm_crtc; struct drm_plane; +struct drm_writeback_connector; /** * drm_color_lut_extract - clamp and round LUT entries @@ -91,6 +92,12 @@ int drm_plane_create_color_properties(struct drm_plane *plane, enum drm_color_encoding default_encoding, enum drm_color_range default_range); +int drm_writeback_create_color_properties(struct drm_writeback_connector *wb_connector, + u32 supported_encodings, + u32 supported_ranges, + enum drm_color_encoding default_encoding, + enum drm_color_range default_range); + /** * enum drm_color_lut_tests - hw-specific LUT tests to perform * diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 8f34f4b8183d..178bfbcb13e3 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -28,6 +28,7 @@ #include <linux/ctype.h> #include <linux/hdmi.h> #include <linux/notifier.h> +#include <drm/drm_color_mgmt.h> #include <drm/drm_mode_object.h> #include <drm/drm_util.h> #include <drm/drm_property.h> @@ -1120,6 +1121,22 @@ struct drm_connector_state { */ struct drm_writeback_job *writeback_job; + /** + * @writeback_color_encoding: + * + * Color encoding for non RGB formats used by writeback connectors. + * See also: drm_writeback_create_color_properties() + */ + enum drm_color_encoding writeback_color_encoding; + + /** + * @writeback_color_range: + * + * Color encoding for non RGB formats used by writeback connectors. + * See also: drm_writeback_create_color_properties() + */ + enum drm_color_range writeback_color_range; + /** * @max_requested_bpc: Connector property to limit the maximum bit * depth of the pixels. diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 2e848b816218..1d2a7cb6d410 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -863,6 +863,20 @@ struct drm_mode_config { */ struct drm_property *writeback_out_fence_ptr_property; + /** + * @writeback_color_encoding: Optional property for writeback + * connectors, color encoding for non RGB formats. + * See also: drm_writeback_create_color_properties() + */ + struct drm_property *writeback_color_encoding; + + /** + * @writeback_color_range: Optional property for writeback connectors, + * color range for non RGB formats. + * See also: drm_writeback_create_color_properties() + */ + struct drm_property *writeback_color_range; + /** * @hdr_output_metadata_property: Connector property containing hdr * metatada. This will be provided by userspace compositors based -- 2.50.1