drm/atomic-helper: Export both plane and modeset check helpers
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 26 Nov 2014 15:57:41 +0000 (16:57 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 17 Dec 2014 19:23:22 +0000 (20:23 +0100)
The default call sequence for these two parts won't fit for all
drivers. So export the two pieces and explain with a bit of kerneldoc
when each should be called.

v2: Squash in fixup from Rob to actually add the newly exported
functions to headers

Cc: Rob Clark <robdclark@gmail.com>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
drivers/gpu/drm/drm_atomic_helper.c
include/drm/drm_atomic_helper.h
include/drm/drm_crtc.h

index bbdbe47..0cd71da 100644 (file)
@@ -330,7 +330,29 @@ mode_fixup(struct drm_atomic_state *state)
        return 0;
 }
 
-static int
+/**
+ * drm_atomic_helper_check - validate state object for modeset changes
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * Check the state object to see if the requested state is physically possible.
+ * This does all the crtc and connector related computations for an atomic
+ * update. It computes and updates crtc_state->mode_changed, adds any additional
+ * connectors needed for full modesets and calls down into ->mode_fixup
+ * functions of the driver backend.
+ *
+ * IMPORTANT:
+ *
+ * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a
+ * plane update can't be done without a full modeset) _must_ call this function
+ * afterwards after that change. It is permitted to call this function multiple
+ * times for the same update, e.g. when the ->atomic_check functions depend upon
+ * the adjusted dotclock for fifo space allocation and watermark computation.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int
 drm_atomic_helper_check_modeset(struct drm_device *dev,
                                struct drm_atomic_state *state)
 {
@@ -406,23 +428,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 
        return mode_fixup(state);
 }
+EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
 
 /**
- * drm_atomic_helper_check - validate state object
+ * drm_atomic_helper_check - validate state object for modeset changes
  * @dev: DRM device
  * @state: the driver state object
  *
  * Check the state object to see if the requested state is physically possible.
- * Only crtcs and planes have check callbacks, so for any additional (global)
- * checking that a driver needs it can simply wrap that around this function.
- * Drivers without such needs can directly use this as their ->atomic_check()
- * callback.
+ * This does all the plane update related checks using by calling into the
+ * ->atomic_check hooks provided by the driver.
  *
  * RETURNS
  * Zero for success or -errno
  */
-int drm_atomic_helper_check(struct drm_device *dev,
-                           struct drm_atomic_state *state)
+int
+drm_atomic_helper_check_planes(struct drm_device *dev,
+                              struct drm_atomic_state *state)
 {
        int nplanes = dev->mode_config.num_total_plane;
        int ncrtcs = dev->mode_config.num_crtc;
@@ -471,6 +493,33 @@ int drm_atomic_helper_check(struct drm_device *dev,
                }
        }
 
+       return ret;
+}
+EXPORT_SYMBOL(drm_atomic_helper_check_planes);
+
+/**
+ * drm_atomic_helper_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * Check the state object to see if the requested state is physically possible.
+ * Only crtcs and planes have check callbacks, so for any additional (global)
+ * checking that a driver needs it can simply wrap that around this function.
+ * Drivers without such needs can directly use this as their ->atomic_check()
+ * callback.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int drm_atomic_helper_check(struct drm_device *dev,
+                           struct drm_atomic_state *state)
+{
+       int ret;
+
+       ret = drm_atomic_helper_check_planes(dev, state);
+       if (ret)
+               return ret;
+
        ret = drm_atomic_helper_check_modeset(dev, state);
        if (ret)
                return ret;
index f956b41..2095917 100644 (file)
 
 #include <drm/drm_crtc.h>
 
+int drm_atomic_helper_check_modeset(struct drm_device *dev,
+                               struct drm_atomic_state *state);
+int drm_atomic_helper_check_planes(struct drm_device *dev,
+                              struct drm_atomic_state *state);
 int drm_atomic_helper_check(struct drm_device *dev,
                            struct drm_atomic_state *state);
 int drm_atomic_helper_commit(struct drm_device *dev,
index b863298..4ee7821 100644 (file)
@@ -238,6 +238,7 @@ struct drm_atomic_state;
 /**
  * struct drm_crtc_state - mutable CRTC state
  * @enable: whether the CRTC should be enabled, gates all other state
+ * @active: whether the CRTC is actively displaying (used for DPMS)
  * @mode_changed: for use by helpers and drivers when computing state updates
  * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
  * @last_vblank_count: for helpers and drivers to capture the vblank of the
@@ -248,9 +249,16 @@ struct drm_atomic_state;
  * @event: optional pointer to a DRM event to signal upon completion of the
  *     state update
  * @state: backpointer to global drm_atomic_state
+ *
+ * Note that the distinction between @enable and @active is rather subtile:
+ * Flipping @active while @enable is set without changing anything else may
+ * never return in a failure from the ->atomic_check callback. Userspace assumes
+ * that a DPMS On will always succeed. In other words: @enable controls resource
+ * assignment, @active controls the actual hardware state.
  */
 struct drm_crtc_state {
        bool enable;
+       bool active;
 
        /* computed state bits used by helpers and drivers */
        bool planes_changed : 1;