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@xxxxxxxxx> + * + * 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@xxxxxxxxx> + * + * 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel