diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-05-28 00:13:16 (GMT) |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-05-28 06:06:51 (GMT) |
commit | 26099a74805eaf79f3058cc4097ebaa8cc55122c (patch) | |
tree | dd74da3803f2d0b6d16e22c2d0f67a3a42b26690 | |
parent | 2c58077541cc6859a9a9046d9c3a4d61bdbd4f18 (diff) | |
download | linux-26099a74805eaf79f3058cc4097ebaa8cc55122c.tar.xz |
drm/nouveau: fix dual-link displays when plugged into single-link outputs
When selecting the native mode for a display we weren't taking into account
whether or not it was actually supported on that particular output.
This patch modifies our native mode selection to run all modes through
mode_valid() first.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index bfa6562..256e82b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -431,24 +431,27 @@ nouveau_connector_set_property(struct drm_connector *connector, } static struct drm_display_mode * -nouveau_connector_native_mode(struct nouveau_connector *connector) +nouveau_connector_native_mode(struct drm_connector *connector) { - struct drm_device *dev = connector->base.dev; + struct drm_connector_helper_funcs *helper = connector->helper_private; + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct drm_device *dev = connector->dev; struct drm_display_mode *mode, *largest = NULL; int high_w = 0, high_h = 0, high_v = 0; - /* Use preferred mode if there is one.. */ - list_for_each_entry(mode, &connector->base.probed_modes, head) { + list_for_each_entry(mode, &nv_connector->base.probed_modes, head) { + if (helper->mode_valid(connector, mode) != MODE_OK) + continue; + + /* Use preferred mode if there is one.. */ if (mode->type & DRM_MODE_TYPE_PREFERRED) { NV_DEBUG_KMS(dev, "native mode from preferred\n"); return drm_mode_duplicate(dev, mode); } - } - /* Otherwise, take the resolution with the largest width, then height, - * then vertical refresh - */ - list_for_each_entry(mode, &connector->base.probed_modes, head) { + /* Otherwise, take the resolution with the largest width, then + * height, then vertical refresh + */ if (mode->hdisplay < high_w) continue; @@ -552,7 +555,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) */ if (!nv_connector->native_mode) nv_connector->native_mode = - nouveau_connector_native_mode(nv_connector); + nouveau_connector_native_mode(connector); if (ret == 0 && nv_connector->native_mode) { struct drm_display_mode *mode; @@ -583,9 +586,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector, switch (nv_encoder->dcb->type) { case OUTPUT_LVDS: - BUG_ON(!nv_connector->native_mode); - if (mode->hdisplay > nv_connector->native_mode->hdisplay || - mode->vdisplay > nv_connector->native_mode->vdisplay) + if (nv_connector->native_mode && + (mode->hdisplay > nv_connector->native_mode->hdisplay || + mode->vdisplay > nv_connector->native_mode->vdisplay)) return MODE_PANEL; min_clock = 0; @@ -727,7 +730,7 @@ nouveau_connector_create_lvds(struct drm_device *dev, if (ret == 0) goto out; nv_connector->detected_encoder = nv_encoder; - nv_connector->native_mode = nouveau_connector_native_mode(nv_connector); + nv_connector->native_mode = nouveau_connector_native_mode(connector); list_for_each_entry_safe(mode, temp, &connector->probed_modes, head) drm_mode_remove(connector, mode); |