Continuing the Libretto W100 saga, in order to use a non-native mode on
the SDVO panel, I need to engage the panel fitter for that pipe. So try
to do so in a generic fashion such that we use the panel fitter to fixup
any input (adjusted) mode that is not equal to the output mode.

Signed-off-by: Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/i915_drv.h      |    2 -
 drivers/gpu/drm/i915/intel_display.c |   69 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_dp.c      |    2 -
 drivers/gpu/drm/i915/intel_drv.h     |   20 ++++++++--
 drivers/gpu/drm/i915/intel_lvds.c    |    6 +--
 drivers/gpu/drm/i915/intel_panel.c   |   61 ------------------------------
 6 files changed, 82 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 30780f2..80a243e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -644,8 +644,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[2];
        struct drm_crtc *pipe_to_crtc_mapping[2];
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 8645a97..2b2c010 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2024,6 +2024,63 @@ static void intel_crtc_wait_for_pending_flips(struct 
drm_crtc *crtc)
                   atomic_read(&obj->pending_flip) == 0);
 }
 
+static bool pch_pf_enable(struct intel_crtc *crtc,
+                         int *x, int *y, int *width, int *height)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int htotal = I915_READ(HTOTAL(crtc->pipe)) & 0xffff;
+       int vtotal = I915_READ(VTOTAL(crtc->pipe)) & 0xffff;
+       int src = I915_READ(PIPESRC(crtc->pipe));
+       int src_width, src_height;
+       int dst_width, dst_height;
+
+       /* Native modes don't need fitting */
+       if ((htotal << 16 | vtotal) == src)
+               return false;
+
+       src_width = (src >> 16) + 1;
+       src_height = (src & 0xffff) + 1;
+       dst_width = (htotal & 0xffff) + 1;
+       dst_height = (vtotal & 0xffff) + 1;
+
+       switch (crtc->fitting_mode) {
+       case DRM_MODE_SCALE_CENTER:
+               *width = src_width;
+               *height = src_height;
+               *x = (dst_width - src_width + 1)/2;
+               *y = (dst_height - src_height + 1)/2;
+               break;
+
+       default:
+       case DRM_MODE_SCALE_ASPECT:
+               /* Scale but preserve the aspect ratio */
+               {
+                       u32 scaled_width = dst_width * src_height;
+                       u32 scaled_height = src_width * dst_height;
+                       if (scaled_width > scaled_height) { /* pillar */
+                               *width = scaled_height / src_height;
+                               *x = (dst_width - *width + 1) / 2;
+                               *y = 0;
+                               *height = dst_height;
+                       } else if (scaled_width < scaled_height) { /* letter */
+                               *height = scaled_width / src_width;
+                               *y = (dst_height - *height + 1) / 2;
+                               *x = 0;
+                               *width = dst_width;
+                       } else {
+                       case DRM_MODE_SCALE_FULLSCREEN:
+                               *x = *y = 0;
+                               *width = dst_width;
+                               *height = dst_height;
+                       }
+               }
+               break;
+       }
+
+       return true;
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -2031,6 +2088,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
+       int x, y, width, height;
        u32 reg, temp;
 
        if (intel_crtc->active)
@@ -2047,9 +2105,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
        ironlake_fdi_enable(crtc);
 
-       /* Enable panel fitting for LVDS */
-       if (dev_priv->pch_pf_size &&
-           (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
+       if (pch_pf_enable(intel_crtc, &x, &y, &width, &height)) {
                /* Force use of hard-coded filter coefficients
                 * as some pre-programmed values are broken,
                 * e.g. x201.
@@ -2057,9 +2113,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1,
                           PF_ENABLE | PF_FILTER_MED_3x3);
                I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS,
-                          dev_priv->pch_pf_pos);
+                          x << 16 | y);
                I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ,
-                          dev_priv->pch_pf_size);
+                          width << 16 | height);
        }
 
        /* Enable CPU pipe */
@@ -2631,6 +2687,9 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
        if (adjusted_mode->crtc_htotal == 0)
                drm_mode_set_crtcinfo(adjusted_mode, 0);
 
+       to_intel_crtc(crtc)->fitting_mode =
+               intel_mode_get_panel_fitting(adjusted_mode);
+
        return true;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1dc6040..f452714 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -598,8 +598,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct 
drm_display_mode *mode,
 
        if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
                intel_fixed_panel_mode(dev_priv->panel_fixed_mode, 
adjusted_mode);
-               intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
-                                       mode, adjusted_mode);
                /*
                 * the mode->clock is used to calculate the Data&Link M/N
                 * of the pipe. For the eDP the fixed clock should be used.
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index acdea65..8b29fce 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -110,6 +110,8 @@
 /* drm_display_mode->private_flags */
 #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
 #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << 
INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
+#define INTEL_MODE_PANEL_FITTING_SHIFT (0x4)
+#define INTEL_MODE_PANEL_FITTING_MASK (0xf << INTEL_MODE_PANEL_FITTING_SHIFT)
 
 static inline void
 intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
@@ -125,6 +127,19 @@ intel_mode_get_pixel_multiplier(const struct 
drm_display_mode *mode)
        return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) >> 
INTEL_MODE_PIXEL_MULTIPLIER_SHIFT;
 }
 
