add property blobs and edid reporting support

This commit is contained in:
Dave Airlie 2007-12-06 10:44:51 +10:00
parent c9cda51af5
commit 67f6eb1eb8
9 changed files with 134 additions and 18 deletions

View 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);
}

View 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);

View 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);

View 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__ */

View 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),

View 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);
}

View 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);
}

View 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)

View 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++) {