@@ -707,6 +707,10 @@ 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->preferred_color_format !=
+ new_connector_state->preferred_color_format)
+ new_crtc_state->connectors_changed = true;
}
if (funcs->atomic_check)
@@ -798,6 +798,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->preferred_color_format_property) {
+ state->preferred_color_format = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
@@ -881,6 +883,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->preferred_color_format_property) {
+ *val = state->preferred_color_format;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
@@ -1061,6 +1061,14 @@ static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = {
{ DRM_MODE_SUBCONNECTOR_Native, "Native" }, /* DP */
};
+static const struct drm_prop_enum_list drm_preferred_color_format_enum_list[] = {
+ { 0, "auto" },
+ { DRM_COLOR_FORMAT_RGB444, "rgb" },
+ { DRM_COLOR_FORMAT_YCBCR444, "ycbcr444" },
+ { DRM_COLOR_FORMAT_YCBCR422, "ycbcr422" },
+ { DRM_COLOR_FORMAT_YCBCR420, "ycbcr420" },
+};
+
static const struct drm_prop_enum_list drm_active_color_format_enum_list[] = {
{ 0, "not applicable" },
{ DRM_COLOR_FORMAT_RGB444, "rgb" },
@@ -1398,11 +1406,20 @@ static const u32 dp_colorspaces =
* drm_connector_attach_max_bpc_property() to create and attach the
* property to the connector during initialization.
*
+ * preferred color format:
+ * This property is used by userspace to change the used color format. When
+ * used the driver will use the selected format if valid for the hardware,
+ * sink, and current resolution and refresh rate combination. Drivers to
+ * use the function drm_connector_attach_preferred_color_format_property()
+ * to create and attach the property to the connector during
+ * initialization. Possible values are "auto", "rgb", "ycbcr444",
+ * "ycbcr422", and "ycbcr420".
+ *
* active color format:
* This read-only property tells userspace the color format actually used
* by the hardware display engine "on the cable" on a connector. The chosen
* value depends on hardware capabilities, both display engine and
- * connected monitor. Drivers shall use
+ * connected monitor, and the "preferred color format". Drivers shall use
* drm_connector_attach_active_color_format_property() to install this
* property. Possible values are "not applicable", "rgb", "ycbcr444",
* "ycbcr422", and "ycbcr420".
@@ -2468,6 +2485,37 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_connector_attach_max_bpc_property);
+/**
+ * drm_connector_attach_preferred_color_format_property - attach "preferred color format" property
+ * @connector: connector to attach preferred 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_preferred_color_format_property(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+
+ if (!connector->preferred_color_format_property) {
+ prop = drm_property_create_enum(dev, 0, "preferred color format",
+ drm_preferred_color_format_enum_list,
+ ARRAY_SIZE(drm_preferred_color_format_enum_list));
+ if (!prop)
+ return -ENOMEM;
+
+ connector->preferred_color_format_property = prop;
+ }
+
+ drm_object_attach_property(&connector->base, prop, 0);
+ connector->state->preferred_color_format = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_preferred_color_format_property);
+
/**
* drm_connector_attach_active_color_format_property - attach "active color format" property
* @connector: connector to attach active color format property on.
@@ -1026,6 +1026,16 @@ struct drm_connector_state {
*/
enum drm_privacy_screen_status privacy_screen_sw_state;
+ /**
+ * preferred_color_format: Property set by userspace to tell the GPU
+ * driver which color format to use. It only gets applied if hardware,
+ * meaning both the computer and the monitor, and the driver support the
+ * given format at the current resolution and refresh rate. Userspace
+ * can check for (un-)successful application via the "active color
+ * format" property.
+ */
+ u32 preferred_color_format;
+
/**
* @hdr_output_metadata:
* DRM blob property for HDR output metadata
@@ -1699,6 +1709,12 @@ struct drm_connector {
*/
struct drm_property *privacy_screen_hw_state_property;
+ /**
+ * @preferred_color_format_property: Default connector property for the
+ * preferred color format to be driven out of the connector.
+ */
+ struct drm_property *preferred_color_format_property;
+
/**
* @active_color_format_property: Default connector property for the
* active color format to be driven out of the connector.
@@ -2059,6 +2075,7 @@ void drm_connector_attach_privacy_screen_provider(
struct drm_connector *connector, struct drm_privacy_screen *priv);
void drm_connector_update_privacy_screen(const struct drm_connector_state *connector_state);
+int drm_connector_attach_preferred_color_format_property(struct drm_connector *connector);
int drm_connector_attach_active_color_format_property(struct drm_connector *connector);
void drm_connector_set_active_color_format_property(struct drm_connector *connector,
u32 active_color_format);