aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-12-22 02:19:26 -0500
committerBen Skeggs <bskeggs@redhat.com>2015-01-21 21:14:58 -0500
commit576f79116ee8ed6f41f0f9f1fc295eaad5d5aeee (patch)
treeb0f3d34c3d389f9ae5b0a99b98c3f3d7ddb5007e
parenta91d322120a65ec5ada5518d948fda84aa87796f (diff)
drm/nv50-/kms: allow disabling of gpu scaling on fixed panels
The hilarious part is that, under X, this won't work anyway because the server decides to construct its own modes for some reason. Tested with modetest, which isn't quite as insane. I'd hope that wayland is more sensible. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-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,
458 458
459 switch (value) { 459 switch (value) {
460 case DRM_MODE_SCALE_NONE: 460 case DRM_MODE_SCALE_NONE:
461 /* We allow 'None' for EDID modes, even on a fixed
462 * panel (some exist with support for lower refresh
463 * rates, which people might want to use for power
464 * saving purposes).
465 *
466 * Non-EDID modes will force the use of GPU scaling
467 * to the native mode regardless of this setting.
468 */
469 switch (nv_connector->type) {
470 case DCB_CONNECTOR_LVDS:
471 case DCB_CONNECTOR_LVDS_SPWG:
472 case DCB_CONNECTOR_eDP:
473 /* ... except prior to G80, where the code
474 * doesn't support such things.
475 */
476 if (disp->disp.oclass < NV50_DISP)
477 return -EINVAL;
478 break;
479 default:
480 break;
481 }
482 break;
461 case DRM_MODE_SCALE_FULLSCREEN: 483 case DRM_MODE_SCALE_FULLSCREEN:
462 case DRM_MODE_SCALE_CENTER: 484 case DRM_MODE_SCALE_CENTER:
463 case DRM_MODE_SCALE_ASPECT: 485 case DRM_MODE_SCALE_ASPECT:
@@ -466,11 +488,6 @@ nouveau_connector_set_property(struct drm_connector *connector,
466 return -EINVAL; 488 return -EINVAL;
467 } 489 }
468 490
469 /* LVDS always needs gpu scaling */
470 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
471 value == DRM_MODE_SCALE_NONE)
472 return -EINVAL;
473
474 /* Changing between GPU and panel scaling requires a full 491 /* Changing between GPU and panel scaling requires a full
475 * modeset 492 * modeset
476 */ 493 */
@@ -662,8 +679,6 @@ nouveau_connector_scaler_modes_add(struct drm_connector *connector)
662 if (!m) 679 if (!m)
663 continue; 680 continue;
664 681
665 m->type |= DRM_MODE_TYPE_DRIVER;
666
667 drm_mode_probed_add(connector, m); 682 drm_mode_probed_add(connector, m);
668 modes++; 683 modes++;
669 } 684 }
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 {
72 int dithering_mode; 72 int dithering_mode;
73 int dithering_depth; 73 int dithering_depth;
74 int scaling_mode; 74 int scaling_mode;
75 bool scaling_full;
75 enum nouveau_underscan_type underscan; 76 enum nouveau_underscan_type underscan;
76 u32 underscan_hborder; 77 u32 underscan_hborder;
77 u32 underscan_vborder; 78 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)
729 * effectively handles NONE/FULL scaling 729 * effectively handles NONE/FULL scaling
730 */ 730 */
731 nv_connector = nouveau_crtc_connector_get(nv_crtc); 731 nv_connector = nouveau_crtc_connector_get(nv_crtc);
732 if (nv_connector && nv_connector->native_mode) 732 if (nv_connector && nv_connector->native_mode) {
733 mode = nv_connector->scaling_mode; 733 mode = nv_connector->scaling_mode;
734 if (nv_connector->scaling_full) /* non-EDID LVDS/eDP mode */
735 mode = DRM_MODE_SCALE_FULLSCREEN;
736 }
734 737
735 if (mode != DRM_MODE_SCALE_NONE) 738 if (mode != DRM_MODE_SCALE_NONE)
736 omode = nv_connector->native_mode; 739 omode = nv_connector->native_mode;
@@ -1478,8 +1481,23 @@ nv50_encoder_mode_fixup(struct drm_encoder *encoder,
1478 1481
1479 nv_connector = nouveau_encoder_connector_get(nv_encoder); 1482 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1480 if (nv_connector && nv_connector->native_mode) { 1483 if (nv_connector && nv_connector->native_mode) {
1481 if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) 1484 nv_connector->scaling_full = false;
1482 drm_mode_copy(adjusted_mode, nv_connector->native_mode); 1485 if (nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) {
1486 switch (nv_connector->type) {
1487 case DCB_CONNECTOR_LVDS:
1488 case DCB_CONNECTOR_LVDS_SPWG:
1489 case DCB_CONNECTOR_eDP:
1490 /* force use of scaler for non-edid modes */
1491 if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
1492 return true;
1493 nv_connector->scaling_full = true;
1494 break;
1495 default:
1496 return true;
1497 }
1498 }
1499
1500 drm_mode_copy(adjusted_mode, nv_connector->native_mode);
1483 } 1501 }
1484 1502
1485 return true; 1503 return true;