drm/nouveau/kms/nv50: convert encoder mode_fixup into an atomic_check()
authorBen Skeggs <bskeggs@redhat.com>
Fri, 4 Nov 2016 07:20:36 +0000 (17:20 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 7 Nov 2016 04:04:58 +0000 (14:04 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nv50_display.c

index 617c57daad21d2069ab173f05591c08885f20183..03a3e3fc84ab144d7e25bbfea1e8318c3730bdcb 100644 (file)
@@ -2773,8 +2773,50 @@ out:
 }
 
 /******************************************************************************
- * Encoder helpers
+ * Output path helpers
  *****************************************************************************/
+static int
+nv50_outp_atomic_check_view(struct drm_encoder *encoder,
+                           struct drm_crtc_state *crtc_state,
+                           struct drm_connector_state *conn_state,
+                           struct drm_display_mode *native_mode)
+{
+       struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+       struct drm_display_mode *mode = &crtc_state->mode;
+       struct drm_connector *connector = conn_state->connector;
+       struct nouveau_conn_atom *asyc = nouveau_conn_atom(conn_state);
+       struct nouveau_drm *drm = nouveau_drm(encoder->dev);
+
+       NV_ATOMIC(drm, "%s atomic_check\n", encoder->name);
+       asyc->scaler.full = false;
+       if (!native_mode)
+               return 0;
+
+       if (asyc->scaler.mode == DRM_MODE_SCALE_NONE) {
+               switch (connector->connector_type) {
+               case DRM_MODE_CONNECTOR_LVDS:
+               case DRM_MODE_CONNECTOR_eDP:
+                       /* Force use of scaler for non-EDID modes. */
+                       if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
+                               break;
+                       mode = native_mode;
+                       asyc->scaler.full = true;
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               mode = native_mode;
+       }
+
+       if (!drm_mode_equal(adjusted_mode, mode)) {
+               drm_mode_copy(adjusted_mode, mode);
+               crtc_state->mode_changed = true;
+       }
+
+       return 0;
+}
+
 static bool
 nv50_encoder_mode_fixup(struct drm_encoder *encoder,
                        const struct drm_display_mode *mode,
@@ -2785,23 +2827,17 @@ nv50_encoder_mode_fixup(struct drm_encoder *encoder,
 
        nv_connector = nouveau_encoder_connector_get(nv_encoder);
        if (nv_connector && 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;
-                       }
-               }
+               struct nouveau_conn_atom *asyc
+                       = nouveau_conn_atom(nv_connector->base.state);
+               struct drm_crtc_state crtc_state = {
+                       .mode = *mode,
+                       .adjusted_mode = *adjusted_mode,
+               };
 
-               drm_mode_copy(adjusted_mode, nv_connector->native_mode);
+               nv50_outp_atomic_check_view(encoder, &crtc_state, &asyc->state,
+                                           nv_connector->native_mode);
+               nv_connector->scaling_full = asyc->scaler.full;
+               drm_mode_copy(adjusted_mode, &crtc_state.adjusted_mode);
        }
 
        return true;