static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool async) { struct atmel_hlcdc_dc *dc = dev->dev_private; struct atmel_hlcdc_dc_commit *commit; int ret; ret = drm_atomic_helper_prepare_planes(dev, state); if (ret) return ret; /* Allocate the commit object. */ commit = kzalloc(sizeof(*commit), GFP_KERNEL); if (!commit) { ret = -ENOMEM; goto error; } INIT_WORK(&commit->work, atmel_hlcdc_dc_atomic_work); commit->dev = dev; commit->state = state; spin_lock(&dc->commit.wait.lock); ret = wait_event_interruptible_locked(dc->commit.wait, !dc->commit.pending); if (ret == 0) dc->commit.pending = true; spin_unlock(&dc->commit.wait.lock); if (ret) { kfree(commit); goto error; } /* Swap the state, this is the point of no return. */ drm_atomic_helper_swap_state(state, true); if (async) queue_work(dc->wq, &commit->work); else atmel_hlcdc_dc_atomic_complete(commit); return 0; error: drm_atomic_helper_cleanup_planes(dev, state); return ret; }
/* block until specified crtcs are no longer pending update, and * atomically mark them as pending update */ static int start_atomic(struct msm_drm_private *priv, uint32_t crtc_mask) { int ret; spin_lock(&priv->pending_crtcs_event.lock); ret = wait_event_interruptible_locked(priv->pending_crtcs_event, !(priv->pending_crtcs & crtc_mask)); if (ret == 0) { DBG("start: %08x", crtc_mask); priv->pending_crtcs |= crtc_mask; } spin_unlock(&priv->pending_crtcs_event.lock); return ret; }