From 1d581656c756fd17a6cf55474d32586f6769663f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 15:03:39 +0200 Subject: [PATCH] backend/drm: set "max bpc" to the max "max bpc" is a maximum value, the driver is free to choose a smaller value depending on the bandwidth available. Some faulty monitors misbehave with higher bpc values. We'll add a workaround if users get hit by these in practice. References: https://gitlab.freedesktop.org/wayland/weston/-/issues/612 --- backend/drm/atomic.c | 3 +++ backend/drm/drm.c | 8 ++++++++ backend/drm/properties.c | 27 +++++++++++++++++++++++++++ include/backend/drm/drm.h | 1 + include/backend/drm/properties.h | 4 ++++ 5 files changed, 43 insertions(+) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 82ead96e..ab1b2160 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -284,6 +284,9 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, atomic_add(&atom, conn->id, conn->props.content_type, DRM_MODE_CONTENT_TYPE_GRAPHICS); } + if (active && conn->props.max_bpc != 0 && conn->max_bpc > 0) { + atomic_add(&atom, conn->id, conn->props.max_bpc, conn->max_bpc); + } atomic_add(&atom, crtc->id, crtc->props.mode_id, mode_id); atomic_add(&atom, crtc->id, crtc->props.active, active); if (active) { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 1c22878c..262a533e 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1317,6 +1317,14 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, wlr_conn->output.non_desktop = non_desktop; } + wlr_conn->max_bpc = 0; + if (wlr_conn->props.max_bpc != 0) { + if (!introspect_drm_prop_range(drm->fd, wlr_conn->props.max_bpc, + NULL, &wlr_conn->max_bpc)) { + wlr_log(WLR_ERROR, "Failed to introspect 'max bpc' property"); + } + } + size_t edid_len = 0; uint8_t *edid = get_drm_prop_blob(drm->fd, wlr_conn->id, wlr_conn->props.edid, &edid_len); diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 51fbc80a..4f495177 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -26,6 +27,7 @@ static const struct prop_info connector_info[] = { { "PATH", INDEX(path) }, { "content type", INDEX(content_type) }, { "link-status", INDEX(link_status) }, + { "max bpc", INDEX(max_bpc) }, { "non-desktop", INDEX(non_desktop) }, { "panel orientation", INDEX(panel_orientation) }, { "subconnector", INDEX(subconnector) }, @@ -181,3 +183,28 @@ char *get_drm_prop_enum(int fd, uint32_t obj, uint32_t prop_id) { return str; } + +bool introspect_drm_prop_range(int fd, uint32_t prop_id, + uint64_t *min, uint64_t *max) { + drmModePropertyRes *prop = drmModeGetProperty(fd, prop_id); + if (!prop) { + return false; + } + + if (drmModeGetPropertyType(prop) != DRM_MODE_PROP_RANGE) { + drmModeFreeProperty(prop); + return false; + } + + assert(prop->count_values == 2); + + if (min != NULL) { + *min = prop->values[0]; + } + if (max != NULL) { + *max = prop->values[1]; + } + + drmModeFreeProperty(prop); + return true; +} diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index dbc47364..700ed654 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -119,6 +119,7 @@ struct wlr_drm_connector { enum wlr_drm_connector_status status; bool desired_enabled; uint32_t id; + uint64_t max_bpc; struct wlr_drm_lease *lease; struct wlr_drm_crtc *crtc; diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index f6c6023a..b6ca14f1 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -21,6 +21,7 @@ union wlr_drm_connector_props { uint32_t non_desktop; uint32_t panel_orientation; // not guaranteed to exist uint32_t content_type; // not guaranteed to exist + uint32_t max_bpc; // not guaranteed to exist // atomic-modesetting only @@ -76,4 +77,7 @@ bool get_drm_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret); void *get_drm_prop_blob(int fd, uint32_t obj, uint32_t prop, size_t *ret_len); char *get_drm_prop_enum(int fd, uint32_t obj, uint32_t prop); +bool introspect_drm_prop_range(int fd, uint32_t prop_id, + uint64_t *min, uint64_t *max); + #endif