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
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ad74d1d..eda1aa0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6263,6 +6263,9 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
struct intel_crtc_state *pipe_config)
{
+ if (pipe_config->ips_force_disable)
+ return false;
+
if (pipe_config->pipe_bpp > 24)
return false;
@@ -10830,7 +10833,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
struct intel_dpll_hw_state dpll_hw_state;
struct intel_shared_dpll *shared_dpll;
struct intel_crtc_wm_state wm_state;
- bool force_thru;
+ bool force_thru, ips_force_disable;
/* FIXME: before the switch to atomic started, a new pipe_config was
* kzalloc'd. Code that depends on any field being zero should be
@@ -10841,6 +10844,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
shared_dpll = crtc_state->shared_dpll;
dpll_hw_state = crtc_state->dpll_hw_state;
force_thru = crtc_state->pch_pfit.force_thru;
+ ips_force_disable = crtc_state->ips_force_disable;
if (IS_G4X(dev_priv) ||
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
wm_state = crtc_state->wm;
@@ -10854,6 +10858,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
crtc_state->shared_dpll = shared_dpll;
crtc_state->dpll_hw_state = dpll_hw_state;
crtc_state->pch_pfit.force_thru = force_thru;
+ crtc_state->ips_force_disable = ips_force_disable;
if (IS_G4X(dev_priv) ||
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
crtc_state->wm = wm_state;