Intel-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] drm/i915: factor out GMCH panel fitting code and use for eDP v3
@ 2013-04-25 19:55 Jesse Barnes
  2013-04-25 19:55 ` [PATCH 2/3] drm/i915: move PCH pfit controls into pipe_config Jesse Barnes
  2013-04-25 19:55 ` [PATCH 3/3] drm/i915: warn about invalid pfit modes Jesse Barnes
  0 siblings, 2 replies; 6+ messages in thread
From: Jesse Barnes @ 2013-04-25 19:55 UTC (permalink / raw)
  To: intel-gfx

This gets the panel fitter working on eDP on VLV, and should also apply
to eDP panels on G4x chipsets (if we ever detect and mark an all-in-one
panel as eDP anyway).

A few cleanups are still possible on top of this, for example the LVDS
border control could be placed in the LVDS encoder structure and updated
based on the result of the panel fitter calculation.

Multi-pipe fitting isn't handled correctly either if we ever get a config
that wants to try the panel fitter on more than one output at a time.

v2: use pipe_config for storing pfit values (Daniel)
    add i9xx_pfit_enable function for use by 9xx and VLV (Daniel)
v3: fixup conflicts and lvds_dither check

Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/intel_display.c |   33 ++++++
 drivers/gpu/drm/i915/intel_dp.c      |   11 +-
 drivers/gpu/drm/i915/intel_drv.h     |    6 +
 drivers/gpu/drm/i915/intel_lvds.c    |  209 +---------------------------------
 drivers/gpu/drm/i915/intel_panel.c   |  191 +++++++++++++++++++++++++++++++
 5 files changed, 241 insertions(+), 209 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2e83dbe..fc6f768 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3601,6 +3601,33 @@ g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
 	}
 }
 
+static void i9xx_pfit_enable(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc_config *pipe_config = &crtc->config;
+
+	if (!(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
+	      intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)))
+		return;
+
+	WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
+	assert_pipe_disabled(dev_priv, crtc->pipe);
+
+	/*
+	 * Enable automatic panel scaling so that non-native modes
+	 * fill the screen.  The panel fitter should only be
+	 * adjusted whilst the pipe is disabled, according to
+	 * register description and PRM.
+	 */
+	DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
+		      pipe_config->pfit_control,
+		      pipe_config->pfit_pgm_ratios);
+
+	I915_WRITE(PFIT_PGM_RATIOS, pipe_config->pfit_pgm_ratios);
+	I915_WRITE(PFIT_CONTROL, pipe_config->pfit_control);
+}
+
 static void valleyview_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3634,6 +3661,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 
+	/* Enable panel fitting for eDP */
+	i9xx_pfit_enable(intel_crtc);
+
 	intel_enable_pipe(dev_priv, pipe, false);
 	intel_enable_plane(dev_priv, plane, pipe);
 
@@ -3670,6 +3700,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
 
+	/* Enable panel fitting for LVDS */
+	i9xx_pfit_enable(intel_crtc);
+
 	intel_enable_pipe(dev_priv, pipe, false);
 	intel_enable_plane(dev_priv, plane, pipe);
 	if (IS_G4X(dev))
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f63973a..9c834bc 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -712,6 +712,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 	struct drm_display_mode *mode = &pipe_config->requested_mode;
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct intel_crtc *intel_crtc = encoder->new_crtc;
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	int lane_count, clock;
 	int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
@@ -728,9 +729,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
 		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
 				       adjusted_mode);
-		intel_pch_panel_fitting(dev,
-					intel_connector->panel.fitting_mode,
-					mode, adjusted_mode);
+		if (!HAS_PCH_SPLIT(dev))
+			intel_gmch_panel_fitting(intel_crtc, pipe_config,
+						 intel_connector->panel.fitting_mode);
+		else
+			intel_pch_panel_fitting(dev,
+						intel_connector->panel.fitting_mode,
+						mode, adjusted_mode);
 	}
 	/* We need to take the panel's fixed mode into account. */
 	target_clock = adjusted_mode->clock;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a5fe976..9f3f71b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -237,6 +237,9 @@ struct intel_crtc_config {
 	int pixel_target_clock;
 	/* Used by SDVO (and if we ever fix it, HDMI). */
 	unsigned pixel_multiplier;
+
+	/* Panel fitter controls for gen2-gen4 + VLV */
+	u32 pfit_control, pfit_pgm_ratios;
 };
 
 struct intel_crtc {
@@ -558,6 +561,9 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,
 				    int fitting_mode,
 				    const struct drm_display_mode *mode,
 				    struct drm_display_mode *adjusted_mode);
+extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
+				     struct intel_crtc_config *pipe_config,
+				     int fitting_mode);
 extern void intel_panel_set_backlight(struct drm_device *dev,
 				      u32 level, u32 max);
 extern int intel_panel_setup_backlight(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 8408545..7d41881 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -49,8 +49,6 @@ struct intel_lvds_connector {
 struct intel_lvds_encoder {
 	struct intel_encoder base;
 
-	u32 pfit_control;
-	u32 pfit_pgm_ratios;
 	bool is_dual_link;
 	u32 reg;
 
@@ -153,32 +151,6 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
 	I915_WRITE(lvds_encoder->reg, temp);
 }
 
-static void intel_pre_enable_lvds(struct intel_encoder *encoder)
-{
-	struct drm_device *dev = encoder->base.dev;
-	struct intel_lvds_encoder *enc = to_lvds_encoder(&encoder->base);
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (HAS_PCH_SPLIT(dev) || !enc->pfit_control)
-		return;
-
-	WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
-	assert_pipe_disabled(dev_priv, to_intel_crtc(encoder->base.crtc)->pipe);
-
-	/*
-	 * Enable automatic panel scaling so that non-native modes
-	 * fill the screen.  The panel fitter should only be
-	 * adjusted whilst the pipe is disabled, according to
-	 * register description and PRM.
-	 */
-	DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
-		      enc->pfit_control,
-		      enc->pfit_pgm_ratios);
-
-	I915_WRITE(PFIT_PGM_RATIOS, enc->pfit_pgm_ratios);
-	I915_WRITE(PFIT_CONTROL, enc->pfit_control);
-}
-
 /**
  * Sets the power state for the panel.
  */
@@ -247,62 +219,6 @@ static int intel_lvds_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 }
 
