Merge tag 'topic/core-stuff-2014-11-28' of git://anongit.freedesktop.org/drm-intel into drm-next

So here's a pile of atomic fixes and improvements from various people.
There's still more patches in-flight, so I think I'll keep collecting them
in a separate branch.

* tag 'topic/core-stuff-2014-11-28' of git://anongit.freedesktop.org/drm-intel:
  drm/atomic: clear plane's CRTC and FB when shutting down
  drm: Handle atomic state properly in kms getfoo ioctl
  drm: use mode_object_find helpers
  drm: fix indentation
  drm/msm: switch to atomic-helpers iterator macros
  drm/atomic: add plane iterator macros
  drm/atomic: track bitmask of planes attached to crtc
  drm: Free atomic state during cleanup
  drm: Make drm_atomic.h standalone includible
  drm: Make drm_atomic_helper.h standalone includible
  drm/plane: Add missing kerneldoc
  drm/plane: Pass old state to ->atomic_update()
  drm/atomic_helper: Cope with plane->crtc == NULL in disable helper
  drm/atomic: Drop per-plane locking TODO
  drm/atomic-helper: Skip vblank waits for unchanged fbs
  drm: Document that drm_dev_alloc doesn't need a parent
This commit is contained in:
Dave Airlie 2014-12-02 08:59:34 +10:00
commit 9be23ae435
16 changed files with 226 additions and 75 deletions

View File

@ -2343,6 +2343,7 @@ void intel_crt_init(struct drm_device *dev)
<title>Atomic State Reset and Initialization</title>
!Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization
</sect3>
!Iinclude/drm/drm_atomic_helper.h
!Edrivers/gpu/drm/drm_atomic_helper.c
</sect2>
<sect2>

View File

