backend-drm: set connector max bpc

"max bpc" property is meant for working around faulty sink hardware.
Normally it should be set to the maximum possible value so that the
kernel driver has full freedom to choose the link bpc without being
artificially forced to lower color precision.

The default value is 16 because that is a nice round number and more
than any link technology I've heard is using today which would be 12.

Also offer an API set the value, so that weston.ini could be used in the
next patch for sink workaround purposes.

Closes: https://gitlab.freedesktop.org/wayland/weston/-/issues/612

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
dev
Pekka Paalanen 3 years ago committed by Pekka Paalanen
parent 4d2ea5dd0b
commit d24adbbe25
  1. 14
      include/libweston/backend-drm.h
  2. 3
      libweston/backend-drm/drm-internal.h
  3. 13
      libweston/backend-drm/drm.c
  4. 27
      libweston/backend-drm/kms.c

@ -78,6 +78,20 @@ struct weston_drm_output_api {
*/
void (*set_seat)(struct weston_output *output,
const char *seat);
/** Set the "max bpc" KMS connector property
*
* The property is used for working around faulty sink hardware like
* monitors or media converters that mishandle the kernel driver
* chosen bits-per-channel on the physical link. When having trouble,
* try a lower value like 8.
*
* The value actually used in KMS is silently clamped to the range the
* KMS driver claims to support. The default value is 16.
*
* This can be set only while the output is disabled.
*/
void (*set_max_bpc)(struct weston_output *output, unsigned max_bpc);
};
static inline const struct weston_drm_output_api *

@ -187,6 +187,7 @@ enum wdrm_connector_property {
WDRM_CONNECTOR_HDCP_CONTENT_TYPE,
WDRM_CONNECTOR_PANEL_ORIENTATION,
WDRM_CONNECTOR_HDR_OUTPUT_METADATA,
WDRM_CONNECTOR_MAX_BPC,
WDRM_CONNECTOR__COUNT
};
@ -559,6 +560,8 @@ struct drm_output {
uint32_t hdr_output_metadata_blob_id;
uint64_t ackd_color_outcome_serial;
unsigned max_bpc;
/* Plane being displayed directly on the CRTC */
struct drm_plane *scanout_plane;

@ -1389,6 +1389,17 @@ drm_output_set_seat(struct weston_output *base,
seat ? seat : "");
}
static void
drm_output_set_max_bpc(struct weston_output *base, unsigned max_bpc)
{
struct drm_output *output = to_drm_output(base);
assert(output);
assert(!output->base.enabled);
output->max_bpc = max_bpc;
}
static int
drm_output_init_gamma_size(struct drm_output *output)
{
@ -2278,6 +2289,7 @@ drm_output_create(struct weston_compositor *compositor, const char *name)
output->device = device;
output->crtc = NULL;
output->max_bpc = 16;
output->gbm_format = DRM_FORMAT_INVALID;
#ifdef BUILD_DRM_GBM
output->gbm_bo_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
@ -3055,6 +3067,7 @@ static const struct weston_drm_output_api api = {
drm_output_set_mode,
drm_output_set_gbm_format,
drm_output_set_seat,
drm_output_set_max_bpc,
};
static struct drm_backend *

@ -146,6 +146,7 @@ const struct drm_property_info connector_props[] = {
[WDRM_CONNECTOR_HDR_OUTPUT_METADATA] = {
.name = "HDR_OUTPUT_METADATA",
},
[WDRM_CONNECTOR_MAX_BPC] = { .name = "max bpc", },
};
const struct drm_property_info crtc_props[] = {
@ -905,6 +906,30 @@ drm_connector_set_hdcp_property(struct drm_connector *connector,
assert(ret == 0);
}
static int
drm_connector_set_max_bpc(struct drm_connector *connector,
struct drm_output *output,
drmModeAtomicReq *req)
{
const struct drm_property_info *info;
uint64_t max_bpc;
uint64_t a, b;
if (!drm_connector_has_prop(connector, WDRM_CONNECTOR_MAX_BPC))
return 0;
info = &connector->props[WDRM_CONNECTOR_MAX_BPC];
assert(info->flags & DRM_MODE_PROP_RANGE);
assert(info->num_range_values == 2);
a = info->range_values[0];
b = info->range_values[1];
assert(a <= b);
max_bpc = MAX(a, MIN(output->max_bpc, b));
return connector_add_prop(req, connector,
WDRM_CONNECTOR_MAX_BPC, max_bpc);
}
static int
drm_output_apply_state_atomic(struct drm_output_state *state,
drmModeAtomicReq *req,
@ -965,6 +990,8 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
WDRM_CONNECTOR_HDR_OUTPUT_METADATA,
output->hdr_output_metadata_blob_id);
}
ret |= drm_connector_set_max_bpc(&head->connector, output, req);
}
if (ret != 0) {

Loading…
Cancel
Save