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