@ -243,12 +243,6 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
if (state->plane_states[index])
return state->plane_states[index];
/*
* TODO: We currently don't have per-plane mutexes. So instead of trying
* crazy tricks with deferring plane->crtc and hoping for the best just
* grab all crtc locks. Once we have per-plane locks we must update this
* to only take the plane mutex.
*/
ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
if (ret)
return ERR_PTR(ret);
@ -350,7 +344,8 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
/**
* drm_atomic_set_crtc_for_plane - set crtc for plane
* @plane_state: atomic state object for the plane
* @state: the incoming atomic state
* @plane: the plane whose incoming state to update
* @crtc: crtc to use for the plane
*
* Changing the assigned crtc for a plane requires us to grab the lock and state
@ -363,20 +358,35 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state);
* sequence must be restarted. All other errors are fatal.
*/
int
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
struct drm_crtc *crtc)
drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
struct drm_plane *plane, struct drm_crtc *crtc)
{
struct drm_plane_state *plane_state =
drm_atomic_get_plane_state(state, plane);
struct drm_crtc_state *crtc_state;
if (WARN_ON(IS_ERR(plane_state)))
return PTR_ERR(plane_state);
if (plane_state->crtc) {
crtc_state = drm_atomic_get_crtc_state(plane_state->state,
plane_state->crtc);
if (WARN_ON(IS_ERR(crtc_state)))
return PTR_ERR(crtc_state);
crtc_state->plane_mask &= ~(1 << drm_plane_index(plane));
}
plane_state->crtc = crtc;
if (crtc) {
crtc_state = drm_atomic_get_crtc_state(plane_state->state,
crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
crtc_state->plane_mask |= (1 << drm_plane_index(plane));
}
plane_state->crtc = crtc;
if (crtc)
DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n",
plane_state, crtc->base.id);

View File

@ -751,6 +751,33 @@ static void wait_for_fences(struct drm_device *dev,
}
}
static bool framebuffer_changed(struct drm_device *dev,
struct drm_atomic_state *old_state,
struct drm_crtc *crtc)
{
struct drm_plane *plane;
struct drm_plane_state *old_plane_state;
int nplanes = old_state->dev->mode_config.num_total_plane;
int i;
for (i = 0; i < nplanes; i++) {
plane = old_state->planes[i];
old_plane_state = old_state->plane_states[i];
if (!plane)
continue;
if (plane->state->crtc != crtc &&
old_plane_state->crtc != crtc)
continue;
if (plane->state->fb != old_plane_state->fb)
return true;
}
return false;
}
/**
* drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs
* @dev: DRM device
@ -758,7 +785,9 @@ static void wait_for_fences(struct drm_device *dev,
*
* Helper to, after atomic commit, wait for vblanks on all effected
* crtcs (ie. before cleaning up old framebuffers using
* drm_atomic_helper_cleanup_planes())
* drm_atomic_helper_cleanup_planes()). It will only wait on crtcs where the
* framebuffers have actually changed to optimize for the legacy cursor and
* plane update use-case.
*/
void
drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
@ -784,6 +813,9 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
if (!crtc->state->enable)
continue;
if (!framebuffer_changed(dev, old_state, crtc))
continue;
ret = drm_crtc_vblank_get(crtc);
if (ret != 0)
continue;
@ -1014,6 +1046,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
for (i = 0; i < nplanes; i++) {
struct drm_plane_helper_funcs *funcs;
struct drm_plane *plane = old_state->planes[i];
struct drm_plane_state *old_plane_state;
if (!plane)
continue;
@ -1023,7 +1056,9 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
if (!funcs || !funcs->atomic_update)
continue;
funcs->atomic_update(plane);
old_plane_state = old_state->plane_states[i];
funcs->atomic_update(plane, old_plane_state);
}
for (i = 0; i < ncrtcs; i++) {
@ -1187,7 +1222,7 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
goto fail;
}
ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, fb);
@ -1243,6 +1278,17 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane)
struct drm_plane_state *plane_state;
int ret = 0;
/*
* FIXME: Without plane->crtc set we can't get at the implicit legacy
* acquire context. The real fix will be to wire the acquire ctx through
* everywhere we need it, but meanwhile prevent chaos by just skipping
* this noop. The critical case is the cursor ioctls which a) only grab
* crtc/cursor-plane locks (so we need the crtc to get at the right
* acquire context) and b) can try to disable the plane multiple times.
*/
if (!plane->crtc)
return 0;
state = drm_atomic_state_alloc(plane->dev);
if (!state)
return -ENOMEM;
@ -1255,7 +1301,7 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane)
goto fail;
}
ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
ret = drm_atomic_set_crtc_for_plane(state, plane, NULL);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, NULL);
@ -1406,11 +1452,24 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
goto fail;
}
primary_state = drm_atomic_get_plane_state(state, crtc->primary);
if (IS_ERR(primary_state)) {
ret = PTR_ERR(primary_state);
goto fail;
}
if (!set->mode) {
WARN_ON(set->fb);
WARN_ON(set->num_connectors);
crtc_state->enable = false;
ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(primary_state, NULL);
goto commit;
}
@ -1420,13 +1479,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
crtc_state->enable = true;
drm_mode_copy(&crtc_state->mode, set->mode);
primary_state = drm_atomic_get_plane_state(state, crtc->primary);
if (IS_ERR(primary_state)) {
ret = PTR_ERR(primary_state);
goto fail;
}
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(primary_state, set->fb);
@ -1698,7 +1751,7 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
goto fail;
}
ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, fb);

View File

