drm/nouveau/nvif: split out display interface definitions
[deliverable/linux.git] / drivers / gpu / drm / nouveau / nouveau_connector.c
index 2e7cbe933533c97b9a211827d5005d2adc282496..40612e7cea4d1c924036127766ed73c7a57a3227 100644 (file)
@@ -42,6 +42,7 @@
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
 
+#include <nvif/cl0046.h>
 #include <nvif/event.h>
 
 MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
@@ -56,6 +57,10 @@ MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)");
 int nouveau_duallink = 1;
 module_param_named(duallink, nouveau_duallink, int, 0400);
 
+MODULE_PARM_DESC(hdmimhz, "Force a maximum HDMI pixel clock (in MHz)");
+int nouveau_hdmimhz = 0;
+module_param_named(hdmimhz, nouveau_hdmimhz, int, 0400);
+
 struct nouveau_encoder *
 find_encoder(struct drm_connector *connector, int type)
 {
@@ -809,12 +814,23 @@ nouveau_connector_get_modes(struct drm_connector *connector)
 }
 
 static unsigned
-get_tmds_link_bandwidth(struct drm_connector *connector)
+get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
 {
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_drm *drm = nouveau_drm(connector->dev);
        struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
 
+       if (hdmi) {
+               if (nouveau_hdmimhz > 0)
+                       return nouveau_hdmimhz * 1000;
+               /* Note: these limits are conservative, some Fermi's
+                * can do 297 MHz. Unclear how this can be determined.
+                */
+               if (drm->device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
+                       return 297000;
+               if (drm->device.info.family >= NV_DEVICE_INFO_V0_FERMI)
+                       return 225000;
+       }
        if (dcb->location != DCB_LOC_ON_CHIP ||
            drm->device.info.chipset >= 0x46)
                return 165000;
@@ -835,6 +851,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
        struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
        unsigned min_clock = 25000, max_clock = min_clock;
        unsigned clock = mode->clock;
+       bool hdmi;
 
        switch (nv_encoder->dcb->type) {
        case DCB_OUTPUT_LVDS:
@@ -847,8 +864,10 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
                max_clock = 400000;
                break;
        case DCB_OUTPUT_TMDS:
-               max_clock = get_tmds_link_bandwidth(connector);
-               if (nouveau_duallink && nv_encoder->dcb->duallink_possible)
+               hdmi = drm_detect_hdmi_monitor(nv_connector->edid);
+               max_clock = get_tmds_link_bandwidth(connector, hdmi);
+               if (!hdmi && nouveau_duallink &&
+                   nv_encoder->dcb->duallink_possible)
                        max_clock *= 2;
                break;
        case DCB_OUTPUT_ANALOG:
@@ -898,8 +917,6 @@ nouveau_connector_helper_funcs = {
 static const struct drm_connector_funcs
 nouveau_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
-       .save = NULL,
-       .restore = NULL,
        .detect = nouveau_connector_detect,
        .destroy = nouveau_connector_destroy,
        .fill_modes = drm_helper_probe_single_connector_modes,
@@ -910,8 +927,6 @@ nouveau_connector_funcs = {
 static const struct drm_connector_funcs
 nouveau_connector_funcs_lvds = {
        .dpms = drm_helper_connector_dpms,
-       .save = NULL,
-       .restore = NULL,
        .detect = nouveau_connector_detect_lvds,
        .destroy = nouveau_connector_destroy,
        .fill_modes = drm_helper_probe_single_connector_modes,
@@ -944,8 +959,6 @@ nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
 static const struct drm_connector_funcs
 nouveau_connector_funcs_dp = {
        .dpms = nouveau_connector_dp_dpms,
-       .save = NULL,
-       .restore = NULL,
        .detect = nouveau_connector_detect,
        .destroy = nouveau_connector_destroy,
        .fill_modes = drm_helper_probe_single_connector_modes,
This page took 0.043382 seconds and 5 git commands to generate.