29 #include <linux/export.h>
36 #define VMW_DIRTY_DELAY (HZ / 30)
68 static int vmw_fb_setcolreg(
unsigned regno,
unsigned red,
unsigned green,
76 DRM_ERROR(
"Bad regno %u.\n", regno);
83 pal[regno] = ((red & 0xff00) << 8) |
85 ((blue & 0xff00) >> 8);
88 DRM_ERROR(
"Bad depth %u, bpp %u.\n", par->
depth, par->
bpp);
104 depth = (var->
transp.length > 0) ? 32 : 24;
113 var->
red.offset = 16;
114 var->
green.offset = 8;
115 var->
blue.offset = 0;
117 var->
green.length = 8;
118 var->
blue.length = 8;
123 var->
red.offset = 16;
124 var->
green.offset = 8;
125 var->
blue.offset = 0;
127 var->
green.length = 8;
128 var->
blue.length = 8;
133 DRM_ERROR(
"Bad depth %u.\n", depth);
139 DRM_ERROR(
"Can not handle panning without display topology\n");
145 DRM_ERROR(
"Requested geom can not fit in framebuffer\n");
150 info->
fix.line_length,
152 DRM_ERROR(
"Requested geom can not fit in framebuffer\n");
159 static int vmw_fb_set_par(
struct fb_info *info)
166 info->
fix.line_length,
197 static int vmw_fb_blank(
int blank,
struct fb_info *info)
206 static void vmw_fb_dirty_flush(
struct vmw_fb_par *par)
210 int stride = (info->
fix.line_length / 4);
225 if (!par->
dirty.active) {
226 spin_unlock_irqrestore(&par->
dirty.lock,
flags);
235 spin_unlock_irqrestore(&par->
dirty.lock,
flags);
237 for (
i =
y * stride;
i < info->
fix.smem_len / 4;
i += stride) {
238 for (
k =
i+
x;
k <
i+
x+
w &&
k < info->
fix.smem_len / 4;
k++)
243 DRM_INFO(
"%s, (%u, %u) (%ux%u)\n", __func__,
x,
y,
w,
h);
248 DRM_ERROR(
"Fifo reserve failed.\n");
260 static void vmw_fb_dirty_mark(
struct vmw_fb_par *par,
261 unsigned x1,
unsigned y1,
266 unsigned x2 = x1 +
width;
267 unsigned y2 = y1 +
height;
277 if (par->
dirty.active)
280 if (x1 < par->
dirty.x1)
282 if (y1 < par->
dirty.y1)
284 if (x2 > par->
dirty.x2)
286 if (y2 > par->
dirty.y2)
289 spin_unlock_irqrestore(&par->
dirty.lock, flags);
292 static void vmw_deferred_io(
struct fb_info *info,
306 min =
min(min, start);
311 y1 = min / info->
fix.line_length;
312 y2 = (max / info->
fix.line_length) + 1;
319 spin_unlock_irqrestore(&par->
dirty.lock, flags);
322 vmw_fb_dirty_flush(par);
327 .deferred_io = vmw_deferred_io,
337 vmw_fb_dirty_mark(info->
par, rect->
dx, rect->
dy,
344 vmw_fb_dirty_mark(info->
par, region->
dx, region->
dy,
351 vmw_fb_dirty_mark(info->
par, image->
dx, image->
dy,
359 static struct fb_ops vmw_fb_ops = {
361 .fb_check_var = vmw_fb_check_var,
362 .fb_set_par = vmw_fb_set_par,
363 .fb_setcolreg = vmw_fb_setcolreg,
364 .fb_fillrect = vmw_fb_fillrect,
365 .fb_copyarea = vmw_fb_copyarea,
366 .fb_imageblit = vmw_fb_imageblit,
367 .fb_pan_display = vmw_fb_pan_display,
368 .fb_blank = vmw_fb_blank,
371 static int vmw_fb_create_bo(
struct vmw_private *vmw_priv,
412 unsigned initial_width, initial_height;
413 unsigned fb_width, fb_height;
414 unsigned fb_bpp, fb_depth, fb_offset, fb_pitch, fb_size;
427 fb_pitch = fb_width * fb_bpp / 8;
428 fb_size = fb_pitch * fb_height;
441 par->
depth = fb_depth;
456 ret = vmw_fb_create_bo(vmw_priv, fb_size, &par->
vmw_bo);
462 par->
vmw_bo->base.num_pages,
475 info->
fix.type_aux = 0;
476 info->
fix.xpanstep = 1;
477 info->
fix.ypanstep = 1;
478 info->
fix.ywrapstep = 0;
480 info->
fix.line_length = fb_pitch;
482 info->
fix.smem_start = 0;
483 info->
fix.smem_len = fb_size;
490 info->
fbops = &vmw_fb_ops;
493 info->
var.red.offset = 16;
494 info->
var.green.offset = 8;
495 info->
var.blue.offset = 0;
496 info->
var.red.length = 8;
497 info->
var.green.length = 8;
498 info->
var.blue.length = 8;
499 info->
var.transp.offset = 0;
500 info->
var.transp.length = 0;
502 info->
var.xres_virtual = fb_width;
503 info->
var.yres_virtual = fb_height;
504 info->
var.bits_per_pixel = par->
bpp;
505 info->
var.xoffset = 0;
506 info->
var.yoffset = 0;
508 info->
var.height = -1;
509 info->
var.width = -1;
511 info->
var.xres = initial_width;
512 info->
var.yres = initial_height;
529 par->
dirty.active =
true;
594 par->
dirty.active =
false;
595 spin_unlock_irqrestore(&par->
dirty.lock, flags);
630 DRM_ERROR(
"could not move buffer to start of VRAM\n");
636 par->
vmw_bo->base.num_pages,
639 par->
bo_ptr = ttm_kmap_obj_virtual(&par->
map, &dummy);
642 par->
dirty.active =
true;
643 spin_unlock_irqrestore(&par->
dirty.lock, flags);
646 vmw_fb_set_par(info);
648 vmw_fb_dirty_mark(par, 0, 0, info->
var.xres, info->
var.yres);