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);
+}
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);
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;
}
EXPORT_SYMBOL(drm_property_destroy);
-
int drm_output_attach_property(struct drm_output *output,
struct drm_property *property, uint64_t init_val)
{
}
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)
{
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;
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,
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);
struct drm_property_blob {
struct list_head head;
- unsigned int id;
unsigned int length;
+ unsigned int id;
void *data;
};
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];
};
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,
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__ */
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),
output->interlace_allowed = 0;
output->doublescan_allowed = 0;
- drm_output_attach_property(output, dev->mode_config.edid_property, 0);
}
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);
}
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 */
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;
#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)
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++) {