|
@@ -969,18 +969,33 @@ nouveau_connector_get_modes(struct drm_connector *connector)
|
|
|
}
|
|
|
|
|
|
static unsigned
|
|
|
-get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
|
|
|
+get_tmds_link_bandwidth(struct drm_connector *connector)
|
|
|
{
|
|
|
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
|
|
+ struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
|
|
|
struct nouveau_drm *drm = nouveau_drm(connector->dev);
|
|
|
struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
|
|
|
+ struct drm_display_info *info = NULL;
|
|
|
+ const unsigned duallink_scale =
|
|
|
+ nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1;
|
|
|
+
|
|
|
+ if (drm_detect_hdmi_monitor(nv_connector->edid))
|
|
|
+ info = &nv_connector->base.display_info;
|
|
|
|
|
|
- if (hdmi) {
|
|
|
+ if (info) {
|
|
|
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->client.device.info.chipset >= 0x120) {
|
|
|
+ const int max_tmds_clock =
|
|
|
+ info->hdmi.scdc.scrambling.supported ?
|
|
|
+ 594000 : 340000;
|
|
|
+ return info->max_tmds_clock ?
|
|
|
+ min(info->max_tmds_clock, max_tmds_clock) :
|
|
|
+ max_tmds_clock;
|
|
|
+ }
|
|
|
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
|
|
|
return 297000;
|
|
|
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI)
|
|
@@ -988,13 +1003,13 @@ get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
|
|
|
}
|
|
|
if (dcb->location != DCB_LOC_ON_CHIP ||
|
|
|
drm->client.device.info.chipset >= 0x46)
|
|
|
- return 165000;
|
|
|
+ return 165000 * duallink_scale;
|
|
|
else if (drm->client.device.info.chipset >= 0x40)
|
|
|
- return 155000;
|
|
|
+ return 155000 * duallink_scale;
|
|
|
else if (drm->client.device.info.chipset >= 0x18)
|
|
|
- return 135000;
|
|
|
+ return 135000 * duallink_scale;
|
|
|
else
|
|
|
- return 112000;
|
|
|
+ return 112000 * duallink_scale;
|
|
|
}
|
|
|
|
|
|
static enum drm_mode_status
|
|
@@ -1006,7 +1021,6 @@ 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:
|
|
@@ -1019,11 +1033,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
|
|
|
max_clock = 400000;
|
|
|
break;
|
|
|
case DCB_OUTPUT_TMDS:
|
|
|
- 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;
|
|
|
+ max_clock = get_tmds_link_bandwidth(connector);
|
|
|
break;
|
|
|
case DCB_OUTPUT_ANALOG:
|
|
|
max_clock = nv_encoder->dcb->crtconf.maxfreq;
|