.. | .. |
---|
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 | } |
---|