nv50_mstc_mode_valid(struct drm_connector *connector,
                     struct drm_display_mode *mode)
 {
-       return MODE_OK;
+       struct nv50_mstc *mstc = nv50_mstc(connector);
+       struct nouveau_encoder *outp = mstc->mstm->outp;
+
+       /* TODO: calculate the PBN from the dotclock and validate against the
+        * MSTB's max possible PBN
+        */
+
+       return nv50_dp_mode_valid(connector, outp, mode, NULL);
 }
 
 static int
 
 #include "nouveau_reg.h"
 #include "nouveau_drv.h"
 #include "dispnv04/hw.h"
+#include "dispnv50/disp.h"
 #include "nouveau_acpi.h"
 
 #include "nouveau_display.h"
                return 112000 * duallink_scale;
 }
 
+enum drm_mode_status
+nouveau_conn_mode_clock_valid(const struct drm_display_mode *mode,
+                             const unsigned min_clock,
+                             const unsigned max_clock,
+                             unsigned int *clock_out)
+{
+       unsigned int clock = mode->clock;
+
+       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) ==
+           DRM_MODE_FLAG_3D_FRAME_PACKING)
+               clock *= 2;
+
+       if (clock < min_clock)
+               return MODE_CLOCK_LOW;
+       if (clock > max_clock)
+               return MODE_CLOCK_HIGH;
+
+       if (clock_out)
+               *clock_out = clock;
+
+       return MODE_OK;
+}
+
 static enum drm_mode_status
 nouveau_connector_mode_valid(struct drm_connector *connector,
                             struct drm_display_mode *mode)
        struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
        struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
        unsigned min_clock = 25000, max_clock = min_clock;
-       unsigned clock = mode->clock;
 
        switch (nv_encoder->dcb->type) {
        case DCB_OUTPUT_LVDS:
        case DCB_OUTPUT_TV:
                return get_slave_funcs(encoder)->mode_valid(encoder, mode);
        case DCB_OUTPUT_DP:
-               if (mode->flags & DRM_MODE_FLAG_INTERLACE &&
-                   !nv_encoder->caps.dp_interlace)
-                       return MODE_NO_INTERLACE;
-
-               max_clock  = nv_encoder->dp.link_nr;
-               max_clock *= nv_encoder->dp.link_bw;
-               clock = clock * (connector->display_info.bpc * 3) / 10;
-               break;
+               return nv50_dp_mode_valid(connector, nv_encoder, mode, NULL);
        default:
                BUG();
                return MODE_BAD;
        }
 
-       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
-               clock *= 2;
-
-       if (clock < min_clock)
-               return MODE_CLOCK_LOW;
-
-       if (clock > max_clock)
-               return MODE_CLOCK_HIGH;
-
-       return MODE_OK;
+       return nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
+                                            NULL);
 }
 
 static struct drm_encoder *
 
                                     const struct drm_connector_state *,
                                     struct drm_property *, u64 *);
 struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
+enum drm_mode_status
+nouveau_conn_mode_clock_valid(const struct drm_display_mode *,
+                             const unsigned min_clock,
+                             const unsigned max_clock,
+                             unsigned *clock);
 
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
 extern int nouveau_backlight_init(struct drm_connector *);
 
                return NOUVEAU_DP_SST;
        return ret;
 }
+
+/* TODO:
+ * - Use the minimum possible BPC here, once we add support for the max bpc
+ *   property.
+ * - Validate the mode against downstream port caps (see
+ *   drm_dp_downstream_max_clock())
+ * - Validate against the DP caps advertised by the GPU (we don't check these
+ *   yet)
+ */
+enum drm_mode_status
+nv50_dp_mode_valid(struct drm_connector *connector,
+                  struct nouveau_encoder *outp,
+                  const struct drm_display_mode *mode,
+                  unsigned *out_clock)
+{
+       const unsigned min_clock = 25000;
+       unsigned max_clock, clock;
+       enum drm_mode_status ret;
+
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
+               return MODE_NO_INTERLACE;
+
+       max_clock = outp->dp.link_nr * outp->dp.link_bw;
+       clock = mode->clock * (connector->display_info.bpc * 3) / 10;
+
+       ret = nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
+                                           &clock);
+       if (out_clock)
+               *out_clock = clock;
+       return ret;
+}
 
 };
 
 int nouveau_dp_detect(struct nouveau_encoder *);
+enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *,
+                                       struct nouveau_encoder *,
+                                       const struct drm_display_mode *,
+                                       unsigned *clock);
 
 struct nouveau_connector *
 nouveau_encoder_connector_get(struct nouveau_encoder *encoder);