diff options
-rw-r--r-- | linux-core/nv50_connector.c | 4 | ||||
-rw-r--r-- | linux-core/nv50_connector.h | 3 | ||||
-rw-r--r-- | linux-core/nv50_crtc.c | 8 | ||||
-rw-r--r-- | linux-core/nv50_crtc.h | 4 | ||||
-rw-r--r-- | linux-core/nv50_kms_wrapper.c | 21 |
5 files changed, 31 insertions, 9 deletions
diff --git a/linux-core/nv50_connector.c b/linux-core/nv50_connector.c index be133de3..309f450c 100644 --- a/linux-core/nv50_connector.c +++ b/linux-core/nv50_connector.c @@ -185,9 +185,9 @@ int nv50_connector_create(struct drm_device *dev, int bus, int i2c_index, int ty /* some reasonable defaults */ if (type == CONNECTOR_DVI_D || type == CONNECTOR_DVI_I || type == CONNECTOR_LVDS) - connector->scaling_mode = SCALE_FULLSCREEN; + connector->requested_scaling_mode = SCALE_FULLSCREEN; else - connector->scaling_mode = SCALE_NON_GPU; + connector->requested_scaling_mode = SCALE_NON_GPU; connector->use_dithering = false; diff --git a/linux-core/nv50_connector.h b/linux-core/nv50_connector.h index 02b1561e..aac94457 100644 --- a/linux-core/nv50_connector.h +++ b/linux-core/nv50_connector.h @@ -47,7 +47,8 @@ struct nv50_connector { struct nv50_i2c_channel *i2c_chan; struct nv50_output *output; - int scaling_mode; + int requested_scaling_mode; + bool use_dithering; bool (*detect) (struct nv50_connector *connector); diff --git a/linux-core/nv50_crtc.c b/linux-core/nv50_crtc.c index ffb976f4..c4ca7e76 100644 --- a/linux-core/nv50_crtc.c +++ b/linux-core/nv50_crtc.c @@ -255,7 +255,7 @@ static int nv50_crtc_set_scale(struct nv50_crtc *crtc) NV50_DEBUG("\n"); - switch (crtc->scaling_mode) { + switch (crtc->requested_scaling_mode) { case SCALE_ASPECT: nv50_crtc_calc_scale(crtc, &outX, &outY); break; @@ -283,6 +283,9 @@ static int nv50_crtc_set_scale(struct nv50_crtc *crtc) OUT_MODE(NV50_CRTC0_SCALE_RES1 + offset, outY << 16 | outX); OUT_MODE(NV50_CRTC0_SCALE_RES2 + offset, outY << 16 | outX); + /* processed */ + crtc->scaling_mode = crtc->requested_scaling_mode; + return 0; } @@ -492,6 +495,9 @@ int nv50_crtc_create(struct drm_device *dev, int index) crtc->mode = kzalloc(sizeof(struct nouveau_hw_mode), GFP_KERNEL); crtc->native_mode = kzalloc(sizeof(struct nouveau_hw_mode), GFP_KERNEL); + crtc->requested_scaling_mode = SCALE_INVALID; + crtc->scaling_mode = SCALE_INVALID; + if (!crtc->mode || !crtc->native_mode) { rval = -ENOMEM; goto out; diff --git a/linux-core/nv50_crtc.h b/linux-core/nv50_crtc.h index 8235c9d6..b4b83584 100644 --- a/linux-core/nv50_crtc.h +++ b/linux-core/nv50_crtc.h @@ -46,6 +46,10 @@ struct nv50_crtc { bool use_native_mode; bool use_dithering; + + /* Changing scaling modes requires a modeset sometimes. */ + /* We need to know the currently active hw mode, as well as the requested one by the user. */ + int requested_scaling_mode; int scaling_mode; struct nv50_cursor *cursor; diff --git a/linux-core/nv50_kms_wrapper.c b/linux-core/nv50_kms_wrapper.c index 6e0805fc..67836f3f 100644 --- a/linux-core/nv50_kms_wrapper.c +++ b/linux-core/nv50_kms_wrapper.c @@ -635,12 +635,12 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) if (connector->output != output) continue; - crtc->scaling_mode = connector->scaling_mode; + crtc->requested_scaling_mode = connector->requested_scaling_mode; crtc->use_dithering = connector->use_dithering; break; } - if (crtc->scaling_mode == SCALE_NON_GPU) + if (crtc->requested_scaling_mode == SCALE_NON_GPU) crtc->use_native_mode = false; else crtc->use_native_mode = true; @@ -1086,6 +1086,7 @@ static int nv50_kms_connector_set_property(struct drm_connector *drm_connector, struct drm_device *dev = drm_connector->dev; struct nv50_connector *connector = to_nv50_connector(drm_connector); int rval = 0; + bool delay_change = false; /* DPMS */ if (property == dev->mode_config.dpms_property && drm_connector->encoder) { @@ -1123,7 +1124,7 @@ static int nv50_kms_connector_set_property(struct drm_connector *drm_connector, if (connector->type == CONNECTOR_LVDS && internal_value == SCALE_NON_GPU) return -EINVAL; - connector->scaling_mode = internal_value; + connector->requested_scaling_mode = internal_value; if (drm_connector->encoder && drm_connector->encoder->crtc) crtc = to_nv50_crtc(drm_connector->encoder->crtc); @@ -1131,7 +1132,17 @@ static int nv50_kms_connector_set_property(struct drm_connector *drm_connector, if (!crtc) return 0; - crtc->scaling_mode = connector->scaling_mode; + crtc->requested_scaling_mode = connector->requested_scaling_mode; + + /* going from and to a gpu scaled regime requires a modesetting, so wait until next modeset */ + if (crtc->scaling_mode == SCALE_NON_GPU || internal_value == SCALE_NON_GPU) { + DRM_INFO("Moving from or to a non-gpu scaled mode, this will be processed upon next modeset."); + delay_change = true; + } + + if (delay_change) + return 0; + rval = crtc->set_scale(crtc); if (rval) return rval; @@ -1194,7 +1205,7 @@ static int nv50_kms_get_scaling_mode(struct drm_connector *drm_connector) connector = to_nv50_connector(drm_connector); - switch (connector->scaling_mode) { + switch (connector->requested_scaling_mode) { case SCALE_NON_GPU: drm_mode = DRM_MODE_SCALE_NON_GPU; break; |