summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_connector.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-10-06 13:29:05 +1000
committerBen Skeggs <bskeggs@redhat.com>2011-12-21 19:01:16 +1000
commitb29caa5885e85bbda7c84ea55721b9e79718583a (patch)
treecd624c2e776ea2d558e315ba1cb5b63c0868ef3c /drivers/gpu/drm/nouveau/nouveau_connector.c
parent27d5030a235d89842ed70e18d924f017b34a496d (diff)
downloadtalos-obmc-linux-b29caa5885e85bbda7c84ea55721b9e79718583a.tar.gz
talos-obmc-linux-b29caa5885e85bbda7c84ea55721b9e79718583a.zip
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.c78
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 cea6696b1906..5e830a585538 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) {
OpenPOWER on IntegriCloud