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
1 changed files with 89 additions and 76 deletions
|
@ -3395,20 +3395,94 @@ 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 */
|
}
|
||||||
|
|
||||||
|
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,
|
if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
|
||||||
&intel_dp->sink_count, 1) < 0)
|
&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)
|
if (!is_edp(intel_dp) && !intel_dp->sink_count)
|
||||||
return false;
|
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] &
|
if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
|
||||||
DP_DWN_STRM_PORT_PRESENT))
|
DP_DWN_STRM_PORT_PRESENT))
|
||||||
return true; /* native DP sink */
|
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)
|
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue