diff options
Diffstat (limited to 'drivers/gpu/drm/drm_mode_object.c')
-rw-r--r-- | drivers/gpu/drm/drm_mode_object.c | 159 |
1 files changed, 113 insertions, 46 deletions
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index da9a9adbcc98..1055533792f3 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -233,6 +233,9 @@ int drm_object_property_set_value(struct drm_mode_object *obj, { int i; + WARN_ON(drm_drv_uses_atomic_modeset(property->dev) && + !(property->flags & DRM_MODE_PROP_IMMUTABLE)); + for (i = 0; i < obj->properties->count; i++) { if (obj->properties->properties[i] == property) { obj->properties->values[i] = val; @@ -244,24 +247,7 @@ int drm_object_property_set_value(struct drm_mode_object *obj, } EXPORT_SYMBOL(drm_object_property_set_value); -/** - * drm_object_property_get_value - retrieve the value of a property - * @obj: drm mode object to get property value from - * @property: property to retrieve - * @val: storage for the property value - * - * This function retrieves the softare state of the given property for the given - * property. Since there is no driver callback to retrieve the current property - * value this might be out of sync with the hardware, depending upon the driver - * and property. - * - * Atomic drivers should never call this function directly, the core will read - * out property values through the various ->atomic_get_property callbacks. - * - * Returns: - * Zero on success, error code on failure. - */ -int drm_object_property_get_value(struct drm_mode_object *obj, +int __drm_object_property_get_value(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val) { int i; @@ -284,6 +270,31 @@ int drm_object_property_get_value(struct drm_mode_object *obj, return -EINVAL; } + +/** + * drm_object_property_get_value - retrieve the value of a property + * @obj: drm mode object to get property value from + * @property: property to retrieve + * @val: storage for the property value + * + * This function retrieves the softare state of the given property for the given + * property. Since there is no driver callback to retrieve the current property + * value this might be out of sync with the hardware, depending upon the driver + * and property. + * + * Atomic drivers should never call this function directly, the core will read + * out property values through the various ->atomic_get_property callbacks. + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_object_property_get_value(struct drm_mode_object *obj, + struct drm_property *property, uint64_t *val) +{ + WARN_ON(drm_drv_uses_atomic_modeset(property->dev)); + + return __drm_object_property_get_value(obj, property, val); +} EXPORT_SYMBOL(drm_object_property_get_value); /* helper for getconnector and getproperties ioctls */ @@ -302,7 +313,7 @@ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, continue; if (*arg_count_props > count) { - ret = drm_object_property_get_value(obj, prop, &val); + ret = __drm_object_property_get_value(obj, prop, &val); if (ret) return ret; @@ -381,6 +392,83 @@ struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj, return NULL; } +static int set_property_legacy(struct drm_mode_object *obj, + struct drm_property *prop, + uint64_t prop_value) +{ + struct drm_device *dev = prop->dev; + struct drm_mode_object *ref; + int ret = -EINVAL; + + if (!drm_property_change_valid_get(prop, prop_value, &ref)) + return -EINVAL; + + drm_modeset_lock_all(dev); + switch (obj->type) { + case DRM_MODE_OBJECT_CONNECTOR: + ret = drm_mode_connector_set_obj_prop(obj, prop, + prop_value); + break; + case DRM_MODE_OBJECT_CRTC: + ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value); + break; + case DRM_MODE_OBJECT_PLANE: + ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj), + prop, prop_value); + break; + } + drm_property_change_valid_put(prop, ref); + drm_modeset_unlock_all(dev); + + return ret; +} + +static int set_property_atomic(struct drm_mode_object *obj, + struct drm_property *prop, + uint64_t prop_value) +{ + struct drm_device *dev = prop->dev; + struct drm_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + int ret; + + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + state->acquire_ctx = &ctx; +retry: + if (prop == state->dev->mode_config.dpms_property) { + if (obj->type != DRM_MODE_OBJECT_CONNECTOR) { + ret = -EINVAL; + goto out; + } + + ret = drm_atomic_connector_commit_dpms(state, + obj_to_connector(obj), + prop_value); + } else { + ret = drm_atomic_set_property(state, obj, prop, prop_value); + if (ret) + goto out; + ret = drm_atomic_commit(state); + } +out: + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + goto retry; + } + + drm_atomic_state_put(state); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; +} + int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -388,18 +476,13 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, struct drm_mode_object *arg_obj; struct drm_property *property; int ret = -EINVAL; - struct drm_mode_object *ref; 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) { - ret = -ENOENT; - goto out; - } + if (!arg_obj) + return -ENOENT; if (!arg_obj->properties) goto out_unref; @@ -408,28 +491,12 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, if (!property) goto out_unref; - if (!drm_property_change_valid_get(property, arg->value, &ref)) - goto out_unref; - - 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(obj_to_plane(arg_obj), - property, arg->value); - break; - } - - drm_property_change_valid_put(property, ref); + if (drm_drv_uses_atomic_modeset(property->dev)) + ret = set_property_atomic(arg_obj, property, arg->value); + else + ret = set_property_legacy(arg_obj, property, arg->value); out_unref: drm_mode_object_put(arg_obj); -out: - drm_modeset_unlock_all(dev); return ret; } |