mirror of https://gitee.com/openkylin/linux.git
drm: add extended property types
If we continue to use bitmask for type, we will quickly run out of room to add new types. Split this up so existing part of bitmask range continues to function as before, but reserve a chunk of the remaining space for an integer type-id. Wrap this all up in some type-check helpers to keep the backwards-compat uglyness contained. Signed-off-by: Rob Clark <robdclark@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
a2b34e226a
commit
5ea22f24d7
|
@ -3094,6 +3094,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&property->head, &dev->mode_config.property_list);
|
list_add_tail(&property->head, &dev->mode_config.property_list);
|
||||||
|
|
||||||
|
WARN_ON(!drm_property_type_valid(property));
|
||||||
|
|
||||||
return property;
|
return property;
|
||||||
fail:
|
fail:
|
||||||
kfree(property->values);
|
kfree(property->values);
|
||||||
|
@ -3251,14 +3254,16 @@ int drm_property_add_enum(struct drm_property *property, int index,
|
||||||
{
|
{
|
||||||
struct drm_property_enum *prop_enum;
|
struct drm_property_enum *prop_enum;
|
||||||
|
|
||||||
if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
|
if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
|
||||||
|
drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bitmask enum properties have the additional constraint of values
|
* Bitmask enum properties have the additional constraint of values
|
||||||
* from 0 to 63
|
* from 0 to 63
|
||||||
*/
|
*/
|
||||||
if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
|
if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
|
||||||
|
(value > 63))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!list_empty(&property->enum_blob_list)) {
|
if (!list_empty(&property->enum_blob_list)) {
|
||||||
|
@ -3439,10 +3444,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
|
if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
|
||||||
|
drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
|
||||||
list_for_each_entry(prop_enum, &property->enum_blob_list, head)
|
list_for_each_entry(prop_enum, &property->enum_blob_list, head)
|
||||||
enum_count++;
|
enum_count++;
|
||||||
} else if (property->flags & DRM_MODE_PROP_BLOB) {
|
} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
|
||||||
list_for_each_entry(prop_blob, &property->enum_blob_list, head)
|
list_for_each_entry(prop_blob, &property->enum_blob_list, head)
|
||||||
blob_count++;
|
blob_count++;
|
||||||
}
|
}
|
||||||
|
@ -3464,7 +3470,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
out_resp->count_values = value_count;
|
out_resp->count_values = value_count;
|
||||||
|
|
||||||
if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
|
if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
|
||||||
|
drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
|
||||||
if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
|
if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
|
||||||
copied = 0;
|
copied = 0;
|
||||||
enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
|
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,
|
||||||
out_resp->count_enum_blobs = enum_count;
|
out_resp->count_enum_blobs = enum_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property->flags & DRM_MODE_PROP_BLOB) {
|
if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
|
||||||
if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
|
if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
|
||||||
copied = 0;
|
copied = 0;
|
||||||
blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
|
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,
|
||||||
{
|
{
|
||||||
if (property->flags & DRM_MODE_PROP_IMMUTABLE)
|
if (property->flags & DRM_MODE_PROP_IMMUTABLE)
|
||||||
return false;
|
return false;
|
||||||
if (property->flags & DRM_MODE_PROP_RANGE) {
|
|
||||||
|
if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
|
||||||
if (value < property->values[0] || value > property->values[1])
|
if (value < property->values[0] || value > property->values[1])
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
} else if (property->flags & DRM_MODE_PROP_BITMASK) {
|
} else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
|
||||||
int i;
|
int i;
|
||||||
uint64_t valid_mask = 0;
|
uint64_t valid_mask = 0;
|
||||||
for (i = 0; i < property->num_values; i++)
|
for (i = 0; i < property->num_values; i++)
|
||||||
valid_mask |= (1ULL << property->values[i]);
|
valid_mask |= (1ULL << property->values[i]);
|
||||||
return !(value & ~valid_mask);
|
return !(value & ~valid_mask);
|
||||||
} else if (property->flags & DRM_MODE_PROP_BLOB) {
|
} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
|
||||||
/* Only the driver knows */
|
/* Only the driver knows */
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -930,6 +930,23 @@ extern void drm_mode_config_cleanup(struct drm_device *dev);
|
||||||
|
|
||||||
extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
|
extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
|
||||||
struct edid *edid);
|
struct edid *edid);
|
||||||
|
|
||||||
|
static inline bool drm_property_type_is(struct drm_property *property,
|
||||||
|
uint32_t type)
|
||||||
|
{
|
||||||
|
/* instanceof for props.. handles extended type vs original types: */
|
||||||
|
if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
|
||||||
|
return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
|
||||||
|
return property->flags & type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool drm_property_type_valid(struct drm_property *property)
|
||||||
|
{
|
||||||
|
if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
|
||||||
|
return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
|
||||||
|
return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
extern int drm_object_property_set_value(struct drm_mode_object *obj,
|
extern int drm_object_property_set_value(struct drm_mode_object *obj,
|
||||||
struct drm_property *property,
|
struct drm_property *property,
|
||||||
uint64_t val);
|
uint64_t val);
|
||||||
|
|
|
@ -252,6 +252,19 @@ struct drm_mode_get_connector {
|
||||||
#define DRM_MODE_PROP_BLOB (1<<4)
|
#define DRM_MODE_PROP_BLOB (1<<4)
|
||||||
#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */
|
#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */
|
||||||
|
|
||||||
|
/* non-extended types: legacy bitmask, one bit per type: */
|
||||||
|
#define DRM_MODE_PROP_LEGACY_TYPE ( \
|
||||||
|
DRM_MODE_PROP_RANGE | \
|
||||||
|
DRM_MODE_PROP_ENUM | \
|
||||||
|
DRM_MODE_PROP_BLOB | \
|
||||||
|
DRM_MODE_PROP_BITMASK)
|
||||||
|
|
||||||
|
/* extended-types: rather than continue to consume a bit per type,
|
||||||
|
* grab a chunk of the bits to use as integer type id.
|
||||||
|
*/
|
||||||
|
#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
|
||||||
|
#define DRM_MODE_PROP_TYPE(n) ((n) << 6)
|
||||||
|
|
||||||
struct drm_mode_property_enum {
|
struct drm_mode_property_enum {
|
||||||
__u64 value;
|
__u64 value;
|
||||||
char name[DRM_PROP_NAME_LEN];
|
char name[DRM_PROP_NAME_LEN];
|
||||||
|
|
Loading…
Reference in New Issue