diff options
author | Jakob Bornecrantz <jakob@vmware.com> | 2010-05-28 05:21:59 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-05-31 19:37:25 -0400 |
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 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 | } |