-static void
-centre_horizontally(struct drm_display_mode *mode,
-		    int width)
-{
-	u32 border, sync_pos, blank_width, sync_width;
-
-	/* keep the hsync and hblank widths constant */
-	sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
-	blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
-	sync_pos = (blank_width - sync_width + 1) / 2;
-
-	border = (mode->hdisplay - width + 1) / 2;
-	border += border & 1; /* make the border even */
-
-	mode->crtc_hdisplay = width;
-	mode->crtc_hblank_start = width + border;
-	mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
-
-	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
-	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
-}
-
-static void
-centre_vertically(struct drm_display_mode *mode,
-		  int height)
-{
-	u32 border, sync_pos, blank_width, sync_width;
-
-	/* keep the vsync and vblank widths constant */
-	sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
-	blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
-	sync_pos = (blank_width - sync_width + 1) / 2;
-
-	border = (mode->vdisplay - height + 1) / 2;
-
-	mode->crtc_vdisplay = height;
-	mode->crtc_vblank_start = height + border;
-	mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
-
-	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
-	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
-}
-
-static inline u32 panel_fitter_scaling(u32 source, u32 target)
-{
-	/*
-	 * Floating point operation is not supported. So the FACTOR
-	 * is defined, which can avoid the floating point computation
-	 * when calculating the panel ratio.
-	 */
-#define ACCURACY 12
-#define FACTOR (1 << ACCURACY)
-	u32 ratio = source * FACTOR / target;
-	return (FACTOR * ratio + FACTOR/2) / FACTOR;
-}
-
 static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 				      struct intel_crtc_config *pipe_config)
 {
@@ -315,7 +231,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 	struct drm_display_mode *mode = &pipe_config->requested_mode;
 	struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
-	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
 	unsigned int lvds_bpp;
 	int pipe;
 
@@ -338,11 +253,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 		DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
 			      pipe_config->pipe_bpp, lvds_bpp);
 		pipe_config->pipe_bpp = lvds_bpp;
