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