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 /drivers/gpu/drm/drm_crtc.c | |
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>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 182 |
1 files changed, 182 insertions, 0 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 | { |