-
-		/* Make sure pre-965 set dither correctly for 18bpp panels. */
-		if (INTEL_INFO(dev)->gen < 4 && lvds_bpp == 18)
-			pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-
 	}
 
 	/*
@@ -361,18 +271,11 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 					intel_connector->panel.fitting_mode,
 					mode, adjusted_mode);
 		return true;
+	} else {
+		intel_gmch_panel_fitting(intel_crtc, pipe_config,
+					 intel_connector->panel.fitting_mode);
 	}
 
-	/* Native modes don't need fitting */
-	if (adjusted_mode->hdisplay == mode->hdisplay &&
-	    adjusted_mode->vdisplay == mode->vdisplay)
-		goto out;
-
-	/* 965+ wants fuzzy fitting */
-	if (INTEL_INFO(dev)->gen >= 4)
-		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
-				 PFIT_FILTER_FUZZY);
-
 	/*
 	 * Enable automatic panel scaling for non-native modes so that they fill
 	 * the screen.  Should be enabled before the pipe is enabled, according
@@ -385,107 +288,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 	pipe_config->timings_set = true;
 
-	switch (intel_connector->panel.fitting_mode) {
-	case DRM_MODE_SCALE_CENTER:
-		/*
-		 * For centered modes, we have to calculate border widths &
-		 * heights and modify the values programmed into the CRTC.
-		 */
-		centre_horizontally(adjusted_mode, mode->hdisplay);
-		centre_vertically(adjusted_mode, mode->vdisplay);
-		border = LVDS_BORDER_ENABLE;
-		break;
-
-	case DRM_MODE_SCALE_ASPECT:
-		/* Scale but preserve the aspect ratio */
-		if (INTEL_INFO(dev)->gen >= 4) {
-			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
-			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
-
-			/* 965+ is easy, it does everything in hw */
-			if (scaled_width > scaled_height)
-				pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR;
-			else if (scaled_width < scaled_height)
-				pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER;
-			else if (adjusted_mode->hdisplay != mode->hdisplay)
-				pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
-		} else {
-			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
-			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
-			/*
-			 * For earlier chips we have to calculate the scaling
-			 * ratio by hand and program it into the
-			 * PFIT_PGM_RATIO register
-			 */
-			if (scaled_width > scaled_height) { /* pillar */
-				centre_horizontally(adjusted_mode, scaled_height / mode->vdisplay);
-
-				border = LVDS_BORDER_ENABLE;
-				if (mode->vdisplay != adjusted_mode->vdisplay) {
-					u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
-					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
-							    bits << PFIT_VERT_SCALE_SHIFT);
-					pfit_control |= (PFIT_ENABLE |
-							 VERT_INTERP_BILINEAR |
-							 HORIZ_INTERP_BILINEAR);
-				}
-			} else if (scaled_width < scaled_height) { /* letter */
-				centre_vertically(adjusted_mode, scaled_width / mode->hdisplay);
-
-				border = LVDS_BORDER_ENABLE;
-				if (mode->hdisplay != adjusted_mode->hdisplay) {
-					u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
-					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
-							    bits << PFIT_VERT_SCALE_SHIFT);
-					pfit_control |= (PFIT_ENABLE |
-							 VERT_INTERP_BILINEAR |
-							 HORIZ_INTERP_BILINEAR);
-				}
-			} else
-				/* Aspects match, Let hw scale both directions */
-				pfit_control |= (PFIT_ENABLE |
-						 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-						 VERT_INTERP_BILINEAR |
-						 HORIZ_INTERP_BILINEAR);
-		}
-		break;
-
-	case DRM_MODE_SCALE_FULLSCREEN:
-		/*
-		 * Full scaling, even if it changes the aspect ratio.
-		 * Fortunately this is all done for us in hw.
-		 */
-		if (mode->vdisplay != adjusted_mode->vdisplay ||
-		    mode->hdisplay != adjusted_mode->hdisplay) {
-			pfit_control |= PFIT_ENABLE;
-			if (INTEL_INFO(dev)->gen >= 4)
-				pfit_control |= PFIT_SCALING_AUTO;
-			else
-				pfit_control |= (VERT_AUTO_SCALE |
-						 VERT_INTERP_BILINEAR |
-						 HORIZ_AUTO_SCALE |
-						 HORIZ_INTERP_BILINEAR);
-		}
-		break;
-
-	default:
-		break;
-	}
-
-out:
-	/* If not enabling scaling, be consistent and always use 0. */
-	if ((pfit_control & PFIT_ENABLE) == 0) {
-		pfit_control = 0;
-		pfit_pgm_ratios = 0;
-	}
-
-	if (pfit_control != lvds_encoder->pfit_control ||
-	    pfit_pgm_ratios != lvds_encoder->pfit_pgm_ratios) {
-		lvds_encoder->pfit_control = pfit_control;
-		lvds_encoder->pfit_pgm_ratios = pfit_pgm_ratios;
-	}
-	dev_priv->lvds_border_bits = border;
-
 	/*
 	 * XXX: It would be nice to support lower refresh rates on the
 	 * panels to reduce power consumption, and perhaps match the
@@ -1115,10 +917,6 @@ bool intel_lvds_init(struct drm_device *dev)
 
 	lvds_encoder->attached_connector = lvds_connector;
 
-	if (!HAS_PCH_SPLIT(dev)) {
-		lvds_encoder->pfit_control = I915_READ(PFIT_CONTROL);
-	}
-
 	intel_encoder = &lvds_encoder->base;
 	encoder = &intel_encoder->base;
 	intel_connector = &lvds_connector->base;
@@ -1130,7 +928,6 @@ bool intel_lvds_init(struct drm_device *dev)
 			 DRM_MODE_ENCODER_LVDS);
 
 	intel_encoder->enable = intel_enable_lvds;
-	intel_encoder->pre_enable = intel_pre_enable_lvds;
 	intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;
 	intel_encoder->compute_config = intel_lvds_compute_config;
 	intel_encoder->disable = intel_disable_lvds;
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 7f6141d..b2cdedf 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -117,6 +117,197 @@ done:
 	dev_priv->pch_pf_size = (width << 16) | height;
 }
 
+static void
+centre_horizontally(struct drm_display_mode *mode,
+		    int width)
+{
+	u32 border, sync_pos, blank_width, sync_width;
+
+	/* keep the hsync and hblank widths constant */
+	sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
+	sync_pos = (blank_width - sync_width + 1) / 2;
+
+	border = (mode->hdisplay - width + 1) / 2;
+	border += border & 1; /* make the border even */
+
+	mode->crtc_hdisplay = width;
+	mode->crtc_hblank_start = width + border;
+	mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
+
+	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
+	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
+}
+
+static void
+centre_vertically(struct drm_display_mode *mode,
+		  int height)
+{
+	u32 border, sync_pos, blank_width, sync_width;
+
+	/* keep the vsync and vblank widths constant */
+	sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
+	sync_pos = (blank_width - sync_width + 1) / 2;
+
+	border = (mode->vdisplay - height + 1) / 2;
+
+	mode->crtc_vdisplay = height;
+	mode->crtc_vblank_start = height + border;
+	mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
+
+	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
+	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
+}
+
+static inline u32 panel_fitter_scaling(u32 source, u32 target)
+{
+	/*
+	 * Floating point operation is not supported. So the FACTOR
+	 * is defined, which can avoid the floating point computation
+	 * when calculating the panel ratio.
+	 */
+#define ACCURACY 12
+#define FACTOR (1 << ACCURACY)
+	u32 ratio = source * FACTOR / target;
+	return (FACTOR * ratio + FACTOR/2) / FACTOR;
+}
+
+void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
+			      struct intel_crtc_config *pipe_config,
+			      int fitting_mode)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
+	struct drm_display_mode *mode, *adjusted_mode;
+
+	mode = &pipe_config->requested_mode;
+	adjusted_mode = &pipe_config->adjusted_mode;
+
+	/* Native modes don't need fitting */
+	if (adjusted_mode->hdisplay == mode->hdisplay &&
+	    adjusted_mode->vdisplay == mode->vdisplay)
+		goto out;
+
+	switch (fitting_mode) {
+	case DRM_MODE_SCALE_CENTER:
+		/*
+		 * For centered modes, we have to calculate border widths &
+		 * heights and modify the values programmed into the CRTC.
+		 */
+		centre_horizontally(adjusted_mode, mode->hdisplay);
+		centre_vertically(adjusted_mode, mode->vdisplay);
+		break;
+	case DRM_MODE_SCALE_ASPECT:
+		/* Scale but preserve the aspect ratio */
+		if (INTEL_INFO(dev)->gen >= 4) {
+			u32 scaled_width = adjusted_mode->hdisplay *
+				mode->vdisplay;
+			u32 scaled_height = mode->hdisplay *
+				adjusted_mode->vdisplay;
+
+			/* 965+ is easy, it does everything in hw */
+			if (scaled_width > scaled_height)
+				pfit_control |= PFIT_ENABLE |
+					PFIT_SCALING_PILLAR;
+			else if (scaled_width < scaled_height)
+				pfit_control |= PFIT_ENABLE |
+					PFIT_SCALING_LETTER;
+			else if (adjusted_mode->hdisplay != mode->hdisplay)
+				pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
+		} else {
+			u32 scaled_width = adjusted_mode->hdisplay *
+				mode->vdisplay;
+			u32 scaled_height = mode->hdisplay *
+				adjusted_mode->vdisplay;
+			/*
+			 * For earlier chips we have to calculate the scaling
+			 * ratio by hand and program it into the
+			 * PFIT_PGM_RATIO register
+			 */
+			if (scaled_width > scaled_height) { /* pillar */
+				centre_horizontally(adjusted_mode,
+						    scaled_height /
+						    mode->vdisplay);
+
+				border = LVDS_BORDER_ENABLE;
+				if (mode->vdisplay != adjusted_mode->vdisplay) {
+					u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
+					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
+							    bits << PFIT_VERT_SCALE_SHIFT);
+					pfit_control |= (PFIT_ENABLE |
+							 VERT_INTERP_BILINEAR |
+							 HORIZ_INTERP_BILINEAR);
+				}
+			} else if (scaled_width < scaled_height) { /* letter */
+				centre_vertically(adjusted_mode,
+						  scaled_width /
+						  mode->hdisplay);
+
+				border = LVDS_BORDER_ENABLE;
+				if (mode->hdisplay != adjusted_mode->hdisplay) {
+					u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
+					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
+							    bits << PFIT_VERT_SCALE_SHIFT);
+					pfit_control |= (PFIT_ENABLE |
+							 VERT_INTERP_BILINEAR |
+							 HORIZ_INTERP_BILINEAR);
+				}
+			} else {
+				/* Aspects match, Let hw scale both directions */
+				pfit_control |= (PFIT_ENABLE |
+						 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+						 VERT_INTERP_BILINEAR |
+						 HORIZ_INTERP_BILINEAR);
+			}
+		}
+		break;
+	default:
+	case DRM_MODE_SCALE_FULLSCREEN:
+		/*
+		 * Full scaling, even if it changes the aspect ratio.
+		 * Fortunately this is all done for us in hw.
+		 */
+		if (mode->vdisplay != adjusted_mode->vdisplay ||
+		    mode->hdisplay != adjusted_mode->hdisplay) {
+			pfit_control |= PFIT_ENABLE;
+			if (INTEL_INFO(dev)->gen >= 4)
+				pfit_control |= PFIT_SCALING_AUTO;
+			else
+				pfit_control |= (VERT_AUTO_SCALE |
+						 VERT_INTERP_BILINEAR |
+						 HORIZ_AUTO_SCALE |
+						 HORIZ_INTERP_BILINEAR);
+		}
+		break;
+	}
+
+	/* 965+ wants fuzzy fitting */
+	/* FIXME: handle multiple panels by failing gracefully */
+	if (INTEL_INFO(dev)->gen >= 4)
+		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
+				 PFIT_FILTER_FUZZY);
+
+out:
+	if ((pfit_control & PFIT_ENABLE) == 0) {
+		pfit_control = 0;
+		pfit_pgm_ratios = 0;
+	}
+
+	/* Make sure pre-965 set dither correctly */
+	if (INTEL_INFO(dev)->gen < 4 && (pipe_config->pipe_bpp == 18 ||
+					 dev_priv->lvds_dither))
+		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+
+	if (pfit_control != pipe_config->pfit_control ||
+	    pfit_pgm_ratios != pipe_config->pfit_pgm_ratios) {
+		pipe_config->pfit_control = pfit_control;
+		pipe_config->pfit_pgm_ratios = pfit_pgm_ratios;
+	}
+	dev_priv->lvds_border_bits = border;
+}
+
 static int is_backlight_combination_mode(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] drm/i915: move PCH pfit controls into pipe_config
  2013-04-25 19:55 [PATCH 1/3] drm/i915: factor out GMCH panel fitting code and use for eDP v3 Jesse Barnes
