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 static const struct drm_connector_funcs vmw_stdu_connector_funcs = { 872 .dpms = vmw_du_connector_dpms, 873 .detect = vmw_du_connector_detect, 874 .fill_modes = drm_helper_probe_single_connector_modes, 875 .destroy = vmw_stdu_connector_destroy, 876 .reset = vmw_du_connector_reset, 877 .atomic_duplicate_state = vmw_du_connector_duplicate_state, 878 .atomic_destroy_state = vmw_du_connector_destroy_state, 879 }; 880 881 882 static const struct 883 drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { 884 .get_modes = vmw_connector_get_modes, 885 .mode_valid = vmw_stdu_connector_mode_valid 886 }; 887 888 889 890 /****************************************************************************** 891 * Screen Target Display Plane Functions 892 *****************************************************************************/ 893 894 895 896 /** 897 * vmw_stdu_primary_plane_cleanup_fb - Unpins the display surface 898 * 899 * @plane: display plane 900 * @old_state: Contains the FB to clean up 901 * 902 * Unpins the display surface 903 * 904 * Returns 0 on success 905 */ 906 static void 907 vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane, 908 struct drm_plane_state *old_state) 909 { 910 struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); 911 912 if (vps->surf) 913 WARN_ON(!vps->pinned); 914 915 vmw_du_plane_cleanup_fb(plane, old_state); 916 917 vps->content_fb_type = SAME_AS_DISPLAY; 918 vps->cpp = 0; 919 } 920 921 922 923 /** 924 * vmw_stdu_primary_plane_prepare_fb - Readies the display surface 925 * 926 * @plane: display plane 927 * @new_state: info on the new plane state, including the FB 928 * 929 * This function allocates a new display surface if the content is 930 * backed by a buffer object. The display surface is pinned here, and it'll 931 * be unpinned in .cleanup_fb() 932 * 933 * Returns 0 on success 934 */ 935 static int 936 vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, 937 struct drm_plane_state *new_state) 938 { 939 struct vmw_private *dev_priv = vmw_priv(plane->dev); 940 struct drm_framebuffer *new_fb = new_state->fb; 941 struct vmw_framebuffer *vfb; 942 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); 943 enum stdu_content_type new_content_type; 944 struct vmw_framebuffer_surface *new_vfbs; 945 uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h; 946 int ret; 947 948 /* No FB to prepare */ 949 if (!new_fb) { 950 if (vps->surf) { 951 WARN_ON(vps->pinned != 0); 952 vmw_surface_unreference(&vps->surf); 953 } 954 955 return 0; 956 } 957 958 vfb = vmw_framebuffer_to_vfb(new_fb); 959 new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb); 960 961 if (new_vfbs && 962 new_vfbs->surface->metadata.base_size.width == hdisplay && 963 new_vfbs->surface->metadata.base_size.height == vdisplay) 964 new_content_type = SAME_AS_DISPLAY; 965 else if (vfb->bo) 966 new_content_type = SEPARATE_BO; 967 else 968 new_content_type = SEPARATE_SURFACE; 969 970 if (new_content_type != SAME_AS_DISPLAY) { 971 struct vmw_surface_metadata metadata = {0}; 972 973 /* 974 * If content buffer is a buffer object, then we have to 975 * construct surface info 976 */ 977 if (new_content_type == SEPARATE_BO) { 978 979 switch (new_fb->format->cpp[0]*8) { 980 case 32: 981 metadata.format = SVGA3D_X8R8G8B8; 982 break; 983 984 case 16: 985 metadata.format = SVGA3D_R5G6B5; 986 break; 987 988 case 8: 989 metadata.format = SVGA3D_P8; 990 break; 991 992 default: 993 DRM_ERROR("Invalid format\n"); 994 return -EINVAL; 995 } 996 997 metadata.mip_levels[0] = 1; 998 metadata.num_sizes = 1; 999 metadata.scanout = true; 1000 } else { 1001 metadata = new_vfbs->surface->metadata; 1002 } 1003 1004 metadata.base_size.width = hdisplay; 1005 metadata.base_size.height = vdisplay; 1006 metadata.base_size.depth = 1; 1007 1008 if (vps->surf) { 1009 struct drm_vmw_size cur_base_size = 1010 vps->surf->metadata.base_size; 1011 1012 if (cur_base_size.width != metadata.base_size.width || 1013 cur_base_size.height != metadata.base_size.height || 1014 vps->surf->metadata.format != metadata.format) { 1015 WARN_ON(vps->pinned != 0); 1016 vmw_surface_unreference(&vps->surf); 1017 } 1018 1019 } 1020 1021 if (!vps->surf) { 1022 ret = vmw_gb_surface_define(dev_priv, &metadata, 1023 &vps->surf); 1024 if (ret != 0) { 1025 DRM_ERROR("Couldn't allocate STDU surface.\n"); 1026 return ret; 1027 } 1028 } 1029 } else { 1030 /* 1031 * prepare_fb and clean_fb should only take care of pinning 1032 * and unpinning. References are tracked by state objects. 1033 * The only time we add a reference in prepare_fb is if the 1034 * state object doesn't have a reference to begin with 1035 */ 1036 if (vps->surf) { 1037 WARN_ON(vps->pinned != 0); 1038 vmw_surface_unreference(&vps->surf); 1039 } 1040 1041 vps->surf = vmw_surface_reference(new_vfbs->surface); 1042 } 1043 1044 if (vps->surf) { 1045 1046 /* Pin new surface before flipping */ 1047 ret = vmw_resource_pin(&vps->surf->res, false); 1048 if (ret) 1049 goto out_srf_unref; 1050 1051 vps->pinned++; 1052 } 1053 1054 vps->content_fb_type = new_content_type; 1055 1056 /* 1057 * This should only happen if the buffer object is too large to create a 1058 * proxy surface for. 1059 */ 1060 if (vps->content_fb_type == SEPARATE_BO) 1061 vps->cpp = new_fb->pitches[0] / new_fb->width; 1062 1063 return 0; 1064 1065 out_srf_unref: 1066 vmw_surface_unreference(&vps->surf); 1067 return ret; 1068 } 1069 1070 static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, 1071 uint32_t num_hits) 1072 { 1073 return sizeof(struct vmw_stdu_update_gb_image) + 1074 sizeof(struct vmw_stdu_update); 1075 } 1076 1077 static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, 1078 void *cmd, uint32_t num_hits) 1079 { 1080 struct vmw_du_update_plane_buffer *bo_update = 1081 container_of(update, typeof(*bo_update), base); 1082 1083 bo_update->fb_left = INT_MAX; 1084 bo_update->fb_top = INT_MAX; 1085 1086 return 0; 1087 } 1088 1089 static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane *update, 1090 void *cmd, struct drm_rect *clip, 1091 uint32_t fb_x, uint32_t fb_y) 1092 { 1093 struct vmw_du_update_plane_buffer *bo_update = 1094 container_of(update, typeof(*bo_update), base); 1095 1096 bo_update->fb_left = min_t(int, bo_update->fb_left, fb_x); 1097 bo_update->fb_top = min_t(int, bo_update->fb_top, fb_y); 1098 1099 return 0; 1100 } 1101 1102 static uint32_t 1103 vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd, 1104 struct drm_rect *bb) 1105 { 1106 struct vmw_du_update_plane_buffer *bo_update; 1107 struct vmw_screen_target_display_unit *stdu; 1108 struct vmw_framebuffer_bo *vfbbo; 1109 struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0); 1110 struct vmw_stdu_update_gb_image *cmd_img = cmd; 1111 struct vmw_stdu_update *cmd_update; 1112 struct ttm_buffer_object *src_bo, *dst_bo; 1113 u32 src_offset, dst_offset; 1114 s32 src_pitch, dst_pitch; 1115 s32 width, height; 1116 1117 bo_update = container_of(update, typeof(*bo_update), base); 1118 stdu = container_of(update->du, typeof(*stdu), base); 1119 vfbbo = container_of(update->vfb, typeof(*vfbbo), base); 1120 1121 width = bb->x2 - bb->x1; 1122 height = bb->y2 - bb->y1; 1123 1124 diff.cpp = stdu->cpp; 1125 1126 dst_bo = &stdu->display_srf->res.guest_memory_bo->tbo; 1127 dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; 1128 dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp; 1129 1130 src_bo = &vfbbo->buffer->tbo; 1131 src_pitch = update->vfb->base.pitches[0]; 1132 src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left * 1133 stdu->cpp; 1134 1135 (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, src_bo, 1136 src_offset, src_pitch, width * stdu->cpp, height, 1137 &diff); 1138 1139 if (drm_rect_visible(&diff.rect)) { 1140 SVGA3dBox *box = &cmd_img->body.box; 1141 1142 cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; 1143 cmd_img->header.size = sizeof(cmd_img->body); 1144 cmd_img->body.image.sid = stdu->display_srf->res.id; 1145 cmd_img->body.image.face = 0; 1146 cmd_img->body.image.mipmap = 0; 1147 1148 box->x = diff.rect.x1; 1149 box->y = diff.rect.y1; 1150 box->z = 0; 1151 box->w = drm_rect_width(&diff.rect); 1152 box->h = drm_rect_height(&diff.rect); 1153 box->d = 1; 1154 1155 cmd_update = (struct vmw_stdu_update *)&cmd_img[1]; 1156 vmw_stdu_populate_update(cmd_update, stdu->base.unit, 1157 diff.rect.x1, diff.rect.x2, 1158 diff.rect.y1, diff.rect.y2); 1159 1160 return sizeof(*cmd_img) + sizeof(*cmd_update); 1161 } 1162 1163 return 0; 1164 } 1165 1166 /** 1167 * vmw_stdu_plane_update_bo - Update display unit for bo backed fb. 1168 * @dev_priv: device private. 1169 * @plane: plane state. 1170 * @old_state: old plane state. 1171 * @vfb: framebuffer which is blitted to display unit. 1172 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. 1173 * The returned fence pointer may be NULL in which case the device 1174 * has already synchronized. 1175 * 1176 * Return: 0 on success or a negative error code on failure. 1177 */ 1178 static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, 1179 struct drm_plane *plane, 1180 struct drm_plane_state *old_state, 1181 struct vmw_framebuffer *vfb, 1182 struct vmw_fence_obj **out_fence) 1183 { 1184 struct vmw_du_update_plane_buffer bo_update; 1185 1186 memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer)); 1187 bo_update.base.plane = plane; 1188 bo_update.base.old_state = old_state; 1189 bo_update.base.dev_priv = dev_priv; 1190 bo_update.base.du = vmw_crtc_to_du(plane->state->crtc); 1191 bo_update.base.vfb = vfb; 1192 bo_update.base.out_fence = out_fence; 1193 bo_update.base.mutex = NULL; 1194 bo_update.base.intr = false; 1195 1196 bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; 1197 bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; 1198 bo_update.base.clip = vmw_stdu_bo_clip_cpu; 1199 bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; 1200 1201 return vmw_du_helper_plane_update(&bo_update.base); 1202 } 1203 1204 static uint32_t 1205 vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update, 1206 uint32_t num_hits) 1207 { 1208 struct vmw_framebuffer_surface *vfbs; 1209 uint32_t size = 0; 1210 1211 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1212 1213 if (vfbs->is_bo_proxy) 1214 size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; 1215 1216 size += sizeof(struct vmw_stdu_update); 1217 1218 return size; 1219 } 1220 1221 static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update, 1222 uint32_t num_hits) 1223 { 1224 struct vmw_framebuffer_surface *vfbs; 1225 uint32_t size = 0; 1226 1227 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1228 1229 if (vfbs->is_bo_proxy) 1230 size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; 1231 1232 size += sizeof(struct vmw_stdu_surface_copy) + sizeof(SVGA3dCopyBox) * 1233 num_hits + sizeof(struct vmw_stdu_update); 1234 1235 return size; 1236 } 1237 1238 static uint32_t 1239 vmw_stdu_surface_update_proxy(struct vmw_du_update_plane *update, void *cmd) 1240 { 1241 struct vmw_framebuffer_surface *vfbs; 1242 struct drm_plane_state *state = update->plane->state; 1243 struct drm_plane_state *old_state = update->old_state; 1244 struct vmw_stdu_update_gb_image *cmd_update = cmd; 1245 struct drm_atomic_helper_damage_iter iter; 1246 struct drm_rect clip; 1247 uint32_t copy_size = 0; 1248 1249 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1250 1251 /* 1252 * proxy surface is special where a buffer object type fb is wrapped 1253 * in a surface and need an update gb image command to sync with device. 1254 */ 1255 drm_atomic_helper_damage_iter_init(&iter, old_state, state); 1256 drm_atomic_for_each_plane_damage(&iter, &clip) { 1257 SVGA3dBox *box = &cmd_update->body.box; 1258 1259 cmd_update->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; 1260 cmd_update->header.size = sizeof(cmd_update->body); 1261 cmd_update->body.image.sid = vfbs->surface->res.id; 1262 cmd_update->body.image.face = 0; 1263 cmd_update->body.image.mipmap = 0; 1264 1265 box->x = clip.x1; 1266 box->y = clip.y1; 1267 box->z = 0; 1268 box->w = drm_rect_width(&clip); 1269 box->h = drm_rect_height(&clip); 1270 box->d = 1; 1271 1272 copy_size += sizeof(*cmd_update); 1273 cmd_update++; 1274 } 1275 1276 return copy_size; 1277 } 1278 1279 static uint32_t 1280 vmw_stdu_surface_populate_copy(struct vmw_du_update_plane *update, void *cmd, 1281 uint32_t num_hits) 1282 { 1283 struct vmw_screen_target_display_unit *stdu; 1284 struct vmw_framebuffer_surface *vfbs; 1285 struct vmw_stdu_surface_copy *cmd_copy = cmd; 1286 1287 stdu = container_of(update->du, typeof(*stdu), base); 1288 vfbs = container_of(update->vfb, typeof(*vfbs), base); 1289 1290 cmd_copy->header.id = SVGA_3D_CMD_SURFACE_COPY; 1291 cmd_copy->header.size = sizeof(cmd_copy->body) + sizeof(SVGA3dCopyBox) * 1292 num_hits; 1293 cmd_copy->body.src.sid = vfbs->surface->res.id; 1294 cmd_copy->body.dest.sid = stdu->display_srf->res.id; 1295 1296 return sizeof(*cmd_copy); 1297 } 1298 1299 static uint32_t 1300 vmw_stdu_surface_populate_clip(struct vmw_du_update_plane *update, void *cmd, 1301 struct drm_rect *clip, uint32_t fb_x, 1302 uint32_t fb_y) 1303 { 1304 struct SVGA3dCopyBox *box = cmd; 1305 1306 box->srcx = fb_x; 1307 box->srcy = fb_y; 1308 box->srcz = 0; 1309 box->x = clip->x1; 1310 box->y = clip->y1; 1311 box->z = 0; 1312 box->w = drm_rect_width(clip); 1313 box->h = drm_rect_height(clip); 1314 box->d = 1; 1315 1316 return sizeof(*box); 1317 } 1318 1319 static uint32_t 1320 vmw_stdu_surface_populate_update(struct vmw_du_update_plane *update, void *cmd, 1321 struct drm_rect *bb) 1322 { 1323 vmw_stdu_populate_update(cmd, update->du->unit, bb->x1, bb->x2, bb->y1, 1324 bb->y2); 1325 1326 return sizeof(struct vmw_stdu_update); 1327 } 1328 1329 /** 1330 * vmw_stdu_plane_update_surface - Update display unit for surface backed fb 1331 * @dev_priv: Device private 1332 * @plane: Plane state 1333 * @old_state: Old plane state 1334 * @vfb: Framebuffer which is blitted to display unit 1335 * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj. 1336 * The returned fence pointer may be NULL in which case the device 1337 * has already synchronized. 1338 * 1339 * Return: 0 on success or a negative error code on failure. 1340 */ 1341 static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, 1342 struct drm_plane *plane, 1343 struct drm_plane_state *old_state, 1344 struct vmw_framebuffer *vfb, 1345 struct vmw_fence_obj **out_fence) 1346 { 1347 struct vmw_du_update_plane srf_update; 1348 struct vmw_screen_target_display_unit *stdu; 1349 struct vmw_framebuffer_surface *vfbs; 1350 1351 stdu = vmw_crtc_to_stdu(plane->state->crtc); 1352 vfbs = container_of(vfb, typeof(*vfbs), base); 1353 1354 memset(&srf_update, 0, sizeof(struct vmw_du_update_plane)); 1355 srf_update.plane = plane; 1356 srf_update.old_state = old_state; 1357 srf_update.dev_priv = dev_priv; 1358 srf_update.du = vmw_crtc_to_du(plane->state->crtc); 1359 srf_update.vfb = vfb; 1360 srf_update.out_fence = out_fence; 1361 srf_update.mutex = &dev_priv->cmdbuf_mutex; 1362 srf_update.intr = true; 1363 1364 if (vfbs->is_bo_proxy) 1365 srf_update.post_prepare = vmw_stdu_surface_update_proxy; 1366 1367 if (vfbs->surface->res.id != stdu->display_srf->res.id) { 1368 srf_update.calc_fifo_size = vmw_stdu_surface_fifo_size; 1369 srf_update.pre_clip = vmw_stdu_surface_populate_copy; 1370 srf_update.clip = vmw_stdu_surface_populate_clip; 1371 } else { 1372 srf_update.calc_fifo_size = 1373 vmw_stdu_surface_fifo_size_same_display; 1374 } 1375 1376 srf_update.post_clip = vmw_stdu_surface_populate_update; 1377 1378 return vmw_du_helper_plane_update(&srf_update); 1379 } 1380 1381 /** 1382 * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane 1383 * @plane: display plane 1384 * @state: Only used to get crtc info 1385 * 1386 * Formally update stdu->display_srf to the new plane, and bind the new 1387 * plane STDU. This function is called during the commit phase when 1388 * all the preparation have been done and all the configurations have 1389 * been checked. 1390 */ 1391 static void 1392 vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, 1393 struct drm_atomic_state *state) 1394 { 1395 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane); 1396 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); 1397 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); 1398 struct drm_crtc *crtc = new_state->crtc; 1399 struct vmw_screen_target_display_unit *stdu; 1400 struct vmw_fence_obj *fence = NULL; 1401 struct vmw_private *dev_priv; 1402 int ret; 1403 1404 /* If case of device error, maintain consistent atomic state */ 1405 if (crtc && new_state->fb) { 1406 struct vmw_framebuffer *vfb = 1407 vmw_framebuffer_to_vfb(new_state->fb); 1408 stdu = vmw_crtc_to_stdu(crtc); 1409 dev_priv = vmw_priv(crtc->dev); 1410 1411 stdu->display_srf = vps->surf; 1412 stdu->content_fb_type = vps->content_fb_type; 1413 stdu->cpp = vps->cpp; 1414 1415 ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); 1416 if (ret) 1417 DRM_ERROR("Failed to bind surface to STDU.\n"); 1418 1419 if (vfb->bo) 1420 ret = vmw_stdu_plane_update_bo(dev_priv, plane, 1421 old_state, vfb, &fence); 1422 else 1423 ret = vmw_stdu_plane_update_surface(dev_priv, plane, 1424 old_state, vfb, 1425 &fence); 1426 if (ret) 1427 DRM_ERROR("Failed to update STDU.\n"); 1428 } else { 1429 crtc = old_state->crtc; 1430 stdu = vmw_crtc_to_stdu(crtc); 1431 dev_priv = vmw_priv(crtc->dev); 1432 1433 /* Blank STDU when fb and crtc are NULL */ 1434 if (!stdu->defined) 1435 return; 1436 1437 ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); 1438 if (ret) 1439 DRM_ERROR("Failed to blank STDU\n"); 1440 1441 ret = vmw_stdu_update_st(dev_priv, stdu); 1442 if (ret) 1443 DRM_ERROR("Failed to update STDU.\n"); 1444 1445 return; 1446 } 1447 1448 if (fence) 1449 vmw_fence_obj_unreference(&fence); 1450 } 1451 1452 1453 static const struct drm_plane_funcs vmw_stdu_plane_funcs = { 1454 .update_plane = drm_atomic_helper_update_plane, 1455 .disable_plane = drm_atomic_helper_disable_plane, 1456 .destroy = vmw_du_primary_plane_destroy, 1457 .reset = vmw_du_plane_reset, 1458 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 1459 .atomic_destroy_state = vmw_du_plane_destroy_state, 1460 }; 1461 1462 static const struct drm_plane_funcs vmw_stdu_cursor_funcs = { 1463 .update_plane = drm_atomic_helper_update_plane, 1464 .disable_plane = drm_atomic_helper_disable_plane, 1465 .destroy = vmw_du_cursor_plane_destroy, 1466 .reset = vmw_du_plane_reset, 1467 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 1468 .atomic_destroy_state = vmw_du_plane_destroy_state, 1469 }; 1470 1471 1472 /* 1473 * Atomic Helpers 1474 */ 1475 static const struct 1476 drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs = { 1477 .atomic_check = vmw_du_cursor_plane_atomic_check, 1478 .atomic_update = vmw_du_cursor_plane_atomic_update, 1479 .prepare_fb = vmw_du_cursor_plane_prepare_fb, 1480 .cleanup_fb = vmw_du_cursor_plane_cleanup_fb, 1481 }; 1482 1483 static const struct 1484 drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = { 1485 .atomic_check = vmw_du_primary_plane_atomic_check, 1486 .atomic_update = vmw_stdu_primary_plane_atomic_update, 1487 .prepare_fb = vmw_stdu_primary_plane_prepare_fb, 1488 .cleanup_fb = vmw_stdu_primary_plane_cleanup_fb, 1489 }; 1490 1491 static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { 1492 .prepare = vmw_stdu_crtc_helper_prepare, 1493 .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb, 1494 .atomic_check = vmw_du_crtc_atomic_check, 1495 .atomic_begin = vmw_du_crtc_atomic_begin, 1496 .atomic_flush = vmw_du_crtc_atomic_flush, 1497 .atomic_enable = vmw_stdu_crtc_atomic_enable, 1498 .atomic_disable = vmw_stdu_crtc_atomic_disable, 1499 }; 1500 1501 1502 /** 1503 * vmw_stdu_init - Sets up a Screen Target Display Unit 1504 * 1505 * @dev_priv: VMW DRM device 1506 * @unit: unit number range from 0 to VMWGFX_NUM_DISPLAY_UNITS 1507 * 1508 * This function is called once per CRTC, and allocates one Screen Target 1509 * display unit to represent that CRTC. Since the SVGA device does not separate 1510 * out encoder and connector, they are represented as part of the STDU as well. 1511 */ 1512 static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) 1513 { 1514 struct vmw_screen_target_display_unit *stdu; 1515 struct drm_device *dev = &dev_priv->drm; 1516 struct drm_connector *connector; 1517 struct drm_encoder *encoder; 1518 struct drm_plane *primary; 1519 struct vmw_cursor_plane *cursor; 1520 struct drm_crtc *crtc; 1521 int ret; 1522 1523 stdu = kzalloc(sizeof(*stdu), GFP_KERNEL); 1524 if (!stdu) 1525 return -ENOMEM; 1526 1527 stdu->base.unit = unit; 1528 crtc = &stdu->base.crtc; 1529 encoder = &stdu->base.encoder; 1530 connector = &stdu->base.connector; 1531 primary = &stdu->base.primary; 1532 cursor = &stdu->base.cursor; 1533 1534 stdu->base.pref_active = (unit == 0); 1535 stdu->base.pref_width = dev_priv->initial_width; 1536 stdu->base.pref_height = dev_priv->initial_height; 1537 stdu->base.is_implicit = false; 1538 1539 /* Initialize primary plane */ 1540 ret = drm_universal_plane_init(dev, primary, 1541 0, &vmw_stdu_plane_funcs, 1542 vmw_primary_plane_formats, 1543 ARRAY_SIZE(vmw_primary_plane_formats), 1544 NULL, DRM_PLANE_TYPE_PRIMARY, NULL); 1545 if (ret) { 1546 DRM_ERROR("Failed to initialize primary plane"); 1547 goto err_free; 1548 } 1549 1550 drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs); 1551 drm_plane_enable_fb_damage_clips(primary); 1552 1553 /* Initialize cursor plane */ 1554 ret = drm_universal_plane_init(dev, &cursor->base, 1555 0, &vmw_stdu_cursor_funcs, 1556 vmw_cursor_plane_formats, 1557 ARRAY_SIZE(vmw_cursor_plane_formats), 1558 NULL, DRM_PLANE_TYPE_CURSOR, NULL); 1559 if (ret) { 1560 DRM_ERROR("Failed to initialize cursor plane"); 1561 drm_plane_cleanup(&stdu->base.primary); 1562 goto err_free; 1563 } 1564 1565 drm_plane_helper_add(&cursor->base, &vmw_stdu_cursor_plane_helper_funcs); 1566 1567 ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs, 1568 DRM_MODE_CONNECTOR_VIRTUAL); 1569 if (ret) { 1570 DRM_ERROR("Failed to initialize connector\n"); 1571 goto err_free; 1572 } 1573 1574 drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs); 1575 connector->status = vmw_du_connector_detect(connector, false); 1576 1577 ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs, 1578 DRM_MODE_ENCODER_VIRTUAL, NULL); 1579 if (ret) { 1580 DRM_ERROR("Failed to initialize encoder\n"); 1581 goto err_free_connector; 1582 } 1583 1584 (void) drm_connector_attach_encoder(connector, encoder); 1585 encoder->possible_crtcs = (1 << unit); 1586 encoder->possible_clones = 0; 1587 1588 ret = drm_connector_register(connector); 1589 if (ret) { 1590 DRM_ERROR("Failed to register connector\n"); 1591 goto err_free_encoder; 1592 } 1593 1594 ret = drm_crtc_init_with_planes(dev, crtc, primary, 1595 &cursor->base, 1596 &vmw_stdu_crtc_funcs, NULL); 1597 if (ret) { 1598 DRM_ERROR("Failed to initialize CRTC\n"); 1599 goto err_free_unregister; 1600 } 1601 1602 drm_crtc_helper_add(crtc, &vmw_stdu_crtc_helper_funcs); 1603 1604 drm_mode_crtc_set_gamma_size(crtc, 256); 1605 1606 drm_object_attach_property(&connector->base, 1607 dev_priv->hotplug_mode_update_property, 1); 1608 drm_object_attach_property(&connector->base, 1609 dev->mode_config.suggested_x_property, 0); 1610 drm_object_attach_property(&connector->base, 1611 dev->mode_config.suggested_y_property, 0); 1612 return 0; 1613 1614 err_free_unregister: 1615 drm_connector_unregister(connector); 1616 err_free_encoder: 1617 drm_encoder_cleanup(encoder); 1618 err_free_connector: 1619 drm_connector_cleanup(connector); 1620 err_free: 1621 kfree(stdu); 1622 return ret; 1623 } 1624 1625 1626 1627 /** 1628 * vmw_stdu_destroy - Cleans up a vmw_screen_target_display_unit 1629 * 1630 * @stdu: Screen Target Display Unit to be destroyed 1631 * 1632 * Clean up after vmw_stdu_init 1633 */ 1634 static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu) 1635 { 1636 vmw_du_cleanup(&stdu->base); 1637 kfree(stdu); 1638 } 1639 1640 1641 1642 /****************************************************************************** 1643 * Screen Target Display KMS Functions 1644 * 1645 * These functions are called by the common KMS code in vmwgfx_kms.c 1646 *****************************************************************************/ 1647 1648 /** 1649 * vmw_kms_stdu_init_display - Initializes a Screen Target based display 1650 * 1651 * @dev_priv: VMW DRM device 1652 * 1653 * This function initialize a Screen Target based display device. It checks 1654 * the capability bits to make sure the underlying hardware can support 1655 * screen targets, and then creates the maximum number of CRTCs, a.k.a Display 1656 * Units, as supported by the display hardware. 1657 * 1658 * RETURNS: 1659 * 0 on success, error code otherwise 1660 */ 1661 int vmw_kms_stdu_init_display(struct vmw_private *dev_priv) 1662 { 1663 struct drm_device *dev = &dev_priv->drm; 1664 int i, ret; 1665 1666 1667 /* Do nothing if there's no support for MOBs */ 1668 if (!dev_priv->has_mob) 1669 return -ENOSYS; 1670 1671 if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) 1672 return -ENOSYS; 1673 1674 dev_priv->active_display_unit = vmw_du_screen_target; 1675 1676 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) { 1677 ret = vmw_stdu_init(dev_priv, i); 1678 1679 if (unlikely(ret != 0)) { 1680 drm_err(&dev_priv->drm, 1681 "Failed to initialize STDU %d", i); 1682 return ret; 1683 } 1684 } 1685 1686 drm_mode_config_reset(dev); 1687 1688 return 0; 1689 } 1690