Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2016 Intel Corporation
0003  *
0004  * Permission to use, copy, modify, distribute, and sell this software and its
0005  * documentation for any purpose is hereby granted without fee, provided that
0006  * the above copyright notice appear in all copies and that both that copyright
0007  * notice and this permission notice appear in supporting documentation, and
0008  * that the name of the copyright holders not be used in advertising or
0009  * publicity pertaining to distribution of the software without specific,
0010  * written prior permission.  The copyright holders make no representations
0011  * about the suitability of this software for any purpose.  It is provided "as
0012  * is" without express or implied warranty.
0013  *
0014  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0015  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
0016  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0017  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
0018  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
0019  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
0020  * OF THIS SOFTWARE.
0021  */
0022 
0023 #include <linux/export.h>
0024 #include <linux/uaccess.h>
0025 
0026 #include <drm/drm_atomic.h>
0027 #include <drm/drm_drv.h>
0028 #include <drm/drm_device.h>
0029 #include <drm/drm_file.h>
0030 #include <drm/drm_mode_object.h>
0031 #include <drm/drm_print.h>
0032 
0033 #include "drm_crtc_internal.h"
0034 
0035 /*
0036  * Internal function to assign a slot in the object idr and optionally
0037  * register the object into the idr.
0038  */
0039 int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
0040               uint32_t obj_type, bool register_obj,
0041               void (*obj_free_cb)(struct kref *kref))
0042 {
0043     int ret;
0044 
0045     WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
0046 
0047     mutex_lock(&dev->mode_config.idr_mutex);
0048     ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL,
0049             1, 0, GFP_KERNEL);
0050     if (ret >= 0) {
0051         /*
0052          * Set up the object linking under the protection of the idr
0053          * lock so that other users can't see inconsistent state.
0054          */
0055         obj->id = ret;
0056         obj->type = obj_type;
0057         if (obj_free_cb) {
0058             obj->free_cb = obj_free_cb;
0059             kref_init(&obj->refcount);
0060         }
0061     }
0062     mutex_unlock(&dev->mode_config.idr_mutex);
0063 
0064     return ret < 0 ? ret : 0;
0065 }
0066 
0067 /**
0068  * drm_mode_object_add - allocate a new modeset identifier
0069  * @dev: DRM device
0070  * @obj: object pointer, used to generate unique ID
0071  * @obj_type: object type
0072  *
0073  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
0074  * for tracking modes, CRTCs and connectors.
0075  *
0076  * Returns:
0077  * Zero on success, error code on failure.
0078  */
0079 int drm_mode_object_add(struct drm_device *dev,
0080             struct drm_mode_object *obj, uint32_t obj_type)
0081 {
0082     return __drm_mode_object_add(dev, obj, obj_type, true, NULL);
0083 }
0084 
0085 void drm_mode_object_register(struct drm_device *dev,
0086                   struct drm_mode_object *obj)
0087 {
0088     mutex_lock(&dev->mode_config.idr_mutex);
0089     idr_replace(&dev->mode_config.object_idr, obj, obj->id);
0090     mutex_unlock(&dev->mode_config.idr_mutex);
0091 }
0092 
0093 /**
0094  * drm_mode_object_unregister - free a modeset identifier
0095  * @dev: DRM device
0096  * @object: object to free
0097  *
0098  * Free @id from @dev's unique identifier pool.
0099  * This function can be called multiple times, and guards against
0100  * multiple removals.
0101  * These modeset identifiers are _not_ reference counted. Hence don't use this
0102  * for reference counted modeset objects like framebuffers.
0103  */
0104 void drm_mode_object_unregister(struct drm_device *dev,
0105                 struct drm_mode_object *object)
0106 {
0107     WARN_ON(!dev->driver->load && dev->registered && !object->free_cb);
0108 
0109     mutex_lock(&dev->mode_config.idr_mutex);
0110     if (object->id) {
0111         idr_remove(&dev->mode_config.object_idr, object->id);
0112         object->id = 0;
0113     }
0114     mutex_unlock(&dev->mode_config.idr_mutex);
0115 }
0116 
0117 /**
0118  * drm_mode_object_lease_required - check types which must be leased to be used
0119  * @type: type of object
0120  *
0121  * Returns whether the provided type of drm_mode_object must
0122  * be owned or leased to be used by a process.
0123  */
0124 bool drm_mode_object_lease_required(uint32_t type)
0125 {
0126     switch(type) {
0127     case DRM_MODE_OBJECT_CRTC:
0128     case DRM_MODE_OBJECT_CONNECTOR:
0129     case DRM_MODE_OBJECT_PLANE:
0130         return true;
0131     default:
0132         return false;
0133     }
0134 }
0135 
0136 struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
0137                            struct drm_file *file_priv,
0138                            uint32_t id, uint32_t type)
0139 {
0140     struct drm_mode_object *obj = NULL;
0141 
0142     mutex_lock(&dev->mode_config.idr_mutex);
0143     obj = idr_find(&dev->mode_config.object_idr, id);
0144     if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
0145         obj = NULL;
0146     if (obj && obj->id != id)
0147         obj = NULL;
0148 
0149     if (obj && drm_mode_object_lease_required(obj->type) &&
0150         !_drm_lease_held(file_priv, obj->id))
0151         obj = NULL;
0152 
0153     if (obj && obj->free_cb) {
0154         if (!kref_get_unless_zero(&obj->refcount))
0155             obj = NULL;
0156     }
0157     mutex_unlock(&dev->mode_config.idr_mutex);
0158 
0159     return obj;
0160 }
0161 
0162 /**
0163  * drm_mode_object_find - look up a drm object with static lifetime
0164  * @dev: drm device
0165  * @file_priv: drm file
0166  * @id: id of the mode object
0167  * @type: type of the mode object
0168  *
0169  * This function is used to look up a modeset object. It will acquire a
0170  * reference for reference counted objects. This reference must be dropped again
0171  * by callind drm_mode_object_put().
0172  */
0173 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
0174         struct drm_file *file_priv,
0175         uint32_t id, uint32_t type)
0176 {
0177     struct drm_mode_object *obj = NULL;
0178 
0179     obj = __drm_mode_object_find(dev, file_priv, id, type);
0180     return obj;
0181 }
0182 EXPORT_SYMBOL(drm_mode_object_find);
0183 
0184 /**
0185  * drm_mode_object_put - release a mode object reference
0186  * @obj: DRM mode object
0187  *
0188  * This function decrements the object's refcount if it is a refcounted modeset
0189  * object. It is a no-op on any other object. This is used to drop references
0190  * acquired with drm_mode_object_get().
0191  */
0192 void drm_mode_object_put(struct drm_mode_object *obj)
0193 {
0194     if (obj->free_cb) {
0195         DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
0196         kref_put(&obj->refcount, obj->free_cb);
0197     }
0198 }
0199 EXPORT_SYMBOL(drm_mode_object_put);
0200 
0201 /**
0202  * drm_mode_object_get - acquire a mode object reference
0203  * @obj: DRM mode object
0204  *
0205  * This function increments the object's refcount if it is a refcounted modeset
0206  * object. It is a no-op on any other object. References should be dropped again
0207  * by calling drm_mode_object_put().
0208  */
0209 void drm_mode_object_get(struct drm_mode_object *obj)
0210 {
0211     if (obj->free_cb) {
0212         DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
0213         kref_get(&obj->refcount);
0214     }
0215 }
0216 EXPORT_SYMBOL(drm_mode_object_get);
0217 
0218 /**
0219  * drm_object_attach_property - attach a property to a modeset object
0220  * @obj: drm modeset object
0221  * @property: property to attach
0222  * @init_val: initial value of the property
0223  *
0224  * This attaches the given property to the modeset object with the given initial
0225  * value. Currently this function cannot fail since the properties are stored in
0226  * a statically sized array.
0227  *
0228  * Note that all properties must be attached before the object itself is
0229  * registered and accessible from userspace.
0230  */
0231 void drm_object_attach_property(struct drm_mode_object *obj,
0232                 struct drm_property *property,
0233                 uint64_t init_val)
0234 {
0235     int count = obj->properties->count;
0236     struct drm_device *dev = property->dev;
0237 
0238 
0239     if (obj->type == DRM_MODE_OBJECT_CONNECTOR) {
0240         struct drm_connector *connector = obj_to_connector(obj);
0241 
0242         WARN_ON(!dev->driver->load &&
0243             connector->registration_state == DRM_CONNECTOR_REGISTERED);
0244     } else {
0245         WARN_ON(!dev->driver->load && dev->registered);
0246     }
0247 
0248     if (count == DRM_OBJECT_MAX_PROPERTY) {
0249         WARN(1, "Failed to attach object property (type: 0x%x). Please "
0250             "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
0251             "you see this message on the same object type.\n",
0252             obj->type);
0253         return;
0254     }
0255 
0256     obj->properties->properties[count] = property;
0257     obj->properties->values[count] = init_val;
0258     obj->properties->count++;
0259 }
0260 EXPORT_SYMBOL(drm_object_attach_property);
0261 
0262 /**
0263  * drm_object_property_set_value - set the value of a property
0264  * @obj: drm mode object to set property value for
0265  * @property: property to set
0266  * @val: value the property should be set to
0267  *
0268  * This function sets a given property on a given object. This function only
0269  * changes the software state of the property, it does not call into the
0270  * driver's ->set_property callback.
0271  *
0272  * Note that atomic drivers should not have any need to call this, the core will
0273  * ensure consistency of values reported back to userspace through the
0274  * appropriate ->atomic_get_property callback. Only legacy drivers should call
0275  * this function to update the tracked value (after clamping and other
0276  * restrictions have been applied).
0277  *
0278  * Returns:
0279  * Zero on success, error code on failure.
0280  */
0281 int drm_object_property_set_value(struct drm_mode_object *obj,
0282                   struct drm_property *property, uint64_t val)
0283 {
0284     int i;
0285 
0286     WARN_ON(drm_drv_uses_atomic_modeset(property->dev) &&
0287         !(property->flags & DRM_MODE_PROP_IMMUTABLE));
0288 
0289     for (i = 0; i < obj->properties->count; i++) {
0290         if (obj->properties->properties[i] == property) {
0291             obj->properties->values[i] = val;
0292             return 0;
0293         }
0294     }
0295 
0296     return -EINVAL;
0297 }
0298 EXPORT_SYMBOL(drm_object_property_set_value);
0299 
0300 static int __drm_object_property_get_prop_value(struct drm_mode_object *obj,
0301                         struct drm_property *property,
0302                         uint64_t *val)
0303 {
0304     int i;
0305 
0306     for (i = 0; i < obj->properties->count; i++) {
0307         if (obj->properties->properties[i] == property) {
0308             *val = obj->properties->values[i];
0309             return 0;
0310         }
0311     }
0312 
0313     return -EINVAL;
0314 }
0315 
0316 static int __drm_object_property_get_value(struct drm_mode_object *obj,
0317                        struct drm_property *property,
0318                        uint64_t *val)
0319 {
0320 
0321     /* read-only properties bypass atomic mechanism and still store
0322      * their value in obj->properties->values[].. mostly to avoid
0323      * having to deal w/ EDID and similar props in atomic paths:
0324      */
0325     if (drm_drv_uses_atomic_modeset(property->dev) &&
0326             !(property->flags & DRM_MODE_PROP_IMMUTABLE))
0327         return drm_atomic_get_property(obj, property, val);
0328 
0329     return __drm_object_property_get_prop_value(obj, property, val);
0330 }
0331 
0332 /**
0333  * drm_object_property_get_value - retrieve the value of a property
0334  * @obj: drm mode object to get property value from
0335  * @property: property to retrieve
0336  * @val: storage for the property value
0337  *
0338  * This function retrieves the softare state of the given property for the given
0339  * property. Since there is no driver callback to retrieve the current property
0340  * value this might be out of sync with the hardware, depending upon the driver
0341  * and property.
0342  *
0343  * Atomic drivers should never call this function directly, the core will read
0344  * out property values through the various ->atomic_get_property callbacks.
0345  *
0346  * Returns:
0347  * Zero on success, error code on failure.
0348  */
0349 int drm_object_property_get_value(struct drm_mode_object *obj,
0350                   struct drm_property *property, uint64_t *val)
0351 {
0352     WARN_ON(drm_drv_uses_atomic_modeset(property->dev));
0353 
0354     return __drm_object_property_get_value(obj, property, val);
0355 }
0356 EXPORT_SYMBOL(drm_object_property_get_value);
0357 
0358 /**
0359  * drm_object_property_get_default_value - retrieve the default value of a
0360  * property when in atomic mode.
0361  * @obj: drm mode object to get property value from
0362  * @property: property to retrieve
0363  * @val: storage for the property value
0364  *
0365  * This function retrieves the default state of the given property as passed in
0366  * to drm_object_attach_property
0367  *
0368  * Only atomic drivers should call this function directly, as for non-atomic
0369  * drivers it will return the current value.
0370  *
0371  * Returns:
0372  * Zero on success, error code on failure.
0373  */
0374 int drm_object_property_get_default_value(struct drm_mode_object *obj,
0375                       struct drm_property *property,
0376                       uint64_t *val)
0377 {
0378     WARN_ON(!drm_drv_uses_atomic_modeset(property->dev));
0379 
0380     return __drm_object_property_get_prop_value(obj, property, val);
0381 }
0382 EXPORT_SYMBOL(drm_object_property_get_default_value);
0383 
0384 /* helper for getconnector and getproperties ioctls */
0385 int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
0386                    uint32_t __user *prop_ptr,
0387                    uint64_t __user *prop_values,
0388                    uint32_t *arg_count_props)
0389 {
0390     int i, ret, count;
0391 
0392     for (i = 0, count = 0; i < obj->properties->count; i++) {
0393         struct drm_property *prop = obj->properties->properties[i];
0394         uint64_t val;
0395 
0396         if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
0397             continue;
0398 
0399         if (*arg_count_props > count) {
0400             ret = __drm_object_property_get_value(obj, prop, &val);
0401             if (ret)
0402                 return ret;
0403 
0404             if (put_user(prop->base.id, prop_ptr + count))
0405                 return -EFAULT;
0406 
0407             if (put_user(val, prop_values + count))
0408                 return -EFAULT;
0409         }
0410 
0411         count++;
0412     }
0413     *arg_count_props = count;
0414 
0415     return 0;
0416 }
0417 
0418 /**
0419  * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
0420  * @dev: DRM device
0421  * @data: ioctl data
0422  * @file_priv: DRM file info
0423  *
0424  * This function retrieves the current value for an object's property. Compared
0425  * to the connector specific ioctl this one is extended to also work on crtc and
0426  * plane objects.
0427  *
0428  * Called by the user via ioctl.
0429  *
0430  * Returns:
0431  * Zero on success, negative errno on failure.
0432  */
0433 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
0434                       struct drm_file *file_priv)
0435 {
0436     struct drm_mode_obj_get_properties *arg = data;
0437     struct drm_mode_object *obj;
0438     struct drm_modeset_acquire_ctx ctx;
0439     int ret = 0;
0440 
0441     if (!drm_core_check_feature(dev, DRIVER_MODESET))
0442         return -EOPNOTSUPP;
0443 
0444     DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
0445 
0446     obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
0447     if (!obj) {
0448         ret = -ENOENT;
0449         goto out;
0450     }
0451     if (!obj->properties) {
0452         ret = -EINVAL;
0453         goto out_unref;
0454     }
0455 
0456     ret = drm_mode_object_get_properties(obj, file_priv->atomic,
0457             (uint32_t __user *)(unsigned long)(arg->props_ptr),
0458             (uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
0459             &arg->count_props);
0460 
0461 out_unref:
0462     drm_mode_object_put(obj);
0463 out:
0464     DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
0465     return ret;
0466 }
0467 
0468 struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj,
0469                            uint32_t prop_id)
0470 {
0471     int i;
0472 
0473     for (i = 0; i < obj->properties->count; i++)
0474         if (obj->properties->properties[i]->base.id == prop_id)
0475             return obj->properties->properties[i];
0476 
0477     return NULL;
0478 }
0479 
0480 static int set_property_legacy(struct drm_mode_object *obj,
0481                    struct drm_property *prop,
0482                    uint64_t prop_value)
0483 {
0484     struct drm_device *dev = prop->dev;
0485     struct drm_mode_object *ref;
0486     struct drm_modeset_acquire_ctx ctx;
0487     int ret = -EINVAL;
0488 
0489     if (!drm_property_change_valid_get(prop, prop_value, &ref))
0490         return -EINVAL;
0491 
0492     DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
0493     switch (obj->type) {
0494     case DRM_MODE_OBJECT_CONNECTOR:
0495         ret = drm_connector_set_obj_prop(obj, prop, prop_value);
0496         break;
0497     case DRM_MODE_OBJECT_CRTC:
0498         ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value);
0499         break;
0500     case DRM_MODE_OBJECT_PLANE:
0501         ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj),
0502                           prop, prop_value);
0503         break;
0504     }
0505     drm_property_change_valid_put(prop, ref);
0506     DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
0507 
0508     return ret;
0509 }
0510 
0511 static int set_property_atomic(struct drm_mode_object *obj,
0512                    struct drm_file *file_priv,
0513                    struct drm_property *prop,
0514                    uint64_t prop_value)
0515 {
0516     struct drm_device *dev = prop->dev;
0517     struct drm_atomic_state *state;
0518     struct drm_modeset_acquire_ctx ctx;
0519     int ret;
0520 
0521     state = drm_atomic_state_alloc(dev);
0522     if (!state)
0523         return -ENOMEM;
0524 
0525     drm_modeset_acquire_init(&ctx, 0);
0526     state->acquire_ctx = &ctx;
0527 
0528 retry:
0529     if (prop == state->dev->mode_config.dpms_property) {
0530         if (obj->type != DRM_MODE_OBJECT_CONNECTOR) {
0531             ret = -EINVAL;
0532             goto out;
0533         }
0534 
0535         ret = drm_atomic_connector_commit_dpms(state,
0536                                obj_to_connector(obj),
0537                                prop_value);
0538     } else {
0539         ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value);
0540         if (ret)
0541             goto out;
0542         ret = drm_atomic_commit(state);
0543     }
0544 out:
0545     if (ret == -EDEADLK) {
0546         drm_atomic_state_clear(state);
0547         drm_modeset_backoff(&ctx);
0548         goto retry;
0549     }
0550 
0551     drm_atomic_state_put(state);
0552 
0553     drm_modeset_drop_locks(&ctx);
0554     drm_modeset_acquire_fini(&ctx);
0555 
0556     return ret;
0557 }
0558 
0559 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
0560                     struct drm_file *file_priv)
0561 {
0562     struct drm_mode_obj_set_property *arg = data;
0563     struct drm_mode_object *arg_obj;
0564     struct drm_property *property;
0565     int ret = -EINVAL;
0566 
0567     if (!drm_core_check_feature(dev, DRIVER_MODESET))
0568         return -EOPNOTSUPP;
0569 
0570     arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
0571     if (!arg_obj)
0572         return -ENOENT;
0573 
0574     if (!arg_obj->properties)
0575         goto out_unref;
0576 
0577     property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id);
0578     if (!property)
0579         goto out_unref;
0580 
0581     if (drm_drv_uses_atomic_modeset(property->dev))
0582         ret = set_property_atomic(arg_obj, file_priv, property, arg->value);
0583     else
0584         ret = set_property_legacy(arg_obj, property, arg->value);
0585 
0586 out_unref:
0587     drm_mode_object_put(arg_obj);
0588     return ret;
0589 }