1 /**************************************************************************
2  *
3  * Copyright © 2007 David Airlie
4  * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25  * USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 #include <linux/fb.h>
30 #include <linux/pci.h>
31 
32 #include <drm/drm_fourcc.h>
33 #include <drm/ttm/ttm_placement.h>
34 
35 #include "vmwgfx_drv.h"
36 #include "vmwgfx_kms.h"
37 
38 #define VMW_DIRTY_DELAY (HZ / 30)
39 
40 struct vmw_fb_par {
41 	struct vmw_private *vmw_priv;
42 
43 	void *vmalloc;
44 
45 	struct mutex bo_mutex;
46 	struct vmw_buffer_object *vmw_bo;
47 	unsigned bo_size;
48 	struct drm_framebuffer *set_fb;
49 	struct drm_display_mode *set_mode;
50 	u32 fb_x;
51 	u32 fb_y;
52 	bool bo_iowrite;
53 
54 	u32 pseudo_palette[17];
55 
56 	unsigned max_width;
57 	unsigned max_height;
58 
59 	struct {
60 		spinlock_t lock;
61 		bool active;
62 		unsigned x1;
63 		unsigned y1;
64 		unsigned x2;
65 		unsigned y2;
66 	} dirty;
67 
68 	struct drm_crtc *crtc;
69 	struct drm_connector *con;
70 	struct delayed_work local_work;
71 };
72 
vmw_fb_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)73 static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
74 			    unsigned blue, unsigned transp,
75 			    struct fb_info *info)
76 {
77 	struct vmw_fb_par *par = info->par;
78 	u32 *pal = par->pseudo_palette;
79 
80 	if (regno > 15) {
81 		DRM_ERROR("Bad regno %u.\n", regno);
82 		return 1;
83 	}
84 
85 	switch (par->set_fb->format->depth) {
86 	case 24:
87 	case 32:
88 		pal[regno] = ((red & 0xff00) << 8) |
89 			      (green & 0xff00) |
90 			     ((blue  & 0xff00) >> 8);
91 		break;
92 	default:
93 		DRM_ERROR("Bad depth %u, bpp %u.\n",
94 			  par->set_fb->format->depth,
95 			  par->set_fb->format->cpp[0] * 8);
96 		return 1;
97 	}
98 
99 	return 0;
100 }
101 
vmw_fb_check_var(struct fb_var_screeninfo * var,struct fb_info * info)102 static int vmw_fb_check_var(struct fb_var_screeninfo *var,
103 			    struct fb_info *info)
104 {
105 	int depth = var->bits_per_pixel;
106 	struct vmw_fb_par *par = info->par;
107 	struct vmw_private *vmw_priv = par->vmw_priv;
108 
109 	switch (var->bits_per_pixel) {
110 	case 32:
111 		depth = (var->transp.length > 0) ? 32 : 24;
112 		break;
113 	default:
114 		DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
115 		return -EINVAL;
116 	}
117 
118 	switch (depth) {
119 	case 24:
120 		var->red.offset = 16;
121 		var->green.offset = 8;
122 		var->blue.offset = 0;
123 		var->red.length = 8;
124 		var->green.length = 8;
125 		var->blue.length = 8;
126 		var->transp.length = 0;
127 		var->transp.offset = 0;
128 		break;
129 	case 32:
130 		var->red.offset = 16;
131 		var->green.offset = 8;
132 		var->blue.offset = 0;
133 		var->red.length = 8;
134 		var->green.length = 8;
135 		var->blue.length = 8;
136 		var->transp.length = 8;
137 		var->transp.offset = 24;
138 		break;
139 	default:
140 		DRM_ERROR("Bad depth %u.\n", depth);
141 		return -EINVAL;
142 	}
143 
144 	if ((var->xoffset + var->xres) > par->max_width ||
145 	    (var->yoffset + var->yres) > par->max_height) {
146 		DRM_ERROR("Requested geom can not fit in framebuffer\n");
147 		return -EINVAL;
148 	}
149 
150 	if (!vmw_kms_validate_mode_vram(vmw_priv,
151 					var->xres * var->bits_per_pixel/8,
152 					var->yoffset + var->yres)) {
153 		DRM_ERROR("Requested geom can not fit in framebuffer\n");
154 		return -EINVAL;
155 	}
156 
157 	return 0;
158 }
159 
vmw_fb_blank(int blank,struct fb_info * info)160 static int vmw_fb_blank(int blank, struct fb_info *info)
161 {
162 	return 0;
163 }
164 
165 /**
166  * vmw_fb_dirty_flush - flush dirty regions to the kms framebuffer
167  *
168  * @work: The struct work_struct associated with this task.
169  *
170  * This function flushes the dirty regions of the vmalloc framebuffer to the
171  * kms framebuffer, and if the kms framebuffer is visible, also updated the
172  * corresponding displays. Note that this function runs even if the kms
173  * framebuffer is not bound to a crtc and thus not visible, but it's turned
174  * off during hibernation using the par->dirty.active bool.
175  */
vmw_fb_dirty_flush(struct work_struct * work)176 static void vmw_fb_dirty_flush(struct work_struct *work)
177 {
178 	struct vmw_fb_par *par = container_of(work, struct vmw_fb_par,
179 					      local_work.work);
180 	struct vmw_private *vmw_priv = par->vmw_priv;
181 	struct fb_info *info = vmw_priv->fb_info;
182 	unsigned long irq_flags;
183 	s32 dst_x1, dst_x2, dst_y1, dst_y2, w = 0, h = 0;
184 	u32 cpp, max_x, max_y;
185 	struct drm_clip_rect clip;
186 	struct drm_framebuffer *cur_fb;
187 	u8 *src_ptr, *dst_ptr;
188 	struct vmw_buffer_object *vbo = par->vmw_bo;
189 	void *virtual;
190 
191 	if (!READ_ONCE(par->dirty.active))
192 		return;
193 
194 	mutex_lock(&par->bo_mutex);
195 	cur_fb = par->set_fb;
196 	if (!cur_fb)
197 		goto out_unlock;
198 
199 	(void) ttm_bo_reserve(&vbo->base, false, false, NULL);
200 	virtual = vmw_bo_map_and_cache(vbo);
201 	if (!virtual)
202 		goto out_unreserve;
203 
204 	spin_lock_irqsave(&par->dirty.lock, irq_flags);
205 	if (!par->dirty.active) {
206 		spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
207 		goto out_unreserve;
208 	}
209 
210 	/*
211 	 * Handle panning when copying from vmalloc to framebuffer.
212 	 * Clip dirty area to framebuffer.
213 	 */
214 	cpp = cur_fb->format->cpp[0];
215 	max_x = par->fb_x + cur_fb->width;
216 	max_y = par->fb_y + cur_fb->height;
217 
218 	dst_x1 = par->dirty.x1 - par->fb_x;
219 	dst_y1 = par->dirty.y1 - par->fb_y;
220 	dst_x1 = max_t(s32, dst_x1, 0);
221 	dst_y1 = max_t(s32, dst_y1, 0);
222 
223 	dst_x2 = par->dirty.x2 - par->fb_x;
224 	dst_y2 = par->dirty.y2 - par->fb_y;
225 	dst_x2 = min_t(s32, dst_x2, max_x);
226 	dst_y2 = min_t(s32, dst_y2, max_y);
227 	w = dst_x2 - dst_x1;
228 	h = dst_y2 - dst_y1;
229 	w = max_t(s32, 0, w);
230 	h = max_t(s32, 0, h);
231 
232 	par->dirty.x1 = par->dirty.x2 = 0;
233 	par->dirty.y1 = par->dirty.y2 = 0;
234 	spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
235 
236 	if (w && h) {
237 		dst_ptr = (u8 *)virtual  +
238 			(dst_y1 * par->set_fb->pitches[0] + dst_x1 * cpp);
239 		src_ptr = (u8 *)par->vmalloc +
240 			((dst_y1 + par->fb_y) * info->fix.line_length +
241 			 (dst_x1 + par->fb_x) * cpp);
242 
243 		while (h-- > 0) {
244 			memcpy(dst_ptr, src_ptr, w*cpp);
245 			dst_ptr += par->set_fb->pitches[0];
246 			src_ptr += info->fix.line_length;
247 		}
248 
249 		clip.x1 = dst_x1;
250 		clip.x2 = dst_x2;
251 		clip.y1 = dst_y1;
252 		clip.y2 = dst_y2;
253 	}
254 
255 out_unreserve:
256 	ttm_bo_unreserve(&vbo->base);
257 	if (w && h) {
258 		WARN_ON_ONCE(par->set_fb->funcs->dirty(cur_fb, NULL, 0, 0,
259 						       &clip, 1));
260 		vmw_cmd_flush(vmw_priv, false);
261 	}
262 out_unlock:
263 	mutex_unlock(&par->bo_mutex);
264 }
265 
vmw_fb_dirty_mark(struct vmw_fb_par * par,unsigned x1,unsigned y1,unsigned width,unsigned height)266 static void vmw_fb_dirty_mark(struct vmw_fb_par *par,
267 			      unsigned x1, unsigned y1,
268 			      unsigned width, unsigned height)
269 {
270 	unsigned long flags;
271 	unsigned x2 = x1 + width;
272 	unsigned y2 = y1 + height;
273 
274 	spin_lock_irqsave(&par->dirty.lock, flags);
275 	if (par->dirty.x1 == par->dirty.x2) {
276 		par->dirty.x1 = x1;
277 		par->dirty.y1 = y1;
278 		par->dirty.x2 = x2;
279 		par->dirty.y2 = y2;
280 		/* if we are active start the dirty work
281 		 * we share the work with the defio system */
282 		if (par->dirty.active)
283 			schedule_delayed_work(&par->local_work,
284 					      VMW_DIRTY_DELAY);
285 	} else {
286 		if (x1 < par->dirty.x1)
287 			par->dirty.x1 = x1;
288 		if (y1 < par->dirty.y1)
289 			par->dirty.y1 = y1;
290 		if (x2 > par->dirty.x2)
291 			par->dirty.x2 = x2;
292 		if (y2 > par->dirty.y2)
293 			par->dirty.y2 = y2;
294 	}
295 	spin_unlock_irqrestore(&par->dirty.lock, flags);
296 }
297 
vmw_fb_pan_display(struct fb_var_screeninfo * var,struct fb_info * info)298 static int vmw_fb_pan_display(struct fb_var_screeninfo *var,
299 			      struct fb_info *info)
300 {
301 	struct vmw_fb_par *par = info->par;
302 
303 	if ((var->xoffset + var->xres) > var->xres_virtual ||
304 	    (var->yoffset + var->yres) > var->yres_virtual) {
305 		DRM_ERROR("Requested panning can not fit in framebuffer\n");
306 		return -EINVAL;
307 	}
308 
309 	mutex_lock(&par->bo_mutex);
310 	par->fb_x = var->xoffset;
311 	par->fb_y = var->yoffset;
312 	if (par->set_fb)
313 		vmw_fb_dirty_mark(par, par->fb_x, par->fb_y, par->set_fb->width,
314 				  par->set_fb->height);
315 	mutex_unlock(&par->bo_mutex);
316 
317 	return 0;
318 }
319 
vmw_deferred_io(struct fb_info * info,struct list_head * pagereflist)320 static void vmw_deferred_io(struct fb_info *info, struct list_head *pagereflist)
321 {
322 	struct vmw_fb_par *par = info->par;
323 	unsigned long start, end, min, max;
324 	unsigned long flags;
325 	struct fb_deferred_io_pageref *pageref;
326 	int y1, y2;
327 
328 	min = ULONG_MAX;
329 	max = 0;
330 	list_for_each_entry(pageref, pagereflist, list) {
331 		start = pageref->offset;
332 		end = start + PAGE_SIZE - 1;
333 		min = min(min, start);
334 		max = max(max, end);
335 	}
336 
337 	if (min < max) {
338 		y1 = min / info->fix.line_length;
339 		y2 = (max / info->fix.line_length) + 1;
340 
341 		spin_lock_irqsave(&par->dirty.lock, flags);
342 		par->dirty.x1 = 0;
343 		par->dirty.y1 = y1;
344 		par->dirty.x2 = info->var.xres;
345 		par->dirty.y2 = y2;
346 		spin_unlock_irqrestore(&par->dirty.lock, flags);
347 
348 		/*
349 		 * Since we've already waited on this work once, try to
350 		 * execute asap.
351 		 */
352 		cancel_delayed_work(&par->local_work);
353 		schedule_delayed_work(&par->local_work, 0);
354 	}
355 };
356 
357 static struct fb_deferred_io vmw_defio = {
358 	.delay		= VMW_DIRTY_DELAY,
359 	.deferred_io	= vmw_deferred_io,
360 };
361 
362 /*
363  * Draw code
364  */
365 
vmw_fb_fillrect(struct fb_info * info,const struct fb_fillrect * rect)366 static void vmw_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
367 {
368 	cfb_fillrect(info, rect);
369 	vmw_fb_dirty_mark(info->par, rect->dx, rect->dy,
370 			  rect->width, rect->height);
371 }
372 
vmw_fb_copyarea(struct fb_info * info,const struct fb_copyarea * region)373 static void vmw_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
374 {
375 	cfb_copyarea(info, region);
376 	vmw_fb_dirty_mark(info->par, region->dx, region->dy,
377 			  region->width, region->height);
378 }
379 
vmw_fb_imageblit(struct fb_info * info,const struct fb_image * image)380 static void vmw_fb_imageblit(struct fb_info *info, const struct fb_image *image)
381 {
382 	cfb_imageblit(info, image);
383 	vmw_fb_dirty_mark(info->par, image->dx, image->dy,
384 			  image->width, image->height);
385 }
386 
387 /*
388  * Bring up code
389  */
390 
vmw_fb_create_bo(struct vmw_private * vmw_priv,size_t size,struct vmw_buffer_object ** out)391 static int vmw_fb_create_bo(struct vmw_private *vmw_priv,
392 			    size_t size, struct vmw_buffer_object **out)
393 {
394 	struct vmw_buffer_object *vmw_bo;
395 	int ret;
396 
397 	ret = vmw_bo_create(vmw_priv, size,
398 			      &vmw_sys_placement,
399 			      false, false,
400 			      &vmw_bo_bo_free, &vmw_bo);
401 	if (unlikely(ret != 0))
402 		return ret;
403 
404 	*out = vmw_bo;
405 
406 	return ret;
407 }
408 
vmw_fb_compute_depth(struct fb_var_screeninfo * var,int * depth)409 static int vmw_fb_compute_depth(struct fb_var_screeninfo *var,
410 				int *depth)
411 {
412 	switch (var->bits_per_pixel) {
413 	case 32:
414 		*depth = (var->transp.length > 0) ? 32 : 24;
415 		break;
416 	default:
417 		DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
418 		return -EINVAL;
419 	}
420 
421 	return 0;
422 }
423 
vmwgfx_set_config_internal(struct drm_mode_set * set)424 static int vmwgfx_set_config_internal(struct drm_mode_set *set)
425 {
426 	struct drm_crtc *crtc = set->crtc;
427 	struct drm_modeset_acquire_ctx ctx;
428 	int ret;
429 
430 	drm_modeset_acquire_init(&ctx, 0);
431 
432 restart:
433 	ret = crtc->funcs->set_config(set, &ctx);
434 
435 	if (ret == -EDEADLK) {
436 		drm_modeset_backoff(&ctx);
437 		goto restart;
438 	}
439 
440 	drm_modeset_drop_locks(&ctx);
441 	drm_modeset_acquire_fini(&ctx);
442 
443 	return ret;
444 }
445 
vmw_fb_kms_detach(struct vmw_fb_par * par,bool detach_bo,bool unref_bo)446 static int vmw_fb_kms_detach(struct vmw_fb_par *par,
447 			     bool detach_bo,
448 			     bool unref_bo)
449 {
450 	struct drm_framebuffer *cur_fb = par->set_fb;
451 	int ret;
452 
453 	/* Detach the KMS framebuffer from crtcs */
454 	if (par->set_mode) {
455 		struct drm_mode_set set;
456 
457 		set.crtc = par->crtc;
458 		set.x = 0;
459 		set.y = 0;
460 		set.mode = NULL;
461 		set.fb = NULL;
462 		set.num_connectors = 0;
463 		set.connectors = &par->con;
464 		ret = vmwgfx_set_config_internal(&set);
465 		if (ret) {
466 			DRM_ERROR("Could not unset a mode.\n");
467 			return ret;
468 		}
469 		drm_mode_destroy(&par->vmw_priv->drm, par->set_mode);
470 		par->set_mode = NULL;
471 	}
472 
473 	if (cur_fb) {
474 		drm_framebuffer_put(cur_fb);
475 		par->set_fb = NULL;
476 	}
477 
478 	if (par->vmw_bo && detach_bo && unref_bo)
479 		vmw_bo_unreference(&par->vmw_bo);
480 
481 	return 0;
482 }
483 
vmw_fb_kms_framebuffer(struct fb_info * info)484 static int vmw_fb_kms_framebuffer(struct fb_info *info)
485 {
486 	struct drm_mode_fb_cmd2 mode_cmd = {0};
487 	struct vmw_fb_par *par = info->par;
488 	struct fb_var_screeninfo *var = &info->var;
489 	struct drm_framebuffer *cur_fb;
490 	struct vmw_framebuffer *vfb;
491 	int ret = 0, depth;
492 	size_t new_bo_size;
493 
494 	ret = vmw_fb_compute_depth(var, &depth);
495 	if (ret)
496 		return ret;
497 
498 	mode_cmd.width = var->xres;
499 	mode_cmd.height = var->yres;
500 	mode_cmd.pitches[0] = ((var->bits_per_pixel + 7) / 8) * mode_cmd.width;
501 	mode_cmd.pixel_format =
502 		drm_mode_legacy_fb_format(var->bits_per_pixel, depth);
503 
504 	cur_fb = par->set_fb;
505 	if (cur_fb && cur_fb->width == mode_cmd.width &&
506 	    cur_fb->height == mode_cmd.height &&
507 	    cur_fb->format->format == mode_cmd.pixel_format &&
508 	    cur_fb->pitches[0] == mode_cmd.pitches[0])
509 		return 0;
510 
511 	/* Need new buffer object ? */
512 	new_bo_size = (size_t) mode_cmd.pitches[0] * (size_t) mode_cmd.height;
513 	ret = vmw_fb_kms_detach(par,
514 				par->bo_size < new_bo_size ||
515 				par->bo_size > 2*new_bo_size,
516 				true);
517 	if (ret)
518 		return ret;
519 
520 	if (!par->vmw_bo) {
521 		ret = vmw_fb_create_bo(par->vmw_priv, new_bo_size,
522 				       &par->vmw_bo);
523 		if (ret) {
524 			DRM_ERROR("Failed creating a buffer object for "
525 				  "fbdev.\n");
526 			return ret;
527 		}
528 		par->bo_size = new_bo_size;
529 	}
530 
531 	vfb = vmw_kms_new_framebuffer(par->vmw_priv, par->vmw_bo, NULL,
532 				      true, &mode_cmd);
533 	if (IS_ERR(vfb))
534 		return PTR_ERR(vfb);
535 
536 	par->set_fb = &vfb->base;
537 
538 	return 0;
539 }
540 
vmw_fb_set_par(struct fb_info * info)541 static int vmw_fb_set_par(struct fb_info *info)
542 {
543 	struct vmw_fb_par *par = info->par;
544 	struct vmw_private *vmw_priv = par->vmw_priv;
545 	struct drm_mode_set set;
546 	struct fb_var_screeninfo *var = &info->var;
547 	struct drm_display_mode new_mode = { DRM_MODE("fb_mode",
548 		DRM_MODE_TYPE_DRIVER,
549 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
550 		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
551 	};
552 	struct drm_display_mode *mode;
553 	int ret;
554 
555 	mode = drm_mode_duplicate(&vmw_priv->drm, &new_mode);
556 	if (!mode) {
557 		DRM_ERROR("Could not create new fb mode.\n");
558 		return -ENOMEM;
559 	}
560 
561 	mode->hdisplay = var->xres;
562 	mode->vdisplay = var->yres;
563 	vmw_guess_mode_timing(mode);
564 
565 	if (!vmw_kms_validate_mode_vram(vmw_priv,
566 					mode->hdisplay *
567 					DIV_ROUND_UP(var->bits_per_pixel, 8),
568 					mode->vdisplay)) {
569 		drm_mode_destroy(&vmw_priv->drm, mode);
570 		return -EINVAL;
571 	}
572 
573 	mutex_lock(&par->bo_mutex);
574 	ret = vmw_fb_kms_framebuffer(info);
575 	if (ret)
576 		goto out_unlock;
577 
578 	par->fb_x = var->xoffset;
579 	par->fb_y = var->yoffset;
580 
581 	set.crtc = par->crtc;
582 	set.x = 0;
583 	set.y = 0;
584 	set.mode = mode;
585 	set.fb = par->set_fb;
586 	set.num_connectors = 1;
587 	set.connectors = &par->con;
588 
589 	ret = vmwgfx_set_config_internal(&set);
590 	if (ret)
591 		goto out_unlock;
592 
593 	vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
594 			  par->set_fb->width, par->set_fb->height);
595 
596 	/* If there already was stuff dirty we wont
597 	 * schedule a new work, so lets do it now */
598 
599 	schedule_delayed_work(&par->local_work, 0);
600 
601 out_unlock:
602 	if (par->set_mode)
603 		drm_mode_destroy(&vmw_priv->drm, par->set_mode);
604 	par->set_mode = mode;
605 
606 	mutex_unlock(&par->bo_mutex);
607 
608 	return ret;
609 }
610 
611 
612 static const struct fb_ops vmw_fb_ops = {
613 	.owner = THIS_MODULE,
614 	.fb_check_var = vmw_fb_check_var,
615 	.fb_set_par = vmw_fb_set_par,
616 	.fb_setcolreg = vmw_fb_setcolreg,
617 	.fb_fillrect = vmw_fb_fillrect,
618 	.fb_copyarea = vmw_fb_copyarea,
619 	.fb_imageblit = vmw_fb_imageblit,
620 	.fb_pan_display = vmw_fb_pan_display,
621 	.fb_blank = vmw_fb_blank,
622 	.fb_mmap = fb_deferred_io_mmap,
623 };
624 
vmw_fb_init(struct vmw_private * vmw_priv)625 int vmw_fb_init(struct vmw_private *vmw_priv)
626 {
627 	struct device *device = vmw_priv->drm.dev;
628 	struct vmw_fb_par *par;
629 	struct fb_info *info;
630 	unsigned fb_width, fb_height;
631 	unsigned int fb_bpp, fb_pitch, fb_size;
632 	struct drm_display_mode *init_mode;
633 	int ret;
634 
635 	fb_bpp = 32;
636 
637 	/* XXX As shouldn't these be as well. */
638 	fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
639 	fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
640 
641 	fb_pitch = fb_width * fb_bpp / 8;
642 	fb_size = fb_pitch * fb_height;
643 
644 	info = framebuffer_alloc(sizeof(*par), device);
645 	if (!info)
646 		return -ENOMEM;
647 
648 	/*
649 	 * Par
650 	 */
651 	vmw_priv->fb_info = info;
652 	par = info->par;
653 	memset(par, 0, sizeof(*par));
654 	INIT_DELAYED_WORK(&par->local_work, &vmw_fb_dirty_flush);
655 	par->vmw_priv = vmw_priv;
656 	par->vmalloc = NULL;
657 	par->max_width = fb_width;
658 	par->max_height = fb_height;
659 
660 	ret = vmw_kms_fbdev_init_data(vmw_priv, 0, par->max_width,
661 				      par->max_height, &par->con,
662 				      &par->crtc, &init_mode);
663 	if (ret)
664 		goto err_kms;
665 
666 	info->var.xres = init_mode->hdisplay;
667 	info->var.yres = init_mode->vdisplay;
668 
669 	/*
670 	 * Create buffers and alloc memory
671 	 */
672 	par->vmalloc = vzalloc(fb_size);
673 	if (unlikely(par->vmalloc == NULL)) {
674 		ret = -ENOMEM;
675 		goto err_free;
676 	}
677 
678 	/*
679 	 * Fixed and var
680 	 */
681 	strcpy(info->fix.id, "svgadrmfb");
682 	info->fix.type = FB_TYPE_PACKED_PIXELS;
683 	info->fix.visual = FB_VISUAL_TRUECOLOR;
684 	info->fix.type_aux = 0;
685 	info->fix.xpanstep = 1; /* doing it in hw */
686 	info->fix.ypanstep = 1; /* doing it in hw */
687 	info->fix.ywrapstep = 0;
688 	info->fix.accel = FB_ACCEL_NONE;
689 	info->fix.line_length = fb_pitch;
690 
691 	info->fix.smem_start = 0;
692 	info->fix.smem_len = fb_size;
693 
694 	info->pseudo_palette = par->pseudo_palette;
695 	info->screen_base = (char __iomem *)par->vmalloc;
696 	info->screen_size = fb_size;
697 
698 	info->fbops = &vmw_fb_ops;
699 
700 	/* 24 depth per default */
701 	info->var.red.offset = 16;
702 	info->var.green.offset = 8;
703 	info->var.blue.offset = 0;
704 	info->var.red.length = 8;
705 	info->var.green.length = 8;
706 	info->var.blue.length = 8;
707 	info->var.transp.offset = 0;
708 	info->var.transp.length = 0;
709 
710 	info->var.xres_virtual = fb_width;
711 	info->var.yres_virtual = fb_height;
712 	info->var.bits_per_pixel = fb_bpp;
713 	info->var.xoffset = 0;
714 	info->var.yoffset = 0;
715 	info->var.activate = FB_ACTIVATE_NOW;
716 	info->var.height = -1;
717 	info->var.width = -1;
718 
719 	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
720 	info->apertures = alloc_apertures(1);
721 	if (!info->apertures) {
722 		ret = -ENOMEM;
723 		goto err_aper;
724 	}
725 	info->apertures->ranges[0].base = vmw_priv->vram_start;
726 	info->apertures->ranges[0].size = vmw_priv->vram_size;
727 
728 	/*
729 	 * Dirty & Deferred IO
730 	 */
731 	par->dirty.x1 = par->dirty.x2 = 0;
732 	par->dirty.y1 = par->dirty.y2 = 0;
733 	par->dirty.active = true;
734 	spin_lock_init(&par->dirty.lock);
735 	mutex_init(&par->bo_mutex);
736 	info->fbdefio = &vmw_defio;
737 	fb_deferred_io_init(info);
738 
739 	ret = register_framebuffer(info);
740 	if (unlikely(ret != 0))
741 		goto err_defio;
742 
743 	vmw_fb_set_par(info);
744 
745 	return 0;
746 
747 err_defio:
748 	fb_deferred_io_cleanup(info);
749 err_aper:
750 err_free:
751 	vfree(par->vmalloc);
752 err_kms:
753 	framebuffer_release(info);
754 	vmw_priv->fb_info = NULL;
755 
756 	return ret;
757 }
758 
vmw_fb_close(struct vmw_private * vmw_priv)759 int vmw_fb_close(struct vmw_private *vmw_priv)
760 {
761 	struct fb_info *info;
762 	struct vmw_fb_par *par;
763 
764 	if (!vmw_priv->fb_info)
765 		return 0;
766 
767 	info = vmw_priv->fb_info;
768 	par = info->par;
769 
770 	/* ??? order */
771 	fb_deferred_io_cleanup(info);
772 	cancel_delayed_work_sync(&par->local_work);
773 	unregister_framebuffer(info);
774 
775 	mutex_lock(&par->bo_mutex);
776 	(void) vmw_fb_kms_detach(par, true, true);
777 	mutex_unlock(&par->bo_mutex);
778 
779 	vfree(par->vmalloc);
780 	framebuffer_release(info);
781 
782 	return 0;
783 }
784 
vmw_fb_off(struct vmw_private * vmw_priv)785 int vmw_fb_off(struct vmw_private *vmw_priv)
786 {
787 	struct fb_info *info;
788 	struct vmw_fb_par *par;
789 	unsigned long flags;
790 
791 	if (!vmw_priv->fb_info)
792 		return -EINVAL;
793 
794 	info = vmw_priv->fb_info;
795 	par = info->par;
796 
797 	spin_lock_irqsave(&par->dirty.lock, flags);
798 	par->dirty.active = false;
799 	spin_unlock_irqrestore(&par->dirty.lock, flags);
800 
801 	flush_delayed_work(&info->deferred_work);
802 	flush_delayed_work(&par->local_work);
803 
804 	return 0;
805 }
806 
vmw_fb_on(struct vmw_private * vmw_priv)807 int vmw_fb_on(struct vmw_private *vmw_priv)
808 {
809 	struct fb_info *info;
810 	struct vmw_fb_par *par;
811 	unsigned long flags;
812 
813 	if (!vmw_priv->fb_info)
814 		return -EINVAL;
815 
816 	info = vmw_priv->fb_info;
817 	par = info->par;
818 
819 	spin_lock_irqsave(&par->dirty.lock, flags);
820 	par->dirty.active = true;
821 	spin_unlock_irqrestore(&par->dirty.lock, flags);
822 
823 	/*
824 	 * Need to reschedule a dirty update, because otherwise that's
825 	 * only done in dirty_mark() if the previous coalesced
826 	 * dirty region was empty.
827 	 */
828 	schedule_delayed_work(&par->local_work, 0);
829 
830 	return 0;
831 }
832