Commit 9340d77f authored by Ilia Mirkin's avatar Ilia Mirkin Committed by Ben Skeggs

drm/nouveau/disp: take sink support into account for exposing 594mhz

Scrambling is required for supporting any mode over 340MHz. If it's not
supported, reject any modes that would require it.
Signed-off-by: default avatarIlia Mirkin <imirkin@alum.mit.edu>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7a406f8a
...@@ -969,18 +969,33 @@ nouveau_connector_get_modes(struct drm_connector *connector) ...@@ -969,18 +969,33 @@ nouveau_connector_get_modes(struct drm_connector *connector)
} }
static unsigned 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_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct dcb_output *dcb = nv_connector->detected_encoder->dcb; 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) if (nouveau_hdmimhz > 0)
return nouveau_hdmimhz * 1000; return nouveau_hdmimhz * 1000;
/* Note: these limits are conservative, some Fermi's /* Note: these limits are conservative, some Fermi's
* can do 297 MHz. Unclear how this can be determined. * 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) if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
return 297000; return 297000;
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI) 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) ...@@ -988,13 +1003,13 @@ get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
} }
if (dcb->location != DCB_LOC_ON_CHIP || if (dcb->location != DCB_LOC_ON_CHIP ||
drm->client.device.info.chipset >= 0x46) drm->client.device.info.chipset >= 0x46)
return 165000; return 165000 * duallink_scale;
else if (drm->client.device.info.chipset >= 0x40) else if (drm->client.device.info.chipset >= 0x40)
return 155000; return 155000 * duallink_scale;
else if (drm->client.device.info.chipset >= 0x18) else if (drm->client.device.info.chipset >= 0x18)
return 135000; return 135000 * duallink_scale;
else else
return 112000; return 112000 * duallink_scale;
} }
static enum drm_mode_status static enum drm_mode_status
...@@ -1006,7 +1021,6 @@ nouveau_connector_mode_valid(struct drm_connector *connector, ...@@ -1006,7 +1021,6 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
struct drm_encoder *encoder = to_drm_encoder(nv_encoder); struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
unsigned min_clock = 25000, max_clock = min_clock; unsigned min_clock = 25000, max_clock = min_clock;
unsigned clock = mode->clock; unsigned clock = mode->clock;
bool hdmi;
switch (nv_encoder->dcb->type) { switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_LVDS: case DCB_OUTPUT_LVDS:
...@@ -1019,11 +1033,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, ...@@ -1019,11 +1033,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
max_clock = 400000; max_clock = 400000;
break; break;
case DCB_OUTPUT_TMDS: case DCB_OUTPUT_TMDS:
hdmi = drm_detect_hdmi_monitor(nv_connector->edid); max_clock = get_tmds_link_bandwidth(connector);
max_clock = get_tmds_link_bandwidth(connector, hdmi);
if (!hdmi && nouveau_duallink &&
nv_encoder->dcb->duallink_possible)
max_clock *= 2;
break; break;
case DCB_OUTPUT_ANALOG: case DCB_OUTPUT_ANALOG:
max_clock = nv_encoder->dcb->crtconf.maxfreq; max_clock = nv_encoder->dcb->crtconf.maxfreq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment