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: Ville 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
			
			
This commit is contained in:
		
							parent
							
								
									1dd5b6f202
								
							
						
					
					
						commit
						fe5a66f91c
					
				| @ -3395,20 +3395,94 @@ intel_dp_link_down(struct intel_dp *intel_dp) | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
| 			     sizeof(intel_dp->dpcd)) < 0) | ||||
| 		return false; /* aux transfer failed */ | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd); | ||||
| 
 | ||||
| 	if (intel_dp->dpcd[DP_DPCD_REV] == 0) | ||||
| 		return false; /* DPCD not present */ | ||||
| 	return intel_dp->dpcd[DP_DPCD_REV] != 0; | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
| intel_edp_init_dpcd(struct intel_dp *intel_dp) | ||||
| { | ||||
| 	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 */ | ||||
| 	WARN_ON(intel_dp->dpcd[DP_DPCD_REV] != 0); | ||||
| 
 | ||||
| 	if (!intel_dp_read_dpcd(intel_dp)) | ||||
| 		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 */ | ||||
| 	drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, | ||||
| 			 intel_dp->psr_dpcd, | ||||
| 			 sizeof(intel_dp->psr_dpcd)); | ||||
| 	if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) { | ||||
| 		dev_priv->psr.sink_support = true; | ||||
| 		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (INTEL_GEN(dev_priv) >= 9 && | ||||
| 	    (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { | ||||
| 		uint8_t frame_sync_cap; | ||||
| 
 | ||||
| 		dev_priv->psr.sink_support = true; | ||||
| 		drm_dp_dpcd_read(&intel_dp->aux, | ||||
| 				 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP, | ||||
| 				 &frame_sync_cap, 1); | ||||
| 		dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false; | ||||
| 		/* PSR2 needs frame sync as well */ | ||||
| 		dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync; | ||||
| 		DRM_DEBUG_KMS("PSR2 %s on sink", | ||||
| 			      dev_priv->psr.psr2_support ? "supported" : "not supported"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Read the eDP Display control capabilities registers */ | ||||
| 	if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) && | ||||
| 	    drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, | ||||
| 			     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), | ||||
| 			      intel_dp->edp_dpcd); | ||||
| 
 | ||||
| 	/* Intermediate frequency support */ | ||||
| 	if (intel_dp->edp_dpcd[0] >= 0x03) { /* eDp v1.4 or higher */ | ||||
| 		__le16 sink_rates[DP_MAX_SUPPORTED_RATES]; | ||||
| 		int i; | ||||
| 
 | ||||
| 		drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES, | ||||
| 				sink_rates, sizeof(sink_rates)); | ||||
| 
 | ||||
| 		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) { | ||||
| 			int val = le16_to_cpu(sink_rates[i]); | ||||
| 
 | ||||
| 			if (val == 0) | ||||
| 				break; | ||||
| 
 | ||||
| 			/* Value read is in kHz while drm clock is saved in deca-kHz */ | ||||
| 			intel_dp->sink_rates[i] = (val * 200) / 10; | ||||
| 		} | ||||
| 		intel_dp->num_sink_rates = i; | ||||
| 	} | ||||
| 
 | ||||
| 	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) | ||||
| @ -3431,68 +3505,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) | ||||
| 	if (!is_edp(intel_dp) && !intel_dp->sink_count) | ||||
| 		return false; | ||||
| 
 | ||||
| 	/* 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, | ||||
| 				 intel_dp->psr_dpcd, | ||||
| 				 sizeof(intel_dp->psr_dpcd)); | ||||
| 		if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) { | ||||
| 			dev_priv->psr.sink_support = true; | ||||
| 			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (INTEL_INFO(dev)->gen >= 9 && | ||||
| 			(intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) { | ||||
| 			uint8_t frame_sync_cap; | ||||
| 
 | ||||
| 			dev_priv->psr.sink_support = true; | ||||
| 			drm_dp_dpcd_read(&intel_dp->aux, | ||||
| 					 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP, | ||||
| 					 &frame_sync_cap, 1); | ||||
| 			dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false; | ||||
| 			/* PSR2 needs frame sync as well */ | ||||
| 			dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync; | ||||
| 			DRM_DEBUG_KMS("PSR2 %s on sink", | ||||
| 				dev_priv->psr.psr2_support ? "supported" : "not supported"); | ||||
| 		} | ||||
| 
 | ||||
| 		/* 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) && | ||||
| 				(drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, | ||||
| 						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), | ||||
| 					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 */ | ||||
| 	if (is_edp(intel_dp) && (intel_dp->edp_dpcd[0] >= 0x03)) { /* eDp v1.4 or higher */ | ||||
| 		__le16 sink_rates[DP_MAX_SUPPORTED_RATES]; | ||||
| 		int i; | ||||
| 
 | ||||
| 		drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES, | ||||
| 				sink_rates, sizeof(sink_rates)); | ||||
| 
 | ||||
| 		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) { | ||||
| 			int val = le16_to_cpu(sink_rates[i]); | ||||
| 
 | ||||
| 			if (val == 0) | ||||
| 				break; | ||||
| 
 | ||||
| 			/* Value read is in kHz while drm clock is saved in deca-kHz */ | ||||
| 			intel_dp->sink_rates[i] = (val * 200) / 10; | ||||
| 		} | ||||
| 		intel_dp->num_sink_rates = i; | ||||
| 	} | ||||
| 
 | ||||
| 	intel_dp_print_rates(intel_dp); | ||||
| 
 | ||||
| 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & | ||||
| 	      DP_DWN_STRM_PORT_PRESENT)) | ||||
| 		return true; /* native DP sink */ | ||||
| @ -4252,6 +4264,12 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) | ||||
| 	if (intel_encoder->type != INTEL_OUTPUT_EDP) | ||||
| 		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); | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 	/* 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 (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 (!has_dpcd) { | ||||
| 		/* if this fails, presume the device is a ghost */ | ||||
| 		DRM_INFO("failed to retrieve link info, disabling eDP\n"); | ||||
| 		goto out_vdd_off; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user