diff mbox

[RFCv1,04/12] drm: add DRM_MODE_PROP_SIGNED property flag

Message ID 1381020350-1125-5-git-send-email-robdclark@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Rob Clark Oct. 6, 2013, 12:45 a.m. UTC
Flag for range property types indicating that the value is a signed
integer rather than unsigned.  For range properties, the signed flag
will trigger use of signed integer comparisions, to handle negative
values properly.
---
 drivers/gpu/drm/drm_crtc.c  | 10 ++++++++--
 include/drm/drm_crtc.h      |  9 +++++++++
 include/uapi/drm/drm_mode.h |  2 ++
 3 files changed, 19 insertions(+), 2 deletions(-)

Comments

Matt Plumtree Oct. 7, 2013, 2:46 p.m. UTC | #1
> static bool drm_property_change_is_valid(struct drm_property *property,
>  					 uint64_t value)
>  {
> -	if (property->flags & DRM_MODE_PROP_IMMUTABLE)
> +	if (property->flags & DRM_MODE_PROP_IMMUTABLE) {
>  		return false;
> -	if (property->flags & DRM_MODE_PROP_RANGE) {
> +	} else if (property->flags & (DRM_MODE_PROP_RANGE|DRM_MODE_PROP_SIGNED)) {
> +		int64_t svalue = U642I64(value);
> +		if (svalue < U642I64(property->values[0]) ||
> +				svalue > U642I64(property->values[1]))
> +			return false;
> +		return true;
> +	} else if (property->flags & DRM_MODE_PROP_RANGE) {
>		if (value < property->values[0] || value > property->values[1])
>  			return false;
>  		return true;

I don't think this is doing what you think it should. If the flags include
DRM_MODE_PROP_RANGE, the first "else if" will be executed regardless of
whether DRM_MODE_PROP_SIGNED is set or not. This means that the second
"else if" will never be executed.

You'd need to add "== (DRM_MODE_PROP_RANGE|DRM_MODE_PROP_SIGNED)" or
similar.

Matt
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 471cf16..46bae42 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3211,9 +3211,15 @@  EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
 static bool drm_property_change_is_valid(struct drm_property *property,
 					 uint64_t value)
 {
-	if (property->flags & DRM_MODE_PROP_IMMUTABLE)
+	if (property->flags & DRM_MODE_PROP_IMMUTABLE) {
 		return false;
-	if (property->flags & DRM_MODE_PROP_RANGE) {
+	} else if (property->flags & (DRM_MODE_PROP_RANGE|DRM_MODE_PROP_SIGNED)) {
+		int64_t svalue = U642I64(value);
+		if (svalue < U642I64(property->values[0]) ||
+				svalue > U642I64(property->values[1]))
+			return false;
+		return true;
+	} else if (property->flags & DRM_MODE_PROP_RANGE) {
 		if (value < property->values[0] || value > property->values[1])
 			return false;
 		return true;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 77c8f11..e042d12 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -64,6 +64,15 @@  struct drm_object_properties {
 	uint64_t values[DRM_OBJECT_MAX_PROPERTY];
 };
 
+static inline int64_t U642I64(uint64_t val)
+{
+	return (int64_t)*((int64_t *)&val);
+}
+static inline uint64_t I642U64(int64_t val)
+{
+	return (uint64_t)*((uint64_t *)&val);
+}
+
 /*
  * Note on terminology:  here, for brevity and convenience, we refer to connector
  * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS,
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 15db837..6d4f089 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -241,6 +241,8 @@  struct drm_mode_get_connector {
  * be changed dynamically, assuming the pixel format does not change.
  */
 #define DRM_MODE_PROP_DYNAMIC	(1<<24)
+/* Indicates that numeric property values are signed rather than unsigned: */
+#define DRM_MODE_PROP_SIGNED   (1<<25)
 
 struct drm_mode_property_enum {
 	__u64 value;