diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-28 17:49:53 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-28 17:49:53 -0700 |
commit | 53b3b6bbfde6aae8d1ededc86ad4e0e1e00eb5f8 (patch) | |
tree | b29473f21270aefd113b298c9402be8b4b3c91b4 /drivers/gpu/drm/drm_atomic.c | |
parent | 746bb4ed6d626f3f9e431a7f9b20504538e62ded (diff) | |
parent | f2bfc71aee75feff33ca659322b72ffeed5a243d (diff) |
Merge tag 'drm-next-2018-10-24' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"This is going to rebuild more than drm as it adds a new helper to
list.h for doing bulk updates. Seemed like a reasonable addition to
me.
Otherwise the usual merge window stuff lots of i915 and amdgpu, not so
much nouveau, and piles of everything else.
Core:
- Adds a new list.h helper for doing bulk list updates for TTM.
- Don't leak fb address in smem_start to userspace (comes with EXPORT
workaround for people using mali out of tree hacks)
- udmabuf device to turn memfd regions into dma-buf
- Per-plane blend mode property
- ref/unref replacements with get/put
- fbdev conflicting framebuffers code cleaned up
- host-endian format variants
- panel orientation quirk for Acer One 10
bridge:
- TI SN65DSI86 chip support
vkms:
- GEM support.
- Cursor support
amdgpu:
- Merge amdkfd and amdgpu into one module
- CEC over DP AUX support
- Picasso APU support + VCN dynamic powergating
- Raven2 APU support
- Vega20 enablement + kfd support
- ACP powergating improvements
- ABGR/XBGR display support
- VCN jpeg support
- xGMI support
- DC i2c/aux cleanup
- Ycbcr 4:2:0 support
- GPUVM improvements
- Powerplay and powerplay endian fixes
- Display underflow fixes
vmwgfx:
- Move vmwgfx specific TTM code to vmwgfx
- Split out vmwgfx buffer/resource validation code
- Atomic operation rework
bochs:
- use more helpers
- format/byteorder improvements
qxl:
- use more helpers
i915:
- GGTT coherency getparam
- Turn off resource streamer API
- More Icelake enablement + DMC firmware
- Full PPGTT for Ivybridge, Haswell and Valleyview
- DDB distribution based on resolution
- Limited range DP display support
nouveau:
- CEC over DP AUX support
- Initial HDMI 2.0 support
virtio-gpu:
- vmap support for PRIME objects
tegra:
- Initial Tegra194 support
- DMA/IOMMU integration fixes
msm:
- a6xx perf improvements + clock prefix
- GPU preemption optimisations
- a6xx devfreq support
- cursor support
rockchip:
- PX30 support
- rgb output interface support
mediatek:
- HDMI output support on mt2701 and mt7623
rcar-du:
- Interlaced modes on Gen3
- LVDS on R8A77980
- D3 and E3 SoC support
hisilicon:
- misc fixes
mxsfb:
- runtime pm support
sun4i:
- R40 TCON support
- Allwinner A64 support
- R40 HDMI support
omapdrm:
- Driver rework changing display pipeline ordering to use common code
- DMM memory barrier and irq fixes
- Errata workarounds
exynos:
- out-bridge support for LVDS bridge driver
- Samsung 16x16 tiled format support
- Plane alpha and pixel blend mode support
tilcdc:
- suspend/resume update
mali-dp:
- misc updates"
* tag 'drm-next-2018-10-24' of git://anongit.freedesktop.org/drm/drm: (1382 commits)
firmware/dmc/icl: Add missing MODULE_FIRMWARE() for Icelake.
drm/i915/icl: Fix signal_levels
drm/i915/icl: Fix DDI/TC port clk_off bits
drm/i915/icl: create function to identify combophy port
drm/i915/gen9+: Fix initial readout for Y tiled framebuffers
drm/i915: Large page offsets for pread/pwrite
drm/i915/selftests: Disable shrinker across mmap-exhaustion
drm/i915/dp: Link train Fallback on eDP only if fallback link BW can fit panel's native mode
drm/i915: Fix intel_dp_mst_best_encoder()
drm/i915: Skip vcpi allocation for MSTB ports that are gone
drm/i915: Don't unset intel_connector->mst_port
drm/i915: Only reset seqno if actually idle
drm/i915: Use the correct crtc when sanitizing plane mapping
drm/i915: Restore vblank interrupts earlier
drm/i915: Check fb stride against plane max stride
drm/amdgpu/vcn:Fix uninitialized symbol error
drm: panel-orientation-quirks: Add quirk for Acer One 10 (S1003)
drm/amd/amdgpu: Fix debugfs error handling
drm/amdgpu: Update gc_9_0 golden settings.
drm/amd/powerplay: update PPtable with DC BTC and Tvr SocLimit fields
...
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 1506 |
1 files changed, 2 insertions, 1504 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 281cf9cbb44c..3dbfbddae7e6 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -28,6 +28,7 @@ #include <drm/drmP.h> #include <drm/drm_atomic.h> +#include <drm/drm_atomic_uapi.h> #include <drm/drm_mode.h> #include <drm/drm_print.h> #include <drm/drm_writeback.h> @@ -314,350 +315,6 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_crtc_state); -static void set_out_fence_for_crtc(struct drm_atomic_state *state, - struct drm_crtc *crtc, s32 __user *fence_ptr) -{ - state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr; -} - -static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, - struct drm_crtc *crtc) -{ - s32 __user *fence_ptr; - - fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr; - state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL; - - return fence_ptr; -} - -static int set_out_fence_for_connector(struct drm_atomic_state *state, - struct drm_connector *connector, - s32 __user *fence_ptr) -{ - unsigned int index = drm_connector_index(connector); - - if (!fence_ptr) - return 0; - - if (put_user(-1, fence_ptr)) - return -EFAULT; - - state->connectors[index].out_fence_ptr = fence_ptr; - - return 0; -} - -static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state, - struct drm_connector *connector) -{ - unsigned int index = drm_connector_index(connector); - s32 __user *fence_ptr; - - fence_ptr = state->connectors[index].out_fence_ptr; - state->connectors[index].out_fence_ptr = NULL; - - return fence_ptr; -} - -/** - * drm_atomic_set_mode_for_crtc - set mode for CRTC - * @state: the CRTC whose incoming state to update - * @mode: kernel-internal mode to use for the CRTC, or NULL to disable - * - * Set a mode (originating from the kernel) on the desired CRTC state and update - * the enable property. - * - * RETURNS: - * Zero on success, error code on failure. Cannot return -EDEADLK. - */ -int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, - const struct drm_display_mode *mode) -{ - struct drm_crtc *crtc = state->crtc; - struct drm_mode_modeinfo umode; - - /* Early return for no change. */ - if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0) - return 0; - - drm_property_blob_put(state->mode_blob); - state->mode_blob = NULL; - - if (mode) { - drm_mode_convert_to_umode(&umode, mode); - state->mode_blob = - drm_property_create_blob(state->crtc->dev, - sizeof(umode), - &umode); - if (IS_ERR(state->mode_blob)) - return PTR_ERR(state->mode_blob); - - drm_mode_copy(&state->mode, mode); - state->enable = true; - DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n", - mode->name, crtc->base.id, crtc->name, state); - } else { - memset(&state->mode, 0, sizeof(state->mode)); - state->enable = false; - DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n", - crtc->base.id, crtc->name, state); - } - - return 0; -} -EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc); - -/** - * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC - * @state: the CRTC whose incoming state to update - * @blob: pointer to blob property to use for mode - * - * Set a mode (originating from a blob property) on the desired CRTC state. - * This function will take a reference on the blob property for the CRTC state, - * and release the reference held on the state's existing mode property, if any - * was set. - * - * RETURNS: - * Zero on success, error code on failure. Cannot return -EDEADLK. - */ -int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, - struct drm_property_blob *blob) -{ - struct drm_crtc *crtc = state->crtc; - - if (blob == state->mode_blob) - return 0; - - drm_property_blob_put(state->mode_blob); - state->mode_blob = NULL; - - memset(&state->mode, 0, sizeof(state->mode)); - - if (blob) { - int ret; - - if (blob->length != sizeof(struct drm_mode_modeinfo)) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n", - crtc->base.id, crtc->name, - blob->length); - return -EINVAL; - } - - ret = drm_mode_convert_umode(crtc->dev, - &state->mode, blob->data); - if (ret) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n", - crtc->base.id, crtc->name, - ret, drm_get_mode_status_name(state->mode.status)); - drm_mode_debug_printmodeline(&state->mode); - return -EINVAL; - } - - state->mode_blob = drm_property_blob_get(blob); - state->enable = true; - DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n", - state->mode.name, crtc->base.id, crtc->name, - state); - } else { - state->enable = false; - DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n", - crtc->base.id, crtc->name, state); - } - - return 0; -} -EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc); - -/** - * drm_atomic_replace_property_blob_from_id - lookup the new blob and replace the old one with it - * @dev: DRM device - * @blob: a pointer to the member blob to be replaced - * @blob_id: ID of the new blob - * @expected_size: total expected size of the blob data (in bytes) - * @expected_elem_size: expected element size of the blob data (in bytes) - * @replaced: did the blob get replaced? - * - * Replace @blob with another blob with the ID @blob_id. If @blob_id is zero - * @blob becomes NULL. - * - * If @expected_size is positive the new blob length is expected to be equal - * to @expected_size bytes. If @expected_elem_size is positive the new blob - * length is expected to be a multiple of @expected_elem_size bytes. Otherwise - * an error is returned. - * - * @replaced will indicate to the caller whether the blob was replaced or not. - * If the old and new blobs were in fact the same blob @replaced will be false - * otherwise it will be true. - * - * RETURNS: - * Zero on success, error code on failure. - */ -static int -drm_atomic_replace_property_blob_from_id(struct drm_device *dev, - struct drm_property_blob **blob, - uint64_t blob_id, - ssize_t expected_size, - ssize_t expected_elem_size, - bool *replaced) -{ - struct drm_property_blob *new_blob = NULL; - - if (blob_id != 0) { - new_blob = drm_property_lookup_blob(dev, blob_id); - if (new_blob == NULL) - return -EINVAL; - - if (expected_size > 0 && - new_blob->length != expected_size) { - drm_property_blob_put(new_blob); - return -EINVAL; - } - if (expected_elem_size > 0 && - new_blob->length % expected_elem_size != 0) { - drm_property_blob_put(new_blob); - return -EINVAL; - } - } - - *replaced |= drm_property_replace_blob(blob, new_blob); - drm_property_blob_put(new_blob); - - return 0; -} - -/** - * drm_atomic_crtc_set_property - set property on CRTC - * @crtc: the drm CRTC to set a property on - * @state: the state object to update with the new property value - * @property: the property to set - * @val: the new property value - * - * This function handles generic/core properties and calls out to driver's - * &drm_crtc_funcs.atomic_set_property for driver properties. To ensure - * consistent behavior you must call this function rather than the driver hook - * directly. - * - * RETURNS: - * Zero on success, error code on failure - */ -int drm_atomic_crtc_set_property(struct drm_crtc *crtc, - struct drm_crtc_state *state, struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = crtc->dev; - struct drm_mode_config *config = &dev->mode_config; - bool replaced = false; - int ret; - - if (property == config->prop_active) - state->active = val; - else if (property == config->prop_mode_id) { - struct drm_property_blob *mode = - drm_property_lookup_blob(dev, val); - ret = drm_atomic_set_mode_prop_for_crtc(state, mode); - drm_property_blob_put(mode); - return ret; - } else if (property == config->degamma_lut_property) { - ret = drm_atomic_replace_property_blob_from_id(dev, - &state->degamma_lut, - val, - -1, sizeof(struct drm_color_lut), - &replaced); - state->color_mgmt_changed |= replaced; - return ret; - } else if (property == config->ctm_property) { - ret = drm_atomic_replace_property_blob_from_id(dev, - &state->ctm, - val, - sizeof(struct drm_color_ctm), -1, - &replaced); - state->color_mgmt_changed |= replaced; - return ret; - } else if (property == config->gamma_lut_property) { - ret = drm_atomic_replace_property_blob_from_id(dev, - &state->gamma_lut, - val, - -1, sizeof(struct drm_color_lut), - &replaced); - state->color_mgmt_changed |= replaced; - return ret; - } else if (property == config->prop_out_fence_ptr) { - s32 __user *fence_ptr = u64_to_user_ptr(val); - - if (!fence_ptr) - return 0; - - if (put_user(-1, fence_ptr)) - return -EFAULT; - - set_out_fence_for_crtc(state->state, crtc, fence_ptr); - } else if (crtc->funcs->atomic_set_property) { - return crtc->funcs->atomic_set_property(crtc, state, property, val); - } else { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n", - crtc->base.id, crtc->name, - property->base.id, property->name); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL(drm_atomic_crtc_set_property); - -/** - * drm_atomic_crtc_get_property - get property value from CRTC state - * @crtc: the drm CRTC to set a property on - * @state: the state object to get the property value from - * @property: the property to set - * @val: return location for the property value - * - * This function handles generic/core properties and calls out to driver's - * &drm_crtc_funcs.atomic_get_property for driver properties. To ensure - * consistent behavior you must call this function rather than the driver hook - * directly. - * - * RETURNS: - * Zero on success, error code on failure - */ -static int -drm_atomic_crtc_get_property(struct drm_crtc *crtc, - const struct drm_crtc_state *state, - struct drm_property *property, uint64_t *val) -{ - struct drm_device *dev = crtc->dev; - struct drm_mode_config *config = &dev->mode_config; - - if (property == config->prop_active) - *val = state->active; - else if (property == config->prop_mode_id) - *val = (state->mode_blob) ? state->mode_blob->base.id : 0; - else if (property == config->degamma_lut_property) - *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; - else if (property == config->ctm_property) - *val = (state->ctm) ? state->ctm->base.id : 0; - else if (property == config->gamma_lut_property) - *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0; - else if (property == config->prop_out_fence_ptr) - *val = 0; - else if (crtc->funcs->atomic_get_property) - return crtc->funcs->atomic_get_property(crtc, state, property, val); - else - return -EINVAL; - - return 0; -} - -/** - * drm_atomic_crtc_check - check crtc state - * @crtc: crtc to check - * @state: crtc state to check - * - * Provides core sanity checks for crtc state. - * - * RETURNS: - * Zero on success, error code on failure - */ static int drm_atomic_crtc_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -733,16 +390,6 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p, crtc->funcs->atomic_print_state(p, state); } -/** - * drm_atomic_connector_check - check connector state - * @connector: connector to check - * @state: connector state to check - * - * Provides core sanity checks for connector state. - * - * RETURNS: - * Zero on success, error code on failure - */ static int drm_atomic_connector_check(struct drm_connector *connector, struct drm_connector_state *state) { @@ -841,155 +488,6 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_plane_state); -/** - * drm_atomic_plane_set_property - set property on plane - * @plane: the drm plane to set a property on - * @state: the state object to update with the new property value - * @property: the property to set - * @val: the new property value - * - * This function handles generic/core properties and calls out to driver's - * &drm_plane_funcs.atomic_set_property for driver properties. To ensure - * consistent behavior you must call this function rather than the driver hook - * directly. - * - * RETURNS: - * Zero on success, error code on failure - */ -static int drm_atomic_plane_set_property(struct drm_plane *plane, - struct drm_plane_state *state, struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = plane->dev; - struct drm_mode_config *config = &dev->mode_config; - - if (property == config->prop_fb_id) { - struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val); - drm_atomic_set_fb_for_plane(state, fb); - if (fb) - drm_framebuffer_put(fb); - } else if (property == config->prop_in_fence_fd) { - if (state->fence) - return -EINVAL; - - if (U642I64(val) == -1) - return 0; - - state->fence = sync_file_get_fence(val); - if (!state->fence) - return -EINVAL; - - } else if (property == config->prop_crtc_id) { - struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val); - return drm_atomic_set_crtc_for_plane(state, crtc); - } else if (property == config->prop_crtc_x) { - state->crtc_x = U642I64(val); - } else if (property == config->prop_crtc_y) { - state->crtc_y = U642I64(val); - } else if (property == config->prop_crtc_w) { - state->crtc_w = val; - } else if (property == config->prop_crtc_h) { - state->crtc_h = val; - } else if (property == config->prop_src_x) { - state->src_x = val; - } else if (property == config->prop_src_y) { - state->src_y = val; - } else if (property == config->prop_src_w) { - state->src_w = val; - } else if (property == config->prop_src_h) { - state->src_h = val; - } else if (property == plane->alpha_property) { - state->alpha = val; - } else if (property == plane->rotation_property) { - if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n", - plane->base.id, plane->name, val); - return -EINVAL; - } - state->rotation = val; - } else if (property == plane->zpos_property) { - state->zpos = val; - } else if (property == plane->color_encoding_property) { - state->color_encoding = val; - } else if (property == plane->color_range_property) { - state->color_range = val; - } else if (plane->funcs->atomic_set_property) { - return plane->funcs->atomic_set_property(plane, state, - property, val); - } else { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n", - plane->base.id, plane->name, - property->base.id, property->name); - return -EINVAL; - } - - return 0; -} - -/** - * drm_atomic_plane_get_property - get property value from plane state - * @plane: the drm plane to set a property on - * @state: the state object to get the property value from - * @property: the property to set - * @val: return location for the property value - * - * This function handles generic/core properties and calls out to driver's - * &drm_plane_funcs.atomic_get_property for driver properties. To ensure - * consistent behavior you must call this function rather than the driver hook - * directly. - * - * RETURNS: - * Zero on success, error code on failure - */ -static int -drm_atomic_plane_get_property(struct drm_plane *plane, - const struct drm_plane_state *state, - struct drm_property *property, uint64_t *val) -{ - struct drm_device *dev = plane->dev; - struct drm_mode_config *config = &dev->mode_config; - - if (property == config->prop_fb_id) { - *val = (state->fb) ? state->fb->base.id : 0; - } else if (property == config->prop_in_fence_fd) { - *val = -1; - } else if (property == config->prop_crtc_id) { - *val = (state->crtc) ? state->crtc->base.id : 0; - } else if (property == config->prop_crtc_x) { - *val = I642U64(state->crtc_x); - } else if (property == config->prop_crtc_y) { - *val = I642U64(state->crtc_y); - } else if (property == config->prop_crtc_w) { - *val = state->crtc_w; - } else if (property == config->prop_crtc_h) { - *val = state->crtc_h; - } else if (property == config->prop_src_x) { - *val = state->src_x; - } else if (property == config->prop_src_y) { - *val = state->src_y; - } else if (property == config->prop_src_w) { - *val = state->src_w; - } else if (property == config->prop_src_h) { - *val = state->src_h; - } else if (property == plane->alpha_property) { - *val = state->alpha; - } else if (property == plane->rotation_property) { - *val = state->rotation; - } else if (property == plane->zpos_property) { - *val = state->zpos; - } else if (property == plane->color_encoding_property) { - *val = state->color_encoding; - } else if (property == plane->color_range_property) { - *val = state->color_range; - } else if (plane->funcs->atomic_get_property) { - return plane->funcs->atomic_get_property(plane, state, property, val); - } else { - return -EINVAL; - } - - return 0; -} - static bool plane_switching_crtc(struct drm_atomic_state *state, struct drm_plane *plane, @@ -1329,111 +827,6 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_connector_state); -/** - * drm_atomic_connector_set_property - set property on connector. - * @connector: the drm connector to set a property on - * @state: the state object to update with the new property value - * @property: the property to set - * @val: the new property value - * - * This function handles generic/core properties and calls out to driver's - * &drm_connector_funcs.atomic_set_property for driver properties. To ensure - * consistent behavior you must call this function rather than the driver hook - * directly. - * - * RETURNS: - * Zero on success, error code on failure - */ -static int drm_atomic_connector_set_property(struct drm_connector *connector, - struct drm_connector_state *state, struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = connector->dev; - struct drm_mode_config *config = &dev->mode_config; - - if (property == config->prop_crtc_id) { - struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val); - return drm_atomic_set_crtc_for_connector(state, crtc); - } else if (property == config->dpms_property) { - /* setting DPMS property requires special handling, which - * is done in legacy setprop path for us. Disallow (for - * now?) atomic writes to DPMS property: - */ - return -EINVAL; - } else if (property == config->tv_select_subconnector_property) { - state->tv.subconnector = val; - } else if (property == config->tv_left_margin_property) { - state->tv.margins.left = val; - } else if (property == config->tv_right_margin_property) { - state->tv.margins.right = val; - } else if (property == config->tv_top_margin_property) { - state->tv.margins.top = val; - } else if (property == config->tv_bottom_margin_property) { - state->tv.margins.bottom = val; - } else if (property == config->tv_mode_property) { - state->tv.mode = val; - } else if (property == config->tv_brightness_property) { - state->tv.brightness = val; - } else if (property == config->tv_contrast_property) { - state->tv.contrast = val; - } else if (property == config->tv_flicker_reduction_property) { - state->tv.flicker_reduction = val; - } else if (property == config->tv_overscan_property) { - state->tv.overscan = val; - } else if (property == config->tv_saturation_property) { - state->tv.saturation = val; - } else if (property == config->tv_hue_property) { - state->tv.hue = val; - } else if (property == config->link_status_property) { - /* Never downgrade from GOOD to BAD on userspace's request here, - * only hw issues can do that. - * - * For an atomic property the userspace doesn't need to be able - * to understand all the properties, but needs to be able to - * restore the state it wants on VT switch. So if the userspace - * tries to change the link_status from GOOD to BAD, driver - * silently rejects it and returns a 0. This prevents userspace - * from accidently breaking the display when it restores the - * state. - */ - if (state->link_status != DRM_LINK_STATUS_GOOD) - state->link_status = val; - } else if (property == config->aspect_ratio_property) { - state->picture_aspect_ratio = val; - } else if (property == config->content_type_property) { - state->content_type = val; - } else if (property == connector->scaling_mode_property) { - state->scaling_mode = val; - } else if (property == connector->content_protection_property) { - if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) { - DRM_DEBUG_KMS("only drivers can set CP Enabled\n"); - return -EINVAL; - } - state->content_protection = val; - } else if (property == config->writeback_fb_id_property) { - struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val); - int ret = drm_atomic_set_writeback_fb_for_connector(state, fb); - if (fb) - drm_framebuffer_put(fb); - return ret; - } else if (property == config->writeback_out_fence_ptr_property) { - s32 __user *fence_ptr = u64_to_user_ptr(val); - - return set_out_fence_for_connector(state->state, connector, - fence_ptr); - } else if (connector->funcs->atomic_set_property) { - return connector->funcs->atomic_set_property(connector, - state, property, val); - } else { - DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n", - connector->base.id, connector->name, - property->base.id, property->name); - return -EINVAL; - } - - return 0; -} - static void drm_atomic_connector_print_state(struct drm_printer *p, const struct drm_connector_state *state) { @@ -1451,360 +844,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, } /** - * drm_atomic_connector_get_property - get property value from connector state - * @connector: the drm connector to set a property on - * @state: the state object to get the property value from - * @property: the property to set - * @val: return location for the property value - * - * This function handles generic/core properties and calls out to driver's - * &drm_connector_funcs.atomic_get_property for driver properties. To ensure - * consistent behavior you must call this function rather than the driver hook - * directly. - * - * RETURNS: - * Zero on success, error code on failure - */ -static int -drm_atomic_connector_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, uint64_t *val) -{ - struct drm_device *dev = connector->dev; - struct drm_mode_config *config = &dev->mode_config; - - if (property == config->prop_crtc_id) { - *val = (state->crtc) ? state->crtc->base.id : 0; - } else if (property == config->dpms_property) { - *val = connector->dpms; - } else if (property == config->tv_select_subconnector_property) { - *val = state->tv.subconnector; - } else if (property == config->tv_left_margin_property) { - *val = state->tv.margins.left; - } else if (property == config->tv_right_margin_property) { - *val = state->tv.margins.right; - } else if (property == config->tv_top_margin_property) { - *val = state->tv.margins.top; - } else if (property == config->tv_bottom_margin_property) { - *val = state->tv.margins.bottom; - } else if (property == config->tv_mode_property) { - *val = state->tv.mode; - } else if (property == config->tv_brightness_property) { - *val = state->tv.brightness; - } else if (property == config->tv_contrast_property) { - *val = state->tv.contrast; - } else if (property == config->tv_flicker_reduction_property) { - *val = state->tv.flicker_reduction; - } else if (property == config->tv_overscan_property) { - *val = state->tv.overscan; - } else if (property == config->tv_saturation_property) { - *val = state->tv.saturation; - } else if (property == config->tv_hue_property) { - *val = state->tv.hue; - } else if (property == config->link_status_property) { - *val = state->link_status; - } else if (property == config->aspect_ratio_property) { - *val = state->picture_aspect_ratio; - } else if (property == config->content_type_property) { - *val = state->content_type; - } else if (property == connector->scaling_mode_property) { - *val = state->scaling_mode; - } else if (property == connector->content_protection_property) { - *val = state->content_protection; - } else if (property == config->writeback_fb_id_property) { - /* Writeback framebuffer is one-shot, write and forget */ - *val = 0; - } else if (property == config->writeback_out_fence_ptr_property) { - *val = 0; - } else if (connector->funcs->atomic_get_property) { - return connector->funcs->atomic_get_property(connector, - state, property, val); - } else { - return -EINVAL; - } - - return 0; -} - -int drm_atomic_get_property(struct drm_mode_object *obj, - struct drm_property *property, uint64_t *val) -{ - struct drm_device *dev = property->dev; - int ret; - - switch (obj->type) { - case DRM_MODE_OBJECT_CONNECTOR: { - struct drm_connector *connector = obj_to_connector(obj); - WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); - ret = drm_atomic_connector_get_property(connector, - connector->state, property, val); - break; - } - case DRM_MODE_OBJECT_CRTC: { - struct drm_crtc *crtc = obj_to_crtc(obj); - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); - ret = drm_atomic_crtc_get_property(crtc, - crtc->state, property, val); - break; - } - case DRM_MODE_OBJECT_PLANE: { - struct drm_plane *plane = obj_to_plane(obj); - WARN_ON(!drm_modeset_is_locked(&plane->mutex)); - ret = drm_atomic_plane_get_property(plane, - plane->state, property, val); - break; - } - default: - ret = -EINVAL; - break; - } - - return ret; -} - -/** - * drm_atomic_set_crtc_for_plane - set crtc for plane - * @plane_state: the plane whose incoming state to update - * @crtc: crtc to use for the plane - * - * Changing the assigned crtc for a plane requires us to grab the lock and state - * for the new crtc, as needed. This function takes care of all these details - * besides updating the pointer in the state object itself. - * - * Returns: - * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK - * then the w/w mutex code has detected a deadlock and the entire atomic - * sequence must be restarted. All other errors are fatal. - */ -int -drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, - struct drm_crtc *crtc) -{ - struct drm_plane *plane = plane_state->plane; - struct drm_crtc_state *crtc_state; - /* Nothing to do for same crtc*/ - if (plane_state->crtc == crtc) - return 0; - if (plane_state->crtc) { - crtc_state = drm_atomic_get_crtc_state(plane_state->state, - plane_state->crtc); - if (WARN_ON(IS_ERR(crtc_state))) - return PTR_ERR(crtc_state); - - crtc_state->plane_mask &= ~drm_plane_mask(plane); - } - - plane_state->crtc = crtc; - - if (crtc) { - crtc_state = drm_atomic_get_crtc_state(plane_state->state, - crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - crtc_state->plane_mask |= drm_plane_mask(plane); - } - - if (crtc) - DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n", - plane->base.id, plane->name, plane_state, - crtc->base.id, crtc->name); - else - DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n", - plane->base.id, plane->name, plane_state); - - return 0; -} -EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane); - -/** - * drm_atomic_set_fb_for_plane - set framebuffer for plane - * @plane_state: atomic state object for the plane - * @fb: fb to use for the plane - * - * Changing the assigned framebuffer for a plane requires us to grab a reference - * to the new fb and drop the reference to the old fb, if there is one. This - * function takes care of all these details besides updating the pointer in the - * state object itself. - */ -void -drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, - struct drm_framebuffer *fb) -{ - struct drm_plane *plane = plane_state->plane; - - if (fb) - DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n", - fb->base.id, plane->base.id, plane->name, - plane_state); - else - DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n", - plane->base.id, plane->name, plane_state); - - drm_framebuffer_assign(&plane_state->fb, fb); -} -EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); - -/** - * drm_atomic_set_fence_for_plane - set fence for plane - * @plane_state: atomic state object for the plane - * @fence: dma_fence to use for the plane - * - * Helper to setup the plane_state fence in case it is not set yet. - * By using this drivers doesn't need to worry if the user choose - * implicit or explicit fencing. - * - * This function will not set the fence to the state if it was set - * via explicit fencing interfaces on the atomic ioctl. In that case it will - * drop the reference to the fence as we are not storing it anywhere. - * Otherwise, if &drm_plane_state.fence is not set this function we just set it - * with the received implicit fence. In both cases this function consumes a - * reference for @fence. - * - * This way explicit fencing can be used to overrule implicit fencing, which is - * important to make explicit fencing use-cases work: One example is using one - * buffer for 2 screens with different refresh rates. Implicit fencing will - * clamp rendering to the refresh rate of the slower screen, whereas explicit - * fence allows 2 independent render and display loops on a single buffer. If a - * driver allows obeys both implicit and explicit fences for plane updates, then - * it will break all the benefits of explicit fencing. - */ -void -drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, - struct dma_fence *fence) -{ - if (plane_state->fence) { - dma_fence_put(fence); - return; - } - - plane_state->fence = fence; -} -EXPORT_SYMBOL(drm_atomic_set_fence_for_plane); - -/** - * drm_atomic_set_crtc_for_connector - set crtc for connector - * @conn_state: atomic state object for the connector - * @crtc: crtc to use for the connector - * - * Changing the assigned crtc for a connector requires us to grab the lock and - * state for the new crtc, as needed. This function takes care of all these - * details besides updating the pointer in the state object itself. - * - * Returns: - * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK - * then the w/w mutex code has detected a deadlock and the entire atomic - * sequence must be restarted. All other errors are fatal. - */ -int -drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, - struct drm_crtc *crtc) -{ - struct drm_connector *connector = conn_state->connector; - struct drm_crtc_state *crtc_state; - - if (conn_state->crtc == crtc) - return 0; - - if (conn_state->crtc) { - crtc_state = drm_atomic_get_new_crtc_state(conn_state->state, - conn_state->crtc); - - crtc_state->connector_mask &= - ~drm_connector_mask(conn_state->connector); - - drm_connector_put(conn_state->connector); - conn_state->crtc = NULL; - } - - if (crtc) { - crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - - crtc_state->connector_mask |= - drm_connector_mask(conn_state->connector); - - drm_connector_get(conn_state->connector); - conn_state->crtc = crtc; - - DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n", - connector->base.id, connector->name, - conn_state, crtc->base.id, crtc->name); - } else { - DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n", - connector->base.id, connector->name, - conn_state); |