mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
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>
This commit is contained in:
parent
1ae1ddd5e9
commit
d7e1958dbe
@ -318,6 +318,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
|||||||
goto out_err3;
|
goto out_err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Need mmio memory to check for fifo pitchlock cap. */
|
||||||
|
if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
|
||||||
|
!(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
|
||||||
|
!vmw_fifo_have_pitchlock(dev_priv)) {
|
||||||
|
ret = -ENOSYS;
|
||||||
|
DRM_ERROR("Hardware has no pitchlock\n");
|
||||||
|
goto out_err4;
|
||||||
|
}
|
||||||
|
|
||||||
dev_priv->tdev = ttm_object_device_init
|
dev_priv->tdev = ttm_object_device_init
|
||||||
(dev_priv->mem_global_ref.object, 12);
|
(dev_priv->mem_global_ref.object, 12);
|
||||||
|
|
||||||
|
@ -187,6 +187,7 @@ struct vmw_private {
|
|||||||
uint32_t vga_red_mask;
|
uint32_t vga_red_mask;
|
||||||
uint32_t vga_blue_mask;
|
uint32_t vga_blue_mask;
|
||||||
uint32_t vga_green_mask;
|
uint32_t vga_green_mask;
|
||||||
|
uint32_t vga_pitchlock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Framebuffer info.
|
* Framebuffer info.
|
||||||
@ -401,6 +402,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
|
|||||||
extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
|
extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
|
||||||
extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
|
extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||||
extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
|
extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
|
||||||
|
extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TTM glue - vmwgfx_ttm_glue.c
|
* TTM glue - vmwgfx_ttm_glue.c
|
||||||
@ -491,6 +493,9 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
|
|||||||
struct ttm_object_file *tfile,
|
struct ttm_object_file *tfile,
|
||||||
struct ttm_buffer_object *bo,
|
struct ttm_buffer_object *bo,
|
||||||
SVGA3dCmdHeader *header);
|
SVGA3dCmdHeader *header);
|
||||||
|
void vmw_kms_write_svga(struct vmw_private *vmw_priv,
|
||||||
|
unsigned width, unsigned height, unsigned pitch,
|
||||||
|
unsigned bbp, unsigned depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overlay control - vmwgfx_overlay.c
|
* Overlay control - vmwgfx_overlay.c
|
||||||
|
@ -132,16 +132,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* without multimon its hard to resize */
|
if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
|
||||||
if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
|
(var->xoffset != 0 || var->yoffset != 0)) {
|
||||||
(var->xres != par->max_width ||
|
DRM_ERROR("Can not handle panning without display topology\n");
|
||||||
var->yres != par->max_height)) {
|
|
||||||
DRM_ERROR("Tried to resize, but we don't have multimon\n");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var->xres > par->max_width ||
|
if ((var->xoffset + var->xres) > par->max_width ||
|
||||||
var->yres > par->max_height) {
|
(var->yoffset + var->yres) > par->max_height) {
|
||||||
DRM_ERROR("Requested geom can not fit in framebuffer\n");
|
DRM_ERROR("Requested geom can not fit in framebuffer\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -154,8 +152,8 @@ static int vmw_fb_set_par(struct fb_info *info)
|
|||||||
struct vmw_fb_par *par = info->par;
|
struct vmw_fb_par *par = info->par;
|
||||||
struct vmw_private *vmw_priv = par->vmw_priv;
|
struct vmw_private *vmw_priv = par->vmw_priv;
|
||||||
|
|
||||||
if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
|
if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
|
||||||
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
|
vmw_write(vmw_priv, SVGA_REG_ENABLE, 0);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
|
||||||
@ -164,18 +162,11 @@ static int vmw_fb_set_par(struct fb_info *info)
|
|||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
||||||
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
|
vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
|
||||||
vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
|
info->fix.line_length,
|
||||||
vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
|
par->bpp, par->depth);
|
||||||
vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
|
|
||||||
|
|
||||||
/* TODO check if pitch and offset changes */
|
/* TODO check if pitch and offset changes */
|
||||||
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, info->var.xoffset);
|
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)
|
|||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
|
||||||
} else {
|
} else {
|
||||||
vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
|
vmw_write(vmw_priv, SVGA_REG_ENABLE, 0);
|
||||||
vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
|
vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
|
||||||
|
info->fix.line_length,
|
||||||
|
par->bpp, par->depth);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
|
||||||
|
|
||||||
/* TODO check if pitch and offset changes */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is really helpful since if this fails the user
|
||||||
|
* can probably not see anything on the screen.
|
||||||
|
*/
|
||||||
|
WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,48 +416,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
|
|||||||
unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
|
unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* XXX These shouldn't be hardcoded. */
|
||||||
initial_width = 800;
|
initial_width = 800;
|
||||||
initial_height = 600;
|
initial_height = 600;
|
||||||
|
|
||||||
fb_bbp = 32;
|
fb_bbp = 32;
|
||||||
fb_depth = 24;
|
fb_depth = 24;
|
||||||
|
|
||||||
if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
|
/* XXX As shouldn't these be as well. */
|
||||||
fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
|
fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
|
||||||
fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
|
fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
|
||||||
} else {
|
|
||||||
fb_width = min(vmw_priv->fb_max_width, initial_width);
|
|
||||||
fb_height = min(vmw_priv->fb_max_height, initial_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
initial_width = min(fb_width, initial_width);
|
initial_width = min(fb_width, initial_width);
|
||||||
initial_height = min(fb_height, initial_height);
|
initial_height = min(fb_height, initial_height);
|
||||||
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
|
fb_pitch = fb_width * fb_bbp / 8;
|
||||||
vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
|
fb_size = fb_pitch * fb_height;
|
||||||
vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
|
|
||||||
|
|
||||||
fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
|
|
||||||
fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
|
fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
|
||||||
fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
|
|
||||||
|
|
||||||
DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
|
|
||||||
DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
|
|
||||||
DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
|
|
||||||
DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
|
|
||||||
DRM_DEBUG("bpp %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
|
|
||||||
DRM_DEBUG("depth %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
|
|
||||||
DRM_DEBUG("bpl %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
|
|
||||||
DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
|
|
||||||
DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
|
|
||||||
DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
|
|
||||||
DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
|
|
||||||
DRM_DEBUG("fb_pitch %u\n", fb_pitch);
|
|
||||||
DRM_DEBUG("fb_size %u kiB\n", fb_size / 1024);
|
|
||||||
|
|
||||||
info = framebuffer_alloc(sizeof(*par), device);
|
info = framebuffer_alloc(sizeof(*par), device);
|
||||||
if (!info)
|
if (!info)
|
||||||
|
@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
|
|||||||
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
|
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
|
||||||
uint32_t fifo_min, hwversion;
|
uint32_t fifo_min, hwversion;
|
||||||
|
|
||||||
|
if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
|
||||||
|
return false;
|
||||||
|
|
||||||
fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN);
|
fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN);
|
||||||
if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
|
if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
|
||||||
return false;
|
return false;
|
||||||
@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
|
||||||
|
{
|
||||||
|
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
|
||||||
|
uint32_t caps;
|
||||||
|
|
||||||
|
if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
|
||||||
|
if (caps & SVGA_FIFO_CAP_PITCHLOCK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
||||||
{
|
{
|
||||||
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
|
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
|
||||||
|
@ -596,31 +596,11 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
|
|||||||
vmw_framebuffer_to_vfbd(&vfb->base);
|
vmw_framebuffer_to_vfbd(&vfb->base);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
vmw_overlay_pause_all(dev_priv);
|
vmw_overlay_pause_all(dev_priv);
|
||||||
|
|
||||||
ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
|
ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
|
||||||
|
|
||||||
if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
|
|
||||||
vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
|
||||||
|
|
||||||
vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
|
|
||||||
vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
|
|
||||||
} else
|
|
||||||
WARN_ON(true);
|
|
||||||
|
|
||||||
vmw_overlay_resume_all(dev_priv);
|
vmw_overlay_resume_all(dev_priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -668,7 +648,7 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
|
|||||||
|
|
||||||
/* XXX get the first 3 from the surface info */
|
/* XXX get the first 3 from the surface info */
|
||||||
vfbd->base.base.bits_per_pixel = 32;
|
vfbd->base.base.bits_per_pixel = 32;
|
||||||
vfbd->base.base.pitch = width * 32 / 4;
|
vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8;
|
||||||
vfbd->base.base.depth = 24;
|
vfbd->base.base.depth = 24;
|
||||||
vfbd->base.base.width = width;
|
vfbd->base.base.width = width;
|
||||||
vfbd->base.base.height = height;
|
vfbd->base.base.height = height;
|
||||||
@ -827,24 +807,25 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vmw_kms_write_svga(struct vmw_private *vmw_priv,
|
||||||
|
unsigned width, unsigned height, unsigned pitch,
|
||||||
|
unsigned bbp, unsigned depth)
|
||||||
|
{
|
||||||
|
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
|
||||||
|
else if (vmw_fifo_have_pitchlock(vmw_priv))
|
||||||
|
iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
|
||||||
|
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
|
||||||
|
}
|
||||||
|
|
||||||
int vmw_kms_save_vga(struct vmw_private *vmw_priv)
|
int vmw_kms_save_vga(struct vmw_private *vmw_priv)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* setup a single multimon monitor with the size
|
|
||||||
* of 0x0, this stops the UI from resizing when we
|
|
||||||
* change the framebuffer size
|
|
||||||
*/
|
|
||||||
if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
|
|
||||||
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
|
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_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
|
||||||
vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
|
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)
|
|||||||
vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
|
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_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_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
|
||||||
|
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
|
||||||
|
vmw_priv->vga_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);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -867,9 +854,12 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
|
|||||||
vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
|
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);
|
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
|
||||||
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
|
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
|
||||||
|
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
|
||||||
/* TODO check for multimon */
|
vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
|
||||||
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
|
vmw_priv->vga_pitchlock);
|
||||||
|
else if (vmw_fifo_have_pitchlock(vmw_priv))
|
||||||
|
iowrite32(vmw_priv->vga_pitchlock,
|
||||||
|
vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ struct vmw_legacy_display {
|
|||||||
struct list_head active;
|
struct list_head active;
|
||||||
|
|
||||||
unsigned num_active;
|
unsigned num_active;
|
||||||
|
unsigned last_num_active;
|
||||||
|
|
||||||
struct vmw_framebuffer *fb;
|
struct vmw_framebuffer *fb;
|
||||||
};
|
};
|
||||||
@ -88,12 +89,37 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
|
|||||||
{
|
{
|
||||||
struct vmw_legacy_display *lds = dev_priv->ldu_priv;
|
struct vmw_legacy_display *lds = dev_priv->ldu_priv;
|
||||||
struct vmw_legacy_display_unit *entry;
|
struct vmw_legacy_display_unit *entry;
|
||||||
struct drm_crtc *crtc;
|
struct drm_framebuffer *fb = NULL;
|
||||||
|
struct drm_crtc *crtc = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* to stop the screen from changing size on resize */
|
/* If there is no display topology the host just assumes
|
||||||
vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
|
* that the guest will set the same layout as the host.
|
||||||
for (i = 0; i < lds->num_active; i++) {
|
*/
|
||||||
|
if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
|
||||||
|
int w = 0, h = 0;
|
||||||
|
list_for_each_entry(entry, &lds->active, active) {
|
||||||
|
crtc = &entry->base.crtc;
|
||||||
|
w = max(w, crtc->x + crtc->mode.hdisplay);
|
||||||
|
h = max(h, crtc->y + crtc->mode.vdisplay);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crtc == NULL)
|
||||||
|
return 0;
|
||||||
|
fb = entry->base.crtc.fb;
|
||||||
|
|
||||||
|
vmw_write(dev_priv, SVGA_REG_ENABLE, 0);
|
||||||
|
vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
|
||||||
|
fb->bits_per_pixel, fb->depth);
|
||||||
|
vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmw_write(dev_priv, SVGA_REG_ENABLE, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < lds->last_num_active; i++) {
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
|
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
|
vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
|
||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
|
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)
|
|||||||
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now set the mode */
|
if (!list_empty(&lds->active)) {
|
||||||
vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
|
entry = list_entry(lds->active.next, typeof(*entry), active);
|
||||||
|
fb = entry->base.crtc.fb;
|
||||||
|
|
||||||
|
vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
|
||||||
|
fb->bits_per_pixel, fb->depth);
|
||||||
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
list_for_each_entry(entry, &lds->active, active) {
|
list_for_each_entry(entry, &lds->active, active) {
|
||||||
crtc = &entry->base.crtc;
|
crtc = &entry->base.crtc;
|
||||||
@ -120,6 +152,14 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure we always show something. */
|
||||||
|
vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, i ? i : 1);
|
||||||
|
vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
|
||||||
|
|
||||||
|
BUG_ON(i != lds->num_active);
|
||||||
|
|
||||||
|
lds->last_num_active = lds->num_active;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,18 +531,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
|
|||||||
|
|
||||||
INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
|
INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
|
||||||
dev_priv->ldu_priv->num_active = 0;
|
dev_priv->ldu_priv->num_active = 0;
|
||||||
|
dev_priv->ldu_priv->last_num_active = 0;
|
||||||
dev_priv->ldu_priv->fb = NULL;
|
dev_priv->ldu_priv->fb = NULL;
|
||||||
|
|
||||||
drm_mode_create_dirty_info_property(dev_priv->dev);
|
drm_mode_create_dirty_info_property(dev_priv->dev);
|
||||||
|
|
||||||
vmw_ldu_init(dev_priv, 0);
|
vmw_ldu_init(dev_priv, 0);
|
||||||
vmw_ldu_init(dev_priv, 1);
|
/* for old hardware without multimon only enable one display */
|
||||||
vmw_ldu_init(dev_priv, 2);
|
if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
|
||||||
vmw_ldu_init(dev_priv, 3);
|
vmw_ldu_init(dev_priv, 1);
|
||||||
vmw_ldu_init(dev_priv, 4);
|
vmw_ldu_init(dev_priv, 2);
|
||||||
vmw_ldu_init(dev_priv, 5);
|
vmw_ldu_init(dev_priv, 3);
|
||||||
vmw_ldu_init(dev_priv, 6);
|
vmw_ldu_init(dev_priv, 4);
|
||||||
vmw_ldu_init(dev_priv, 7);
|
vmw_ldu_init(dev_priv, 5);
|
||||||
|
vmw_ldu_init(dev_priv, 6);
|
||||||
|
vmw_ldu_init(dev_priv, 7);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user