add property blobs and edid reporting support
authorDave Airlie <airlied@redhat.com>
Thu, 6 Dec 2007 00:44:51 +0000 (10:44 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 6 Dec 2007 00:44:51 +0000 (10:44 +1000)
libdrm/xf86drmMode.c
libdrm/xf86drmMode.h
linux-core/drm_crtc.c
linux-core/drm_crtc.h
linux-core/drm_drv.c
linux-core/intel_crt.c
linux-core/intel_modes.c
shared-core/drm.h
tests/mode/modetest.c

index f4ec004..03bd15f 100644 (file)
@@ -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);
+}
index e936044..6fcf6a1 100644 (file)
@@ -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);
index a3aa783..7084423 100644 (file)
@@ -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);
index d028f75..2c77d9d 100644 (file)
@@ -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__ */
 
index a88ae8b..f8665be 100644 (file)
@@ -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),
index d3ad465..2ab6a27 100644 (file)
@@ -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);
 }
index 346cf1a..f8bf496 100644 (file)
@@ -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);
        }
index 7649abd..0c66f85 100644 (file)
@@ -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)
 
index 46f88d8..c396da4 100644 (file)
@@ -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++) {