summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_pipe_crc.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2017-08-17 17:55:09 +0300
committerVille Syrjälä <ville.syrjala@linux.intel.com>2017-08-25 14:44:38 +0300
commit6e644626945c7c1a7f4d4f83b806b898297846d0 (patch)
tree031e60f059b274712325b0f6f57d0c7fc8f4e4a1 /drivers/gpu/drm/i915/intel_pipe_crc.c
parent3814fd77691c0b35acefc68d5af516f9d48a4281 (diff)
drm/i915: Beef up the IPS vs. CRC workaround
Oneshot disabling of IPS when CRC capturing is started is insufficient. IPS may get re-enabled by any plane update, and hence tests that keep CRC capturing on across plane updates will start to see inconsistent results as soon as IPS kicks back in. Add a new knob into the crtc state to make sure IPS stays disabled as long as CRC capturing is enabled. Forcing a modeset is the easiest way to handle this since that's already how we do the panel fitter workaround. It's a little heavy handed just for IPS, but seeing as we might already do the panel fitter workaround I think it's better to follow that. We migth want to optimize both cases later if someone gets too upset by the extra delay from the modeset. v2: Check the right thing when deciding whether to force a modeset v3: Rebase, check HAS_IPS before forcing a modeset, move ips_force_disable check into pipe_config_supports_ips() Cc: Paulo Zanoni <paulo.r.zanoni@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Marta Lofstedt <marta.lofstedt@intel.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101664 Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Tested-by: Marta Lofsted <marta.lofstedt@intel.com> #v2 Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20170817145509.15549-1-ville.syrjala@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pipe_crc.c')
-rw-r--r--drivers/gpu/drm/i915/intel_pipe_crc.c62
1 files changed, 29 insertions, 33 deletions
diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c
index 8fbd2bd0877f..4e22bb927fed 100644
--- a/drivers/gpu/drm/i915/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/intel_pipe_crc.c
@@ -506,8 +506,8 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
return 0;
}
-static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv,
- bool enable)
+static void hsw_pipe_A_crc_wa(struct drm_i915_private *dev_priv,
+ bool enable)
{
struct drm_device *dev = &dev_priv->drm;
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
@@ -533,10 +533,24 @@ retry:
goto put_state;
}
- pipe_config->pch_pfit.force_thru = enable;
- if (pipe_config->cpu_transcoder == TRANSCODER_EDP &&
- pipe_config->pch_pfit.enabled != enable)
- pipe_config->base.connectors_changed = true;
+ if (HAS_IPS(dev_priv)) {
+ /*
+ * When IPS gets enabled, the pipe CRC changes. Since IPS gets
+ * enabled and disabled dynamically based on package C states,
+ * user space can't make reliable use of the CRCs, so let's just
+ * completely disable it.
+ */
+ pipe_config->ips_force_disable = enable;
+ if (pipe_config->ips_enabled == enable)
+ pipe_config->base.connectors_changed = true;
+ }
+
+ if (IS_HASWELL(dev_priv)) {
+ pipe_config->pch_pfit.force_thru = enable;
+ if (pipe_config->cpu_transcoder == TRANSCODER_EDP &&
+ pipe_config->pch_pfit.enabled != enable)
+ pipe_config->base.connectors_changed = true;
+ }
ret = drm_atomic_commit(state);
@@ -570,8 +584,9 @@ static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
break;
case INTEL_PIPE_CRC_SOURCE_PF:
- if (IS_HASWELL(dev_priv) && pipe == PIPE_A)
- hsw_trans_edp_pipe_A_crc_wa(dev_priv, true);
+ if ((IS_HASWELL(dev_priv) ||
+ IS_BROADWELL(dev_priv)) && pipe == PIPE_A)
+ hsw_pipe_A_crc_wa(dev_priv, true);
*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
break;
@@ -606,7 +621,6 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv,
enum intel_pipe_crc_source source)
{
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
- struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
enum intel_display_power_domain power_domain;
u32 val = 0; /* shut up gcc */
int ret;
@@ -643,14 +657,6 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv,
goto out;
}
- /*
- * When IPS gets enabled, the pipe CRC changes. Since IPS gets
- * enabled and disabled dynamically based on package C states,
- * user space can't make reliable use of the CRCs, so let's just
- * completely disable it.
- */
- hsw_disable_ips(crtc);
-
spin_lock_irq(&pipe_crc->lock);
kfree(pipe_crc->entries);
pipe_crc->entries = entries;
@@ -691,10 +697,9 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv,
g4x_undo_pipe_scramble_reset(dev_priv, pipe);
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_undo_pipe_scramble_reset(dev_priv, pipe);
- else if (IS_HASWELL(dev_priv) && pipe == PIPE_A)
- hsw_trans_edp_pipe_A_crc_wa(dev_priv, false);
-
- hsw_enable_ips(crtc);
+ else if ((IS_HASWELL(dev_priv) ||
+ IS_BROADWELL(dev_priv)) && pipe == PIPE_A)
+ hsw_pipe_A_crc_wa(dev_priv, false);
}
ret = 0;
@@ -935,16 +940,6 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name,
if (ret != 0)
goto out;
- if (source) {
- /*
- * When IPS gets enabled, the pipe CRC changes. Since IPS gets
- * enabled and disabled dynamically based on package C states,
- * user space can't make reliable use of the CRCs, so let's just
- * completely disable it.
- */
- hsw_disable_ips(intel_crtc);
- }
-
I915_WRITE(PIPE_CRC_CTL(crtc->index), val);
POSTING_READ(PIPE_CRC_CTL(crtc->index));
@@ -953,8 +948,9 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name,
g4x_undo_pipe_scramble_reset(dev_priv, crtc->index);
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_undo_pipe_scramble_reset(dev_priv, crtc->index);
- else if (IS_HASWELL(dev_priv) && crtc->index == PIPE_A)
- hsw_trans_edp_pipe_A_crc_wa(dev_priv, false);
+ else if ((IS_HASWELL(dev_priv) ||
+ IS_BROADWELL(dev_priv)) && crtc->index == PIPE_A)
+ hsw_pipe_A_crc_wa(dev_priv, false);
hsw_enable_ips(intel_crtc);
}