aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_atomic_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_atomic_helper.c')
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c112
1 files changed, 103 insertions, 9 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index b16f1d69a0bb..ab4032167094 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -696,6 +696,100 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
696EXPORT_SYMBOL(drm_atomic_helper_check_modeset); 696EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
697 697
698/** 698/**
699 * drm_atomic_helper_check_plane_state() - Check plane state for validity
700 * @plane_state: plane state to check
701 * @crtc_state: crtc state to check
702 * @clip: integer clipping coordinates
703 * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
704 * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
705 * @can_position: is it legal to position the plane such that it
706 * doesn't cover the entire crtc? This will generally
707 * only be false for primary planes.
708 * @can_update_disabled: can the plane be updated while the crtc
709 * is disabled?
710 *
711 * Checks that a desired plane update is valid, and updates various
712 * bits of derived state (clipped coordinates etc.). Drivers that provide
713 * their own plane handling rather than helper-provided implementations may
714 * still wish to call this function to avoid duplication of error checking
715 * code.
716 *
717 * RETURNS:
718 * Zero if update appears valid, error code on failure
719 */
720int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
721 const struct drm_crtc_state *crtc_state,
722 const struct drm_rect *clip,
723 int min_scale,
724 int max_scale,
725 bool can_position,
726 bool can_update_disabled)
727{
728 struct drm_framebuffer *fb = plane_state->fb;
729 struct drm_rect *src = &plane_state->src;
730 struct drm_rect *dst = &plane_state->dst;
731 unsigned int rotation = plane_state->rotation;
732 int hscale, vscale;
733
734 WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
735
736 *src = drm_plane_state_src(plane_state);
737 *dst = drm_plane_state_dest(plane_state);
738
739 if (!fb) {
740 plane_state->visible = false;
741 return 0;
742 }
743
744 /* crtc should only be NULL when disabling (i.e., !fb) */
745 if (WARN_ON(!plane_state->crtc)) {
746 plane_state->visible = false;
747 return 0;
748 }
749
750 if (!crtc_state->enable && !can_update_disabled) {
751 DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
752 return -EINVAL;
753 }
754
755 drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
756
757 /* Check scaling */
758 hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
759 vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
760 if (hscale < 0 || vscale < 0) {
761 DRM_DEBUG_KMS("Invalid scaling of plane\n");
762 drm_rect_debug_print("src: ", &plane_state->src, true);
763 drm_rect_debug_print("dst: ", &plane_state->dst, false);
764 return -ERANGE;
765 }
766
767 plane_state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
768
769 drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
770
771 if (!plane_state->visible)
772 /*
773 * Plane isn't visible; some drivers can handle this
774 * so we just return success here. Drivers that can't
775 * (including those that use the primary plane helper's
776 * update function) will return an error from their
777 * update_plane handler.
778 */
779 return 0;
780
781 if (!can_position && !drm_rect_equals(dst, clip)) {
782 DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
783 drm_rect_debug_print("dst: ", dst, false);
784 drm_rect_debug_print("clip: ", clip, false);
785 return -EINVAL;
786 }
787
788 return 0;
789}
790EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
791
792/**
699 * drm_atomic_helper_check_planes - validate state object for planes changes 793 * drm_atomic_helper_check_planes - validate state object for planes changes
700 * @dev: DRM device 794 * @dev: DRM device
701 * @state: the driver state object 795 * @state: the driver state object
@@ -907,6 +1001,12 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
907 * 1001 *
908 * Drivers can use this for building their own atomic commit if they don't have 1002 * Drivers can use this for building their own atomic commit if they don't have
909 * a pure helper-based modeset implementation. 1003 * a pure helper-based modeset implementation.
1004 *
1005 * Since these updates are not synchronized with lockings, only code paths
1006 * called from &drm_mode_config_helper_funcs.atomic_commit_tail can look at the
1007 * legacy state filled out by this helper. Defacto this means this helper and
1008 * the legacy state pointers are only really useful for transitioning an
1009 * existing driver to the atomic world.
910 */ 1010 */
911void 1011void
912drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, 1012drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
@@ -1787,11 +1887,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
1787 !try_wait_for_completion(&old_conn_state->commit->flip_done)) 1887 !try_wait_for_completion(&old_conn_state->commit->flip_done))
1788 return -EBUSY; 1888 return -EBUSY;
1789 1889
1790 /* commit tracked through new_crtc_state->commit, no need to do it explicitly */ 1890 /* Always track connectors explicitly for e.g. link retraining. */
1791 if (new_conn_state->crtc) 1891 commit = crtc_or_fake_commit(state, new_conn_state->crtc ?: old_conn_state->crtc);
1792 continue;
1793
1794 commit = crtc_or_fake_commit(state, old_conn_state->crtc);
1795 if (!commit) 1892 if (!commit)
1796 return -ENOMEM; 1893 return -ENOMEM;
1797 1894
@@ -1805,10 +1902,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
1805 !try_wait_for_completion(&old_plane_state->commit->flip_done)) 1902 !try_wait_for_completion(&old_plane_state->commit->flip_done))
1806 return -EBUSY; 1903 return -EBUSY;
1807 1904
1808 /* 1905 /* Always track planes explicitly for async pageflip support. */
1809 * Unlike connectors, always track planes explicitly for
1810 * async pageflip support.
1811 */
1812 commit = crtc_or_fake_commit(state, new_plane_state->crtc ?: old_plane_state->crtc); 1906 commit = crtc_or_fake_commit(state, new_plane_state->crtc ?: old_plane_state->crtc);
1813 if (!commit) 1907 if (!commit)
1814 return -ENOMEM; 1908 return -ENOMEM;