Unverified Commit 72921cdf authored by Maxime Ripard's avatar Maxime Ripard
Browse files

drm/connector: Add helper to compare HDR metadata



All the drivers that support the HDR metadata property have a similar
function to compare the metadata from one connector state to the next,
and force a mode change if they differ.

All these functions run pretty much the same code, so let's turn it into
an helper that can be shared across those drivers.

Reviewed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Reviewed-by: default avatarJernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20210430094451.2145002-2-maxime@cerno.tech
parent e057b52c
Loading
Loading
Loading
Loading
+2 −21
Original line number Diff line number Diff line
@@ -6275,25 +6275,6 @@ static int fill_hdr_info_packet(const struct drm_connector_state *state,
	return 0;
}

static bool
is_hdr_metadata_different(const struct drm_connector_state *old_state,
			  const struct drm_connector_state *new_state)
{
	struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
	struct drm_property_blob *new_blob = new_state->hdr_output_metadata;

	if (old_blob != new_blob) {
		if (old_blob && new_blob &&
		    old_blob->length == new_blob->length)
			return memcmp(old_blob->data, new_blob->data,
				      old_blob->length);

		return true;
	}

	return false;
}

static int
amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
				 struct drm_atomic_state *state)
@@ -6311,7 +6292,7 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
	if (!crtc)
		return 0;

	if (is_hdr_metadata_different(old_con_state, new_con_state)) {
	if (!drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state)) {
		struct dc_info_packet hdr_infopacket;

		ret = fill_hdr_info_packet(new_con_state, &hdr_infopacket);
@@ -8803,7 +8784,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
			      dm_old_crtc_state->abm_level;

		hdr_changed =
			is_hdr_metadata_different(old_con_state, new_con_state);
			!drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state);

		if (!scaling_changed && !abm_changed && !hdr_changed)
			continue;
+1 −16
Original line number Diff line number Diff line
@@ -2395,21 +2395,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
	return ret;
}

static bool hdr_metadata_equal(const struct drm_connector_state *old_state,
			       const struct drm_connector_state *new_state)
{
	struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
	struct drm_property_blob *new_blob = new_state->hdr_output_metadata;

	if (!old_blob || !new_blob)
		return old_blob == new_blob;

	if (old_blob->length != new_blob->length)
		return false;

	return !memcmp(old_blob->data, new_blob->data, old_blob->length);
}

static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
					  struct drm_atomic_state *state)
{
@@ -2423,7 +2408,7 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
	if (!crtc)
		return 0;

	if (!hdr_metadata_equal(old_state, new_state)) {
	if (!drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
		crtc_state = drm_atomic_get_crtc_state(state, crtc);
		if (IS_ERR(crtc_state))
			return PTR_ERR(crtc_state);
+28 −0
Original line number Diff line number Diff line
@@ -2173,6 +2173,34 @@ int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *conn
}
EXPORT_SYMBOL(drm_connector_attach_hdr_output_metadata_property);

/**
 * drm_connector_atomic_hdr_metadata_equal - checks if the hdr metadata changed
 * @old_state: old connector state to compare
 * @new_state: new connector state to compare
 *
 * This is used by HDR-enabled drivers to test whether the HDR metadata
 * have changed between two different connector state (and thus probably
 * requires a full blown mode change).
 *
 * Returns:
 * True if the metadata are equal, False otherwise
 */
bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state,
					     struct drm_connector_state *new_state)
{
	struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
	struct drm_property_blob *new_blob = new_state->hdr_output_metadata;

	if (!old_blob || !new_blob)
		return old_blob == new_blob;

	if (old_blob->length != new_blob->length)
		return false;

	return !memcmp(old_blob->data, new_blob->data, old_blob->length);
}
EXPORT_SYMBOL(drm_connector_atomic_hdr_metadata_equal);

/**
 * drm_connector_set_vrr_capable_property - sets the variable refresh rate
 * capable property for a connector
+1 −12
Original line number Diff line number Diff line
@@ -109,16 +109,6 @@ int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
	return -EINVAL;
}

static bool blob_equal(const struct drm_property_blob *a,
		       const struct drm_property_blob *b)
{
	if (a && b)
		return a->length == b->length &&
			!memcmp(a->data, b->data, a->length);

	return !a == !b;
}

int intel_digital_connector_atomic_check(struct drm_connector *conn,
					 struct drm_atomic_state *state)
{
@@ -149,8 +139,7 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn,
	    new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
	    new_conn_state->base.content_type != old_conn_state->base.content_type ||
	    new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode ||
	    !blob_equal(new_conn_state->base.hdr_output_metadata,
			old_conn_state->base.hdr_output_metadata))
	    !drm_connector_atomic_hdr_metadata_equal(old_state, new_state))
		crtc_state->mode_changed = true;

	return 0;
+2 −0
Original line number Diff line number Diff line
@@ -1672,6 +1672,8 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
int drm_connector_attach_vrr_capable_property(
		struct drm_connector *connector);
int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector);
bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state,
					     struct drm_connector_state *new_state);
int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector);
int drm_mode_create_dp_colorspace_property(struct drm_connector *connector);