Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.h      |    2 +
 drivers/gpu/drm/i915/intel_display.c |   16 +++----
 drivers/gpu/drm/i915/intel_lvds.c    |   70 ++++++++++++++++++++++++++++++++--
 3 files changed, 75 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ad8dab5..6da15d8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -610,6 +610,8 @@ 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 07f893f..9b5fab4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1914,15 +1914,13 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, 
int mode)
                /* Enable panel fitting for LVDS */
                if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
                    || HAS_eDP || intel_pch_has_edp(crtc)) {
-                       temp = I915_READ(pf_ctl_reg);
-                       I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | 
PF_FILTER_MED_3x3);
-
-                       /* currently full aspect */
-                       I915_WRITE(pf_win_pos, 0);
-
-                       I915_WRITE(pf_win_size,
-                                  (dev_priv->panel_fixed_mode->hdisplay << 16) 
|
-                                  (dev_priv->panel_fixed_mode->vdisplay));
+                       if (dev_priv->pch_pf_size) {
+                               temp = I915_READ(pf_ctl_reg);
+                               I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | 
PF_FILTER_MED_3x3);
+                               I915_WRITE(pf_win_pos, dev_priv->pch_pf_pos);
+                               I915_WRITE(pf_win_size, dev_priv->pch_pf_size);
+                       } else
+                               I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
                }
 
                /* Enable CPU pipe */
diff --git a/drivers/gpu/drm/i915/intel_lvds.c 
b/drivers/gpu/drm/i915/intel_lvds.c
index 312ac30..abbe32e 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -218,6 +218,68 @@ static inline u32 panel_fitter_scaling(u32 source, u32 
target)
        return (FACTOR * ratio + FACTOR/2) / FACTOR;
 }
 
+static bool
+intel_pch_lvds_mode_fixup(struct intel_lvds *intel_lvds,
+                         struct drm_display_mode *mode,
+                         struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = intel_lvds->base.enc.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
+       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 (intel_lvds->fitting_mode) {
+       case DRM_MODE_SCALE_CENTER:
+               width = mode->hdisplay;
+               height = mode->vdisplay;
+               x = (fixed_mode->hdisplay - width + 1)/2;
+               y = (fixed_mode->vdisplay - height + 1)/2;
+               break;
+
+       case DRM_MODE_SCALE_ASPECT:
+               /* Scale but preserve the aspect ratio */
+               {
+                       u32 scaled_width = fixed_mode->hdisplay * 
mode->vdisplay;
+                       u32 scaled_height = mode->hdisplay * 
fixed_mode->vdisplay;
+                       if (scaled_width > scaled_height) { /* pillar */
+                               width = scaled_height / mode->vdisplay;
+                               x = (fixed_mode->hdisplay - width + 1) / 2;
+                               y = 0;
+                               height = fixed_mode->vdisplay;
+                       } else if (scaled_width < scaled_height) { /* letter */
+                               height = scaled_width / mode->hdisplay;
+                               y = (fixed_mode->vdisplay - height + 1) / 2;
+                               x = 0;
+                               width = fixed_mode->hdisplay;
+                       } else {
+                               x = y = 0;
+                               width = fixed_mode->hdisplay;
+                               height = fixed_mode->vdisplay;
+                       }
+               }
+               break;
+
+       default:
+       case DRM_MODE_SCALE_FULLSCREEN:
+               x = y = 0;
+               width = fixed_mode->hdisplay;
+               height = fixed_mode->vdisplay;
+               break;
+       }
+
+done:
+       dev_priv->pch_pf_pos = (x << 16) | y;
+       dev_priv->pch_pf_size = (width << 16) | height;
+       return true;
+}
+
 static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                                  struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode)
@@ -267,6 +329,10 @@ static bool intel_lvds_mode_fixup(struct drm_encoder 
*encoder,
        adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
        drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
 
+       if (HAS_PCH_SPLIT(dev))
+               return intel_pch_lvds_mode_fixup(intel_lvds,
+                                                mode, adjusted_mode);
+
        /* Make sure pre-965s set dither correctly */
        if (!IS_I965G(dev)) {
                if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
@@ -278,10 +344,6 @@ static bool intel_lvds_mode_fixup(struct drm_encoder 
*encoder,
            adjusted_mode->vdisplay == mode->vdisplay)
                goto out;
 
-       /* full screen scale for now */
-       if (HAS_PCH_SPLIT(dev))
-               goto out;
-
        /* 965+ wants fuzzy fitting */
        if (IS_I965G(dev))
                pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
-- 
1.7.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to