diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-04 03:02:26 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-04 03:02:26 +0300 |
commit | 906dde0f355bd97c080c215811ae7db1137c4af8 (patch) | |
tree | 1e1b4ba58a59c4027f06d86e7430566ee0dcbb15 /drivers/gpu/drm/drm_atomic.c | |
parent | 69c0067aa3f40d3e52ab78643aecb17d669d3389 (diff) | |
parent | 7846b12fe0b5feab5446d892f41b5140c1419109 (diff) | |
download | linux-906dde0f355bd97c080c215811ae7db1137c4af8.tar.xz |
Merge tag 'drm-for-v4.14' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull request for 4.14 merge window.
I'm sending this early, as my continuing journey into fatherhood is
occurring really soon now, I'm going to be mostly useless for the next
couple of weeks, though I may be able to read email, I doubt I'll be
doing much patch applications or git sending. If anything urgent pops
up I've asked Daniel/Jani/Alex/Sean to try and direct stuff towards
you.
Outside drm changes:
Some rcar-du updates that touch the V4L tree, all acks should be in
place. It adds one export to the radix tree code for new i915 use
case. There are some minor AGP cleanups (don't see that too often).
Changes to the vbox driver in staging to avoid breaking compilation.
Summary:
core:
- Atomic helper fixes
- Atomic UAPI fixes
- Add YCBCR 4:2:0 support
- Drop set_busid hook
- Refactor fb_helper locking
- Remove a bunch of internal APIs
- Add a bunch of better default handlers
- Format modifier/blob plane property added
- More internal header refactoring
- Make more internal API names consistent
- Enhanced syncobj APIs (wait/signal/reset/create signalled)
bridge:
- Add Synopsys Designware MIPI DSI host bridge driver
tiny:
- Add Pervasive Displays RePaper displays
- Add support for LEGO MINDSTORMS EV3 LCD
i915:
- Lots of GEN10/CNL support patches
- drm syncobj support
- Skylake+ watermark refactoring
- GVT vGPU 48-bit ppgtt support
- GVT performance improvements
- NOA change ioctl
- CCS (color compression) scanout support
- GPU reset improvements
amdgpu:
- Initial hugepage support
- BO migration logic rework
- Vega10 improvements
- Powerplay fixes
- Stop reprogramming the MC
- Fixes for ACP audio on stoney
- SR-IOV fixes/improvements
- Command submission overhead improvements
amdkfd:
- Non-dGPU upstreaming patches
- Scratch VA ioctl
- Image tiling modes
- Update PM4 headers for new firmware
- Drop all BUG_ONs.
nouveau:
- GP108 modesetting support.
- Disable MSI on big endian.
vmwgfx:
- Add fence fd support.
msm:
- Runtime PM improvements
exynos:
- NV12MT support
- Refactor KMS drivers
imx-drm:
- Lock scanout channel to improve memory bw
- Cleanups
etnaviv:
- GEM object population fixes
tegra:
- Prep work for Tegra186 support
- PRIME mmap support
sunxi:
- HDMI support improvements
- HDMI CEC support
omapdrm:
- HDMI hotplug IRQ support
- Big driver cleanup
- OMAP5 DSI support
rcar-du:
- vblank fixes
- VSP1 updates
arcgpu:
- Minor fixes
stm:
- Add STM32 DSI controller driver
dw_hdmi:
- Add support for Rockchip RK3399
- HDMI CEC support
atmel-hlcdc:
- Add 8-bit color support
vc4:
- Atomic fixes
- New ioctl to attach a label to a buffer object
- HDMI CEC support
- Allow userspace to dictate rendering order on submit ioctl"
* tag 'drm-for-v4.14' of git://people.freedesktop.org/~airlied/linux: (1074 commits)
drm/syncobj: Add a signal ioctl (v3)
drm/syncobj: Add a reset ioctl (v3)
drm/syncobj: Add a syncobj_array_find helper
drm/syncobj: Allow wait for submit and signal behavior (v5)
drm/syncobj: Add a CREATE_SIGNALED flag
drm/syncobj: Add a callback mechanism for replace_fence (v3)
drm/syncobj: add sync obj wait interface. (v8)
i915: Use drm_syncobj_fence_get
drm/syncobj: Add a race-free drm_syncobj_fence_get helper (v2)
drm/syncobj: Rename fence_get to find_fence
drm: kirin: Add mode_valid logic to avoid mode clocks we can't generate
drm/vmwgfx: Bump the version for fence FD support
drm/vmwgfx: Add export fence to file descriptor support
drm/vmwgfx: Add support for imported Fence File Descriptor
drm/vmwgfx: Prepare to support fence fd
drm/vmwgfx: Fix incorrect command header offset at restart
drm/vmwgfx: Support the NOP_ERROR command
drm/vmwgfx: Restart command buffers after errors
drm/vmwgfx: Move irq bottom half processing to threads
drm/vmwgfx: Don't use drm_irq_[un]install
...
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 219 |
1 files changed, 128 insertions, 91 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index aed25c4183bb..2fd383d7253a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -29,7 +29,6 @@ #include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_mode.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <linux/sync_file.h> @@ -188,12 +187,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) } for (i = 0; i < state->num_private_objs; i++) { - void *obj_state = state->private_objs[i].obj_state; + struct drm_private_obj *obj = state->private_objs[i].ptr; - state->private_objs[i].funcs->destroy_state(obj_state); - state->private_objs[i].obj = NULL; - state->private_objs[i].obj_state = NULL; - state->private_objs[i].funcs = NULL; + if (!obj) + continue; + + obj->funcs->atomic_destroy_state(obj, + state->private_objs[i].state); + state->private_objs[i].ptr = NULL; + state->private_objs[i].state = NULL; } state->num_private_objs = 0; @@ -409,34 +411,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, } EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc); -/** - * drm_atomic_replace_property_blob - replace a blob property - * @blob: a pointer to the member blob to be replaced - * @new_blob: the new blob to replace with - * @replaced: whether the blob has been replaced - * - * RETURNS: - * Zero on success, error code on failure - */ -static void -drm_atomic_replace_property_blob(struct drm_property_blob **blob, - struct drm_property_blob *new_blob, - bool *replaced) -{ - struct drm_property_blob *old_blob = *blob; - - if (old_blob == new_blob) - return; - - drm_property_blob_put(old_blob); - if (new_blob) - drm_property_blob_get(new_blob); - *blob = new_blob; - *replaced = true; - - return; -} - static int drm_atomic_replace_property_blob_from_id(struct drm_device *dev, struct drm_property_blob **blob, @@ -457,7 +431,7 @@ drm_atomic_replace_property_blob_from_id(struct drm_device *dev, } } - drm_atomic_replace_property_blob(blob, new_blob, replaced); + *replaced |= drm_property_replace_blob(blob, new_blob); drm_property_blob_put(new_blob); return 0; @@ -739,7 +713,7 @@ EXPORT_SYMBOL(drm_atomic_get_plane_state); * RETURNS: * Zero on success, error code on failure */ -int drm_atomic_plane_set_property(struct drm_plane *plane, +static int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val) { @@ -796,7 +770,6 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, return 0; } -EXPORT_SYMBOL(drm_atomic_plane_set_property); /** * drm_atomic_plane_get_property - get property value from plane state @@ -991,11 +964,44 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, } /** + * drm_atomic_private_obj_init - initialize private object + * @obj: private object + * @state: initial private object state + * @funcs: pointer to the struct of function pointers that identify the object + * type + * + * Initialize the private object, which can be embedded into any + * driver private object that needs its own atomic state. + */ +void +drm_atomic_private_obj_init(struct drm_private_obj *obj, + struct drm_private_state *state, + const struct drm_private_state_funcs *funcs) +{ + memset(obj, 0, sizeof(*obj)); + + obj->state = state; + obj->funcs = funcs; +} +EXPORT_SYMBOL(drm_atomic_private_obj_init); + +/** + * drm_atomic_private_obj_fini - finalize private object + * @obj: private object + * + * Finalize the private object. + */ +void +drm_atomic_private_obj_fini(struct drm_private_obj *obj) +{ + obj->funcs->atomic_destroy_state(obj, obj->state); +} +EXPORT_SYMBOL(drm_atomic_private_obj_fini); + +/** * drm_atomic_get_private_obj_state - get private object state * @state: global atomic state * @obj: private object to get the state for - * @funcs: pointer to the struct of function pointers that identify the object - * type * * This function returns the private object state for the given private object, * allocating the state if needed. It does not grab any locks as the caller is @@ -1005,18 +1011,18 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, * * Either the allocated state or the error code encoded into a pointer. */ -void * -drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, - const struct drm_private_state_funcs *funcs) +struct drm_private_state * +drm_atomic_get_private_obj_state(struct drm_atomic_state *state, + struct drm_private_obj *obj) { int index, num_objs, i; size_t size; struct __drm_private_objs_state *arr; + struct drm_private_state *obj_state; for (i = 0; i < state->num_private_objs; i++) - if (obj == state->private_objs[i].obj && - state->private_objs[i].obj_state) - return state->private_objs[i].obj_state; + if (obj == state->private_objs[i].ptr) + return state->private_objs[i].state; num_objs = state->num_private_objs + 1; size = sizeof(*state->private_objs) * num_objs; @@ -1028,18 +1034,21 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, index = state->num_private_objs; memset(&state->private_objs[index], 0, sizeof(*state->private_objs)); - state->private_objs[index].obj_state = funcs->duplicate_state(state, obj); - if (!state->private_objs[index].obj_state) + obj_state = obj->funcs->atomic_duplicate_state(obj); + if (!obj_state) return ERR_PTR(-ENOMEM); - state->private_objs[index].obj = obj; - state->private_objs[index].funcs = funcs; + state->private_objs[index].state = obj_state; + state->private_objs[index].old_state = obj->state; + state->private_objs[index].new_state = obj_state; + state->private_objs[index].ptr = obj; + state->num_private_objs = num_objs; - DRM_DEBUG_ATOMIC("Added new private object state %p to %p\n", - state->private_objs[index].obj_state, state); + DRM_DEBUG_ATOMIC("Added new private object %p state %p to %p\n", + obj, obj_state, state); - return state->private_objs[index].obj_state; + return obj_state; } EXPORT_SYMBOL(drm_atomic_get_private_obj_state); @@ -1135,7 +1144,7 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state); * RETURNS: * Zero on success, error code on failure */ -int drm_atomic_connector_set_property(struct drm_connector *connector, +static int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val) { @@ -1202,7 +1211,6 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, return 0; } -EXPORT_SYMBOL(drm_atomic_connector_set_property); static void drm_atomic_connector_print_state(struct drm_printer *p, const struct drm_connector_state *state) @@ -1580,38 +1588,6 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state, EXPORT_SYMBOL(drm_atomic_add_affected_planes); /** - * drm_atomic_legacy_backoff - locking backoff for legacy ioctls - * @state: atomic state - * - * This function should be used by legacy entry points which don't understand - * -EDEADLK semantics. For simplicity this one will grab all modeset locks after - * the slowpath completed. - */ -void drm_atomic_legacy_backoff(struct drm_atomic_state *state) -{ - struct drm_device *dev = state->dev; - int ret; - bool global = false; - - if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) { - global = true; - - dev->mode_config.acquire_ctx = NULL; - } - -retry: - drm_modeset_backoff(state->acquire_ctx); - - ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); - if (ret) - goto retry; - - if (global) - dev->mode_config.acquire_ctx = state->acquire_ctx; -} -EXPORT_SYMBOL(drm_atomic_legacy_backoff); - -/** * drm_atomic_check_only - check whether a given config would work * @state: atomic configuration to check * @@ -1857,9 +1833,60 @@ static struct drm_pending_vblank_event *create_vblank_event( return e; } -static int atomic_set_prop(struct drm_atomic_state *state, - struct drm_mode_object *obj, struct drm_property *prop, - uint64_t prop_value) +int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, + struct drm_connector *connector, + int mode) +{ + struct drm_connector *tmp_connector; + struct drm_connector_state *new_conn_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i, ret, old_mode = connector->dpms; + bool active = false; + + ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex, + state->acquire_ctx); + if (ret) + return ret; + + if (mode != DRM_MODE_DPMS_ON) + mode = DRM_MODE_DPMS_OFF; + connector->dpms = mode; + + crtc = connector->state->crtc; + if (!crtc) + goto out; + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + goto out; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto out; + } + + for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) { + if (new_conn_state->crtc != crtc) + continue; + if (tmp_connector->dpms == DRM_MODE_DPMS_ON) { + active = true; + break; + } + } + + crtc_state->active = active; + ret = drm_atomic_commit(state); +out: + if (ret != 0) + connector->dpms = old_mode; + return ret; +} + +int drm_atomic_set_property(struct drm_atomic_state *state, + struct drm_mode_object *obj, + struct drm_property *prop, + uint64_t prop_value) { struct drm_mode_object *ref; int ret; @@ -2042,7 +2069,7 @@ static int prepare_crtc_signaling(struct drm_device *dev, { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; - int i, ret; + int i, c = 0, ret; if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) return 0; @@ -2103,8 +2130,17 @@ static int prepare_crtc_signaling(struct drm_device *dev, crtc_state->event->base.fence = fence; } + + c++; } + /* + * Having this flag means user mode pends on event which will never + * reach due to lack of at least one CRTC for signaling + */ + if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) + return -EINVAL; + return 0; } @@ -2272,7 +2308,8 @@ retry: goto out; } - ret = atomic_set_prop(state, obj, prop, prop_value); + ret = drm_atomic_set_property(state, obj, prop, + prop_value); if (ret) { drm_mode_object_put(obj); goto out; |