[1/2] drm: add bitmask property type

Message ID 1337158738-31685-2-git-send-email-rob.clark@linaro.org
State Superseded
Headers show

Commit Message

Rob Clark May 16, 2012, 8:58 a.m.
From: Rob Clark <rob@ti.com>

A bitmask property is similar to an enum.  The enum value is a bit
position (0-63), and valid property values consist of a mask of
zero or more of (1 << enum_val[n]).

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/gpu/drm/drm_crtc.c |   46 +++++++++++++++++++++++++++++++++++++++++---
 include/drm/drm_crtc.h     |    3 +++
 include/drm/drm_mode.h     |    1 +
 3 files changed, 47 insertions(+), 3 deletions(-)

Comments

Paulo Zanoni May 16, 2012, 5:58 p.m. | #1
2012/5/16 Rob Clark <rob.clark@linaro.org>:
> From: Rob Clark <rob@ti.com>
>
> A bitmask property is similar to an enum.  The enum value is a bit
> position (0-63), and valid property values consist of a mask of
> zero or more of (1 << enum_val[n]).
>
> Signed-off-by: Rob Clark <rob@ti.com>

<Bikeshedding>
"int num_values" appears after column 80 in 2 places
</Bikeshedding>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/drm_crtc.c |   46 +++++++++++++++++++++++++++++++++++++++++---
>  include/drm/drm_crtc.h     |    3 +++
>  include/drm/drm_mode.h     |    1 +
>  3 files changed, 47 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 75661c8..022873e 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -2707,6 +2707,33 @@ struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
>  }
>  EXPORT_SYMBOL(drm_property_create_enum);
>
> +struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
> +                                        int flags, const char *name,
> +                                        const struct drm_prop_enum_list *props, int num_values)
> +{
> +       struct drm_property *property;
> +       int i, ret;
> +
> +       flags |= DRM_MODE_PROP_BITMASK;
> +
> +       property = drm_property_create(dev, flags, name, num_values);
> +       if (!property)
> +               return NULL;
> +
> +       for (i = 0; i < num_values; i++) {
> +               ret = drm_property_add_enum(property, i,
> +                                     props[i].type,
> +                                     props[i].name);
> +               if (ret) {
> +                       drm_property_destroy(dev, property);
> +                       return NULL;
> +               }
> +       }
> +
> +       return property;
> +}
> +EXPORT_SYMBOL(drm_property_create_bitmask);
> +
>  struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
>                                         const char *name,
>                                         uint64_t min, uint64_t max)
> @@ -2731,7 +2758,14 @@ int drm_property_add_enum(struct drm_property *property, int index,
>  {
>        struct drm_property_enum *prop_enum;
>
> -       if (!(property->flags & DRM_MODE_PROP_ENUM))
> +       if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
> +               return -EINVAL;
> +
> +       /*
> +        * Bitmask enum properties have the additional constraint of values
> +        * from 0 to 63
> +        */
> +       if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
>                return -EINVAL;
>
>        if (!list_empty(&property->enum_blob_list)) {
> @@ -2875,7 +2909,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
>        }
>        property = obj_to_property(obj);
>
> -       if (property->flags & DRM_MODE_PROP_ENUM) {
> +       if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
>                list_for_each_entry(prop_enum, &property->enum_blob_list, head)
>                        enum_count++;
>        } else if (property->flags & DRM_MODE_PROP_BLOB) {
> @@ -2900,7 +2934,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
>        }
>        out_resp->count_values = value_count;
>
> -       if (property->flags & DRM_MODE_PROP_ENUM) {
> +       if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
>                if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
>                        copied = 0;
>                        enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
> @@ -3055,6 +3089,12 @@ static bool drm_property_change_is_valid(struct drm_property *property,
>                if (value < property->values[0] || value > property->values[1])
>                        return false;
>                return true;
> +       } else if (property->flags & DRM_MODE_PROP_BITMASK) {
> +               int i;
> +               __u64 valid_mask = 0;
> +               for (i = 0; i < property->num_values; i++)
> +                       valid_mask |= (1LL << property->values[i]);
> +               return !(value & ~valid_mask);
>        } else {
>                int i;
>                for (i = 0; i < property->num_values; i++)
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index e194c78..39e3e1c 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -940,6 +940,9 @@ extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int
>                                         const char *name,
>                                         const struct drm_prop_enum_list *props,
>                                         int num_values);
> +struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
> +                                        int flags, const char *name,
> +                                        const struct drm_prop_enum_list *props, int num_values);
>  struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
>                                         const char *name,
>                                         uint64_t min, uint64_t max);
> diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
> index 326f2be..5581980 100644
> --- a/include/drm/drm_mode.h
> +++ b/include/drm/drm_mode.h
> @@ -230,6 +230,7 @@ struct drm_mode_get_connector {
>  #define DRM_MODE_PROP_IMMUTABLE        (1<<2)
>  #define DRM_MODE_PROP_ENUM     (1<<3) /* enumerated type with text strings */
>  #define DRM_MODE_PROP_BLOB     (1<<4)
> +#define DRM_MODE_PROP_BITMASK  (1<<5) /* bitmask of enumerated types */
>
>  struct drm_mode_property_enum {
>        __u64 value;
> --
> 1.7.9.5
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

Patch

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 75661c8..022873e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2707,6 +2707,33 @@  struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
 }
 EXPORT_SYMBOL(drm_property_create_enum);
 
+struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+					 int flags, const char *name,
+					 const struct drm_prop_enum_list *props, int num_values)
+{
+	struct drm_property *property;
+	int i, ret;
+
+	flags |= DRM_MODE_PROP_BITMASK;
+
+	property = drm_property_create(dev, flags, name, num_values);
+	if (!property)
+		return NULL;
+
+	for (i = 0; i < num_values; i++) {
+		ret = drm_property_add_enum(property, i,
+				      props[i].type,
+				      props[i].name);
+		if (ret) {
+			drm_property_destroy(dev, property);
+			return NULL;
+		}
+	}
+
+	return property;
+}
+EXPORT_SYMBOL(drm_property_create_bitmask);
+
 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
 					 const char *name,
 					 uint64_t min, uint64_t max)
