diff options
author | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2017-08-07 06:20:06 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-08-08 08:09:34 -0400 |
commit | 3dfeb631a15db17f187f1e5cc522207f46506611 (patch) | |
tree | 5ef03ef049b16b09b3280535ff8ab2e2c3764f2c /drivers/gpu/drm/omapdrm/omap_crtc.c | |
parent | 481e1625f04fa12cdaa80895e7d6a63eca5aa8c5 (diff) |
drm/omap: Rework the rotation-on-crtc hack
I want/need to rework the core property handling, and this hack is
getting in the way. But since it's a non-standard propety only used by
legacy userspace we know that this will only every be called from
ioctl code. And never on some other free-standing state struct, where
this old hack wouldn't work either.
v2: don't forget zorder and get_property!
v3: Shadow the legacy state to avoid locking issues in get_property
(Maarten).
v4: Review from Laurent
- Move struct omap_crtc_state into omap_crtc.c
- Clean up comments.
- Don't forget to copy the shadowed state over on duplicate.
v5: Don't forget to update the reset handler (Maarten).
v6: Update omap_crtc_state shadow values in omap_crtc_atomic_check (Maarten).
v7:
- Fix get_property to return 0 and set value in *val (Maarten).
- Update comment in set_property for changes in v6 (Maarten).
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> (v4)
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> (v4)
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/a6a10a4f-2ebc-5f81-00bd-5e906967f384@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 124 |
1 files changed, 85 insertions, 39 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 14e8a7738b06..09e05e002703 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
@@ -26,6 +26,16 @@ | |||
26 | 26 | ||
27 | #include "omap_drv.h" | 27 | #include "omap_drv.h" |
28 | 28 | ||
29 | #define to_omap_crtc_state(x) container_of(x, struct omap_crtc_state, base) | ||
30 | |||
31 | struct omap_crtc_state { | ||
32 | /* Must be first. */ | ||
33 | struct drm_crtc_state base; | ||
34 | /* Shadow values for legacy userspace support. */ | ||
35 | unsigned int rotation; | ||
36 | unsigned int zpos; | ||
37 | }; | ||
38 | |||
29 | #define to_omap_crtc(x) container_of(x, struct omap_crtc, base) | 39 | #define to_omap_crtc(x) container_of(x, struct omap_crtc, base) |
30 | 40 | ||
31 | struct omap_crtc { | 41 | struct omap_crtc { |
@@ -445,6 +455,8 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
445 | static int omap_crtc_atomic_check(struct drm_crtc *crtc, | 455 | static int omap_crtc_atomic_check(struct drm_crtc *crtc, |
446 | struct drm_crtc_state *state) | 456 | struct drm_crtc_state *state) |
447 | { | 457 | { |
458 | struct drm_plane_state *pri_state; | ||
459 | |||
448 | if (state->color_mgmt_changed && state->gamma_lut) { | 460 | if (state->color_mgmt_changed && state->gamma_lut) { |
449 | uint length = state->gamma_lut->length / | 461 | uint length = state->gamma_lut->length / |
450 | sizeof(struct drm_color_lut); | 462 | sizeof(struct drm_color_lut); |
@@ -453,6 +465,16 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc, | |||
453 | return -EINVAL; | 465 | return -EINVAL; |
454 | } | 466 | } |
455 | 467 | ||
468 | pri_state = drm_atomic_get_new_plane_state(state->state, crtc->primary); | ||
469 | if (pri_state) { | ||
470 | struct omap_crtc_state *omap_crtc_state = | ||
471 | to_omap_crtc_state(state); | ||
472 | |||
473 | /* Mirror new values for zpos and rotation in omap_crtc_state */ | ||
474 | omap_crtc_state->zpos = pri_state->zpos; | ||
475 | omap_crtc_state->rotation = pri_state->rotation; | ||
476 | } | ||
477 | |||
456 | return 0; | 478 | return 0; |
457 | } | 479 | } |
458 | 480 | ||
@@ -498,39 +520,32 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, | |||
498 | spin_unlock_irq(&crtc->dev->event_lock); | 520 | spin_unlock_irq(&crtc->dev->event_lock); |
499 | } | 521 | } |
500 | 522 | ||
501 | static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc, | ||
502 | struct drm_property *property) | ||
503 | { | ||
504 | struct drm_device *dev = crtc->dev; | ||
505 | struct omap_drm_private *priv = dev->dev_private; | ||
506 | |||
507 | return property == priv->zorder_prop || | ||
508 | property == crtc->primary->rotation_property; | ||
509 | } | ||
510 | |||
511 | static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, | 523 | static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, |
512 | struct drm_crtc_state *state, | 524 | struct drm_crtc_state *state, |
513 | struct drm_property *property, | 525 | struct drm_property *property, |
514 | uint64_t val) | 526 | uint64_t val) |
515 | { | 527 | { |
516 | if (omap_crtc_is_plane_prop(crtc, property)) { | 528 | struct omap_drm_private *priv = crtc->dev->dev_private; |
517 | struct drm_plane_state *plane_state; | 529 | struct drm_plane_state *plane_state; |
518 | struct drm_plane *plane = crtc->primary; | ||
519 | |||
520 | /* | ||
521 | * Delegate property set to the primary plane. Get the plane | ||
522 | * state and set the property directly. | ||
523 | */ | ||
524 | |||
525 | plane_state = drm_atomic_get_plane_state(state->state, plane); | ||
526 | if (IS_ERR(plane_state)) | ||
527 | return PTR_ERR(plane_state); | ||
528 | 530 | ||
529 | return drm_atomic_plane_set_property(plane, plane_state, | 531 | /* |
530 | property, val); | 532 | * Delegate property set to the primary plane. Get the plane state and |
531 | } | 533 | * set the property directly, the shadow copy will be assigned in the |
534 | * omap_crtc_atomic_check callback. This way updates to plane state will | ||
535 | * always be mirrored in the crtc state correctly. | ||
536 | */ | ||
537 | plane_state = drm_atomic_get_plane_state(state->state, crtc->primary); | ||
538 | if (IS_ERR(plane_state)) | ||
539 | return PTR_ERR(plane_state); | ||
540 | |||
541 | if (property == crtc->primary->rotation_property) | ||
542 | plane_state->rotation = val; | ||
543 | else if (property == priv->zorder_prop) | ||
544 | plane_state->zpos = val; | ||
545 | else | ||
546 | return -EINVAL; | ||
532 | 547 | ||
533 | return -EINVAL; | 548 | return 0; |
534 | } | 549 | } |
535 | 550 | ||
536 | static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, | 551 | static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, |
@@ -538,28 +553,59 @@ static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, | |||
538 | struct drm_property *property, | 553 | struct drm_property *property, |
539 | uint64_t *val) | 554 | uint64_t *val) |
540 | { | 555 | { |
541 | if (omap_crtc_is_plane_prop(crtc, property)) { | 556 | struct omap_drm_private *priv = crtc->dev->dev_private; |
542 | /* | 557 | struct omap_crtc_state *omap_state = to_omap_crtc_state(state); |
543 | * Delegate property get to the primary plane. The | 558 | |
544 | * drm_atomic_plane_get_property() function isn't exported, but | 559 | if (property == crtc->primary->rotation_property) |
545 | * can be called through drm_object_property_get_value() as that | 560 | *val = omap_state->rotation; |
546 | * will call drm_atomic_get_property() for atomic drivers. | 561 | else if (property == priv->zorder_prop) |
547 | */ | 562 | *val = omap_state->zpos; |
548 | return drm_object_property_get_value(&crtc->primary->base, | 563 | else |
549 | property, val); | 564 | return -EINVAL; |
550 | } | 565 | |
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static void omap_crtc_reset(struct drm_crtc *crtc) | ||
570 | { | ||
571 | if (crtc->state) | ||
572 | __drm_atomic_helper_crtc_destroy_state(crtc->state); | ||
573 | |||
574 | kfree(crtc->state); | ||
575 | crtc->state = kzalloc(sizeof(struct omap_crtc_state), GFP_KERNEL); | ||
576 | |||
577 | if (crtc->state) | ||
578 | crtc->state->crtc = crtc; | ||
579 | } | ||
580 | |||
581 | static struct drm_crtc_state * | ||
582 | omap_crtc_duplicate_state(struct drm_crtc *crtc) | ||
583 | { | ||
584 | struct omap_crtc_state *state, *current_state; | ||
585 | |||
586 | if (WARN_ON(!crtc->state)) | ||
587 | return NULL; | ||
588 | |||
589 | current_state = to_omap_crtc_state(crtc->state); | ||
590 | |||
591 | state = kmalloc(sizeof(*state), GFP_KERNEL); | ||
592 | if (state) | ||
593 | __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); | ||
594 | |||
595 | state->zpos = current_state->zpos; | ||
596 | state->rotation = current_state->rotation; | ||
551 | 597 | ||
552 | return -EINVAL; | 598 | return &state->base; |
553 | } | 599 | } |
554 | 600 | ||
555 | static const struct drm_crtc_funcs omap_crtc_funcs = { | 601 | static const struct drm_crtc_funcs omap_crtc_funcs = { |
556 | .reset = drm_atomic_helper_crtc_reset, | 602 | .reset = omap_crtc_reset, |
557 | .set_config = drm_atomic_helper_set_config, | 603 | .set_config = drm_atomic_helper_set_config, |
558 | .destroy = omap_crtc_destroy, | 604 | .destroy = omap_crtc_destroy, |
559 | .page_flip = drm_atomic_helper_page_flip, | 605 | .page_flip = drm_atomic_helper_page_flip, |
560 | .gamma_set = drm_atomic_helper_legacy_gamma_set, | 606 | .gamma_set = drm_atomic_helper_legacy_gamma_set, |
561 | .set_property = drm_atomic_helper_crtc_set_property, | 607 | .set_property = drm_atomic_helper_crtc_set_property, |
562 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, | 608 | .atomic_duplicate_state = omap_crtc_duplicate_state, |
563 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, | 609 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, |
564 | .atomic_set_property = omap_crtc_atomic_set_property, | 610 | .atomic_set_property = omap_crtc_atomic_set_property, |
565 | .atomic_get_property = omap_crtc_atomic_get_property, | 611 | .atomic_get_property = omap_crtc_atomic_get_property, |