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