modesetting: add dpms property and initial settable property ioctl
authorDave Airlie <airlied@redhat.com>
Tue, 11 Dec 2007 04:46:51 +0000 (14:46 +1000)
committerDave Airlie <airlied@linux.ie>
Tue, 11 Dec 2007 04:46:51 +0000 (14:46 +1000)
libdrm/xf86drmMode.c
linux-core/drm_crtc.c
linux-core/drm_crtc.h
shared-core/drm.h
tests/mode/Makefile
tests/mode/modetest.c

index 03bd15f..7e2683e 100644 (file)
@@ -421,10 +421,10 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
        if (prop.count_values)
                prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
 
-       if (prop.count_enum_blobs & (prop.flags & DRM_MODE_PROP_ENUM))
+       if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
                prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
 
-       if (prop.count_enum_blobs & (prop.flags & DRM_MODE_PROP_BLOB)) {
+       if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
                prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
                prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
        }
index fba275b..871f899 100644 (file)
@@ -592,6 +592,8 @@ struct drm_output *drm_output_create(struct drm_device *dev,
 
        drm_output_attach_property(output, dev->mode_config.edid_property, 0);
 
+       drm_output_attach_property(output, dev->mode_config.dpms_property, 0);
+
        mutex_unlock(&dev->mode_config.mutex);
 
        return output;
@@ -729,6 +731,15 @@ void drm_mode_config_init(struct drm_device *dev)
        dev->mode_config.edid_property = drm_property_create(dev,
                                                             DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE,
                                                             "EDID", 0);
+
+       dev->mode_config.dpms_property = drm_property_create(dev,
+                                                            DRM_MODE_PROP_ENUM,
+                                                            "DPMS", 4);
+       drm_property_add_enum(dev->mode_config.dpms_property, 0, DPMSModeOn, "On");
+       drm_property_add_enum(dev->mode_config.dpms_property, 1, DPMSModeStandby, "Standby");
+       drm_property_add_enum(dev->mode_config.dpms_property, 2, DPMSModeSuspend, "Suspend");
+       drm_property_add_enum(dev->mode_config.dpms_property, 3, DPMSModeOff, "Off");
+       
 }
 EXPORT_SYMBOL(drm_mode_config_init);
 
@@ -1985,7 +1996,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
        int ret = 0, i;
        int copied;
        struct drm_property_enum *prop_enum;
-       struct drm_property_enum __user *enum_ptr;
+       struct drm_mode_property_enum __user *enum_ptr;
        struct drm_property_blob *prop_blob;
        uint32_t *blob_id_ptr;
        uint64_t __user *values_ptr;