@ 2013-04-25 19:55 ` Jesse Barnes
  2013-05-02 22:02   ` Paulo Zanoni
  2013-04-25 19:55 ` [PATCH 3/3] drm/i915: warn about invalid pfit modes Jesse Barnes
  1 sibling, 1 reply; 6+ messages in thread
From: Jesse Barnes @ 2013-04-25 19:55 UTC (permalink / raw)
  To: intel-gfx

And put the pfit stuff into substructs while we're at it.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_drv.h      |    2 --
 drivers/gpu/drm/i915/intel_ddi.c     |    2 +-
 drivers/gpu/drm/i915/intel_display.c |   65 ++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_dp.c      |    6 ++--
 drivers/gpu/drm/i915/intel_drv.h     |   18 +++++++---
 drivers/gpu/drm/i915/intel_lvds.c    |    6 ++--
 drivers/gpu/drm/i915/intel_panel.c   |   25 +++++++------
 7 files changed, 63 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8a257a9..14156f2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1021,8 +1021,6 @@ typedef struct drm_i915_private {
 	struct sdvo_device_mapping sdvo_mappings[2];
 	/* indicate whether the LVDS_BORDER should be enabled or not */
 	unsigned int lvds_border_bits;
-	/* Panel fitter placement and size for Ironlake+ */
-	u32 pch_pf_pos, pch_pf_size;
 
 	struct drm_crtc *plane_to_crtc_mapping[3];
 	struct drm_crtc *pipe_to_crtc_mapping[3];
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index eef450b..0d7cf31 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -995,7 +995,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 			/* Can only use the always-on power well for eDP when
 			 * not using the panel fitter, and when not using motion
 			  * blur mitigation (which we don't support). */
-			if (dev_priv->pch_pf_size)
+			if (intel_crtc->config.pch_pfit.size)
 				temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
 			else
 				temp |= TRANS_DDI_EDP_INPUT_A_ON;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fc6f768..dacfc6c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3225,6 +3225,28 @@ void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
 	}
 }
 
+static void ironlake_pfit_enable(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = crtc->pipe;
+
+	if (crtc->config.pch_pfit.size &&
+	    intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) {
+		/* Force use of hard-coded filter coefficients
+		 * as some pre-programmed values are broken,
+		 * e.g. x201.
+		 */
+		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+			I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
+						 PF_PIPE_SEL_IVB(pipe));
+		else
+			I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
+		I915_WRITE(PF_WIN_POS(pipe), crtc->config.pch_pfit.pos);
+		I915_WRITE(PF_WIN_SZ(pipe), crtc->config.pch_pfit.size);
+	}
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3269,21 +3291,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 			encoder->pre_enable(encoder);
 
 	/* Enable panel fitting for LVDS */
-	if (dev_priv->pch_pf_size &&
-	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
-	     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
-		/* Force use of hard-coded filter coefficients
-		 * as some pre-programmed values are broken,
-		 * e.g. x201.
-		 */
-		if (IS_IVYBRIDGE(dev))
-			I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
-						 PF_PIPE_SEL_IVB(pipe));
-		else
-			I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
-		I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
-		I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
-	}
+	ironlake_pfit_enable(intel_crtc);
 
 	/*
 	 * On ILK+ LUT must be loaded before the pipe is running but with
@@ -3353,17 +3361,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_ddi_enable_pipe_clock(intel_crtc);
 
 	/* Enable panel fitting for eDP */
-	if (dev_priv->pch_pf_size &&
-	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
-		/* Force use of hard-coded filter coefficients
-		 * as some pre-programmed values are broken,
-		 * e.g. x201.
-		 */
-		I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
-					 PF_PIPE_SEL_IVB(pipe));
-		I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
-		I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
-	}
+	ironlake_pfit_enable(intel_crtc);
 
 	/*
 	 * On ILK+ LUT must be loaded before the pipe is running but with
@@ -3621,11 +3619,11 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
 	 * register description and PRM.
 	 */
 	DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
-		      pipe_config->pfit_control,
-		      pipe_config->pfit_pgm_ratios);
+		      pipe_config->gmch_pfit.control,
+		      pipe_config->gmch_pfit.pgm_ratios);
 
-	I915_WRITE(PFIT_PGM_RATIOS, pipe_config->pfit_pgm_ratios);
-	I915_WRITE(PFIT_CONTROL, pipe_config->pfit_control);
+	I915_WRITE(PFIT_PGM_RATIOS, pipe_config->gmch_pfit.pgm_ratios);
+	I915_WRITE(PFIT_CONTROL, pipe_config->gmch_pfit.control);
 }
 
 static void valleyview_crtc_enable(struct drm_crtc *crtc)
@@ -5800,6 +5798,9 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
 		/* XXX: Should check for edp transcoder here, but thanks to init
 		 * sequence that's not yet available. Just in case desktop eDP
 		 * on PORT D is possible on haswell, too. */
+		/* Even the eDP panel fitter is outside the always-on well. */
+		if (I915_READ(PF_WIN_SZ(crtc->pipe)))
+			enable = true;
 	}
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
@@ -5809,10 +5810,6 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
 			enable = true;
 	}
 
-	/* Even the eDP panel fitter is outside the always-on well. */
-	if (dev_priv->pch_pf_size)
-		enable = true;
-
 	intel_set_power_well(dev, enable);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9c834bc..9ac034e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -710,7 +710,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
-	struct drm_display_mode *mode = &pipe_config->requested_mode;
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	struct intel_crtc *intel_crtc = encoder->new_crtc;
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
@@ -733,9 +732,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 			intel_gmch_panel_fitting(intel_crtc, pipe_config,
 						 intel_connector->panel.fitting_mode);
 		else
-			intel_pch_panel_fitting(dev,
-						intel_connector->panel.fitting_mode,
-						mode, adjusted_mode);
+			intel_pch_panel_fitting(intel_crtc, pipe_config,
+						intel_connector->panel.fitting_mode);
 	}
 	/* We need to take the panel's fixed mode into account. */
 	target_clock = adjusted_mode->clock;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9f3f71b..a8c6960 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -239,7 +239,16 @@ struct intel_crtc_config {
 	unsigned pixel_multiplier;
 
 	/* Panel fitter controls for gen2-gen4 + VLV */
-	u32 pfit_control, pfit_pgm_ratios;
+	struct {
+		u32 control;
+		u32 pgm_ratios;
+	} gmch_pfit;
+
+	/* Panel fitter placement and size for Ironlake+ */
+	struct {
+		u32 pos;
+		u32 size;
+	} pch_pfit;
 };
 
 struct intel_crtc {
@@ -557,10 +566,9 @@ extern void intel_panel_fini(struct intel_panel *panel);
 
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 				   struct drm_display_mode *adjusted_mode);
-extern void intel_pch_panel_fitting(struct drm_device *dev,
-				    int fitting_mode,
-				    const struct drm_display_mode *mode,
-				    struct drm_display_mode *adjusted_mode);
+extern void intel_pch_panel_fitting(struct intel_crtc *crtc,
+				    struct intel_crtc_config *pipe_config,
+				    int fitting_mode);
 extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
 				     struct intel_crtc_config *pipe_config,
 				     int fitting_mode);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 7d41881..3e29499 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -229,7 +229,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 	struct intel_connector *intel_connector =
 		&lvds_encoder->attached_connector->base;
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
-	struct drm_display_mode *mode = &pipe_config->requested_mode;
 	struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
 	unsigned int lvds_bpp;
 	int pipe;
@@ -267,9 +266,8 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
 	if (HAS_PCH_SPLIT(dev)) {
 		pipe_config->has_pch_encoder = true;
 
-		intel_pch_panel_fitting(dev,
-					intel_connector->panel.fitting_mode,
-					mode, adjusted_mode);
+		intel_pch_panel_fitting(intel_crtc, pipe_config,
+					intel_connector->panel.fitting_mode);
 		return true;
 	} else {
 		intel_gmch_panel_fitting(intel_crtc, pipe_config,
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index b2cdedf..016e676 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -54,14 +54,17 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 
 /* adjusted_mode has been preset to be the panel's fixed mode */
 void
-intel_pch_panel_fitting(struct drm_device *dev,
-			int fitting_mode,
-			const struct drm_display_mode *mode,
-			struct drm_display_mode *adjusted_mode)
+intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
+			struct intel_crtc_config *pipe_config,
+			int fitting_mode)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+	struct drm_display_mode *mode, *adjusted_mode;
 	int x, y, width, height;
 
+	mode = &pipe_config->requested_mode;
+	adjusted_mode = &pipe_config->adjusted_mode;
+
 	x = y = width = height = 0;
 
 	/* Native modes don't need fitting */
@@ -113,8 +116,8 @@ intel_pch_panel_fitting(struct drm_device *dev,
 	}
 
 done:
-	dev_priv->pch_pf_pos = (x << 16) | y;
-	dev_priv->pch_pf_size = (width << 16) | height;
+	pipe_config->pch_pfit.pos = (x << 16) | y;
+	pipe_config->pch_pfit.size = (width << 16) | height;
 }
 
 static void
@@ -300,10 +303,10 @@ out:
 					 dev_priv->lvds_dither))
 		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 
-	if (pfit_control != pipe_config->pfit_control ||
-	    pfit_pgm_ratios != pipe_config->pfit_pgm_ratios) {
-		pipe_config->pfit_control = pfit_control;
-		pipe_config->pfit_pgm_ratios = pfit_pgm_ratios;
+	if (pfit_control != pipe_config->gmch_pfit.control ||
+	    pfit_pgm_ratios != pipe_config->gmch_pfit.pgm_ratios) {
+		pipe_config->gmch_pfit.control = pfit_control;
+		pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
 	}
 	dev_priv->lvds_border_bits = border;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] drm/i915: warn about invalid pfit modes
  2013-04-25 19:55 [PATCH 1/3] drm/i915: factor out GMCH panel fitting code and use for eDP v3 Jesse Barnes
  2013-04-25 19:55 ` [PATCH 2/3] drm/i915: move PCH pfit controls into pipe_config Jesse Barnes
