aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx
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
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')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c81
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c18
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c72
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c70
6 files changed, 148 insertions, 107 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0c9c0811f42d..bdd87dc9e7b1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -318,6 +318,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
318 goto out_err3; 318 goto out_err3;
319 } 319 }
320 320
321 /* Need mmio memory to check for fifo pitchlock cap. */
322 if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
323 !(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
324 !vmw_fifo_have_pitchlock(dev_priv)) {
325 ret = -ENOSYS;
326 DRM_ERROR("Hardware has no pitchlock\n");
327 goto out_err4;
328 }
329
321 dev_priv->tdev = ttm_object_device_init 330 dev_priv->tdev = ttm_object_device_init
322 (dev_priv->mem_global_ref.object, 12); 331 (dev_priv->mem_global_ref.object, 12);
323 332
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 9a0a82b41c3e..1341adef408d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -187,6 +187,7 @@ struct vmw_private {
187 uint32_t vga_red_mask; 187 uint32_t vga_red_mask;
188 uint32_t vga_blue_mask; 188 uint32_t vga_blue_mask;
189 uint32_t vga_green_mask; 189 uint32_t vga_green_mask;
190 uint32_t vga_pitchlock;
190 191
191 /* 192 /*
192 * Framebuffer info. 193 * Framebuffer info.
@@ -401,6 +402,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
401extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason); 402extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
402extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma); 403extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
403extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv); 404extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
405extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
404 406
405/** 407/**
406 * TTM glue - vmwgfx_ttm_glue.c 408 * TTM glue - vmwgfx_ttm_glue.c
@@ -491,6 +493,9 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
491 struct ttm_object_file *tfile, 493 struct ttm_object_file *tfile,
492 struct ttm_buffer_object *bo, 494 struct ttm_buffer_object *bo,
493 SVGA3dCmdHeader *header); 495 SVGA3dCmdHeader *header);
496void vmw_kms_write_svga(struct vmw_private *vmw_priv,
497 unsigned width, unsigned height, unsigned pitch,
498 unsigned bbp, unsigned depth);
494 499
495/** 500/**
496 * Overlay control - vmwgfx_overlay.c 501 * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 7421aaad8d09..fb66e62b8e2c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -132,16 +132,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
132 return -EINVAL; 132 return -EINVAL;
133 } 133 }
134 134
135 /* without multimon its hard to resize */ 135 if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
136 if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) && 136 (var->xoffset != 0 || var->yoffset != 0)) {
137 (var->xres != par->max_width || 137 DRM_ERROR("Can not handle panning without display topology\n");
138 var->yres != par->max_height)) {
139 DRM_ERROR("Tried to resize, but we don't have multimon\n");
140 return -EINVAL; 138 return -EINVAL;
141 } 139 }
142 140
143 if (var->xres > par->max_width || 141 if ((var->xoffset + var->xres) > par->max_width ||
144 var->yres > par->max_height) { 142 (var->yoffset + var->yres) > par->max_height) {
145 DRM_ERROR("Requested geom can not fit in framebuffer\n"); 143 DRM_ERROR("Requested geom can not fit in framebuffer\n");
146 return -EINVAL; 144 return -EINVAL;
147 } 145 }
@@ -154,8 +152,8 @@ static int vmw_fb_set_par(struct fb_info *info)
154 struct vmw_fb_par *par = info->par; 152 struct vmw_fb_par *par = info->par;
155 struct vmw_private *vmw_priv = par->vmw_priv; 153 struct vmw_private *vmw_priv = par->vmw_priv;
156 154
157 if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { 155 if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
158 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); 156 vmw_write(vmw_priv, SVGA_REG_ENABLE, 0);
159 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); 157 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
160 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); 158 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
161 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0); 159 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
@@ -164,18 +162,11 @@ static int vmw_fb_set_par(struct fb_info *info)
164 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0); 162 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
165 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); 163 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
166 164
167 vmw_write(vmw_priv, SVGA_REG_ENABLE, 1); 165 vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
168 vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width); 166 info->fix.line_length,
169 vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height); 167 par->bpp, par->depth);
170 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
171 vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
172 vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
173 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
174 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
175 168
176 /* TODO check if pitch and offset changes */ 169 /* TODO check if pitch and offset changes */
177
178 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
179 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); 170 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
180 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); 171 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
181 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, info->var.xoffset); 172 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, info->var.xoffset);
@@ -183,13 +174,22 @@ static int vmw_fb_set_par(struct fb_info *info)
183 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres); 174 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
184 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres); 175 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
185 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); 176 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
177 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
178 vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
186 } else { 179 } else {
187 vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres); 180 vmw_write(vmw_priv, SVGA_REG_ENABLE, 0);
188 vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres); 181 vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
182 info->fix.line_length,
183 par->bpp, par->depth);
184 vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
189 185
190 /* TODO check if pitch and offset changes */
191 } 186 }
192 187
188 /* This is really helpful since if this fails the user
189 * can probably not see anything on the screen.
190 */
191 WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
192
193 return 0; 193 return 0;
194} 194}
195 195
@@ -416,48 +416,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
416 unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size; 416 unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
417 int ret; 417 int ret;
418 418
419 /* XXX These shouldn't be hardcoded. */
419 initial_width = 800; 420 initial_width = 800;
420 initial_height = 600; 421 initial_height = 600;
421 422
422 fb_bbp = 32; 423 fb_bbp = 32;
423 fb_depth = 24; 424 fb_depth = 24;
424 425
425 if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { 426 /* XXX As shouldn't these be as well. */
426 fb_width = min(vmw_priv->fb_max_width, (unsigned)2048); 427 fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
427 fb_height = min(vmw_priv->fb_max_height, (unsigned)2048); 428 fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
428 } else {
429 fb_width = min(vmw_priv->fb_max_width, initial_width);
430 fb_height = min(vmw_priv->fb_max_height, initial_height);
431 }
432 429
433 initial_width = min(fb_width, initial_width); 430 initial_width = min(fb_width, initial_width);
434 initial_height = min(fb_height, initial_height); 431 initial_height = min(fb_height, initial_height);
435 432
436 vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width); 433 fb_pitch = fb_width * fb_bbp / 8;
437 vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height); 434 fb_size = fb_pitch * fb_height;
438 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
439 vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
440 vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
441 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
442 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
443
444 fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
445 fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET); 435 fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
446 fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
447
448 DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
449 DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
450 DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
451 DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
452 DRM_DEBUG("bpp %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
453 DRM_DEBUG("depth %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
454 DRM_DEBUG("bpl %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
455 DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
456 DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
457 DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
458 DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
459 DRM_DEBUG("fb_pitch %u\n", fb_pitch);
460 DRM_DEBUG("fb_size %u kiB\n", fb_size / 1024);
461 436
462 info = framebuffer_alloc(sizeof(*par), device); 437 info = framebuffer_alloc(sizeof(*par), device);
463 if (!info) 438 if (!info)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index a8e5445f94ec..e6a1eb7ea954 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
34 __le32 __iomem *fifo_mem = dev_priv->mmio_virt; 34 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
35 uint32_t fifo_min, hwversion; 35 uint32_t fifo_min, hwversion;
36 36
37 if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
38 return false;
39
37 fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN); 40 fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN);
38 if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int)) 41 if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
39 return false; 42 return false;
@@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
48 return true; 51 return true;
49} 52}
50 53
54bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
55{
56 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
57 uint32_t caps;
58
59 if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
60 return false;
61
62 caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
63 if (caps & SVGA_FIFO_CAP_PITCHLOCK)
64 return true;
65
66 return false;
67}
68
51int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) 69int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
52{ 70{
53 __le32 __iomem *fifo_mem = dev_priv->mmio_virt; 71 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 642bcd7a1500..c748207e9e1c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -596,31 +596,11 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
596 vmw_framebuffer_to_vfbd(&vfb->base); 596 vmw_framebuffer_to_vfbd(&vfb->base);
597 int ret; 597 int ret;
598 598
599
599 vmw_overlay_pause_all(dev_priv); 600 vmw_overlay_pause_all(dev_priv);
600 601
601 ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer); 602 ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
602 603
603 if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
604 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
605 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
606 vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
607 vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
608 vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
609 vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
610 vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
611 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
612
613 vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
614 vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
615 vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
616 vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
617 vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
618 vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
619 vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
620 vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
621 } else
622 WARN_ON(true);
623
624 vmw_overlay_resume_all(dev_priv); 604 vmw_overlay_resume_all(dev_priv);
625 605
626 return 0; 606 return 0;
@@ -668,7 +648,7 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
668 648
669 /* XXX get the first 3 from the surface info */ 649 /* XXX get the first 3 from the surface info */
670 vfbd->base.base.bits_per_pixel = 32; 650 vfbd->base.base.bits_per_pixel = 32;
671 vfbd->base.base.pitch = width * 32 / 4; 651 vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8;
672 vfbd->base.base.depth = 24; 652 vfbd->base.base.depth = 24;
673 vfbd->base.base.width = width; 653 vfbd->base.base.width = width;
674 vfbd->base.base.height = height; 654 vfbd->base.base.height = height;
@@ -827,24 +807,25 @@ out:
827 return ret; 807 return ret;
828} 808}
829 809
830int vmw_kms_save_vga(struct vmw_private *vmw_priv) 810void vmw_kms_write_svga(struct vmw_private *vmw_priv,
811 unsigned width, unsigned height, unsigned pitch,
812 unsigned bbp, unsigned depth)
831{ 813{
832 /* 814 if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
833 * setup a single multimon monitor with the size 815 vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
834 * of 0x0, this stops the UI from resizing when we 816 else if (vmw_fifo_have_pitchlock(vmw_priv))
835 * change the framebuffer size 817 iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
836 */ 818 vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
837 if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { 819 vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
838 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); 820 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
839 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); 821 vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
840 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); 822 vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
841 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0); 823 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
842 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0); 824 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
843 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0); 825}
844 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
845 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
846 }
847 826
827int vmw_kms_save_vga(struct vmw_private *vmw_priv)
828{
848 vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH); 829 vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
849 vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT); 830 vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
850 vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL); 831 vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
@@ -853,6 +834,12 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
853 vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK); 834 vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
854 vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK); 835 vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
855 vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK); 836 vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
837 if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
838 vmw_priv->vga_pitchlock =
839 vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
840 else if (vmw_fifo_have_pitchlock(vmw_priv))
841 vmw_priv->vga_pitchlock =
842 ioread32(vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
856 843
857 return 0; 844 return 0;
858} 845}
@@ -867,9 +854,12 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
867 vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask); 854 vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
868 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask); 855 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
869 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask); 856 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
870 857 if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
871 /* TODO check for multimon */ 858 vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
872 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0); 859 vmw_priv->vga_pitchlock);
860 else if (vmw_fifo_have_pitchlock(vmw_priv))
861 iowrite32(vmw_priv->vga_pitchlock,
862 vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
873 863
874 return 0; 864 return 0;
875} 865}
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}