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