[Intel-gfx] [PATCH 1/2] drm/i915: factor out GMCH panel fitting code and use for eDP v2
Mika Kuoppala
mika.kuoppala at linux.intel.com
Wed Apr 24 17:05:54 CEST 2013
Jesse Barnes <jbarnes at virtuousgeek.org> writes:
> This gets the panel fitter working on eDP on VLV, and should also apply
> to eDP panels on G4x chipsets (if we ever detect and mark an all-in-one
> panel as eDP anyway).
>
> A few cleanups are still possible on top of this, for example the LVDS
> border control could be placed in the LVDS encoder structure and updated
> based on the result of the panel fitter calculation.
>
> Multi-pipe fitting isn't handled correctly either if we ever get a config
> that wants to try the panel fitter on more than one output at a time.
>
> v2: use pipe_config for storing pfit values (Daniel)
> add i9xx_pfit_enable function for use by 9xx and VLV (Daniel)
>
> Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
> ---
> drivers/gpu/drm/i915/intel_display.c | 33 ++++++
> drivers/gpu/drm/i915/intel_dp.c | 11 +-
> drivers/gpu/drm/i915/intel_drv.h | 6 +
> drivers/gpu/drm/i915/intel_lvds.c | 208 +---------------------------------
> drivers/gpu/drm/i915/intel_panel.c | 190 +++++++++++++++++++++++++++++++
> 5 files changed, 240 insertions(+), 208 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3fadd33..085a3ef 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3692,6 +3692,33 @@ g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
> }
> }
>
> +static void i9xx_pfit_enable(struct intel_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_crtc_config *pipe_config = &crtc->config;
> +
> + if (!(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
> + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)))
> + return;
> +
> + WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
> + assert_pipe_disabled(dev_priv, crtc->pipe);
> +
> + /*
> + * Enable automatic panel scaling so that non-native modes
> + * fill the screen. The panel fitter should only be
> + * adjusted whilst the pipe is disabled, according to
> + * register description and PRM.
> + */
> + DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
> + pipe_config->pfit_control,
> + pipe_config->pfit_pgm_ratios);
> +
> + I915_WRITE(PFIT_PGM_RATIOS, pipe_config->pfit_pgm_ratios);
> + I915_WRITE(PFIT_CONTROL, pipe_config->pfit_control);
> +}
> +
> static void valleyview_crtc_enable(struct drm_crtc *crtc)
> {
> struct drm_device *dev = crtc->dev;
> @@ -3725,6 +3752,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->enable(encoder);
>
> + /* Enable panel fitting for eDP */
> + i9xx_pfit_enable(intel_crtc);
> +
> intel_enable_pipe(dev_priv, pipe, false);
> intel_enable_plane(dev_priv, plane, pipe);
>
> @@ -3761,6 +3791,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
> if (encoder->pre_enable)
> encoder->pre_enable(encoder);
>
> + /* Enable panel fitting for LVDS */
> + i9xx_pfit_enable(intel_crtc);
> +
> intel_enable_pipe(dev_priv, pipe, false);
> intel_enable_plane(dev_priv, plane, pipe);
> if (IS_G4X(dev))
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 0580026..cb562ab 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -669,6 +669,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
> struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
> struct drm_display_mode *mode = &pipe_config->requested_mode;
> struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> + struct intel_crtc *intel_crtc = encoder->new_crtc;
> struct intel_connector *intel_connector = intel_dp->attached_connector;
> int lane_count, clock;
> int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
> @@ -685,9 +686,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
> if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
> intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
> adjusted_mode);
> - intel_pch_panel_fitting(dev,
> - intel_connector->panel.fitting_mode,
> - mode, adjusted_mode);
> + if (!HAS_PCH_SPLIT(dev))
> + intel_gmch_panel_fitting(intel_crtc, pipe_config,
> + intel_connector->panel.fitting_mode);
> + else
> + intel_pch_panel_fitting(dev,
> + intel_connector->panel.fitting_mode,
> + mode, adjusted_mode);
> }
> /* We need to take the panel's fixed mode into account. */
> target_clock = adjusted_mode->clock;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 63264ed..8b45527 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -224,6 +224,9 @@ struct intel_crtc_config {
> int pixel_target_clock;
> /* Used by SDVO (and if we ever fix it, HDMI). */
> unsigned pixel_multiplier;
> +
> + /* Panel fitter controls for gen2-gen4 + VLV */
> + u32 pfit_control, pfit_pgm_ratios;
> };
>
> struct intel_crtc {
> @@ -540,6 +543,9 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,
> int fitting_mode,
> const struct drm_display_mode *mode,
> struct drm_display_mode *adjusted_mode);
> +extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
> + struct intel_crtc_config *pipe_config,
> + int fitting_mode);
> extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
> extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
> extern int intel_panel_setup_backlight(struct drm_connector *connector);
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 563f505..cb0066a 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -49,8 +49,6 @@ struct intel_lvds_connector {
> struct intel_lvds_encoder {
> struct intel_encoder base;
>
> - u32 pfit_control;
> - u32 pfit_pgm_ratios;
> bool is_dual_link;
> u32 reg;
>
> @@ -150,32 +148,6 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
> I915_WRITE(lvds_encoder->reg, temp);
> }
>
> -static void intel_pre_enable_lvds(struct intel_encoder *encoder)
> -{
> - struct drm_device *dev = encoder->base.dev;
> - struct intel_lvds_encoder *enc = to_lvds_encoder(&encoder->base);
> - struct drm_i915_private *dev_priv = dev->dev_private;
> -
> - if (HAS_PCH_SPLIT(dev) || !enc->pfit_control)
> - return;
> -
> - WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
> - assert_pipe_disabled(dev_priv, to_intel_crtc(encoder->base.crtc)->pipe);
> -
> - /*
> - * Enable automatic panel scaling so that non-native modes
> - * fill the screen. The panel fitter should only be
> - * adjusted whilst the pipe is disabled, according to
> - * register description and PRM.
> - */
> - DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
> - enc->pfit_control,
> - enc->pfit_pgm_ratios);
> -
> - I915_WRITE(PFIT_PGM_RATIOS, enc->pfit_pgm_ratios);
> - I915_WRITE(PFIT_CONTROL, enc->pfit_control);
> -}
> -
> /**
> * Sets the power state for the panel.
> */
> @@ -244,62 +216,6 @@ static int intel_lvds_mode_valid(struct drm_connector *connector,
> return MODE_OK;
> }
>
> -static void
> -centre_horizontally(struct drm_display_mode *mode,
> - int width)
> -{
> - u32 border, sync_pos, blank_width, sync_width;
> -
> - /* keep the hsync and hblank widths constant */
> - sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
> - blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
> - sync_pos = (blank_width - sync_width + 1) / 2;
> -
> - border = (mode->hdisplay - width + 1) / 2;
> - border += border & 1; /* make the border even */
> -
> - mode->crtc_hdisplay = width;
> - mode->crtc_hblank_start = width + border;
> - mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
> -
> - mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
> - mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
> -}
> -
> -static void
> -centre_vertically(struct drm_display_mode *mode,
> - int height)
> -{
> - u32 border, sync_pos, blank_width, sync_width;
> -
> - /* keep the vsync and vblank widths constant */
> - sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
> - blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
> - sync_pos = (blank_width - sync_width + 1) / 2;
> -
> - border = (mode->vdisplay - height + 1) / 2;
> -
> - mode->crtc_vdisplay = height;
> - mode->crtc_vblank_start = height + border;
> - mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
> -
> - mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
> - mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
> -}
> -
> -static inline u32 panel_fitter_scaling(u32 source, u32 target)
> -{
> - /*
> - * Floating point operation is not supported. So the FACTOR
> - * is defined, which can avoid the floating point computation
> - * when calculating the panel ratio.
> - */
> -#define ACCURACY 12
> -#define FACTOR (1 << ACCURACY)
> - u32 ratio = source * FACTOR / target;
> - return (FACTOR * ratio + FACTOR/2) / FACTOR;
> -}
> -
> static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
> struct intel_crtc_config *pipe_config)
> {
> @@ -312,7 +228,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
> struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
> struct drm_display_mode *mode = &pipe_config->requested_mode;
> struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
> - u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
> unsigned int lvds_bpp;
> int pipe;
>
> @@ -352,18 +267,11 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
> intel_connector->panel.fitting_mode,
> mode, adjusted_mode);
> return true;
> + } else {
> + intel_gmch_panel_fitting(intel_crtc, pipe_config,
> + intel_connector->panel.fitting_mode);
> }
>
> - /* Native modes don't need fitting */
> - if (adjusted_mode->hdisplay == mode->hdisplay &&
> - adjusted_mode->vdisplay == mode->vdisplay)
> - goto out;
> -
> - /* 965+ wants fuzzy fitting */
> - if (INTEL_INFO(dev)->gen >= 4)
> - pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
> - PFIT_FILTER_FUZZY);
> -
> /*
> * Enable automatic panel scaling for non-native modes so that they fill
> * the screen. Should be enabled before the pipe is enabled, according
> @@ -376,111 +284,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
> drm_mode_set_crtcinfo(adjusted_mode, 0);
> pipe_config->timings_set = true;
>
> - switch (intel_connector->panel.fitting_mode) {
> - case DRM_MODE_SCALE_CENTER:
> - /*
> - * For centered modes, we have to calculate border widths &
> - * heights and modify the values programmed into the CRTC.
> - */
> - centre_horizontally(adjusted_mode, mode->hdisplay);
> - centre_vertically(adjusted_mode, mode->vdisplay);
> - border = LVDS_BORDER_ENABLE;
> - break;
> -
> - case DRM_MODE_SCALE_ASPECT:
> - /* Scale but preserve the aspect ratio */
> - if (INTEL_INFO(dev)->gen >= 4) {
> - u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
> - u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
> -
> - /* 965+ is easy, it does everything in hw */
> - if (scaled_width > scaled_height)
> - pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR;
> - else if (scaled_width < scaled_height)
> - pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER;
> - else if (adjusted_mode->hdisplay != mode->hdisplay)
> - pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
> - } else {
> - u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
> - u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
> - /*
> - * For earlier chips we have to calculate the scaling
> - * ratio by hand and program it into the
> - * PFIT_PGM_RATIO register
> - */
> - if (scaled_width > scaled_height) { /* pillar */
> - centre_horizontally(adjusted_mode, scaled_height / mode->vdisplay);
> -
> - border = LVDS_BORDER_ENABLE;
> - if (mode->vdisplay != adjusted_mode->vdisplay) {
> - u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
> - pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
> - bits << PFIT_VERT_SCALE_SHIFT);
> - pfit_control |= (PFIT_ENABLE |
> - VERT_INTERP_BILINEAR |
> - HORIZ_INTERP_BILINEAR);
> - }
> - } else if (scaled_width < scaled_height) { /* letter */
> - centre_vertically(adjusted_mode, scaled_width / mode->hdisplay);
> -
> - border = LVDS_BORDER_ENABLE;
> - if (mode->hdisplay != adjusted_mode->hdisplay) {
> - u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
> - pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
> - bits << PFIT_VERT_SCALE_SHIFT);
> - pfit_control |= (PFIT_ENABLE |
> - VERT_INTERP_BILINEAR |
> - HORIZ_INTERP_BILINEAR);
> - }
> - } else
> - /* Aspects match, Let hw scale both directions */
> - pfit_control |= (PFIT_ENABLE |
> - VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
> - VERT_INTERP_BILINEAR |
> - HORIZ_INTERP_BILINEAR);
> - }
> - break;
> -
> - case DRM_MODE_SCALE_FULLSCREEN:
> - /*
> - * Full scaling, even if it changes the aspect ratio.
> - * Fortunately this is all done for us in hw.
> - */
> - if (mode->vdisplay != adjusted_mode->vdisplay ||
> - mode->hdisplay != adjusted_mode->hdisplay) {
> - pfit_control |= PFIT_ENABLE;
> - if (INTEL_INFO(dev)->gen >= 4)
> - pfit_control |= PFIT_SCALING_AUTO;
> - else
> - pfit_control |= (VERT_AUTO_SCALE |
> - VERT_INTERP_BILINEAR |
> - HORIZ_AUTO_SCALE |
> - HORIZ_INTERP_BILINEAR);
> - }
> - break;
> -
> - default:
> - break;
> - }
> -
> -out:
> - /* If not enabling scaling, be consistent and always use 0. */
> - if ((pfit_control & PFIT_ENABLE) == 0) {
> - pfit_control = 0;
> - pfit_pgm_ratios = 0;
> - }
> -
> - /* Make sure pre-965 set dither correctly */
> - if (INTEL_INFO(dev)->gen < 4 && dev_priv->lvds_dither)
> - pfit_control |= PANEL_8TO6_DITHER_ENABLE;
> -
> - if (pfit_control != lvds_encoder->pfit_control ||
> - pfit_pgm_ratios != lvds_encoder->pfit_pgm_ratios) {
> - lvds_encoder->pfit_control = pfit_control;
> - lvds_encoder->pfit_pgm_ratios = pfit_pgm_ratios;
> - }
> - dev_priv->lvds_border_bits = border;
> -
> /*
> * XXX: It would be nice to support lower refresh rates on the
> * panels to reduce power consumption, and perhaps match the
> @@ -1110,10 +913,6 @@ bool intel_lvds_init(struct drm_device *dev)
>
> lvds_encoder->attached_connector = lvds_connector;
>
> - if (!HAS_PCH_SPLIT(dev)) {
> - lvds_encoder->pfit_control = I915_READ(PFIT_CONTROL);
> - }
> -
> intel_encoder = &lvds_encoder->base;
> encoder = &intel_encoder->base;
> intel_connector = &lvds_connector->base;
> @@ -1125,7 +924,6 @@ bool intel_lvds_init(struct drm_device *dev)
> DRM_MODE_ENCODER_LVDS);
>
> intel_encoder->enable = intel_enable_lvds;
> - intel_encoder->pre_enable = intel_pre_enable_lvds;
> intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;
> intel_encoder->compute_config = intel_lvds_compute_config;
> intel_encoder->disable = intel_disable_lvds;
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index eb5e6e9..d434a8d 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -117,6 +117,196 @@ done:
> dev_priv->pch_pf_size = (width << 16) | height;
> }
>
> +static void
> +centre_horizontally(struct drm_display_mode *mode,
> + int width)
> +{
> + u32 border, sync_pos, blank_width, sync_width;
> +
> + /* keep the hsync and hblank widths constant */
> + sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
> + blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
> + sync_pos = (blank_width - sync_width + 1) / 2;
> +
> + border = (mode->hdisplay - width + 1) / 2;
> + border += border & 1; /* make the border even */
> +
> + mode->crtc_hdisplay = width;
> + mode->crtc_hblank_start = width + border;
> + mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
> +
> + mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
> + mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
> +}
> +
> +static void
> +centre_vertically(struct drm_display_mode *mode,
> + int height)
> +{
> + u32 border, sync_pos, blank_width, sync_width;
> +
> + /* keep the vsync and vblank widths constant */
> + sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
> + blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
> + sync_pos = (blank_width - sync_width + 1) / 2;
> +
> + border = (mode->vdisplay - height + 1) / 2;
> +
> + mode->crtc_vdisplay = height;
> + mode->crtc_vblank_start = height + border;
> + mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
> +
> + mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
> + mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
> +}
> +
> +static inline u32 panel_fitter_scaling(u32 source, u32 target)
> +{
> + /*
> + * Floating point operation is not supported. So the FACTOR
> + * is defined, which can avoid the floating point computation
> + * when calculating the panel ratio.
> + */
> +#define ACCURACY 12
> +#define FACTOR (1 << ACCURACY)
> + u32 ratio = source * FACTOR / target;
> + return (FACTOR * ratio + FACTOR/2) / FACTOR;
> +}
> +
> +void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
> + struct intel_crtc_config *pipe_config,
> + int fitting_mode)
> +{
> + struct drm_device *dev = intel_crtc->base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
> + struct drm_display_mode *mode, *adjusted_mode;
> +
> + mode = &pipe_config->requested_mode;
> + adjusted_mode = &pipe_config->adjusted_mode;
> +
> + /* Native modes don't need fitting */
> + if (adjusted_mode->hdisplay == mode->hdisplay &&
> + adjusted_mode->vdisplay == mode->vdisplay)
> + goto out;
> +
> + switch (fitting_mode) {
> + case DRM_MODE_SCALE_CENTER:
> + /*
> + * For centered modes, we have to calculate border widths &
> + * heights and modify the values programmed into the CRTC.
> + */
> + centre_horizontally(adjusted_mode, mode->hdisplay);
> + centre_vertically(adjusted_mode, mode->vdisplay);
> + break;
> + case DRM_MODE_SCALE_ASPECT:
> + /* Scale but preserve the aspect ratio */
> + if (INTEL_INFO(dev)->gen >= 4) {
> + u32 scaled_width = adjusted_mode->hdisplay *
> + mode->vdisplay;
> + u32 scaled_height = mode->hdisplay *
> + adjusted_mode->vdisplay;
> +
> + /* 965+ is easy, it does everything in hw */
> + if (scaled_width > scaled_height)
> + pfit_control |= PFIT_ENABLE |
> + PFIT_SCALING_PILLAR;
> + else if (scaled_width < scaled_height)
> + pfit_control |= PFIT_ENABLE |
> + PFIT_SCALING_LETTER;
> + else if (adjusted_mode->hdisplay != mode->hdisplay)
> + pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
> + } else {
> + u32 scaled_width = adjusted_mode->hdisplay *
> + mode->vdisplay;
> + u32 scaled_height = mode->hdisplay *
> + adjusted_mode->vdisplay;
> + /*
> + * For earlier chips we have to calculate the scaling
> + * ratio by hand and program it into the
> + * PFIT_PGM_RATIO register
> + */
> + if (scaled_width > scaled_height) { /* pillar */
> + centre_horizontally(adjusted_mode,
> + scaled_height /
> + mode->vdisplay);
> +
> + border = LVDS_BORDER_ENABLE;
> + if (mode->vdisplay != adjusted_mode->vdisplay) {
> + u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
> + pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
> + bits << PFIT_VERT_SCALE_SHIFT);
> + pfit_control |= (PFIT_ENABLE |
> + VERT_INTERP_BILINEAR |
> + HORIZ_INTERP_BILINEAR);
> + }
> + } else if (scaled_width < scaled_height) { /* letter */
> + centre_vertically(adjusted_mode,
> + scaled_width /
> + mode->hdisplay);
> +
> + border = LVDS_BORDER_ENABLE;
> + if (mode->hdisplay != adjusted_mode->hdisplay) {
> + u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
> + pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
> + bits << PFIT_VERT_SCALE_SHIFT);
> + pfit_control |= (PFIT_ENABLE |
> + VERT_INTERP_BILINEAR |
> + HORIZ_INTERP_BILINEAR);
> + }
> + } else {
> + /* Aspects match, Let hw scale both directions */
> + pfit_control |= (PFIT_ENABLE |
> + VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
> + VERT_INTERP_BILINEAR |
> + HORIZ_INTERP_BILINEAR);
> + }
> + }
> + break;
> + default:
> + case DRM_MODE_SCALE_FULLSCREEN:
^^
This is different than it was in lvds_compute_config. If we get called
with DRM_MODE_SCALE_NONE we go to fullscreen instead.
Is this intentional?
--Mika
> + /*
> + * Full scaling, even if it changes the aspect ratio.
> + * Fortunately this is all done for us in hw.
> + */
> + if (mode->vdisplay != adjusted_mode->vdisplay ||
> + mode->hdisplay != adjusted_mode->hdisplay) {
> + pfit_control |= PFIT_ENABLE;
> + if (INTEL_INFO(dev)->gen >= 4)
> + pfit_control |= PFIT_SCALING_AUTO;
> + else
> + pfit_control |= (VERT_AUTO_SCALE |
> + VERT_INTERP_BILINEAR |
> + HORIZ_AUTO_SCALE |
> + HORIZ_INTERP_BILINEAR);
> + }
> + break;
> + }
> +
> + /* 965+ wants fuzzy fitting */
> + /* FIXME: handle multiple panels by failing gracefully */
> + if (INTEL_INFO(dev)->gen >= 4)
> + pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
> + PFIT_FILTER_FUZZY);
> +
> +out:
> + if ((pfit_control & PFIT_ENABLE) == 0) {
> + pfit_control = 0;
> + pfit_pgm_ratios = 0;
> + }
> +
> + /* Make sure pre-965 set dither correctly */
> + if (INTEL_INFO(dev)->gen < 4 && dev_priv->lvds_dither)
> + pfit_control |= PANEL_8TO6_DITHER_ENABLE;
> +
> + if (pfit_control != pipe_config->pfit_control ||
> + pfit_pgm_ratios != pipe_config->pfit_pgm_ratios) {
> + pipe_config->pfit_control = pfit_control;
> + pipe_config->pfit_pgm_ratios = pfit_pgm_ratios;
> + }
> + dev_priv->lvds_border_bits = border;
> +}
> +
> static int is_backlight_combination_mode(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> --
> 1.7.10.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list