xref: /openbmc/linux/drivers/gpu/drm/qxl/qxl_display.c (revision d236d361)
1 /*
2  * Copyright 2013 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Dave Airlie
23  *          Alon Levy
24  */
25 
26 
27 #include <linux/crc32.h>
28 
29 #include "qxl_drv.h"
30 #include "qxl_object.h"
31 #include "drm_crtc_helper.h"
32 #include <drm/drm_plane_helper.h>
33 #include <drm/drm_atomic_helper.h>
34 #include <drm/drm_atomic.h>
35 
36 static bool qxl_head_enabled(struct qxl_head *head)
37 {
38 	return head->width && head->height;
39 }
40 
41 static void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count)
42 {
43 	if (qdev->client_monitors_config &&
44 	    count > qdev->client_monitors_config->count) {
45 		kfree(qdev->client_monitors_config);
46 		qdev->client_monitors_config = NULL;
47 	}
48 	if (!qdev->client_monitors_config) {
49 		qdev->client_monitors_config = kzalloc(
50 				sizeof(struct qxl_monitors_config) +
51 				sizeof(struct qxl_head) * count, GFP_KERNEL);
52 		if (!qdev->client_monitors_config) {
53 			qxl_io_log(qdev,
54 				   "%s: allocation failure for %u heads\n",
55 				   __func__, count);
56 			return;
57 		}
58 	}
59 	qdev->client_monitors_config->count = count;
60 }
61 
62 enum {
63 	MONITORS_CONFIG_MODIFIED,
64 	MONITORS_CONFIG_UNCHANGED,
65 	MONITORS_CONFIG_BAD_CRC,
66 };
67 
68 static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
69 {
70 	int i;
71 	int num_monitors;
72 	uint32_t crc;
73 	int status = MONITORS_CONFIG_UNCHANGED;
74 
75 	num_monitors = qdev->rom->client_monitors_config.count;
76 	crc = crc32(0, (const uint8_t *)&qdev->rom->client_monitors_config,
77 		  sizeof(qdev->rom->client_monitors_config));
78 	if (crc != qdev->rom->client_monitors_config_crc) {
79 		qxl_io_log(qdev, "crc mismatch: have %X (%zd) != %X\n", crc,
80 			   sizeof(qdev->rom->client_monitors_config),
81 			   qdev->rom->client_monitors_config_crc);
82 		return MONITORS_CONFIG_BAD_CRC;
83 	}
84 	if (!num_monitors) {
85 		DRM_DEBUG_KMS("no client monitors configured\n");
86 		return status;
87 	}
88 	if (num_monitors > qdev->monitors_config->max_allowed) {
89 		DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n",
90 			      qdev->monitors_config->max_allowed, num_monitors);
91 		num_monitors = qdev->monitors_config->max_allowed;
92 	} else {
93 		num_monitors = qdev->rom->client_monitors_config.count;
94 	}
95 	if (qdev->client_monitors_config
96 	      && (num_monitors != qdev->client_monitors_config->count)) {
97 		status = MONITORS_CONFIG_MODIFIED;
98 	}
99 	qxl_alloc_client_monitors_config(qdev, num_monitors);
100 	/* we copy max from the client but it isn't used */
101 	qdev->client_monitors_config->max_allowed =
102 				qdev->monitors_config->max_allowed;
103 	for (i = 0 ; i < qdev->client_monitors_config->count ; ++i) {
104 		struct qxl_urect *c_rect =
105 			&qdev->rom->client_monitors_config.heads[i];
106 		struct qxl_head *client_head =
107 			&qdev->client_monitors_config->heads[i];
108 		if (client_head->x != c_rect->left) {
109 			client_head->x = c_rect->left;
110 			status = MONITORS_CONFIG_MODIFIED;
111 		}
112 		if (client_head->y != c_rect->top) {
113 			client_head->y = c_rect->top;
114 			status = MONITORS_CONFIG_MODIFIED;
115 		}
116 		if (client_head->width != c_rect->right - c_rect->left) {
117 			client_head->width = c_rect->right - c_rect->left;
118 			status = MONITORS_CONFIG_MODIFIED;
119 		}
120 		if (client_head->height != c_rect->bottom - c_rect->top) {
121 			client_head->height = c_rect->bottom - c_rect->top;
122 			status = MONITORS_CONFIG_MODIFIED;
123 		}
124 		if (client_head->surface_id != 0) {
125 			client_head->surface_id = 0;
126 			status = MONITORS_CONFIG_MODIFIED;
127 		}
128 		if (client_head->id != i) {
129 			client_head->id = i;
130 			status = MONITORS_CONFIG_MODIFIED;
131 		}
132 		if (client_head->flags != 0) {
133 			client_head->flags = 0;
134 			status = MONITORS_CONFIG_MODIFIED;
135 		}
136 		DRM_DEBUG_KMS("read %dx%d+%d+%d\n", client_head->width, client_head->height,
137 			  client_head->x, client_head->y);
138 	}
139 
140 	return status;
141 }
142 
143 static void qxl_update_offset_props(struct qxl_device *qdev)
144 {
145 	struct drm_device *dev = &qdev->ddev;
146 	struct drm_connector *connector;
147 	struct qxl_output *output;
148 	struct qxl_head *head;
149 
150 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
151 		output = drm_connector_to_qxl_output(connector);
152 
153 		head = &qdev->client_monitors_config->heads[output->index];
154 
155 		drm_object_property_set_value(&connector->base,
156 			dev->mode_config.suggested_x_property, head->x);
157 		drm_object_property_set_value(&connector->base,
158 			dev->mode_config.suggested_y_property, head->y);
159 	}
160 }
161 
162 void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
163 {
164 	struct drm_device *dev = &qdev->ddev;
165 	int status, retries;
166 
167 	for (retries = 0; retries < 10; retries++) {
168 		status = qxl_display_copy_rom_client_monitors_config(qdev);
169 		if (status != MONITORS_CONFIG_BAD_CRC)
170 			break;
171 		udelay(5);
172 	}
173 	if (status == MONITORS_CONFIG_BAD_CRC) {
174 		qxl_io_log(qdev, "config: bad crc\n");
175 		DRM_DEBUG_KMS("ignoring client monitors config: bad crc");
176 		return;
177 	}
178 	if (status == MONITORS_CONFIG_UNCHANGED) {
179 		qxl_io_log(qdev, "config: unchanged\n");
180 		DRM_DEBUG_KMS("ignoring client monitors config: unchanged");
181 		return;
182 	}
183 
184 	drm_modeset_lock_all(dev);
185 	qxl_update_offset_props(qdev);
186 	drm_modeset_unlock_all(dev);
187 	if (!drm_helper_hpd_irq_event(dev)) {
188 		/* notify that the monitor configuration changed, to
189 		   adjust at the arbitrary resolution */
190 		drm_kms_helper_hotplug_event(dev);
191 	}
192 }
193 
194 static int qxl_add_monitors_config_modes(struct drm_connector *connector,
195                                          unsigned *pwidth,
196                                          unsigned *pheight)
197 {
198 	struct drm_device *dev = connector->dev;
199 	struct qxl_device *qdev = dev->dev_private;
200 	struct qxl_output *output = drm_connector_to_qxl_output(connector);
201 	int h = output->index;
202 	struct drm_display_mode *mode = NULL;
203 	struct qxl_head *head;
204 
205 	if (!qdev->monitors_config)
206 		return 0;
207 	if (h >= qdev->monitors_config->max_allowed)
208 		return 0;
209 	if (!qdev->client_monitors_config)
210 		return 0;
211 	if (h >= qdev->client_monitors_config->count)
212 		return 0;
213 
214 	head = &qdev->client_monitors_config->heads[h];
215 	DRM_DEBUG_KMS("head %d is %dx%d\n", h, head->width, head->height);
216 
217 	mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
218 			    false);
219 	mode->type |= DRM_MODE_TYPE_PREFERRED;
220 	mode->hdisplay = head->width;
221 	mode->vdisplay = head->height;
222 	drm_mode_set_name(mode);
223 	*pwidth = head->width;
224 	*pheight = head->height;
225 	drm_mode_probed_add(connector, mode);
226 	/* remember the last custom size for mode validation */
227 	qdev->monitors_config_width = mode->hdisplay;
228 	qdev->monitors_config_height = mode->vdisplay;
229 	return 1;
230 }
231 
232 static struct mode_size {
233 	int w;
234 	int h;
235 } common_modes[] = {
236 	{ 640,  480},
237 	{ 720,  480},
238 	{ 800,  600},
239 	{ 848,  480},
240 	{1024,  768},
241 	{1152,  768},
242 	{1280,  720},
243 	{1280,  800},
244 	{1280,  854},
245 	{1280,  960},
246 	{1280, 1024},
247 	{1440,  900},
248 	{1400, 1050},
249 	{1680, 1050},
250 	{1600, 1200},
251 	{1920, 1080},
252 	{1920, 1200}
253 };
254 
255 static int qxl_add_common_modes(struct drm_connector *connector,
256                                 unsigned pwidth,
257                                 unsigned pheight)
258 {
259 	struct drm_device *dev = connector->dev;
260 	struct drm_display_mode *mode = NULL;
261 	int i;
262 	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
263 		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
264 				    60, false, false, false);
265 		if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
266 			mode->type |= DRM_MODE_TYPE_PREFERRED;
267 		drm_mode_probed_add(connector, mode);
268 	}
269 	return i - 1;
270 }
271 
272 static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
273 				  struct drm_crtc_state *old_crtc_state)
274 {
275 	struct drm_device *dev = crtc->dev;
276 	struct drm_pending_vblank_event *event;
277 	unsigned long flags;
278 
279 	if (crtc->state && crtc->state->event) {
280 		event = crtc->state->event;
281 		crtc->state->event = NULL;
282 
283 		spin_lock_irqsave(&dev->event_lock, flags);
284 		drm_crtc_send_vblank_event(crtc, event);
285 		spin_unlock_irqrestore(&dev->event_lock, flags);
286 	}
287 }
288 
289 static void qxl_crtc_destroy(struct drm_crtc *crtc)
290 {
291 	struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
292 
293 	drm_crtc_cleanup(crtc);
294 	kfree(qxl_crtc);
295 }
296 
297 static const struct drm_crtc_funcs qxl_crtc_funcs = {
298 	.set_config = drm_atomic_helper_set_config,
299 	.destroy = qxl_crtc_destroy,
300 	.page_flip = drm_atomic_helper_page_flip,
301 	.reset = drm_atomic_helper_crtc_reset,
302 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
303 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
304 };
305 
306 void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
307 {
308 	struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
309 
310 	drm_gem_object_unreference_unlocked(qxl_fb->obj);
311 	drm_framebuffer_cleanup(fb);
312 	kfree(qxl_fb);
313 }
314 
315 static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
316 					 struct drm_file *file_priv,
317 					 unsigned flags, unsigned color,
318 					 struct drm_clip_rect *clips,
319 					 unsigned num_clips)
320 {
321 	/* TODO: vmwgfx where this was cribbed from had locking. Why? */
322 	struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
323 	struct qxl_device *qdev = qxl_fb->base.dev->dev_private;
324 	struct drm_clip_rect norect;
325 	struct qxl_bo *qobj;
326 	int inc = 1;
327 
328 	drm_modeset_lock_all(fb->dev);
329 
330 	qobj = gem_to_qxl_bo(qxl_fb->obj);
331 	/* if we aren't primary surface ignore this */
332 	if (!qobj->is_primary) {
333 		drm_modeset_unlock_all(fb->dev);
334 		return 0;
335 	}
336 
337 	if (!num_clips) {
338 		num_clips = 1;
339 		clips = &norect;
340 		norect.x1 = norect.y1 = 0;
341 		norect.x2 = fb->width;
342 		norect.y2 = fb->height;
343 	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
344 		num_clips /= 2;
345 		inc = 2; /* skip source rects */
346 	}
347 
348 	qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color,
349 			  clips, num_clips, inc);
350 
351 	drm_modeset_unlock_all(fb->dev);
352 
353 	return 0;
354 }
355 
356 static const struct drm_framebuffer_funcs qxl_fb_funcs = {
357 	.destroy = qxl_user_framebuffer_destroy,
358 	.dirty = qxl_framebuffer_surface_dirty,
359 /*	TODO?
360  *	.create_handle = qxl_user_framebuffer_create_handle, */
361 };
362 
363 int
364 qxl_framebuffer_init(struct drm_device *dev,
365 		     struct qxl_framebuffer *qfb,
366 		     const struct drm_mode_fb_cmd2 *mode_cmd,
367 		     struct drm_gem_object *obj,
368 		     const struct drm_framebuffer_funcs *funcs)
369 {
370 	int ret;
371 
372 	qfb->obj = obj;
373 	drm_helper_mode_fill_fb_struct(dev, &qfb->base, mode_cmd);
374 	ret = drm_framebuffer_init(dev, &qfb->base, funcs);
375 	if (ret) {
376 		qfb->obj = NULL;
377 		return ret;
378 	}
379 	return 0;
380 }
381 
382 static void qxl_crtc_dpms(struct drm_crtc *crtc, int mode)
383 {
384 }
385 
386 static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc,
387 				  const struct drm_display_mode *mode,
388 				  struct drm_display_mode *adjusted_mode)
389 {
390 	struct drm_device *dev = crtc->dev;
391 	struct qxl_device *qdev = dev->dev_private;
392 
393 	qxl_io_log(qdev, "%s: (%d,%d) => (%d,%d)\n",
394 		   __func__,
395 		   mode->hdisplay, mode->vdisplay,
396 		   adjusted_mode->hdisplay,
397 		   adjusted_mode->vdisplay);
398 	return true;
399 }
400 
401 static void
402 qxl_send_monitors_config(struct qxl_device *qdev)
403 {
404 	int i;
405 
406 	BUG_ON(!qdev->ram_header->monitors_config);
407 
408 	if (qdev->monitors_config->count == 0) {
409 		qxl_io_log(qdev, "%s: 0 monitors??\n", __func__);
410 		return;
411 	}
412 	for (i = 0 ; i < qdev->monitors_config->count ; ++i) {
413 		struct qxl_head *head = &qdev->monitors_config->heads[i];
414 
415 		if (head->y > 8192 || head->x > 8192 ||
416 		    head->width > 8192 || head->height > 8192) {
417 			DRM_ERROR("head %d wrong: %dx%d+%d+%d\n",
418 				  i, head->width, head->height,
419 				  head->x, head->y);
420 			return;
421 		}
422 	}
423 	qxl_io_monitors_config(qdev);
424 }
425 
426 static void qxl_monitors_config_set(struct qxl_device *qdev,
427 				    int index,
428 				    unsigned x, unsigned y,
429 				    unsigned width, unsigned height,
430 				    unsigned surf_id)
431 {
432 	DRM_DEBUG_KMS("%d:%dx%d+%d+%d\n", index, width, height, x, y);
433 	qdev->monitors_config->heads[index].x = x;
434 	qdev->monitors_config->heads[index].y = y;
435 	qdev->monitors_config->heads[index].width = width;
436 	qdev->monitors_config->heads[index].height = height;
437 	qdev->monitors_config->heads[index].surface_id = surf_id;
438 
439 }
440 
441 void qxl_mode_set_nofb(struct drm_crtc *crtc)
442 {
443 	struct qxl_device *qdev = crtc->dev->dev_private;
444 	struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
445 	struct drm_display_mode *mode = &crtc->mode;
446 
447 	DRM_DEBUG("Mode set (%d,%d)\n",
448 		  mode->hdisplay, mode->vdisplay);
449 
450 	qxl_monitors_config_set(qdev, qcrtc->index, 0, 0,
451 				mode->hdisplay,	mode->vdisplay, 0);
452 
453 }
454 
455 static void qxl_crtc_commit(struct drm_crtc *crtc)
456 {
457 	DRM_DEBUG("\n");
458 }
459 
460 static void qxl_crtc_disable(struct drm_crtc *crtc)
461 {
462 	struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
463 	struct qxl_device *qdev = crtc->dev->dev_private;
464 
465 	qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
466 
467 	qxl_send_monitors_config(qdev);
468 }
469 
470 static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
471 	.dpms = qxl_crtc_dpms,
472 	.disable = qxl_crtc_disable,
473 	.mode_fixup = qxl_crtc_mode_fixup,
474 	.mode_set_nofb = qxl_mode_set_nofb,
475 	.commit = qxl_crtc_commit,
476 	.atomic_flush = qxl_crtc_atomic_flush,
477 };
478 
479 int qxl_primary_atomic_check(struct drm_plane *plane,
480 			     struct drm_plane_state *state)
481 {
482 	struct qxl_device *qdev = plane->dev->dev_private;
483 	struct qxl_framebuffer *qfb;
484 	struct qxl_bo *bo;
485 
486 	if (!state->crtc || !state->fb)
487 		return 0;
488 
489 	qfb = to_qxl_framebuffer(state->fb);
490 	bo = gem_to_qxl_bo(qfb->obj);
491 
492 	if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
493 		DRM_ERROR("Mode doesn't fit in vram size (vgamem)");
494 		return -EINVAL;
495 	}
496 
497 	return 0;
498 }
499 
500 static void qxl_primary_atomic_update(struct drm_plane *plane,
501 				      struct drm_plane_state *old_state)
502 {
503 	struct qxl_device *qdev = plane->dev->dev_private;
504 	struct qxl_framebuffer *qfb =
505 		to_qxl_framebuffer(plane->state->fb);
506 	struct qxl_framebuffer *qfb_old;
507 	struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
508 	struct qxl_bo *bo_old;
509 	struct drm_clip_rect norect = {
510 	    .x1 = 0,
511 	    .y1 = 0,
512 	    .x2 = qfb->base.width,
513 	    .y2 = qfb->base.height
514 	};
515 
516 	if (!old_state->fb) {
517 		qxl_io_log(qdev,
518 			   "create primary fb: %dx%d,%d,%d\n",
519 			   bo->surf.width, bo->surf.height,
520 			   bo->surf.stride, bo->surf.format);
521 
522 		qxl_io_create_primary(qdev, 0, bo);
523 		bo->is_primary = true;
524 		return;
525 
526 	} else {
527 		qfb_old = to_qxl_framebuffer(old_state->fb);
528 		bo_old = gem_to_qxl_bo(qfb_old->obj);
529 		bo_old->is_primary = false;
530 	}
531 
532 	bo->is_primary = true;
533 	qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
534 }
535 
536 static void qxl_primary_atomic_disable(struct drm_plane *plane,
537 				       struct drm_plane_state *old_state)
538 {
539 	struct qxl_device *qdev = plane->dev->dev_private;
540 
541 	if (old_state->fb)
542 	{	struct qxl_framebuffer *qfb =
543 			to_qxl_framebuffer(old_state->fb);
544 		struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
545 
546 		qxl_io_destroy_primary(qdev);
547 		bo->is_primary = false;
548 	}
549 }
550 
551 int qxl_plane_atomic_check(struct drm_plane *plane,
552 			   struct drm_plane_state *state)
553 {
554 	return 0;
555 }
556 
557 static void qxl_cursor_atomic_update(struct drm_plane *plane,
558 				     struct drm_plane_state *old_state)
559 {
560 	struct drm_device *dev = plane->dev;
561 	struct qxl_device *qdev = dev->dev_private;
562 	struct drm_framebuffer *fb = plane->state->fb;
563 	struct qxl_release *release;
564 	struct qxl_cursor_cmd *cmd;
565 	struct qxl_cursor *cursor;
566 	struct drm_gem_object *obj;
567 	struct qxl_bo *cursor_bo, *user_bo = NULL;
568 	int ret;
569 	void *user_ptr;
570 	int size = 64*64*4;
571 
572 	ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
573 					 QXL_RELEASE_CURSOR_CMD,
574 					 &release, NULL);
575 	if (ret)
576 		return;
577 
578 	cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
579 
580 	if (fb != old_state->fb) {
581 		obj = to_qxl_framebuffer(fb)->obj;
582 		user_bo = gem_to_qxl_bo(obj);
583 
584 		/* pinning is done in the prepare/cleanup framevbuffer */
585 		ret = qxl_bo_kmap(user_bo, &user_ptr);
586 		if (ret)
587 			goto out_free_release;
588 
589 		ret = qxl_alloc_bo_reserved(qdev, release,
590 					    sizeof(struct qxl_cursor) + size,
591 					    &cursor_bo);
592 		if (ret)
593 			goto out_kunmap;
594 
595 		ret = qxl_release_reserve_list(release, true);
596 		if (ret)
597 			goto out_free_bo;
598 
599 		ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
600 		if (ret)
601 			goto out_backoff;
602 
603 		cursor->header.unique = 0;
604 		cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
605 		cursor->header.width = 64;
606 		cursor->header.height = 64;
607 		cursor->header.hot_spot_x = fb->hot_x;
608 		cursor->header.hot_spot_y = fb->hot_y;
609 		cursor->data_size = size;
610 		cursor->chunk.next_chunk = 0;
611 		cursor->chunk.prev_chunk = 0;
612 		cursor->chunk.data_size = size;
613 		memcpy(cursor->chunk.data, user_ptr, size);
614 		qxl_bo_kunmap(cursor_bo);
615 		qxl_bo_kunmap(user_bo);
616 
617 		cmd->u.set.visible = 1;
618 		cmd->u.set.shape = qxl_bo_physical_address(qdev,
619 							   cursor_bo, 0);
620 		cmd->type = QXL_CURSOR_SET;
621 	} else {
622 
623 		ret = qxl_release_reserve_list(release, true);
624 		if (ret)
625 			goto out_free_release;
626 
627 		cmd->type = QXL_CURSOR_MOVE;
628 	}
629 
630 	cmd->u.position.x = plane->state->crtc_x + fb->hot_x;
631 	cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
632 
633 	qxl_release_unmap(qdev, release, &cmd->release_info);
634 	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
635 	qxl_release_fence_buffer_objects(release);
636 
637 	return;
638 
639 out_backoff:
640 	qxl_release_backoff_reserve_list(release);
641 out_free_bo:
642 	qxl_bo_unref(&cursor_bo);
643 out_kunmap:
644 	qxl_bo_kunmap(user_bo);
645 out_free_release:
646 	qxl_release_free(qdev, release);
647 	return;
648 
649 }
650 
651 void qxl_cursor_atomic_disable(struct drm_plane *plane,
652 			       struct drm_plane_state *old_state)
653 {
654 	struct qxl_device *qdev = plane->dev->dev_private;
655 	struct qxl_release *release;
656 	struct qxl_cursor_cmd *cmd;
657 	int ret;
658 
659 	ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
660 					 QXL_RELEASE_CURSOR_CMD,
661 					 &release, NULL);
662 	if (ret)
663 		return;
664 
665 	ret = qxl_release_reserve_list(release, true);
666 	if (ret) {
667 		qxl_release_free(qdev, release);
668 		return;
669 	}
670 
671 	cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
672 	cmd->type = QXL_CURSOR_HIDE;
673 	qxl_release_unmap(qdev, release, &cmd->release_info);
674 
675 	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
676 	qxl_release_fence_buffer_objects(release);
677 }
678 
679 int qxl_plane_prepare_fb(struct drm_plane *plane,
680 			 struct drm_plane_state *new_state)
681 {
682 	struct drm_gem_object *obj;
683 	struct qxl_bo *user_bo;
684 	int ret;
685 
686 	if (!new_state->fb)
687 		return 0;
688 
689 	obj = to_qxl_framebuffer(new_state->fb)->obj;
690 	user_bo = gem_to_qxl_bo(obj);
691 
692 	ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
693 	if (ret)
694 		return ret;
695 
696 	return 0;
697 }
698 
699 static void qxl_plane_cleanup_fb(struct drm_plane *plane,
700 				 struct drm_plane_state *old_state)
701 {
702 	struct drm_gem_object *obj;
703 	struct qxl_bo *user_bo;
704 
705 	if (!plane->state->fb) {
706 		/* we never executed prepare_fb, so there's nothing to
707 		 * unpin.
708 		 */
709 		return;
710 	}
711 
712 	obj = to_qxl_framebuffer(plane->state->fb)->obj;
713 	user_bo = gem_to_qxl_bo(obj);
714 	qxl_bo_unpin(user_bo);
715 }
716 
717 static const uint32_t qxl_cursor_plane_formats[] = {
718 	DRM_FORMAT_ARGB8888,
719 };
720 
721 static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = {
722 	.atomic_check = qxl_plane_atomic_check,
723 	.atomic_update = qxl_cursor_atomic_update,
724 	.atomic_disable = qxl_cursor_atomic_disable,
725 	.prepare_fb = qxl_plane_prepare_fb,
726 	.cleanup_fb = qxl_plane_cleanup_fb,
727 };
728 
729 static const struct drm_plane_funcs qxl_cursor_plane_funcs = {
730 	.update_plane	= drm_atomic_helper_update_plane,
731 	.disable_plane	= drm_atomic_helper_disable_plane,
732 	.destroy	= drm_primary_helper_destroy,
733 	.reset		= drm_atomic_helper_plane_reset,
734 	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
735 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
736 };
737 
738 static const uint32_t qxl_primary_plane_formats[] = {
739 	DRM_FORMAT_XRGB8888,
740 	DRM_FORMAT_ARGB8888,
741 };
742 
743 static const struct drm_plane_helper_funcs primary_helper_funcs = {
744 	.atomic_check = qxl_primary_atomic_check,
745 	.atomic_update = qxl_primary_atomic_update,
746 	.atomic_disable = qxl_primary_atomic_disable,
747 	.prepare_fb = qxl_plane_prepare_fb,
748 	.cleanup_fb = qxl_plane_cleanup_fb,
749 };
750 
751 static const struct drm_plane_funcs qxl_primary_plane_funcs = {
752 	.update_plane	= drm_atomic_helper_update_plane,
753 	.disable_plane	= drm_atomic_helper_disable_plane,
754 	.destroy	= drm_primary_helper_destroy,
755 	.reset		= drm_atomic_helper_plane_reset,
756 	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
757 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
758 };
759 
760 static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
761 					  unsigned int possible_crtcs,
762 					  enum drm_plane_type type)
763 {
764 	const struct drm_plane_helper_funcs *helper_funcs = NULL;
765 	struct drm_plane *plane;
766 	const struct drm_plane_funcs *funcs;
767 	const uint32_t *formats;
768 	int num_formats;
769 	int err;
770 
771 	if (type == DRM_PLANE_TYPE_PRIMARY) {
772 		funcs = &qxl_primary_plane_funcs;
773 		formats = qxl_primary_plane_formats;
774 		num_formats = ARRAY_SIZE(qxl_primary_plane_formats);
775 		helper_funcs = &primary_helper_funcs;
776 	} else if (type == DRM_PLANE_TYPE_CURSOR) {
777 		funcs = &qxl_cursor_plane_funcs;
778 		formats = qxl_cursor_plane_formats;
779 		helper_funcs = &qxl_cursor_helper_funcs;
780 		num_formats = ARRAY_SIZE(qxl_cursor_plane_formats);
781 	} else {
782 		return ERR_PTR(-EINVAL);
783 	}
784 
785 	plane = kzalloc(sizeof(*plane), GFP_KERNEL);
786 	if (!plane)
787 		return ERR_PTR(-ENOMEM);
788 
789 	err = drm_universal_plane_init(&qdev->ddev, plane, possible_crtcs,
790 				       funcs, formats, num_formats,
791 				       type, NULL);
792 	if (err)
793 		goto free_plane;
794 
795 	drm_plane_helper_add(plane, helper_funcs);
796 
797 	return plane;
798 
799 free_plane:
800 	kfree(plane);
801 	return ERR_PTR(-EINVAL);
802 }
803 
804 static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
805 {
806 	struct qxl_crtc *qxl_crtc;
807 	struct drm_plane *primary, *cursor;
808 	struct qxl_device *qdev = dev->dev_private;
809 	int r;
810 
811 	qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL);
812 	if (!qxl_crtc)
813 		return -ENOMEM;
814 
815 	primary = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_PRIMARY);
816 	if (IS_ERR(primary)) {
817 		r = -ENOMEM;
818 		goto free_mem;
819 	}
820 
821 	cursor = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_CURSOR);
822 	if (IS_ERR(cursor)) {
823 		r = -ENOMEM;
824 		goto clean_primary;
825 	}
826 
827 	r = drm_crtc_init_with_planes(dev, &qxl_crtc->base, primary, cursor,
828 				      &qxl_crtc_funcs, NULL);
829 	if (r)
830 		goto clean_cursor;
831 
832 	qxl_crtc->index = crtc_id;
833 	drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
834 	return 0;
835 
836 clean_cursor:
837 	drm_plane_cleanup(cursor);
838 	kfree(cursor);
839 clean_primary:
840 	drm_plane_cleanup(primary);
841 	kfree(primary);
842 free_mem:
843 	kfree(qxl_crtc);
844 	return r;
845 }
846 
847 static void qxl_enc_dpms(struct drm_encoder *encoder, int mode)
848 {
849 	DRM_DEBUG("\n");
850 }
851 
852 static void qxl_enc_prepare(struct drm_encoder *encoder)
853 {
854 	DRM_DEBUG("\n");
855 }
856 
857 static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev,
858 		struct drm_encoder *encoder)
859 {
860 	int i;
861 	struct qxl_output *output = drm_encoder_to_qxl_output(encoder);
862 	struct qxl_head *head;
863 	struct drm_display_mode *mode;
864 
865 	BUG_ON(!encoder);
866 	/* TODO: ugly, do better */
867 	i = output->index;
868 	if (!qdev->monitors_config ||
869 	    qdev->monitors_config->max_allowed <= i) {
870 		DRM_ERROR(
871 		"head number too large or missing monitors config: %p, %d",
872 		qdev->monitors_config,
873 		qdev->monitors_config ?
874 			qdev->monitors_config->max_allowed : -1);
875 		return;
876 	}
877 	if (!encoder->crtc) {
878 		DRM_ERROR("missing crtc on encoder %p\n", encoder);
879 		return;
880 	}
881 	if (i != 0)
882 		DRM_DEBUG("missing for multiple monitors: no head holes\n");
883 	head = &qdev->monitors_config->heads[i];
884 	head->id = i;
885 	if (encoder->crtc->enabled) {
886 		mode = &encoder->crtc->mode;
887 		head->width = mode->hdisplay;
888 		head->height = mode->vdisplay;
889 		head->x = encoder->crtc->x;
890 		head->y = encoder->crtc->y;
891 		if (qdev->monitors_config->count < i + 1)
892 			qdev->monitors_config->count = i + 1;
893 	} else {
894 		head->width = 0;
895 		head->height = 0;
896 		head->x = 0;
897 		head->y = 0;
898 	}
899 	DRM_DEBUG_KMS("setting head %d to +%d+%d %dx%d out of %d\n",
900 		      i, head->x, head->y, head->width, head->height, qdev->monitors_config->count);
901 	head->flags = 0;
902 	/* TODO - somewhere else to call this for multiple monitors
903 	 * (config_commit?) */
904 	qxl_send_monitors_config(qdev);
905 }
906 
907 static void qxl_enc_commit(struct drm_encoder *encoder)
908 {
909 	struct qxl_device *qdev = encoder->dev->dev_private;
910 
911 	qxl_write_monitors_config_for_encoder(qdev, encoder);
912 	DRM_DEBUG("\n");
913 }
914 
915 static void qxl_enc_mode_set(struct drm_encoder *encoder,
916 				struct drm_display_mode *mode,
917 				struct drm_display_mode *adjusted_mode)
918 {
919 	DRM_DEBUG("\n");
920 }
921 
922 static int qxl_conn_get_modes(struct drm_connector *connector)
923 {
924 	unsigned pwidth = 1024;
925 	unsigned pheight = 768;
926 	int ret = 0;
927 
928 	ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
929 	if (ret < 0)
930 		return ret;
931 	ret += qxl_add_common_modes(connector, pwidth, pheight);
932 	return ret;
933 }
934 
935 static int qxl_conn_mode_valid(struct drm_connector *connector,
936 			       struct drm_display_mode *mode)
937 {
938 	struct drm_device *ddev = connector->dev;
939 	struct qxl_device *qdev = ddev->dev_private;
940 	int i;
941 
942 	/* TODO: is this called for user defined modes? (xrandr --add-mode)
943 	 * TODO: check that the mode fits in the framebuffer */
944 
945 	if(qdev->monitors_config_width == mode->hdisplay &&
946 	   qdev->monitors_config_height == mode->vdisplay)
947 		return MODE_OK;
948 
949 	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
950 		if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay)
951 			return MODE_OK;
952 	}
953 	return MODE_BAD;
954 }
955 
956 static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
957 {
958 	struct qxl_output *qxl_output =
959 		drm_connector_to_qxl_output(connector);
960 
961 	DRM_DEBUG("\n");
962 	return &qxl_output->enc;
963 }
964 
965 
966 static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs = {
967 	.dpms = qxl_enc_dpms,
968 	.prepare = qxl_enc_prepare,
969 	.mode_set = qxl_enc_mode_set,
970 	.commit = qxl_enc_commit,
971 };
972 
973 static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = {
974 	.get_modes = qxl_conn_get_modes,
975 	.mode_valid = qxl_conn_mode_valid,
976 	.best_encoder = qxl_best_encoder,
977 };
978 
979 static enum drm_connector_status qxl_conn_detect(
980 			struct drm_connector *connector,
981 			bool force)
982 {
983 	struct qxl_output *output =
984 		drm_connector_to_qxl_output(connector);
985 	struct drm_device *ddev = connector->dev;
986 	struct qxl_device *qdev = ddev->dev_private;
987 	bool connected = false;
988 
989 	/* The first monitor is always connected */
990 	if (!qdev->client_monitors_config) {
991 		if (output->index == 0)
992 			connected = true;
993 	} else
994 		connected = qdev->client_monitors_config->count > output->index &&
995 		     qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]);
996 
997 	DRM_DEBUG("#%d connected: %d\n", output->index, connected);
998 	if (!connected)
999 		qxl_monitors_config_set(qdev, output->index, 0, 0, 0, 0, 0);
1000 
1001 	return connected ? connector_status_connected
1002 			 : connector_status_disconnected;
1003 }
1004 
1005 static int qxl_conn_set_property(struct drm_connector *connector,
1006 				   struct drm_property *property,
1007 				   uint64_t value)
1008 {
1009 	DRM_DEBUG("\n");
1010 	return 0;
1011 }
1012 
1013 static void qxl_conn_destroy(struct drm_connector *connector)
1014 {
1015 	struct qxl_output *qxl_output =
1016 		drm_connector_to_qxl_output(connector);
1017 
1018 	drm_connector_unregister(connector);
1019 	drm_connector_cleanup(connector);
1020 	kfree(qxl_output);
1021 }
1022 
1023 static const struct drm_connector_funcs qxl_connector_funcs = {
1024 	.dpms = drm_helper_connector_dpms,
1025 	.detect = qxl_conn_detect,
1026 	.fill_modes = drm_helper_probe_single_connector_modes,
1027 	.set_property = qxl_conn_set_property,
1028 	.destroy = qxl_conn_destroy,
1029 	.reset = drm_atomic_helper_connector_reset,
1030 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1031 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1032 };
1033 
1034 static void qxl_enc_destroy(struct drm_encoder *encoder)
1035 {
1036 	drm_encoder_cleanup(encoder);
1037 }
1038 
1039 static const struct drm_encoder_funcs qxl_enc_funcs = {
1040 	.destroy = qxl_enc_destroy,
1041 };
1042 
1043 static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev)
1044 {
1045 	if (qdev->hotplug_mode_update_property)
1046 		return 0;
1047 
1048 	qdev->hotplug_mode_update_property =
1049 		drm_property_create_range(&qdev->ddev, DRM_MODE_PROP_IMMUTABLE,
1050 					  "hotplug_mode_update", 0, 1);
1051 
1052 	return 0;
1053 }
1054 
1055 static int qdev_output_init(struct drm_device *dev, int num_output)
1056 {
1057 	struct qxl_device *qdev = dev->dev_private;
1058 	struct qxl_output *qxl_output;
1059 	struct drm_connector *connector;
1060 	struct drm_encoder *encoder;
1061 
1062 	qxl_output = kzalloc(sizeof(struct qxl_output), GFP_KERNEL);
1063 	if (!qxl_output)
1064 		return -ENOMEM;
1065 
1066 	qxl_output->index = num_output;
1067 
1068 	connector = &qxl_output->base;
1069 	encoder = &qxl_output->enc;
1070 	drm_connector_init(dev, &qxl_output->base,
1071 			   &qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
1072 
1073 	drm_encoder_init(dev, &qxl_output->enc, &qxl_enc_funcs,
1074 			 DRM_MODE_ENCODER_VIRTUAL, NULL);
1075 
1076 	/* we get HPD via client monitors config */
1077 	connector->polled = DRM_CONNECTOR_POLL_HPD;
1078 	encoder->possible_crtcs = 1 << num_output;
1079 	drm_mode_connector_attach_encoder(&qxl_output->base,
1080 					  &qxl_output->enc);
1081 	drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs);
1082 	drm_connector_helper_add(connector, &qxl_connector_helper_funcs);
1083 
1084 	drm_object_attach_property(&connector->base,
1085 				   qdev->hotplug_mode_update_property, 0);
1086 	drm_object_attach_property(&connector->base,
1087 				   dev->mode_config.suggested_x_property, 0);
1088 	drm_object_attach_property(&connector->base,
1089 				   dev->mode_config.suggested_y_property, 0);
1090 	return 0;
1091 }
1092 
1093 static struct drm_framebuffer *
1094 qxl_user_framebuffer_create(struct drm_device *dev,
1095 			    struct drm_file *file_priv,
1096 			    const struct drm_mode_fb_cmd2 *mode_cmd)
1097 {
1098 	struct drm_gem_object *obj;
1099 	struct qxl_framebuffer *qxl_fb;
1100 	int ret;
1101 
1102 	obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
1103 	if (!obj)
1104 		return NULL;
1105 
1106 	qxl_fb = kzalloc(sizeof(*qxl_fb), GFP_KERNEL);
1107 	if (qxl_fb == NULL)
1108 		return NULL;
1109 
1110 	ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs);
1111 	if (ret) {
1112 		kfree(qxl_fb);
1113 		drm_gem_object_unreference_unlocked(obj);
1114 		return NULL;
1115 	}
1116 
1117 	return &qxl_fb->base;
1118 }
1119 
1120 static const struct drm_mode_config_funcs qxl_mode_funcs = {
1121 	.fb_create = qxl_user_framebuffer_create,
1122 	.atomic_check = drm_atomic_helper_check,
1123 	.atomic_commit = drm_atomic_helper_commit,
1124 };
1125 
1126 int qxl_create_monitors_object(struct qxl_device *qdev)
1127 {
1128 	int ret;
1129 	struct drm_gem_object *gobj;
1130 	int max_allowed = qxl_num_crtc;
1131 	int monitors_config_size = sizeof(struct qxl_monitors_config) +
1132 		max_allowed * sizeof(struct qxl_head);
1133 
1134 	ret = qxl_gem_object_create(qdev, monitors_config_size, 0,
1135 				    QXL_GEM_DOMAIN_VRAM,
1136 				    false, false, NULL, &gobj);
1137 	if (ret) {
1138 		DRM_ERROR("%s: failed to create gem ret=%d\n", __func__, ret);
1139 		return -ENOMEM;
1140 	}
1141 	qdev->monitors_config_bo = gem_to_qxl_bo(gobj);
1142 
1143 	ret = qxl_bo_pin(qdev->monitors_config_bo, QXL_GEM_DOMAIN_VRAM, NULL);
1144 	if (ret)
1145 		return ret;
1146 
1147 	qxl_bo_kmap(qdev->monitors_config_bo, NULL);
1148 
1149 	qdev->monitors_config = qdev->monitors_config_bo->kptr;
1150 	qdev->ram_header->monitors_config =
1151 		qxl_bo_physical_address(qdev, qdev->monitors_config_bo, 0);
1152 
1153 	memset(qdev->monitors_config, 0, monitors_config_size);
1154 	qdev->monitors_config->max_allowed = max_allowed;
1155 	return 0;
1156 }
1157 
1158 int qxl_destroy_monitors_object(struct qxl_device *qdev)
1159 {
1160 	int ret;
1161 
1162 	qdev->monitors_config = NULL;
1163 	qdev->ram_header->monitors_config = 0;
1164 
1165 	qxl_bo_kunmap(qdev->monitors_config_bo);
1166 	ret = qxl_bo_unpin(qdev->monitors_config_bo);
1167 	if (ret)
1168 		return ret;
1169 
1170 	qxl_bo_unref(&qdev->monitors_config_bo);
1171 	return 0;
1172 }
1173 
1174 int qxl_modeset_init(struct qxl_device *qdev)
1175 {
1176 	int i;
1177 	int ret;
1178 
1179 	drm_mode_config_init(&qdev->ddev);
1180 
1181 	ret = qxl_create_monitors_object(qdev);
1182 	if (ret)
1183 		return ret;
1184 
1185 	qdev->ddev.mode_config.funcs = (void *)&qxl_mode_funcs;
1186 
1187 	/* modes will be validated against the framebuffer size */
1188 	qdev->ddev.mode_config.min_width = 0;
1189 	qdev->ddev.mode_config.min_height = 0;
1190 	qdev->ddev.mode_config.max_width = 8192;
1191 	qdev->ddev.mode_config.max_height = 8192;
1192 
1193 	qdev->ddev.mode_config.fb_base = qdev->vram_base;
1194 
1195 	drm_mode_create_suggested_offset_properties(&qdev->ddev);
1196 	qxl_mode_create_hotplug_mode_update_property(qdev);
1197 
1198 	for (i = 0 ; i < qxl_num_crtc; ++i) {
1199 		qdev_crtc_init(&qdev->ddev, i);
1200 		qdev_output_init(&qdev->ddev, i);
1201 	}
1202 
1203 	qxl_display_read_client_monitors_config(qdev);
1204 	qdev->mode_info.mode_config_initialized = true;
1205 
1206 	drm_mode_config_reset(&qdev->ddev);
1207 
1208 	/* primary surface must be created by this point, to allow
1209 	 * issuing command queue commands and having them read by
1210 	 * spice server. */
1211 	qxl_fbdev_init(qdev);
1212 	return 0;
1213 }
1214 
1215 void qxl_modeset_fini(struct qxl_device *qdev)
1216 {
1217 	qxl_fbdev_fini(qdev);
1218 
1219 	qxl_destroy_monitors_object(qdev);
1220 	if (qdev->mode_info.mode_config_initialized) {
1221 		drm_mode_config_cleanup(&qdev->ddev);
1222 		qdev->mode_info.mode_config_initialized = false;
1223 	}
1224 }
1225