From: Rob Clark <robdclark@gmail.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH 1/7] drm: add atomic fxns
Date: Fri, 30 May 2014 13:23:03 -0400 [thread overview]
Message-ID: <1401470589-596-2-git-send-email-robdclark@gmail.com> (raw)
In-Reply-To: <1401470589-596-1-git-send-email-robdclark@gmail.com>
The 'atomic' mechanism allows for multiple properties to be updated,
checked, and commited atomically. This will be the basis of atomic-
modeset and nuclear-pageflip.
The basic flow is:
state = dev->atomic_begin();
for (... one or more ...)
obj->set_property(obj, state, prop, value);
if (dev->atomic_check(state))
dev->atomic_commit(state);
dev->atomic_end(state);
The split of check and commit steps is to allow for ioctls with a
test-only flag (which would skip the commit step).
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/Makefile | 2 +-
drivers/gpu/drm/armada/armada_crtc.c | 3 +-
drivers/gpu/drm/armada/armada_output.c | 3 +-
drivers/gpu/drm/armada/armada_overlay.c | 3 +-
drivers/gpu/drm/ast/ast_drv.c | 6 +
drivers/gpu/drm/ast/ast_drv.h | 1 +
drivers/gpu/drm/cirrus/cirrus_drv.c | 6 +
drivers/gpu/drm/cirrus/cirrus_drv.h | 1 +
drivers/gpu/drm/drm_atomic.c | 274 ++++++++++++++++++++++++++++
drivers/gpu/drm/drm_crtc.c | 149 +++++++++------
drivers/gpu/drm/drm_modeset_lock.c | 28 +++
drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +-
drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 +
drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 +-
drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 +-
drivers/gpu/drm/gma500/cdv_intel_dp.c | 4 +-
drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 4 +-
drivers/gpu/drm/gma500/cdv_intel_lvds.c | 4 +-
drivers/gpu/drm/gma500/mdfld_dsi_output.c | 4 +-
drivers/gpu/drm/gma500/psb_drv.c | 7 +
drivers/gpu/drm/gma500/psb_drv.h | 1 +
drivers/gpu/drm/gma500/psb_intel_drv.h | 4 +-
drivers/gpu/drm/gma500/psb_intel_lvds.c | 4 +-
drivers/gpu/drm/gma500/psb_intel_sdvo.c | 4 +-
drivers/gpu/drm/i915/i915_drv.c | 8 +
drivers/gpu/drm/i915/intel_crt.c | 4 +-
drivers/gpu/drm/i915/intel_dp.c | 4 +-
drivers/gpu/drm/i915/intel_drv.h | 1 +
drivers/gpu/drm/i915/intel_hdmi.c | 4 +-
drivers/gpu/drm/i915/intel_lvds.c | 4 +-
drivers/gpu/drm/i915/intel_sdvo.c | 4 +-
drivers/gpu/drm/i915/intel_tv.c | 6 +-
drivers/gpu/drm/mgag200/mgag200_drv.c | 7 +
drivers/gpu/drm/mgag200/mgag200_drv.h | 1 +
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 3 +-
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 3 +-
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 3 +-
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 +-
drivers/gpu/drm/msm/msm_drv.c | 6 +
drivers/gpu/drm/msm/msm_drv.h | 1 +
drivers/gpu/drm/nouveau/dispnv04/overlay.c | 5 +-
drivers/gpu/drm/nouveau/nouveau_connector.c | 3 +-
drivers/gpu/drm/nouveau/nouveau_drm.c | 7 +
drivers/gpu/drm/nouveau/nouveau_drm.h | 1 +
drivers/gpu/drm/omapdrm/omap_crtc.c | 6 +-
drivers/gpu/drm/omapdrm/omap_drv.c | 6 +
drivers/gpu/drm/omapdrm/omap_drv.h | 4 +-
drivers/gpu/drm/omapdrm/omap_plane.c | 3 +-
drivers/gpu/drm/qxl/qxl_display.c | 4 +-
drivers/gpu/drm/qxl/qxl_drv.c | 9 +
drivers/gpu/drm/radeon/radeon_connectors.c | 9 +-
drivers/gpu/drm/radeon/radeon_drv.c | 9 +
drivers/gpu/drm/rcar-du/rcar_du_drv.c | 7 +
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +-
drivers/gpu/drm/shmobile/shmob_drm_drv.c | 7 +
drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 +
drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 +
drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +-
drivers/gpu/drm/udl/udl_connector.c | 6 +-
drivers/gpu/drm/udl/udl_drv.c | 8 +
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 +
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 +
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 4 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +-
include/drm/drmP.h | 80 ++++++++
include/drm/drm_atomic.h | 114 ++++++++++++
include/drm/drm_crtc.h | 15 +-
include/drm/drm_modeset_lock.h | 41 +++++
include/uapi/drm/drm_mode.h | 3 +
69 files changed, 867 insertions(+), 103 deletions(-)
create mode 100644 drivers/gpu/drm/drm_atomic.c
create mode 100644 include/drm/drm_atomic.h
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index bf4c12d..c1d5f73 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
drm_info.o drm_debugfs.o drm_encoder_slave.o \
drm_trace_points.o drm_global.o drm_prime.o \
drm_rect.o drm_vma_manager.o drm_flip_work.o \
- drm_plane_helper.o drm_modeset_lock.o
+ drm_plane_helper.o drm_modeset_lock.o drm_atomic.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 81c34f9..7d3c649 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -961,7 +961,8 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
static int
armada_drm_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
struct armada_private *priv = crtc->dev->dev_private;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c
index d685a54..9915306 100644
--- a/drivers/gpu/drm/armada/armada_output.c
+++ b/drivers/gpu/drm/armada/armada_output.c
@@ -54,7 +54,8 @@ static void armada_drm_connector_destroy(struct drm_connector *conn)
}
static int armada_drm_connector_set_property(struct drm_connector *conn,
- struct drm_property *property, uint64_t value)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t value, void *blob_data)
{
struct armada_connector *dconn = drm_to_armada_conn(conn);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index c5b06fd..601ba9a 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -283,7 +283,8 @@ static void armada_plane_destroy(struct drm_plane *plane)
}
static int armada_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
struct armada_private *priv = plane->dev->dev_private;
struct armada_plane *dplane = drm_to_armada_plane(plane);
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 2ba39ac..cd81d68 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -215,6 +215,12 @@ static struct drm_driver driver = {
.dumb_map_offset = ast_dumb_mmap_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
};
static int __init ast_init(void)
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 5d6a875..0d21ff8 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -29,6 +29,7 @@
#define __AST_DRV_H__
#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/ttm/ttm_bo_api.h>
#include <drm/ttm/ttm_bo_driver.h>
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
index 08ce520..023db21 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -137,6 +137,12 @@ static struct drm_driver driver = {
.dumb_create = cirrus_dumb_create,
.dumb_map_offset = cirrus_dumb_mmap_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
};
static const struct dev_pm_ops cirrus_pm_ops = {
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 117d3ec..f929bc8 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -14,6 +14,7 @@
#include <video/vga.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/ttm/ttm_bo_api.h>
#include <drm/ttm/ttm_bo_driver.h>
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
new file mode 100644
index 0000000..560fe23
--- /dev/null
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+
+/**
+ * drm_atomic_begin - start a sequence of atomic updates
+ * @dev: DRM device
+ * @flags: the modifier flags that userspace has requested
+ *
+ * Begin a sequence of atomic property sets. Returns a driver
+ * private state object that is passed back into the various
+ * object's set_property() fxns, and into the remainder of the
+ * atomic funcs. The state object should accumulate the changes
+ * from one o more set_property()'s. At the end, the state can
+ * be checked, and optionally committed.
+ *
+ * RETURNS
+ * a driver state object, which is passed back in to the
+ * various other atomic fxns, or error (such as -EBUSY if
+ * there is still a pending async update)
+ */
+struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev,
+ uint32_t flags)
+{
+ struct drm_atomic_state *state;
+ uint32_t acquire_flags = 0;
+ int sz;
+ void *ptr;
+
+ sz = sizeof(*state);
+
+ ptr = kzalloc(sz, GFP_KERNEL);
+
+ state = ptr;
+ ptr = &state[1];
+
+ kref_init(&state->refcount);
+
+ if (flags & DRM_MODE_ATOMIC_NOLOCK)
+ acquire_flags |= DRM_MODESET_ACQUIRE_NOLOCK;
+ if (flags & DRM_MODE_ATOMIC_NONBLOCK)
+ acquire_flags |= DRM_MODESET_ACQUIRE_NONBLOCK;
+
+ drm_modeset_acquire_init(&state->acquire_ctx, acquire_flags);
+
+ state->dev = dev;
+ state->flags = flags;
+
+ return state;
+}
+EXPORT_SYMBOL(drm_atomic_begin);
+
+/**
+ * drm_atomic_set_event - set a pending event on mode object
+ * @dev: DRM device
+ * @state: the driver state object
+ * @obj: the object to set the event on
+ * @event: the event to send back
+ *
+ * Set pending event for an update on the specified object. The
+ * event is to be sent back to userspace after the update completes.
+ */
+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)
+{
+ return -EINVAL; /* for now */
+}
+EXPORT_SYMBOL(drm_atomic_set_event);
+
+/**
+ * drm_atomic_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * Check the state object to see if the requested state is
+ * physically possible.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int drm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
+{
+ struct drm_atomic_state *a = state;
+ a->acquire_ctx.frozen = true;
+ return 0; /* for now */
+}
+EXPORT_SYMBOL(drm_atomic_check);
+
+/* Note that we drop and re-acquire the locks w/ ww_mutex directly,
+ * since we keep the crtc in our list with in_atomic == true.
+ */
+
+static void drop_locks(struct drm_atomic_state *a,
+ struct ww_acquire_ctx *ww_ctx)
+{
+ struct drm_modeset_acquire_ctx *ctx = &a->acquire_ctx;
+ struct drm_modeset_lock *lock;
+
+ mutex_lock(&ctx->mutex);
+ list_for_each_entry(lock, &ctx->locked, head)
+ ww_mutex_unlock(&lock->mutex);
+ mutex_unlock(&ctx->mutex);
+
+ ww_acquire_fini(ww_ctx);
+}
+
+static void grab_locks(struct drm_atomic_state *a,
+ struct ww_acquire_ctx *ww_ctx)
+{
+ struct drm_modeset_acquire_ctx *ctx = &a->acquire_ctx;
+ struct drm_modeset_lock *lock, *slow_locked, *contended;
+ int ret;
+
+ lock = slow_locked = contended = NULL;
+
+
+ ww_acquire_init(ww_ctx, &crtc_ww_class);
+
+ /*
+ * We need to do proper rain^Hww dance.. another context
+ * could sneak in a grab the lock in order to check
+ * crtc->in_atomic, and we get -EDEADLK. But the winner
+ * will realize the mistake when it sees crtc->in_atomic
+ * already set, and then drop lock and return -EBUSY.
+ * So we just need to keep dancing until we win.
+ */
+retry:
+ ret = 0;
+ list_for_each_entry(lock, &ctx->locked, head) {
+ if (lock == slow_locked) {
+ slow_locked = NULL;
+ continue;
+ }
+ contended = lock;
+ ret = ww_mutex_lock(&lock->mutex, ww_ctx);
+ if (ret)
+ goto fail;
+ }
+
+fail:
+ if (ret == -EDEADLK) {
+ /* we lost out in a seqno race, backoff, lock and retry.. */
+
+ list_for_each_entry(lock, &ctx->locked, head) {
+ if (lock == contended)
+ break;
+ ww_mutex_unlock(&lock->mutex);
+ }
+
+ if (slow_locked)
+ ww_mutex_unlock(&slow_locked->mutex);
+
+ ww_mutex_lock_slow(&contended->mutex, ww_ctx);
+ slow_locked = contended;
+ goto retry;
+ }
+ WARN_ON(ret); /* if we get EALREADY then something is fubar */
+}
+
+static void commit_locks(struct drm_atomic_state *a,
+ struct ww_acquire_ctx *ww_ctx)
+{
+ /* and properly release them (clear in_atomic, remove from list): */
+ drm_modeset_drop_locks(&a->acquire_ctx);
+ ww_acquire_fini(ww_ctx);
+ a->committed = true;
+}
+
+static int atomic_commit(struct drm_atomic_state *a,
+ struct ww_acquire_ctx *ww_ctx)
+{
+ int ret = 0;
+
+ commit_locks(a, ww_ctx);
+
+ return ret;
+}
+
+/**
+ * drm_atomic_commit - commit state
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * Commit the state. This will only be called if atomic_check()
+ * succeeds.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int drm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *a)
+{
+ return atomic_commit(a, &a->acquire_ctx.ww_ctx);
+}
+EXPORT_SYMBOL(drm_atomic_commit);
+
+/**
+ * drm_atomic_commit_unlocked - like drm_atomic_commit
+ * but can be called back by driver in other thread. Manages the lock
+ * transfer from initiating thread.
+ */
+int drm_atomic_commit_unlocked(struct drm_device *dev,
+ struct drm_atomic_state *a)
+{
+ struct ww_acquire_ctx ww_ctx;
+ grab_locks(a, &ww_ctx);
+ return atomic_commit(a, &ww_ctx);
+}
+EXPORT_SYMBOL(drm_atomic_commit_unlocked);
+
+/**
+ * drm_atomic_end - conclude the atomic update
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * Release resources associated with the state object.
+ */
+void drm_atomic_end(struct drm_device *dev, struct drm_atomic_state *a)
+{
+ /* if commit is happening from another thread, it will
+ * block grabbing locks until we drop (and not set
+ * a->committed until after), so this is not a race:
+ */
+ if (!a->committed)
+ drop_locks(a, &a->acquire_ctx.ww_ctx);
+
+ drm_atomic_state_unreference(a);
+}
+EXPORT_SYMBOL(drm_atomic_end);
+
+void _drm_atomic_state_free(struct kref *kref)
+{
+ struct drm_atomic_state *a =
+ container_of(kref, struct drm_atomic_state, refcount);
+
+ /* in case we haven't already: */
+ if (!a->committed) {
+ grab_locks(a, &a->acquire_ctx.ww_ctx);
+ commit_locks(a, &a->acquire_ctx.ww_ctx);
+ }
+
+ __drm_modeset_acquire_fini(&a->acquire_ctx);
+
+ kfree(a);
+}
+EXPORT_SYMBOL(_drm_atomic_state_free);
+
+
+const struct drm_atomic_funcs drm_atomic_funcs = {
+};
+EXPORT_SYMBOL(drm_atomic_funcs);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 186bed4..a1bb8aa 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -38,6 +38,7 @@
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_modeset_lock.h>
+#include <drm/drm_atomic.h>
#include "drm_crtc_internal.h"
@@ -3833,20 +3834,21 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
}
-static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
- struct drm_property *property,
- uint64_t value)
+static int drm_mode_connector_set_obj_prop(struct drm_connector *connector,
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t value, void *blob_data)
{
int ret = -EINVAL;
- struct drm_connector *connector = obj_to_connector(obj);
/* Do DPMS ourselves */
if (property == connector->dev->mode_config.dpms_property) {
if (connector->funcs->dpms)
(*connector->funcs->dpms)(connector, (int)value);
ret = 0;
- } else if (connector->funcs->set_property)
- ret = connector->funcs->set_property(connector, property, value);
+ } else if (connector->funcs->set_property) {
+ ret = connector->funcs->set_property(connector, state,
+ property, value, blob_data);
+ }
/* store the property value if successful */
if (!ret)
@@ -3854,38 +3856,90 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
return ret;
}
-static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
- struct drm_property *property,
- uint64_t value)
+static int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc,
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t value, void *blob_data)
{
int ret = -EINVAL;
- struct drm_crtc *crtc = obj_to_crtc(obj);
if (crtc->funcs->set_property)
- ret = crtc->funcs->set_property(crtc, property, value);
+ ret = crtc->funcs->set_property(crtc, state, property,
+ value, blob_data);
if (!ret)
- drm_object_property_set_value(obj, property, value);
+ drm_object_property_set_value(&crtc->base, property, value);
return ret;
}
-static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
- struct drm_property *property,
- uint64_t value)
+static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t value, void *blob_data)
{
int ret = -EINVAL;
- struct drm_plane *plane = obj_to_plane(obj);
if (plane->funcs->set_property)
- ret = plane->funcs->set_property(plane, property, value);
+ ret = plane->funcs->set_property(plane, state, property,
+ value, blob_data);
if (!ret)
- drm_object_property_set_value(obj, property, value);
+ drm_object_property_set_value(&plane->base, property, value);
return ret;
}
+static int drm_mode_set_obj_prop(struct drm_device *dev,
+ struct drm_mode_object *obj, struct drm_atomic_state *state,
+ struct drm_property *property, uint64_t value, void *blob_data)
+{
+ if (drm_property_change_is_valid(property, value)) {
+ switch (obj->type) {
+ case DRM_MODE_OBJECT_CONNECTOR:
+ return drm_mode_connector_set_obj_prop(obj_to_connector(obj),
+ state, property, value, blob_data);
+ case DRM_MODE_OBJECT_CRTC:
+ return drm_mode_crtc_set_obj_prop(obj_to_crtc(obj),
+ state, property, value, blob_data);
+ case DRM_MODE_OBJECT_PLANE:
+ return drm_mode_plane_set_obj_prop(obj_to_plane(obj),
+ state, property, value, blob_data);
+ }
+ }
+
+ return -EINVAL;
+}
+
+/* call with mode_config mutex held */
+static int drm_mode_set_obj_prop_id(struct drm_device *dev,
+ struct drm_atomic_state *state,
+ uint32_t obj_id, uint32_t obj_type,
+ uint32_t prop_id, uint64_t value, void *blob_data)
+{
+ struct drm_mode_object *arg_obj;
+ struct drm_property *property;
+ int i;
+
+ arg_obj = drm_mode_object_find(dev, obj_id, obj_type);
+ if (!arg_obj)
+ return -ENOENT;
+ if (!arg_obj->properties)
+ return -EINVAL;
+
+ for (i = 0; i < arg_obj->properties->count; i++)
+ if (arg_obj->properties->ids[i] == prop_id)
+ break;
+
+ if (i == arg_obj->properties->count)
+ return -EINVAL;
+
+ property = drm_property_find(dev, prop_id);
+ if (!property)
+ return -ENOENT;
+
+ return drm_mode_set_obj_prop(dev, arg_obj, state, property,
+ value, blob_data);
+}
+
/**
- * drm_mode_getproperty_ioctl - get the current value of a object's property
+ * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
* @dev: DRM device
* @data: ioctl data
* @file_priv: DRM file info
@@ -3975,58 +4029,41 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_obj_set_property *arg = data;
- struct drm_mode_object *arg_obj;
- struct drm_mode_object *prop_obj;
- struct drm_property *property;
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_atomic_state *state;
int ret = -EINVAL;
- int i;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- drm_modeset_lock_all(dev);
+retry:
+ state = dev->driver->atomic_begin(dev, 0);
+ if (IS_ERR(state))
+ return PTR_ERR(state);
- arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
- if (!arg_obj) {
- ret = -ENOENT;
- goto out;
- }
- if (!arg_obj->properties)
+ ret = drm_modeset_lock(&config->connection_mutex, &state->acquire_ctx);
+ if (ret)
goto out;
-
- for (i = 0; i < arg_obj->properties->count; i++)
- if (arg_obj->properties->ids[i] == arg->prop_id)
- break;
-
- if (i == arg_obj->properties->count)
+ ret = drm_modeset_lock_all_crtcs(dev, &state->acquire_ctx);
+ if (ret)
goto out;
- prop_obj = drm_mode_object_find(dev, arg->prop_id,
- DRM_MODE_OBJECT_PROPERTY);
- if (!prop_obj) {
- ret = -ENOENT;
+ ret = drm_mode_set_obj_prop_id(dev, state,
+ arg->obj_id, arg->obj_type,
+ arg->prop_id, arg->value, NULL);
+ if (ret)
goto out;
- }
- property = obj_to_property(prop_obj);
- if (!drm_property_change_is_valid(property, arg->value))
+ ret = dev->driver->atomic_check(dev, state);
+ if (ret)
goto out;
- switch (arg_obj->type) {
- case DRM_MODE_OBJECT_CONNECTOR:
- ret = drm_mode_connector_set_obj_prop(arg_obj, property,
- arg->value);
- break;
- case DRM_MODE_OBJECT_CRTC:
- ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
- break;
- case DRM_MODE_OBJECT_PLANE:
- ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value);
- break;
- }
+ ret = dev->driver->atomic_commit(dev, state);
out:
- drm_modeset_unlock_all(dev);
+ dev->driver->atomic_end(dev, state);
+ if (ret == -EDEADLK)
+ goto retry;
return ret;
}
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index edd8508..38a846b 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -31,18 +31,29 @@ void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
{
ww_acquire_init(&ctx->ww_ctx, &crtc_ww_class);
INIT_LIST_HEAD(&ctx->locked);
+ mutex_init(&ctx->mutex);
+ ctx->nolock = !!(flags & DRM_MODESET_ACQUIRE_NOLOCK);
+ ctx->nonblock = !!(flags & DRM_MODESET_ACQUIRE_NONBLOCK);
}
EXPORT_SYMBOL(drm_modeset_acquire_init);
+/* special version for atomic.. which needs to ww_acquire_fini() itself */
+void __drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx)
+{
+ mutex_destroy(&ctx->mutex);
+}
+
void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx)
{
ww_acquire_fini(&ctx->ww_ctx);
+ __drm_modeset_acquire_fini(ctx);
}
EXPORT_SYMBOL(drm_modeset_acquire_fini);
void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx)
{
WARN_ON(ctx->contended);
+ mutex_lock(&ctx->mutex);
while (!list_empty(&ctx->locked)) {
struct drm_modeset_lock *lock;
@@ -51,6 +62,7 @@ void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx)
drm_modeset_unlock(lock);
}
+ mutex_unlock(&ctx->mutex);
}
EXPORT_SYMBOL(drm_modeset_drop_locks);
@@ -60,8 +72,13 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
{
int ret;
+ if (ctx->nolock)
+ return 0;
+
+ WARN_ON(ctx->frozen); /* all locks should be held by now! */
WARN_ON(ctx->contended);
+retry:
if (interruptible && slow) {
ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx);
} else if (interruptible) {
@@ -73,6 +90,15 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
ret = ww_mutex_lock(&lock->mutex, &ctx->ww_ctx);
}
if (!ret) {
+ if (lock->atomic_pending) {
+ /* some other pending update with dropped locks */
+ ww_mutex_unlock(&lock->mutex);
+ if (ctx->nonblock)
+ return -EBUSY;
+ wait_event(lock->event, !lock->atomic_pending);
+ goto retry;
+ }
+ lock->atomic_pending = true;
WARN_ON(!list_empty(&lock->head));
list_add(&lock->head, &ctx->locked);
} else if (ret == -EALREADY) {
@@ -154,7 +180,9 @@ EXPORT_SYMBOL(drm_modeset_lock_interruptible);
void drm_modeset_unlock(struct drm_modeset_lock *lock)
{
list_del_init(&lock->head);
+ lock->atomic_pending = false;
ww_mutex_unlock(&lock->mutex);
+ wake_up_all(&lock->event);
}
EXPORT_SYMBOL(drm_modeset_unlock);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 1ef5ab9..2a56973 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -281,8 +281,10 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
}
static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
struct drm_device *dev = crtc->dev;
struct exynos_drm_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 2d27ba2..318969d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -14,6 +14,7 @@
#include <linux/pm_runtime.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
#include <linux/anon_inodes.h>
@@ -341,6 +342,12 @@ static struct drm_driver exynos_drm_driver = {
.dumb_create = exynos_drm_gem_dumb_create,
.dumb_map_offset = exynos_drm_gem_dumb_map_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = exynos_dmabuf_prime_export,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 8371cbd..9da0935 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -212,8 +212,10 @@ static void exynos_plane_destroy(struct drm_plane *plane)
}
static int exynos_plane_set_property(struct drm_plane *plane,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
struct drm_device *dev = plane->dev;
struct exynos_plane *exynos_plane = to_exynos_plane(plane);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index c18268c..6d637d3 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -205,8 +205,10 @@ static int cdv_intel_crt_get_modes(struct drm_connector *connector)
}
static int cdv_intel_crt_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
return 0;
}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 9ff30c2..31d872d 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1645,8 +1645,10 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector)
static int
cdv_intel_dp_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
struct drm_psb_private *dev_priv = connector->dev->dev_private;
struct gma_encoder *encoder = gma_attached_encoder(connector);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index b99084b..f0e4d78 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -150,8 +150,10 @@ static enum drm_connector_status cdv_hdmi_detect(
}
static int cdv_hdmi_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
struct drm_encoder *encoder = connector->encoder;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 8ecc920..7ffaed4 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -452,8 +452,10 @@ static void cdv_intel_lvds_destroy(struct drm_connector *connector)
}
static int cdv_intel_lvds_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
struct drm_encoder *encoder = connector->encoder;
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 6e91b20..2318a46 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -243,8 +243,10 @@ mdfld_dsi_connector_detect(struct drm_connector *connector, bool force)
}
static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
struct drm_encoder *encoder = connector->encoder;
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 59ea45e..f342ae7 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -487,6 +487,13 @@ static struct drm_driver driver = {
.disable_vblank = psb_disable_vblank,
.get_vblank_counter = psb_get_vblank_counter,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
+
.gem_free_object = psb_gem_free_object,
.gem_vm_ops = &psb_gem_vm_ops,
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 55ebe2b..413ea37 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -25,6 +25,7 @@
#include <drm/drmP.h>
#include <drm/drm_global.h>
#include <drm/gma_drm.h>
+#include <drm/drm_atomic.h>
#include "psb_reg.h"
#include "psb_intel_drv.h"
#include "gma_display.h"
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
index 336bd3a..96e9759 100644
--- a/drivers/gpu/drm/gma500/psb_intel_drv.h
+++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
@@ -254,8 +254,10 @@ extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
extern int psb_intel_lvds_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode);
extern int psb_intel_lvds_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value);
+ uint64_t value,
+ void *blob_data);
extern void psb_intel_lvds_destroy(struct drm_connector *connector);
extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index d7778d0..6b64d9d 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -569,8 +569,10 @@ void psb_intel_lvds_destroy(struct drm_connector *connector)
}
int psb_intel_lvds_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
struct drm_encoder *encoder = connector->encoder;
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index deeb082..724b525 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1705,8 +1705,10 @@ static bool psb_intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)
static int
psb_intel_sdvo_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 284e748..a3d1291d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1119,6 +1119,14 @@ static struct drm_driver driver = {
.dumb_create = i915_gem_dumb_create,
.dumb_map_offset = i915_gem_mmap_gtt,
.dumb_destroy = drm_gem_dumb_destroy,
+
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
+
.ioctls = i915_ioctls,
.fops = &i915_driver_fops,
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 33328fc..0e52fc8 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -725,8 +725,10 @@ out:
}
static int intel_crt_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9926dc1..caa573c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3271,8 +3271,10 @@ intel_dp_detect_audio(struct drm_connector *connector)
static int
intel_dp_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct intel_connector *intel_connector = to_intel_connector(connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 824f8ae..8c838e4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -31,6 +31,7 @@
#include "i915_drv.h"
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_dp_helper.h>
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b606162..8e160b0 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1044,8 +1044,10 @@ intel_hdmi_detect_audio(struct drm_connector *connector)
static int
intel_hdmi_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
struct intel_digital_port *intel_dig_port =
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 1b1541d..4028237 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -486,8 +486,10 @@ static void intel_lvds_destroy(struct drm_connector *connector)
}
static int intel_lvds_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct drm_device *dev = connector->dev;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 2bf09e8..4e36ee99 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2052,8 +2052,10 @@ static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)
static int
intel_sdvo_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 97d9fc9..26dc38d 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1445,8 +1445,10 @@ intel_tv_destroy(struct drm_connector *connector)
static int
-intel_tv_set_property(struct drm_connector *connector, struct drm_property *property,
- uint64_t val)
+intel_tv_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
+ struct drm_property *property,
+ uint64_t val, void *blob_data)
{
struct drm_device *dev = connector->dev;
struct intel_tv *intel_tv = intel_attached_tv(connector);
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index f15ea3c..0425bdd 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -103,6 +103,13 @@ static struct drm_driver driver = {
.dumb_create = mgag200_dumb_create,
.dumb_map_offset = mgag200_dumb_mmap_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
};
static struct pci_driver mgag200_pci_driver = {
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index cf11ee6..c4d1600 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -16,6 +16,7 @@
#include <video/vga.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/ttm/ttm_bo_api.h>
#include <drm/ttm/ttm_bo_driver.h>
#include <drm/ttm/ttm_placement.h>
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index ef9957d..efa19c8 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -468,7 +468,8 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc,
}
static int mdp4_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
// XXX
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 66f33db..8c064dc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -85,7 +85,8 @@ void mdp4_plane_install_properties(struct drm_plane *plane,
}
int mdp4_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
// XXX
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 6ea10bd..ff48944 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -386,7 +386,8 @@ static int mdp5_crtc_page_flip(struct drm_crtc *crtc,
}
static int mdp5_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
// XXX
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 47f7bbb..5cbf226 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -100,7 +100,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane,
}
int mdp5_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
// XXX
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index afedd8b..36b9273 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -812,6 +812,12 @@ static struct drm_driver msm_driver = {
.gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
.gem_prime_vmap = msm_gem_prime_vmap,
.gem_prime_vunmap = msm_gem_prime_vunmap,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = msm_debugfs_init,
.debugfs_cleanup = msm_debugfs_cleanup,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 9d10ee0..afc990e 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -50,6 +50,7 @@ static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/msm_drm.h>
struct msm_kms;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index ab03f77..577e6aa 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -221,8 +221,9 @@ nv10_set_params(struct nouveau_plane *plane)
static int
nv_set_property(struct drm_plane *plane,
- struct drm_property *property,
- uint64_t value)
+ struct drm_atomic_state *state,
+ struct drm_property *property,
+ uint64_t value, void *blob_data)
{
struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index d07ce02..3351e72 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -447,7 +447,8 @@ nouveau_connector_force(struct drm_connector *connector)
static int
nouveau_connector_set_property(struct drm_connector *connector,
- struct drm_property *property, uint64_t value)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t value, void *blob_data)
{
struct nouveau_display *disp = nouveau_display(connector->dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index ddd8375..9a96d6d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -858,6 +858,13 @@ driver = {
.dumb_map_offset = nouveau_display_dumb_map_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
+
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
#ifdef GIT_REVISION
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 7efbafa..8941696 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -29,6 +29,7 @@
#include <subdev/vm.h>
#include <drmP.h>
+#include <drm/drm_atomic.h>
#include <drm/nouveau_drm.h>
#include <drm/ttm/ttm_bo_api.h>
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 2d28dc3..a75934d 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -382,7 +382,8 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
}
static int omap_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
struct omap_drm_private *priv = crtc->dev->dev_private;
@@ -392,7 +393,8 @@ static int omap_crtc_set_property(struct drm_crtc *crtc,
!!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270)));
}
- return omap_plane_set_property(omap_crtc->plane, property, val);
+ return omap_plane_set_property(omap_crtc->plane, state,
+ property, val, blob_data);
}
static const struct drm_crtc_funcs omap_crtc_funcs = {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 002b972..fe3983b 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -649,6 +649,12 @@ static struct drm_driver omap_drm_driver = {
.dumb_create = omap_gem_dumb_create,
.dumb_map_offset = omap_gem_dumb_map_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
.ioctls = ioctls,
.num_ioctls = DRM_OMAP_NUM_IOCTLS,
.fops = &omapdriver_fops,
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 284b80f..346fc8a 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -25,6 +25,7 @@
#include <linux/types.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/omap_drm.h>
#include <linux/platform_data/omap_drm.h>
@@ -178,7 +179,8 @@ int omap_plane_mode_set(struct drm_plane *plane,
void omap_plane_install_properties(struct drm_plane *plane,
struct drm_mode_object *obj);
int omap_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val);
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data);
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
struct omap_dss_device *dssdev);
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 3cf31ee..8ae5c49 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -336,7 +336,8 @@ void omap_plane_install_properties(struct drm_plane *plane,
}
int omap_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
struct omap_plane *omap_plane = to_omap_plane(plane);
struct omap_drm_private *priv = plane->dev->dev_private;
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 3ab9072..b54c970 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -819,8 +819,10 @@ static enum drm_connector_status qxl_conn_detect(
}
static int qxl_conn_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
DRM_DEBUG("\n");
return 0;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 6e93663..1984c2c 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -34,6 +34,7 @@
#include "drmP.h"
#include "drm/drm.h"
#include "drm_crtc_helper.h"
+#include "drm_atomic.h"
#include "qxl_drv.h"
#include "qxl_object.h"
@@ -220,6 +221,14 @@ static struct drm_driver qxl_driver = {
.dumb_create = qxl_mode_dumb_create,
.dumb_map_offset = qxl_mode_dumb_mmap,
.dumb_destroy = drm_gem_dumb_destroy,
+
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
+
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = qxl_debugfs_init,
.debugfs_cleanup = qxl_debugfs_takedown,
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index bcfe5d5..b0f75a7 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -360,8 +360,9 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn
}
}
-static int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property,
- uint64_t val)
+static int radeon_connector_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
struct drm_device *dev = connector->dev;
struct radeon_device *rdev = dev->dev_private;
@@ -683,8 +684,10 @@ static void radeon_connector_destroy(struct drm_connector *connector)
}
static int radeon_lvds_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
struct drm_device *dev = connector->dev;
struct radeon_encoder *radeon_encoder;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 15447a41..745791d 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -34,6 +34,7 @@
#include "radeon_drv.h"
#include <drm/drm_pciids.h>
+#include <drm/drm_atomic.h>
#include <linux/console.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@@ -545,6 +546,14 @@ static struct drm_driver kms_driver = {
.dumb_create = radeon_mode_dumb_create,
.dumb_map_offset = radeon_mode_dumb_mmap,
.dumb_destroy = drm_gem_dumb_destroy,
+
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
+
.fops = &radeon_driver_kms_fops,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 792fd1d..3f642a8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -21,6 +21,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
@@ -175,6 +176,12 @@ static struct drm_driver rcar_du_driver = {
.dumb_create = rcar_du_dumb_create,
.dumb_map_offset = drm_gem_cma_dumb_map_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
.fops = &rcar_du_fops,
.name = "rcar-du",
.desc = "Renesas R-Car Display Unit",
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 3fb69d9..3a5d843 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -397,8 +397,10 @@ done:
}
static int rcar_du_plane_set_property(struct drm_plane *plane,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t value)
+ uint64_t value,
+ void *blob_data)
{
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct rcar_du_group *rgrp = rplane->group;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
index 82c84c7..7474ffb 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -21,6 +21,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_gem_cma_helper.h>
#include "shmob_drm_crtc.h"
@@ -285,6 +286,12 @@ static struct drm_driver shmob_drm_driver = {
.dumb_create = drm_gem_cma_dumb_create,
.dumb_map_offset = drm_gem_cma_dumb_map_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
.fops = &shmob_drm_fops,
.name = "shmob-drm",
.desc = "Renesas SH Mobile DRM",
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index b20b694..3579b07 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -519,6 +519,12 @@ static struct drm_driver tilcdc_driver = {
.dumb_create = drm_gem_cma_dumb_create,
.dumb_map_offset = drm_gem_cma_dumb_map_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = tilcdc_debugfs_init,
.debugfs_cleanup = tilcdc_debugfs_cleanup,
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index 0938036..1280a65 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -31,6 +31,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h>
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
index 595068b..693f3ec 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
@@ -206,7 +206,8 @@ static struct drm_encoder *slave_connector_best_encoder(
}
static int slave_connector_set_property(struct drm_connector *connector,
- struct drm_property *property, uint64_t value)
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t value, void *blob_data)
{
struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
return get_slave_funcs(encoder)->set_property(encoder,
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index b44d548..936244d 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -115,9 +115,9 @@ udl_best_single_encoder(struct drm_connector *connector)
return encoder;
}
-static int udl_connector_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t val)
+static int udl_connector_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state, struct drm_property *property,
+ uint64_t val, void *blob_data)
{
return 0;
}
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index 3ddd6cd..52ade41 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <drm/drm_usb.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
#include "udl_drv.h"
static struct drm_driver driver;
@@ -88,6 +89,13 @@ static struct drm_driver driver = {
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import = udl_gem_prime_import,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
+
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 6bdd15e..3ec6792 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1433,6 +1433,13 @@ static struct drm_driver driver = {
.prime_fd_to_handle = vmw_prime_fd_to_handle,
.prime_handle_to_fd = vmw_prime_handle_to_fd,
+ .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,
+ .atomic_funcs = &drm_atomic_funcs,
+
.fops = &vmwgfx_driver_fops,
.name = VMWGFX_DRIVER_NAME,
.desc = VMWGFX_DRIVER_DESC,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 6b252a8..b0d6f3a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -30,6 +30,7 @@
#include "vmwgfx_reg.h"
#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
#include <drm/vmwgfx_drm.h>
#include <drm/drm_hashtab.h>
#include <linux/suspend.h>
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8f3edc4..c881ba1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -2007,8 +2007,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
}
int vmw_du_connector_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val)
+ uint64_t val,
+ void *blob_data)
{
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 8d038c3..6b02fdb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -141,8 +141,10 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force);
int vmw_du_connector_fill_modes(struct drm_connector *connector,
uint32_t max_width, uint32_t max_height);
int vmw_du_connector_set_property(struct drm_connector *connector,
+ struct drm_atomic_state *state,
struct drm_property *property,
- uint64_t val);
+ uint64_t val,
+ void *blob_data);
/*
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index a9b8a5d..5ac3587 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -948,6 +948,86 @@ struct drm_driver {
struct drm_device *dev,
uint32_t handle);
+ /*
+ * Atomic functions:
+ */
+
+ /**
+ * atomic_begin - start a sequence of atomic updates
+ * @dev: DRM device
+ * @flags: the modifier flags that userspace has requested
+ *
+ * Begin a sequence of atomic property sets. Returns a driver
+ * private state object that is passed back into the various
+ * object's set_property() fxns, and into the remainder of the
+ * atomic funcs. The state object should accumulate the changes
+ * from one o more set_property()'s. At the end, the state can
+ * be checked, and optionally committed.
+ *
+ * RETURNS
+ * a driver state object, which is passed back in to the
+ * various other atomic fxns, or error (such as -EBUSY if
+ * there is still a pending async update)
+ */
+ struct drm_atomic_state *(*atomic_begin)(struct drm_device *dev, uint32_t flags);
+
+ /**
+ * atomic_set_event - set a pending event on mode object
+ * @dev: DRM device
+ * @state: the driver state object
+ * @obj: the object to set the event on
+ * @event: the event to send back
+ *
+ * Set pending event for an update on the specified object. The
+ * event is to be sent back to userspace after the update completes.
+ */
+ int (*atomic_set_event)(struct drm_device *dev,
+ struct drm_atomic_state *state, struct drm_mode_object *obj,
+ struct drm_pending_vblank_event *event);
+
+ /**
+ * atomic_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * Check the state object to see if the requested state is
+ * physically possible.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+ int (*atomic_check)(struct drm_device *dev,
+ struct drm_atomic_state *state);
+
+ /**
+ * atomic_commit - commit state
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * Commit the state. This will only be called if atomic_check()
+ * succeeds.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+ int (*atomic_commit)(struct drm_device *dev,
+ struct drm_atomic_state *state);
+
+ /**
+ * atomic_end - conclude the atomic update
+ * @dev: DRM device
+ * @state: the driver state object
+
+ * Release resources associated with the state object.
+ */
+ void (*atomic_end)(struct drm_device *dev,
+ struct drm_atomic_state *state);
+
+ /**
+ * Funcs used by drm-atomic-helpers
+ */
+ const struct drm_atomic_funcs *atomic_funcs;
+
/* Driver private ops for this object */
const struct vm_operations_struct *gem_vm_ops;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
new file mode 100644
index 0000000..ff72b81
--- /dev/null
+++ b/include/drm/drm_atomic.h
@@ -0,0 +1,114 @@
+/*
+ * 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 dummy; /* for now */
+};
+
+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);
+
+/**
+ * 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;
+
+ 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_ */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3a3f7da..4963429 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -216,6 +216,8 @@ struct drm_encoder;
struct drm_pending_vblank_event;
struct drm_plane;
struct drm_bridge;
+struct drm_atomic_state;
+struct drm_atomic_funcs;
/**
* drm_crtc_funcs - control CRTCs for a given device
@@ -278,7 +280,9 @@ struct drm_crtc_funcs {
uint32_t flags);
int (*set_property)(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val);
+ struct drm_atomic_state *state,
+ struct drm_property *property, uint64_t val,
+ void *blob_data);
};
/**
@@ -392,8 +396,9 @@ struct drm_connector_funcs {
enum drm_connector_status (*detect)(struct drm_connector *connector,
bool force);
int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
- int (*set_property)(struct drm_connector *connector, struct drm_property *property,
- uint64_t val);
+ int (*set_property)(struct drm_connector *connector,
+ struct drm_atomic_state *state,
+ struct drm_property *property, uint64_t val, void *blob_data);
void (*destroy)(struct drm_connector *connector);
void (*force)(struct drm_connector *connector);
};
@@ -562,7 +567,9 @@ struct drm_plane_funcs {
void (*destroy)(struct drm_plane *plane);
int (*set_property)(struct drm_plane *plane,
- struct drm_property *property, uint64_t val);
+ struct drm_atomic_state *state,
+ struct drm_property *property, uint64_t val,
+ void *blob_data);
};
enum drm_plane_type {
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
index cfb1dc1..39560a4 100644
--- a/include/drm/drm_modeset_lock.h
+++ b/include/drm/drm_modeset_lock.h
@@ -32,6 +32,15 @@ struct drm_modeset_acquire_ctx {
struct ww_acquire_ctx ww_ctx;
+ bool nolock : 1;
+ bool nonblock : 1;
+
+ /* just for debugging, the context is 'frozen' in drm_atomic_check()
+ * to catch anyone who might be trying to acquire a lock after it is
+ * too late.
+ */
+ bool frozen : 1;
+
/* contended lock: if a lock is contended you should only call
* drm_modeset_backoff() which drops locks and slow-locks the
* contended lock.
@@ -40,6 +49,16 @@ struct drm_modeset_acquire_ctx {
/* list of 'struct drm_modeset_lock': */
struct list_head locked;
+
+ /* currently simply for protecting against 'locked' list manipulation
+ * between original thread calling atomic->end() and driver thread
+ * calling back drm_atomic_commit_unlocked().
+ *
+ * Other spots are sufficiently synchronized by virtue of holding
+ * the lock's ww_mutex. But during the lock/resource hand-over to the
+ * driver thread (drop_locks()/grab_locks()), we cannot rely on this.
+ */
+ struct mutex mutex;
};
/**
@@ -59,16 +78,37 @@ struct drm_modeset_lock {
struct ww_mutex mutex;
/**
+ * Are we busy (pending asynchronous/NONBLOCK update)? Any further
+ * asynchronous update will return -EBUSY if it also needs to acquire
+ * this lock. While a synchronous update will block until the pending
+ * async update completes.
+ *
+ * Drivers must ensure the update is completed before sending vblank
+ * event to userspace. Typically this just means don't send event
+ * before drm_atomic_commit_unlocked() returns.
+ */
+ bool atomic_pending;
+
+ /**
* Resources that are locked as part of an atomic update are added
* to a list (so we know what to unlock at the end).
*/
struct list_head head;
+
+ /**
+ * For waiting on atomic_pending locks, if not a NONBLOCK operation.
+ */
+ wait_queue_head_t event;
};
extern struct ww_class crtc_ww_class;
+#define DRM_MODESET_ACQUIRE_NOLOCK 0x0001
+#define DRM_MODESET_ACQUIRE_NONBLOCK 0x0002
+
void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
uint32_t flags);
+void __drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx);
void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx);
void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx);
void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx);
@@ -78,6 +118,7 @@ static inline void drm_modeset_lock_init(struct drm_modeset_lock *lock)
{
ww_mutex_init(&lock->mutex, &crtc_ww_class);
INIT_LIST_HEAD(&lock->head);
+ init_waitqueue_head(&lock->event);
}
static inline void drm_modeset_lock_fini(struct drm_modeset_lock *lock)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index ded505e..6421edc 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -511,4 +511,7 @@ struct drm_mode_destroy_dumb {
uint32_t handle;
};
+#define DRM_MODE_ATOMIC_NONBLOCK 0x0200
+#define DRM_MODE_ATOMIC_NOLOCK 0x8000 /* only used internally */
+
#endif
--
1.9.3
next prev parent reply other threads:[~2014-05-30 17:23 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-30 17:23 [PATCH 0/7] prepare for atomic/nuclear modeset/pageflip (vN+1) Rob Clark
2014-05-30 17:23 ` Rob Clark [this message]
2014-05-30 17:23 ` [PATCH 2/7] drm: split propvals out and blob property support Rob Clark
2014-05-30 17:23 ` [PATCH 3/7] drm: Refactor object property check code Rob Clark
2014-05-30 17:23 ` [PATCH 4/7] drm: convert plane to properties/state Rob Clark
2014-05-30 17:23 ` [PATCH 5/7] drm: convert crtc " Rob Clark
2014-05-30 17:23 ` [PATCH 6/7] drm/msm: add atomic support Rob Clark
2014-05-30 17:23 ` [PATCH 7/7] drm: Fix up the atomic legacy paths so they work Rob Clark
-- strict thread matches above, loose matches on Subject: below --
2014-07-23 19:38 [PATCH 0/7] prepare for atomic.. the great propertyification Rob Clark
2014-07-23 19:38 ` [PATCH 1/7] drm: add atomic fxns Rob Clark
2014-07-23 21:34 ` Daniel Vetter
2014-07-23 21:38 ` Daniel Vetter
2014-07-24 10:02 ` Thierry Reding
2014-07-24 18:31 ` "Stéphane Viau"
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1401470589-596-2-git-send-email-robdclark@gmail.com \
--to=robdclark@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.