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).
---
 drivers/gpu/drm/Makefile                    |   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_helper.c         | 135 +++++++++++++++++++++++++++
 drivers/gpu/drm/drm_crtc.c                  | 139 ++++++++++++++++++----------
 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             |   5 +-
 drivers/gpu/drm/mgag200/mgag200_drv.c       |   7 ++
 drivers/gpu/drm/mgag200/mgag200_drv.h       |   1 +
 drivers/gpu/drm/msm/mdp4/mdp4_crtc.c        |   4 +-
 drivers/gpu/drm/msm/mdp4/mdp4_plane.c       |   4 +-
 drivers/gpu/drm/msm/msm_drv.c               |   6 ++
 drivers/gpu/drm/msm/msm_drv.h               |   1 +
 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         |   7 +-
 drivers/gpu/drm/omapdrm/omap_drv.c          |   6 ++
 drivers/gpu/drm/omapdrm/omap_drv.h          |   5 +-
 drivers/gpu/drm/omapdrm/omap_plane.c        |   4 +-
 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 +-
 drivers/gpu/host1x/drm/drm.c                |   7 ++
 drivers/gpu/host1x/drm/drm.h                |   1 +
 drivers/staging/imx-drm/imx-drm-core.c      |   8 ++
 include/drm/drmP.h                          |  77 +++++++++++++++
 include/drm/drm_atomic_helper.h             | 100 ++++++++++++++++++++
 include/drm/drm_crtc.h                      |  14 +--
 63 files changed, 634 insertions(+), 98 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_atomic_helper.c
 create mode 100644 include/drm/drm_atomic_helper.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f089adf..4e68e0d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -13,7 +13,8 @@ drm-y       :=        drm_auth.o drm_buffer.o drm_bufs.o 
drm_cache.o \
                drm_crtc.o drm_modes.o drm_edid.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_rect.o drm_vma_manager.o drm_flip_work.o \
+               drm_atomic_helper.o

 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 32e270d..d78edaf 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -217,6 +217,12 @@ static struct drm_driver driver = {
        .dumb_map_offset = ast_dumb_mmap_offset,
        .dumb_destroy = drm_gem_dumb_destroy,

+       .atomic_begin     = drm_atomic_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 8492b68..5dddca5 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_helper.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 138364d..e558d1a 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -102,6 +102,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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_funcs,
 };

 static struct pci_driver cirrus_pci_driver = {
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h 
b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 9b0bb91..7d363dc 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_helper.h>

 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
new file mode 100644
index 0000000..46c67b8
--- /dev/null
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+
+/**
+ * drm_atomic_helper_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 private 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)
+ */
+void *drm_atomic_helper_begin(struct drm_device *dev, uint32_t flags)
+{
+       struct drm_atomic_helper_state *state;
+       int sz;
+       void *ptr;
+
+       sz = sizeof(*state);
+
+       ptr = kzalloc(sz, GFP_KERNEL);
+
+       state = ptr;
+       ptr = &state[1];
+
+       kref_init(&state->refcount);
+       state->dev = dev;
+       state->flags = flags;
+       return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_begin);
+
+/**
+ * drm_atomic_helper_set_event - set a pending event on mode object
+ * @dev: DRM device
+ * @state: the driver private 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_helper_set_event(struct drm_device *dev,
+               void *state, struct drm_mode_object *obj,
+               struct drm_pending_vblank_event *event)
+{
+       return -EINVAL;  /* for now */
+}
+EXPORT_SYMBOL(drm_atomic_helper_set_event);
+
+/**
+ * drm_atomic_helper_check - validate state object
+ * @dev: DRM device
+ * @state: the driver private state object
+ *
+ * Check the state object to see if the requested state is
+ * physically possible.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int drm_atomic_helper_check(struct drm_device *dev, void *state)
+{
+       return 0;  /* for now */
+}
+EXPORT_SYMBOL(drm_atomic_helper_check);
+
+/**
+ * drm_atomic_helper_commit - commit state
+ * @dev: DRM device
+ * @state: the driver private state object
+ *
+ * Commit the state.  This will only be called if atomic_check()
+ * succeeds.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int drm_atomic_helper_commit(struct drm_device *dev, void *state)
+{
+       return 0;  /* for now */
+}
+EXPORT_SYMBOL(drm_atomic_helper_commit);
+
+/**
+ * drm_atomic_helper_end - conclude the atomic update
+ * @dev: DRM device
+ * @state: the driver private state object
+ *
+ * Release resources associated with the state object.
+ */
+void drm_atomic_helper_end(struct drm_device *dev, void *state)
+{
+       drm_atomic_helper_state_unreference(state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_end);
+
+void _drm_atomic_helper_state_free(struct kref *kref)
+{
+       struct drm_atomic_helper_state *state =
+               container_of(kref, struct drm_atomic_helper_state, refcount);
+       kfree(state);
+}
+EXPORT_SYMBOL(_drm_atomic_helper_state_free);
+
+
+const struct drm_atomic_helper_funcs drm_atomic_helper_funcs = {
+};
+EXPORT_SYMBOL(drm_atomic_helper_funcs);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index bff2fa9..f2a6d72 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3231,20 +3231,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,
+                                          void *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)
@@ -3252,36 +3253,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,
+                                     void *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,
+                                     void *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, void *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, void *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_mode_object *prop_obj;
+       struct drm_property *property;
+       int i;
+
+       arg_obj = drm_mode_object_find(dev, obj_id, obj_type);
+       if (!arg_obj)
+               return -EINVAL;
+       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;
+
+       prop_obj = drm_mode_object_find(dev, prop_id,
+                                       DRM_MODE_OBJECT_PROPERTY);
+       if (!prop_obj)
+               return -EINVAL;
+       property = obj_to_property(prop_obj);
+
+       return drm_mode_set_obj_prop(dev, arg_obj, state, property,
+                       value, blob_data);
+}
+
 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
                                      struct drm_file *file_priv)
 {
@@ -3342,53 +3397,35 @@ 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;
+       void *state;
        int ret = -EINVAL;
-       int i;

        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;

        drm_modeset_lock_all(dev);

-       arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
-       if (!arg_obj)
-               goto out;
-       if (!arg_obj->properties)
-               goto out;
-
-       for (i = 0; i < arg_obj->properties->count; i++)
-               if (arg_obj->properties->ids[i] == arg->prop_id)
-                       break;
+       state = dev->driver->atomic_begin(dev, 0);
+       if (IS_ERR(state)) {
+               ret = PTR_ERR(state);
+               goto out_unlock;
+       }

-       if (i == arg_obj->properties->count)
+       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;

-       prop_obj = drm_mode_object_find(dev, arg->prop_id,
-                                       DRM_MODE_OBJECT_PROPERTY);
-       if (!prop_obj)
-               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:
+       dev->driver->atomic_end(dev, state);
+out_unlock:
        drm_modeset_unlock_all(dev);
        return ret;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c 
b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index ebc0150..82a9fca 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -254,8 +254,10 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
 }

 static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,
