aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSinclair Yeh <syeh@vmware.com>2017-03-23 17:38:18 -0400
committerSinclair Yeh <syeh@vmware.com>2017-03-31 18:21:12 -0400
commitb0119cb9229d0db0d8c3ec8b302d549775e03a0c (patch)
treee834c21a6556cd24a08d7b1e3a9e80f8e957e784
parent904bb5e5817f5c5b42e6e3775699c728fd420284 (diff)
drm/vmwgfx: Switch over to internal atomic API for SOU and LDU
Switch over to internal atomic API. This completes the atomic internal atomic switch for all the Display Units. 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_ldu.c103
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c217
2 files changed, 25 insertions, 295 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 1b9e08335cce..5e2f639b8d04 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -95,7 +95,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
95 95
96 if (crtc == NULL) 96 if (crtc == NULL)
97 return 0; 97 return 0;
98 fb = entry->base.crtc.primary->fb; 98 fb = entry->base.crtc.primary->state->fb;
99 99
100 return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0], 100 return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
101 fb->format->cpp[0] * 8, 101 fb->format->cpp[0] * 8,
@@ -104,7 +104,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
104 104
105 if (!list_empty(&lds->active)) { 105 if (!list_empty(&lds->active)) {
106 entry = list_entry(lds->active.next, typeof(*entry), active); 106 entry = list_entry(lds->active.next, typeof(*entry), active);
107 fb = entry->base.crtc.primary->fb; 107 fb = entry->base.crtc.primary->state->fb;
108 108
109 vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0], 109 vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
110 fb->format->cpp[0] * 8, fb->format->depth); 110 fb->format->cpp[0] * 8, fb->format->depth);
@@ -255,102 +255,13 @@ static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc)
255{ 255{
256} 256}
257 257
258static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
259{
260 struct vmw_private *dev_priv;
261 struct vmw_legacy_display_unit *ldu;
262 struct drm_connector *connector;
263 struct drm_display_mode *mode;
264 struct drm_encoder *encoder;
265 struct vmw_framebuffer *vfb;
266 struct drm_framebuffer *fb;
267 struct drm_crtc *crtc;
268
269 if (!set)
270 return -EINVAL;
271
272 if (!set->crtc)
273 return -EINVAL;
274
275 /* get the ldu */
276 crtc = set->crtc;
277 ldu = vmw_crtc_to_ldu(crtc);
278 vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
279 dev_priv = vmw_priv(crtc->dev);
280
281 if (set->num_connectors > 1) {
282 DRM_ERROR("to many connectors\n");
283 return -EINVAL;
284 }
285
286 if (set->num_connectors == 1 &&
287 set->connectors[0] != &ldu->base.connector) {
288 DRM_ERROR("connector doesn't match %p %p\n",
289 set->connectors[0], &ldu->base.connector);
290 return -EINVAL;
291 }
292
293 /* ldu only supports one fb active at the time */
294 if (dev_priv->ldu_priv->fb && vfb &&
295 !(dev_priv->ldu_priv->num_active == 1 &&
296 !list_empty(&ldu->active)) &&
297 dev_priv->ldu_priv->fb != vfb) {
298 DRM_ERROR("Multiple framebuffers not supported\n");
299 return -EINVAL;
300 }
301
302 /* since they always map one to one these are safe */
303 connector = &ldu->base.connector;
304 encoder = &ldu->base.encoder;
305
306 /* should we turn the crtc off? */
307 if (set->num_connectors == 0 || !set->mode || !set->fb) {
308
309 connector->encoder = NULL;
310 encoder->crtc = NULL;
311 crtc->primary->fb = NULL;
312 crtc->enabled = false;
313
314 vmw_ldu_del_active(dev_priv, ldu);
315
316 return vmw_ldu_commit_list(dev_priv);
317 }
318
319
320 /* we now know we want to set a mode */
321 mode = set->mode;
322 fb = set->fb;
323
324 if (set->x + mode->hdisplay > fb->width ||
325 set->y + mode->vdisplay > fb->height) {
326 DRM_ERROR("set outside of framebuffer\n");
327 return -EINVAL;
328 }
329
330 vmw_svga_enable(dev_priv);
331
332 crtc->primary->fb = fb;
333 encoder->crtc = crtc;
334 connector->encoder = encoder;
335 crtc->x = set->x;
336 crtc->y = set->y;
337 crtc->mode = *mode;
338 crtc->enabled = true;
339 ldu->base.set_gui_x = set->x;
340 ldu->base.set_gui_y = set->y;
341
342 vmw_ldu_add_active(dev_priv, ldu, vfb);
343
344 return vmw_ldu_commit_list(dev_priv);
345}
346
347static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = { 258static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
348 .gamma_set = vmw_du_crtc_gamma_set, 259 .gamma_set = vmw_du_crtc_gamma_set,
349 .destroy = vmw_ldu_crtc_destroy, 260 .destroy = vmw_ldu_crtc_destroy,
350 .reset = vmw_du_crtc_reset, 261 .reset = vmw_du_crtc_reset,
351 .atomic_duplicate_state = vmw_du_crtc_duplicate_state, 262 .atomic_duplicate_state = vmw_du_crtc_duplicate_state,
352 .atomic_destroy_state = vmw_du_crtc_destroy_state, 263 .atomic_destroy_state = vmw_du_crtc_destroy_state,
353 .set_config = vmw_ldu_crtc_set_config, 264 .set_config = vmw_kms_set_config,
354}; 265};
355 266
356 267
@@ -439,8 +350,8 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
439 350
440 351
441static const struct drm_plane_funcs vmw_ldu_plane_funcs = { 352static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
442 .update_plane = drm_primary_helper_update, 353 .update_plane = drm_atomic_helper_update_plane,
443 .disable_plane = drm_primary_helper_disable, 354 .disable_plane = drm_atomic_helper_disable_plane,
444 .destroy = vmw_du_primary_plane_destroy, 355 .destroy = vmw_du_primary_plane_destroy,
445 .reset = vmw_du_plane_reset, 356 .reset = vmw_du_plane_reset,
446 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 357 .atomic_duplicate_state = vmw_du_plane_duplicate_state,
@@ -448,8 +359,8 @@ static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
448}; 359};
449 360
450static const struct drm_plane_funcs vmw_ldu_cursor_funcs = { 361static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
451 .update_plane = vmw_du_cursor_plane_update, 362 .update_plane = drm_atomic_helper_update_plane,
452 .disable_plane = vmw_du_cursor_plane_disable, 363 .disable_plane = drm_atomic_helper_disable_plane,
453 .destroy = vmw_du_cursor_plane_destroy, 364 .destroy = vmw_du_cursor_plane_destroy,
454 .reset = vmw_du_plane_reset, 365 .reset = vmw_du_plane_reset,
455 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 366 .atomic_duplicate_state = vmw_du_plane_duplicate_state,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 536f4b55492e..106a943a613c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -205,52 +205,6 @@ static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
205} 205}
206 206
207/** 207/**
208 * Free the backing store.
209 */
210static void vmw_sou_backing_free(struct vmw_private *dev_priv,
211 struct vmw_screen_object_unit *sou)
212{
213 vmw_dmabuf_unreference(&sou->buffer);
214 sou->buffer_size = 0;
215}
216
217/**
218 * Allocate the backing store for the buffer.
219 */
220static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
221 struct vmw_screen_object_unit *sou,
222 unsigned long size)
223{
224 int ret;
225
226 if (sou->buffer_size == size)
227 return 0;
228
229 if (sou->buffer)
230 vmw_sou_backing_free(dev_priv, sou);
231
232 sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
233 if (unlikely(sou->buffer == NULL))
234 return -ENOMEM;
235
236 /* After we have alloced the backing store might not be able to
237 * resume the overlays, this is preferred to failing to alloc.
238 */
239 vmw_overlay_pause_all(dev_priv);
240 ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
241 &vmw_vram_ne_placement,
242 false, &vmw_dmabuf_bo_free);
243 vmw_overlay_resume_all(dev_priv);
244
245 if (unlikely(ret != 0))
246 sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
247 else
248 sou->buffer_size = size;
249
250 return ret;
251}
252
253/**
254 * vmw_sou_crtc_mode_set_nofb - Create new screen 208 * vmw_sou_crtc_mode_set_nofb - Create new screen
255 * 209 *
256 * @crtc: CRTC associated with the new screen 210 * @crtc: CRTC associated with the new screen
@@ -353,158 +307,14 @@ static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
353 } 307 }
354} 308}
355 309
356static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
357{
358 struct vmw_private *dev_priv;
359 struct vmw_screen_object_unit *sou;
360 struct drm_connector *connector;
361 struct drm_display_mode *mode;
362 struct drm_encoder *encoder;
363 struct vmw_framebuffer *vfb;
364 struct drm_framebuffer *fb;
365 struct drm_crtc *crtc;
366 int ret = 0;
367
368 if (!set)
369 return -EINVAL;
370
371 if (!set->crtc)
372 return -EINVAL;
373
374 /* get the sou */
375 crtc = set->crtc;
376 sou = vmw_crtc_to_sou(crtc);
377 vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
378 dev_priv = vmw_priv(crtc->dev);
379
380 if (set->num_connectors > 1) {
381 DRM_ERROR("Too many connectors\n");
382 return -EINVAL;
383 }
384
385 if (set->num_connectors == 1 &&
386 set->connectors[0] != &sou->base.connector) {
387 DRM_ERROR("Connector doesn't match %p %p\n",
388 set->connectors[0], &sou->base.connector);
389 return -EINVAL;
390 }
391
392 /* Only one active implicit frame-buffer at a time. */
393 mutex_lock(&dev_priv->global_kms_state_mutex);
394 if (sou->base.is_implicit &&
395 dev_priv->implicit_fb && vfb &&
396 !(dev_priv->num_implicit == 1 &&
397 sou->base.active_implicit) &&
398 dev_priv->implicit_fb != vfb) {
399 mutex_unlock(&dev_priv->global_kms_state_mutex);
400 DRM_ERROR("Multiple implicit framebuffers not supported.\n");
401 return -EINVAL;
402 }
403 mutex_unlock(&dev_priv->global_kms_state_mutex);
404
405 /* since they always map one to one these are safe */
406 connector = &sou->base.connector;
407 encoder = &sou->base.encoder;
408
409 /* should we turn the crtc off */
410 if (set->num_connectors == 0 || !set->mode || !set->fb) {
411 ret = vmw_sou_fifo_destroy(dev_priv, sou);
412 /* the hardware has hung don't do anything more */
413 if (unlikely(ret != 0))
414 return ret;
415
416 connector->encoder = NULL;
417 encoder->crtc = NULL;
418 crtc->primary->fb = NULL;
419 crtc->x = 0;
420 crtc->y = 0;
421 crtc->enabled = false;
422
423 vmw_kms_del_active(dev_priv, &sou->base);
424
425 vmw_sou_backing_free(dev_priv, sou);
426
427 return 0;
428 }
429
430
431 /* we now know we want to set a mode */
432 mode = set->mode;
433 fb = set->fb;
434
435 if (set->x + mode->hdisplay > fb->width ||
436 set->y + mode->vdisplay > fb->height) {
437 DRM_ERROR("set outside of framebuffer\n");
438 return -EINVAL;
439 }
440
441 vmw_svga_enable(dev_priv);
442
443 if (mode->hdisplay != crtc->mode.hdisplay ||
444 mode->vdisplay != crtc->mode.vdisplay) {
445 /* no need to check if depth is different, because backing
446 * store depth is forced to 4 by the device.
447 */
448
449 ret = vmw_sou_fifo_destroy(dev_priv, sou);
450 /* the hardware has hung don't do anything more */
451 if (unlikely(ret != 0))
452 return ret;
453
454 vmw_sou_backing_free(dev_priv, sou);
455 }
456
457 if (!sou->buffer) {
458 /* forced to depth 4 by the device */
459 size_t size = mode->hdisplay * mode->vdisplay * 4;
460 ret = vmw_sou_backing_alloc(dev_priv, sou, size);
461 if (unlikely(ret != 0))
462 return ret;
463 }
464
465 ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
466 if (unlikely(ret != 0)) {
467 /*
468 * We are in a bit of a situation here, the hardware has
469 * hung and we may or may not have a buffer hanging of
470 * the screen object, best thing to do is not do anything
471 * if we where defined, if not just turn the crtc of.
472 * Not what userspace wants but it needs to htfu.
473 */
474 if (sou->defined)
475 return ret;
476
477 connector->encoder = NULL;
478 encoder->crtc = NULL;
479 crtc->primary->fb = NULL;
480 crtc->x = 0;
481 crtc->y = 0;
482 crtc->enabled = false;
483
484 return ret;
485 }
486
487 vmw_kms_add_active(dev_priv, &sou->base, vfb);
488
489 connector->encoder = encoder;
490 encoder->crtc = crtc;
491 crtc->mode = *mode;
492 crtc->primary->fb = fb;
493 crtc->x = set->x;
494 crtc->y = set->y;
495 crtc->enabled = true;
496
497 return 0;
498}
499
500static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, 310static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
501 struct drm_framebuffer *fb, 311 struct drm_framebuffer *new_fb,
502 struct drm_pending_vblank_event *event, 312 struct drm_pending_vblank_event *event,
503 uint32_t flags) 313 uint32_t flags)
504{ 314{
505 struct vmw_private *dev_priv = vmw_priv(crtc->dev); 315 struct vmw_private *dev_priv = vmw_priv(crtc->dev);
506 struct drm_framebuffer *old_fb = crtc->primary->fb; 316 struct drm_framebuffer *old_fb = crtc->primary->fb;
507 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); 317 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
508 struct vmw_fence_obj *fence = NULL; 318 struct vmw_fence_obj *fence = NULL;
509 struct drm_vmw_rect vclips; 319 struct drm_vmw_rect vclips;
510 int ret; 320 int ret;
@@ -512,7 +322,12 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
512 if (!vmw_kms_crtc_flippable(dev_priv, crtc)) 322 if (!vmw_kms_crtc_flippable(dev_priv, crtc))
513 return -EINVAL; 323 return -EINVAL;
514 324
515 crtc->primary->fb = fb; 325 flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
326 ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
327 if (ret) {
328 DRM_ERROR("Page flip error %d.\n", ret);
329 return ret;
330 }
516 331
517 /* do a full screen dirty update */ 332 /* do a full screen dirty update */
518 vclips.x = crtc->x; 333 vclips.x = crtc->x;
@@ -559,7 +374,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
559 return ret; 374 return ret;
560 375
561out_no_fence: 376out_no_fence:
562 crtc->primary->fb = old_fb; 377 drm_atomic_set_fb_for_plane(crtc->primary->state, old_fb);
563 return ret; 378 return ret;
564} 379}
565 380
@@ -569,7 +384,7 @@ static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
569 .reset = vmw_du_crtc_reset, 384 .reset = vmw_du_crtc_reset,
570 .atomic_duplicate_state = vmw_du_crtc_duplicate_state, 385 .atomic_duplicate_state = vmw_du_crtc_duplicate_state,
571 .atomic_destroy_state = vmw_du_crtc_destroy_state, 386 .atomic_destroy_state = vmw_du_crtc_destroy_state,
572 .set_config = vmw_sou_crtc_set_config, 387 .set_config = vmw_kms_set_config,
573 .page_flip = vmw_sou_crtc_page_flip, 388 .page_flip = vmw_sou_crtc_page_flip,
574}; 389};
575 390
@@ -711,12 +526,16 @@ static void
711vmw_sou_primary_plane_atomic_update(struct drm_plane *plane, 526vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
712 struct drm_plane_state *old_state) 527 struct drm_plane_state *old_state)
713{ 528{
529 struct drm_crtc *crtc = plane->state->crtc;
530
531 if (crtc)
532 crtc->primary->fb = plane->state->fb;
714} 533}
715 534
716 535
717static const struct drm_plane_funcs vmw_sou_plane_funcs = { 536static const struct drm_plane_funcs vmw_sou_plane_funcs = {
718 .update_plane = drm_primary_helper_update, 537 .update_plane = drm_atomic_helper_update_plane,
719 .disable_plane = drm_primary_helper_disable, 538 .disable_plane = drm_atomic_helper_disable_plane,
720 .destroy = vmw_du_primary_plane_destroy, 539 .destroy = vmw_du_primary_plane_destroy,
721 .reset = vmw_du_plane_reset, 540 .reset = vmw_du_plane_reset,
722 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 541 .atomic_duplicate_state = vmw_du_plane_duplicate_state,
@@ -724,8 +543,8 @@ static const struct drm_plane_funcs vmw_sou_plane_funcs = {
724}; 543};
725 544
726static const struct drm_plane_funcs vmw_sou_cursor_funcs = { 545static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
727 .update_plane = vmw_du_cursor_plane_update, 546 .update_plane = drm_atomic_helper_update_plane,
728 .disable_plane = vmw_du_cursor_plane_disable, 547 .disable_plane = drm_atomic_helper_disable_plane,
729 .destroy = vmw_du_cursor_plane_destroy, 548 .destroy = vmw_du_cursor_plane_destroy,
730 .reset = vmw_du_plane_reset, 549 .reset = vmw_du_plane_reset,
731 .atomic_duplicate_state = vmw_du_plane_duplicate_state, 550 .atomic_duplicate_state = vmw_du_plane_duplicate_state,