Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cd300e0 authored by Jani Nikula's avatar Jani Nikula Committed by Daniel Vetter
Browse files

drm/i915: Move cached EDID to intel_connector



Move the cached EDID from intel_dp and intel_lvds_connector to
intel_connector. Unify cached EDID handling for LVDS and eDP, in
preparation for adding more generic EDID caching later.

Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Reviewed-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent ebda95a9
Loading
Loading
Loading
Loading
+34 −27
Original line number Diff line number Diff line
@@ -2317,44 +2317,45 @@ g4x_dp_detect(struct intel_dp *intel_dp)
static struct edid *
intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
{
	struct intel_dp *intel_dp = intel_attached_dp(connector);
	struct intel_connector *intel_connector = to_intel_connector(connector);

	/* use cached edid if we have one */
	if (intel_connector->edid) {
		struct edid *edid;
		int size;

	if (is_edp(intel_dp)) {
		if (!intel_dp->edid)
		/* invalid edid */
		if (IS_ERR(intel_connector->edid))
			return NULL;

		size = (intel_dp->edid->extensions + 1) * EDID_LENGTH;
		size = (intel_connector->edid->extensions + 1) * EDID_LENGTH;
		edid = kmalloc(size, GFP_KERNEL);
		if (!edid)
			return NULL;

		memcpy(edid, intel_dp->edid, size);
		memcpy(edid, intel_connector->edid, size);
		return edid;
	}

	edid = drm_get_edid(connector, adapter);
	return edid;
	return drm_get_edid(connector, adapter);
}

static int
intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
{
	struct intel_dp *intel_dp = intel_attached_dp(connector);
	int	ret;
	struct intel_connector *intel_connector = to_intel_connector(connector);

	if (is_edp(intel_dp)) {
		drm_mode_connector_update_edid_property(connector,
							intel_dp->edid);
		ret = drm_add_edid_modes(connector, intel_dp->edid);
		drm_edid_to_eld(connector,
				intel_dp->edid);
		return intel_dp->edid_mode_count;
	/* use cached edid if we have one */
	if (intel_connector->edid) {
		/* invalid edid */
		if (IS_ERR(intel_connector->edid))
			return 0;

		return intel_connector_update_modes(connector,
						    intel_connector->edid);
	}

	ret = intel_ddc_get_modes(connector, adapter);
	return ret;
	return intel_ddc_get_modes(connector, adapter);
}


@@ -2506,6 +2507,9 @@ intel_dp_destroy(struct drm_connector *connector)
	struct intel_dp *intel_dp = intel_attached_dp(connector);
	struct intel_connector *intel_connector = to_intel_connector(connector);

	if (!IS_ERR_OR_NULL(intel_connector->edid))
		kfree(intel_connector->edid);

	if (is_edp(intel_dp)) {
		intel_panel_destroy_backlight(dev);
		intel_panel_fini(&intel_connector->panel);
@@ -2523,7 +2527,6 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
	i2c_del_adapter(&intel_dp->adapter);
	drm_encoder_cleanup(encoder);
	if (is_edp(intel_dp)) {
		kfree(intel_dp->edid);
		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
		ironlake_panel_vdd_off_sync(intel_dp);
	}
@@ -2810,13 +2813,17 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
		ironlake_edp_panel_vdd_on(intel_dp);
		edid = drm_get_edid(connector, &intel_dp->adapter);
		if (edid) {
			drm_mode_connector_update_edid_property(connector,
								edid);
			intel_dp->edid_mode_count =
				drm_add_edid_modes(connector, edid);
			if (drm_add_edid_modes(connector, edid)) {
				drm_mode_connector_update_edid_property(connector, edid);
				drm_edid_to_eld(connector, edid);
			intel_dp->edid = edid;
			} else {
				kfree(edid);
				edid = ERR_PTR(-EINVAL);
			}
		} else {
			edid = ERR_PTR(-ENOENT);
		}
		intel_connector->edid = edid;

		/* prefer fixed mode from EDID if available */
		list_for_each_entry(scan, &connector->probed_modes, head) {
+3 −2
Original line number Diff line number Diff line
@@ -186,6 +186,9 @@ struct intel_connector {

	/* Panel info for eDP and LVDS */
	struct intel_panel panel;

	/* Cached EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */
	struct edid *edid;
};

struct intel_crtc {
@@ -367,8 +370,6 @@ struct intel_dp {
	int backlight_off_delay;
	struct delayed_work panel_vdd_work;
	bool want_panel_vdd;
	struct edid *edid; /* cached EDID for eDP */
	int edid_mode_count;
	struct intel_connector *attached_connector;
};

+23 −11
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ struct intel_lvds_connector {
	struct intel_connector base;

	struct notifier_block lid_notifier;
	struct edid *edid;
	int fitting_mode;
};

@@ -460,8 +459,14 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
	struct drm_device *dev = connector->dev;
	struct drm_display_mode *mode;

	if (lvds_connector->edid)
		return drm_add_edid_modes(connector, lvds_connector->edid);
	/* use cached edid if we have one */
	if (lvds_connector->base.edid) {
		/* invalid edid */
		if (IS_ERR(lvds_connector->base.edid))
			return 0;

		return drm_add_edid_modes(connector, lvds_connector->base.edid);
	}

	mode = drm_mode_duplicate(dev, lvds_connector->base.panel.fixed_mode);
	if (mode == NULL)
@@ -553,6 +558,9 @@ static void intel_lvds_destroy(struct drm_connector *connector)
	if (lvds_connector->lid_notifier.notifier_call)
		acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);

	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
		kfree(lvds_connector->base.edid);

	intel_panel_destroy_backlight(connector->dev);
	intel_panel_fini(&lvds_connector->base.panel);

@@ -922,6 +930,7 @@ bool intel_lvds_init(struct drm_device *dev)
	struct drm_encoder *encoder;
	struct drm_display_mode *scan; /* *modes, *bios_mode; */
	struct drm_display_mode *fixed_mode = NULL;
	struct edid *edid;
	struct drm_crtc *crtc;
	u32 lvds;
	int pipe;
@@ -1021,18 +1030,21 @@ bool intel_lvds_init(struct drm_device *dev)
	 * Attempt to get the fixed panel mode from DDC.  Assume that the
	 * preferred mode is the right one.
	 */
	lvds_connector->edid = drm_get_edid(connector,
					    intel_gmbus_get_adapter(dev_priv, pin));
	if (lvds_connector->edid) {
		if (drm_add_edid_modes(connector, lvds_connector->edid)) {
	edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin));
	if (edid) {
		if (drm_add_edid_modes(connector, edid)) {
			drm_mode_connector_update_edid_property(connector,
								lvds_connector->edid);
								edid);
		} else {
			kfree(lvds_connector->edid);
			lvds_connector->edid = NULL;
			kfree(edid);
			edid = ERR_PTR(-EINVAL);
		}
	} else {
		edid = ERR_PTR(-ENOENT);
	}
	if (!lvds_connector->edid) {
	lvds_connector->base.edid = edid;

	if (IS_ERR_OR_NULL(edid)) {
		/* Didn't get an EDID, so
		 * Set wide sync ranges so we get all modes
		 * handed to valid_mode for checking