1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 /************************************************************************** 3 * 4 * Copyright 2009-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 #include "vmwgfx_bo.h" 28 #include "vmwgfx_drv.h" 29 30 #include "device_include/svga_overlay.h" 31 #include "device_include/svga_escape.h" 32 33 #include <drm/ttm/ttm_placement.h> 34 35 #define VMW_MAX_NUM_STREAMS 1 36 #define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE) 37 38 struct vmw_stream { 39 struct vmw_bo *buf; 40 bool claimed; 41 bool paused; 42 struct drm_vmw_control_stream_arg saved; 43 }; 44 45 /* 46 * Overlay control 47 */ 48 struct vmw_overlay { 49 /* 50 * Each stream is a single overlay. In Xv these are called ports. 51 */ 52 struct mutex mutex; 53 struct vmw_stream stream[VMW_MAX_NUM_STREAMS]; 54 }; 55 56 struct vmw_escape_header { 57 uint32_t cmd; 58 SVGAFifoCmdEscape body; 59 }; 60 61 struct vmw_escape_video_flush { 62 struct vmw_escape_header escape; 63 SVGAEscapeVideoFlush flush; 64 }; 65 66 static inline void fill_escape(struct vmw_escape_header *header, 67 uint32_t size) 68 { 69 header->cmd = SVGA_CMD_ESCAPE; 70 header->body.nsid = SVGA_ESCAPE_NSID_VMWARE; 71 header->body.size = size; 72 } 73 74 static inline void fill_flush(struct vmw_escape_video_flush *cmd, 75 uint32_t stream_id) 76 { 77 fill_escape(&cmd->escape, sizeof(cmd->flush)); 78 cmd->flush.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_FLUSH; 79 cmd->flush.streamId = stream_id; 80 } 81 82 /* 83 * Send put command to hw. 84 * 85 * Returns 86 * -ERESTARTSYS if interrupted by a signal. 87 */ 88 static int vmw_overlay_send_put(struct vmw_private *dev_priv, 89 struct vmw_bo *buf, 90 struct drm_vmw_control_stream_arg *arg, 91 bool interruptible) 92 { 93 struct vmw_escape_video_flush *flush; 94 size_t fifo_size; 95 bool have_so = (dev_priv->active_display_unit == vmw_du_screen_object); 96 int i, num_items; 97 SVGAGuestPtr ptr; 98 99 struct { 100 struct vmw_escape_header escape; 101 struct { 102 uint32_t cmdType; 103 uint32_t streamId; 104 } header; 105 } *cmds; 106 struct { 107 uint32_t registerId; 108 uint32_t value; 109 } *items; 110 111 /* defines are a index needs + 1 */ 112 if (have_so) 113 num_items = SVGA_VIDEO_DST_SCREEN_ID + 1; 114 else 115 num_items = SVGA_VIDEO_PITCH_3 + 1; 116 117 fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items; 118 119 cmds = VMW_CMD_RESERVE(dev_priv, fifo_size); 120 /* hardware has hung, can't do anything here */ 121 if (!cmds) 122 return -ENOMEM; 123 124 items = (typeof(items))&cmds[1]; 125 flush = (struct vmw_escape_video_flush *)&items[num_items]; 126 127 /* the size is header + number of items */ 128 fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1)); 129 130 cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; 131 cmds->header.streamId = arg->stream_id; 132 133 /* the IDs are neatly numbered */ 134 for (i = 0; i < num_items; i++) 135 items[i].registerId = i; 136 137 vmw_bo_get_guest_ptr(&buf->tbo, &ptr); 138 ptr.offset += arg->offset; 139 140 items[SVGA_VIDEO_ENABLED].value = true; 141 items[SVGA_VIDEO_FLAGS].value = arg->flags; 142 items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset; 143 items[SVGA_VIDEO_FORMAT].value = arg->format; 144 items[SVGA_VIDEO_COLORKEY].value = arg->color_key; 145 items[SVGA_VIDEO_SIZE].value = arg->size; 146 items[SVGA_VIDEO_WIDTH].value = arg->width; 147 items[SVGA_VIDEO_HEIGHT].value = arg->height; 148 items[SVGA_VIDEO_SRC_X].value = arg->src.x; 149 items[SVGA_VIDEO_SRC_Y].value = arg->src.y; 150 items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w; 151 items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h; 152 items[SVGA_VIDEO_DST_X].value = arg->dst.x; 153 items[SVGA_VIDEO_DST_Y].value = arg->dst.y; 154 items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w; 155 items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h; 156 items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0]; 157 items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1]; 158 items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2]; 159 if (have_so) { 160 items[SVGA_VIDEO_DATA_GMRID].value = ptr.gmrId; 161 items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID; 162 } 163 164 fill_flush(flush, arg->stream_id); 165 166 vmw_cmd_commit(dev_priv, fifo_size); 167 168 return 0; 169 } 170 171 /* 172 * Send stop command to hw. 173 * 174 * Returns 175 * -ERESTARTSYS if interrupted by a signal. 176 */ 177 static int vmw_overlay_send_stop(struct vmw_private *dev_priv, 178 uint32_t stream_id, 179 bool interruptible) 180 { 181 struct { 182 struct vmw_escape_header escape; 183 SVGAEscapeVideoSetRegs body; 184 struct vmw_escape_video_flush flush; 185 } *cmds; 186 int ret; 187 188 for (;;) { 189 cmds = VMW_CMD_RESERVE(dev_priv, sizeof(*cmds)); 190 if (cmds) 191 break; 192 193 ret = vmw_fallback_wait(dev_priv, false, true, 0, 194 interruptible, 3*HZ); 195 if (interruptible && ret == -ERESTARTSYS) 196 return ret; 197 else 198 BUG_ON(ret != 0); 199 } 200 201 fill_escape(&cmds->escape, sizeof(cmds->body)); 202 cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; 203 cmds->body.header.streamId = stream_id; 204 cmds->body.items[0].registerId = SVGA_VIDEO_ENABLED; 205 cmds->body.items[0].value = false; 206 fill_flush(&cmds->flush, stream_id); 207 208 vmw_cmd_commit(dev_priv, sizeof(*cmds)); 209 210 return 0; 211 } 212 213 /* 214 * Move a buffer to vram or gmr if @pin is set, else unpin the buffer. 215 * 216 * With the introduction of screen objects buffers could now be 217 * used with GMRs instead of being locked to vram. 218 */ 219 static int vmw_overlay_move_buffer(struct vmw_private *dev_priv, 220 struct vmw_bo *buf, 221 bool pin, bool inter) 222 { 223 if (!pin) 224 return vmw_bo_unpin(dev_priv, buf, inter); 225 226 if (dev_priv->active_display_unit == vmw_du_legacy) 227 return vmw_bo_pin_in_vram(dev_priv, buf, inter); 228 229 return vmw_bo_pin_in_vram_or_gmr(dev_priv, buf, inter); 230 } 231 232 /* 233 * Stop or pause a stream. 234 * 235 * If the stream is paused the no evict flag is removed from the buffer 236 * but left in vram. This allows for instance mode_set to evict it 237 * should it need to. 238 * 239 * The caller must hold the overlay lock. 240 * 241 * @stream_id which stream to stop/pause. 242 * @pause true to pause, false to stop completely. 243 */ 244 static int vmw_overlay_stop(struct vmw_private *dev_priv, 245 uint32_t stream_id, bool pause, 246 bool interruptible) 247 { 248 struct vmw_overlay *overlay = dev_priv->overlay_priv; 249 struct vmw_stream *stream = &overlay->stream[stream_id]; 250 int ret; 251 252 /* no buffer attached the stream is completely stopped */ 253 if (!stream->buf) 254 return 0; 255 256 /* If the stream is paused this is already done */ 257 if (!stream->paused) { 258 ret = vmw_overlay_send_stop(dev_priv, stream_id, 259 interruptible); 260 if (ret) 261 return ret; 262 263 /* We just remove the NO_EVICT flag so no -ENOMEM */ 264 ret = vmw_overlay_move_buffer(dev_priv, stream->buf, false, 265 interruptible); 266 if (interruptible && ret == -ERESTARTSYS) 267 return ret; 268 else 269 BUG_ON(ret != 0); 270 } 271 272 if (!pause) { 273 vmw_bo_unreference(&stream->buf); 274 stream->paused = false; 275 } else { 276 stream->paused = true; 277 } 278 279 return 0; 280 } 281 282 /* 283 * Update a stream and send any put or stop fifo commands needed. 284 * 285 * The caller must hold the overlay lock. 286 * 287 * Returns 288 * -ENOMEM if buffer doesn't fit in vram. 289 * -ERESTARTSYS if interrupted. 290 */ 291 static int vmw_overlay_update_stream(struct vmw_private *dev_priv, 292 struct vmw_bo *buf, 293 struct drm_vmw_control_stream_arg *arg, 294 bool interruptible) 295 { 296 struct vmw_overlay *overlay = dev_priv->overlay_priv; 297 struct vmw_stream *stream = &overlay->stream[arg->stream_id]; 298 int ret = 0; 299 300 if (!buf) 301 return -EINVAL; 302 303 DRM_DEBUG(" %s: old %p, new %p, %spaused\n", __func__, 304 stream->buf, buf, stream->paused ? "" : "not "); 305 306 if (stream->buf != buf) { 307 ret = vmw_overlay_stop(dev_priv, arg->stream_id, 308 false, interruptible); 309 if (ret) 310 return ret; 311 } else if (!stream->paused) { 312 /* If the buffers match and not paused then just send 313 * the put command, no need to do anything else. 314 */ 315 ret = vmw_overlay_send_put(dev_priv, buf, arg, interruptible); 316 if (ret == 0) 317 stream->saved = *arg; 318 else 319 BUG_ON(!interruptible); 320 321 return ret; 322 } 323 324 /* We don't start the old stream if we are interrupted. 325 * Might return -ENOMEM if it can't fit the buffer in vram. 326 */ 327 ret = vmw_overlay_move_buffer(dev_priv, buf, true, interruptible); 328 if (ret) 329 return ret; 330 331 ret = vmw_overlay_send_put(dev_priv, buf, arg, interruptible); 332 if (ret) { 333 /* This one needs to happen no matter what. We only remove 334 * the NO_EVICT flag so this is safe from -ENOMEM. 335 */ 336 BUG_ON(vmw_overlay_move_buffer(dev_priv, buf, false, false) 337 != 0); 338 return ret; 339 } 340 341 if (stream->buf != buf) 342 stream->buf = vmw_bo_reference(buf); 343 stream->saved = *arg; 344 /* stream is no longer stopped/paused */ 345 stream->paused = false; 346 347 return 0; 348 } 349 350 /* 351 * Try to resume all paused streams. 352 * 353 * Used by the kms code after moving a new scanout buffer to vram. 354 * 355 * Takes the overlay lock. 356 */ 357 int vmw_overlay_resume_all(struct vmw_private *dev_priv) 358 { 359 struct vmw_overlay *overlay = dev_priv->overlay_priv; 360 int i, ret; 361 362 if (!overlay) 363 return 0; 364 365 mutex_lock(&overlay->mutex); 366 367 for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { 368 struct vmw_stream *stream = &overlay->stream[i]; 369 if (!stream->paused) 370 continue; 371 372 ret = vmw_overlay_update_stream(dev_priv, stream->buf, 373 &stream->saved, false); 374 if (ret != 0) 375 DRM_INFO("%s: *warning* failed to resume stream %i\n", 376 __func__, i); 377 } 378 379 mutex_unlock(&overlay->mutex); 380 381 return 0; 382 } 383 384 /* 385 * Pauses all active streams. 386 * 387 * Used by the kms code when moving a new scanout buffer to vram. 388 * 389 * Takes the overlay lock. 390 */ 391 int vmw_overlay_pause_all(struct vmw_private *dev_priv) 392 { 393 struct vmw_overlay *overlay = dev_priv->overlay_priv; 394 int i, ret; 395 396 if (!overlay) 397 return 0; 398 399 mutex_lock(&overlay->mutex); 400 401 for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { 402 if (overlay->stream[i].paused) 403 DRM_INFO("%s: *warning* stream %i already paused\n", 404 __func__, i); 405 ret = vmw_overlay_stop(dev_priv, i, true, false); 406 WARN_ON(ret != 0); 407 } 408 409 mutex_unlock(&overlay->mutex); 410 411 return 0; 412 } 413 414 415 static bool vmw_overlay_available(const struct vmw_private *dev_priv) 416 { 417 return (dev_priv->overlay_priv != NULL && 418 ((vmw_fifo_caps(dev_priv) & VMW_OVERLAY_CAP_MASK) == 419 VMW_OVERLAY_CAP_MASK)); 420 } 421 422 int vmw_overlay_ioctl(struct drm_device *dev, void *data, 423 struct drm_file *file_priv) 424 { 425 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 426 struct vmw_private *dev_priv = vmw_priv(dev); 427 struct vmw_overlay *overlay = dev_priv->overlay_priv; 428 struct drm_vmw_control_stream_arg *arg = 429 (struct drm_vmw_control_stream_arg *)data; 430 struct vmw_bo *buf; 431 struct vmw_resource *res; 432 int ret; 433 434 if (!vmw_overlay_available(dev_priv)) 435 return -ENOSYS; 436 437 ret = vmw_user_stream_lookup(dev_priv, tfile, &arg->stream_id, &res); 438 if (ret) 439 return ret; 440 441 mutex_lock(&overlay->mutex); 442 443 if (!arg->enabled) { 444 ret = vmw_overlay_stop(dev_priv, arg->stream_id, false, true); 445 goto out_unlock; 446 } 447 448 ret = vmw_user_bo_lookup(file_priv, arg->handle, &buf); 449 if (ret) 450 goto out_unlock; 451 452 ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); 453 454 vmw_bo_unreference(&buf); 455 drm_gem_object_put(&buf->tbo.base); 456 457 out_unlock: 458 mutex_unlock(&overlay->mutex); 459 vmw_resource_unreference(&res); 460 461 return ret; 462 } 463 464 int vmw_overlay_num_overlays(struct vmw_private *dev_priv) 465 { 466 if (!vmw_overlay_available(dev_priv)) 467 return 0; 468 469 return VMW_MAX_NUM_STREAMS; 470 } 471 472 int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv) 473 { 474 struct vmw_overlay *overlay = dev_priv->overlay_priv; 475 int i, k; 476 477 if (!vmw_overlay_available(dev_priv)) 478 return 0; 479 480 mutex_lock(&overlay->mutex); 481 482 for (i = 0, k = 0; i < VMW_MAX_NUM_STREAMS; i++) 483 if (!overlay->stream[i].claimed) 484 k++; 485 486 mutex_unlock(&overlay->mutex); 487 488 return k; 489 } 490 491 int vmw_overlay_claim(struct vmw_private *dev_priv, uint32_t *out) 492 { 493 struct vmw_overlay *overlay = dev_priv->overlay_priv; 494 int i; 495 496 if (!overlay) 497 return -ENOSYS; 498 499 mutex_lock(&overlay->mutex); 500 501 for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { 502 503 if (overlay->stream[i].claimed) 504 continue; 505 506 overlay->stream[i].claimed = true; 507 *out = i; 508 mutex_unlock(&overlay->mutex); 509 return 0; 510 } 511 512 mutex_unlock(&overlay->mutex); 513 return -ESRCH; 514 } 515 516 int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id) 517 { 518 struct vmw_overlay *overlay = dev_priv->overlay_priv; 519 520 BUG_ON(stream_id >= VMW_MAX_NUM_STREAMS); 521 522 if (!overlay) 523 return -ENOSYS; 524 525 mutex_lock(&overlay->mutex); 526 527 WARN_ON(!overlay->stream[stream_id].claimed); 528 vmw_overlay_stop(dev_priv, stream_id, false, false); 529 overlay->stream[stream_id].claimed = false; 530 531 mutex_unlock(&overlay->mutex); 532 return 0; 533 } 534 535 int vmw_overlay_init(struct vmw_private *dev_priv) 536 { 537 struct vmw_overlay *overlay; 538 int i; 539 540 if (dev_priv->overlay_priv) 541 return -EINVAL; 542 543 overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); 544 if (!overlay) 545 return -ENOMEM; 546 547 mutex_init(&overlay->mutex); 548 for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { 549 overlay->stream[i].buf = NULL; 550 overlay->stream[i].paused = false; 551 overlay->stream[i].claimed = false; 552 } 553 554 dev_priv->overlay_priv = overlay; 555 556 return 0; 557 } 558 559 int vmw_overlay_close(struct vmw_private *dev_priv) 560 { 561 struct vmw_overlay *overlay = dev_priv->overlay_priv; 562 bool forgotten_buffer = false; 563 int i; 564 565 if (!overlay) 566 return -ENOSYS; 567 568 for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { 569 if (overlay->stream[i].buf) { 570 forgotten_buffer = true; 571 vmw_overlay_stop(dev_priv, i, false, false); 572 } 573 } 574 575 WARN_ON(forgotten_buffer); 576 577 dev_priv->overlay_priv = NULL; 578 kfree(overlay); 579 580 return 0; 581 } 582