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:
Коммит
9be23ae435
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 @@ retry:
|
|||
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 @@ retry:
|
|||
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 @@ retry:
|
|||
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 @@ retry:
|
|||
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 @@ retry:
|
|||
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);
|
||||
|
|
|
@ -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 @@ out:
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 */
|
||||
/*@{ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче