| .. | .. |
|---|
| 25 | 25 | * |
|---|
| 26 | 26 | **************************************************************************/ |
|---|
| 27 | 27 | |
|---|
| 28 | | -#include "vmwgfx_kms.h" |
|---|
| 29 | | -#include <drm/drm_plane_helper.h> |
|---|
| 30 | 28 | #include <drm/drm_atomic.h> |
|---|
| 31 | 29 | #include <drm/drm_atomic_helper.h> |
|---|
| 30 | +#include <drm/drm_damage_helper.h> |
|---|
| 31 | +#include <drm/drm_fourcc.h> |
|---|
| 32 | +#include <drm/drm_plane_helper.h> |
|---|
| 33 | +#include <drm/drm_vblank.h> |
|---|
| 32 | 34 | |
|---|
| 35 | +#include "vmwgfx_kms.h" |
|---|
| 33 | 36 | |
|---|
| 34 | 37 | #define vmw_crtc_to_sou(x) \ |
|---|
| 35 | 38 | container_of(x, struct vmw_screen_object_unit, base.crtc) |
|---|
| .. | .. |
|---|
| 74 | 77 | struct vmw_kms_sou_dirty_cmd { |
|---|
| 75 | 78 | SVGA3dCmdHeader header; |
|---|
| 76 | 79 | SVGA3dCmdBlitSurfaceToScreen body; |
|---|
| 80 | +}; |
|---|
| 81 | + |
|---|
| 82 | +struct vmw_kms_sou_define_gmrfb { |
|---|
| 83 | + uint32_t header; |
|---|
| 84 | + SVGAFifoCmdDefineGMRFB body; |
|---|
| 77 | 85 | }; |
|---|
| 78 | 86 | |
|---|
| 79 | 87 | /** |
|---|
| .. | .. |
|---|
| 124 | 132 | BUG_ON(!sou->buffer); |
|---|
| 125 | 133 | |
|---|
| 126 | 134 | fifo_size = sizeof(*cmd); |
|---|
| 127 | | - cmd = vmw_fifo_reserve(dev_priv, fifo_size); |
|---|
| 128 | | - /* The hardware has hung, nothing we can do about it here. */ |
|---|
| 129 | | - if (unlikely(cmd == NULL)) { |
|---|
| 130 | | - DRM_ERROR("Fifo reserve failed.\n"); |
|---|
| 135 | + cmd = VMW_FIFO_RESERVE(dev_priv, fifo_size); |
|---|
| 136 | + if (unlikely(cmd == NULL)) |
|---|
| 131 | 137 | return -ENOMEM; |
|---|
| 132 | | - } |
|---|
| 133 | 138 | |
|---|
| 134 | 139 | memset(cmd, 0, fifo_size); |
|---|
| 135 | 140 | cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN; |
|---|
| .. | .. |
|---|
| 176 | 181 | return 0; |
|---|
| 177 | 182 | |
|---|
| 178 | 183 | fifo_size = sizeof(*cmd); |
|---|
| 179 | | - cmd = vmw_fifo_reserve(dev_priv, fifo_size); |
|---|
| 180 | | - /* the hardware has hung, nothing we can do about it here */ |
|---|
| 181 | | - if (unlikely(cmd == NULL)) { |
|---|
| 182 | | - DRM_ERROR("Fifo reserve failed.\n"); |
|---|
| 184 | + cmd = VMW_FIFO_RESERVE(dev_priv, fifo_size); |
|---|
| 185 | + if (unlikely(cmd == NULL)) |
|---|
| 183 | 186 | return -ENOMEM; |
|---|
| 184 | | - } |
|---|
| 185 | 187 | |
|---|
| 186 | 188 | memset(cmd, 0, fifo_size); |
|---|
| 187 | 189 | cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN; |
|---|
| .. | .. |
|---|
| 241 | 243 | sou->buffer = vps->bo; |
|---|
| 242 | 244 | sou->buffer_size = vps->bo_size; |
|---|
| 243 | 245 | |
|---|
| 244 | | - if (sou->base.is_implicit) { |
|---|
| 245 | | - x = crtc->x; |
|---|
| 246 | | - y = crtc->y; |
|---|
| 247 | | - } else { |
|---|
| 248 | | - conn_state = sou->base.connector.state; |
|---|
| 249 | | - vmw_conn_state = vmw_connector_state_to_vcs(conn_state); |
|---|
| 246 | + conn_state = sou->base.connector.state; |
|---|
| 247 | + vmw_conn_state = vmw_connector_state_to_vcs(conn_state); |
|---|
| 250 | 248 | |
|---|
| 251 | | - x = vmw_conn_state->gui_x; |
|---|
| 252 | | - y = vmw_conn_state->gui_y; |
|---|
| 253 | | - } |
|---|
| 249 | + x = vmw_conn_state->gui_x; |
|---|
| 250 | + y = vmw_conn_state->gui_y; |
|---|
| 254 | 251 | |
|---|
| 255 | 252 | ret = vmw_sou_fifo_create(dev_priv, sou, x, y, &crtc->mode); |
|---|
| 256 | 253 | if (ret) |
|---|
| 257 | 254 | DRM_ERROR("Failed to define Screen Object %dx%d\n", |
|---|
| 258 | 255 | crtc->x, crtc->y); |
|---|
| 259 | 256 | |
|---|
| 260 | | - vmw_kms_add_active(dev_priv, &sou->base, vfb); |
|---|
| 261 | 257 | } else { |
|---|
| 262 | 258 | sou->buffer = NULL; |
|---|
| 263 | 259 | sou->buffer_size = 0; |
|---|
| 264 | | - |
|---|
| 265 | | - vmw_kms_del_active(dev_priv, &sou->base); |
|---|
| 266 | 260 | } |
|---|
| 267 | 261 | } |
|---|
| 268 | 262 | |
|---|
| .. | .. |
|---|
| 317 | 311 | } |
|---|
| 318 | 312 | } |
|---|
| 319 | 313 | |
|---|
| 320 | | -static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, |
|---|
| 321 | | - struct drm_framebuffer *new_fb, |
|---|
| 322 | | - struct drm_pending_vblank_event *event, |
|---|
| 323 | | - uint32_t flags, |
|---|
| 324 | | - struct drm_modeset_acquire_ctx *ctx) |
|---|
| 325 | | -{ |
|---|
| 326 | | - struct vmw_private *dev_priv = vmw_priv(crtc->dev); |
|---|
| 327 | | - int ret; |
|---|
| 328 | | - |
|---|
| 329 | | - if (!vmw_kms_crtc_flippable(dev_priv, crtc)) |
|---|
| 330 | | - return -EINVAL; |
|---|
| 331 | | - |
|---|
| 332 | | - ret = drm_atomic_helper_page_flip(crtc, new_fb, event, flags, ctx); |
|---|
| 333 | | - if (ret) { |
|---|
| 334 | | - DRM_ERROR("Page flip error %d.\n", ret); |
|---|
| 335 | | - return ret; |
|---|
| 336 | | - } |
|---|
| 337 | | - |
|---|
| 338 | | - if (vmw_crtc_to_du(crtc)->is_implicit) |
|---|
| 339 | | - vmw_kms_update_implicit_fb(dev_priv, crtc); |
|---|
| 340 | | - |
|---|
| 341 | | - return ret; |
|---|
| 342 | | -} |
|---|
| 343 | | - |
|---|
| 344 | 314 | static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { |
|---|
| 345 | 315 | .gamma_set = vmw_du_crtc_gamma_set, |
|---|
| 346 | 316 | .destroy = vmw_sou_crtc_destroy, |
|---|
| 347 | 317 | .reset = vmw_du_crtc_reset, |
|---|
| 348 | 318 | .atomic_duplicate_state = vmw_du_crtc_duplicate_state, |
|---|
| 349 | 319 | .atomic_destroy_state = vmw_du_crtc_destroy_state, |
|---|
| 350 | | - .set_config = vmw_kms_set_config, |
|---|
| 351 | | - .page_flip = vmw_sou_crtc_page_flip, |
|---|
| 320 | + .set_config = drm_atomic_helper_set_config, |
|---|
| 321 | + .page_flip = drm_atomic_helper_page_flip, |
|---|
| 322 | + .get_vblank_counter = vmw_get_vblank_counter, |
|---|
| 323 | + .enable_vblank = vmw_enable_vblank, |
|---|
| 324 | + .disable_vblank = vmw_disable_vblank, |
|---|
| 352 | 325 | }; |
|---|
| 353 | 326 | |
|---|
| 354 | 327 | /* |
|---|
| .. | .. |
|---|
| 377 | 350 | .dpms = vmw_du_connector_dpms, |
|---|
| 378 | 351 | .detect = vmw_du_connector_detect, |
|---|
| 379 | 352 | .fill_modes = vmw_du_connector_fill_modes, |
|---|
| 380 | | - .set_property = vmw_du_connector_set_property, |
|---|
| 381 | 353 | .destroy = vmw_sou_connector_destroy, |
|---|
| 382 | 354 | .reset = vmw_du_connector_reset, |
|---|
| 383 | 355 | .atomic_duplicate_state = vmw_du_connector_duplicate_state, |
|---|
| 384 | 356 | .atomic_destroy_state = vmw_du_connector_destroy_state, |
|---|
| 385 | | - .atomic_set_property = vmw_du_connector_atomic_set_property, |
|---|
| 386 | | - .atomic_get_property = vmw_du_connector_atomic_get_property, |
|---|
| 387 | 357 | }; |
|---|
| 388 | 358 | |
|---|
| 389 | 359 | |
|---|
| 390 | 360 | static const struct |
|---|
| 391 | 361 | drm_connector_helper_funcs vmw_sou_connector_helper_funcs = { |
|---|
| 392 | | - .best_encoder = drm_atomic_helper_best_encoder, |
|---|
| 393 | 362 | }; |
|---|
| 394 | 363 | |
|---|
| 395 | 364 | |
|---|
| .. | .. |
|---|
| 499 | 468 | return vmw_bo_pin_in_vram(dev_priv, vps->bo, true); |
|---|
| 500 | 469 | } |
|---|
| 501 | 470 | |
|---|
| 471 | +static uint32_t vmw_sou_bo_fifo_size(struct vmw_du_update_plane *update, |
|---|
| 472 | + uint32_t num_hits) |
|---|
| 473 | +{ |
|---|
| 474 | + return sizeof(struct vmw_kms_sou_define_gmrfb) + |
|---|
| 475 | + sizeof(struct vmw_kms_sou_bo_blit) * num_hits; |
|---|
| 476 | +} |
|---|
| 477 | + |
|---|
| 478 | +static uint32_t vmw_sou_bo_define_gmrfb(struct vmw_du_update_plane *update, |
|---|
| 479 | + void *cmd) |
|---|
| 480 | +{ |
|---|
| 481 | + struct vmw_framebuffer_bo *vfbbo = |
|---|
| 482 | + container_of(update->vfb, typeof(*vfbbo), base); |
|---|
| 483 | + struct vmw_kms_sou_define_gmrfb *gmr = cmd; |
|---|
| 484 | + int depth = update->vfb->base.format->depth; |
|---|
| 485 | + |
|---|
| 486 | + /* Emulate RGBA support, contrary to svga_reg.h this is not |
|---|
| 487 | + * supported by hosts. This is only a problem if we are reading |
|---|
| 488 | + * this value later and expecting what we uploaded back. |
|---|
| 489 | + */ |
|---|
| 490 | + if (depth == 32) |
|---|
| 491 | + depth = 24; |
|---|
| 492 | + |
|---|
| 493 | + gmr->header = SVGA_CMD_DEFINE_GMRFB; |
|---|
| 494 | + |
|---|
| 495 | + gmr->body.format.bitsPerPixel = update->vfb->base.format->cpp[0] * 8; |
|---|
| 496 | + gmr->body.format.colorDepth = depth; |
|---|
| 497 | + gmr->body.format.reserved = 0; |
|---|
| 498 | + gmr->body.bytesPerLine = update->vfb->base.pitches[0]; |
|---|
| 499 | + vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &gmr->body.ptr); |
|---|
| 500 | + |
|---|
| 501 | + return sizeof(*gmr); |
|---|
| 502 | +} |
|---|
| 503 | + |
|---|
| 504 | +static uint32_t vmw_sou_bo_populate_clip(struct vmw_du_update_plane *update, |
|---|
| 505 | + void *cmd, struct drm_rect *clip, |
|---|
| 506 | + uint32_t fb_x, uint32_t fb_y) |
|---|
| 507 | +{ |
|---|
| 508 | + struct vmw_kms_sou_bo_blit *blit = cmd; |
|---|
| 509 | + |
|---|
| 510 | + blit->header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN; |
|---|
| 511 | + blit->body.destScreenId = update->du->unit; |
|---|
| 512 | + blit->body.srcOrigin.x = fb_x; |
|---|
| 513 | + blit->body.srcOrigin.y = fb_y; |
|---|
| 514 | + blit->body.destRect.left = clip->x1; |
|---|
| 515 | + blit->body.destRect.top = clip->y1; |
|---|
| 516 | + blit->body.destRect.right = clip->x2; |
|---|
| 517 | + blit->body.destRect.bottom = clip->y2; |
|---|
| 518 | + |
|---|
| 519 | + return sizeof(*blit); |
|---|
| 520 | +} |
|---|
| 521 | + |
|---|
| 522 | +static uint32_t vmw_stud_bo_post_clip(struct vmw_du_update_plane *update, |
|---|
| 523 | + void *cmd, struct drm_rect *bb) |
|---|
| 524 | +{ |
|---|
| 525 | + return 0; |
|---|
| 526 | +} |
|---|
| 527 | + |
|---|
| 528 | +/** |
|---|
| 529 | + * vmw_sou_plane_update_bo - Update display unit for bo backed fb. |
|---|
| 530 | + * @dev_priv: Device private. |
|---|
| 531 | + * @plane: Plane state. |
|---|
| 532 | + * @old_state: Old plane state. |
|---|
| 533 | + * @vfb: Framebuffer which is blitted to display unit. |
|---|
| 534 | + * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. |
|---|
| 535 | + * The returned fence pointer may be NULL in which case the device |
|---|
| 536 | + * has already synchronized. |
|---|
| 537 | + * |
|---|
| 538 | + * Return: 0 on success or a negative error code on failure. |
|---|
| 539 | + */ |
|---|
| 540 | +static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv, |
|---|
| 541 | + struct drm_plane *plane, |
|---|
| 542 | + struct drm_plane_state *old_state, |
|---|
| 543 | + struct vmw_framebuffer *vfb, |
|---|
| 544 | + struct vmw_fence_obj **out_fence) |
|---|
| 545 | +{ |
|---|
| 546 | + struct vmw_du_update_plane_buffer bo_update; |
|---|
| 547 | + |
|---|
| 548 | + memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer)); |
|---|
| 549 | + bo_update.base.plane = plane; |
|---|
| 550 | + bo_update.base.old_state = old_state; |
|---|
| 551 | + bo_update.base.dev_priv = dev_priv; |
|---|
| 552 | + bo_update.base.du = vmw_crtc_to_du(plane->state->crtc); |
|---|
| 553 | + bo_update.base.vfb = vfb; |
|---|
| 554 | + bo_update.base.out_fence = out_fence; |
|---|
| 555 | + bo_update.base.mutex = NULL; |
|---|
| 556 | + bo_update.base.cpu_blit = false; |
|---|
| 557 | + bo_update.base.intr = true; |
|---|
| 558 | + |
|---|
| 559 | + bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size; |
|---|
| 560 | + bo_update.base.post_prepare = vmw_sou_bo_define_gmrfb; |
|---|
| 561 | + bo_update.base.clip = vmw_sou_bo_populate_clip; |
|---|
| 562 | + bo_update.base.post_clip = vmw_stud_bo_post_clip; |
|---|
| 563 | + |
|---|
| 564 | + return vmw_du_helper_plane_update(&bo_update.base); |
|---|
| 565 | +} |
|---|
| 566 | + |
|---|
| 567 | +static uint32_t vmw_sou_surface_fifo_size(struct vmw_du_update_plane *update, |
|---|
| 568 | + uint32_t num_hits) |
|---|
| 569 | +{ |
|---|
| 570 | + return sizeof(struct vmw_kms_sou_dirty_cmd) + sizeof(SVGASignedRect) * |
|---|
| 571 | + num_hits; |
|---|
| 572 | +} |
|---|
| 573 | + |
|---|
| 574 | +static uint32_t vmw_sou_surface_post_prepare(struct vmw_du_update_plane *update, |
|---|
| 575 | + void *cmd) |
|---|
| 576 | +{ |
|---|
| 577 | + struct vmw_du_update_plane_surface *srf_update; |
|---|
| 578 | + |
|---|
| 579 | + srf_update = container_of(update, typeof(*srf_update), base); |
|---|
| 580 | + |
|---|
| 581 | + /* |
|---|
| 582 | + * SOU SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN is special in the sense that |
|---|
| 583 | + * its bounding box is filled before iterating over all the clips. So |
|---|
| 584 | + * store the FIFO start address and revisit to fill the details. |
|---|
| 585 | + */ |
|---|
| 586 | + srf_update->cmd_start = cmd; |
|---|
| 587 | + |
|---|
| 588 | + return 0; |
|---|
| 589 | +} |
|---|
| 590 | + |
|---|
| 591 | +static uint32_t vmw_sou_surface_pre_clip(struct vmw_du_update_plane *update, |
|---|
| 592 | + void *cmd, uint32_t num_hits) |
|---|
| 593 | +{ |
|---|
| 594 | + struct vmw_kms_sou_dirty_cmd *blit = cmd; |
|---|
| 595 | + struct vmw_framebuffer_surface *vfbs; |
|---|
| 596 | + |
|---|
| 597 | + vfbs = container_of(update->vfb, typeof(*vfbs), base); |
|---|
| 598 | + |
|---|
| 599 | + blit->header.id = SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN; |
|---|
| 600 | + blit->header.size = sizeof(blit->body) + sizeof(SVGASignedRect) * |
|---|
| 601 | + num_hits; |
|---|
| 602 | + |
|---|
| 603 | + blit->body.srcImage.sid = vfbs->surface->res.id; |
|---|
| 604 | + blit->body.destScreenId = update->du->unit; |
|---|
| 605 | + |
|---|
| 606 | + /* Update the source and destination bounding box later in post_clip */ |
|---|
| 607 | + blit->body.srcRect.left = 0; |
|---|
| 608 | + blit->body.srcRect.top = 0; |
|---|
| 609 | + blit->body.srcRect.right = 0; |
|---|
| 610 | + blit->body.srcRect.bottom = 0; |
|---|
| 611 | + |
|---|
| 612 | + blit->body.destRect.left = 0; |
|---|
| 613 | + blit->body.destRect.top = 0; |
|---|
| 614 | + blit->body.destRect.right = 0; |
|---|
| 615 | + blit->body.destRect.bottom = 0; |
|---|
| 616 | + |
|---|
| 617 | + return sizeof(*blit); |
|---|
| 618 | +} |
|---|
| 619 | + |
|---|
| 620 | +static uint32_t vmw_sou_surface_clip_rect(struct vmw_du_update_plane *update, |
|---|
| 621 | + void *cmd, struct drm_rect *clip, |
|---|
| 622 | + uint32_t src_x, uint32_t src_y) |
|---|
| 623 | +{ |
|---|
| 624 | + SVGASignedRect *rect = cmd; |
|---|
| 625 | + |
|---|
| 626 | + /* |
|---|
| 627 | + * rects are relative to dest bounding box rect on screen object, so |
|---|
| 628 | + * translate to it later in post_clip |
|---|
| 629 | + */ |
|---|
| 630 | + rect->left = clip->x1; |
|---|
| 631 | + rect->top = clip->y1; |
|---|
| 632 | + rect->right = clip->x2; |
|---|
| 633 | + rect->bottom = clip->y2; |
|---|
| 634 | + |
|---|
| 635 | + return sizeof(*rect); |
|---|
| 636 | +} |
|---|
| 637 | + |
|---|
| 638 | +static uint32_t vmw_sou_surface_post_clip(struct vmw_du_update_plane *update, |
|---|
| 639 | + void *cmd, struct drm_rect *bb) |
|---|
| 640 | +{ |
|---|
| 641 | + struct vmw_du_update_plane_surface *srf_update; |
|---|
| 642 | + struct drm_plane_state *state = update->plane->state; |
|---|
| 643 | + struct drm_rect src_bb; |
|---|
| 644 | + struct vmw_kms_sou_dirty_cmd *blit; |
|---|
| 645 | + SVGASignedRect *rect; |
|---|
| 646 | + uint32_t num_hits; |
|---|
| 647 | + int translate_src_x; |
|---|
| 648 | + int translate_src_y; |
|---|
| 649 | + int i; |
|---|
| 650 | + |
|---|
| 651 | + srf_update = container_of(update, typeof(*srf_update), base); |
|---|
| 652 | + |
|---|
| 653 | + blit = srf_update->cmd_start; |
|---|
| 654 | + rect = (SVGASignedRect *)&blit[1]; |
|---|
| 655 | + |
|---|
| 656 | + num_hits = (blit->header.size - sizeof(blit->body))/ |
|---|
| 657 | + sizeof(SVGASignedRect); |
|---|
| 658 | + |
|---|
| 659 | + src_bb = *bb; |
|---|
| 660 | + |
|---|
| 661 | + /* To translate bb back to fb src coord */ |
|---|
| 662 | + translate_src_x = (state->src_x >> 16) - state->crtc_x; |
|---|
| 663 | + translate_src_y = (state->src_y >> 16) - state->crtc_y; |
|---|
| 664 | + |
|---|
| 665 | + drm_rect_translate(&src_bb, translate_src_x, translate_src_y); |
|---|
| 666 | + |
|---|
| 667 | + blit->body.srcRect.left = src_bb.x1; |
|---|
| 668 | + blit->body.srcRect.top = src_bb.y1; |
|---|
| 669 | + blit->body.srcRect.right = src_bb.x2; |
|---|
| 670 | + blit->body.srcRect.bottom = src_bb.y2; |
|---|
| 671 | + |
|---|
| 672 | + blit->body.destRect.left = bb->x1; |
|---|
| 673 | + blit->body.destRect.top = bb->y1; |
|---|
| 674 | + blit->body.destRect.right = bb->x2; |
|---|
| 675 | + blit->body.destRect.bottom = bb->y2; |
|---|
| 676 | + |
|---|
| 677 | + /* rects are relative to dest bb rect */ |
|---|
| 678 | + for (i = 0; i < num_hits; i++) { |
|---|
| 679 | + rect->left -= bb->x1; |
|---|
| 680 | + rect->top -= bb->y1; |
|---|
| 681 | + rect->right -= bb->x1; |
|---|
| 682 | + rect->bottom -= bb->y1; |
|---|
| 683 | + rect++; |
|---|
| 684 | + } |
|---|
| 685 | + |
|---|
| 686 | + return 0; |
|---|
| 687 | +} |
|---|
| 688 | + |
|---|
| 689 | +/** |
|---|
| 690 | + * vmw_sou_plane_update_surface - Update display unit for surface backed fb. |
|---|
| 691 | + * @dev_priv: Device private. |
|---|
| 692 | + * @plane: Plane state. |
|---|
| 693 | + * @old_state: Old plane state. |
|---|
| 694 | + * @vfb: Framebuffer which is blitted to display unit |
|---|
| 695 | + * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. |
|---|
| 696 | + * The returned fence pointer may be NULL in which case the device |
|---|
| 697 | + * has already synchronized. |
|---|
| 698 | + * |
|---|
| 699 | + * Return: 0 on success or a negative error code on failure. |
|---|
| 700 | + */ |
|---|
| 701 | +static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv, |
|---|
| 702 | + struct drm_plane *plane, |
|---|
| 703 | + struct drm_plane_state *old_state, |
|---|
| 704 | + struct vmw_framebuffer *vfb, |
|---|
| 705 | + struct vmw_fence_obj **out_fence) |
|---|
| 706 | +{ |
|---|
| 707 | + struct vmw_du_update_plane_surface srf_update; |
|---|
| 708 | + |
|---|
| 709 | + memset(&srf_update, 0, sizeof(struct vmw_du_update_plane_surface)); |
|---|
| 710 | + srf_update.base.plane = plane; |
|---|
| 711 | + srf_update.base.old_state = old_state; |
|---|
| 712 | + srf_update.base.dev_priv = dev_priv; |
|---|
| 713 | + srf_update.base.du = vmw_crtc_to_du(plane->state->crtc); |
|---|
| 714 | + srf_update.base.vfb = vfb; |
|---|
| 715 | + srf_update.base.out_fence = out_fence; |
|---|
| 716 | + srf_update.base.mutex = &dev_priv->cmdbuf_mutex; |
|---|
| 717 | + srf_update.base.cpu_blit = false; |
|---|
| 718 | + srf_update.base.intr = true; |
|---|
| 719 | + |
|---|
| 720 | + srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size; |
|---|
| 721 | + srf_update.base.post_prepare = vmw_sou_surface_post_prepare; |
|---|
| 722 | + srf_update.base.pre_clip = vmw_sou_surface_pre_clip; |
|---|
| 723 | + srf_update.base.clip = vmw_sou_surface_clip_rect; |
|---|
| 724 | + srf_update.base.post_clip = vmw_sou_surface_post_clip; |
|---|
| 725 | + |
|---|
| 726 | + return vmw_du_helper_plane_update(&srf_update.base); |
|---|
| 727 | +} |
|---|
| 502 | 728 | |
|---|
| 503 | 729 | static void |
|---|
| 504 | 730 | vmw_sou_primary_plane_atomic_update(struct drm_plane *plane, |
|---|
| .. | .. |
|---|
| 509 | 735 | struct vmw_fence_obj *fence = NULL; |
|---|
| 510 | 736 | int ret; |
|---|
| 511 | 737 | |
|---|
| 738 | + /* In case of device error, maintain consistent atomic state */ |
|---|
| 512 | 739 | if (crtc && plane->state->fb) { |
|---|
| 513 | 740 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); |
|---|
| 514 | 741 | struct vmw_framebuffer *vfb = |
|---|
| 515 | 742 | vmw_framebuffer_to_vfb(plane->state->fb); |
|---|
| 516 | | - struct drm_vmw_rect vclips; |
|---|
| 517 | | - |
|---|
| 518 | | - vclips.x = crtc->x; |
|---|
| 519 | | - vclips.y = crtc->y; |
|---|
| 520 | | - vclips.w = crtc->mode.hdisplay; |
|---|
| 521 | | - vclips.h = crtc->mode.vdisplay; |
|---|
| 522 | 743 | |
|---|
| 523 | 744 | if (vfb->bo) |
|---|
| 524 | | - ret = vmw_kms_sou_do_bo_dirty(dev_priv, vfb, NULL, |
|---|
| 525 | | - &vclips, 1, 1, true, |
|---|
| 526 | | - &fence, crtc); |
|---|
| 745 | + ret = vmw_sou_plane_update_bo(dev_priv, plane, |
|---|
| 746 | + old_state, vfb, &fence); |
|---|
| 527 | 747 | else |
|---|
| 528 | | - ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, NULL, |
|---|
| 529 | | - &vclips, NULL, 0, 0, |
|---|
| 530 | | - 1, 1, &fence, crtc); |
|---|
| 531 | | - |
|---|
| 532 | | - /* |
|---|
| 533 | | - * We cannot really fail this function, so if we do, then output |
|---|
| 534 | | - * an error and maintain consistent atomic state. |
|---|
| 535 | | - */ |
|---|
| 748 | + ret = vmw_sou_plane_update_surface(dev_priv, plane, |
|---|
| 749 | + old_state, vfb, |
|---|
| 750 | + &fence); |
|---|
| 536 | 751 | if (ret != 0) |
|---|
| 537 | 752 | DRM_ERROR("Failed to update screen.\n"); |
|---|
| 538 | 753 | } else { |
|---|
| 539 | | - /* |
|---|
| 540 | | - * When disabling a plane, CRTC and FB should always be NULL |
|---|
| 541 | | - * together, otherwise it's an error. |
|---|
| 542 | | - * Here primary plane is being disable so should really blank |
|---|
| 543 | | - * the screen object display unit, if not already done. |
|---|
| 544 | | - */ |
|---|
| 754 | + /* Do nothing when fb and crtc is NULL (blank crtc) */ |
|---|
| 545 | 755 | return; |
|---|
| 546 | 756 | } |
|---|
| 547 | 757 | |
|---|
| 758 | + /* For error case vblank event is send from vmw_du_crtc_atomic_flush */ |
|---|
| 548 | 759 | event = crtc->state->event; |
|---|
| 549 | | - /* |
|---|
| 550 | | - * In case of failure and other cases, vblank event will be sent in |
|---|
| 551 | | - * vmw_du_crtc_atomic_flush. |
|---|
| 552 | | - */ |
|---|
| 553 | 760 | if (event && fence) { |
|---|
| 554 | 761 | struct drm_file *file_priv = event->base.file_priv; |
|---|
| 555 | 762 | |
|---|
| .. | .. |
|---|
| 640 | 847 | primary = &sou->base.primary; |
|---|
| 641 | 848 | cursor = &sou->base.cursor; |
|---|
| 642 | 849 | |
|---|
| 643 | | - sou->base.active_implicit = false; |
|---|
| 644 | 850 | sou->base.pref_active = (unit == 0); |
|---|
| 645 | 851 | sou->base.pref_width = dev_priv->initial_width; |
|---|
| 646 | 852 | sou->base.pref_height = dev_priv->initial_height; |
|---|
| .. | .. |
|---|
| 653 | 859 | sou->base.is_implicit = false; |
|---|
| 654 | 860 | |
|---|
| 655 | 861 | /* Initialize primary plane */ |
|---|
| 656 | | - vmw_du_plane_reset(primary); |
|---|
| 657 | | - |
|---|
| 658 | 862 | ret = drm_universal_plane_init(dev, &sou->base.primary, |
|---|
| 659 | 863 | 0, &vmw_sou_plane_funcs, |
|---|
| 660 | 864 | vmw_primary_plane_formats, |
|---|
| .. | .. |
|---|
| 666 | 870 | } |
|---|
| 667 | 871 | |
|---|
| 668 | 872 | drm_plane_helper_add(primary, &vmw_sou_primary_plane_helper_funcs); |
|---|
| 873 | + drm_plane_enable_fb_damage_clips(primary); |
|---|
| 669 | 874 | |
|---|
| 670 | 875 | /* Initialize cursor plane */ |
|---|
| 671 | | - vmw_du_plane_reset(cursor); |
|---|
| 672 | | - |
|---|
| 673 | 876 | ret = drm_universal_plane_init(dev, &sou->base.cursor, |
|---|
| 674 | 877 | 0, &vmw_sou_cursor_funcs, |
|---|
| 675 | 878 | vmw_cursor_plane_formats, |
|---|
| .. | .. |
|---|
| 683 | 886 | |
|---|
| 684 | 887 | drm_plane_helper_add(cursor, &vmw_sou_cursor_plane_helper_funcs); |
|---|
| 685 | 888 | |
|---|
| 686 | | - vmw_du_connector_reset(connector); |
|---|
| 687 | 889 | ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs, |
|---|
| 688 | 890 | DRM_MODE_CONNECTOR_VIRTUAL); |
|---|
| 689 | 891 | if (ret) { |
|---|
| .. | .. |
|---|
| 693 | 895 | |
|---|
| 694 | 896 | drm_connector_helper_add(connector, &vmw_sou_connector_helper_funcs); |
|---|
| 695 | 897 | connector->status = vmw_du_connector_detect(connector, true); |
|---|
| 696 | | - vmw_connector_state_to_vcs(connector->state)->is_implicit = false; |
|---|
| 697 | | - |
|---|
| 698 | 898 | |
|---|
| 699 | 899 | ret = drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs, |
|---|
| 700 | 900 | DRM_MODE_ENCODER_VIRTUAL, NULL); |
|---|
| .. | .. |
|---|
| 713 | 913 | goto err_free_encoder; |
|---|
| 714 | 914 | } |
|---|
| 715 | 915 | |
|---|
| 716 | | - |
|---|
| 717 | | - vmw_du_crtc_reset(crtc); |
|---|
| 718 | 916 | ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary, |
|---|
| 719 | 917 | &sou->base.cursor, |
|---|
| 720 | 918 | &vmw_screen_object_crtc_funcs, NULL); |
|---|
| .. | .. |
|---|
| 733 | 931 | dev->mode_config.suggested_x_property, 0); |
|---|
| 734 | 932 | drm_object_attach_property(&connector->base, |
|---|
| 735 | 933 | dev->mode_config.suggested_y_property, 0); |
|---|
| 736 | | - if (dev_priv->implicit_placement_property) |
|---|
| 737 | | - drm_object_attach_property |
|---|
| 738 | | - (&connector->base, |
|---|
| 739 | | - dev_priv->implicit_placement_property, |
|---|
| 740 | | - sou->base.is_implicit); |
|---|
| 741 | | - |
|---|
| 742 | 934 | return 0; |
|---|
| 743 | 935 | |
|---|
| 744 | 936 | err_free_unregister: |
|---|
| .. | .. |
|---|
| 757 | 949 | struct drm_device *dev = dev_priv->dev; |
|---|
| 758 | 950 | int i, ret; |
|---|
| 759 | 951 | |
|---|
| 952 | + /* Screen objects won't work if GMR's aren't available */ |
|---|
| 953 | + if (!dev_priv->has_gmr) |
|---|
| 954 | + return -ENOSYS; |
|---|
| 955 | + |
|---|
| 760 | 956 | if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) { |
|---|
| 761 | 957 | DRM_INFO("Not using screen objects," |
|---|
| 762 | 958 | " missing cap SCREEN_OBJECT_2\n"); |
|---|
| .. | .. |
|---|
| 764 | 960 | } |
|---|
| 765 | 961 | |
|---|
| 766 | 962 | ret = -ENOMEM; |
|---|
| 767 | | - dev_priv->num_implicit = 0; |
|---|
| 768 | | - dev_priv->implicit_fb = NULL; |
|---|
| 769 | 963 | |
|---|
| 770 | 964 | ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); |
|---|
| 771 | 965 | if (unlikely(ret != 0)) |
|---|
| 772 | 966 | return ret; |
|---|
| 773 | 967 | |
|---|
| 774 | | - vmw_kms_create_implicit_placement_property(dev_priv, false); |
|---|
| 775 | | - |
|---|
| 776 | 968 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) |
|---|
| 777 | 969 | vmw_sou_init(dev_priv, i); |
|---|
| 778 | 970 | |
|---|
| 779 | 971 | dev_priv->active_display_unit = vmw_du_screen_object; |
|---|
| 972 | + |
|---|
| 973 | + drm_mode_config_reset(dev); |
|---|
| 780 | 974 | |
|---|
| 781 | 975 | DRM_INFO("Screen Objects Display Unit initialized\n"); |
|---|
| 782 | 976 | |
|---|
| .. | .. |
|---|
| 802 | 996 | if (depth == 32) |
|---|
| 803 | 997 | depth = 24; |
|---|
| 804 | 998 | |
|---|
| 805 | | - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
|---|
| 806 | | - if (!cmd) { |
|---|
| 807 | | - DRM_ERROR("Out of fifo space for dirty framebuffer command.\n"); |
|---|
| 999 | + cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); |
|---|
| 1000 | + if (!cmd) |
|---|
| 808 | 1001 | return -ENOMEM; |
|---|
| 809 | | - } |
|---|
| 810 | 1002 | |
|---|
| 811 | 1003 | cmd->header = SVGA_CMD_DEFINE_GMRFB; |
|---|
| 812 | 1004 | cmd->body.format.bitsPerPixel = framebuffer->base.format->cpp[0] * 8; |
|---|
| .. | .. |
|---|
| 946 | 1138 | struct vmw_framebuffer_surface *vfbs = |
|---|
| 947 | 1139 | container_of(framebuffer, typeof(*vfbs), base); |
|---|
| 948 | 1140 | struct vmw_kms_sou_surface_dirty sdirty; |
|---|
| 949 | | - struct vmw_validation_ctx ctx; |
|---|
| 1141 | + DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
|---|
| 950 | 1142 | int ret; |
|---|
| 951 | 1143 | |
|---|
| 952 | 1144 | if (!srf) |
|---|
| 953 | 1145 | srf = &vfbs->surface->res; |
|---|
| 954 | 1146 | |
|---|
| 955 | | - ret = vmw_kms_helper_resource_prepare(srf, true, &ctx); |
|---|
| 1147 | + ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE, |
|---|
| 1148 | + NULL, NULL); |
|---|
| 956 | 1149 | if (ret) |
|---|
| 957 | 1150 | return ret; |
|---|
| 1151 | + |
|---|
| 1152 | + ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true); |
|---|
| 1153 | + if (ret) |
|---|
| 1154 | + goto out_unref; |
|---|
| 958 | 1155 | |
|---|
| 959 | 1156 | sdirty.base.fifo_commit = vmw_sou_surface_fifo_commit; |
|---|
| 960 | 1157 | sdirty.base.clip = vmw_sou_surface_clip; |
|---|
| .. | .. |
|---|
| 972 | 1169 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, |
|---|
| 973 | 1170 | dest_x, dest_y, num_clips, inc, |
|---|
| 974 | 1171 | &sdirty.base); |
|---|
| 975 | | - vmw_kms_helper_resource_finish(&ctx, out_fence); |
|---|
| 1172 | + vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence, |
|---|
| 1173 | + NULL); |
|---|
| 976 | 1174 | |
|---|
| 1175 | + return ret; |
|---|
| 1176 | + |
|---|
| 1177 | +out_unref: |
|---|
| 1178 | + vmw_validation_unref_lists(&val_ctx); |
|---|
| 977 | 1179 | return ret; |
|---|
| 978 | 1180 | } |
|---|
| 979 | 1181 | |
|---|
| .. | .. |
|---|
| 1051 | 1253 | container_of(framebuffer, struct vmw_framebuffer_bo, |
|---|
| 1052 | 1254 | base)->buffer; |
|---|
| 1053 | 1255 | struct vmw_kms_dirty dirty; |
|---|
| 1256 | + DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
|---|
| 1054 | 1257 | int ret; |
|---|
| 1055 | 1258 | |
|---|
| 1056 | | - ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible, |
|---|
| 1057 | | - false, false); |
|---|
| 1259 | + ret = vmw_validation_add_bo(&val_ctx, buf, false, false); |
|---|
| 1058 | 1260 | if (ret) |
|---|
| 1059 | 1261 | return ret; |
|---|
| 1262 | + |
|---|
| 1263 | + ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); |
|---|
| 1264 | + if (ret) |
|---|
| 1265 | + goto out_unref; |
|---|
| 1060 | 1266 | |
|---|
| 1061 | 1267 | ret = do_bo_define_gmrfb(dev_priv, framebuffer); |
|---|
| 1062 | 1268 | if (unlikely(ret != 0)) |
|---|
| .. | .. |
|---|
| 1069 | 1275 | num_clips; |
|---|
| 1070 | 1276 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, |
|---|
| 1071 | 1277 | 0, 0, num_clips, increment, &dirty); |
|---|
| 1072 | | - vmw_kms_helper_buffer_finish(dev_priv, NULL, buf, out_fence, NULL); |
|---|
| 1278 | + vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence, |
|---|
| 1279 | + NULL); |
|---|
| 1073 | 1280 | |
|---|
| 1074 | 1281 | return ret; |
|---|
| 1075 | 1282 | |
|---|
| 1076 | 1283 | out_revert: |
|---|
| 1077 | | - vmw_kms_helper_buffer_revert(buf); |
|---|
| 1284 | + vmw_validation_revert(&val_ctx); |
|---|
| 1285 | +out_unref: |
|---|
| 1286 | + vmw_validation_unref_lists(&val_ctx); |
|---|
| 1078 | 1287 | |
|---|
| 1079 | 1288 | return ret; |
|---|
| 1080 | 1289 | } |
|---|
| .. | .. |
|---|
| 1150 | 1359 | struct vmw_buffer_object *buf = |
|---|
| 1151 | 1360 | container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; |
|---|
| 1152 | 1361 | struct vmw_kms_dirty dirty; |
|---|
| 1362 | + DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); |
|---|
| 1153 | 1363 | int ret; |
|---|
| 1154 | 1364 | |
|---|
| 1155 | | - ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, true, false, |
|---|
| 1156 | | - false); |
|---|
| 1365 | + ret = vmw_validation_add_bo(&val_ctx, buf, false, false); |
|---|
| 1157 | 1366 | if (ret) |
|---|
| 1158 | 1367 | return ret; |
|---|
| 1368 | + |
|---|
| 1369 | + ret = vmw_validation_prepare(&val_ctx, NULL, true); |
|---|
| 1370 | + if (ret) |
|---|
| 1371 | + goto out_unref; |
|---|
| 1159 | 1372 | |
|---|
| 1160 | 1373 | ret = do_bo_define_gmrfb(dev_priv, vfb); |
|---|
| 1161 | 1374 | if (unlikely(ret != 0)) |
|---|
| .. | .. |
|---|
| 1168 | 1381 | num_clips; |
|---|
| 1169 | 1382 | ret = vmw_kms_helper_dirty(dev_priv, vfb, NULL, vclips, |
|---|
| 1170 | 1383 | 0, 0, num_clips, 1, &dirty); |
|---|
| 1171 | | - vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL, |
|---|
| 1172 | | - user_fence_rep); |
|---|
| 1384 | + vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL, |
|---|
| 1385 | + user_fence_rep); |
|---|
| 1173 | 1386 | |
|---|
| 1174 | 1387 | return ret; |
|---|
| 1175 | 1388 | |
|---|
| 1176 | 1389 | out_revert: |
|---|
| 1177 | | - vmw_kms_helper_buffer_revert(buf); |
|---|
| 1178 | | - |
|---|
| 1390 | + vmw_validation_revert(&val_ctx); |
|---|
| 1391 | +out_unref: |
|---|
| 1392 | + vmw_validation_unref_lists(&val_ctx); |
|---|
| 1393 | + |
|---|
| 1179 | 1394 | return ret; |
|---|
| 1180 | 1395 | } |
|---|