@@ -2731,7 +2758,14 @@  int drm_property_add_enum(struct drm_property *property, int index,
 {
 	struct drm_property_enum *prop_enum;
 
-	if (!(property->flags & DRM_MODE_PROP_ENUM))
+	if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
+		return -EINVAL;
+
+	/*
+	 * Bitmask enum properties have the additional constraint of values
+	 * from 0 to 63
+	 */
+	if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
 		return -EINVAL;
 
 	if (!list_empty(&property->enum_blob_list)) {
@@ -2875,7 +2909,7 @@  int drm_mode_getproperty_ioctl(struct drm_device *dev,
 	}
 	property = obj_to_property(obj);
 
-	if (property->flags & DRM_MODE_PROP_ENUM) {
+	if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
 		list_for_each_entry(prop_enum, &property->enum_blob_list, head)
 			enum_count++;
 	} else if (property->flags & DRM_MODE_PROP_BLOB) {
@@ -2900,7 +2934,7 @@  int drm_mode_getproperty_ioctl(struct drm_device *dev,
 	}
 	out_resp->count_values = value_count;
 
-	if (property->flags & DRM_MODE_PROP_ENUM) {
+	if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
 		if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
 			copied = 0;
 			enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
@@ -3055,6 +3089,12 @@  static bool drm_property_change_is_valid(struct drm_property *property,
 		if (value < property->values[0] || value > property->values[1])
 			return false;
 		return true;
+	} else if (property->flags & DRM_MODE_PROP_BITMASK) {
+		int i;
+		__u64 valid_mask = 0;
+		for (i = 0; i < property->num_values; i++)
+			valid_mask |= (1LL << property->values[i]);
+		return !(value & ~valid_mask);
 	} else {
 		int i;
 		for (i = 0; i < property->num_values; i++)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e194c78..39e3e1c 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -940,6 +940,9 @@  extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int
 					 const char *name,
 					 const struct drm_prop_enum_list *props,
 					 int num_values);
+struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+					 int flags, const char *name,
+					 const struct drm_prop_enum_list *props, int num_values);
 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
 					 const char *name,
 					 uint64_t min, uint64_t max);
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 326f2be..5581980 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -230,6 +230,7 @@  struct drm_mode_get_connector {
 #define DRM_MODE_PROP_IMMUTABLE	(1<<2)
 #define DRM_MODE_PROP_ENUM	(1<<3) /* enumerated type with text strings */
 #define DRM_MODE_PROP_BLOB	(1<<4)
+#define DRM_MODE_PROP_BITMASK	(1<<5) /* bitmask of enumerated types */
 
 struct drm_mode_property_enum {
 	__u64 value;