aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2007-12-06 10:44:51 +1000
committerDave Airlie <airlied@redhat.com>2007-12-06 10:44:51 +1000
commit67f6eb1eb8d3dc5bb5fdb097655d3da326f637c1 (patch)
tree86656d6f79feea5919194e62c38880a4adebfa2f
parentc9cda51af5a8bea1d30ce575ae260de52950fe2f (diff)
add property blobs and edid reporting support
-rw-r--r--libdrm/xf86drmMode.c41
-rw-r--r--libdrm/xf86drmMode.h3
-rw-r--r--linux-core/drm_crtc.c75
-rw-r--r--linux-core/drm_crtc.h8
-rw-r--r--linux-core/drm_drv.c1
-rw-r--r--linux-core/intel_crt.c1
-rw-r--r--linux-core/intel_modes.c1
-rw-r--r--shared-core/drm.h13
-rw-r--r--tests/mode/modetest.c9
9 files changed, 134 insertions, 18 deletions
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
index f4ec004c..03bd15f1 100644
--- a/libdrm/xf86drmMode.c
+++ b/libdrm/xf86drmMode.c
@@ -470,3 +470,44 @@ void drmModeFreeProperty(drmModePropertyPtr ptr)
drmFree(ptr->enums);
drmFree(ptr);
}
+
+drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
+{
+ struct drm_mode_get_blob blob;
+ drmModePropertyBlobPtr r;
+
+ blob.length = 0;
+ blob.data = 0;
+ blob.blob_id = blob_id;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+ return NULL;
+
+ if (blob.length)
+ blob.data = VOID2U64(drmMalloc(blob.length));
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
+ r = NULL;
+ goto err_allocs;
+ }
+
+ if (!(r = drmMalloc(sizeof(*r))))
+ return NULL;
+
+ r->id = blob.blob_id;
+ r->length = blob.length;
+ r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
+
+err_allocs:
+ drmFree(U642VOID(blob.data));
+ return r;
+}
+
+void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
+{
+ if (!ptr)
+ return;
+
+ drmFree(ptr->data);
+ drmFree(ptr);
+}
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
index e936044b..6fcf6a19 100644
--- a/libdrm/xf86drmMode.h
+++ b/libdrm/xf86drmMode.h
@@ -220,3 +220,6 @@ extern int drmModeDetachMode(int fd, uint32_t outputId, struct drm_mode_modeinfo
extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId);
extern void drmModeFreeProperty(drmModePropertyPtr ptr);
+
+extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
+extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index a3aa783b..70844237 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -590,6 +590,8 @@ struct drm_output *drm_output_create(struct drm_device *dev,
list_add_tail(&output->head, &dev->mode_config.output_list);
dev->mode_config.num_output++;
+ drm_output_attach_property(output, dev->mode_config.edid_property, 0);
+
mutex_unlock(&dev->mode_config.mutex);
return output;
@@ -1935,7 +1937,6 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
}
EXPORT_SYMBOL(drm_property_destroy);
-
int drm_output_attach_property(struct drm_output *output,
struct drm_property *property, uint64_t init_val)
{
@@ -1955,6 +1956,24 @@ int drm_output_attach_property(struct drm_output *output,
}
EXPORT_SYMBOL(drm_output_attach_property);
+int drm_output_property_set_value(struct drm_output *output,
+ struct drm_property *property, uint64_t value)
+{
+ int i;
+
+ for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) {
+ if (output->property_ids[i] == property->id) {
+ output->property_values[i] = value;
+ break;
+ }
+ }
+
+ if (i == DRM_OUTPUT_MAX_PROPERTY)
+ return -EINVAL;
+ return 0;
+}
+EXPORT_SYMBOL(drm_output_property_set_value);
+
int drm_mode_getproperty_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
@@ -2052,17 +2071,17 @@ done:
return ret;
}
-static int drm_property_create_blob(struct drm_device *dev, int length,
- void *data)
+static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
+ void *data)
{
struct drm_property_blob *blob;
if (!length || !data)
- return -EINVAL;
+ return NULL;
blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
if (!blob)
- return -EINVAL;
+ return NULL;
blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob));
blob->length = length;
@@ -2072,7 +2091,7 @@ static int drm_property_create_blob(struct drm_device *dev, int length,
blob->id = drm_idr_get(dev, blob);
list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
- return blob->id;
+ return blob;
}
static void drm_property_destroy_blob(struct drm_device *dev,
@@ -2082,3 +2101,47 @@ static void drm_property_destroy_blob(struct drm_device *dev,
list_del(&blob->head);
kfree(blob);
}
+
+int drm_mode_getblob_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+ struct drm_mode_get_blob *out_resp = data;
+ struct drm_property_blob *blob;
+ int ret = 0;
+ void *blob_ptr;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ blob = idr_find(&dev->mode_config.crtc_idr, out_resp->blob_id);
+ if (!blob || (blob->id != out_resp->blob_id)) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (out_resp->length == blob->length) {
+ blob_ptr = (void *)(unsigned long)out_resp->data;
+ if (copy_to_user(blob_ptr, blob->data, blob->length)){
+ ret = -EFAULT;
+ goto done;
+ }
+ }
+ out_resp->length = blob->length;
+
+done:
+ mutex_unlock(&dev->mode_config.mutex);
+ return ret;
+}
+
+int drm_mode_output_update_edid_property(struct drm_output *output, unsigned char *edid)
+{
+ struct drm_device *dev = output->dev;
+ int ret = 0;
+ if (output->edid_blob_ptr)
+ drm_property_destroy_blob(dev, output->edid_blob_ptr);
+
+ output->edid_blob_ptr = drm_property_create_blob(output->dev, 128, edid);
+
+ ret = drm_output_property_set_value(output, dev->mode_config.edid_property, output->edid_blob_ptr->id);
+ return ret;
+}
+EXPORT_SYMBOL(drm_mode_output_update_edid_property);
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index d028f75f..2c77d9d7 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -236,8 +236,8 @@ struct drm_framebuffer {
struct drm_property_blob {
struct list_head head;
- unsigned int id;
unsigned int length;
+ unsigned int id;
void *data;
};
@@ -456,7 +456,7 @@ struct drm_output {
void *driver_private;
struct list_head user_modes;
-
+ struct drm_property_blob *edid_blob_ptr;
u32 property_ids[DRM_OUTPUT_MAX_PROPERTY];
uint64_t property_values[DRM_OUTPUT_MAX_PROPERTY];
};
@@ -547,7 +547,7 @@ extern int drm_mode_vrefresh(struct drm_display_mode *mode);
extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
int adjust_flags);
extern void drm_mode_output_list_update(struct drm_output *output);
-
+extern int drm_mode_output_update_edid_property(struct drm_output *output, unsigned char *edid);
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
extern bool drm_initial_config(struct drm_device *dev, bool cangrow);
extern void drm_framebuffer_set_object(struct drm_device *dev,
@@ -594,5 +594,7 @@ extern int drm_mode_detachmode_ioctl(struct drm_device *dev,
extern int drm_mode_getproperty_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
+extern int drm_mode_getblob_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
#endif /* __DRM_CRTC_H__ */
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index a88ae8b5..f8665be7 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -125,6 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_ROOT_ONLY),
diff --git a/linux-core/intel_crt.c b/linux-core/intel_crt.c
index d3ad4654..2ab6a27b 100644
--- a/linux-core/intel_crt.c
+++ b/linux-core/intel_crt.c
@@ -246,5 +246,4 @@ void intel_crt_init(struct drm_device *dev)
output->interlace_allowed = 0;
output->doublescan_allowed = 0;
- drm_output_attach_property(output, dev->mode_config.edid_property, 0);
}
diff --git a/linux-core/intel_modes.c b/linux-core/intel_modes.c
index 346cf1ac..f8bf496c 100644
--- a/linux-core/intel_modes.c
+++ b/linux-core/intel_modes.c
@@ -55,6 +55,7 @@ int intel_ddc_get_modes(struct drm_output *output)
edid = drm_get_edid(output, &intel_output->ddc_bus->adapter);
if (edid) {
+ drm_mode_output_update_edid_property(output, edid);
ret = drm_add_edid_modes(output, edid);
kfree(edid);
}
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 7649abd6..0c66f85c 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -980,11 +980,6 @@ struct drm_mode_property_enum {
unsigned char name[DRM_PROP_NAME_LEN];
};
-struct drm_mode_property_blob {
- uint64_t data_ptr;
- uint32_t length;
-};
-
struct drm_mode_get_property {
uint64_t values_ptr; /* values and blob lengths */
uint64_t enum_blob_ptr; /* enum and blob id ptrs */
@@ -997,6 +992,12 @@ struct drm_mode_get_property {
int count_enum_blobs;
};
+struct drm_mode_get_blob {
+ uint32_t blob_id;
+ uint32_t length;
+ uint64_t data;
+};
+
struct drm_mode_fb_cmd {
unsigned int buffer_id;
unsigned int width, height;
@@ -1111,7 +1112,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_GETPROPBLOB DRM_IOWR(0xA8, struct drm_mode_get_propblob)
+#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/modetest.c b/tests/mode/modetest.c
index 46f88d82..c396da41 100644
--- a/tests/mode/modetest.c
+++ b/tests/mode/modetest.c
@@ -75,9 +75,14 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
printf("%d ", props->values[j]);
printf("\n\tenums %d: \n", props->count_enums);
+
+ if (props->flags & DRM_MODE_PROP_BLOB) {
+ drmModePropertyBlobPtr blob;
- if (prop->flags & DRM_MODE_PROP_BLOB) {
-
+ blob = drmModeGetPropertyBlob(fd, output->prop_values[i]);
+
+ printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data);
+ drmModeFreePropertyBlob(blob);
} else {
for (j = 0; j < props->count_enums; j++) {