blob: 7946b7fe52cb21c17ed61dc44ad94a7a28a7edd6 [file] [log] [blame]
/*
* Copyright (C) 2014 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRM_ATOMIC_HELPER_H_
#define DRM_ATOMIC_HELPER_H_
/**
* DOC: atomic state helpers
*
* Base helper atomic state and functions. Drivers are free to either
* use these as-is, extend them, or completely replace them, in order
* to implement the atomic KMS API.
*
* A naive driver, with no special constraints or hw support for atomic
* updates may simply add the following to their driver struct:
*
* .atomic_begin = drm_atomic_begin,
* .atomic_set_event = drm_atomic_set_event,
* .atomic_check = drm_atomic_check,
* .atomic_commit = drm_atomic_commit,
* .atomic_end = drm_atomic_end,
* .atomics = &drm_atomic_funcs,
*
* In addition, if you're plane/crtc doesn't already have it's own custom
* properties, then add to your plane/crtc_funcs:
*
* .set_property = drm_atomic_{plane,crtc}_set_property,
*
* Unlike the crtc helpers, it is intended that the atomic helpers can be
* used piecemeal by the drivers, either using all or overriding parts as
* needed.
*
* A driver which can have (for example) conflicting modes across multiple
* crtcs (for example, bandwidth limitations or clock/pll configuration
* restrictions), can simply wrap drm_atomic_check() with their own
* driver specific .atomic_check() function.
*
* A driver which can support true atomic updates can wrap
* drm_atomic_commit().
*
* A driver with custom properties should override the appropriate get_state(),
* check_state(), and commit_state() functions in .atomics if it uses
* the drm-atomic-helpers. Otherwise it is free to use &drm_atomic_funcs
* as-is.
*/
/**
* struct drm_atomic_funcs - helper funcs used by the atomic helpers
*/
struct drm_atomic_funcs {
int (*check_plane_state)(struct drm_plane *plane, struct drm_plane_state *pstate);
int (*commit_plane_state)(struct drm_plane *plane, struct drm_plane_state *pstate);
int (*check_crtc_state)(struct drm_crtc *crtc, struct drm_crtc_state *cstate);
int (*commit_crtc_state)(struct drm_crtc *crtc, struct drm_crtc_state *cstate);
};
const extern struct drm_atomic_funcs drm_atomic_funcs;
struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev,
uint32_t flags);
int drm_atomic_set_event(struct drm_device *dev,
struct drm_atomic_state *state, struct drm_mode_object *obj,
struct drm_pending_vblank_event *event);
int drm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
int drm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state);
int drm_atomic_commit_unlocked(struct drm_device *dev,
struct drm_atomic_state *state);
void drm_atomic_end(struct drm_device *dev, struct drm_atomic_state *state);
int drm_atomic_plane_set_property(struct drm_plane *plane,
struct drm_atomic_state *state, struct drm_property *property,
uint64_t val, void *blob_data);
struct drm_plane_state *drm_atomic_get_plane_state(struct drm_plane *plane,
struct drm_atomic_state *state);
static inline int
drm_atomic_check_plane_state(struct drm_plane *plane,
struct drm_plane_state *pstate)
{
const struct drm_atomic_funcs *funcs =
plane->dev->driver->atomic_funcs;
return funcs->check_plane_state(plane, pstate);
}
static inline int
drm_atomic_commit_plane_state(struct drm_plane *plane,
struct drm_plane_state *pstate)
{
const struct drm_atomic_funcs *funcs =
plane->dev->driver->atomic_funcs;
return funcs->commit_plane_state(plane, pstate);
}
int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
struct drm_atomic_state *state, struct drm_property *property,
uint64_t val, void *blob_data);
struct drm_crtc_state *drm_atomic_get_crtc_state(struct drm_crtc *crtc,
struct drm_atomic_state *state);
static inline int
drm_atomic_check_crtc_state(struct drm_crtc *crtc,
struct drm_crtc_state *cstate)
{
const struct drm_atomic_funcs *funcs =
crtc->dev->driver->atomic_funcs;
return funcs->check_crtc_state(crtc, cstate);
}
static inline int
drm_atomic_commit_crtc_state(struct drm_crtc *crtc,
struct drm_crtc_state *cstate)
{
const struct drm_atomic_funcs *funcs =
crtc->dev->driver->atomic_funcs;
return funcs->commit_crtc_state(crtc, cstate);
}
/**
* struct drm_atomic_state - the state object used by atomic helpers
*/
struct drm_atomic_state {
struct kref refcount;
struct drm_device *dev;
uint32_t flags;
struct drm_plane **planes;
struct drm_plane_state **pstates;
struct drm_crtc **crtcs;
struct drm_crtc_state **cstates;
bool committed;
bool checked; /* just for debugging */
struct drm_modeset_acquire_ctx acquire_ctx;
};
static inline void
drm_atomic_state_reference(struct drm_atomic_state *state)
{
kref_get(&state->refcount);
}
static inline void
drm_atomic_state_unreference(struct drm_atomic_state *state)
{
void _drm_atomic_state_free(struct kref *kref);
kref_put(&state->refcount, _drm_atomic_state_free);
}
#endif /* DRM_ATOMIC_HELPER_H_ */