@ -721,6 +721,10 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
drm_mode_object_put(dev, &crtc->base);
list_del(&crtc->head);
dev->mode_config.num_crtc--;
WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
if (crtc->state && crtc->funcs->atomic_destroy_state)
crtc->funcs->atomic_destroy_state(crtc, crtc->state);
}
EXPORT_SYMBOL(drm_crtc_cleanup);
@ -918,6 +922,11 @@ void drm_connector_cleanup(struct drm_connector *connector)
connector->name = NULL;
list_del(&connector->head);
dev->mode_config.num_connector--;
WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
if (connector->state && connector->funcs->atomic_destroy_state)
connector->funcs->atomic_destroy_state(connector,
connector->state);
}
EXPORT_SYMBOL(drm_connector_cleanup);
@ -1244,6 +1253,10 @@ void drm_plane_cleanup(struct drm_plane *plane)
if (plane->type == DRM_PLANE_TYPE_OVERLAY)
dev->mode_config.num_overlay_plane--;
drm_modeset_unlock_all(dev);
WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
if (plane->state && plane->funcs->atomic_destroy_state)
plane->funcs->atomic_destroy_state(plane, plane->state);
}
EXPORT_SYMBOL(drm_plane_cleanup);
@ -1955,6 +1968,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
return true;
}
static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
{
/* For atomic drivers only state objects are synchronously updated and
* protected by modeset locks, so check those first. */
if (connector->state)
return connector->state->best_encoder;
return connector->encoder;
}
/**
* drm_mode_getconnector - get connector configuration
* @dev: drm device for the ioctl
@ -1973,6 +1995,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
{
struct drm_mode_get_connector *out_resp = data;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_display_mode *mode;
int mode_count = 0;
int props_count = 0;
@ -2028,8 +2051,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
out_resp->subpixel = connector->display_info.subpixel_order;
out_resp->connection = connector->status;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
if (connector->encoder)
out_resp->encoder_id = connector->encoder->base.id;
encoder = drm_connector_get_encoder(connector);
if (encoder)
out_resp->encoder_id = encoder->base.id;
else
out_resp->encoder_id = 0;
drm_modeset_unlock(&dev->mode_config.connection_mutex);
@ -2099,6 +2124,33 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
return ret;
}
static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
{
struct drm_connector *connector;
struct drm_device *dev = encoder->dev;
bool uses_atomic = false;
/* For atomic drivers only state objects are synchronously updated and
* protected by modeset locks, so check those first. */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (!connector->state)
continue;
uses_atomic = true;
if (connector->state->best_encoder != encoder)
continue;
return connector->state->crtc;
}
/* Don't return stale data (e.g. pending async disable). */
if (uses_atomic)
return NULL;
return encoder->crtc;
}
/**
* drm_mode_getencoder - get encoder configuration
* @dev: drm device for the ioctl
@ -2117,6 +2169,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
{
struct drm_mode_get_encoder *enc_resp = data;
struct drm_encoder *encoder;
struct drm_crtc *crtc;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@ -2126,7 +2179,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
return -ENOENT;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
if (encoder->crtc)
crtc = drm_encoder_get_crtc(encoder);
if (crtc)
enc_resp->crtc_id = crtc->base.id;
else if (encoder->crtc)
enc_resp->crtc_id = encoder->crtc->base.id;
else
enc_resp->crtc_id = 0;
@ -2392,7 +2448,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_set_plane *plane_req = data;
struct drm_mode_object *obj;
struct drm_plane *plane;
struct drm_crtc *crtc = NULL;
struct drm_framebuffer *fb = NULL;
@ -2415,14 +2470,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
* First, find the plane, crtc, and fb objects. If not available,
* we don't bother to call the driver.
*/
obj = drm_mode_object_find(dev, plane_req->plane_id,
DRM_MODE_OBJECT_PLANE);
if (!obj) {
plane = drm_plane_find(dev, plane_req->plane_id);
if (!plane) {
DRM_DEBUG_KMS("Unknown plane ID %d\n",
plane_req->plane_id);
return -ENOENT;
}
plane = obj_to_plane(obj);
if (plane_req->fb_id) {
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
@ -2432,14 +2485,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
return -ENOENT;
}
obj = drm_mode_object_find(dev, plane_req->crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!obj) {
crtc = drm_crtc_find(dev, plane_req->crtc_id);
if (!crtc) {
DRM_DEBUG_KMS("Unknown crtc ID %d\n",
plane_req->crtc_id);
return -ENOENT;
}
crtc = obj_to_crtc(obj);
}
/*

View File

@ -535,6 +535,8 @@ static void drm_fs_inode_free(struct inode *inode)
* The initial ref-count of the object is 1. Use drm_dev_ref() and
* drm_dev_unref() to take and drop further ref-counts.
*
* Note that for purely virtual devices @parent can be NULL.
*
* RETURNS:
* Pointer to new DRM device, or NULL if out of memory.
*/

View File

@ -443,7 +443,7 @@ int drm_plane_helper_commit(struct drm_plane *plane,
crtc_funcs[i]->atomic_begin(crtc[i]);
}
plane_funcs->atomic_update(plane);
plane_funcs->atomic_update(plane, plane_state);
for (i = 0; i < 2; i++) {
if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)

View File

@ -84,7 +84,7 @@ static void crtc_flush(struct drm_crtc *crtc)
struct drm_plane *plane;
uint32_t flush = 0;
for_each_plane_on_crtc(crtc, plane) {
drm_atomic_crtc_for_each_plane(plane, crtc) {
enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
flush |= pipe2flush(pipe_id);
}
@ -197,7 +197,7 @@ static void setup_mixer(struct mdp4_kms *mdp4_kms)
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
struct drm_plane *plane;
for_each_plane_on_crtc(crtc, plane) {
drm_atomic_crtc_for_each_plane(plane, crtc) {
enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
int idx = idxs[pipe_id];
mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
@ -221,7 +221,7 @@ static void blend_setup(struct drm_crtc *crtc)
mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0);
mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0);
for_each_plane_on_crtc(crtc, plane) {
drm_atomic_crtc_for_each_plane(plane, crtc) {
enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
int idx = idxs[pipe_id];
if (idx > 0) {

View File

@ -107,7 +107,8 @@ static int mdp4_plane_atomic_check(struct drm_plane *plane,
return 0;
}
static void mdp4_plane_atomic_update(struct drm_plane *plane)
static void mdp4_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct drm_plane_state *state = plane->state;
int ret;

View File

@ -91,7 +91,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)
if (!mdp5_crtc->ctl)
return;
for_each_plane_on_crtc(crtc, plane) {
drm_atomic_crtc_for_each_plane(plane, crtc) {
flush_mask |= mdp5_plane_get_flush(plane);
}
flush_mask |= mdp5_ctl_get_flush(mdp5_crtc->ctl);
@ -124,8 +124,9 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
}
spin_unlock_irqrestore(&dev->event_lock, flags);
for_each_plane_on_crtc(crtc, plane)
drm_atomic_crtc_for_each_plane(plane, crtc) {
mdp5_plane_complete_flip(plane);
}
}
static void mdp5_crtc_destroy(struct drm_crtc *crtc)
@ -195,7 +196,7 @@ static void blend_setup(struct drm_crtc *crtc)
if (!mdp5_crtc->ctl)
goto out;
for_each_plane_on_crtc(crtc, plane) {
drm_atomic_crtc_for_each_plane(plane, crtc) {
enum mdp_mixer_stage_id stage =
to_mdp5_plane_state(plane->state)->stage;
@ -317,7 +318,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
/* verify that there are not too many planes attached to crtc
* and that we don't have conflicting mixer stages:
*/
for_each_pending_plane_on_crtc(state->state, crtc, plane) {
drm_atomic_crtc_state_for_each_plane(plane, state) {
struct drm_plane_state *pstate;
if (cnt >= ARRAY_SIZE(pstates)) {

View File

@ -213,7 +213,8 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
return 0;
}
static void mdp5_plane_atomic_update(struct drm_plane *plane)
static void mdp5_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct drm_plane_state *state = plane->state;

View File

@ -65,27 +65,4 @@ static inline void msm_kms_init(struct msm_kms *kms,
struct msm_kms *mdp4_kms_init(struct drm_device *dev);
struct msm_kms *mdp5_kms_init(struct drm_device *dev);
/* TODO move these helper iterator macro somewhere common: */
#define for_each_plane_on_crtc(_crtc, _plane) \
list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \
if ((_plane)->state->crtc == (_crtc))
static inline bool
__plane_will_be_attached_to_crtc(struct drm_atomic_state *state,
struct drm_plane *plane, struct drm_crtc *crtc)
{
int idx = drm_plane_index(plane);
/* if plane is modified in incoming state, use the new state: */
if (state->plane_states[idx])
return state->plane_states[idx]->crtc == crtc;
/* otherwise, current state: */
return plane->state->crtc == crtc;
}
#define for_each_pending_plane_on_crtc(_state, _crtc, _plane) \
list_for_each_entry((_plane), &(_crtc)->dev->mode_config.plane_list, head) \
if (__plane_will_be_attached_to_crtc((_state), (_plane), (_crtc)))
#endif /* __MSM_KMS_H__ */

View File

@ -809,7 +809,7 @@ struct drm_device {
struct drm_local_map *agp_buffer_map;
unsigned int agp_buffer_token;
struct drm_mode_config mode_config; /**< Current mode config */
struct drm_mode_config mode_config; /**< Current mode config */
/** \name GEM information */
/*@{ */

View File

@ -28,6 +28,8 @@
#ifndef DRM_ATOMIC_H_
#define DRM_ATOMIC_H_
#include <drm/drm_crtc.h>
struct drm_atomic_state * __must_check
drm_atomic_state_alloc(struct drm_device *dev);
void drm_atomic_state_clear(struct drm_atomic_state *state);
@ -44,8 +46,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
struct drm_connector *connector);
int __must_check
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
struct drm_crtc *crtc);
drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
struct drm_plane *plane, struct drm_crtc *crtc);
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
struct drm_framebuffer *fb);
int __must_check

View File

@ -28,6 +28,8 @@
#ifndef DRM_ATOMIC_HELPER_H_
#define DRM_ATOMIC_HELPER_H_
#include <drm/drm_crtc.h>
int drm_atomic_helper_check(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_atomic_helper_commit(struct drm_device *dev,
@ -96,5 +98,29 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state);
/**
* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
* @plane: the loop cursor
* @crtc: the crtc whose planes are iterated
*
* This iterates over the current state, useful (for example) when applying
* atomic state after it has been checked and swapped. To iterate over the
* planes which *will* be attached (for ->atomic_check()) see
* drm_crtc_for_each_pending_plane()
*/
#define drm_atomic_crtc_for_each_plane(plane, crtc) \
drm_for_each_plane_mask(plane, (crtc)->dev, (crtc)->state->plane_mask)
/**
* drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state
* @plane: the loop cursor
* @crtc_state: the incoming crtc-state
*
* Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
* attached if the specified state is applied. Useful during (for example)
* ->atomic_check() operations, to validate the incoming state
*/
#define drm_atomic_crtc_state_for_each_plane(plane, crtc_state) \
drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask)
#endif /* DRM_ATOMIC_HELPER_H_ */

View File

@ -231,6 +231,7 @@ struct drm_atomic_state;
* struct drm_crtc_state - mutable CRTC state
* @enable: whether the CRTC should be enabled, gates all other state
* @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
* update to ensure framebuffer cleanup isn't done too early
* @planes_changed: for use by helpers and drivers when computing state updates
@ -247,6 +248,13 @@ struct drm_crtc_state {
bool planes_changed : 1;
bool mode_changed : 1;
/* attached planes bitmask:
* WARNING: transitional helpers do not maintain plane_mask so
* drivers not converted over to atomic helpers should not rely
* on plane_mask being accurate!
*/
u32 plane_mask;
/* last_vblank_count: for vblank waits before cleanup */
u32 last_vblank_count;
@ -438,7 +446,7 @@ struct drm_crtc {
* @state: backpointer to global drm_atomic_state
*/
struct drm_connector_state {
struct drm_crtc *crtc;
struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */
struct drm_encoder *best_encoder;
@ -673,8 +681,8 @@ struct drm_connector {
* @state: backpointer to global drm_atomic_state
*/
struct drm_plane_state {
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
struct fence *fence;
/* Signed dest location allows it to be partially off screen */
@ -1054,6 +1062,19 @@ struct drm_mode_config {
uint32_t cursor_width, cursor_height;
};
/**
* drm_for_each_plane_mask - iterate over planes specified by bitmask
* @plane: the loop cursor
* @dev: the DRM device
* @plane_mask: bitmask of plane indices
*
* Iterate over all planes specified by bitmask.
*/
#define drm_for_each_plane_mask(plane, dev, plane_mask) \
list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
if ((plane_mask) & (1 << drm_plane_index(plane)))
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
#define obj_to_connector(x) container_of(x, struct drm_connector, base)
#define obj_to_encoder(x) container_of(x, struct drm_encoder, base)

View File

@ -49,6 +49,10 @@ extern int drm_crtc_init(struct drm_device *dev,
/**
* drm_plane_helper_funcs - helper operations for CRTCs
* @prepare_fb: prepare a framebuffer for use by the plane
* @cleanup_fb: cleanup a framebuffer when it's no longer used by the plane
* @atomic_check: check that a given atomic state is valid and can be applied
* @atomic_update: apply an atomic state to the plane
*
* The helper operations are called by the mid-layer CRTC helper.
*/
@ -60,7 +64,8 @@ struct drm_plane_helper_funcs {
int (*atomic_check)(struct drm_plane *plane,
struct drm_plane_state *state);
void (*atomic_update)(struct drm_plane *plane);
void (*atomic_update)(struct drm_plane *plane,
struct drm_plane_state *old_state);
};
static inline void drm_plane_helper_add(struct drm_plane *plane,