aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_plane_helper.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-10 04:55:35 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-10 04:55:35 -0500
commiteb84f976c88d72cbcbe756df38d1f19be3db77d6 (patch)
treedb3ff3b5edc305a0352b69327b914ef3a92e05a5 /drivers/gpu/drm/drm_plane_helper.c
parent69f627f56fac212c1e49cd0d285e3f8cd264dd0c (diff)
parentcc7096fb6d1dfbdac5e7e2675c046fd40646cc66 (diff)
Merge remote-tracking branch 'airlied/drm-next' into HEAD
Backmerge drm-next so that I can keep merging patches. Specifically I want: - atomic stuff, yay! - eld parsing patch from Jani. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers/gpu/drm/drm_plane_helper.c')
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c198
1 files changed, 197 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index fe4d1fb2376c..93c6533c25da 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -27,10 +27,38 @@
27#include <drm/drmP.h> 27#include <drm/drmP.h>
28#include <drm/drm_plane_helper.h> 28#include <drm/drm_plane_helper.h>
29#include <drm/drm_rect.h> 29#include <drm/drm_rect.h>
30#include <drm/drm_plane_helper.h> 30#include <drm/drm_atomic.h>
31#include <drm/drm_crtc_helper.h>
32#include <drm/drm_atomic_helper.h>
31 33
32#define SUBPIXEL_MASK 0xffff 34#define SUBPIXEL_MASK 0xffff
33 35
36/**
37 * DOC: overview
38 *
39 * This helper library has two parts. The first part has support to implement
40 * primary plane support on top of the normal CRTC configuration interface.
41 * Since the legacy ->set_config interface ties the primary plane together with
42 * the CRTC state this does not allow userspace to disable the primary plane
43 * itself. To avoid too much duplicated code use
44 * drm_plane_helper_check_update() which can be used to enforce the same
45 * restrictions as primary planes had thus. The default primary plane only
46 * expose XRBG8888 and ARGB8888 as valid pixel formats for the attached
47 * framebuffer.
48 *
49 * Drivers are highly recommended to implement proper support for primary
50 * planes, and newly merged drivers must not rely upon these transitional
51 * helpers.
52 *
53 * The second part also implements transitional helpers which allow drivers to
54 * gradually switch to the atomic helper infrastructure for plane updates. Once
55 * that switch is complete drivers shouldn't use these any longer, instead using
56 * the proper legacy implementations for update and disable plane hooks provided
57 * by the atomic helpers.
58 *
59 * Again drivers are strongly urged to switch to the new interfaces.
60 */
61
34/* 62/*
35 * This is the minimal list of formats that seem to be safe for modeset use 63 * This is the minimal list of formats that seem to be safe for modeset use
36 * with all current DRM drivers. Most hardware can actually support more 64 * with all current DRM drivers. Most hardware can actually support more
@@ -374,3 +402,171 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
374 return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs); 402 return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs);
375} 403}
376EXPORT_SYMBOL(drm_crtc_init); 404EXPORT_SYMBOL(drm_crtc_init);
405
406int drm_plane_helper_commit(struct drm_plane *plane,
407 struct drm_plane_state *plane_state,
408 struct drm_framebuffer *old_fb)
409{
410 struct drm_plane_helper_funcs *plane_funcs;
411 struct drm_crtc *crtc[2];
412 struct drm_crtc_helper_funcs *crtc_funcs[2];
413 int i, ret = 0;
414
415 plane_funcs = plane->helper_private;
416
417 /* Since this is a transitional helper we can't assume that plane->state
418 * is always valid. Hence we need to use plane->crtc instead of
419 * plane->state->crtc as the old crtc. */
420 crtc[0] = plane->crtc;
421 crtc[1] = crtc[0] != plane_state->crtc ? plane_state->crtc : NULL;
422
423 for (i = 0; i < 2; i++)
424 crtc_funcs[i] = crtc[i] ? crtc[i]->helper_private : NULL;
425
426 if (plane_funcs->atomic_check) {
427 ret = plane_funcs->atomic_check(plane, plane_state);
428 if (ret)
429 goto out;
430 }
431
432 if (plane_funcs->prepare_fb && plane_state->fb) {
433 ret = plane_funcs->prepare_fb(plane, plane_state->fb);
434 if (ret)
435 goto out;
436 }
437
438 /* Point of no return, commit sw state. */
439 swap(plane->state, plane_state);
440
441 for (i = 0; i < 2; i++) {
442 if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin)
443 crtc_funcs[i]->atomic_begin(crtc[i]);
444 }
445
446 plane_funcs->atomic_update(plane);
447
448 for (i = 0; i < 2; i++) {
449 if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)
450 crtc_funcs[i]->atomic_flush(crtc[i]);
451 }
452
453 for (i = 0; i < 2; i++) {
454 if (!crtc[i])
455 continue;
456
457 /* There's no other way to figure out whether the crtc is running. */
458 ret = drm_crtc_vblank_get(crtc[i]);
459 if (ret == 0) {
460 drm_crtc_wait_one_vblank(crtc[i]);
461 drm_crtc_vblank_put(crtc[i]);
462 }
463
464 ret = 0;
465 }
466
467 if (plane_funcs->cleanup_fb && old_fb)
468 plane_funcs->cleanup_fb(plane, old_fb);
469out:
470 if (plane_state) {
471 if (plane->funcs->atomic_destroy_state)
472 plane->funcs->atomic_destroy_state(plane, plane_state);
473 else
474 drm_atomic_helper_plane_destroy_state(plane, plane_state);
475 }
476
477 return ret;
478}
479
480/**
481 * drm_plane_helper_update() - Helper for primary plane update
482 * @plane: plane object to update
483 * @crtc: owning CRTC of owning plane
484 * @fb: framebuffer to flip onto plane
485 * @crtc_x: x offset of primary plane on crtc
486 * @crtc_y: y offset of primary plane on crtc
487 * @crtc_w: width of primary plane rectangle on crtc
488 * @crtc_h: height of primary plane rectangle on crtc
489 * @src_x: x offset of @fb for panning
490 * @src_y: y offset of @fb for panning
491 * @src_w: width of source rectangle in @fb
492 * @src_h: height of source rectangle in @fb
493 *
494 * Provides a default plane update handler using the atomic plane update
495 * functions. It is fully left to the driver to check plane constraints and
496 * handle corner-cases like a fully occluded or otherwise invisible plane.
497 *
498 * This is useful for piecewise transitioning of a driver to the atomic helpers.
499 *
500 * RETURNS:
501 * Zero on success, error code on failure
502 */
503int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
504 struct drm_framebuffer *fb,
505 int crtc_x, int crtc_y,
506 unsigned int crtc_w, unsigned int crtc_h,
507 uint32_t src_x, uint32_t src_y,
508 uint32_t src_w, uint32_t src_h)
509{
510 struct drm_plane_state *plane_state;
511
512 if (plane->funcs->atomic_duplicate_state)
513 plane_state = plane->funcs->atomic_duplicate_state(plane);
514 else if (plane->state)
515 plane_state = drm_atomic_helper_plane_duplicate_state(plane);
516 else
517 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
518 if (!plane_state)
519 return -ENOMEM;
520
521 plane_state->crtc = crtc;
522 drm_atomic_set_fb_for_plane(plane_state, fb);
523 plane_state->crtc_x = crtc_x;
524 plane_state->crtc_y = crtc_y;
525 plane_state->crtc_h = crtc_h;
526 plane_state->crtc_w = crtc_w;
527 plane_state->src_x = src_x;
528 plane_state->src_y = src_y;
529 plane_state->src_h = src_h;
530 plane_state->src_w = src_w;
531
532 return drm_plane_helper_commit(plane, plane_state, plane->fb);
533}
534EXPORT_SYMBOL(drm_plane_helper_update);
535
536/**
537 * drm_plane_helper_disable() - Helper for primary plane disable
538 * @plane: plane to disable
539 *
540 * Provides a default plane disable handler using the atomic plane update
541 * functions. It is fully left to the driver to check plane constraints and
542 * handle corner-cases like a fully occluded or otherwise invisible plane.
543 *
544 * This is useful for piecewise transitioning of a driver to the atomic helpers.
545 *
546 * RETURNS:
547 * Zero on success, error code on failure
548 */
549int drm_plane_helper_disable(struct drm_plane *plane)
550{
551 struct drm_plane_state *plane_state;
552
553 /* crtc helpers love to call disable functions for already disabled hw
554 * functions. So cope with that. */
555 if (!plane->crtc)
556 return 0;
557
558 if (plane->funcs->atomic_duplicate_state)
559 plane_state = plane->funcs->atomic_duplicate_state(plane);
560 else if (plane->state)
561 plane_state = drm_atomic_helper_plane_duplicate_state(plane);
562 else
563 plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
564 if (!plane_state)
565 return -ENOMEM;
566
567 plane_state->crtc = NULL;
568 drm_atomic_set_fb_for_plane(plane_state, NULL);
569
570 return drm_plane_helper_commit(plane, plane_state, plane->fb);
571}
572EXPORT_SYMBOL(drm_plane_helper_disable);