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 | |
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')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 81 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 72 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 70 |
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, | |||
401 | extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason); | 402 | extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason); |
402 | extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma); | 403 | extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma); |
403 | extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv); | 404 | extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv); |
405 | extern 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); |
496 | void 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 | ||
54 | bool 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 | |||
51 | int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | 69 | int 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 | ||
830 | int vmw_kms_save_vga(struct vmw_private *vmw_priv) | 810 | void 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 | ||
827 | int 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 | } |