aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSinclair Yeh <syeh@vmware.com>2017-03-23 14:28:11 -0400
committerSinclair Yeh <syeh@vmware.com>2017-03-31 12:13:08 -0400
commit36cc79bc9077319c04bd3b132edcacaa9a0d9f2b (patch)
tree85674576ea3047d63c069cb3ae7ce73bfce90c41
parent27d247c678a09fcac08d6865db73e41b23d3d5f3 (diff)
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>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c271
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h39
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c108
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c87
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c89
7 files changed, 398 insertions, 198 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index d08f26973d0b..83ff0f033d5f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -650,6 +650,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
650 spin_lock_init(&dev_priv->waiter_lock); 650 spin_lock_init(&dev_priv->waiter_lock);
651 spin_lock_init(&dev_priv->cap_lock); 651 spin_lock_init(&dev_priv->cap_lock);
652 spin_lock_init(&dev_priv->svga_lock); 652 spin_lock_init(&dev_priv->svga_lock);
653 spin_lock_init(&dev_priv->cursor_lock);
653 654
654 for (i = vmw_res_context; i < vmw_res_max; ++i) { 655 for (i = vmw_res_context; i < vmw_res_max; ++i) {
655 idr_init(&dev_priv->res_idr[i]); 656 idr_init(&dev_priv->res_idr[i]);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index bc6ee5a847a7..130d51c5ec6a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -414,6 +414,7 @@ struct vmw_private {
414 unsigned num_implicit; 414 unsigned num_implicit;
415 struct vmw_framebuffer *implicit_fb; 415 struct vmw_framebuffer *implicit_fb;
416 struct mutex global_kms_state_mutex; 416 struct mutex global_kms_state_mutex;
417 spinlock_t cursor_lock;
417 418
418 /* 419 /*
419 * Context and surface management. 420 * Context and surface management.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 6bcba56ef158..c9f5ddabfb72 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -33,10 +33,9 @@
33 33
34void vmw_du_cleanup(struct vmw_display_unit *du) 34void vmw_du_cleanup(struct vmw_display_unit *du)
35{ 35{
36 if (du->cursor_surface) 36 drm_plane_cleanup(&du->primary);
37 vmw_surface_unreference(&du->cursor_surface); 37 drm_plane_cleanup(&du->cursor);
38 if (du->cursor_dmabuf) 38
39 vmw_dmabuf_unreference(&du->cursor_dmabuf);
40 drm_connector_unregister(&du->connector); 39 drm_connector_unregister(&du->connector);
41 drm_crtc_cleanup(&du->crtc); 40 drm_crtc_cleanup(&du->crtc);
42 drm_encoder_cleanup(&du->encoder); 41 drm_encoder_cleanup(&du->encoder);
@@ -47,9 +46,9 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
47 * Display Unit Cursor functions 46 * Display Unit Cursor functions
48 */ 47 */
49 48
50int vmw_cursor_update_image(struct vmw_private *dev_priv, 49static int vmw_cursor_update_image(struct vmw_private *dev_priv,
51 u32 *image, u32 width, u32 height, 50 u32 *image, u32 width, u32 height,
52 u32 hotspotX, u32 hotspotY) 51 u32 hotspotX, u32 hotspotY)
53{ 52{
54 struct { 53 struct {
55 u32 cmd; 54 u32 cmd;
@@ -83,10 +82,10 @@ int vmw_cursor_update_image(struct vmw_private *dev_priv,
83 return 0; 82 return 0;
84} 83}
85 84
86int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv, 85static int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
87 struct vmw_dma_buffer *dmabuf, 86 struct vmw_dma_buffer *dmabuf,
88 u32 width, u32 height, 87 u32 width, u32 height,
89 u32 hotspotX, u32 hotspotY) 88 u32 hotspotX, u32 hotspotY)
90{ 89{
91 struct ttm_bo_kmap_obj map; 90 struct ttm_bo_kmap_obj map;
92 unsigned long kmap_offset; 91 unsigned long kmap_offset;
@@ -120,145 +119,22 @@ err_unreserve:
120} 119}
121 120
122 121
123void vmw_cursor_update_position(struct vmw_private *dev_priv, 122static void vmw_cursor_update_position(struct vmw_private *dev_priv,
124 bool show, int x, int y) 123 bool show, int x, int y)
125{ 124{
126 u32 *fifo_mem = dev_priv->mmio_virt; 125 u32 *fifo_mem = dev_priv->mmio_virt;
127 uint32_t count; 126 uint32_t count;
128 127
128 spin_lock(&dev_priv->cursor_lock);
129 vmw_mmio_write(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON); 129 vmw_mmio_write(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
130 vmw_mmio_write(x, fifo_mem + SVGA_FIFO_CURSOR_X); 130 vmw_mmio_write(x, fifo_mem + SVGA_FIFO_CURSOR_X);
131 vmw_mmio_write(y, fifo_mem + SVGA_FIFO_CURSOR_Y); 131 vmw_mmio_write(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
132 count = vmw_mmio_read(fifo_mem + SVGA_FIFO_CURSOR_COUNT); 132 count = vmw_mmio_read(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
133 vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT); 133 vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
134 spin_unlock(&dev_priv->cursor_lock);
134} 135}
135 136
136 137
137/*
138 * vmw_du_crtc_cursor_set2 - Driver cursor_set2 callback.
139 */
140int 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
224out:
225 drm_modeset_unlock_all(dev_priv->dev);
226 drm_modeset_lock_crtc(crtc, crtc->cursor);
227
228 return ret;
229}
230
231int 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
262void vmw_kms_cursor_snoop(struct vmw_surface *srf, 138void vmw_kms_cursor_snoop(struct vmw_surface *srf,
263 struct ttm_object_file *tfile, 139 struct ttm_object_file *tfile,
264 struct ttm_buffer_object *bo, 140 struct ttm_buffer_object *bo,
@@ -393,6 +269,125 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
393 mutex_unlock(&dev->mode_config.mutex); 269 mutex_unlock(&dev->mode_config.mutex);
394} 270}
395 271
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 */
293int 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
359out:
360 return ret;
361}
362
363
364int 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
375void 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
383void 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
396/* 391/*
397 * Generic framebuffer code 392 * Generic framebuffer code
398 */ 393 */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index cb36e1d70133..e400bfb26167 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -33,6 +33,8 @@
33#include <drm/drm_encoder.h> 33#include <drm/drm_encoder.h>
34#include "vmwgfx_drv.h" 34#include "vmwgfx_drv.h"
35 35
36
37
36/** 38/**
37 * struct vmw_kms_dirty - closure structure for the vmw_kms_helper_dirty 39 * struct vmw_kms_dirty - closure structure for the vmw_kms_helper_dirty
38 * function. 40 * function.
@@ -125,19 +127,17 @@ struct vmw_framebuffer_dmabuf {
125}; 127};
126 128
127 129
128/* 130static const uint32_t vmw_primary_plane_formats[] = {
129 * Basic cursor manipulation 131 DRM_FORMAT_XRGB1555,
130 */ 132 DRM_FORMAT_RGB565,
131int vmw_cursor_update_image(struct vmw_private *dev_priv, 133 DRM_FORMAT_RGB888,
132 u32 *image, u32 width, u32 height, 134 DRM_FORMAT_XRGB8888,
133 u32 hotspotX, u32 hotspotY); 135 DRM_FORMAT_ARGB8888,
134int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv, 136};
135 struct vmw_dma_buffer *dmabuf,
136 u32 width, u32 height,
137 u32 hotspotX, u32 hotspotY);
138void vmw_cursor_update_position(struct vmw_private *dev_priv,
139 bool show, int x, int y);
140 137
138static const uint32_t vmw_cursor_plane_formats[] = {
139 DRM_FORMAT_ARGB8888,
140};
141 141
142/** 142/**
143 * Base class display unit. 143 * Base class display unit.
@@ -150,6 +150,8 @@ struct vmw_display_unit {
150 struct drm_crtc crtc; 150 struct drm_crtc crtc;
151 struct drm_encoder encoder; 151 struct drm_encoder encoder;
152 struct drm_connector connector; 152 struct drm_connector connector;
153 struct drm_plane primary;
154 struct drm_plane cursor;
153 155
154 struct vmw_surface *cursor_surface; 156 struct vmw_surface *cursor_surface;
155 struct vmw_dma_buffer *cursor_dmabuf; 157 struct vmw_dma_buffer *cursor_dmabuf;
@@ -270,6 +272,19 @@ void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
270void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv, 272void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
271 bool immutable); 273 bool immutable);
272 274
275/* Universal Plane Helpers */
276void vmw_du_primary_plane_destroy(struct drm_plane *plane);
277void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
278int vmw_du_cursor_plane_disable(struct drm_plane *plane);
279int vmw_du_cursor_plane_update(struct drm_plane *plane,
280 struct drm_crtc *crtc,
281 struct drm_framebuffer *fb,
282 int crtc_x, int crtc_y,
283 unsigned int crtc_w,
284 unsigned int crtc_h,
285 uint32_t src_x, uint32_t src_y,
286 uint32_t src_w, uint32_t src_h);
287
273 288
274/* 289/*
275 * Legacy display unit functions - vmwgfx_ldu.c 290 * Legacy display unit functions - vmwgfx_ldu.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 3806148e1bdb..3efcbe514472 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -75,10 +75,9 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
75{ 75{
76 struct vmw_legacy_display *lds = dev_priv->ldu_priv; 76 struct vmw_legacy_display *lds = dev_priv->ldu_priv;
77 struct vmw_legacy_display_unit *entry; 77 struct vmw_legacy_display_unit *entry;
78 struct vmw_display_unit *du = NULL;
79 struct drm_framebuffer *fb = NULL; 78 struct drm_framebuffer *fb = NULL;
80 struct drm_crtc *crtc = NULL; 79 struct drm_crtc *crtc = NULL;
81 int i = 0, ret; 80 int i = 0;
82 81
83 /* If there is no display topology the host just assumes 82 /* If there is no display topology the host just assumes
84 * that the guest will set the same layout as the host. 83 * that the guest will set the same layout as the host.
@@ -132,25 +131,6 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
132 131
133 lds->last_num_active = lds->num_active; 132 lds->last_num_active = lds->num_active;
134 133
135
136 /* Find the first du with a cursor. */
137 list_for_each_entry(entry, &lds->active, active) {
138 du = &entry->base;
139
140 if (!du->cursor_dmabuf)
141 continue;
142
143 ret = vmw_cursor_update_dmabuf(dev_priv,
144 du->cursor_dmabuf,
145 64, 64,
146 du->hotspot_x,
147 du->hotspot_y);
148 if (ret == 0)
149 break;
150
151 DRM_ERROR("Could not update cursor image\n");
152 }
153
154 return 0; 134 return 0;
155} 135}
156 136
@@ -298,8 +278,6 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
298} 278}
299 279
300static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = { 280static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
301 .cursor_set2 = vmw_du_crtc_cursor_set2,
302 .cursor_move = vmw_du_crtc_cursor_move,
303 .gamma_set = vmw_du_crtc_gamma_set, 281 .gamma_set = vmw_du_crtc_gamma_set,
304 .destroy = vmw_ldu_crtc_destroy, 282 .destroy = vmw_ldu_crtc_destroy,
305 .set_config = vmw_ldu_crtc_set_config, 283 .set_config = vmw_ldu_crtc_set_config,
@@ -336,6 +314,23 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
336 .destroy = vmw_ldu_connector_destroy, 314 .destroy = vmw_ldu_connector_destroy,
337}; 315};
338 316
317/*
318 * Legacy Display Plane Functions
319 */
320
321static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
322 .update_plane = drm_primary_helper_update,
323 .disable_plane = drm_primary_helper_disable,
324 .destroy = vmw_du_primary_plane_destroy,
325};
326
327static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
328 .update_plane = vmw_du_cursor_plane_update,
329 .disable_plane = vmw_du_cursor_plane_disable,
330 .destroy = vmw_du_cursor_plane_destroy,
331};
332
333
339static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) 334static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
340{ 335{
341 struct vmw_legacy_display_unit *ldu; 336 struct vmw_legacy_display_unit *ldu;
@@ -343,6 +338,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
343 struct drm_connector *connector; 338 struct drm_connector *connector;
344 struct drm_encoder *encoder; 339 struct drm_encoder *encoder;
345 struct drm_crtc *crtc; 340 struct drm_crtc *crtc;
341 int ret;
346 342
347 ldu = kzalloc(sizeof(*ldu), GFP_KERNEL); 343 ldu = kzalloc(sizeof(*ldu), GFP_KERNEL);
348 if (!ldu) 344 if (!ldu)
@@ -361,19 +357,61 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
361 ldu->base.pref_mode = NULL; 357 ldu->base.pref_mode = NULL;
362 ldu->base.is_implicit = true; 358 ldu->base.is_implicit = true;
363 359
364 drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, 360 /* Initialize primary plane */
365 DRM_MODE_CONNECTOR_VIRTUAL); 361 ret = drm_universal_plane_init(dev, &ldu->base.primary,
362 0, &vmw_ldu_plane_funcs,
363 vmw_primary_plane_formats,
364 ARRAY_SIZE(vmw_primary_plane_formats),
365 DRM_PLANE_TYPE_PRIMARY, NULL);
366 if (ret) {
367 DRM_ERROR("Failed to initialize primary plane");
368 goto err_free;
369 }
370
371 /* Initialize cursor plane */
372 ret = drm_universal_plane_init(dev, &ldu->base.cursor,
373 0, &vmw_ldu_cursor_funcs,
374 vmw_cursor_plane_formats,
375 ARRAY_SIZE(vmw_cursor_plane_formats),
376 DRM_PLANE_TYPE_CURSOR, NULL);
377 if (ret) {
378 DRM_ERROR("Failed to initialize cursor plane");
379 drm_plane_cleanup(&ldu->base.primary);
380 goto err_free;
381 }
382
383 ret = drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
384 DRM_MODE_CONNECTOR_VIRTUAL);
385 if (ret) {
386 DRM_ERROR("Failed to initialize connector\n");
387 goto err_free;
388 }
366 connector->status = vmw_du_connector_detect(connector, true); 389 connector->status = vmw_du_connector_detect(connector, true);
367 390
368 drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, 391 ret = drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
369 DRM_MODE_ENCODER_VIRTUAL, NULL); 392 DRM_MODE_ENCODER_VIRTUAL, NULL);
370 drm_mode_connector_attach_encoder(connector, encoder); 393 if (ret) {
394 DRM_ERROR("Failed to initialize encoder\n");
395 goto err_free_connector;
396 }
397
398 (void) drm_mode_connector_attach_encoder(connector, encoder);
371 encoder->possible_crtcs = (1 << unit); 399 encoder->possible_crtcs = (1 << unit);
372 encoder->possible_clones = 0; 400 encoder->possible_clones = 0;
373 401
374 (void) drm_connector_register(connector); 402 ret = drm_connector_register(connector);
403 if (ret) {
404 DRM_ERROR("Failed to register connector\n");
405 goto err_free_encoder;
406 }
375 407
376 drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs); 408 ret = drm_crtc_init_with_planes(dev, crtc, &ldu->base.primary,
409 &ldu->base.cursor,
410 &vmw_legacy_crtc_funcs, NULL);
411 if (ret) {
412 DRM_ERROR("Failed to initialize CRTC\n");
413 goto err_free_unregister;
414 }
377 415
378 drm_mode_crtc_set_gamma_size(crtc, 256); 416 drm_mode_crtc_set_gamma_size(crtc, 256);
379 417
@@ -390,6 +428,16 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
390 1); 428 1);
391 429
392 return 0; 430 return 0;
431
432err_free_unregister:
433 drm_connector_unregister(connector);
434err_free_encoder:
435 drm_encoder_cleanup(encoder);
436err_free_connector:
437 drm_connector_cleanup(connector);
438err_free:
439 kfree(ldu);
440 return ret;
393} 441}
394 442
395int vmw_kms_ldu_init_display(struct vmw_private *dev_priv) 443int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index d4268efc37d2..8ffccb87cf3a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -459,8 +459,6 @@ out_no_fence:
459} 459}
460 460
461static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { 461static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
462 .cursor_set2 = vmw_du_crtc_cursor_set2,
463 .cursor_move = vmw_du_crtc_cursor_move,
464 .gamma_set = vmw_du_crtc_gamma_set, 462 .gamma_set = vmw_du_crtc_gamma_set,
465 .destroy = vmw_sou_crtc_destroy, 463 .destroy = vmw_sou_crtc_destroy,
466 .set_config = vmw_sou_crtc_set_config, 464 .set_config = vmw_sou_crtc_set_config,
@@ -497,6 +495,23 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
497 .destroy = vmw_sou_connector_destroy, 495 .destroy = vmw_sou_connector_destroy,
498}; 496};
499 497
498/*
499 * Screen Object Display Plane Functions
500 */
501
502static const struct drm_plane_funcs vmw_sou_plane_funcs = {
503 .update_plane = drm_primary_helper_update,
504 .disable_plane = drm_primary_helper_disable,
505 .destroy = vmw_du_primary_plane_destroy,
506};
507
508static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
509 .update_plane = vmw_du_cursor_plane_update,
510 .disable_plane = vmw_du_cursor_plane_disable,
511 .destroy = vmw_du_cursor_plane_destroy,
512};
513
514
500static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) 515static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
501{ 516{
502 struct vmw_screen_object_unit *sou; 517 struct vmw_screen_object_unit *sou;
@@ -504,6 +519,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
504 struct drm_connector *connector; 519 struct drm_connector *connector;
505 struct drm_encoder *encoder; 520 struct drm_encoder *encoder;
506 struct drm_crtc *crtc; 521 struct drm_crtc *crtc;
522 int ret;
507 523
508 sou = kzalloc(sizeof(*sou), GFP_KERNEL); 524 sou = kzalloc(sizeof(*sou), GFP_KERNEL);
509 if (!sou) 525 if (!sou)
@@ -521,19 +537,62 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
521 sou->base.pref_mode = NULL; 537 sou->base.pref_mode = NULL;
522 sou->base.is_implicit = false; 538 sou->base.is_implicit = false;
523 539
524 drm_connector_init(dev, connector, &vmw_sou_connector_funcs, 540 /* Initialize primary plane */
525 DRM_MODE_CONNECTOR_VIRTUAL); 541 ret = drm_universal_plane_init(dev, &sou->base.primary,
542 0, &vmw_sou_plane_funcs,
543 vmw_primary_plane_formats,
544 ARRAY_SIZE(vmw_primary_plane_formats),
545 DRM_PLANE_TYPE_PRIMARY, NULL);
546 if (ret) {
547 DRM_ERROR("Failed to initialize primary plane");
548 goto err_free;
549 }
550
551 /* Initialize cursor plane */
552 ret = drm_universal_plane_init(dev, &sou->base.cursor,
553 0, &vmw_sou_cursor_funcs,
554 vmw_cursor_plane_formats,
555 ARRAY_SIZE(vmw_cursor_plane_formats),
556 DRM_PLANE_TYPE_CURSOR, NULL);
557 if (ret) {
558 DRM_ERROR("Failed to initialize cursor plane");
559 drm_plane_cleanup(&sou->base.primary);
560 goto err_free;
561 }
562
563 ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
564 DRM_MODE_CONNECTOR_VIRTUAL);
565 if (ret) {
566 DRM_ERROR("Failed to initialize connector\n");
567 goto err_free;
568 }
569
526 connector->status = vmw_du_connector_detect(connector, true); 570 connector->status = vmw_du_connector_detect(connector, true);
527 571
528 drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs, 572 ret = drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
529 DRM_MODE_ENCODER_VIRTUAL, NULL); 573 DRM_MODE_ENCODER_VIRTUAL, NULL);
530 drm_mode_connector_attach_encoder(connector, encoder); 574 if (ret) {
575 DRM_ERROR("Failed to initialize encoder\n");
576 goto err_free_connector;
577 }
578
579 (void) drm_mode_connector_attach_encoder(connector, encoder);
531 encoder->possible_crtcs = (1 << unit); 580 encoder->possible_crtcs = (1 << unit);
532 encoder->possible_clones = 0; 581 encoder->possible_clones = 0;
533 582
534 (void) drm_connector_register(connector); 583 ret = drm_connector_register(connector);
584 if (ret) {
585 DRM_ERROR("Failed to register connector\n");
586 goto err_free_encoder;
587 }
535 588
536 drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); 589 ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
590 &sou->base.cursor,
591 &vmw_screen_object_crtc_funcs, NULL);
592 if (ret) {
593 DRM_ERROR("Failed to initialize CRTC\n");
594 goto err_free_unregister;
595 }
537 596
538 drm_mode_crtc_set_gamma_size(crtc, 256); 597 drm_mode_crtc_set_gamma_size(crtc, 256);
539 598
@@ -550,6 +609,16 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
550 sou->base.is_implicit); 609 sou->base.is_implicit);
551 610
552 return 0; 611 return 0;
612
613err_free_unregister:
614 drm_connector_unregister(connector);
615err_free_encoder:
616 drm_encoder_cleanup(encoder);
617err_free_connector:
618 drm_connector_cleanup(connector);
619err_free:
620 kfree(sou);
621 return ret;
553} 622}
554 623
555int vmw_kms_sou_init_display(struct vmw_private *dev_priv) 624int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index b27cd18ee66a..4d9dd1b67b93 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1015,8 +1015,6 @@ out_finish:
1015 * Screen Target CRTC dispatch table 1015 * Screen Target CRTC dispatch table
1016 */ 1016 */
1017static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = { 1017static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
1018 .cursor_set2 = vmw_du_crtc_cursor_set2,
1019 .cursor_move = vmw_du_crtc_cursor_move,
1020 .gamma_set = vmw_du_crtc_gamma_set, 1018 .gamma_set = vmw_du_crtc_gamma_set,
1021 .destroy = vmw_stdu_crtc_destroy, 1019 .destroy = vmw_stdu_crtc_destroy,
1022 .set_config = vmw_stdu_crtc_set_config, 1020 .set_config = vmw_stdu_crtc_set_config,
@@ -1081,6 +1079,23 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
1081 1079
1082 1080
1083 1081
1082/******************************************************************************
1083 * Screen Target Display Plane Functions
1084 *****************************************************************************/
1085
1086static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
1087 .update_plane = drm_primary_helper_update,
1088 .disable_plane = drm_primary_helper_disable,
1089 .destroy = vmw_du_primary_plane_destroy,
1090};
1091
1092static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
1093 .update_plane = vmw_du_cursor_plane_update,
1094 .disable_plane = vmw_du_cursor_plane_disable,
1095 .destroy = vmw_du_cursor_plane_destroy,
1096};
1097
1098
1084/** 1099/**
1085 * vmw_stdu_init - Sets up a Screen Target Display Unit 1100 * vmw_stdu_init - Sets up a Screen Target Display Unit
1086 * 1101 *
@@ -1097,7 +1112,9 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
1097 struct drm_device *dev = dev_priv->dev; 1112 struct drm_device *dev = dev_priv->dev;
1098 struct drm_connector *connector; 1113 struct drm_connector *connector;
1099 struct drm_encoder *encoder; 1114 struct drm_encoder *encoder;
1115 struct drm_plane *primary, *cursor;
1100 struct drm_crtc *crtc; 1116 struct drm_crtc *crtc;
1117 int ret;
1101 1118
1102 1119
1103 stdu = kzalloc(sizeof(*stdu), GFP_KERNEL); 1120 stdu = kzalloc(sizeof(*stdu), GFP_KERNEL);
@@ -1108,25 +1125,69 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
1108 crtc = &stdu->base.crtc; 1125 crtc = &stdu->base.crtc;
1109 encoder = &stdu->base.encoder; 1126 encoder = &stdu->base.encoder;
1110 connector = &stdu->base.connector; 1127 connector = &stdu->base.connector;
1128 primary = &stdu->base.primary;
1129 cursor = &stdu->base.cursor;
1111 1130
1112 stdu->base.pref_active = (unit == 0); 1131 stdu->base.pref_active = (unit == 0);
1113 stdu->base.pref_width = dev_priv->initial_width; 1132 stdu->base.pref_width = dev_priv->initial_width;
1114 stdu->base.pref_height = dev_priv->initial_height; 1133 stdu->base.pref_height = dev_priv->initial_height;
1115 stdu->base.is_implicit = false; 1134 stdu->base.is_implicit = false;
1116 1135
1117 drm_connector_init(dev, connector, &vmw_stdu_connector_funcs, 1136 /* Initialize primary plane */
1118 DRM_MODE_CONNECTOR_VIRTUAL); 1137 ret = drm_universal_plane_init(dev, primary,
1138 0, &vmw_stdu_plane_funcs,
1139 vmw_primary_plane_formats,
1140 ARRAY_SIZE(vmw_primary_plane_formats),
1141 DRM_PLANE_TYPE_PRIMARY, NULL);
1142 if (ret) {
1143 DRM_ERROR("Failed to initialize primary plane");
1144 goto err_free;
1145 }
1146
1147 /* Initialize cursor plane */
1148 ret = drm_universal_plane_init(dev, cursor,
1149 0, &vmw_stdu_cursor_funcs,
1150 vmw_cursor_plane_formats,
1151 ARRAY_SIZE(vmw_cursor_plane_formats),
1152 DRM_PLANE_TYPE_CURSOR, NULL);
1153 if (ret) {
1154 DRM_ERROR("Failed to initialize cursor plane");
1155 drm_plane_cleanup(&stdu->base.primary);
1156 goto err_free;
1157 }
1158
1159 ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
1160 DRM_MODE_CONNECTOR_VIRTUAL);
1161 if (ret) {
1162 DRM_ERROR("Failed to initialize connector\n");
1163 goto err_free;
1164 }
1119 connector->status = vmw_du_connector_detect(connector, false); 1165 connector->status = vmw_du_connector_detect(connector, false);
1120 1166
1121 drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs, 1167 ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
1122 DRM_MODE_ENCODER_VIRTUAL, NULL); 1168 DRM_MODE_ENCODER_VIRTUAL, NULL);
1123 drm_mode_connector_attach_encoder(connector, encoder); 1169 if (ret) {
1170 DRM_ERROR("Failed to initialize encoder\n");
1171 goto err_free_connector;
1172 }
1173
1174 (void) drm_mode_connector_attach_encoder(connector, encoder);
1124 encoder->possible_crtcs = (1 << unit); 1175 encoder->possible_crtcs = (1 << unit);
1125 encoder->possible_clones = 0; 1176 encoder->possible_clones = 0;
1126 1177
1127 (void) drm_connector_register(connector); 1178 ret = drm_connector_register(connector);
1179 if (ret) {
1180 DRM_ERROR("Failed to register connector\n");
1181 goto err_free_encoder;
1182 }
1128 1183
1129 drm_crtc_init(dev, crtc, &vmw_stdu_crtc_funcs); 1184 ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary,
1185 &stdu->base.cursor,
1186 &vmw_stdu_crtc_funcs, NULL);
1187 if (ret) {
1188 DRM_ERROR("Failed to initialize CRTC\n");
1189 goto err_free_unregister;
1190 }
1130 1191
1131 drm_mode_crtc_set_gamma_size(crtc, 256); 1192 drm_mode_crtc_set_gamma_size(crtc, 256);
1132 1193
@@ -1142,6 +1203,16 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
1142 dev_priv->implicit_placement_property, 1203 dev_priv->implicit_placement_property,
1143 stdu->base.is_implicit); 1204 stdu->base.is_implicit);
1144 return 0; 1205 return 0;
1206
1207err_free_unregister:
1208 drm_connector_unregister(connector);
1209err_free_encoder:
1210 drm_encoder_cleanup(encoder);
1211err_free_connector:
1212 drm_connector_cleanup(connector);
1213err_free:
1214 kfree(stdu);
1215 return ret;
1145} 1216}
1146 1217
1147 1218