summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c29
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c24
3 files changed, 44 insertions, 10 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index c8ac9482cf2e..d13f50db765d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -458,6 +458,28 @@ nouveau_connector_set_property(struct drm_connector *connector,
switch (value) {
case DRM_MODE_SCALE_NONE:
+ /* We allow 'None' for EDID modes, even on a fixed
+ * panel (some exist with support for lower refresh
+ * rates, which people might want to use for power
+ * saving purposes).
+ *
+ * Non-EDID modes will force the use of GPU scaling
+ * to the native mode regardless of this setting.
+ */
+ switch (nv_connector->type) {
+ case DCB_CONNECTOR_LVDS:
+ case DCB_CONNECTOR_LVDS_SPWG:
+ case DCB_CONNECTOR_eDP:
+ /* ... except prior to G80, where the code
+ * doesn't support such things.
+ */
+ if (disp->disp.oclass < NV50_DISP)
+ return -EINVAL;
+ break;
+ default:
+ break;
+ }
+ break;
case DRM_MODE_SCALE_FULLSCREEN:
case DRM_MODE_SCALE_CENTER:
case DRM_MODE_SCALE_ASPECT:
@@ -466,11 +488,6 @@ nouveau_connector_set_property(struct drm_connector *connector,
return -EINVAL;
}
- /* LVDS always needs gpu scaling */
- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
- value == DRM_MODE_SCALE_NONE)
- return -EINVAL;
-
/* Changing between GPU and panel scaling requires a full
* modeset
*/
@@ -662,8 +679,6 @@ nouveau_connector_scaler_modes_add(struct drm_connector *connector)
if (!m)
continue;
- m->type |= DRM_MODE_TYPE_DRIVER;
-
drm_mode_probed_add(connector, m);
modes++;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 629a380c7085..a2d099142d96 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -72,6 +72,7 @@ struct nouveau_connector {
int dithering_mode;
int dithering_depth;
int scaling_mode;
+ bool scaling_full;
enum nouveau_underscan_type underscan;
u32 underscan_hborder;
u32 underscan_vborder;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 4f544f3683db..85cc667cfb0f 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -729,8 +729,11 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
* effectively handles NONE/FULL scaling
*/
nv_connector = nouveau_crtc_connector_get(nv_crtc);
- if (nv_connector && nv_connector->native_mode)
+ if (nv_connector && nv_connector->native_mode) {
mode = nv_connector->scaling_mode;
+ if (nv_connector->scaling_full) /* non-EDID LVDS/eDP mode */
+ mode = DRM_MODE_SCALE_FULLSCREEN;
+ }
if (mode != DRM_MODE_SCALE_NONE)
omode = nv_connector->native_mode;
@@ -1478,8 +1481,23 @@ nv50_encoder_mode_fixup(struct drm_encoder *encoder,
nv_connector = nouveau_encoder_connector_get(nv_encoder);
if (nv_connector && nv_connector->native_mode) {
- if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE)
- drm_mode_copy(adjusted_mode, nv_connector->native_mode);
+ nv_connector->scaling_full = false;
+ if (nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) {
+ switch (nv_connector->type) {
+ case DCB_CONNECTOR_LVDS:
+ case DCB_CONNECTOR_LVDS_SPWG:
+ case DCB_CONNECTOR_eDP:
+ /* force use of scaler for non-edid modes */
+ if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
+ return true;
+ nv_connector->scaling_full = true;
+ break;
+ default:
+ return true;
+ }
+ }
+
+ drm_mode_copy(adjusted_mode, nv_connector->native_mode);
}
return true;