Commit 4d90f2d5 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Start tracking PSR state in crtc state

Add the minimal amount of PSR tracking into the crtc state. This allows
precomputing the possibility of using PSR correctly, and it means we can
safely call the psr enable/disable functions for any DP endcoder.

As a nice bonus we get rid of some more crtc->config usage, which we
want to kill off eventually.

v2: Fix 'goto unlock' fail in intel_psr_enable() (Jani)
    Check intel_dp_is_edp() in is_edp_psr() (Jani)

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171012130201.21318-1-ville.syrjala@linux.intel.comReviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Acked-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent fa9caf0b
...@@ -1832,6 +1832,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -1832,6 +1832,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (!HAS_DDI(dev_priv)) if (!HAS_DDI(dev_priv))
intel_dp_set_clock(encoder, pipe_config); intel_dp_set_clock(encoder, pipe_config);
intel_psr_compute_config(intel_dp, pipe_config);
return true; return true;
} }
......
...@@ -718,6 +718,9 @@ struct intel_crtc_state { ...@@ -718,6 +718,9 @@ struct intel_crtc_state {
struct intel_link_m_n dp_m2_n2; struct intel_link_m_n dp_m2_n2;
bool has_drrs; bool has_drrs;
bool has_psr;
bool has_psr2;
/* /*
* Frequence the dpll for the port should run at. Differs from the * Frequence the dpll for the port should run at. Differs from the
* adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
...@@ -1764,6 +1767,8 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, ...@@ -1764,6 +1767,8 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
void intel_psr_init(struct drm_i915_private *dev_priv); void intel_psr_init(struct drm_i915_private *dev_priv);
void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, void intel_psr_single_frame_update(struct drm_i915_private *dev_priv,
unsigned frontbuffer_bits); unsigned frontbuffer_bits);
void intel_psr_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state);
/* intel_runtime_pm.c */ /* intel_runtime_pm.c */
int intel_power_domains_init(struct drm_i915_private *); int intel_power_domains_init(struct drm_i915_private *);
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
static bool is_edp_psr(struct intel_dp *intel_dp) static bool is_edp_psr(struct intel_dp *intel_dp)
{ {
if (!intel_dp_is_edp(intel_dp))
return false;
return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED;
} }
...@@ -376,22 +379,25 @@ static void hsw_psr_activate(struct intel_dp *intel_dp) ...@@ -376,22 +379,25 @@ static void hsw_psr_activate(struct intel_dp *intel_dp)
hsw_activate_psr1(intel_dp); hsw_activate_psr1(intel_dp);
} }
static bool intel_psr_match_conditions(struct intel_dp *intel_dp) void intel_psr_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{ {
struct intel_digital_port *dig_port = dp_to_dig_port(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(dig_port->base.base.dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *crtc = dig_port->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
const struct drm_display_mode *adjusted_mode = const struct drm_display_mode *adjusted_mode =
&intel_crtc->config->base.adjusted_mode; &crtc_state->base.adjusted_mode;
int psr_setup_time; int psr_setup_time;
lockdep_assert_held(&dev_priv->psr.lock); if (!HAS_PSR(dev_priv))
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); return;
WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
dev_priv->psr.source_ok = false; if (!is_edp_psr(intel_dp))
return;
if (!i915_modparams.enable_psr) {
DRM_DEBUG_KMS("PSR disable by flag\n");
return;
}
/* /*
* HSW spec explicitly says PSR is tied to port A. * HSW spec explicitly says PSR is tied to port A.
...@@ -402,66 +408,70 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) ...@@ -402,66 +408,70 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
*/ */
if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) { if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) {
DRM_DEBUG_KMS("PSR condition failed: Port not supported\n"); DRM_DEBUG_KMS("PSR condition failed: Port not supported\n");
return false; return;
}
if (!i915_modparams.enable_psr) {
DRM_DEBUG_KMS("PSR disable by flag\n");
return false;
} }
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
!dev_priv->psr.link_standby) { !dev_priv->psr.link_standby) {
DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n"); DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n");
return false; return;
} }
if (IS_HASWELL(dev_priv) && if (IS_HASWELL(dev_priv) &&
I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) & I915_READ(HSW_STEREO_3D_CTL(crtc_state->cpu_transcoder)) &
S3D_ENABLE) { S3D_ENABLE) {
DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n"); DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
return false; return;
} }
if (IS_HASWELL(dev_priv) && if (IS_HASWELL(dev_priv) &&
adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
return false; return;
} }
psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd); psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
if (psr_setup_time < 0) { if (psr_setup_time < 0) {
DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n", DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n",
intel_dp->psr_dpcd[1]); intel_dp->psr_dpcd[1]);
return false; return;
} }
if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) > if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) { adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) {
DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n", DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n",
psr_setup_time); psr_setup_time);
return false; return;
}
/*
* FIXME psr2_support is messed up. It's both computed
* dynamically during PSR enable, and extracted from sink
* caps during eDP detection.
*/
if (!dev_priv->psr.psr2_support) {
crtc_state->has_psr = true;
return;
} }
/* PSR2 is restricted to work with panel resolutions upto 3200x2000 */ /* PSR2 is restricted to work with panel resolutions upto 3200x2000 */
if (dev_priv->psr.psr2_support && if (adjusted_mode->crtc_hdisplay > 3200 ||
(intel_crtc->config->pipe_src_w > 3200 || adjusted_mode->crtc_vdisplay > 2000) {
intel_crtc->config->pipe_src_h > 2000)) { DRM_DEBUG_KMS("PSR2 disabled, panel resolution too big\n");
dev_priv->psr.psr2_support = false; return;
return false;
} }
/* /*
* FIXME:enable psr2 only for y-cordinate psr2 panels * FIXME:enable psr2 only for y-cordinate psr2 panels
* After gtc implementation , remove this restriction. * After gtc implementation , remove this restriction.
*/ */
if (!dev_priv->psr.y_cord_support && dev_priv->psr.psr2_support) { if (!dev_priv->psr.y_cord_support) {
DRM_DEBUG_KMS("PSR2 disabled, panel does not support Y coordinate\n"); DRM_DEBUG_KMS("PSR2 disabled, panel does not support Y coordinate\n");
return false; return;
} }
dev_priv->psr.source_ok = true; crtc_state->has_psr = true;
return true; crtc_state->has_psr2 = true;
} }
static void intel_psr_activate(struct intel_dp *intel_dp) static void intel_psr_activate(struct intel_dp *intel_dp)
...@@ -531,13 +541,8 @@ void intel_psr_enable(struct intel_dp *intel_dp, ...@@ -531,13 +541,8 @@ void intel_psr_enable(struct intel_dp *intel_dp,
struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
if (!HAS_PSR(dev_priv)) if (!crtc_state->has_psr)
return;
if (!is_edp_psr(intel_dp)) {
DRM_DEBUG_KMS("PSR not supported by this panel\n");
return; return;
}
WARN_ON(dev_priv->drrs.dp); WARN_ON(dev_priv->drrs.dp);
mutex_lock(&dev_priv->psr.lock); mutex_lock(&dev_priv->psr.lock);
...@@ -546,8 +551,8 @@ void intel_psr_enable(struct intel_dp *intel_dp, ...@@ -546,8 +551,8 @@ void intel_psr_enable(struct intel_dp *intel_dp,
goto unlock; goto unlock;
} }
if (!intel_psr_match_conditions(intel_dp)) dev_priv->psr.psr2_support = crtc_state->has_psr2;
goto unlock; dev_priv->psr.source_ok = true;
dev_priv->psr.busy_frontbuffer_bits = 0; dev_priv->psr.busy_frontbuffer_bits = 0;
...@@ -668,7 +673,7 @@ void intel_psr_disable(struct intel_dp *intel_dp, ...@@ -668,7 +673,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
if (!HAS_PSR(dev_priv)) if (!old_crtc_state->has_psr)
return; return;
mutex_lock(&dev_priv->psr.lock); mutex_lock(&dev_priv->psr.lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment