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