[Intel-gfx] [PATCH] drm/i915: Enable aspect/centering panel fitting for Ironlake.
Chris Wilson
chris at chris-wilson.co.uk
Wed Aug 4 16:04:01 CEST 2010
Signed-off-by: Chris Wilson <chris at 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
More information about the Intel-gfx
mailing list