summaryrefslogtreecommitdiff
path: root/linux-core
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 /linux-core
parentc9cda51af5a8bea1d30ce575ae260de52950fe2f (diff)
add property blobs and edid reporting support
Diffstat (limited to 'linux-core')
-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
5 files changed, 76 insertions, 10 deletions
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);
}