From 3b6786e3e6523b1ceca3645ea4c6081f170d2134 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Dec 2007 14:46:51 +1000 Subject: [PATCH] modesetting: add dpms property and initial settable property ioctl --- libdrm/xf86drmMode.c | 4 ++-- linux-core/drm_crtc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++------ linux-core/drm_crtc.h | 5 +++-- shared-core/drm.h | 7 ++++++ tests/mode/Makefile | 2 +- tests/mode/modetest.c | 10 +++++---- 6 files changed, 71 insertions(+), 16 deletions(-) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 03bd15f..7e2683e 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -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))); } diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fba275b..871f899 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -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; +} + diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 2c77d9d..ad5ecc5 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -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, diff --git a/shared-core/drm.h b/shared-core/drm.h index 0c66f85..df43802 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -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) diff --git a/tests/mode/Makefile b/tests/mode/Makefile index 205c2ba..a3d3b49 100644 --- a/tests/mode/Makefile +++ b/tests/mode/Makefile @@ -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 diff --git a/tests/mode/modetest.c b/tests/mode/modetest.c index c396da4..4a8c6a1 100644 --- a/tests/mode/modetest.c +++ b/tests/mode/modetest.c @@ -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) { -- 2.7.4