diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-02 10:00:35 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-11-17 23:38:12 -0500 |
commit | 1f5bd44354c878cf8bb0e28a7cb27677e3640c45 (patch) | |
tree | b9b77bbb092f74c78ac8881ad5a54a3f6c9de06b /drivers/gpu/drm/nouveau | |
parent | 907af60b93045ae33b450553167aa8f684252de3 (diff) |
drm/nouveau: Reject modes exceeding the integrated TMDS maximum bandwidth.
Reported-by: Grzesiek Sójka <pld@pfu.pl>
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 0871495096fa..6208eedc0970 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -641,11 +641,28 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
641 | return ret; | 641 | return ret; |
642 | } | 642 | } |
643 | 643 | ||
644 | static unsigned | ||
645 | get_tmds_link_bandwidth(struct drm_connector *connector) | ||
646 | { | ||
647 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
648 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | ||
649 | struct dcb_entry *dcb = nv_connector->detected_encoder->dcb; | ||
650 | |||
651 | if (dcb->location != DCB_LOC_ON_CHIP || | ||
652 | dev_priv->chipset >= 0x46) | ||
653 | return 165000; | ||
654 | else if (dev_priv->chipset >= 0x40) | ||
655 | return 155000; | ||
656 | else if (dev_priv->chipset >= 0x18) | ||
657 | return 135000; | ||
658 | else | ||
659 | return 112000; | ||
660 | } | ||
661 | |||
644 | static int | 662 | static int |
645 | nouveau_connector_mode_valid(struct drm_connector *connector, | 663 | nouveau_connector_mode_valid(struct drm_connector *connector, |
646 | struct drm_display_mode *mode) | 664 | struct drm_display_mode *mode) |
647 | { | 665 | { |
648 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | ||
649 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 666 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
650 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 667 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
651 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | 668 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); |
@@ -663,11 +680,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
663 | max_clock = 400000; | 680 | max_clock = 400000; |
664 | break; | 681 | break; |
665 | case OUTPUT_TMDS: | 682 | case OUTPUT_TMDS: |
666 | if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) || | 683 | max_clock = get_tmds_link_bandwidth(connector); |
667 | !nv_encoder->dcb->duallink_possible) | 684 | if (nouveau_duallink && nv_encoder->dcb->duallink_possible) |
668 | max_clock = 165000; | 685 | max_clock *= 2; |
669 | else | ||
670 | max_clock = 330000; | ||
671 | break; | 686 | break; |
672 | case OUTPUT_ANALOG: | 687 | case OUTPUT_ANALOG: |
673 | max_clock = nv_encoder->dcb->crtconf.maxfreq; | 688 | max_clock = nv_encoder->dcb->crtconf.maxfreq; |