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
