On Tue, Mar 20, 2012 at 10:48 AM, Paulo Zanoni <przanoni@xxxxxxxxx> wrote: > From: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> > > They're named "underscan x" and "underscan y". The properties accept > values from 0 to 100, where 0 is "don't compensate" and 100 is "shrink > the screen as much as possible". FWIW, the radeon driver already exposes something similar. It might be worthwhile to try and use consistent naming and property options. We have an "underscan" property: static struct drm_prop_enum_list radeon_underscan_enum_list[] = { { UNDERSCAN_OFF, "off" }, { UNDERSCAN_ON, "on" }, { UNDERSCAN_AUTO, "auto" }, }; "off" disables underscan "on" forces it on "auto" tries to enable/disable underscan automatically based on EDID information. RIght now we just check if the monitor is HDMI and the mode is an standard HD mode, but IIRC, there is also a CEA extension block that is supposed to tell you whether the monitor is overscanning or not. Then we have "underscan hborder" and "underscan vborder" to adjust the amount of underscan. See radeon_display.c in the kernel. Alex > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_drv.h | 2 + > drivers/gpu/drm/i915/intel_display.c | 110 +++++++++++++++++++++++++++++++++- > 2 files changed, 111 insertions(+), 1 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 7994c4f..fb9062d 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -781,6 +781,8 @@ typedef struct drm_i915_private { > struct drm_property *broadcast_rgb_property; > struct drm_property *force_audio_property; > struct drm_property *rotation_property; > + struct drm_property *x_underscan_property; > + struct drm_property *y_underscan_property; > } drm_i915_private_t; > > enum hdmi_force_audio { > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 4842de8..b36572d 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -5620,6 +5620,77 @@ static int ironlake_get_refclk(struct drm_crtc *crtc) > return 120000; > } > > +/* > + * The overscan compensation property (aka underscan property) has values from 0 > + * to 100, where 0 means that the compensation is disabled and 100 means the > + * screen should shrink as much as possible. The current maximum supported value > + * (from the specifications) is "src/dst < 1.125". > + * > + * In short: > + * - if val == 0 -> dst = src > + * - if val == 100 -> dst = src * 8/9 > + * - dst can't be odd > + * - dst can't be < src * 8 / (double)9 > + * - so the formulae, not considering rounding, should be: > + * - dst = 9*src - prop*src/100 / 9 > + */ > +static void ironlake_crtc_overscan_compensate(struct drm_crtc *crtc) > +{ > + struct drm_device *dev = crtc->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + int pipe = intel_crtc->pipe; > + uint64_t prop_x = 0, prop_y = 0; > + int tot_x, tot_y, src_x, src_y, dst_x, dst_y, pos_x, pos_y; > + u32 reg; > + > + drm_crtc_property_get_value(crtc, dev_priv->x_underscan_property, > + &prop_x); > + drm_crtc_property_get_value(crtc, dev_priv->y_underscan_property, > + &prop_y); > + > + if (prop_x == 0 && prop_y == 0 && > + !(dev_priv->pch_pf_size && > + (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP))) { > + I915_WRITE(PF_CTL(pipe), 0); > + I915_WRITE(PF_WIN_POS(pipe), 0); > + I915_WRITE(PF_WIN_SZ(pipe), 0); > + return; > + } > + > + reg = I915_READ(HTOTAL(pipe)); > + tot_x = (reg & 0xFFF) + 1; > + reg = I915_READ(VTOTAL(pipe)); > + tot_y = (reg & 0xFFF) + 1; > + reg = I915_READ(PIPESRC(pipe)); > + src_x = ((reg >> 16) & 0xFFF) + 1; > + src_y = (reg & 0xFFF) + 1; > + > + dst_x = (src_x * 9 - src_x * prop_x / 100 + 8) / 9; > + dst_x &= ~1; > + if (dst_x < ((src_x * 8 + 8) / 9)) > + dst_x += 2; > + > + dst_y = (src_y * 9 - src_y * prop_y / 100 + 8) / 9; > + dst_y &= ~1; > + if (dst_y < ((src_y * 8 + 8) / 9)) > + dst_y += 2; > + > + pos_x = (tot_x - dst_x) / 2; > + pos_y = (tot_y - dst_y) / 2; > + > + if (pos_x == 1) > + pos_x = 0; > + reg = I915_READ(PIPECONF(pipe)); > + if ((reg & PIPECONF_INTERLACE_MASK) != PIPECONF_PROGRESSIVE) > + pos_y &= ~1; > + > + I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); > + I915_WRITE(PF_WIN_POS(pipe), (pos_x << 16) | pos_y); > + I915_WRITE(PF_WIN_SZ(pipe), (dst_x << 16) | dst_y); > +} > + > + > static int ironlake_crtc_mode_set(struct drm_crtc *crtc, > struct drm_display_mode *mode, > struct drm_display_mode *adjusted_mode, > @@ -6065,6 +6136,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, > > intel_update_watermarks(dev); > > + ironlake_crtc_overscan_compensate(crtc); > + > return ret; > } > > @@ -7666,6 +7739,11 @@ static int intel_crtc_set_property(struct drm_crtc *crtc, > > if (property == dev_priv->rotation_property) > intel_crtc_set_rotation(crtc, val); > + if (property == dev_priv->x_underscan_property || > + property == dev_priv->y_underscan_property) { > + drm_crtc_property_set_value(crtc, property, val); > + ironlake_crtc_overscan_compensate(crtc); > + } > return 0; > } > > @@ -7708,6 +7786,34 @@ static void intel_attach_rotation_property(struct drm_crtc *crtc) > drm_crtc_attach_property(crtc, prop, 0); > } > > +static void intel_attach_underscan_properties(struct drm_crtc *crtc) > +{ > + struct drm_device *dev = crtc->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_property *prop_x, *prop_y; > + > + prop_x = dev_priv->x_underscan_property; > + if (prop_x == NULL) { > + prop_x = drm_property_create_range(dev, 0, "underscan x", > + 0, 100); > + if (prop_x != NULL) > + dev_priv->x_underscan_property = prop_x; > + } > + > + prop_y = dev_priv->y_underscan_property; > + if (prop_y == NULL) { > + prop_y = drm_property_create_range(dev, 0, "underscan y", > + 0, 100); > + if (prop_y != NULL) > + dev_priv->y_underscan_property = prop_y; > + } > + > + if (prop_x) > + drm_crtc_attach_property(crtc, prop_x, 0); > + if (prop_y) > + drm_crtc_attach_property(crtc, prop_y, 0); > +} > + > static void intel_crtc_init(struct drm_device *dev, int pipe) > { > drm_i915_private_t *dev_priv = dev->dev_private; > @@ -7727,8 +7833,10 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) > intel_crtc->lut_b[i] = i; > } > > - if (INTEL_INFO(dev)->gen >= 5) > + if (INTEL_INFO(dev)->gen >= 5) { > intel_attach_rotation_property(&intel_crtc->base); > + intel_attach_underscan_properties(&intel_crtc->base); > + } > > /* Swap pipes & planes for FBC on pre-965 */ > intel_crtc->pipe = pipe; > -- > 1.7.9.1 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel