Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dda9a66a authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter
Browse files

drm/i915: Disable/enable planes as the first/last thing during modeset on HSW



Refactor the plane enabling/disabling into helper functions and move
the calls to happen as the first thing during .crtc_disable, and the
last thing during .crtc_enable.

Those are the two clear points where we are sure that the pipe is
actually running regardless of the encoder type or hardware
generation.

v2: Made by Paulo:
  Remove the code touching everything but the Haswell functions. We
  need this change on Haswell right now since it fixes a FIFO underrun
  that we get on pipe A while we enable pipe B (see the workaround
  notes on the Haswell mode set sequence documentation). We can bring
  back the code to gens 2-7 later, once they're tested.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent f6071166
Loading
Loading
Loading
Loading
+45 −24
Original line number Diff line number Diff line
@@ -3453,6 +3453,47 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
	return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
}

static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
{
	struct drm_device *dev = crtc->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	int pipe = intel_crtc->pipe;
	int plane = intel_crtc->plane;

	intel_enable_plane(dev_priv, plane, pipe);
	intel_enable_planes(crtc);
	intel_crtc_update_cursor(crtc, true);

	hsw_enable_ips(intel_crtc);

	mutex_lock(&dev->struct_mutex);
	intel_update_fbc(dev);
	mutex_unlock(&dev->struct_mutex);
}

static void haswell_crtc_disable_planes(struct drm_crtc *crtc)
{
	struct drm_device *dev = crtc->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	int pipe = intel_crtc->pipe;
	int plane = intel_crtc->plane;

	intel_crtc_wait_for_pending_flips(crtc);
	drm_vblank_off(dev, pipe);

	/* FBC must be disabled before disabling the plane on HSW. */
	if (dev_priv->fbc.plane == plane)
		intel_disable_fbc(dev);

	hsw_disable_ips(intel_crtc);

	intel_crtc_update_cursor(crtc, false);
	intel_disable_planes(crtc);
	intel_disable_plane(dev_priv, plane, pipe);
}

static void haswell_crtc_enable(struct drm_crtc *crtc)
{
	struct drm_device *dev = crtc->dev;
@@ -3460,7 +3501,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_encoder *encoder;
	int pipe = intel_crtc->pipe;
	int plane = intel_crtc->plane;

	WARN_ON(!crtc->enabled);

@@ -3496,24 +3536,17 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
	intel_update_watermarks(crtc);
	intel_enable_pipe(dev_priv, pipe,
			  intel_crtc->config.has_pch_encoder, false);
	intel_enable_plane(dev_priv, plane, pipe);
	intel_enable_planes(crtc);
	intel_crtc_update_cursor(crtc, true);

	hsw_enable_ips(intel_crtc);

	if (intel_crtc->config.has_pch_encoder)
		lpt_pch_enable(crtc);

	mutex_lock(&dev->struct_mutex);
	intel_update_fbc(dev);
	mutex_unlock(&dev->struct_mutex);

	for_each_encoder_on_crtc(dev, crtc, encoder) {
		encoder->enable(encoder);
		intel_opregion_notify_encoder(encoder, true);
	}

	haswell_crtc_enable_planes(crtc);

	/*
	 * There seems to be a race in PCH platform hw (at least on some
	 * outputs) where an enabled pipe still completes any pageflip right
@@ -3620,30 +3653,18 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	struct intel_encoder *encoder;
	int pipe = intel_crtc->pipe;
	int plane = intel_crtc->plane;
	enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;

	if (!intel_crtc->active)
		return;

	haswell_crtc_disable_planes(crtc);

	for_each_encoder_on_crtc(dev, crtc, encoder) {
		intel_opregion_notify_encoder(encoder, false);
		encoder->disable(encoder);
	}

	intel_crtc_wait_for_pending_flips(crtc);
	drm_vblank_off(dev, pipe);

	/* FBC must be disabled before disabling the plane on HSW. */
	if (dev_priv->fbc.plane == plane)
		intel_disable_fbc(dev);

	hsw_disable_ips(intel_crtc);

	intel_crtc_update_cursor(crtc, false);
	intel_disable_planes(crtc);
	intel_disable_plane(dev_priv, plane, pipe);

	if (intel_crtc->config.has_pch_encoder)
		intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
	intel_disable_pipe(dev_priv, pipe);