+                                       void *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 bb82ef7..08285cb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -13,6 +13,7 @@

 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>

 #include <drm/exynos_drm.h>

@@ -270,6 +271,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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 fcb0652..2e31fb8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -217,8 +217,10 @@ static void exynos_plane_destroy(struct drm_plane *plane)
 }

 static int exynos_plane_set_property(struct drm_plane *plane,
+                                    void *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 661af49..d9c612f9 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -212,8 +212,10 @@ static int cdv_intel_crt_get_modes(struct drm_connector 
*connector)
 }

 static int cdv_intel_crt_set_property(struct drm_connector *connector,
+                                 void *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 f4eb435..5f1a734 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1644,8 +1644,10 @@ cdv_intel_dp_detect_audio(struct drm_connector 
*connector)

 static int
 cdv_intel_dp_set_property(struct drm_connector *connector,
+                     void *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 1c0d723..74e5de1 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -157,8 +157,10 @@ static enum drm_connector_status cdv_hdmi_detect(
 }

 static int cdv_hdmi_set_property(struct drm_connector *connector,
+                                      void *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 20e08e6..97d76c1 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,
+                                      void *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 860a4ee..76dadee 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,
+                               void *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 fcb4e9f..391057b 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -646,6 +646,13 @@ static struct drm_driver driver = {
        .preclose = psb_driver_preclose,
        .postclose = psb_driver_close,

+       .atomic_begin     = drm_atomic_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_funcs,
+
        .gem_init_object = psb_gem_init_object,
        .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 4535ac7..ef6a0609 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_helper.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 bde27fd..d8e1911 100644
--- a/drivers/gpu/drm/gma500/psb_intel_drv.h
+++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
@@ -261,8 +261,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,
+                                       void *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 32342f6..e3a3923 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,
+                                      void *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 6f01cdf..47e0a2a 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1688,8 +1688,10 @@ static bool psb_intel_sdvo_detect_hdmi_audio(struct 
drm_connector *connector)

 static int
 psb_intel_sdvo_set_property(struct drm_connector *connector,
+                       void *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 69d8ed5..a44be85 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -958,6 +958,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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 ea9022e..9a00797 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -676,8 +676,10 @@ static int intel_crt_get_modes(struct drm_connector 
*connector)
 }

 static int intel_crt_set_property(struct drm_connector *connector,
+                                 void *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 79c14e2..08d29fe 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2931,8 +2931,10 @@ intel_dp_detect_audio(struct drm_connector *connector)

 static int
 intel_dp_set_property(struct drm_connector *connector,
+                     void *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 28cae80..8556957 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_helper.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 4148cc8..dbc02ab 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -993,8 +993,10 @@ intel_hdmi_detect_audio(struct drm_connector *connector)

 static int
 intel_hdmi_set_property(struct drm_connector *connector,
+                       void *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 831a5c0..1eb7a97 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -472,8 +472,10 @@ static void intel_lvds_destroy(struct drm_connector 
*connector)
 }

 static int intel_lvds_set_property(struct drm_connector *connector,
+                                  void *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 49482fd..e863830 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2022,8 +2022,10 @@ static bool intel_sdvo_detect_hdmi_audio(struct 
drm_connector *connector)

 static int
 intel_sdvo_set_property(struct drm_connector *connector,
+                       void *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 dd6f84b..4ef1949 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1440,8 +1440,9 @@ 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, void *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 fcce7b2..2047479 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -104,6 +104,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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 baaae19..0b50f77 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_helper.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/mdp4/mdp4_crtc.c 
b/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
index 1d52896..d3fd7ca 100644
--- a/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
@@ -400,8 +400,8 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc,
        return msm_gem_queue_inactive_cb(obj, &mdp4_crtc->pageflip_cb);
 }

-static int mdp4_crtc_set_property(struct drm_crtc *crtc,
-               struct drm_property *property, uint64_t val)
+static int mdp4_crtc_set_property(struct drm_crtc *crtc, void *state,
+               struct drm_property *property, uint64_t val, void *blob_data)
 {
        // XXX
        return -EINVAL;
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_plane.c 
b/drivers/gpu/drm/msm/mdp4/mdp4_plane.c
index 0f0af24..880e96d 100644
--- a/drivers/gpu/drm/msm/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp4/mdp4_plane.c
@@ -84,8 +84,8 @@ void mdp4_plane_install_properties(struct drm_plane *plane,
        // XXX
 }

-int mdp4_plane_set_property(struct drm_plane *plane,
-               struct drm_property *property, uint64_t val)
+int mdp4_plane_set_property(struct drm_plane *plane, void *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 8653769..dadd55a 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -734,6 +734,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_helper_begin,
+       .atomic_set_event   = drm_atomic_helper_set_event,
+       .atomic_check       = drm_atomic_helper_check,
+       .atomic_commit      = drm_atomic_helper_commit,
+       .atomic_end         = drm_atomic_helper_end,
+       .atomic_helpers     = &drm_atomic_helper_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 d39f086..bfd4121 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -40,6 +40,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/msm_drm.h>

 struct msm_kms;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index c5b36f9..89ed23d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -445,7 +445,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)
+               void *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 e893c53..55b56e3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -843,6 +843,13 @@ driver = {
        .dumb_map_offset = nouveau_display_dumb_map_offset,
        .dumb_destroy = drm_gem_dumb_destroy,

+       .atomic_begin     = drm_atomic_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 994fd6e..44f2fc9 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_helper.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 0fd2eb1..5dd22ab 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -362,8 +362,8 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
        return 0;
 }

-static int omap_crtc_set_property(struct drm_crtc *crtc,
-               struct drm_property *property, uint64_t val)
+static int omap_crtc_set_property(struct drm_crtc *crtc, void *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;
@@ -373,7 +373,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 2603d90..2aaeda8 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -626,6 +626,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_helper_begin,
+               .atomic_set_event = drm_atomic_helper_set_event,
+               .atomic_check     = drm_atomic_helper_check,
+               .atomic_commit    = drm_atomic_helper_commit,
+               .atomic_end       = drm_atomic_helper_end,
+               .atomic_helpers   = &drm_atomic_helper_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 30b95b7..16983cc 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_helper.h>
 #include <drm/omap_drm.h>
 #include <linux/platform_data/omap_drm.h>

@@ -173,8 +174,8 @@ int omap_plane_mode_set(struct drm_plane *plane,
                void (*fxn)(void *), void *arg);
 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);
+int omap_plane_set_property(struct drm_plane *plane, void *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 046d5e6..fe32f1b 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -327,8 +327,8 @@ void omap_plane_install_properties(struct drm_plane *plane,
        drm_object_attach_property(obj, prop, 0);
 }

-int omap_plane_set_property(struct drm_plane *plane,
-               struct drm_property *property, uint64_t val)
+int omap_plane_set_property(struct drm_plane *plane, void *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 835caba..9f12205 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -799,8 +799,10 @@ static enum drm_connector_status qxl_conn_detect(
 }

 static int qxl_conn_set_property(struct drm_connector *connector,
+                                  void *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 514118a..65a93ed 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_helper.h"
 #include "qxl_drv.h"
 #include "qxl_object.h"

@@ -221,6 +222,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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 79159b5..1c64ce3 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -366,8 +366,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,
+               void *state, struct drm_property *property,
+               uint64_t val, void *blob_data)
 {
        struct drm_device *dev = connector->dev;
        struct radeon_device *rdev = dev->dev_private;
@@ -667,8 +668,10 @@ static void radeon_connector_destroy(struct drm_connector 
*connector)
 }

 static int radeon_lvds_set_property(struct drm_connector *connector,
+                                   void *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 cdd12dc..e8a3dda 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_helper.h>
 #include <linux/console.h>
 #include <linux/module.h>

@@ -415,6 +416,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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 0023f97..100ab8b 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_helper.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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 5300064..5691743 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -396,8 +396,10 @@ done:
 }

 static int rcar_du_plane_set_property(struct drm_plane *plane,
+                                     void *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 0155518..ab761ff 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_helper.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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 116da19..305b961 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_helper_begin,
+       .atomic_set_event   = drm_atomic_helper_set_event,
+       .atomic_check       = drm_atomic_helper_check,
+       .atomic_commit      = drm_atomic_helper_commit,
+       .atomic_end         = drm_atomic_helper_end,
+       .atomic_helpers     = &drm_atomic_helper_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..2f0c093 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_helper.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..48bcc26 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)
+               void *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..cd0c01a 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, 
+                              void *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 7650dc0..60e4672 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_helper.h>
 #include "udl_drv.h"

 static struct drm_driver driver;
@@ -89,6 +90,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_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 1a90f0a..54e060c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1138,6 +1138,13 @@ static struct drm_driver driver = {
        .dumb_map_offset = vmw_dumb_map_offset,
        .dumb_destroy = vmw_dumb_destroy,

+       .atomic_begin     = drm_atomic_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_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 150ec64..d930465 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_helper.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 fc43c06..a0f5dfb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1994,8 +1994,10 @@ int vmw_du_connector_fill_modes(struct drm_connector 
*connector,
 }

 int vmw_du_connector_set_property(struct drm_connector *connector,
+                                 void *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..e259d6c 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,
+                                 void *state,
                                  struct drm_property *property,
-                                 uint64_t val);
+                                 uint64_t val,
+                                 void *blob_data);


 /*
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index 8c61cee..f1c764c 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -634,6 +634,13 @@ struct drm_driver tegra_drm_driver = {
        .dumb_map_offset = tegra_bo_dumb_map_offset,
        .dumb_destroy = drm_gem_dumb_destroy,

+       .atomic_begin     = drm_atomic_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_funcs,
+
        .ioctls = tegra_drm_ioctls,
        .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
        .fops = &tegra_drm_fops,
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index 02ce020..ee5765c 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -12,6 +12,7 @@

 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fixed.h>
diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index a2e52a0..e3eeb34 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -19,6 +19,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include <linux/fb.h>
 #include <linux/module.h>
 #include <drm/drm_gem_cma_helper.h>
@@ -784,6 +785,13 @@ static struct drm_driver imx_drm_driver = {
        .dumb_map_offset        = drm_gem_cma_dumb_map_offset,
        .dumb_destroy           = drm_gem_dumb_destroy,

+       .atomic_begin     = drm_atomic_helper_begin,
+       .atomic_set_event = drm_atomic_helper_set_event,
+       .atomic_check     = drm_atomic_helper_check,
+       .atomic_commit    = drm_atomic_helper_commit,
+       .atomic_end       = drm_atomic_helper_end,
+       .atomic_helpers   = &drm_atomic_helper_funcs,
+
        .get_vblank_counter     = drm_vblank_count,
        .enable_vblank          = imx_drm_enable_vblank,
        .disable_vblank         = imx_drm_disable_vblank,
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index b46fb45..4c3de22 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -966,6 +966,83 @@ 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 private 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)
+        */
+       void *(*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 private 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,
+                       void *state, struct drm_mode_object *obj,
+                       struct drm_pending_vblank_event *event);
+
+       /**
+        * atomic_check - validate state object
+        * @dev: DRM device
+        * @state: the driver private 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, void *state);
+
+       /**
+        * atomic_commit - commit state
+        * @dev: DRM device
+        * @state: the driver private 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, void *state);
+
+       /**
+        * atomic_end - conclude the atomic update
+        * @dev: DRM device
+        * @state: the driver private state object
+
+        * Release resources associated with the state object.
+        */
+       void (*atomic_end)(struct drm_device *dev, void *state);
+
+       /**
+        * Helpers used by drm-atomic-helpers
+        */
+       const void *atomic_helpers;
+
        /* Driver private ops for this object */
        const struct vm_operations_struct *gem_vm_ops;

diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
new file mode 100644
index 0000000..e70cd7b
--- /dev/null
+++ b/include/drm/drm_atomic_helper.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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_helper_begin,
+ *     .atomic_set_event = drm_atomic_helper_set_event,
+ *     .atomic_check     = drm_atomic_helper_check,
+ *     .atomic_commit    = drm_atomic_helper_commit,
+ *     .atomic_end       = drm_atomic_helper_end,
+ *     .atomic_helpers   = &drm_atomic_helper_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_helper_{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_helper_check() with their own
+ * driver specific .atomic_check() function.
+ *
+ * A driver which can support true atomic updates can wrap
+ * drm_atomic_helper_commit().
+ *
+ * A driver with custom properties should override the appropriate get_state(),
+ * check_state(), and commit_state() functions in .atomic_helpers if it uses
+ * the drm-atomic-helpers.  Otherwise it is free to use 
&drm_atomic_helper_funcs
+ * as-is.
+ */
+
+/**
+ * struct drm_atomic_helper_funcs - helper funcs used by the atomic helpers
+ */
+struct drm_atomic_helper_funcs {
+       int dummy; /* for now */
+};
+
+const extern struct drm_atomic_helper_funcs drm_atomic_helper_funcs;
+
+void *drm_atomic_helper_begin(struct drm_device *dev, uint32_t flags);
+int drm_atomic_helper_set_event(struct drm_device *dev,
+               void *state, struct drm_mode_object *obj,
+               struct drm_pending_vblank_event *event);
+int drm_atomic_helper_check(struct drm_device *dev, void *state);
+int drm_atomic_helper_commit(struct drm_device *dev, void *state);
+void drm_atomic_helper_end(struct drm_device *dev, void *state);
+
+/**
+ * struct drm_atomic_helper_state - the state object used by atomic helpers
+ */
+struct drm_atomic_helper_state {
+       struct kref refcount;
+       struct drm_device *dev;
+       uint32_t flags;
+};
+
+static inline void
+drm_atomic_helper_state_reference(struct drm_atomic_helper_state *state)
+{
+       kref_get(&state->refcount);
+}
+
+static inline void
+drm_atomic_helper_state_unreference(struct drm_atomic_helper_state *state)
+{
+       void _drm_atomic_helper_state_free(struct kref *kref);
+       kref_put(&state->refcount, _drm_atomic_helper_state_free);
+}
+
+#endif /* DRM_ATOMIC_HELPER_H_ */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 24f4995..ad4e1ce 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -368,8 +368,9 @@ struct drm_crtc_funcs {
                         struct drm_pending_vblank_event *event,
                         uint32_t flags);

-       int (*set_property)(struct drm_crtc *crtc,
-                           struct drm_property *property, uint64_t val);
+       int (*set_property)(struct drm_crtc *crtc, void *state,
+                           struct drm_property *property, uint64_t val,
+                           void *blob_data);
 };

 /**
@@ -479,8 +480,8 @@ 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, void *state,
+                       struct drm_property *property, uint64_t val, void 
*blob_data);
        void (*destroy)(struct drm_connector *connector);
        void (*force)(struct drm_connector *connector);
 };
@@ -650,8 +651,9 @@ struct drm_plane_funcs {
        int (*disable_plane)(struct drm_plane *plane);
        void (*destroy)(struct drm_plane *plane);

-       int (*set_property)(struct drm_plane *plane,
-                           struct drm_property *property, uint64_t val);
+       int (*set_property)(struct drm_plane *plane, void *state,
+                           struct drm_property *property, uint64_t val,
+                           void *blob_data);
 };

 /**
-- 
1.8.3.1

Reply via email to