Commit d9b13620 authored by Daniel Vetter's avatar Daniel Vetter

drm/atomic-helper: Export both plane and modeset check helpers

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: default avatarRob Clark <robdclark@gmail.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
parent 4b08eae5
...@@ -330,7 +330,29 @@ mode_fixup(struct drm_atomic_state *state) ...@@ -330,7 +330,29 @@ mode_fixup(struct drm_atomic_state *state)
return 0; 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, drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state) struct drm_atomic_state *state)
{ {
...@@ -406,23 +428,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, ...@@ -406,23 +428,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
return mode_fixup(state); 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 * @dev: DRM device
* @state: the driver state object * @state: the driver state object
* *
* Check the state object to see if the requested state is physically possible. * 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) * This does all the plane update related checks using by calling into the
* checking that a driver needs it can simply wrap that around this function. * ->atomic_check hooks provided by the driver.
* Drivers without such needs can directly use this as their ->atomic_check()
* callback.
* *
* RETURNS * RETURNS
* Zero for success or -errno * Zero for success or -errno
*/ */
int drm_atomic_helper_check(struct drm_device *dev, int
struct drm_atomic_state *state) drm_atomic_helper_check_planes(struct drm_device *dev,
struct drm_atomic_state *state)
{ {
int nplanes = dev->mode_config.num_total_plane; int nplanes = dev->mode_config.num_total_plane;
int ncrtcs = dev->mode_config.num_crtc; int ncrtcs = dev->mode_config.num_crtc;
...@@ -471,6 +493,33 @@ int drm_atomic_helper_check(struct drm_device *dev, ...@@ -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); ret = drm_atomic_helper_check_modeset(dev, state);
if (ret) if (ret)
return ret; return ret;
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include <drm/drm_crtc.h> #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, int drm_atomic_helper_check(struct drm_device *dev,
struct drm_atomic_state *state); struct drm_atomic_state *state);
int drm_atomic_helper_commit(struct drm_device *dev, int drm_atomic_helper_commit(struct drm_device *dev,
......
...@@ -238,6 +238,7 @@ struct drm_atomic_state; ...@@ -238,6 +238,7 @@ struct drm_atomic_state;
/** /**
* struct drm_crtc_state - mutable CRTC state * struct drm_crtc_state - mutable CRTC state
* @enable: whether the CRTC should be enabled, gates all other 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 * @mode_changed: for use by helpers and drivers when computing state updates
* @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes * @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 * @last_vblank_count: for helpers and drivers to capture the vblank of the
...@@ -248,9 +249,16 @@ struct drm_atomic_state; ...@@ -248,9 +249,16 @@ struct drm_atomic_state;
* @event: optional pointer to a DRM event to signal upon completion of the * @event: optional pointer to a DRM event to signal upon completion of the
* state update * state update
* @state: backpointer to global drm_atomic_state * @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 { struct drm_crtc_state {
bool enable; bool enable;
bool active;
/* computed state bits used by helpers and drivers */ /* computed state bits used by helpers and drivers */
bool planes_changed : 1; bool planes_changed : 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment