Commit b71c0aaa authored by Jani Nikula's avatar Jani Nikula
Browse files

drm/edid: add drm_edid_connector_update()



Add a new function drm_edid_connector_update() to replace the
combination of calls drm_connector_update_edid_property() and
drm_add_edid_modes(). Usually they are called in the drivers in this
order, however the former needs information from the latter.

Since the new drm_edid_read*() functions no longer call the connector
updates directly, and the read and update are separated, we'll need this
new function for the connector update.

This is all in drm_edid.c simply to keep struct drm_edid opaque.

v2:
- Share code with drm_connector_update_edid_property() (Ville)
- Add comment about override EDID handling

Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/75aa3dbc8c9aa26ebbcdeacd98a466ef8d8827f4.1656494768.git.jani.nikula@intel.com
parent 6aa145bc
Loading
Loading
Loading
Loading
+79 −24
Original line number Diff line number Diff line
@@ -6160,7 +6160,7 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
	return num_modes;
}

static int drm_edid_connector_update(struct drm_connector *connector,
static int _drm_edid_connector_update(struct drm_connector *connector,
				      const struct drm_edid *drm_edid)
{
	int num_modes = 0;
@@ -6227,31 +6227,12 @@ static int drm_edid_connector_update(struct drm_connector *connector,
static void _drm_update_tile_info(struct drm_connector *connector,
				  const struct drm_edid *drm_edid);

static int _drm_connector_update_edid_property(struct drm_connector *connector,
static int _drm_edid_connector_property_update(struct drm_connector *connector,
					       const struct drm_edid *drm_edid)
{
	struct drm_device *dev = connector->dev;
	int ret;

	/* ignore requests to set edid when overridden */
	if (connector->override_edid)
		return 0;

	/*
	 * Set the display info, using edid if available, otherwise resetting
	 * the values to defaults. This duplicates the work done in
	 * drm_add_edid_modes, but that function is not consistently called
	 * before this one in all drivers and the computation is cheap enough
	 * that it seems better to duplicate it rather than attempt to ensure
	 * some arbitrary ordering of calls.
	 */
	if (drm_edid)
		update_display_info(connector, drm_edid);
	else
		drm_reset_display_info(connector);

	_drm_update_tile_info(connector, drm_edid);

	if (connector->edid_blob_ptr) {
		const struct edid *old_edid = connector->edid_blob_ptr->data;

@@ -6297,6 +6278,76 @@ static int _drm_connector_update_edid_property(struct drm_connector *connector,
	return ret;
}

/**
 * drm_edid_connector_update - Update connector information from EDID
 * @connector: Connector
 * @drm_edid: EDID
 *
 * Update the connector mode list, display info, ELD, HDR metadata, relevant
 * properties, etc. from the passed in EDID.
 *
 * If EDID is NULL, reset the information.
 *
 * Return: The number of modes added or 0 if we couldn't find any.
 */
int drm_edid_connector_update(struct drm_connector *connector,
			      const struct drm_edid *drm_edid)
{
	int count;

	/*
	 * FIXME: Reconcile the differences in override_edid handling between
	 * this and drm_connector_update_edid_property().
	 *
	 * If override_edid is set, and the EDID passed in here originates from
	 * drm_edid_read() and friends, it will be the override EDID, and there
	 * are no issues. drm_connector_update_edid_property() ignoring requests
	 * to set the EDID dates back to a time when override EDID was not
	 * handled at the low level EDID read.
	 *
	 * The only way the EDID passed in here can be different from the
	 * override EDID is when a driver passes in an EDID that does *not*
	 * originate from drm_edid_read() and friends, or passes in a stale
	 * cached version. This, in turn, is a question of when an override EDID
	 * set via debugfs should take effect.
	 */

	count = _drm_edid_connector_update(connector, drm_edid);

	_drm_update_tile_info(connector, drm_edid);

	/* Note: Ignore errors for now. */
	_drm_edid_connector_property_update(connector, drm_edid);

	return count;
}
EXPORT_SYMBOL(drm_edid_connector_update);

static int _drm_connector_update_edid_property(struct drm_connector *connector,
					       const struct drm_edid *drm_edid)
{
	/* ignore requests to set edid when overridden */
	if (connector->override_edid)
		return 0;

	/*
	 * Set the display info, using edid if available, otherwise resetting
	 * the values to defaults. This duplicates the work done in
	 * drm_add_edid_modes, but that function is not consistently called
	 * before this one in all drivers and the computation is cheap enough
	 * that it seems better to duplicate it rather than attempt to ensure
	 * some arbitrary ordering of calls.
	 */
	if (drm_edid)
		update_display_info(connector, drm_edid);
	else
		drm_reset_display_info(connector);

	_drm_update_tile_info(connector, drm_edid);

	return _drm_edid_connector_property_update(connector, drm_edid);
}

/**
 * drm_connector_update_edid_property - update the edid property of a connector
 * @connector: drm connector
@@ -6308,6 +6359,8 @@ static int _drm_connector_update_edid_property(struct drm_connector *connector,
 * set the connector's tile property here. See drm_connector_set_tile_property()
 * for more details.
 *
 * This function is deprecated. Use drm_edid_connector_update() instead.
 *
 * Returns:
 * Zero on success, negative errno on failure.
 */
@@ -6330,6 +6383,8 @@ EXPORT_SYMBOL(drm_connector_update_edid_property);
 * &drm_display_info structure and ELD in @connector with any information which
 * can be derived from the edid.
 *
 * This function is deprecated. Use drm_edid_connector_update() instead.
 *
 * Return: The number of modes added or 0 if we couldn't find any.
 */
int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
@@ -6342,7 +6397,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
		edid = NULL;
	}

	return drm_edid_connector_update(connector,
	return _drm_edid_connector_update(connector,
					  drm_edid_legacy_init(&drm_edid, edid));
}
EXPORT_SYMBOL(drm_add_edid_modes);
+2 −0
Original line number Diff line number Diff line
@@ -603,6 +603,8 @@ const struct drm_edid *drm_edid_read_ddc(struct drm_connector *connector,
const struct drm_edid *drm_edid_read_custom(struct drm_connector *connector,
					    int (*read_block)(void *context, u8 *buf, unsigned int block, size_t len),
					    void *context);
int drm_edid_connector_update(struct drm_connector *connector,
			      const struct drm_edid *edid);
const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid,
				  int ext_id, int *ext_index);