int vmw_kms_save_vga(struct vmw_private *vmw_priv)
{
+ struct vmw_vga_topology_state *save;
+ uint32_t i;
+
vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
- vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
+ vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
- vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
+ vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
vmw_priv->vga_pitchlock =
- vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
+ vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
else if (vmw_fifo_have_pitchlock(vmw_priv))
- vmw_priv->vga_pitchlock =
- ioread32(vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+ vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt +
+ SVGA_FIFO_PITCHLOCK);
+
+ if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+ return 0;
+ vmw_priv->num_displays = vmw_read(vmw_priv,
+ SVGA_REG_NUM_GUEST_DISPLAYS);
+
+ for (i = 0; i < vmw_priv->num_displays; ++i) {
+ save = &vmw_priv->vga_save[i];
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+ save->primary = vmw_read(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY);
+ save->pos_x = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_X);
+ save->pos_y = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y);
+ save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
+ save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+ }
return 0;
}
int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
{
+ struct vmw_vga_topology_state *save;
+ uint32_t i;
+
vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
- vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
+ vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
iowrite32(vmw_priv->vga_pitchlock,
vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+ if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+ return 0;
+
+ for (i = 0; i < vmw_priv->num_displays; ++i) {
+ save = &vmw_priv->vga_save[i];
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, save->primary);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, save->pos_x);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, save->pos_y);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, save->width);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, save->height);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+ }
+
return 0;
}
+
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_vmw_update_layout_arg *arg =
+ (struct drm_vmw_update_layout_arg *)data;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
+ void __user *user_rects;
+ struct drm_vmw_rect *rects;
+ unsigned rects_size;
+ int ret;
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (!arg->num_outputs) {
+ struct drm_vmw_rect def_rect = {0, 0, 800, 600};
+ vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
+ goto out_unlock;
+ }
+
+ rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
+ rects = kzalloc(rects_size, GFP_KERNEL);
+ if (unlikely(!rects)) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+
+ user_rects = (void __user *)(unsigned long)arg->rects;
+ ret = copy_from_user(rects, user_rects, rects_size);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Failed to get rects.\n");
+ ret = -EFAULT;
+ goto out_free;
+ }
+
+ vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
+
+out_free:
+ kfree(rects);
+out_unlock:
+ ttm_read_unlock(&vmaster->lock);
+ return ret;
+}