@@ -2015,7 +2026,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
        if ((out_resp->count_values >= value_count) && value_count) {
                values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr;
                for (i = 0; i < value_count; i++) {
-                       if (put_user(property->values[i], values_ptr + i)) {
+                       if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
                                ret = -EFAULT;
                                goto done;
                        }
@@ -2024,19 +2035,21 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
        out_resp->count_values = value_count;
 
        if (property->flags & DRM_MODE_PROP_ENUM) {
+
                if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
                        copied = 0;
-                       enum_ptr = (struct drm_property_enum *)(unsigned long)out_resp->enum_blob_ptr;
+                       enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr;
                        list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
-                               if (put_user(prop_enum->value, &enum_ptr[copied].value)) {
+                               
+                               if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
                                        ret = -EFAULT;
                                        goto done;
                                }
                                
                                if (copy_to_user(&enum_ptr[copied].name,
-                                                prop_enum->name, DRM_PROP_NAME_LEN)) {
-                               ret = -EFAULT;
-                               goto done;
+                                                &prop_enum->name, DRM_PROP_NAME_LEN)) {
+                                       ret = -EFAULT;
+                                       goto done;
                                }
                                copied++;
                        }
@@ -2145,3 +2158,35 @@ int drm_mode_output_update_edid_property(struct drm_output *output, unsigned cha
        return ret;
 }
 EXPORT_SYMBOL(drm_mode_output_update_edid_property);
+
+int drm_mode_output_property_set_ioctl(struct drm_device *dev,
+                          void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_output_set_property *out_resp = data;
+       struct drm_output *output;
+       int ret = -EINVAL;
+       int i;
+
+       mutex_lock(&dev->mode_config.mutex);
+       output= idr_find(&dev->mode_config.crtc_idr, out_resp->output_id);
+       if (!output || (output->id != out_resp->output_id)) {
+               goto out;
+       }
+
+       for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) {
+               if (output->property_ids[i] == out_resp->prop_id)
+                       break;
+       }
+
+       if (i == DRM_OUTPUT_MAX_PROPERTY) {
+               goto out;
+       }
+       
+       if (output->funcs->set_property)
+               ret = output->funcs->set_property(output, out_resp->prop_id, out_resp->value);
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
index 2c77d9d..ad5ecc5 100644 (file)
@@ -242,8 +242,8 @@ struct drm_property_blob {
 };
 
 struct drm_property_enum {
-       struct list_head head;
        uint64_t value;
+       struct list_head head;
        unsigned char name[DRM_PROP_NAME_LEN];
 };
 
@@ -396,7 +396,7 @@ struct drm_output_funcs {
        enum drm_output_status (*detect)(struct drm_output *output);
        int (*get_modes)(struct drm_output *output);
        /* JJJ: type checking for properties via property value type */
-       bool (*set_property)(struct drm_output *output, int prop, void *val);
+       bool (*set_property)(struct drm_output *output, int prop, uint64_t val);
        void (*cleanup)(struct drm_output *output);
 };
 
@@ -503,6 +503,7 @@ struct drm_mode_config {
        /* pointers to standard properties */
        struct list_head property_blob_list;
        struct drm_property *edid_property;
+       struct drm_property *dpms_property;
 };
 
 struct drm_output *drm_output_create(struct drm_device *dev,
index 0c66f85..df43802 100644 (file)
@@ -992,6 +992,12 @@ struct drm_mode_get_property {
        int count_enum_blobs;
 };
 
+struct drm_mode_output_set_property {
+       uint64_t value;
+       unsigned int prop_id;
+       unsigned int output_id;
+};
+
 struct drm_mode_get_blob {
        uint32_t blob_id;
        uint32_t length;
@@ -1112,6 +1118,7 @@ struct drm_mode_mode_cmd {
 #define DRM_IOCTL_MODE_RMFB             DRM_IOWR(0xA5, unsigned int)
 #define DRM_IOCTL_MODE_GETFB            DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
 
+#define DRM_IOCTL_MODE_SETPROPERTY     DRM_IOWR(0xAB, struct drm_mode_set_output_property)
 #define DRM_IOCTL_MODE_GETPROPBLOB     DRM_IOWR(0xA8, struct drm_mode_get_blob)
 #define DRM_IOCTL_MODE_ATTACHMODE      DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
 #define DRM_IOCTL_MODE_DETACHMODE      DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
index 205c2ba..a3d3b49 100644 (file)
@@ -5,7 +5,7 @@ all: modetest
 #        -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \
 
 modetest: modetest.c
-       @gcc -o modetest -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modetest.c 
+       @gcc $(CFLAGS) -o modetest -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modetest.c 
 
 clean:
        @rm -f modetest
index c396da4..4a8c6a1 100644 (file)
@@ -80,15 +80,17 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
                                drmModePropertyBlobPtr blob;
 
                                blob = drmModeGetPropertyBlob(fd, output->prop_values[i]);
-
-                               printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data);
-                               drmModeFreePropertyBlob(blob);
+                               if (blob) {
+                                       printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data);
+                                       drmModeFreePropertyBlob(blob);
+                               }
 
                        } else {
                                for (j = 0; j < props->count_enums; j++) {
+                                 printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name);
                                        if (output->prop_values[i] == props->enums[j].value)
                                                name = props->enums[j].name;
-                                       printf("\t\t%d = %s\n", props->enums[j].value, props->enums[j].name);
+
                                }
 
                                if (props->count_enums && name) {