diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-10-06 13:29:05 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-12-21 19:01:16 +1000 |
commit | b29caa5885e85bbda7c84ea55721b9e79718583a (patch) | |
tree | cd624c2e776ea2d558e315ba1cb5b63c0868ef3c /drivers/gpu/drm/nouveau/nouveau_connector.c | |
parent | 27d5030a235d89842ed70e18d924f017b34a496d (diff) | |
download | kernel_goldelico_gta04-b29caa5885e85bbda7c84ea55721b9e79718583a.zip kernel_goldelico_gta04-b29caa5885e85bbda7c84ea55721b9e79718583a.tar.gz kernel_goldelico_gta04-b29caa5885e85bbda7c84ea55721b9e79718583a.tar.bz2 |
drm/nouveau: add overscan compensation connector properties
Exposes the same connector properties as the Radeon implementation, however
their behaviour isn't exactly the same. The primary difference being that
unless both hborder/vborder have been defined by the user, the driver will
keep the aspect ratio of the overscanned area the same as the mode the
display is programmed for.
Enabled for digital outputs on GeForce 8 and up, excluding GF119.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_connector.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index cea6696..5e830a5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -420,15 +420,21 @@ static int nouveau_connector_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t value) { + struct drm_nouveau_private *dev_priv = connector->dev->dev_private; + struct nouveau_display_engine *disp = &dev_priv->engine.display; struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; struct drm_encoder *encoder = to_drm_encoder(nv_encoder); struct drm_device *dev = connector->dev; + struct nouveau_crtc *nv_crtc; int ret; + nv_crtc = NULL; + if (connector->encoder && connector->encoder->crtc) + nv_crtc = nouveau_crtc(connector->encoder->crtc); + /* Scaling mode */ if (property == dev->mode_config.scaling_mode_property) { - struct nouveau_crtc *nv_crtc = NULL; bool modeset = false; switch (value) { @@ -454,8 +460,6 @@ nouveau_connector_set_property(struct drm_connector *connector, modeset = true; nv_connector->scaling_mode = value; - if (connector->encoder && connector->encoder->crtc) - nv_crtc = nouveau_crtc(connector->encoder->crtc); if (!nv_crtc) return 0; @@ -475,18 +479,56 @@ nouveau_connector_set_property(struct drm_connector *connector, return 0; } + /* Underscan */ + if (property == disp->underscan_property) { + if (nv_connector->underscan != value) { + nv_connector->underscan = value; + if (!nv_crtc || !nv_crtc->set_scale) + return 0; + + return nv_crtc->set_scale(nv_crtc, + nv_connector->scaling_mode, + true); + } + + return 0; + } + + if (property == disp->underscan_hborder_property) { + if (nv_connector->underscan_hborder != value) { + nv_connector->underscan_hborder = value; + if (!nv_crtc || !nv_crtc->set_scale) + return 0; + + return nv_crtc->set_scale(nv_crtc, + nv_connector->scaling_mode, + true); + } + + return 0; + } + + if (property == disp->underscan_vborder_property) { + if (nv_connector->underscan_vborder != value) { + nv_connector->underscan_vborder = value; + if (!nv_crtc || !nv_crtc->set_scale) + return 0; + + return nv_crtc->set_scale(nv_crtc, + nv_connector->scaling_mode, + true); + } + + return 0; + } + /* Dithering */ if (property == dev->mode_config.dithering_mode_property) { - struct nouveau_crtc *nv_crtc = NULL; - if (value == DRM_MODE_DITHERING_ON) nv_connector->use_dithering = true; else nv_connector->use_dithering = false; - if (connector->encoder && connector->encoder->crtc) - nv_crtc = nouveau_crtc(connector->encoder->crtc); - if (!nv_crtc || !nv_crtc->set_dither) return 0; @@ -773,6 +815,7 @@ nouveau_connector_create(struct drm_device *dev, int index) { const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_display_engine *disp = &dev_priv->engine.display; struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct nouveau_connector *nv_connector = NULL; struct dcb_connector_table_entry *dcb = NULL; @@ -857,6 +900,25 @@ nouveau_connector_create(struct drm_device *dev, int index) drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); } + /* Add overscan compensation options to digital outputs */ + if ((dev_priv->card_type == NV_50 || + dev_priv->card_type == NV_C0) && + (dcb->type == DCB_CONNECTOR_DVI_D || + dcb->type == DCB_CONNECTOR_DVI_I || + dcb->type == DCB_CONNECTOR_HDMI_0 || + dcb->type == DCB_CONNECTOR_HDMI_1 || + dcb->type == DCB_CONNECTOR_DP)) { + drm_connector_attach_property(connector, + disp->underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(connector, + disp->underscan_hborder_property, + 0); + drm_connector_attach_property(connector, + disp->underscan_vborder_property, + 0); + } + switch (dcb->type) { case DCB_CONNECTOR_VGA: if (dev_priv->card_type >= NV_50) { |