1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 /****************************************************************************** 3 * 4 * COPYRIGHT (C) 2014-2023 VMware, Inc., Palo Alto, CA., USA 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 ******************************************************************************/ 27 28 #include "vmwgfx_bo.h" 29 #include "vmwgfx_kms.h" 30 #include "vmwgfx_vkms.h" 31 #include "vmw_surface_cache.h" 32 33 #include <drm/drm_atomic.h> 34 #include <drm/drm_atomic_helper.h> 35 #include <drm/drm_damage_helper.h> 36 #include <drm/drm_fourcc.h> 37 #include <drm/drm_vblank.h> 38 39 #define vmw_crtc_to_stdu(x) \ 40 container_of(x, struct vmw_screen_target_display_unit, base.crtc) 41 #define vmw_encoder_to_stdu(x) \ 42 container_of(x, struct vmw_screen_target_display_unit, base.encoder) 43 #define vmw_connector_to_stdu(x) \ 44 container_of(x, struct vmw_screen_target_display_unit, base.connector) 45 46 47 48 enum stdu_content_type { 49 SAME_AS_DISPLAY = 0, 50 SEPARATE_SURFACE, 51 SEPARATE_BO 52 }; 53 54 /** 55 * struct vmw_stdu_dirty - closure structure for the update functions 56 * 57 * @base: The base type we derive from. Used by vmw_kms_helper_dirty(). 58 * @left: Left side of bounding box. 59 * @right: Right side of bounding box. 60 * @top: Top side of bounding box. 61 * @bottom: Bottom side of bounding box. 62 * @fb_left: Left side of the framebuffer/content bounding box 63 * @fb_top: Top of the framebuffer/content bounding box 64 * @pitch: framebuffer pitch (stride) 65 * @buf: buffer object when DMA-ing between buffer and screen targets. 66 * @sid: Surface ID when copying between surface and screen targets. 67 */ 68 struct vmw_stdu_dirty { 69 struct vmw_kms_dirty base; 70 s32 left, right, top, bottom; 71 s32 fb_left, fb_top; 72 u32 pitch; 73 union { 74 struct vmw_bo *buf; 75 u32 sid; 76 }; 77 }; 78 79 /* 80 * SVGA commands that are used by this code. Please see the device headers 81 * for explanation. 82 */ 83 struct vmw_stdu_update { 84 SVGA3dCmdHeader header; 85 SVGA3dCmdUpdateGBScreenTarget body; 86 }; 87 88 struct vmw_stdu_dma { 89 SVGA3dCmdHeader header; 90 SVGA3dCmdSurfaceDMA body; 91 }; 92 93 struct vmw_stdu_surface_copy { 94 SVGA3dCmdHeader header; 95 SVGA3dCmdSurfaceCopy body; 96 }; 97 98 struct vmw_stdu_update_gb_image { 99 SVGA3dCmdHeader header; 100 SVGA3dCmdUpdateGBImage body; 101 }; 102 103 /** 104 * struct vmw_screen_target_display_unit - conglomerated STDU structure 105 * 106 * @base: VMW specific DU structure 107 * @display_srf: surface to be displayed. The dimension of this will always 108 * match the display mode. If the display mode matches 109 * content_vfbs dimensions, then this is a pointer into the 110 * corresponding field in content_vfbs. If not, then this 111 * is a separate buffer to which content_vfbs will blit to. 112 * @content_fb_type: content_fb type 113 * @display_width: display width 114 * @display_height: display height 115 * @defined: true if the current display unit has been initialized 116 * @cpp: Bytes per pixel 117 */ 118 struct vmw_screen_target_display_unit { 119 struct vmw_display_unit base; 120 struct vmw_surface *display_srf; 121 enum stdu_content_type content_fb_type; 122 s32 display_width, display_height; 123 124 bool defined; 125 126 /* For CPU Blit */ 127 unsigned int cpp; 128 }; 129 130 131 132 static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); 133 134 135 136 /****************************************************************************** 137 * Screen Target Display Unit CRTC Functions 138 *****************************************************************************/ 139 140 /** 141 * vmw_stdu_crtc_destroy - cleans up the STDU 142 * 143 * @crtc: used to get a reference to the containing STDU 144 */ 145 static void vmw_stdu_crtc_destroy(struct drm_crtc *crtc) 146 { 147 vmw_stdu_destroy(vmw_crtc_to_stdu(crtc)); 148 } 149 150 /** 151 * vmw_stdu_define_st - Defines a Screen Target 152 * 153 * @dev_priv: VMW DRM device 154 * @stdu: display unit to create a Screen Target for 155 * @mode: The mode to set. 156 * @crtc_x: X coordinate of screen target relative to framebuffer origin. 157 * @crtc_y: Y coordinate of screen target relative to framebuffer origin. 158 * 159 * Creates a STDU that we can used later. This function is called whenever the 160 * framebuffer size changes. 161 * 162 * RETURNs: 163 * 0 on success, error code on failure 164 */ 165 static int vmw_stdu_define_st(struct vmw_private *dev_priv, 166 struct vmw_screen_target_display_unit *stdu, 167 struct drm_display_mode *mode, 168 int crtc_x, int crtc_y) 169 { 170 struct { 171 SVGA3dCmdHeader header; 172 SVGA3dCmdDefineGBScreenTarget body; 173 } *cmd; 174 175 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 176 if (unlikely(cmd == NULL)) 177 return -ENOMEM; 178 179 cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SCREENTARGET; 180 cmd->header.size = sizeof(cmd->body); 181 182 cmd->body.stid = stdu->base.unit; 183 cmd->body.width = mode->hdisplay; 184 cmd->body.height = mode->vdisplay; 185 cmd->body.flags = (0 == cmd->body.stid) ? SVGA_STFLAG_PRIMARY : 0; 186 cmd->body.dpi = 0; 187 cmd->body.xRoot = crtc_x; 188 cmd->body.yRoot = crtc_y; 189 190 stdu->base.set_gui_x = cmd->body.xRoot; 191 stdu->base.set_gui_y = cmd->body.yRoot; 192 193 vmw_cmd_commit(dev_priv, sizeof(*cmd)); 194 195 stdu->defined = true; 196 stdu->display_width = mode->hdisplay; 197 stdu->display_height = mode->vdisplay; 198 199 return 0; 200 } 201 202 203 204 /** 205 * vmw_stdu_bind_st - Binds a surface to a Screen Target 206 * 207 * @dev_priv: VMW DRM device 208 * @stdu: display unit affected 209 * @res: Buffer to bind to the screen target. Set to NULL to blank screen. 210 * 211 * Binding a surface to a Screen Target the same as flipping 212 * 213 * Returns: %0 on success or -errno code on failure 214 */ 215 static int vmw_stdu_bind_st(struct vmw_private *dev_priv, 216 struct vmw_screen_target_display_unit *stdu, 217 const struct vmw_resource *res) 218 { 219 SVGA3dSurfaceImageId image; 220 221 struct { 222 SVGA3dCmdHeader header; 223 SVGA3dCmdBindGBScreenTarget body; 224 } *cmd; 225 226 227 if (!stdu->defined) { 228 DRM_ERROR("No screen target defined\n"); 229 return -EINVAL; 230 } 231 232 /* Set up image using information in vfb */ 233 memset(&image, 0, sizeof(image)); 234 image.sid = res ? res->id : SVGA3D_INVALID_ID; 235 236 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 237 if (unlikely(cmd == NULL)) 238 return -ENOMEM; 239 240 cmd->header.id = SVGA_3D_CMD_BIND_GB_SCREENTARGET; 241 cmd->header.size = sizeof(cmd->body); 242 243 cmd->body.stid = stdu->base.unit; 244 cmd->body.image = image; 245 246 vmw_cmd_commit(dev_priv, sizeof(*cmd)); 247 248 return 0; 249 } 250 251 /** 252 * vmw_stdu_populate_update - populate an UPDATE_GB_SCREENTARGET command with a 253 * bounding box. 254 * 255 * @cmd: Pointer to command stream. 256 * @unit: Screen target unit. 257 * @left: Left side of bounding box. 258 * @right: Right side of bounding box. 259 * @top: Top side of bounding box. 260 * @bottom: Bottom side of bounding box. 261 */ 262 static void vmw_stdu_populate_update(void *cmd, int unit, 263 s32 left, s32 right, s32 top, s32 bottom) 264 { 265 struct vmw_stdu_update *update = cmd; 266 267 update->header.id = SVGA_3D_CMD_UPDATE_GB_SCREENTARGET; 268 update->header.size = sizeof(update->body); 269 270 update->body.stid = unit; 271 update->body.rect.x = left; 272 update->body.rect.y = top; 273 update->body.rect.w = right - left; 274 update->body.rect.h = bottom - top; 275 } 276 277 /** 278 * vmw_stdu_update_st - Full update of a Screen Target 279 * 280 * @dev_priv: VMW DRM device 281 * @stdu: display unit affected 282 * 283 * This function needs to be called whenever the content of a screen 284 * target has changed completely. Typically as a result of a backing 285 * surface change. 286 * 287 * RETURNS: 288 * 0 on success, error code on failure 289 */ 290 static int vmw_stdu_update_st(struct vmw_private *dev_priv, 291 struct vmw_screen_target_display_unit *stdu) 292 { 293 struct vmw_stdu_update *cmd; 294 295 if (!stdu->defined) { 296 DRM_ERROR("No screen target defined"); 297 return -EINVAL; 298 } 299 300 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 301 if (unlikely(cmd == NULL)) 302 return -ENOMEM; 303 304 vmw_stdu_populate_update(cmd, stdu->base.unit, 305 0, stdu->display_width, 306 0, stdu->display_height); 307 308 vmw_cmd_commit(dev_priv, sizeof(*cmd)); 309 310 return 0; 311 } 312 313 314 315 /** 316 * vmw_stdu_destroy_st - Destroy a Screen Target 317 * 318 * @dev_priv: VMW DRM device 319 * @stdu: display unit to destroy 320 * 321 * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if 322 * interrupted. 323 */ 324 static int vmw_stdu_destroy_st(struct vmw_private *dev_priv, 325 struct vmw_screen_target_display_unit *stdu) 326 { 327 int ret; 328 329 struct { 330 SVGA3dCmdHeader header; 331 SVGA3dCmdDestroyGBScreenTarget body; 332 } *cmd; 333 334 335 /* Nothing to do if not successfully defined */ 336 if (unlikely(!stdu->defined)) 337 return 0; 338 339 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 340 if (unlikely(cmd == NULL)) 341 return -ENOMEM; 342 343 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SCREENTARGET; 344 cmd->header.size = sizeof(cmd->body); 345 346 cmd->body.stid = stdu->base.unit; 347 348 vmw_cmd_commit(dev_priv, sizeof(*cmd)); 349 350 /* Force sync */ 351 ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ); 352 if (unlikely(ret != 0)) 353 DRM_ERROR("Failed to sync with HW"); 354 355 stdu->defined = false; 356 stdu->display_width = 0; 357 stdu->display_height = 0; 358 359 return ret; 360 } 361 362 363 /** 364 * vmw_stdu_crtc_mode_set_nofb - Updates screen target size 365 * 366 * @crtc: CRTC associated with the screen target 367 * 368 * This function defines/destroys a screen target 369 * 370 */ 371 static void vmw_stdu_crtc_mode_set_nofb(struct drm_crtc *crtc) 372 { 373 struct vmw_private *dev_priv; 374 struct vmw_screen_target_display_unit *stdu; 375 struct drm_connector_state *conn_state; 376 struct vmw_connector_state *vmw_conn_state; 377 int x, y, ret; 378 379 stdu = vmw_crtc_to_stdu(crtc); 380 dev_priv = vmw_priv(crtc->dev); 381 conn_state = stdu->base.connector.state; 382 vmw_conn_state = vmw_connector_state_to_vcs(conn_state); 383 384 if (stdu->defined) { 385 ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); 386 if (ret) 387 DRM_ERROR("Failed to blank CRTC\n"); 388 389 (void) vmw_stdu_update_st(dev_priv, stdu); 390 391 ret = vmw_stdu_destroy_st(dev_priv, stdu); 392 if (ret) 393 DRM_ERROR("Failed to destroy Screen Target\n"); 394 395 stdu->content_fb_type = SAME_AS_DISPLAY; 396 } 397 398 if (!crtc->state->enable) 399 return; 400 401 x = vmw_conn_state->gui_x; 402 y = vmw_conn_state->gui_y; 403 404 vmw_svga_enable(dev_priv); 405 ret = vmw_stdu_define_st(dev_priv, stdu, &crtc->mode, x, y); 406 407 if (ret) 408 DRM_ERROR("Failed to define Screen Target of size %dx%d\n", 409 crtc->x, crtc->y); 410 } 411 412 static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, 413 struct drm_atomic_state *state) 414 { 415 struct vmw_private *dev_priv; 416 struct vmw_screen_target_display_unit *stdu; 417 int ret; 418 419 if (!crtc) { 420 DRM_ERROR("CRTC is NULL\n"); 421 return; 422 } 423 424 stdu = vmw_crtc_to_stdu(crtc); 425 dev_priv = vmw_priv(crtc->dev); 426 427 if (dev_priv->vkms_enabled) 428 drm_crtc_vblank_off(crtc); 429 430 if (stdu->defined) { 431 ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); 432 if (ret) 433 DRM_ERROR("Failed to blank CRTC\n"); 434 435 (void) vmw_stdu_update_st(dev_priv, stdu); 436 437 ret = vmw_stdu_destroy_st(dev_priv, stdu); 438 if (ret) 439 DRM_ERROR("Failed to destroy Screen Target\n"); 440 441 stdu->content_fb_type = SAME_AS_DISPLAY; 442 } 443 } 444 445 /** 446 * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit 447 * 448 * @dirty: The closure structure. 449 * 450 * This function calculates the bounding box for all the incoming clips. 451 */ 452 static void vmw_stdu_bo_cpu_clip(struct vmw_kms_dirty *dirty) 453 { 454 struct vmw_stdu_dirty *ddirty = 455 container_of(dirty, struct vmw_stdu_dirty, base); 456 457 dirty->num_hits = 1; 458 459 /* Calculate destination bounding box */ 460 ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1); 461 ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1); 462 ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2); 463 ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); 464 465 /* 466 * Calculate content bounding box. We only need the top-left 467 * coordinate because width and height will be the same as the 468 * destination bounding box above 469 */ 470 ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x); 471 ddirty->fb_top = min_t(s32, ddirty->fb_top, dirty->fb_y); 472 } 473 474 475 /** 476 * vmw_stdu_bo_cpu_commit - Callback to do a CPU blit from buffer object 477 * 478 * @dirty: The closure structure. 479 * 480 * For the special case when we cannot create a proxy surface in a 481 * 2D VM, we have to do a CPU blit ourselves. 482 */ 483 static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) 484 { 485 struct vmw_stdu_dirty *ddirty = 486 container_of(dirty, struct vmw_stdu_dirty, base); 487 struct vmw_screen_target_display_unit *stdu = 488 container_of(dirty->unit, typeof(*stdu), base); 489 s32 width, height; 490 s32 src_pitch, dst_pitch; 491 struct ttm_buffer_object *src_bo, *dst_bo; 492 u32 src_offset, dst_offset; 493 struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(stdu->cpp); 494 495 if (!dirty->num_hits) 496 return; 497 498 width = ddirty->right - ddirty->left; 499 height = ddirty->bottom - ddirty->top; 500 501 if (width == 0 || height == 0) 502 return; 503 504 /* Assume we are blitting from Guest (bo) to Host (display_srf) */ 505 src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; 506 src_bo = &stdu->display_srf->res.guest_memory_bo->tbo; 507 src_offset = ddirty->top * src_pitch + ddirty->left * stdu->cpp; 508 509 dst_pitch = ddirty->pitch; 510 dst_bo = &ddirty->buf->tbo; 511 dst_offset = ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp; 512 513 (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, 514 src_bo, src_offset, src_pitch, 515 width * stdu->cpp, height, &diff); 516 } 517 518 /** 519 * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed 520 * framebuffer and the screen target system. 521 * 522 * @dev_priv: Pointer to the device private structure. 523 * @file_priv: Pointer to a struct drm-file identifying the caller. May be 524 * set to NULL, but then @user_fence_rep must also be set to NULL. 525 * @vfb: Pointer to the buffer-object backed framebuffer. 526 * @user_fence_rep: User-space provided structure for fence information. 527 * @clips: Array of clip rects. Either @clips or @vclips must be NULL. 528 * @vclips: Alternate array of clip rects. Either @clips or @vclips must 529 * be NULL. 530 * @num_clips: Number of clip rects in @clips or @vclips. 531 * @increment: Increment to use when looping over @clips or @vclips. 532 * @crtc: If crtc is passed, perform stdu dma on that crtc only. 533 * 534 * If DMA-ing till the screen target system, the function will also notify 535 * the screen target system that a bounding box of the cliprects has been 536 * updated. 537 * 538 * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if 539 * interrupted. 540 */ 541 int vmw_kms_stdu_readback(struct vmw_private *dev_priv, 542 struct drm_file *file_priv, 543 struct vmw_framebuffer *vfb, 544 struct drm_vmw_fence_rep __user *user_fence_rep, 545 struct drm_clip_rect *clips, 546 struct drm_vmw_rect *vclips, 547 uint32_t num_clips, 548 int increment, 549 struct drm_crtc *crtc) 550 { 551 struct vmw_bo *buf = 552 container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; 553 struct vmw_stdu_dirty ddirty; 554 int ret; 555 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); 556 557 /* 558 * The GMR domain might seem confusing because it might seem like it should 559 * never happen with screen targets but e.g. the xorg vmware driver issues 560 * CMD_SURFACE_DMA for various pixmap updates which might transition our bo to 561 * a GMR. Instead of forcing another transition we can optimize the readback 562 * by reading directly from the GMR. 563 */ 564 vmw_bo_placement_set(buf, 565 VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR, 566 VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR); 567 ret = vmw_validation_add_bo(&val_ctx, buf); 568 if (ret) 569 return ret; 570 571 ret = vmw_validation_prepare(&val_ctx, NULL, true); 572 if (ret) 573 goto out_unref; 574 575 ddirty.left = ddirty.top = S32_MAX; 576 ddirty.right = ddirty.bottom = S32_MIN; 577 ddirty.fb_left = ddirty.fb_top = S32_MAX; 578 ddirty.pitch = vfb->base.pitches[0]; 579 ddirty.buf = buf; 580 581 ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; 582 ddirty.base.clip = vmw_stdu_bo_cpu_clip; 583 ddirty.base.fifo_reserve_size = 0; 584 585 ddirty.base.crtc = crtc; 586 587 ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips, 588 0, 0, num_clips, increment, &ddirty.base); 589 590 vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL, 591 user_fence_rep); 592 return ret; 593 594 out_unref: 595 vmw_validation_unref_lists(&val_ctx); 596 return ret; 597 } 598 599 /** 600 * vmw_kms_stdu_surface_clip - Callback to encode a surface copy command cliprect 601 * 602 * @dirty: The closure structure. 603 * 604 * Encodes a surface copy command cliprect and updates the bounding box 605 * for the copy. 606 */ 607 static void vmw_kms_stdu_surface_clip(struct vmw_kms_dirty *dirty) 608 { 609 struct vmw_stdu_dirty *sdirty = 610 container_of(dirty, struct vmw_stdu_dirty, base); 611 struct vmw_stdu_surface_copy *cmd = dirty->cmd; 612 struct vmw_screen_target_display_unit *stdu = 613 container_of(dirty->unit, typeof(*stdu), base); 614 615 if (sdirty->sid != stdu->display_srf->res.id) { 616 struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; 617 618 blit += dirty->num_hits; 619 blit->srcx = dirty->fb_x; 620 blit->srcy = dirty->fb_y; 621 blit->x = dirty->unit_x1; 622 blit->y = dirty->unit_y1; 623 blit->d = 1; 624 blit->w = dirty->unit_x2 - dirty->unit_x1; 625 blit->h = dirty->unit_y2 - dirty->unit_y1; 626 } 627 628 dirty->num_hits++; 629 630 /* Destination bounding box */ 631 sdirty->left = min_t(s32, sdirty->left, dirty->unit_x1); 632 sdirty->top = min_t(s32, sdirty->top, dirty->unit_y1); 633 sdirty->right = max_t(s32, sdirty->right, dirty->unit_x2); 634 sdirty->bottom = max_t(s32, sdirty->bottom, dirty->unit_y2); 635 } 636 637 /** 638 * vmw_kms_stdu_surface_fifo_commit - Callback to fill in and submit a surface 639 * copy command. 640 * 641 * @dirty: The closure structure. 642 * 643 * Fills in the missing fields in a surface copy command, and encodes a screen 644 * target update command. 645 */ 646 static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty) 647 { 648 struct vmw_stdu_dirty *sdirty = 649 container_of(dirty, struct vmw_stdu_dirty, base); 650 struct vmw_screen_target_display_unit *stdu = 651 container_of(dirty->unit, typeof(*stdu), base); 652 struct vmw_stdu_surface_copy *cmd = dirty->cmd; 653 struct vmw_stdu_update *update; 654 size_t blit_size = sizeof(SVGA3dCopyBox) * dirty->num_hits; 655 size_t commit_size; 656 657 if (!dirty->num_hits) { 658 vmw_cmd_commit(dirty->dev_priv, 0); 659 return; 660 } 661 662 if (sdirty->sid != stdu->display_srf->res.id) { 663 struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; 664 665 cmd->header.id = SVGA_3D_CMD_SURFACE_COPY; 666 cmd->header.size = sizeof(cmd->body) + blit_size; 667 cmd->body.src.sid = sdirty->sid; 668 cmd->body.dest.sid = stdu->display_srf->res.id; 669 update = (struct vmw_stdu_update *) &blit[dirty->num_hits]; 670 commit_size = sizeof(*cmd) + blit_size + sizeof(*update); 671 stdu->display_srf->res.res_dirty = true; 672 } else { 673 update = dirty->cmd; 674 commit_size = sizeof(*update); 675 } 676 677 vmw_stdu_populate_update(update, stdu->base.unit, sdirty->left, 678 sdirty->right, sdirty->top, sdirty->bottom); 679 680 vmw_cmd_commit(dirty->dev_priv, commit_size); 681 682 sdirty->left = sdirty->top = S32_MAX; 683 sdirty->right = sdirty->bottom = S32_MIN; 684 } 685 686 /** 687 * vmw_kms_stdu_surface_dirty - Dirty part of a surface backed framebuffer 688 * 689 * @dev_priv: Pointer to the device private structure. 690 * @framebuffer: Pointer to the surface-buffer backed framebuffer. 691 * @clips: Array of clip rects. Either @clips or @vclips must be NULL. 692 * @vclips: Alternate array of clip rects. Either @clips or @vclips must 693 * be NULL. 694 * @srf: Pointer to surface to blit from. If NULL, the surface attached 695 * to @framebuffer will be used. 696 * @dest_x: X coordinate offset to align @srf with framebuffer coordinates. 697 * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates. 698 * @num_clips: Number of clip rects in @clips. 699 * @inc: Increment to use when looping over @clips. 700 * @out_fence: If non-NULL, will return a ref-counted pointer to a 701 * struct vmw_fence_obj. The returned fence pointer may be NULL in which 702 * case the device has already synchronized. 703 * @crtc: If crtc is passed, perform surface dirty on that crtc only. 704 * 705 * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if 706 * interrupted. 707 */ 708 int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, 709 struct vmw_framebuffer *framebuffer, 710 struct drm_clip_rect *clips, 711 struct drm_vmw_rect *vclips, 712 struct vmw_resource *srf, 713 s32 dest_x, 714 s32 dest_y, 715 unsigned num_clips, int inc, 716 struct vmw_fence_obj **out_fence, 717 struct drm_crtc *crtc) 718 { 719 struct vmw_framebuffer_surface *vfbs = 720 container_of(framebuffer, typeof(*vfbs), base); 721 struct vmw_stdu_dirty sdirty; 722 DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); 723 int ret; 724 725 if (!srf) 726 srf = &vfbs->surface->res; 727 728 ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE, 729 NULL, NULL); 730 if (ret) 731 return ret; 732 733 ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true); 734 if (ret) 735 goto out_unref; 736 737 if (vfbs->is_bo_proxy) { 738 ret = vmw_kms_update_proxy(srf, clips, num_clips, inc); 739 if (ret) 740 goto out_finish; 741 } 742 743 sdirty.base.fifo_commit = vmw_kms_stdu_surface_fifo_commit; 744 sdirty.base.clip = vmw_kms_stdu_surface_clip; 745 sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) + 746 sizeof(SVGA3dCopyBox) * num_clips + 747 sizeof(struct vmw_stdu_update); 748 sdirty.base.crtc = crtc; 749 sdirty.sid = srf->id; 750 sdirty.left = sdirty.top = S32_MAX; 751 sdirty.right = sdirty.bottom = S32_MIN; 752 753 ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, 754 dest_x, dest_y, num_clips, inc, 755 &sdirty.base); 756 out_finish: 757 vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence, 758 NULL); 759 760 return ret; 761 762 out_unref: 763 vmw_validation_unref_lists(&val_ctx); 764 return ret; 765 } 766 767 /* 768 * Screen Target CRTC dispatch table 769 */ 770 static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = { 771 .gamma_set = vmw_du_crtc_gamma_set, 772 .destroy = vmw_stdu_crtc_destroy, 773 .reset = vmw_du_crtc_reset, 774 .atomic_duplicate_state = vmw_du_crtc_duplicate_state, 775 .atomic_destroy_state = vmw_du_crtc_destroy_state, 776 .set_config = drm_atomic_helper_set_config, 777 .page_flip = drm_atomic_helper_page_flip, 778 .enable_vblank = vmw_vkms_enable_vblank, 779 .disable_vblank = vmw_vkms_disable_vblank, 780 .get_vblank_timestamp = vmw_vkms_get_vblank_timestamp, 781 .get_crc_sources = vmw_vkms_get_crc_sources, 782 .set_crc_source = vmw_vkms_set_crc_source, 783 .verify_crc_source = vmw_vkms_verify_crc_source, 784 }; 785 786 787 788 /****************************************************************************** 789 * Screen Target Display Unit Encoder Functions 790 *****************************************************************************/ 791 792 /** 793 * vmw_stdu_encoder_destroy - cleans up the STDU 794 * 795 * @encoder: used the get the containing STDU 796 * 797 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically 798 * this can be a no-op. Nevertheless, it doesn't hurt of have this in case 799 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't 800 * get called. 801 */ 802 static void vmw_stdu_encoder_destroy(struct drm_encoder *encoder) 803 { 804 vmw_stdu_destroy(vmw_encoder_to_stdu(encoder)); 805 } 806 807 static const struct drm_encoder_funcs vmw_stdu_encoder_funcs = { 808 .destroy = vmw_stdu_encoder_destroy, 809 }; 810 811 812 813 /****************************************************************************** 814 * Screen Target Display Unit Connector Functions 815 *****************************************************************************/ 816 817 /** 818 * vmw_stdu_connector_destroy - cleans up the STDU 819 * 820 * @connector: used to get the containing STDU 821 * 822 * vmwgfx cleans up crtc/encoder/connector all at the same time so technically 823 * this can be a no-op. Nevertheless, it doesn't hurt of have this in case 824 * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't 825 * get called. 826 */ 827 static void vmw_stdu_connector_destroy(struct drm_connector *connector) 828 { 829 vmw_stdu_destroy(vmw_connector_to_stdu(connector)); 830 } 831 832 833 834 static const struct drm_connector_funcs vmw_stdu_connector_funcs = { 835 .dpms = vmw_du_connector_dpms, 836 .detect = vmw_du_connector_detect, 837 .fill_modes = drm_helper_probe_single_connector_modes, 838 .destroy = vmw_stdu_connector_destroy, 839 .reset = vmw_du_connector_reset, 840 .atomic_duplicate_state = vmw_du_connector_duplicate_state, 841 .atomic_destroy_state = vmw_du_connector_destroy_state, 842 }; 843 844 845 static const struct 846 drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { 847 .get_modes = vmw_connector_get_modes, 848 .mode_valid = vmw_connector_mode_valid 849 }; 850 851 852 853 /****************************************************************************** 854 * Screen Target Display Plane Functions 855 *****************************************************************************/ 856 857 858 859 /** 860 * vmw_stdu_primary_plane_cleanup_fb - Unpins the display surface 861 * 862 * @plane: display plane 863 * @old_state: Contains the FB to clean up 864 * 865 * Unpins the display surface 866 * 867 * Returns 0 on success 868 */ 869 static void 870 vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane, 871 struct drm_plane_state *old_state) 872 { 873 struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); 874 875 if (vps->surf) 876 WARN_ON(!vps->pinned); 877 878 vmw_du_plane_cleanup_fb(plane, old_state); 879 880 vps->content_fb_type = SAME_AS_DISPLAY; 881 vps->cpp = 0; 882 } 883 884 885 886 /** 887 * vmw_stdu_primary_plane_prepare_fb - Readies the display surface 888 * 889 * @plane: display plane 890 * @new_state: info on the new plane state, including the FB 891 * 892 * This function allocates a new display surface if the content is 893 * backed by a buffer object. The display surface is pinned here, and it'll 894 * be unpinned in .cleanup_fb() 895 * 896 * Returns: %0 on success 897 */ 898 static int 899 vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, 900 struct drm_plane_state *new_state) 901 { 902 struct vmw_private *dev_priv = vmw_priv(plane->dev); 903 struct drm_framebuffer *new_fb = new_state->fb; 904 struct vmw_framebuffer *vfb; 905 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); 906 enum stdu_content_type new_content_type; 907 struct vmw_framebuffer_surface *new_vfbs; 908 uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h; 909 int ret; 910 911 /* No FB to prepare */ 912 if (!new_fb) { 913 if (vps->surf) { 914 WARN_ON(vps->pinned != 0); 915 vmw_surface_unreference(&vps->surf); 916 } 917 918 return 0; 919 } 920 921 vfb = vmw_framebuffer_to_vfb(new_fb); 922 new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb); 923 924 if (new_vfbs && 925 new_vfbs->surface->metadata.base_size.width == hdisplay && 926 new_vfbs->surface->metadata.base_size.height == vdisplay) 927 new_content_type = SAME_AS_DISPLAY; 928 else if (vfb->bo) 929 new_content_type = SEPARATE_BO; 930 else 931 new_content_type = SEPARATE_SURFACE; 932 933 if (new_content_type != SAME_AS_DISPLAY) { 934 struct vmw_surface_metadata metadata = {0}; 935 936 /* 937 * If content buffer is a buffer object, then we have to 938 * construct surface info 939 */ 940 if (new_content_type == SEPARATE_BO) { 941 942 switch (new_fb->format->cpp[0]*8) { 943 case 32: 944 metadata.format = SVGA3D_X8R8G8B8; 945 break; 946 947 case 16: 948 metadata.format = SVGA3D_R5G6B5; 949 break; 950 951 case 8: 952 metadata.format = SVGA3D_P8; 953 break; 954 955 default: 956 DRM_ERROR("Invalid format\n"); 957 return -EINVAL; 958 } 959 960 metadata.mip_levels[0] = 1; 961 metadata.num_sizes = 1; 962 metadata.scanout = true; 963 } else { 964 metadata = new_vfbs->surface->metadata; 965 } 966 967 metadata.base_size.width = hdisplay; 968 metadata.base_size.height = vdisplay; 969 metadata.base_size.depth = 1; 970 971 if (vps->surf) { 972 struct drm_vmw_size cur_base_size = 973 vps->surf->metadata.base_size; 974 975 if (cur_base_size.width != metadata.base_size.width || 976 cur_base_size.height != metadata.base_size.height || 977 vps->surf->metadata.format != metadata.format) { 978 WARN_ON(vps->pinned != 0); 979 vmw_surface_unreference(&vps->surf); 980 } 981 982 } 983 984 if (!vps->surf) { 985 ret = vmw_gb_surface_define(dev_priv, &metadata, 986 &vps->surf); 987 if (ret != 0) { 988 DRM_ERROR("Couldn't allocate STDU surface.\n"); 989 return ret; 990 } 991 } 992 } else { 993 /* 994 * prepare_fb and clean_fb should only take care of pinning 995 * and unpinning. References are tracked by state objects. 996 * The only time we add a reference in prepare_fb is if the 997 * state object doesn't have a reference to begin with 998 */ 999 if (vps->surf) { 1000 WARN_ON(vps->pinned != 0); 1001 vmw_surface_unreference(&vps->surf); 1002 } 1003 1004 vps->surf = vmw_surface_reference(new_vfbs->surface); 1005 } 1006 1007 if (vps->surf) { 1008 1009 /* Pin new surface before flipping */ 1010 ret = vmw_resource_pin(&vps->surf->res, false); 1011 if (ret) 1012 goto out_srf_unref; 1013 1014 vps->pinned++; 1015 } 1016 1017 vps->content_fb_type = new_content_type; 1018 1019 /* 1020 * This should only happen if the buffer object is too large to create a 1021 * proxy surface for. 1022 */ 1023 if (vps->content_fb_type == SEPARATE_BO) 1024 vps->cpp = new_fb->pitches[0] / new_fb->width; 1025 1026 return 0; 1027 1028 out_srf_unref: 1029 vmw_surface_unreference(&vps->surf); 1030 return ret; 1031 } 1032 1033 static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, 1034 uint32_t num_hits) 1035 { 1036 return sizeof(struct vmw_stdu_update_gb_image) + 1037 sizeof(struct vmw_stdu_update); 1038 } 1039 1040 static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, 1041 void *cmd, uint32_t num_hits) 1042 { 1043 struct vmw_du_update_plane_buffer *bo_update = 1044 container_of(update, typeof(*bo_update), base); 1045 1046 bo_update->fb_left = INT_MAX; 1047 bo_update->fb_top = INT_MAX; 1048 1049 return 0; 1050 } 1051 1052 static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane *update, 1053 void *cmd, struct drm_rect *clip, 1054 uint32_t fb_x, uint32_t fb_y) 1055 { 1056 struct vmw_du_update_plane_buffer *bo_update = 1057 container_of(update, typeof(*bo_update), base); 1058 1059 bo_update->fb_left = min_t(int, bo_update->fb_left, fb_x); 1060 bo_update->fb_top = min_t(int, bo_update->fb_top, fb_y); 1061 1062 return 0; 1063 } 1064 1065 static uint32_t 1066 vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd, 1067 struct drm_rect *bb) 1068 { 1069 struct vmw_du_update_plane_buffer *bo_update; 1070 struct vmw_screen_target_display_unit *stdu; 1071 struct vmw_framebuffer_bo *vfbbo; 1072 struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0); 1073 struct vmw_stdu_update_gb_image *cmd_img = cmd; 1074 struct vmw_stdu_update *cmd_update; 1075 struct ttm_buffer_object *src_bo, *dst_bo; 1076 u32 src_offset, dst_offset; 1077 s32 src_pitch, dst_pitch; 1078 s32 width, height; 1079 1080 bo_update = container_of(update, typeof(*bo_update), base); 1081 stdu = container_of(update->du, typeof(*stdu), base); 1082 vfbbo = container_of(update->vfb, typeof(*vfbbo), base); 1083 1084 width = bb->x2 - bb->x1; 1085 height = bb->y2 - bb->y1; 1086 1087 diff.cpp = stdu->cpp; 1088 1089 dst_bo = &stdu->display_srf->res.guest_memory_bo->tbo; 1090 dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; 1091 dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp; 1092 1093 src_bo = &vfbbo->buffer->tbo; 1094 src_pitch = update->vfb->base.pitches[0]; 1095 src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left * 1096 stdu->cpp; 1097 1098 (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, src_bo, 1099 src_offset, src_pitch, width * stdu->cpp, height, 1100 &diff); 1101 1102 if (drm_rect_visible(&diff.rect)) { 1103 SVGA3dBox *box = &cmd_img->body.box; 1104 1105 cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; 1106 cmd_img->header.size = sizeof(cmd_img->body); 1107 cmd_img->body.image.sid = stdu->display_srf->res.id; 1108 cmd_img->body.image.face = 0; 1109 cmd_img->body.image.mipmap = 0; 1110 1111 box->x = diff.rect.x1; 1112 box->y = diff.rect.y1; 1113 box->z = 0; 1114 box->w = drm_rect_width(&diff.rect); 1115 box->h = drm_rect_height(&diff.rect); 1116 box->d = 1; 1117 1118 cmd_update = (struct vmw_stdu_update *)&cmd_img[1]; 1119 vmw_stdu_populate_update(cmd_update, stdu->base.unit, 1120 diff.rect.x1, diff.rect.x2, 1121 diff.rect.y1, diff.rect.y2); 1122 1123 return sizeof(*cmd_img) + sizeof(*cmd_update); 1124 } 1125 1126 return 0; 1127 } 1128 1129 /** 1130 * vmw_stdu_plane_update_bo - Update display unit for bo backed fb. 1131 * @dev_priv: device private. 1132 * @plane: plane state. 1133 * @old_state: old plane state. 1134 * @vfb: framebuffer which is blitted to display unit. 1135 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. 1136 * The returned fence pointer may be NULL in which case the device 1137 * has already synchronized. 1138 * 1139 * Return: 0 on success or a negative error code on failure. 1140 */ 1141 static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, 1142 struct drm_plane *plane, 1143 struct drm_plane_state *old_state, 1144 struct vmw_framebuffer *vfb, 1145 struct vmw_fence_obj **out_fence) 1146 { 1147 struct vmw_du_update_plane_buffer bo_update; 1148 1149 memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer)); 1150 bo_update.base.plane = plane; 1151 bo_update.base.old_state = old_state; 1152 bo_update.base.dev_priv = dev_priv; 1153 bo_update.base.du = vmw_crtc_to_du(plane->state->crtc); 1154 bo_update.base.vfb = vfb; 1155 bo_update.base.out_fence = out_fence; 1156 bo_update.base.mutex = NULL; 1157 bo_update.base.intr = false; 1158 1159 bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; 1160 bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; 1161 bo_update.base.clip = vmw_stdu_bo_clip_cpu; 1162 bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; 1163 1164 return vmw_du_helper_plane_update(&bo_update.base); 1165 } 1166 1167 static uint32_t 1168 vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update, 1169 uint32_t num_hits) 1170 { 1171 struct vmw_framebuffer_surface *vfbs; 1172 uint32_t size = 0; 1173 1174 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1175 1176 if (vfbs->is_bo_proxy) 1177 size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; 1178 1179 size += sizeof(struct vmw_stdu_update); 1180 1181 return size; 1182 } 1183 1184 static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update, 1185 uint32_t num_hits) 1186 { 1187 struct vmw_framebuffer_surface *vfbs; 1188 uint32_t size = 0; 1189 1190 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1191 1192 if (vfbs->is_bo_proxy) 1193 size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; 1194 1195 size += sizeof(struct vmw_stdu_surface_copy) + sizeof(SVGA3dCopyBox) * 1196 num_hits + sizeof(struct vmw_stdu_update); 1197 1198 return size; 1199 } 1200 1201 static uint32_t 1202 vmw_stdu_surface_update_proxy(struct vmw_du_update_plane *update, void *cmd) 1203 { 1204 struct vmw_framebuffer_surface *vfbs; 1205 struct drm_plane_state *state = update->plane->state; 1206 struct drm_plane_state *old_state = update->old_state; 1207 struct vmw_stdu_update_gb_image *cmd_update = cmd; 1208 struct drm_atomic_helper_damage_iter iter; 1209 struct drm_rect clip; 1210 uint32_t copy_size = 0; 1211 1212 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1213 1214 /* 1215 * proxy surface is special where a buffer object type fb is wrapped 1216 * in a surface and need an update gb image command to sync with device. 1217 */ 1218 drm_atomic_helper_damage_iter_init(&iter, old_state, state); 1219 drm_atomic_for_each_plane_damage(&iter, &clip) { 1220 SVGA3dBox *box = &cmd_update->body.box; 1221 1222 cmd_update->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; 1223 cmd_update->header.size = sizeof(cmd_update->body); 1224 cmd_update->body.image.sid = vfbs->surface->res.id; 1225 cmd_update->body.image.face = 0; 1226 cmd_update->body.image.mipmap = 0; 1227 1228 box->x = clip.x1; 1229 box->y = clip.y1; 1230 box->z = 0; 1231 box->w = drm_rect_width(&clip); 1232 box->h = drm_rect_height(&clip); 1233 box->d = 1; 1234 1235 copy_size += sizeof(*cmd_update); 1236 cmd_update++; 1237 } 1238 1239 return copy_size; 1240 } 1241 1242 static uint32_t 1243 vmw_stdu_surface_populate_copy(struct vmw_du_update_plane *update, void *cmd, 1244 uint32_t num_hits) 1245 { 1246 struct vmw_screen_target_display_unit *stdu; 1247 struct vmw_framebuffer_surface *vfbs; 1248 struct vmw_stdu_surface_copy *cmd_copy = cmd; 1249 1250 stdu = container_of(update->du, typeof(*stdu), base); 1251 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1252 1253 cmd_copy->header.id = SVGA_3D_CMD_SURFACE_COPY; 1254 cmd_copy->header.size = sizeof(cmd_copy->body) + sizeof(SVGA3dCopyBox) * 1255 num_hits; 1256 cmd_copy->body.src.sid = vfbs->surface->res.id; 1257 cmd_copy->body.dest.sid = stdu->display_srf->res.id; 1258 1259 return sizeof(*cmd_copy); 1260 } 1261 1262 static uint32_t 1263 vmw_stdu_surface_populate_clip(struct vmw_du_update_plane *update, void *cmd, 1264 struct drm_rect *clip, uint32_t fb_x, 1265 uint32_t fb_y) 1266 { 1267 struct SVGA3dCopyBox *box = cmd; 1268 1269 box->srcx = fb_x; 1270 box->srcy = fb_y; 1271 box->srcz = 0; 1272 box->x = clip->x1; 1273 box->y = clip->y1; 1274 box->z = 0; 1275 box->w = drm_rect_width(clip); 1276 box->h = drm_rect_height(clip); 1277 box->d = 1; 1278 1279 return sizeof(*box); 1280 } 1281 1282 static uint32_t 1283 vmw_stdu_surface_populate_update(struct vmw_du_update_plane *update, void *cmd, 1284 struct drm_rect *bb) 1285 { 1286 vmw_stdu_populate_update(cmd, update->du->unit, bb->x1, bb->x2, bb->y1, 1287 bb->y2); 1288 1289 return sizeof(struct vmw_stdu_update); 1290 } 1291 1292 /** 1293 * vmw_stdu_plane_update_surface - Update display unit for surface backed fb 1294 * @dev_priv: Device private 1295 * @plane: Plane state 1296 * @old_state: Old plane state 1297 * @vfb: Framebuffer which is blitted to display unit 1298 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. 1299 * The returned fence pointer may be NULL in which case the device 1300 * has already synchronized. 1301 * 1302 * Return: 0 on success or a negative error code on failure. 1303 */ 1304 static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, 1305 struct drm_plane *plane, 1306 struct drm_plane_state *old_state, 1307 struct vmw_framebuffer *vfb, 1308 struct vmw_fence_obj **out_fence) 1309 { 1310 struct vmw_du_update_plane srf_update; 1311 struct vmw_screen_target_display_unit *stdu; 1312 struct vmw_framebuffer_surface *vfbs; 1313 1314 stdu = vmw_crtc_to_stdu(plane->state->crtc); 1315 vfbs = container_of(vfb, typeof(*vfbs), base); 1316 1317 memset(&srf_update, 0, sizeof(struct vmw_du_update_plane)); 1318 srf_update.plane = plane; 1319 srf_update.old_state = old_state; 1320 srf_update.dev_priv = dev_priv; 1321 srf_update.du = vmw_crtc_to_du(plane->state->crtc); 1322 srf_update.vfb = vfb; 1323 srf_update.out_fence = out_fence; 1324 srf_update.mutex = &dev_priv->cmdbuf_mutex; 1325 srf_update.intr = true; 1326 1327 if (vfbs->is_bo_proxy) 1328 srf_update.post_prepare = vmw_stdu_surface_update_proxy; 1329 1330 if (vfbs->surface->res.id != stdu->display_srf->res.id) { 1331 srf_update.calc_fifo_size = vmw_stdu_surface_fifo_size; 1332 srf_update.pre_clip = vmw_stdu_surface_populate_copy; 1333 srf_update.clip = vmw_stdu_surface_populate_clip; 1334 } else { 1335 srf_update.calc_fifo_size = 1336 vmw_stdu_surface_fifo_size_same_display; 1337 } 1338 1339 srf_update.post_clip = vmw_stdu_surface_populate_update; 1340 1341 return vmw_du_helper_plane_update(&srf_update); 1342 } 1343 1344 /** 1345 * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane 1346 * @plane: display plane 1347 * @state: Only used to get crtc info 1348 * 1349 * Formally update stdu->display_srf to the new plane, and bind the new 1350 * plane STDU. This function is called during the commit phase when 1351 * all the preparation have been done and all the configurations have 1352 * been checked. 1353 */ 1354 static void 1355 vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, 1356 struct drm_atomic_state *state) 1357 { 1358 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane); 1359 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); 1360 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); 1361 struct drm_crtc *crtc = new_state->crtc; 1362 struct vmw_screen_target_display_unit *stdu; 1363 struct vmw_fence_obj *fence = NULL; 1364 struct vmw_private *dev_priv; 1365 int ret; 1366 1367 /* If case of device error, maintain consistent atomic state */ 1368 if (crtc && new_state->fb) { 1369 struct vmw_framebuffer *vfb = 1370 vmw_framebuffer_to_vfb(new_state->fb); 1371 stdu = vmw_crtc_to_stdu(crtc); 1372 dev_priv = vmw_priv(crtc->dev); 1373 1374 stdu->display_srf = vps->surf; 1375 stdu->content_fb_type = vps->content_fb_type; 1376 stdu->cpp = vps->cpp; 1377 1378 ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); 1379 if (ret) 1380 DRM_ERROR("Failed to bind surface to STDU.\n"); 1381 1382 if (vfb->bo) 1383 ret = vmw_stdu_plane_update_bo(dev_priv, plane, 1384 old_state, vfb, &fence); 1385 else 1386 ret = vmw_stdu_plane_update_surface(dev_priv, plane, 1387 old_state, vfb, 1388 &fence); 1389 if (ret) 1390 DRM_ERROR("Failed to update STDU.\n"); 1391 } else { 1392 crtc = old_state->crtc; 1393 stdu = vmw_crtc_to_stdu(crtc); 1394 dev_priv = vmw_priv(crtc->dev); 1395 1396 /* Blank STDU when fb and crtc are NULL */ 1397 if (!stdu->defined) 1398 return; 1399 1400 ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); 1401 if (ret) 1402 DRM_ERROR("Failed to blank STDU\n"); 1403 1404 ret = vmw_stdu_update_st(dev_priv, stdu); 1405 if (ret) 1406 DRM_ERROR("Failed to update STDU.\n"); 1407 1408 return; 1409 } 1410 1411 if (fence) 1412 vmw_fence_obj_unreference(&fence); 1413 } 1414 1415 static void 1416 vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc, 1417 struct drm_atomic_state *state) 1418 { 1419 struct vmw_private *vmw = vmw_priv(crtc->dev); 1420 struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc); 1421 1422 if (vmw->vkms_enabled) 1423 vmw_vkms_set_crc_surface(crtc, stdu->display_srf); 1424 vmw_vkms_crtc_atomic_flush(crtc, state); 1425 } 1426 1427 static const struct drm_plane_funcs vmw_stdu_plane_funcs = { 1428 .update_plane = drm_atomic_helper_update_plane, 1429 .disable_plane = drm_atomic_helper_disable_plane, 1430 .destroy = vmw_du_primary_plane_destroy, 1431 .reset = vmw_du_plane_reset, 1432 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 1433 .atomic_destroy_state = vmw_du_plane_destroy_state, 1434 }; 1435 1436 static const struct drm_plane_funcs vmw_stdu_cursor_funcs = { 1437 .update_plane = drm_atomic_helper_update_plane, 1438 .disable_plane = drm_atomic_helper_disable_plane, 1439 .destroy = vmw_du_cursor_plane_destroy, 1440 .reset = vmw_du_plane_reset, 1441 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 1442 .atomic_destroy_state = vmw_du_plane_destroy_state, 1443 }; 1444 1445 1446 /* 1447 * Atomic Helpers 1448 */ 1449 static const struct 1450 drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs = { 1451 .atomic_check = vmw_du_cursor_plane_atomic_check, 1452 .atomic_update = vmw_du_cursor_plane_atomic_update, 1453 .prepare_fb = vmw_du_cursor_plane_prepare_fb, 1454 .cleanup_fb = vmw_du_cursor_plane_cleanup_fb, 1455 }; 1456 1457 static const struct 1458 drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = { 1459 .atomic_check = vmw_du_primary_plane_atomic_check, 1460 .atomic_update = vmw_stdu_primary_plane_atomic_update, 1461 .prepare_fb = vmw_stdu_primary_plane_prepare_fb, 1462 .cleanup_fb = vmw_stdu_primary_plane_cleanup_fb, 1463 }; 1464 1465 static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { 1466 .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb, 1467 .atomic_check = vmw_du_crtc_atomic_check, 1468 .atomic_begin = vmw_du_crtc_atomic_begin, 1469 .atomic_flush = vmw_stdu_crtc_atomic_flush, 1470 .atomic_enable = vmw_vkms_crtc_atomic_enable, 1471 .atomic_disable = vmw_stdu_crtc_atomic_disable, 1472 }; 1473 1474 1475 /** 1476 * vmw_stdu_init - Sets up a Screen Target Display Unit 1477 * 1478 * @dev_priv: VMW DRM device 1479 * @unit: unit number range from 0 to VMWGFX_NUM_DISPLAY_UNITS 1480 * 1481 * This function is called once per CRTC, and allocates one Screen Target 1482 * display unit to represent that CRTC. Since the SVGA device does not separate 1483 * out encoder and connector, they are represented as part of the STDU as well. 1484 * 1485 * Returns: %0 on success or -errno code on failure 1486 */ 1487 static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) 1488 { 1489 struct vmw_screen_target_display_unit *stdu; 1490 struct drm_device *dev = &dev_priv->drm; 1491 struct drm_connector *connector; 1492 struct drm_encoder *encoder; 1493 struct drm_plane *primary; 1494 struct vmw_cursor_plane *cursor; 1495 struct drm_crtc *crtc; 1496 int ret; 1497 1498 stdu = kzalloc(sizeof(*stdu), GFP_KERNEL); 1499 if (!stdu) 1500 return -ENOMEM; 1501 1502 stdu->base.unit = unit; 1503 crtc = &stdu->base.crtc; 1504 encoder = &stdu->base.encoder; 1505 connector = &stdu->base.connector; 1506 primary = &stdu->base.primary; 1507 cursor = &stdu->base.cursor; 1508 1509 stdu->base.pref_active = (unit == 0); 1510 stdu->base.pref_width = dev_priv->initial_width; 1511 stdu->base.pref_height = dev_priv->initial_height; 1512 stdu->base.is_implicit = false; 1513 1514 /* Initialize primary plane */ 1515 ret = drm_universal_plane_init(dev, primary, 1516 0, &vmw_stdu_plane_funcs, 1517 vmw_primary_plane_formats, 1518 ARRAY_SIZE(vmw_primary_plane_formats), 1519 NULL, DRM_PLANE_TYPE_PRIMARY, NULL); 1520 if (ret) { 1521 DRM_ERROR("Failed to initialize primary plane"); 1522 goto err_free; 1523 } 1524 1525 drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs); 1526 drm_plane_enable_fb_damage_clips(primary); 1527 1528 /* Initialize cursor plane */ 1529 ret = drm_universal_plane_init(dev, &cursor->base, 1530 0, &vmw_stdu_cursor_funcs, 1531 vmw_cursor_plane_formats, 1532 ARRAY_SIZE(vmw_cursor_plane_formats), 1533 NULL, DRM_PLANE_TYPE_CURSOR, NULL); 1534 if (ret) { 1535 DRM_ERROR("Failed to initialize cursor plane"); 1536 drm_plane_cleanup(&stdu->base.primary); 1537 goto err_free; 1538 } 1539 1540 drm_plane_helper_add(&cursor->base, &vmw_stdu_cursor_plane_helper_funcs); 1541 1542 ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs, 1543 DRM_MODE_CONNECTOR_VIRTUAL); 1544 if (ret) { 1545 DRM_ERROR("Failed to initialize connector\n"); 1546 goto err_free; 1547 } 1548 1549 drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs); 1550 connector->status = vmw_du_connector_detect(connector, false); 1551 1552 ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs, 1553 DRM_MODE_ENCODER_VIRTUAL, NULL); 1554 if (ret) { 1555 DRM_ERROR("Failed to initialize encoder\n"); 1556 goto err_free_connector; 1557 } 1558 1559 (void) drm_connector_attach_encoder(connector, encoder); 1560 encoder->possible_crtcs = (1 << unit); 1561 encoder->possible_clones = 0; 1562 1563 ret = drm_connector_register(connector); 1564 if (ret) { 1565 DRM_ERROR("Failed to register connector\n"); 1566 goto err_free_encoder; 1567 } 1568 1569 ret = drm_crtc_init_with_planes(dev, crtc, primary, 1570 &cursor->base, 1571 &vmw_stdu_crtc_funcs, NULL); 1572 if (ret) { 1573 DRM_ERROR("Failed to initialize CRTC\n"); 1574 goto err_free_unregister; 1575 } 1576 1577 drm_crtc_helper_add(crtc, &vmw_stdu_crtc_helper_funcs); 1578 1579 drm_mode_crtc_set_gamma_size(crtc, 256); 1580 1581 drm_object_attach_property(&connector->base, 1582 dev_priv->hotplug_mode_update_property, 1); 1583 drm_object_attach_property(&connector->base, 1584 dev->mode_config.suggested_x_property, 0); 1585 drm_object_attach_property(&connector->base, 1586 dev->mode_config.suggested_y_property, 0); 1587 1588 vmw_du_init(&stdu->base); 1589 1590 return 0; 1591 1592 err_free_unregister: 1593 drm_connector_unregister(connector); 1594 err_free_encoder: 1595 drm_encoder_cleanup(encoder); 1596 err_free_connector: 1597 drm_connector_cleanup(connector); 1598 err_free: 1599 kfree(stdu); 1600 return ret; 1601 } 1602 1603 1604 1605 /** 1606 * vmw_stdu_destroy - Cleans up a vmw_screen_target_display_unit 1607 * 1608 * @stdu: Screen Target Display Unit to be destroyed 1609 * 1610 * Clean up after vmw_stdu_init 1611 */ 1612 static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu) 1613 { 1614 vmw_du_cleanup(&stdu->base); 1615 kfree(stdu); 1616 } 1617 1618 1619 1620 /****************************************************************************** 1621 * Screen Target Display KMS Functions 1622 * 1623 * These functions are called by the common KMS code in vmwgfx_kms.c 1624 *****************************************************************************/ 1625 1626 /** 1627 * vmw_kms_stdu_init_display - Initializes a Screen Target based display 1628 * 1629 * @dev_priv: VMW DRM device 1630 * 1631 * This function initialize a Screen Target based display device. It checks 1632 * the capability bits to make sure the underlying hardware can support 1633 * screen targets, and then creates the maximum number of CRTCs, a.k.a Display 1634 * Units, as supported by the display hardware. 1635 * 1636 * RETURNS: 1637 * 0 on success, error code otherwise 1638 */ 1639 int vmw_kms_stdu_init_display(struct vmw_private *dev_priv) 1640 { 1641 struct drm_device *dev = &dev_priv->drm; 1642 int i, ret; 1643 1644 1645 /* Do nothing if there's no support for MOBs */ 1646 if (!dev_priv->has_mob) 1647 return -ENOSYS; 1648 1649 if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) 1650 return -ENOSYS; 1651 1652 dev_priv->active_display_unit = vmw_du_screen_target; 1653 1654 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) { 1655 ret = vmw_stdu_init(dev_priv, i); 1656 1657 if (unlikely(ret != 0)) { 1658 drm_err(&dev_priv->drm, 1659 "Failed to initialize STDU %d", i); 1660 return ret; 1661 } 1662 } 1663 1664 drm_mode_config_reset(dev); 1665 1666 return 0; 1667 } 1668