|
@@ -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_MULTIMON) &&
|
|
|
|
- (var->xres != par->max_width ||
|
|
|
|
- var->yres != par->max_height)) {
|
|
|
|
- DRM_ERROR("Tried to resize, but we don't have multimon\n");
|
|
|
|
|
|
+ if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
|
|
|
|
+ (var->xoffset != 0 || var->yoffset != 0)) {
|
|
|
|
+ DRM_ERROR("Can not handle panning without display topology\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- if (var->xres > par->max_width ||
|
|
|
|
- var->yres > par->max_height) {
|
|
|
|
|
|
+ if ((var->xoffset + var->xres) > par->max_width ||
|
|
|
|
+ (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) {
|
|
|
|
- vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
|
|
|
|
|
|
+ if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
|
|
|
|
+ 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_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
|
|
|
|
- vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
|
|
|
|
- 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);
|
|
|
|
|
|
+ vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
|
|
|
|
+ info->fix.line_length,
|
|
|
|
+ par->bpp, par->depth);
|
|
|
|
|
|
/* 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_HEIGHT, info->var.yres);
|
|
|
|
|
|
+ vmw_write(vmw_priv, SVGA_REG_ENABLE, 0);
|
|
|
|
+ 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) {
|
|
|
|
- fb_width = min(vmw_priv->fb_max_width, (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);
|
|
|
|
- }
|
|
|
|
|
|
+ /* XXX As shouldn't these be as well. */
|
|
|
|
+ fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
|
|
|
|
+ fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
|
|
|
|
|
|
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);
|
|
|
|
- vmw_write(vmw_priv, SVGA_REG_HEIGHT, 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_pitch = fb_width * fb_bbp / 8;
|
|
|
|
+ fb_size = fb_pitch * fb_height;
|
|
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)
|