@ 2013-04-25 19:55 ` Jesse Barnes
  2013-04-25 20:20   ` Daniel Vetter
  1 sibling, 1 reply; 6+ messages in thread
From: Jesse Barnes @ 2013-04-25 19:55 UTC (permalink / raw)
  To: intel-gfx

We prevent invalid ones from getting here in the first place, but it
doesn't hurt to have an extra sanity check.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/intel_panel.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 016e676..48e7207 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -58,7 +58,6 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
 			struct intel_crtc_config *pipe_config,
 			int fitting_mode)
 {
-	struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
 	struct drm_display_mode *mode, *adjusted_mode;
 	int x, y, width, height;
 
@@ -107,12 +106,15 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
 		}
 		break;
 
-	default:
 	case DRM_MODE_SCALE_FULLSCREEN:
 		x = y = 0;
 		width = adjusted_mode->hdisplay;
 		height = adjusted_mode->vdisplay;
 		break;
+
+	default:
+		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
+		return;
 	}
 
 done:
@@ -266,7 +268,6 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
 			}
 		}
 		break;
-	default:
 	case DRM_MODE_SCALE_FULLSCREEN:
 		/*
 		 * Full scaling, even if it changes the aspect ratio.
@@ -284,6 +285,9 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
 						 HORIZ_INTERP_BILINEAR);
 		}
 		break;
+	default:
+		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
+		return;
 	}
 
 	/* 965+ wants fuzzy fitting */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3] drm/i915: warn about invalid pfit modes
  2013-04-25 19:55 ` [PATCH 3/3] drm/i915: warn about invalid pfit modes Jesse Barnes
@ 2013-04-25 20:20   ` Daniel Vetter
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Vetter @ 2013-04-25 20:20 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Thu, Apr 25, 2013 at 12:55:03PM -0700, Jesse Barnes wrote:
> We prevent invalid ones from getting here in the first place, but it
> doesn't hurt to have an extra sanity check.
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Merged all three, with the first one a bit bikeshedded (as discussed on
irc).

