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

Commit fe5a66f9 authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP



Currently we re-read a bunch of static eDP panel caps from the DPCD
over and over again. Let's do it only once to save some time and effort.

v2: Make thing less confusing with intel_edp_init_dpcd() (Chris)
    Move no_aux_handshake setup in there as well
v3: Move tps3/rate printout to intel_dp_long_pulse() so that
    we'll still get them on eDP as well

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Link: http://patchwork.freedesktop.org/patch/msgid/1469800359-7087-1-git-send-email-ville.syrjala@linux.intel.com
parent 1dd5b6f2
Loading
Loading
Loading
Loading
+84 −71
Original line number Original line Diff line number Diff line
@@ -3395,45 +3395,34 @@ intel_dp_link_down(struct intel_dp *intel_dp)
}
}


static bool
static bool
intel_dp_get_dpcd(struct intel_dp *intel_dp)
intel_dp_read_dpcd(struct intel_dp *intel_dp)
{
{
	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
	struct drm_device *dev = dig_port->base.base.dev;
	struct drm_i915_private *dev_priv = to_i915(dev);

	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
			     sizeof(intel_dp->dpcd)) < 0)
			     sizeof(intel_dp->dpcd)) < 0)
		return false; /* aux transfer failed */
		return false; /* aux transfer failed */


	DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd);
	DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd);


	if (intel_dp->dpcd[DP_DPCD_REV] == 0)
	return intel_dp->dpcd[DP_DPCD_REV] != 0;
		return false; /* DPCD not present */
}


	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
static bool
			     &intel_dp->sink_count, 1) < 0)
intel_edp_init_dpcd(struct intel_dp *intel_dp)
		return false;
{
	struct drm_i915_private *dev_priv =
		to_i915(dp_to_dig_port(intel_dp)->base.base.dev);


	/*
	/* this function is meant to be called only once */
	 * Sink count can change between short pulse hpd hence
	WARN_ON(intel_dp->dpcd[DP_DPCD_REV] != 0);
	 * a member variable in intel_dp will track any changes
	 * between short pulse interrupts.
	 */
	intel_dp->sink_count = DP_GET_SINK_COUNT(intel_dp->sink_count);


	/*
	if (!intel_dp_read_dpcd(intel_dp))
	 * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that
	 * a dongle is present but no display. Unless we require to know
	 * if a dongle is present or not, we don't need to update
	 * downstream port information. So, an early return here saves
	 * time from performing other operations which are not required.
	 */
	if (!is_edp(intel_dp) && !intel_dp->sink_count)
		return false;
		return false;


	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
		dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
			DP_NO_AUX_HANDSHAKE_LINK_TRAINING;

	/* Check if the panel supports PSR */
	/* Check if the panel supports PSR */
	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
	if (is_edp(intel_dp)) {
	drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
	drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
			 intel_dp->psr_dpcd,
			 intel_dp->psr_dpcd,
			 sizeof(intel_dp->psr_dpcd));
			 sizeof(intel_dp->psr_dpcd));
@@ -3442,7 +3431,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
	}
	}


		if (INTEL_INFO(dev)->gen >= 9 &&
	if (INTEL_GEN(dev_priv) >= 9 &&
	    (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
	    (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
		uint8_t frame_sync_cap;
		uint8_t frame_sync_cap;


@@ -3458,21 +3447,15 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
	}
	}


	/* Read the eDP Display control capabilities registers */
	/* Read the eDP Display control capabilities registers */
		memset(intel_dp->edp_dpcd, 0, sizeof(intel_dp->edp_dpcd));
	if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
	if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
				(drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,
	    drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,
						intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) ==
			     intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd) ==
			     sizeof(intel_dp->edp_dpcd)))
			     sizeof(intel_dp->edp_dpcd)))
		DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),
		DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),
			      intel_dp->edp_dpcd);
			      intel_dp->edp_dpcd);
	}

	DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n",
		      yesno(intel_dp_source_supports_hbr2(intel_dp)),
		      yesno(drm_dp_tps3_supported(intel_dp->dpcd)));


	/* Intermediate frequency support */
	/* Intermediate frequency support */
	if (is_edp(intel_dp) && (intel_dp->edp_dpcd[0] >= 0x03)) { /* eDp v1.4 or higher */
	if (intel_dp->edp_dpcd[0] >= 0x03) { /* eDp v1.4 or higher */
		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
		int i;
		int i;


@@ -3491,7 +3474,36 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
		intel_dp->num_sink_rates = i;
		intel_dp->num_sink_rates = i;
	}
	}


	intel_dp_print_rates(intel_dp);
	return true;
}


static bool
intel_dp_get_dpcd(struct intel_dp *intel_dp)
{
	if (!intel_dp_read_dpcd(intel_dp))
		return false;

	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
			     &intel_dp->sink_count, 1) < 0)
		return false;

	/*
	 * Sink count can change between short pulse hpd hence
	 * a member variable in intel_dp will track any changes
	 * between short pulse interrupts.
	 */
	intel_dp->sink_count = DP_GET_SINK_COUNT(intel_dp->sink_count);

	/*
	 * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that
	 * a dongle is present but no display. Unless we require to know
	 * if a dongle is present or not, we don't need to update
	 * downstream port information. So, an early return here saves
	 * time from performing other operations which are not required.
	 */
	if (!is_edp(intel_dp) && !intel_dp->sink_count)
		return false;


	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
	      DP_DWN_STRM_PORT_PRESENT))
	      DP_DWN_STRM_PORT_PRESENT))
@@ -4252,6 +4264,12 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
	if (intel_encoder->type != INTEL_OUTPUT_EDP)
	if (intel_encoder->type != INTEL_OUTPUT_EDP)
		intel_encoder->type = INTEL_OUTPUT_DP;
		intel_encoder->type = INTEL_OUTPUT_DP;


	DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n",
		      yesno(intel_dp_source_supports_hbr2(intel_dp)),
		      yesno(drm_dp_tps3_supported(intel_dp->dpcd)));

	intel_dp_print_rates(intel_dp);

	intel_dp_probe_oui(intel_dp);
	intel_dp_probe_oui(intel_dp);


	ret = intel_dp_probe_mst(intel_dp);
	ret = intel_dp_probe_mst(intel_dp);
@@ -5413,14 +5431,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
	pps_unlock(intel_dp);
	pps_unlock(intel_dp);


	/* Cache DPCD and EDID for edp. */
	/* Cache DPCD and EDID for edp. */
	has_dpcd = intel_dp_get_dpcd(intel_dp);
	has_dpcd = intel_edp_init_dpcd(intel_dp);


	if (has_dpcd) {
	if (!has_dpcd) {
		if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
			dev_priv->no_aux_handshake =
				intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
				DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
	} else {
		/* if this fails, presume the device is a ghost */
		/* if this fails, presume the device is a ghost */
		DRM_INFO("failed to retrieve link info, disabling eDP\n");
		DRM_INFO("failed to retrieve link info, disabling eDP\n");
		goto out_vdd_off;
		goto out_vdd_off;