aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@vmware.com>2010-05-28 05:21:59 -0400
committerDave Airlie <airlied@redhat.com>2010-05-31 19:37:25 -0400
commitd7e1958dbe4a7b81d4cab5fab545a068501b967e (patch)
tree92bf46006c21c4f1770bc8803ae6807461fa2e07 /drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
parent1ae1ddd5e99bbc067414ff571ac18d4312b4c8cf (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.c70
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 fefef9012c4b..8fde9bf8be41 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 {
38 struct list_head active; 38 struct list_head active;
39 39
40 unsigned num_active; 40 unsigned num_active;
41 unsigned last_num_active;
41 42
42 struct vmw_framebuffer *fb; 43 struct vmw_framebuffer *fb;
43}; 44};
@@ -88,12 +89,37 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
88{ 89{
89 struct vmw_legacy_display *lds = dev_priv->ldu_priv; 90 struct vmw_legacy_display *lds = dev_priv->ldu_priv;
90 struct vmw_legacy_display_unit *entry; 91 struct vmw_legacy_display_unit *entry;
91 struct drm_crtc *crtc; 92 struct drm_framebuffer *fb = NULL;
93 struct drm_crtc *crtc = NULL;
92 int i = 0; 94 int i = 0;
93 95
94 /* to stop the screen from changing size on resize */ 96 /* If there is no display topology the host just assumes
95 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0); 97 * that the guest will set the same layout as the host.
96 for (i = 0; i < lds->num_active; i++) { 98 */
99 if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
100 int w = 0, h = 0;
101 list_for_each_entry(entry, &lds->active, active) {
102 crtc = &entry->base.crtc;
103 w = max(w, crtc->x + crtc->mode.hdisplay);
104 h = max(h, crtc->y + crtc->mode.vdisplay);
105 i++;
106 }
107
108 if (crtc == NULL)
109 return 0;
110 fb = entry->base.crtc.fb;
111
112 vmw_write(dev_priv, SVGA_REG_ENABLE, 0);
113 vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
114 fb->bits_per_pixel, fb->depth);
115 vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
116
117 return 0;
118 }
119
120 vmw_write(dev_priv, SVGA_REG_ENABLE, 0);
121
122 for (i = 0; i < lds->last_num_active; i++) {
97 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i); 123 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
98 vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i); 124 vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
99 vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0); 125 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)
103 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); 129 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
104 } 130 }
105 131
106 /* Now set the mode */ 132 if (!list_empty(&lds->active)) {
107 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active); 133 entry = list_entry(lds->active.next, typeof(*entry), active);
134 fb = entry->base.crtc.fb;
135
136 vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
137 fb->bits_per_pixel, fb->depth);
138 }
139
108 i = 0; 140 i = 0;
109 list_for_each_entry(entry, &lds->active, active) { 141 list_for_each_entry(entry, &lds->active, active) {
110 crtc = &entry->base.crtc; 142 crtc = &entry->base.crtc;
@@ -120,6 +152,14 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
120 i++; 152 i++;
121 } 153 }
122 154
155 /* Make sure we always show something. */
156 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, i ? i : 1);
157 vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
158
159 BUG_ON(i != lds->num_active);
160
161 lds->last_num_active = lds->num_active;
162
123 return 0; 163 return 0;
124} 164}
125 165
@@ -491,18 +531,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
491 531
492 INIT_LIST_HEAD(&dev_priv->ldu_priv->active); 532 INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
493 dev_priv->ldu_priv->num_active = 0; 533 dev_priv->ldu_priv->num_active = 0;
534 dev_priv->ldu_priv->last_num_active = 0;
494 dev_priv->ldu_priv->fb = NULL; 535 dev_priv->ldu_priv->fb = NULL;
495 536
496 drm_mode_create_dirty_info_property(dev_priv->dev); 537 drm_mode_create_dirty_info_property(dev_priv->dev);
497 538
498 vmw_ldu_init(dev_priv, 0); 539 vmw_ldu_init(dev_priv, 0);
499 vmw_ldu_init(dev_priv, 1); 540 /* for old hardware without multimon only enable one display */
500 vmw_ldu_init(dev_priv, 2); 541 if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
501 vmw_ldu_init(dev_priv, 3); 542 vmw_ldu_init(dev_priv, 1);
502 vmw_ldu_init(dev_priv, 4); 543 vmw_ldu_init(dev_priv, 2);
503 vmw_ldu_init(dev_priv, 5); 544 vmw_ldu_init(dev_priv, 3);
504 vmw_ldu_init(dev_priv, 6); 545 vmw_ldu_init(dev_priv, 4);
505 vmw_ldu_init(dev_priv, 7); 546 vmw_ldu_init(dev_priv, 5);
547 vmw_ldu_init(dev_priv, 6);
548 vmw_ldu_init(dev_priv, 7);
549 }
506 550
507 return 0; 551 return 0;
508} 552}