aboutsummaryrefslogtreecommitdiffstats
path: root/include/drm
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-11-20 06:05:50 -0500
committerThierry Reding <treding@nvidia.com>2015-01-27 04:14:42 -0500
commit407b8bd9f5d284ffa13a9f9a709e6289bb4ae47e (patch)
tree97079a65544c70b332638457eb6409d97fa3ec4c /include/drm
parent3cad4b6887cd3d2b4e7f2c0ad6cb557b8eda4084 (diff)
drm/plane: Add optional ->atomic_disable() callback
In order to prevent drivers from having to perform the same checks over and over again, add an optional ->atomic_disable callback which the core calls under the right circumstances. v2: pass old state and detect edges to avoid calling ->atomic_disable on already disabled planes, remove redundant comment (Daniel Vetter) v3: rename helper to drm_atomic_plane_disabling() to clarify that it is checking for transitions, move helper to drm_atomic_helper.h, clarify check for !old_state and its relation to transitional helpers Here's an extract from some discussion rationalizing the behaviour (for a full version, see the reference below): > > Hm, thinking about this some more this will result in a slight difference > > in behaviour, at least when drivers just use the helper ->reset functions > > but don't disable everything: > > - With transitional helpers we assume we know nothing and call > > ->atomic_disable. > > - With atomic old_state->crtc == NULL in the same situation right after > > boot-up, but we asssume the plane is really off and _dont_ call > > ->atomic_disable. > > > > Should we instead check for (old_state && old_state->crtc) and state that > > drivers need to make sure they don't have stuff hanging around? > > I don't think we can check for old_state because otherwise this will > always return false, whereas we really want it to force-disable planes > that could be on (lacking any more accurate information). For > transitional helpers anyway. > > For the atomic helpers, old_state will never be NULL, but I'd assume > that the driver would reconstruct the current state in ->reset(). By the way, the reason for why old_state can be NULL with transitional helpers is the ordering of the steps in the atomic transition. Currently the Tegra patches do this (based on your blog post and the Exynos proto- type): 1) atomic conversion, phase 1: - implement ->atomic_{check,update,disable}() - use drm_plane_helper_{update,disable}() 2) atomic conversion, phase 2: - call drm_mode_config_reset() from ->load() - implement ->reset() That's only a partial list of what's done in these steps, but that's the only relevant pieces for why old_state is NULL. What happens is that without ->reset() implemented there won't be any initial state, hence plane->state (the old_state here) will be NULL the first time atomic state is applied. We could of course reorder the sequence such that drivers are required to hook up ->reset() before they can (or at the same as they) hook up the transitional helpers. We could add an appropriate WARN_ON to this helper to make that more obvious. However, that will not solve the problem because it only gets rid of the special case. We still don't know whether old_state->crtc == NULL is the current state or just the initial default. So no matter which way we do this, I don't see a way to get away without requiring specific semantics from drivers. They would be that: - drivers recreate the correct state in ->reset() so that old_state->crtc != NULL if the plane is really enabled or - drivers have to ensure that the real state in fact mirrors the initial default as encoded in the state (plane disabled) References: http://lists.freedesktop.org/archives/dri-devel/2015-January/075578.html Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'include/drm')
-rw-r--r--include/drm/drm_atomic_helper.h37
-rw-r--r--include/drm/drm_plane_helper.h3
2 files changed, 40 insertions, 0 deletions
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 2095917ff8c7..a0ea4ded3cb5 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -127,4 +127,41 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
127#define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \ 127#define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \
128 drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) 128 drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask)
129 129
130/*
131 * drm_atomic_plane_disabling - check whether a plane is being disabled
132 * @plane: plane object
133 * @old_state: previous atomic state
134 *
135 * Checks the atomic state of a plane to determine whether it's being disabled
136 * or not. This also WARNs if it detects an invalid state (both CRTC and FB
137 * need to either both be NULL or both be non-NULL).
138 *
139 * RETURNS:
140 * True if the plane is being disabled, false otherwise.
141 */
142static inline bool
143drm_atomic_plane_disabling(struct drm_plane *plane,
144 struct drm_plane_state *old_state)
145{
146 /*
147 * When disabling a plane, CRTC and FB should always be NULL together.
148 * Anything else should be considered a bug in the atomic core, so we
149 * gently warn about it.
150 */
151 WARN_ON((plane->state->crtc == NULL && plane->state->fb != NULL) ||
152 (plane->state->crtc != NULL && plane->state->fb == NULL));
153
154 /*
155 * When using the transitional helpers, old_state may be NULL. If so,
156 * we know nothing about the current state and have to assume that it
157 * might be enabled.
158 *
159 * When using the atomic helpers, old_state won't be NULL. Therefore
160 * this check assumes that either the driver will have reconstructed
161 * the correct state in ->reset() or that the driver will have taken
162 * appropriate measures to disable all planes.
163 */
164 return (!old_state || old_state->crtc) && !plane->state->crtc;
165}
166
130#endif /* DRM_ATOMIC_HELPER_H_ */ 167#endif /* DRM_ATOMIC_HELPER_H_ */
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
index 06d0314a1352..31c11d36fae6 100644
--- a/include/drm/drm_plane_helper.h
+++ b/include/drm/drm_plane_helper.h
@@ -53,6 +53,7 @@ extern int drm_crtc_init(struct drm_device *dev,
53 * @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane 53 * @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane
54 * @atomic_check: check that a given atomic state is valid and can be applied 54 * @atomic_check: check that a given atomic state is valid and can be applied
55 * @atomic_update: apply an atomic state to the plane (mandatory) 55 * @atomic_update: apply an atomic state to the plane (mandatory)
56 * @atomic_disable: disable the plane
56 * 57 *
57 * The helper operations are called by the mid-layer CRTC helper. 58 * The helper operations are called by the mid-layer CRTC helper.
58 */ 59 */
@@ -66,6 +67,8 @@ struct drm_plane_helper_funcs {
66 struct drm_plane_state *state); 67 struct drm_plane_state *state);
67 void (*atomic_update)(struct drm_plane *plane, 68 void (*atomic_update)(struct drm_plane *plane,
68 struct drm_plane_state *old_state); 69 struct drm_plane_state *old_state);
70 void (*atomic_disable)(struct drm_plane *plane,
71 struct drm_plane_state *old_state);
69}; 72};
70 73
71static inline void drm_plane_helper_add(struct drm_plane *plane, 74static inline void drm_plane_helper_add(struct drm_plane *plane,