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