1 /**************************************************************************
3 * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 #include "vmwgfx_drv.h"
32 #include "ttm/ttm_placement.h"
34 #include "svga_overlay.h"
35 #include "svga_escape.h"
37 #define VMW_MAX_NUM_STREAMS 1
40 struct vmw_dma_buffer
*buf
;
43 struct drm_vmw_control_stream_arg saved
;
51 * Each stream is a single overlay. In Xv these are called ports.
54 struct vmw_stream stream
[VMW_MAX_NUM_STREAMS
];
57 static inline struct vmw_overlay
*vmw_overlay(struct drm_device
*dev
)
59 struct vmw_private
*dev_priv
= vmw_priv(dev
);
60 return dev_priv
? dev_priv
->overlay_priv
: NULL
;
63 struct vmw_escape_header
{
65 SVGAFifoCmdEscape body
;
68 struct vmw_escape_video_flush
{
69 struct vmw_escape_header escape
;
70 SVGAEscapeVideoFlush flush
;
73 static inline void fill_escape(struct vmw_escape_header
*header
,
76 header
->cmd
= SVGA_CMD_ESCAPE
;
77 header
->body
.nsid
= SVGA_ESCAPE_NSID_VMWARE
;
78 header
->body
.size
= size
;
81 static inline void fill_flush(struct vmw_escape_video_flush
*cmd
,
84 fill_escape(&cmd
->escape
, sizeof(cmd
->flush
));
85 cmd
->flush
.cmdType
= SVGA_ESCAPE_VMWARE_VIDEO_FLUSH
;
86 cmd
->flush
.streamId
= stream_id
;
90 * Send put command to hw.
93 * -ERESTARTSYS if interrupted by a signal.
95 static int vmw_overlay_send_put(struct vmw_private
*dev_priv
,
96 struct vmw_dma_buffer
*buf
,
97 struct drm_vmw_control_stream_arg
*arg
,
100 struct vmw_escape_video_flush
*flush
;
102 bool have_so
= dev_priv
->sou_priv
? true : false;
107 struct vmw_escape_header escape
;
118 /* defines are a index needs + 1 */
120 num_items
= SVGA_VIDEO_DST_SCREEN_ID
+ 1;
122 num_items
= SVGA_VIDEO_PITCH_3
+ 1;
124 fifo_size
= sizeof(*cmds
) + sizeof(*flush
) + sizeof(*items
) * num_items
;
126 cmds
= vmw_fifo_reserve(dev_priv
, fifo_size
);
127 /* hardware has hung, can't do anything here */
131 items
= (typeof(items
))&cmds
[1];
132 flush
= (struct vmw_escape_video_flush
*)&items
[num_items
];
134 /* the size is header + number of items */
135 fill_escape(&cmds
->escape
, sizeof(*items
) * (num_items
+ 1));
137 cmds
->header
.cmdType
= SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS
;
138 cmds
->header
.streamId
= arg
->stream_id
;
140 /* the IDs are neatly numbered */
141 for (i
= 0; i
< num_items
; i
++)
142 items
[i
].registerId
= i
;
144 vmw_bo_get_guest_ptr(&buf
->base
, &ptr
);
145 ptr
.offset
+= arg
->offset
;
147 items
[SVGA_VIDEO_ENABLED
].value
= true;
148 items
[SVGA_VIDEO_FLAGS
].value
= arg
->flags
;
149 items
[SVGA_VIDEO_DATA_OFFSET
].value
= ptr
.offset
;
150 items
[SVGA_VIDEO_FORMAT
].value
= arg
->format
;
151 items
[SVGA_VIDEO_COLORKEY
].value
= arg
->color_key
;
152 items
[SVGA_VIDEO_SIZE
].value
= arg
->size
;
153 items
[SVGA_VIDEO_WIDTH
].value
= arg
->width
;
154 items
[SVGA_VIDEO_HEIGHT
].value
= arg
->height
;
155 items
[SVGA_VIDEO_SRC_X
].value
= arg
->src
.x
;
156 items
[SVGA_VIDEO_SRC_Y
].value
= arg
->src
.y
;
157 items
[SVGA_VIDEO_SRC_WIDTH
].value
= arg
->src
.w
;
158 items
[SVGA_VIDEO_SRC_HEIGHT
].value
= arg
->src
.h
;
159 items
[SVGA_VIDEO_DST_X
].value
= arg
->dst
.x
;
160 items
[SVGA_VIDEO_DST_Y
].value
= arg
->dst
.y
;
161 items
[SVGA_VIDEO_DST_WIDTH
].value
= arg
->dst
.w
;
162 items
[SVGA_VIDEO_DST_HEIGHT
].value
= arg
->dst
.h
;
163 items
[SVGA_VIDEO_PITCH_1
].value
= arg
->pitch
[0];
164 items
[SVGA_VIDEO_PITCH_2
].value
= arg
->pitch
[1];
165 items
[SVGA_VIDEO_PITCH_3
].value
= arg
->pitch
[2];
167 items
[SVGA_VIDEO_DATA_GMRID
].value
= ptr
.gmrId
;
168 items
[SVGA_VIDEO_DST_SCREEN_ID
].value
= SVGA_ID_INVALID
;
171 fill_flush(flush
, arg
->stream_id
);
173 vmw_fifo_commit(dev_priv
, fifo_size
);
179 * Send stop command to hw.
182 * -ERESTARTSYS if interrupted by a signal.
184 static int vmw_overlay_send_stop(struct vmw_private
*dev_priv
,
189 struct vmw_escape_header escape
;
190 SVGAEscapeVideoSetRegs body
;
191 struct vmw_escape_video_flush flush
;
196 cmds
= vmw_fifo_reserve(dev_priv
, sizeof(*cmds
));
200 ret
= vmw_fallback_wait(dev_priv
, false, true, 0,
201 interruptible
, 3*HZ
);
202 if (interruptible
&& ret
== -ERESTARTSYS
)
208 fill_escape(&cmds
->escape
, sizeof(cmds
->body
));
209 cmds
->body
.header
.cmdType
= SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS
;
210 cmds
->body
.header
.streamId
= stream_id
;
211 cmds
->body
.items
[0].registerId
= SVGA_VIDEO_ENABLED
;
212 cmds
->body
.items
[0].value
= false;
213 fill_flush(&cmds
->flush
, stream_id
);
215 vmw_fifo_commit(dev_priv
, sizeof(*cmds
));
221 * Move a buffer to vram or gmr if @pin is set, else unpin the buffer.
223 * With the introduction of screen objects buffers could now be
224 * used with GMRs instead of being locked to vram.
226 static int vmw_overlay_move_buffer(struct vmw_private
*dev_priv
,
227 struct vmw_dma_buffer
*buf
,
228 bool pin
, bool inter
)
231 return vmw_dmabuf_unpin(dev_priv
, buf
, inter
);
233 if (!dev_priv
->sou_priv
)
234 return vmw_dmabuf_to_vram(dev_priv
, buf
, true, inter
);
236 return vmw_dmabuf_to_vram_or_gmr(dev_priv
, buf
, true, inter
);
240 * Stop or pause a stream.
242 * If the stream is paused the no evict flag is removed from the buffer
243 * but left in vram. This allows for instance mode_set to evict it
246 * The caller must hold the overlay lock.
248 * @stream_id which stream to stop/pause.
249 * @pause true to pause, false to stop completely.
251 static int vmw_overlay_stop(struct vmw_private
*dev_priv
,
252 uint32_t stream_id
, bool pause
,
255 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
256 struct vmw_stream
*stream
= &overlay
->stream
[stream_id
];
259 /* no buffer attached the stream is completely stopped */
263 /* If the stream is paused this is already done */
264 if (!stream
->paused
) {
265 ret
= vmw_overlay_send_stop(dev_priv
, stream_id
,
270 /* We just remove the NO_EVICT flag so no -ENOMEM */
271 ret
= vmw_overlay_move_buffer(dev_priv
, stream
->buf
, false,
273 if (interruptible
&& ret
== -ERESTARTSYS
)
280 vmw_dmabuf_unreference(&stream
->buf
);
281 stream
->paused
= false;
283 stream
->paused
= true;
290 * Update a stream and send any put or stop fifo commands needed.
292 * The caller must hold the overlay lock.
295 * -ENOMEM if buffer doesn't fit in vram.
296 * -ERESTARTSYS if interrupted.
298 static int vmw_overlay_update_stream(struct vmw_private
*dev_priv
,
299 struct vmw_dma_buffer
*buf
,
300 struct drm_vmw_control_stream_arg
*arg
,
303 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
304 struct vmw_stream
*stream
= &overlay
->stream
[arg
->stream_id
];
310 DRM_DEBUG(" %s: old %p, new %p, %spaused\n", __func__
,
311 stream
->buf
, buf
, stream
->paused
? "" : "not ");
313 if (stream
->buf
!= buf
) {
314 ret
= vmw_overlay_stop(dev_priv
, arg
->stream_id
,
315 false, interruptible
);
318 } else if (!stream
->paused
) {
319 /* If the buffers match and not paused then just send
320 * the put command, no need to do anything else.
322 ret
= vmw_overlay_send_put(dev_priv
, buf
, arg
, interruptible
);
324 stream
->saved
= *arg
;
326 BUG_ON(!interruptible
);
331 /* We don't start the old stream if we are interrupted.
332 * Might return -ENOMEM if it can't fit the buffer in vram.
334 ret
= vmw_overlay_move_buffer(dev_priv
, buf
, true, interruptible
);
338 ret
= vmw_overlay_send_put(dev_priv
, buf
, arg
, interruptible
);
340 /* This one needs to happen no matter what. We only remove
341 * the NO_EVICT flag so this is safe from -ENOMEM.
343 BUG_ON(vmw_overlay_move_buffer(dev_priv
, buf
, false, false)
348 if (stream
->buf
!= buf
)
349 stream
->buf
= vmw_dmabuf_reference(buf
);
350 stream
->saved
= *arg
;
351 /* stream is no longer stopped/paused */
352 stream
->paused
= false;
360 * Used by the fb code when starting.
362 * Takes the overlay lock.
364 int vmw_overlay_stop_all(struct vmw_private
*dev_priv
)
366 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
372 mutex_lock(&overlay
->mutex
);
374 for (i
= 0; i
< VMW_MAX_NUM_STREAMS
; i
++) {
375 struct vmw_stream
*stream
= &overlay
->stream
[i
];
379 ret
= vmw_overlay_stop(dev_priv
, i
, false, false);
383 mutex_unlock(&overlay
->mutex
);
389 * Try to resume all paused streams.
391 * Used by the kms code after moving a new scanout buffer to vram.
393 * Takes the overlay lock.
395 int vmw_overlay_resume_all(struct vmw_private
*dev_priv
)
397 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
403 mutex_lock(&overlay
->mutex
);
405 for (i
= 0; i
< VMW_MAX_NUM_STREAMS
; i
++) {
406 struct vmw_stream
*stream
= &overlay
->stream
[i
];
410 ret
= vmw_overlay_update_stream(dev_priv
, stream
->buf
,
411 &stream
->saved
, false);
413 DRM_INFO("%s: *warning* failed to resume stream %i\n",
417 mutex_unlock(&overlay
->mutex
);
423 * Pauses all active streams.
425 * Used by the kms code when moving a new scanout buffer to vram.
427 * Takes the overlay lock.
429 int vmw_overlay_pause_all(struct vmw_private
*dev_priv
)
431 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
437 mutex_lock(&overlay
->mutex
);
439 for (i
= 0; i
< VMW_MAX_NUM_STREAMS
; i
++) {
440 if (overlay
->stream
[i
].paused
)
441 DRM_INFO("%s: *warning* stream %i already paused\n",
443 ret
= vmw_overlay_stop(dev_priv
, i
, true, false);
447 mutex_unlock(&overlay
->mutex
);
452 int vmw_overlay_ioctl(struct drm_device
*dev
, void *data
,
453 struct drm_file
*file_priv
)
455 struct ttm_object_file
*tfile
= vmw_fpriv(file_priv
)->tfile
;
456 struct vmw_private
*dev_priv
= vmw_priv(dev
);
457 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
458 struct drm_vmw_control_stream_arg
*arg
=
459 (struct drm_vmw_control_stream_arg
*)data
;
460 struct vmw_dma_buffer
*buf
;
461 struct vmw_resource
*res
;
467 ret
= vmw_user_stream_lookup(dev_priv
, tfile
, &arg
->stream_id
, &res
);
471 mutex_lock(&overlay
->mutex
);
474 ret
= vmw_overlay_stop(dev_priv
, arg
->stream_id
, false, true);
478 ret
= vmw_user_dmabuf_lookup(tfile
, arg
->handle
, &buf
);
482 ret
= vmw_overlay_update_stream(dev_priv
, buf
, arg
, true);
484 vmw_dmabuf_unreference(&buf
);
487 mutex_unlock(&overlay
->mutex
);
488 vmw_resource_unreference(&res
);
493 int vmw_overlay_num_overlays(struct vmw_private
*dev_priv
)
495 if (!dev_priv
->overlay_priv
)
498 return VMW_MAX_NUM_STREAMS
;
501 int vmw_overlay_num_free_overlays(struct vmw_private
*dev_priv
)
503 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
509 mutex_lock(&overlay
->mutex
);
511 for (i
= 0, k
= 0; i
< VMW_MAX_NUM_STREAMS
; i
++)
512 if (!overlay
->stream
[i
].claimed
)
515 mutex_unlock(&overlay
->mutex
);
520 int vmw_overlay_claim(struct vmw_private
*dev_priv
, uint32_t *out
)
522 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
528 mutex_lock(&overlay
->mutex
);
530 for (i
= 0; i
< VMW_MAX_NUM_STREAMS
; i
++) {
532 if (overlay
->stream
[i
].claimed
)
535 overlay
->stream
[i
].claimed
= true;
537 mutex_unlock(&overlay
->mutex
);
541 mutex_unlock(&overlay
->mutex
);
545 int vmw_overlay_unref(struct vmw_private
*dev_priv
, uint32_t stream_id
)
547 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
549 BUG_ON(stream_id
>= VMW_MAX_NUM_STREAMS
);
554 mutex_lock(&overlay
->mutex
);
556 WARN_ON(!overlay
->stream
[stream_id
].claimed
);
557 vmw_overlay_stop(dev_priv
, stream_id
, false, false);
558 overlay
->stream
[stream_id
].claimed
= false;
560 mutex_unlock(&overlay
->mutex
);
564 int vmw_overlay_init(struct vmw_private
*dev_priv
)
566 struct vmw_overlay
*overlay
;
569 if (dev_priv
->overlay_priv
)
572 if (!(dev_priv
->fifo
.capabilities
& SVGA_FIFO_CAP_VIDEO
) &&
573 (dev_priv
->fifo
.capabilities
& SVGA_FIFO_CAP_ESCAPE
)) {
574 DRM_INFO("hardware doesn't support overlays\n");
578 overlay
= kzalloc(sizeof(*overlay
), GFP_KERNEL
);
582 mutex_init(&overlay
->mutex
);
583 for (i
= 0; i
< VMW_MAX_NUM_STREAMS
; i
++) {
584 overlay
->stream
[i
].buf
= NULL
;
585 overlay
->stream
[i
].paused
= false;
586 overlay
->stream
[i
].claimed
= false;
589 dev_priv
->overlay_priv
= overlay
;
594 int vmw_overlay_close(struct vmw_private
*dev_priv
)
596 struct vmw_overlay
*overlay
= dev_priv
->overlay_priv
;
597 bool forgotten_buffer
= false;
603 for (i
= 0; i
< VMW_MAX_NUM_STREAMS
; i
++) {
604 if (overlay
->stream
[i
].buf
) {
605 forgotten_buffer
= true;
606 vmw_overlay_stop(dev_priv
, i
, false, false);
610 WARN_ON(forgotten_buffer
);
612 dev_priv
->overlay_priv
= NULL
;