diff options
author | Jakob Bornecrantz <jakob@vmware.com> | 2010-05-28 11:21:59 +0200 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-06-01 09:37:25 +1000 |
commit | d7e1958dbe4a7b81d4cab5fab545a068501b967e (patch) | |
tree | 92bf46006c21c4f1770bc8803ae6807461fa2e07 /drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |
parent | 1ae1ddd5e99bbc067414ff571ac18d4312b4c8cf (diff) |
drm/vmwgfx: Support older hardware.
V2: Fix a couple of typos.
Signed-off-by: Jakob Bornecrantz <jakob@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 70 |
1 files changed, 57 insertions, 13 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index fefef9012c4..8fde9bf8be4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -38,6 +38,7 @@ struct vmw_legacy_display { struct list_head active; unsigned num_active; + unsigned last_num_active; struct vmw_framebuffer *fb; }; @@ -88,12 +89,37 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) { struct vmw_legacy_display *lds = dev_priv->ldu_priv; struct vmw_legacy_display_unit *entry; - struct drm_crtc *crtc; + struct drm_framebuffer *fb = NULL; + struct drm_crtc *crtc = NULL; int i = 0; - /* to stop the screen from changing size on resize */ - vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0); - for (i = 0; i < lds->num_active; i++) { + /* If there is no display topology the host just assumes + * that the guest will set the same layout as the host. + */ + if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) { + int w = 0, h = 0; + list_for_each_entry(entry, &lds->active, active) { + crtc = &entry->base.crtc; + w = max(w, crtc->x + crtc->mode.hdisplay); + h = max(h, crtc->y + crtc->mode.vdisplay); + i++; + } + + if (crtc == NULL) + return 0; + fb = entry->base.crtc.fb; + + vmw_write(dev_priv, SVGA_REG_ENABLE, 0); + vmw_kms_write_svga(dev_priv, w, h, fb->pitch, + fb->bits_per_pixel, fb->depth); + vmw_write(dev_priv, SVGA_REG_ENABLE, 1); + + return 0; + } + + vmw_write(dev_priv, SVGA_REG_ENABLE, 0); + + for (i = 0; i < lds->last_num_active; i++) { vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i); vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i); vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0); @@ -103,8 +129,14 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); } - /* Now set the mode */ - vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active); + if (!list_empty(&lds->active)) { + entry = list_entry(lds->active.next, typeof(*entry), active); + fb = entry->base.crtc.fb; + + vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch, + fb->bits_per_pixel, fb->depth); + } + i = 0; list_for_each_entry(entry, &lds->active, active) { crtc = &entry->base.crtc; @@ -120,6 +152,14 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) i++; } + /* Make sure we always show something. */ + vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, i ? i : 1); + vmw_write(dev_priv, SVGA_REG_ENABLE, 1); + + BUG_ON(i != lds->num_active); + + lds->last_num_active = lds->num_active; + return 0; } @@ -491,18 +531,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) INIT_LIST_HEAD(&dev_priv->ldu_priv->active); dev_priv->ldu_priv->num_active = 0; + dev_priv->ldu_priv->last_num_active = 0; dev_priv->ldu_priv->fb = NULL; drm_mode_create_dirty_info_property(dev_priv->dev); vmw_ldu_init(dev_priv, 0); - vmw_ldu_init(dev_priv, 1); - vmw_ldu_init(dev_priv, 2); - vmw_ldu_init(dev_priv, 3); - vmw_ldu_init(dev_priv, 4); - vmw_ldu_init(dev_priv, 5); - vmw_ldu_init(dev_priv, 6); - vmw_ldu_init(dev_priv, 7); + /* for old hardware without multimon only enable one display */ + if (dev_priv->capabilities & SVGA_CAP_MULTIMON) { + vmw_ldu_init(dev_priv, 1); + vmw_ldu_init(dev_priv, 2); + vmw_ldu_init(dev_priv, 3); + vmw_ldu_init(dev_priv, 4); + vmw_ldu_init(dev_priv, 5); + vmw_ldu_init(dev_priv, 6); + vmw_ldu_init(dev_priv, 7); + } return 0; } |