diff options
author | Paulo Zanoni <paulo.r.zanoni@intel.com> | 2012-05-15 17:09:02 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-05-17 06:11:22 -0400 |
commit | c543188afb7a83e66161c026dc6fd5eb38dc0b63 (patch) | |
tree | 4897e68dcea04f30a8da6b573a3776f3684ee404 | |
parent | 7e3bdf4a6dca9eb153cc20d69d717308a68bec00 (diff) |
drm: add generic ioctls to get/set properties on any object
Useless for connector properties (since they already have their own
ioctls), but useful when we add properties to CRTCs, planes and other
objects.
Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
Reviewed-by: Rob Clark <rob.clark@linaro.org>
Tested-by: Rob Clark <rob.clark@linaro.org>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 182 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 4 | ||||
-rw-r--r-- | include/drm/drm.h | 2 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 13 | ||||
-rw-r--r-- | include/drm/drm_mode.h | 15 |
5 files changed, 215 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 19a289f01234..b6783f914246 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -2875,6 +2875,58 @@ int drm_connector_property_get_value(struct drm_connector *connector, | |||
2875 | } | 2875 | } |
2876 | EXPORT_SYMBOL(drm_connector_property_get_value); | 2876 | EXPORT_SYMBOL(drm_connector_property_get_value); |
2877 | 2877 | ||
2878 | void drm_object_attach_property(struct drm_mode_object *obj, | ||
2879 | struct drm_property *property, | ||
2880 | uint64_t init_val) | ||
2881 | { | ||
2882 | int i; | ||
2883 | |||
2884 | for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++) { | ||
2885 | if (obj->properties->ids[i] == 0) { | ||
2886 | obj->properties->ids[i] = property->base.id; | ||
2887 | obj->properties->values[i] = init_val; | ||
2888 | return; | ||
2889 | } | ||
2890 | } | ||
2891 | |||
2892 | WARN(1, "Failed to attach object property (type: 0x%x). Please " | ||
2893 | "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time you see " | ||
2894 | "this message on the same object type.\n", obj->type); | ||
2895 | } | ||
2896 | EXPORT_SYMBOL(drm_object_attach_property); | ||
2897 | |||
2898 | int drm_object_property_set_value(struct drm_mode_object *obj, | ||
2899 | struct drm_property *property, uint64_t val) | ||
2900 | { | ||
2901 | int i; | ||
2902 | |||
2903 | for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++) { | ||
2904 | if (obj->properties->ids[i] == property->base.id) { | ||
2905 | obj->properties->values[i] = val; | ||
2906 | return 0; | ||
2907 | } | ||
2908 | } | ||
2909 | |||
2910 | return -EINVAL; | ||
2911 | } | ||
2912 | EXPORT_SYMBOL(drm_object_property_set_value); | ||
2913 | |||
2914 | int drm_object_property_get_value(struct drm_mode_object *obj, | ||
2915 | struct drm_property *property, uint64_t *val) | ||
2916 | { | ||
2917 | int i; | ||
2918 | |||
2919 | for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++) { | ||
2920 | if (obj->properties->ids[i] == property->base.id) { | ||
2921 | *val = obj->properties->values[i]; | ||
2922 | return 0; | ||
2923 | } | ||
2924 | } | ||
2925 | |||
2926 | return -EINVAL; | ||
2927 | } | ||
2928 | EXPORT_SYMBOL(drm_object_property_get_value); | ||
2929 | |||
2878 | int drm_mode_getproperty_ioctl(struct drm_device *dev, | 2930 | int drm_mode_getproperty_ioctl(struct drm_device *dev, |
2879 | void *data, struct drm_file *file_priv) | 2931 | void *data, struct drm_file *file_priv) |
2880 | { | 2932 | { |
@@ -3148,6 +3200,136 @@ out: | |||
3148 | return ret; | 3200 | return ret; |
3149 | } | 3201 | } |
3150 | 3202 | ||
3203 | static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, | ||
3204 | struct drm_property *property, | ||
3205 | uint64_t value) | ||
3206 | { | ||
3207 | int ret = -EINVAL; | ||
3208 | struct drm_connector *connector = obj_to_connector(obj); | ||
3209 | |||
3210 | /* Do DPMS ourselves */ | ||
3211 | if (property == connector->dev->mode_config.dpms_property) { | ||
3212 | if (connector->funcs->dpms) | ||
3213 | (*connector->funcs->dpms)(connector, (int)value); | ||
3214 | ret = 0; | ||
3215 | } else if (connector->funcs->set_property) | ||
3216 | ret = connector->funcs->set_property(connector, property, value); | ||
3217 | |||
3218 | /* store the property value if successful */ | ||
3219 | if (!ret) | ||
3220 | drm_connector_property_set_value(connector, property, value); | ||
3221 | return ret; | ||
3222 | } | ||
3223 | |||
3224 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | ||
3225 | struct drm_file *file_priv) | ||
3226 | { | ||
3227 | struct drm_mode_obj_get_properties *arg = data; | ||
3228 | struct drm_mode_object *obj; | ||
3229 | int ret = 0; | ||
3230 | int i; | ||
3231 | int copied = 0; | ||
3232 | int props_count = 0; | ||
3233 | uint32_t __user *props_ptr; | ||
3234 | uint64_t __user *prop_values_ptr; | ||
3235 | |||
3236 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3237 | return -EINVAL; | ||
3238 | |||
3239 | mutex_lock(&dev->mode_config.mutex); | ||
3240 | |||
3241 | obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); | ||
3242 | if (!obj) { | ||
3243 | ret = -EINVAL; | ||
3244 | goto out; | ||
3245 | } | ||
3246 | if (!obj->properties) { | ||
3247 | ret = -EINVAL; | ||
3248 | goto out; | ||
3249 | } | ||
3250 | |||
3251 | /* Assume [ prop, 0, prop ] won't happen (if we ever delete properties, | ||
3252 | * we need to remove the gap inside the array). */ | ||
3253 | for (props_count = 0; props_count < DRM_OBJECT_MAX_PROPERTY && | ||
3254 | obj->properties->ids[props_count] != 0; props_count++) | ||
3255 | ; | ||
3256 | |||
3257 | /* This ioctl is called twice, once to determine how much space is | ||
3258 | * needed, and the 2nd time to fill it. */ | ||
3259 | if ((arg->count_props >= props_count) && props_count) { | ||
3260 | copied = 0; | ||
3261 | props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); | ||
3262 | prop_values_ptr = (uint64_t __user *)(unsigned long) | ||
3263 | (arg->prop_values_ptr); | ||
3264 | for (i = 0; i < props_count; i++) { | ||
3265 | if (put_user(obj->properties->ids[i], | ||
3266 | props_ptr + copied)) { | ||
3267 | ret = -EFAULT; | ||
3268 | goto out; | ||
3269 | } | ||
3270 | if (put_user(obj->properties->values[i], | ||
3271 | prop_values_ptr + copied)) { | ||
3272 | ret = -EFAULT; | ||
3273 | goto out; | ||
3274 | } | ||
3275 | copied++; | ||
3276 | } | ||
3277 | } | ||
3278 | arg->count_props = props_count; | ||
3279 | out: | ||
3280 | mutex_unlock(&dev->mode_config.mutex); | ||
3281 | return ret; | ||
3282 | } | ||
3283 | |||
3284 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | ||
3285 | struct drm_file *file_priv) | ||
3286 | { | ||
3287 | struct drm_mode_obj_set_property *arg = data; | ||
3288 | struct drm_mode_object *arg_obj; | ||
3289 | struct drm_mode_object *prop_obj; | ||
3290 | struct drm_property *property; | ||
3291 | int ret = -EINVAL; | ||
3292 | int i; | ||
3293 | |||
3294 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3295 | return -EINVAL; | ||
3296 | |||
3297 | mutex_lock(&dev->mode_config.mutex); | ||
3298 | |||
3299 | arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); | ||
3300 | if (!arg_obj) | ||
3301 | goto out; | ||
3302 | if (!arg_obj->properties) | ||
3303 | goto out; | ||
3304 | |||
3305 | for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++) | ||
3306 | if (arg_obj->properties->ids[i] == arg->prop_id) | ||
3307 | break; | ||
3308 | |||
3309 | if (i == DRM_OBJECT_MAX_PROPERTY) | ||
3310 | goto out; | ||
3311 | |||
3312 | prop_obj = drm_mode_object_find(dev, arg->prop_id, | ||
3313 | DRM_MODE_OBJECT_PROPERTY); | ||
3314 | if (!prop_obj) | ||
3315 | goto out; | ||
3316 | property = obj_to_property(prop_obj); | ||
3317 | |||
3318 | if (!drm_property_change_is_valid(property, arg->value)) | ||
3319 | goto out; | ||
3320 | |||
3321 | switch (arg_obj->type) { | ||
3322 | case DRM_MODE_OBJECT_CONNECTOR: | ||
3323 | ret = drm_mode_connector_set_obj_prop(arg_obj, property, | ||
3324 | arg->value); | ||
3325 | break; | ||
3326 | } | ||
3327 | |||
3328 | out: | ||
3329 | mutex_unlock(&dev->mode_config.mutex); | ||
3330 | return ret; | ||
3331 | } | ||
3332 | |||
3151 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, | 3333 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, |
3152 | struct drm_encoder *encoder) | 3334 | struct drm_encoder *encoder) |
3153 | { | 3335 | { |
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 6116e3b75393..8a9d0792e4ec 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -163,7 +163,9 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
163 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 163 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
164 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 164 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
165 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 165 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
166 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED) | 166 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
167 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | ||
168 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | ||
167 | }; | 169 | }; |
168 | 170 | ||
169 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) | 171 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
diff --git a/include/drm/drm.h b/include/drm/drm.h index 64ff02d5b730..5b831df15bf1 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h | |||
@@ -730,6 +730,8 @@ struct drm_prime_handle { | |||
730 | #define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) | 730 | #define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) |
731 | #define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) | 731 | #define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) |
732 | #define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) | 732 | #define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) |
733 | #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) | ||
734 | #define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) | ||
733 | 735 | ||
734 | /** | 736 | /** |
735 | * Device specific ioctls should only be in their respective headers | 737 | * Device specific ioctls should only be in their respective headers |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 77606794308b..b0c32499fcd4 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -903,6 +903,12 @@ extern int drm_connector_property_set_value(struct drm_connector *connector, | |||
903 | extern int drm_connector_property_get_value(struct drm_connector *connector, | 903 | extern int drm_connector_property_get_value(struct drm_connector *connector, |
904 | struct drm_property *property, | 904 | struct drm_property *property, |
905 | uint64_t *value); | 905 | uint64_t *value); |
906 | extern int drm_object_property_set_value(struct drm_mode_object *obj, | ||
907 | struct drm_property *property, | ||
908 | uint64_t val); | ||
909 | extern int drm_object_property_get_value(struct drm_mode_object *obj, | ||
910 | struct drm_property *property, | ||
911 | uint64_t *value); | ||
906 | extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); | 912 | extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); |
907 | extern void drm_framebuffer_set_object(struct drm_device *dev, | 913 | extern void drm_framebuffer_set_object(struct drm_device *dev, |
908 | unsigned long handle); | 914 | unsigned long handle); |
@@ -917,6 +923,9 @@ extern bool drm_crtc_in_use(struct drm_crtc *crtc); | |||
917 | 923 | ||
918 | extern void drm_connector_attach_property(struct drm_connector *connector, | 924 | extern void drm_connector_attach_property(struct drm_connector *connector, |
919 | struct drm_property *property, uint64_t init_val); | 925 | struct drm_property *property, uint64_t init_val); |
926 | extern void drm_object_attach_property(struct drm_mode_object *obj, | ||
927 | struct drm_property *property, | ||
928 | uint64_t init_val); | ||
920 | extern struct drm_property *drm_property_create(struct drm_device *dev, int flags, | 929 | extern struct drm_property *drm_property_create(struct drm_device *dev, int flags, |
921 | const char *name, int num_values); | 930 | const char *name, int num_values); |
922 | extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, | 931 | extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, |
@@ -1029,6 +1038,10 @@ extern int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, | |||
1029 | void *data, struct drm_file *file_priv); | 1038 | void *data, struct drm_file *file_priv); |
1030 | extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, | 1039 | extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, |
1031 | void *data, struct drm_file *file_priv); | 1040 | void *data, struct drm_file *file_priv); |
1041 | extern int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | ||
1042 | struct drm_file *file_priv); | ||
1043 | extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | ||
1044 | struct drm_file *file_priv); | ||
1032 | 1045 | ||
1033 | extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, | 1046 | extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, |
1034 | int *bpp); | 1047 | int *bpp); |
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 4a0aae38e160..326f2be0d497 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h | |||
@@ -254,6 +254,21 @@ struct drm_mode_connector_set_property { | |||
254 | __u32 connector_id; | 254 | __u32 connector_id; |
255 | }; | 255 | }; |
256 | 256 | ||
257 | struct drm_mode_obj_get_properties { | ||
258 | __u64 props_ptr; | ||
259 | __u64 prop_values_ptr; | ||
260 | __u32 count_props; | ||
261 | __u32 obj_id; | ||
262 | __u32 obj_type; | ||
263 | }; | ||
264 | |||
265 | struct drm_mode_obj_set_property { | ||
266 | __u64 value; | ||
267 | __u32 prop_id; | ||
268 | __u32 obj_id; | ||
269 | __u32 obj_type; | ||
270 | }; | ||
271 | |||
257 | struct drm_mode_get_blob { | 272 | struct drm_mode_get_blob { |
258 | __u32 blob_id; | 273 | __u32 blob_id; |
259 | __u32 length; | 274 | __u32 length; |