Thanks, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] drm/i915: move PCH pfit controls into pipe_config
  2013-04-25 19:55 ` [PATCH 2/3] drm/i915: move PCH pfit controls into pipe_config Jesse Barnes
@ 2013-05-02 22:02   ` Paulo Zanoni
  2013-05-03  8:10     ` Daniel Vetter
  0 siblings, 1 reply; 6+ messages in thread
From: Paulo Zanoni @ 2013-05-02 22:02 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

Hi

2013/4/25 Jesse Barnes <jbarnes@virtuousgeek.org>:
> And put the pfit stuff into substructs while we're at it.
>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |    2 --
>  drivers/gpu/drm/i915/intel_ddi.c     |    2 +-
>  drivers/gpu/drm/i915/intel_display.c |   65 ++++++++++++++++------------------
>  drivers/gpu/drm/i915/intel_dp.c      |    6 ++--
>  drivers/gpu/drm/i915/intel_drv.h     |   18 +++++++---
>  drivers/gpu/drm/i915/intel_lvds.c    |    6 ++--
>  drivers/gpu/drm/i915/intel_panel.c   |   25 +++++++------
>  7 files changed, 63 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 8a257a9..14156f2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1021,8 +1021,6 @@ typedef struct drm_i915_private {
>         struct sdvo_device_mapping sdvo_mappings[2];
>         /* indicate whether the LVDS_BORDER should be enabled or not */
>         unsigned int lvds_border_bits;
> -       /* Panel fitter placement and size for Ironlake+ */
> -       u32 pch_pf_pos, pch_pf_size;
>
>         struct drm_crtc *plane_to_crtc_mapping[3];
>         struct drm_crtc *pipe_to_crtc_mapping[3];
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index eef450b..0d7cf31 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -995,7 +995,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
>                         /* Can only use the always-on power well for eDP when
>                          * not using the panel fitter, and when not using motion
>                           * blur mitigation (which we don't support). */
> -                       if (dev_priv->pch_pf_size)
> +                       if (intel_crtc->config.pch_pfit.size)
>                                 temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
>                         else
>                                 temp |= TRANS_DDI_EDP_INPUT_A_ON;
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index fc6f768..dacfc6c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3225,6 +3225,28 @@ void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
>         }
>  }
>
> +static void ironlake_pfit_enable(struct intel_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       int pipe = crtc->pipe;
> +
> +       if (crtc->config.pch_pfit.size &&
> +           intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) {
> +               /* Force use of hard-coded filter coefficients
> +                * as some pre-programmed values are broken,
> +                * e.g. x201.
> +                */
> +               if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
> +                       I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
> +                                                PF_PIPE_SEL_IVB(pipe));
> +               else
> +                       I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
> +               I915_WRITE(PF_WIN_POS(pipe), crtc->config.pch_pfit.pos);
> +               I915_WRITE(PF_WIN_SZ(pipe), crtc->config.pch_pfit.size);
> +       }
> +}
> +
>  static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
> @@ -3269,21 +3291,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>                         encoder->pre_enable(encoder);
>
>         /* Enable panel fitting for LVDS */
> -       if (dev_priv->pch_pf_size &&
> -           (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
> -            intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
> -               /* Force use of hard-coded filter coefficients
> -                * as some pre-programmed values are broken,
> -                * e.g. x201.
> -                */
> -               if (IS_IVYBRIDGE(dev))
> -                       I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
> -                                                PF_PIPE_SEL_IVB(pipe));
> -               else
> -                       I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
> -               I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
> -               I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
> -       }
> +       ironlake_pfit_enable(intel_crtc);
>
>         /*
>          * On ILK+ LUT must be loaded before the pipe is running but with
> @@ -3353,17 +3361,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>         intel_ddi_enable_pipe_clock(intel_crtc);
>
>         /* Enable panel fitting for eDP */
> -       if (dev_priv->pch_pf_size &&
> -           intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
> -               /* Force use of hard-coded filter coefficients
> -                * as some pre-programmed values are broken,
> -                * e.g. x201.
> -                */
> -               I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
> -                                        PF_PIPE_SEL_IVB(pipe));
> -               I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
> -               I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
> -       }
> +       ironlake_pfit_enable(intel_crtc);
>
>         /*
>          * On ILK+ LUT must be loaded before the pipe is running but with
> @@ -3621,11 +3619,11 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
>          * register description and PRM.
>          */
>         DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
> -                     pipe_config->pfit_control,
> -                     pipe_config->pfit_pgm_ratios);
> +                     pipe_config->gmch_pfit.control,
> +                     pipe_config->gmch_pfit.pgm_ratios);
>
> -       I915_WRITE(PFIT_PGM_RATIOS, pipe_config->pfit_pgm_ratios);
> -       I915_WRITE(PFIT_CONTROL, pipe_config->pfit_control);
> +       I915_WRITE(PFIT_PGM_RATIOS, pipe_config->gmch_pfit.pgm_ratios);
> +       I915_WRITE(PFIT_CONTROL, pipe_config->gmch_pfit.control);
>  }
>
>  static void valleyview_crtc_enable(struct drm_crtc *crtc)
> @@ -5800,6 +5798,9 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
>                 /* XXX: Should check for edp transcoder here, but thanks to init
>                  * sequence that's not yet available. Just in case desktop eDP
>                  * on PORT D is possible on haswell, too. */
> +               /* Even the eDP panel fitter is outside the always-on well. */
> +               if (I915_READ(PF_WIN_SZ(crtc->pipe)))

So this patch made it to drm-intel-next-queued and the line above
causes "unclaimed register" errors. This happens even if we don't
disable the power well, and we were 100% clear of these error messages
on that case, so I guess I can call this a "regression". Can you
please provide a fix?


> +                       enable = true;
>         }
>
>         list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> @@ -5809,10 +5810,6 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
>                         enable = true;
>         }
>
> -       /* Even the eDP panel fitter is outside the always-on well. */
> -       if (dev_priv->pch_pf_size)
> -               enable = true;
> -
>         intel_set_power_well(dev, enable);
>  }
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 9c834bc..9ac034e 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -710,7 +710,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>         struct drm_device *dev = encoder->base.dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
> -       struct drm_display_mode *mode = &pipe_config->requested_mode;
>         struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>         struct intel_crtc *intel_crtc = encoder->new_crtc;
>         struct intel_connector *intel_connector = intel_dp->attached_connector;
> @@ -733,9 +732,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>                         intel_gmch_panel_fitting(intel_crtc, pipe_config,
>                                                  intel_connector->panel.fitting_mode);
>                 else
> -                       intel_pch_panel_fitting(dev,
> -                                               intel_connector->panel.fitting_mode,
> -                                               mode, adjusted_mode);
> +                       intel_pch_panel_fitting(intel_crtc, pipe_config,
> +                                               intel_connector->panel.fitting_mode);
>         }
>         /* We need to take the panel's fixed mode into account. */
>         target_clock = adjusted_mode->clock;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 9f3f71b..a8c6960 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -239,7 +239,16 @@ struct intel_crtc_config {
>         unsigned pixel_multiplier;
>
>         /* Panel fitter controls for gen2-gen4 + VLV */
> -       u32 pfit_control, pfit_pgm_ratios;
> +       struct {
> +               u32 control;
> +               u32 pgm_ratios;
> +       } gmch_pfit;
> +
> +       /* Panel fitter placement and size for Ironlake+ */
> +       struct {
> +               u32 pos;
> +               u32 size;
> +       } pch_pfit;
>  };
>
>  struct intel_crtc {
> @@ -557,10 +566,9 @@ extern void intel_panel_fini(struct intel_panel *panel);
>
>  extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
>                                    struct drm_display_mode *adjusted_mode);
> -extern void intel_pch_panel_fitting(struct drm_device *dev,
> -                                   int fitting_mode,
> -                                   const struct drm_display_mode *mode,
> -                                   struct drm_display_mode *adjusted_mode);
> +extern void intel_pch_panel_fitting(struct intel_crtc *crtc,
> +                                   struct intel_crtc_config *pipe_config,
> +                                   int fitting_mode);
>  extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
>                                      struct intel_crtc_config *pipe_config,
>                                      int fitting_mode);
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 7d41881..3e29499 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -229,7 +229,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
>         struct intel_connector *intel_connector =
>                 &lvds_encoder->attached_connector->base;
>         struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
> -       struct drm_display_mode *mode = &pipe_config->requested_mode;
>         struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
>         unsigned int lvds_bpp;
>         int pipe;
> @@ -267,9 +266,8 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
>         if (HAS_PCH_SPLIT(dev)) {
>                 pipe_config->has_pch_encoder = true;
>
> -               intel_pch_panel_fitting(dev,
> -                                       intel_connector->panel.fitting_mode,
> -                                       mode, adjusted_mode);
> +               intel_pch_panel_fitting(intel_crtc, pipe_config,
> +                                       intel_connector->panel.fitting_mode);
>                 return true;
>         } else {
>                 intel_gmch_panel_fitting(intel_crtc, pipe_config,
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index b2cdedf..016e676 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -54,14 +54,17 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
>
>  /* adjusted_mode has been preset to be the panel's fixed mode */
>  void
> -intel_pch_panel_fitting(struct drm_device *dev,
> -                       int fitting_mode,
> -                       const struct drm_display_mode *mode,
> -                       struct drm_display_mode *adjusted_mode)
> +intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
> +                       struct intel_crtc_config *pipe_config,
> +                       int fitting_mode)
>  {
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
> +       struct drm_display_mode *mode, *adjusted_mode;
>         int x, y, width, height;
>
> +       mode = &pipe_config->requested_mode;
> +       adjusted_mode = &pipe_config->adjusted_mode;
> +
>         x = y = width = height = 0;
>
>         /* Native modes don't need fitting */
> @@ -113,8 +116,8 @@ intel_pch_panel_fitting(struct drm_device *dev,
>         }
>
>  done:
> -       dev_priv->pch_pf_pos = (x << 16) | y;
> -       dev_priv->pch_pf_size = (width << 16) | height;
> +       pipe_config->pch_pfit.pos = (x << 16) | y;
> +       pipe_config->pch_pfit.size = (width << 16) | height;
>  }
>
>  static void
> @@ -300,10 +303,10 @@ out:
>                                          dev_priv->lvds_dither))
>                 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
>
> -       if (pfit_control != pipe_config->pfit_control ||
> -           pfit_pgm_ratios != pipe_config->pfit_pgm_ratios) {
> -               pipe_config->pfit_control = pfit_control;
> -               pipe_config->pfit_pgm_ratios = pfit_pgm_ratios;
> +       if (pfit_control != pipe_config->gmch_pfit.control ||
> +           pfit_pgm_ratios != pipe_config->gmch_pfit.pgm_ratios) {
> +               pipe_config->gmch_pfit.control = pfit_control;
> +               pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
>         }
>         dev_priv->lvds_border_bits = border;
>  }
> --
> 1.7.10.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] drm/i915: move PCH pfit controls into pipe_config
  2013-05-02 22:02   ` Paulo Zanoni
