diff options
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 26 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 17 | ||||
-rw-r--r-- | include/uapi/drm/drm_mode.h | 13 |
3 files changed, 47 insertions, 9 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c4b44be7d464..73f543af4924 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -3094,6 +3094,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, | |||
3094 | } | 3094 | } |
3095 | 3095 | ||
3096 | list_add_tail(&property->head, &dev->mode_config.property_list); | 3096 | list_add_tail(&property->head, &dev->mode_config.property_list); |
3097 | |||
3098 | WARN_ON(!drm_property_type_valid(property)); | ||
3099 | |||
3097 | return property; | 3100 | return property; |
3098 | fail: | 3101 | fail: |
3099 | kfree(property->values); | 3102 | kfree(property->values); |
@@ -3251,14 +3254,16 @@ int drm_property_add_enum(struct drm_property *property, int index, | |||
3251 | { | 3254 | { |
3252 | struct drm_property_enum *prop_enum; | 3255 | struct drm_property_enum *prop_enum; |
3253 | 3256 | ||
3254 | if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) | 3257 | if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3258 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK))) | ||
3255 | return -EINVAL; | 3259 | return -EINVAL; |
3256 | 3260 | ||
3257 | /* | 3261 | /* |
3258 | * Bitmask enum properties have the additional constraint of values | 3262 | * Bitmask enum properties have the additional constraint of values |
3259 | * from 0 to 63 | 3263 | * from 0 to 63 |
3260 | */ | 3264 | */ |
3261 | if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63)) | 3265 | if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) && |
3266 | (value > 63)) | ||
3262 | return -EINVAL; | 3267 | return -EINVAL; |
3263 | 3268 | ||
3264 | if (!list_empty(&property->enum_blob_list)) { | 3269 | if (!list_empty(&property->enum_blob_list)) { |
@@ -3439,10 +3444,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3439 | goto done; | 3444 | goto done; |
3440 | } | 3445 | } |
3441 | 3446 | ||
3442 | if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { | 3447 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3448 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { | ||
3443 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) | 3449 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) |
3444 | enum_count++; | 3450 | enum_count++; |
3445 | } else if (property->flags & DRM_MODE_PROP_BLOB) { | 3451 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { |
3446 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) | 3452 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) |
3447 | blob_count++; | 3453 | blob_count++; |
3448 | } | 3454 | } |
@@ -3464,7 +3470,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3464 | } | 3470 | } |
3465 | out_resp->count_values = value_count; | 3471 | out_resp->count_values = value_count; |
3466 | 3472 | ||
3467 | if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { | 3473 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3474 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { | ||
3468 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { | 3475 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { |
3469 | copied = 0; | 3476 | copied = 0; |
3470 | enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; | 3477 | enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; |
@@ -3486,7 +3493,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3486 | out_resp->count_enum_blobs = enum_count; | 3493 | out_resp->count_enum_blobs = enum_count; |
3487 | } | 3494 | } |
3488 | 3495 | ||
3489 | if (property->flags & DRM_MODE_PROP_BLOB) { | 3496 | if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { |
3490 | if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { | 3497 | if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { |
3491 | copied = 0; | 3498 | copied = 0; |
3492 | blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; | 3499 | blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; |
@@ -3640,17 +3647,18 @@ static bool drm_property_change_is_valid(struct drm_property *property, | |||
3640 | { | 3647 | { |
3641 | if (property->flags & DRM_MODE_PROP_IMMUTABLE) | 3648 | if (property->flags & DRM_MODE_PROP_IMMUTABLE) |
3642 | return false; | 3649 | return false; |
3643 | if (property->flags & DRM_MODE_PROP_RANGE) { | 3650 | |
3651 | if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) { | ||
3644 | if (value < property->values[0] || value > property->values[1]) | 3652 | if (value < property->values[0] || value > property->values[1]) |
3645 | return false; | 3653 | return false; |
3646 | return true; | 3654 | return true; |
3647 | } else if (property->flags & DRM_MODE_PROP_BITMASK) { | 3655 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
3648 | int i; | 3656 | int i; |
3649 | uint64_t valid_mask = 0; | 3657 | uint64_t valid_mask = 0; |
3650 | for (i = 0; i < property->num_values; i++) | 3658 | for (i = 0; i < property->num_values; i++) |
3651 | valid_mask |= (1ULL << property->values[i]); | 3659 | valid_mask |= (1ULL << property->values[i]); |
3652 | return !(value & ~valid_mask); | 3660 | return !(value & ~valid_mask); |
3653 | } else if (property->flags & DRM_MODE_PROP_BLOB) { | 3661 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { |
3654 | /* Only the driver knows */ | 3662 | /* Only the driver knows */ |
3655 | return true; | 3663 | return true; |
3656 | } else { | 3664 | } else { |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 90bd1a25e2c6..92f6ec2de86a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -930,6 +930,23 @@ extern void drm_mode_config_cleanup(struct drm_device *dev); | |||
930 | 930 | ||
931 | extern int drm_mode_connector_update_edid_property(struct drm_connector *connector, | 931 | extern int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
932 | struct edid *edid); | 932 | struct edid *edid); |
933 | |||
934 | static inline bool drm_property_type_is(struct drm_property *property, | ||
935 | uint32_t type) | ||
936 | { | ||
937 | /* instanceof for props.. handles extended type vs original types: */ | ||
938 | if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) | ||
939 | return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type; | ||
940 | return property->flags & type; | ||
941 | } | ||
942 | |||
943 | static inline bool drm_property_type_valid(struct drm_property *property) | ||
944 | { | ||
945 | if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) | ||
946 | return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE); | ||
947 | return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE); | ||
948 | } | ||
949 | |||
933 | extern int drm_object_property_set_value(struct drm_mode_object *obj, | 950 | extern int drm_object_property_set_value(struct drm_mode_object *obj, |
934 | struct drm_property *property, | 951 | struct drm_property *property, |
935 | uint64_t val); | 952 | uint64_t val); |
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 719add464f95..caeaa6f7ebde 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h | |||
@@ -252,6 +252,19 @@ struct drm_mode_get_connector { | |||
252 | #define DRM_MODE_PROP_BLOB (1<<4) | 252 | #define DRM_MODE_PROP_BLOB (1<<4) |
253 | #define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ | 253 | #define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ |
254 | 254 | ||
255 | /* non-extended types: legacy bitmask, one bit per type: */ | ||
256 | #define DRM_MODE_PROP_LEGACY_TYPE ( \ | ||
257 | DRM_MODE_PROP_RANGE | \ | ||
258 | DRM_MODE_PROP_ENUM | \ | ||
259 | DRM_MODE_PROP_BLOB | \ | ||
260 | DRM_MODE_PROP_BITMASK) | ||
261 | |||
262 | /* extended-types: rather than continue to consume a bit per type, | ||
263 | * grab a chunk of the bits to use as integer type id. | ||
264 | */ | ||
265 | #define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 | ||
266 | #define DRM_MODE_PROP_TYPE(n) ((n) << 6) | ||
267 | |||
255 | struct drm_mode_property_enum { | 268 | struct drm_mode_property_enum { |
256 | __u64 value; | 269 | __u64 value; |
257 | char name[DRM_PROP_NAME_LEN]; | 270 | char name[DRM_PROP_NAME_LEN]; |