Skip to content

Commit 36cc79b

Browse files
author
Sinclair Yeh
committed
drm/vmwgfx: Add universal plane support
Universal support is prerequisite for atomic mode set. Explicitly create planes for the cursor and the primary FB. With a functional cursor plane, the DRM will no longer use the legacy cursor_set2 and cursor_move entry points. Signed-off-by: Sinclair Yeh <syeh@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
1 parent 27d247c commit 36cc79b

File tree

7 files changed

+398
-198
lines changed

7 files changed

+398
-198
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
650650
spin_lock_init(&dev_priv->waiter_lock);
651651
spin_lock_init(&dev_priv->cap_lock);
652652
spin_lock_init(&dev_priv->svga_lock);
653+
spin_lock_init(&dev_priv->cursor_lock);
653654

654655
for (i = vmw_res_context; i < vmw_res_max; ++i) {
655656
idr_init(&dev_priv->res_idr[i]);

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ struct vmw_private {
414414
unsigned num_implicit;
415415
struct vmw_framebuffer *implicit_fb;
416416
struct mutex global_kms_state_mutex;
417+
spinlock_t cursor_lock;
417418

418419
/*
419420
* Context and surface management.

drivers/gpu/drm/vmwgfx/vmwgfx_kms.c

Lines changed: 133 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@
3333

3434
void vmw_du_cleanup(struct vmw_display_unit *du)
3535
{
36-
if (du->cursor_surface)
37-
vmw_surface_unreference(&du->cursor_surface);
38-
if (du->cursor_dmabuf)
39-
vmw_dmabuf_unreference(&du->cursor_dmabuf);
36+
drm_plane_cleanup(&du->primary);
37+
drm_plane_cleanup(&du->cursor);
38+
4039
drm_connector_unregister(&du->connector);
4140
drm_crtc_cleanup(&du->crtc);
4241
drm_encoder_cleanup(&du->encoder);
@@ -47,9 +46,9 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
4746
* Display Unit Cursor functions
4847
*/
4948

50-
int vmw_cursor_update_image(struct vmw_private *dev_priv,
51-
u32 *image, u32 width, u32 height,
52-
u32 hotspotX, u32 hotspotY)
49+
static int vmw_cursor_update_image(struct vmw_private *dev_priv,
50+
u32 *image, u32 width, u32 height,
51+
u32 hotspotX, u32 hotspotY)
5352
{
5453
struct {
5554
u32 cmd;
@@ -83,10 +82,10 @@ int vmw_cursor_update_image(struct vmw_private *dev_priv,
8382
return 0;
8483
}
8584

86-
int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
87-
struct vmw_dma_buffer *dmabuf,
88-
u32 width, u32 height,
89-
u32 hotspotX, u32 hotspotY)
85+
static int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
86+
struct vmw_dma_buffer *dmabuf,
87+
u32 width, u32 height,
88+
u32 hotspotX, u32 hotspotY)
9089
{
9190
struct ttm_bo_kmap_obj map;
9291
unsigned long kmap_offset;
@@ -120,145 +119,22 @@ int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
120119
}
121120

122121

123-
void vmw_cursor_update_position(struct vmw_private *dev_priv,
124-
bool show, int x, int y)
122+
static void vmw_cursor_update_position(struct vmw_private *dev_priv,
123+
bool show, int x, int y)
125124
{
126125
u32 *fifo_mem = dev_priv->mmio_virt;
127126
uint32_t count;
128127

128+
spin_lock(&dev_priv->cursor_lock);
129129
vmw_mmio_write(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
130130
vmw_mmio_write(x, fifo_mem + SVGA_FIFO_CURSOR_X);
131131
vmw_mmio_write(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
132132
count = vmw_mmio_read(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
133133
vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
134+
spin_unlock(&dev_priv->cursor_lock);
134135
}
135136

136137

137-
/*
138-
* vmw_du_crtc_cursor_set2 - Driver cursor_set2 callback.
139-
*/
140-
int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
141-
uint32_t handle, uint32_t width, uint32_t height,
142-
int32_t hot_x, int32_t hot_y)
143-
{
144-
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
145-
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
146-
struct vmw_surface *surface = NULL;
147-
struct vmw_dma_buffer *dmabuf = NULL;
148-
s32 hotspot_x, hotspot_y;
149-
int ret;
150-
151-
/*
152-
* FIXME: Unclear whether there's any global state touched by the
153-
* cursor_set function, especially vmw_cursor_update_position looks
154-
* suspicious. For now take the easy route and reacquire all locks. We
155-
* can do this since the caller in the drm core doesn't check anything
156-
* which is protected by any looks.
157-
*/
158-
drm_modeset_unlock_crtc(crtc);
159-
drm_modeset_lock_all(dev_priv->dev);
160-
hotspot_x = hot_x + du->hotspot_x;
161-
hotspot_y = hot_y + du->hotspot_y;
162-
163-
/* A lot of the code assumes this */
164-
if (handle && (width != 64 || height != 64)) {
165-
ret = -EINVAL;
166-
goto out;
167-
}
168-
169-
if (handle) {
170-
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
171-
172-
ret = vmw_user_lookup_handle(dev_priv, tfile,
173-
handle, &surface, &dmabuf);
174-
if (ret) {
175-
DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
176-
ret = -EINVAL;
177-
goto out;
178-
}
179-
}
180-
181-
/* need to do this before taking down old image */
182-
if (surface && !surface->snooper.image) {
183-
DRM_ERROR("surface not suitable for cursor\n");
184-
vmw_surface_unreference(&surface);
185-
ret = -EINVAL;
186-
goto out;
187-
}
188-
189-
/* takedown old cursor */
190-
if (du->cursor_surface) {
191-
vmw_surface_unreference(&du->cursor_surface);
192-
}
193-
if (du->cursor_dmabuf)
194-
vmw_dmabuf_unreference(&du->cursor_dmabuf);
195-
196-
/* setup new image */
197-
ret = 0;
198-
if (surface) {
199-
/* vmw_user_surface_lookup takes one reference */
200-
du->cursor_surface = surface;
201-
202-
du->cursor_age = du->cursor_surface->snooper.age;
203-
ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
204-
64, 64, hotspot_x, hotspot_y);
205-
} else if (dmabuf) {
206-
/* vmw_user_surface_lookup takes one reference */
207-
du->cursor_dmabuf = dmabuf;
208-
209-
ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
210-
hotspot_x, hotspot_y);
211-
} else {
212-
vmw_cursor_update_position(dev_priv, false, 0, 0);
213-
goto out;
214-
}
215-
216-
if (!ret) {
217-
vmw_cursor_update_position(dev_priv, true,
218-
du->cursor_x + hotspot_x,
219-
du->cursor_y + hotspot_y);
220-
du->core_hotspot_x = hot_x;
221-
du->core_hotspot_y = hot_y;
222-
}
223-
224-
out:
225-
drm_modeset_unlock_all(dev_priv->dev);
226-
drm_modeset_lock_crtc(crtc, crtc->cursor);
227-
228-
return ret;
229-
}
230-
231-
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
232-
{
233-
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
234-
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
235-
bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false;
236-
237-
du->cursor_x = x + du->set_gui_x;
238-
du->cursor_y = y + du->set_gui_y;
239-
240-
/*
241-
* FIXME: Unclear whether there's any global state touched by the
242-
* cursor_set function, especially vmw_cursor_update_position looks
243-
* suspicious. For now take the easy route and reacquire all locks. We
244-
* can do this since the caller in the drm core doesn't check anything
245-
* which is protected by any looks.
246-
*/
247-
drm_modeset_unlock_crtc(crtc);
248-
drm_modeset_lock_all(dev_priv->dev);
249-
250-
vmw_cursor_update_position(dev_priv, shown,
251-
du->cursor_x + du->hotspot_x +
252-
du->core_hotspot_x,
253-
du->cursor_y + du->hotspot_y +
254-
du->core_hotspot_y);
255-
256-
drm_modeset_unlock_all(dev_priv->dev);
257-
drm_modeset_lock_crtc(crtc, crtc->cursor);
258-
259-
return 0;
260-
}
261-
262138
void vmw_kms_cursor_snoop(struct vmw_surface *srf,
263139
struct ttm_object_file *tfile,
264140
struct ttm_buffer_object *bo,
@@ -393,6 +269,125 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
393269
mutex_unlock(&dev->mode_config.mutex);
394270
}
395271

272+
273+
274+
/**
275+
* vmw_du_cursor_plane_update() - Update cursor image and location
276+
*
277+
* @plane: plane object to update
278+
* @crtc: owning CRTC of @plane
279+
* @fb: framebuffer to flip onto plane
280+
* @crtc_x: x offset of plane on crtc
281+
* @crtc_y: y offset of plane on crtc
282+
* @crtc_w: width of plane rectangle on crtc
283+
* @crtc_h: height of plane rectangle on crtc
284+
* @src_x: Not used
285+
* @src_y: Not used
286+
* @src_w: Not used
287+
* @src_h: Not used
288+
*
289+
*
290+
* RETURNS:
291+
* Zero on success, error code on failure
292+
*/
293+
int vmw_du_cursor_plane_update(struct drm_plane *plane,
294+
struct drm_crtc *crtc,
295+
struct drm_framebuffer *fb,
296+
int crtc_x, int crtc_y,
297+
unsigned int crtc_w,
298+
unsigned int crtc_h,
299+
uint32_t src_x, uint32_t src_y,
300+
uint32_t src_w, uint32_t src_h)
301+
{
302+
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
303+
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
304+
struct vmw_surface *surface = NULL;
305+
struct vmw_dma_buffer *dmabuf = NULL;
306+
s32 hotspot_x, hotspot_y;
307+
int ret;
308+
309+
hotspot_x = du->hotspot_x + fb->hot_x;
310+
hotspot_y = du->hotspot_y + fb->hot_y;
311+
312+
/* A lot of the code assumes this */
313+
if (crtc_w != 64 || crtc_h != 64) {
314+
ret = -EINVAL;
315+
goto out;
316+
}
317+
318+
if (vmw_framebuffer_to_vfb(fb)->dmabuf)
319+
dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
320+
else
321+
surface = vmw_framebuffer_to_vfbs(fb)->surface;
322+
323+
if (surface && !surface->snooper.image) {
324+
DRM_ERROR("surface not suitable for cursor\n");
325+
ret = -EINVAL;
326+
goto out;
327+
}
328+
329+
/* setup new image */
330+
ret = 0;
331+
if (surface) {
332+
/* vmw_user_surface_lookup takes one reference */
333+
du->cursor_surface = surface;
334+
335+
du->cursor_age = du->cursor_surface->snooper.age;
336+
337+
ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
338+
64, 64, hotspot_x, hotspot_y);
339+
} else if (dmabuf) {
340+
/* vmw_user_surface_lookup takes one reference */
341+
du->cursor_dmabuf = dmabuf;
342+
343+
ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h,
344+
hotspot_x, hotspot_y);
345+
} else {
346+
vmw_cursor_update_position(dev_priv, false, 0, 0);
347+
goto out;
348+
}
349+
350+
if (!ret) {
351+
du->cursor_x = crtc_x + du->set_gui_x;
352+
du->cursor_y = crtc_y + du->set_gui_y;
353+
354+
vmw_cursor_update_position(dev_priv, true,
355+
du->cursor_x + hotspot_x,
356+
du->cursor_y + hotspot_y);
357+
}
358+
359+
out:
360+
return ret;
361+
}
362+
363+
364+
int vmw_du_cursor_plane_disable(struct drm_plane *plane)
365+
{
366+
if (plane->fb) {
367+
drm_framebuffer_unreference(plane->fb);
368+
plane->fb = NULL;
369+
}
370+
371+
return -EINVAL;
372+
}
373+
374+
375+
void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
376+
{
377+
vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
378+
379+
drm_plane_cleanup(plane);
380+
}
381+
382+
383+
void vmw_du_primary_plane_destroy(struct drm_plane *plane)
384+
{
385+
drm_plane_cleanup(plane);
386+
387+
/* Planes are static in our case so we don't free it */
388+
}
389+
390+
396391
/*
397392
* Generic framebuffer code
398393
*/

0 commit comments

Comments
 (0)