+static inline void
+intel_mode_set_panel_fitting(struct drm_display_mode *mode,
+                            int pf_mode)
+{
+       mode->private_flags |= pf_mode << INTEL_MODE_PANEL_FITTING_SHIFT;
+}
+
+static inline int
+intel_mode_get_panel_fitting(const struct drm_display_mode *mode)
+{
+       return (mode->private_flags & INTEL_MODE_PANEL_FITTING_MASK)>> 
INTEL_MODE_PANEL_FITTING_SHIFT;
+}
+
 struct intel_framebuffer {
        struct drm_framebuffer base;
        struct drm_i915_gem_object *obj;
@@ -158,6 +173,7 @@ struct intel_crtc {
        enum plane plane;
        u8 lut_r[256], lut_g[256], lut_b[256];
        int dpms_mode;
+       int fitting_mode;
        bool active; /* is the crtc on? independent of the dpms mode */
        bool busy; /* is scanout buffer being updated frequently? */
        struct timer_list idle_timer;
@@ -250,10 +266,6 @@ extern bool intel_encoder_is_pch_edp(struct drm_encoder 
*encoder);
 /* intel_panel.c */
 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,
-                                   struct drm_display_mode *mode,
-                                   struct drm_display_mode *adjusted_mode);
 extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 extern u32 intel_panel_get_backlight(struct drm_device *dev);
 extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c 
b/drivers/gpu/drm/i915/intel_lvds.c
index aa23070..55c9ac3 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -255,12 +255,10 @@ static bool intel_lvds_mode_fixup(struct drm_encoder 
*encoder,
         * of the original mode.
         */
        intel_fixed_panel_mode(intel_lvds->fixed_mode, adjusted_mode);
+       intel_mode_set_panel_fitting(adjusted_mode, intel_lvds->fitting_mode);
 
-       if (HAS_PCH_SPLIT(dev)) {
-               intel_pch_panel_fitting(dev, intel_lvds->fitting_mode,
-                                       mode, adjusted_mode);
+       if (HAS_PCH_SPLIT(dev))
                return true;
-       }
 
        /* Make sure pre-965s set dither correctly */
        if (INTEL_INFO(dev)->gen < 4) {
diff --git a/drivers/gpu/drm/i915/intel_panel.c 
b/drivers/gpu/drm/i915/intel_panel.c
index 7350ec2..4dda915 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -51,67 +51,6 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
        drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
 }
 
-/* adjusted_mode has been preset to be the panel's fixed mode */
-void
-intel_pch_panel_fitting(struct drm_device *dev,
-                       int fitting_mode,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int x, y, width, height;
-
-       x = y = width = height = 0;
-
-       /* Native modes don't need fitting */
-       if (adjusted_mode->hdisplay == mode->hdisplay &&
-           adjusted_mode->vdisplay == mode->vdisplay)
-               goto done;
-
-       switch (fitting_mode) {
-       case DRM_MODE_SCALE_CENTER:
-               width = mode->hdisplay;
-               height = mode->vdisplay;
-               x = (adjusted_mode->hdisplay - width + 1)/2;
-               y = (adjusted_mode->vdisplay - height + 1)/2;
-               break;
-
-       case DRM_MODE_SCALE_ASPECT:
-               /* Scale but preserve the aspect ratio */
-               {
-                       u32 scaled_width = adjusted_mode->hdisplay * 
mode->vdisplay;
-                       u32 scaled_height = mode->hdisplay * 
adjusted_mode->vdisplay;
-                       if (scaled_width > scaled_height) { /* pillar */
-                               width = scaled_height / mode->vdisplay;
-                               x = (adjusted_mode->hdisplay - width + 1) / 2;
-                               y = 0;
-                               height = adjusted_mode->vdisplay;
-                       } else if (scaled_width < scaled_height) { /* letter */
-                               height = scaled_width / mode->hdisplay;
-                               y = (adjusted_mode->vdisplay - height + 1) / 2;
-                               x = 0;
-                               width = adjusted_mode->hdisplay;
-                       } else {
-                               x = y = 0;
-                               width = adjusted_mode->hdisplay;
-                               height = adjusted_mode->vdisplay;
-                       }
-               }
-               break;
-
-       default:
-       case DRM_MODE_SCALE_FULLSCREEN:
-               x = y = 0;
-               width = adjusted_mode->hdisplay;
-               height = adjusted_mode->vdisplay;
-               break;
-       }
-
-done:
-       dev_priv->pch_pf_pos = (x << 16) | y;
-       dev_priv->pch_pf_size = (width << 16) | height;
-}
-
 static int is_backlight_combination_mode(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-- 
1.7.2.3

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to