@ 2013-05-03  8:10     ` Daniel Vetter
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Vetter @ 2013-05-03  8:10 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, May 3, 2013 at 12:02 AM, Paulo Zanoni <przanoni@gmail.com> wrote:
>>  static void valleyview_crtc_enable(struct drm_crtc *crtc)
>> @@ -5800,6 +5798,9 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
>>                 /* XXX: Should check for edp transcoder here, but thanks to init
>>                  * sequence that's not yet available. Just in case desktop eDP
>>                  * on PORT D is possible on haswell, too. */
>> +               /* Even the eDP panel fitter is outside the always-on well. */
>> +               if (I915_READ(PF_WIN_SZ(crtc->pipe)))
>
> So this patch made it to drm-intel-next-queued and the line above
> causes "unclaimed register" errors. This happens even if we don't
> disable the power well, and we were 100% clear of these error messages
> on that case, so I guess I can call this a "regression". Can you
> please provide a fix?

Well, that hunk switches from checking dev_priv->pch_pf_size (which is
now in crtc->config, so we'd need to check the right
pipe/cpu_transcoder first) to the register value, which is just plain
bogus.

While at it we could fix the XXX in haswell_crtc_disable, which is now
possible with the pch pfit tracking.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-05-03  8:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-25 19:55 [PATCH 1/3] drm/i915: factor out GMCH panel fitting code and use for eDP v3 Jesse Barnes
2013-04-25 19:55 ` [PATCH 2/3] drm/i915: move PCH pfit controls into pipe_config Jesse Barnes
2013-05-02 22:02   ` Paulo Zanoni
2013-05-03  8:10     ` Daniel Vetter
2013-04-25 19:55 ` [PATCH 3/3] drm/i915: warn about invalid pfit modes Jesse Barnes
2013-04-25 20:20   ` Daniel Vetter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox