Skip to content

Commit

Permalink
drm: add generic ioctls to get/set properties on any object
Browse files Browse the repository at this point in the history
Useless for connector properties (since they already have their own
ioctls), but useful when we add properties to CRTCs, planes and other
objects.

Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
Reviewed-by: Rob Clark <rob.clark@linaro.org>
Tested-by: Rob Clark <rob.clark@linaro.org>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Paulo Zanoni authored and Dave Airlie committed May 17, 2012
1 parent 7e3bdf4 commit c543188
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 1 deletion.
182 changes: 182 additions & 0 deletions drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2875,6 +2875,58 @@ int drm_connector_property_get_value(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_connector_property_get_value);

void drm_object_attach_property(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t init_val)
{
int i;

for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++) {
if (obj->properties->ids[i] == 0) {
obj->properties->ids[i] = property->base.id;
obj->properties->values[i] = init_val;
return;
}
}

WARN(1, "Failed to attach object property (type: 0x%x). Please "
"increase DRM_OBJECT_MAX_PROPERTY by 1 for each time you see "
"this message on the same object type.\n", obj->type);
}
EXPORT_SYMBOL(drm_object_attach_property);

int drm_object_property_set_value(struct drm_mode_object *obj,
struct drm_property *property, uint64_t val)
{
int i;

for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++) {
if (obj->properties->ids[i] == property->base.id) {
obj->properties->values[i] = val;
return 0;
}
}

return -EINVAL;
}
EXPORT_SYMBOL(drm_object_property_set_value);

int drm_object_property_get_value(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val)
{
int i;

for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++) {
if (obj->properties->ids[i] == property->base.id) {
*val = obj->properties->values[i];
return 0;
}
}

return -EINVAL;
}
EXPORT_SYMBOL(drm_object_property_get_value);

int drm_mode_getproperty_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
Expand Down Expand Up @@ -3148,6 +3200,136 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
return ret;
}

static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t value)
{
int ret = -EINVAL;
struct drm_connector *connector = obj_to_connector(obj);

/* Do DPMS ourselves */
if (property == connector->dev->mode_config.dpms_property) {
if (connector->funcs->dpms)
(*connector->funcs->dpms)(connector, (int)value);
ret = 0;
} else if (connector->funcs->set_property)
ret = connector->funcs->set_property(connector, property, value);

/* store the property value if successful */
if (!ret)
drm_connector_property_set_value(connector, property, value);
return ret;
}

int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_obj_get_properties *arg = data;
struct drm_mode_object *obj;
int ret = 0;
int i;
int copied = 0;
int props_count = 0;
uint32_t __user *props_ptr;
uint64_t __user *prop_values_ptr;

if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;

mutex_lock(&dev->mode_config.mutex);

obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
if (!obj) {
ret = -EINVAL;
goto out;
}
if (!obj->properties) {
ret = -EINVAL;
goto out;
}

/* Assume [ prop, 0, prop ] won't happen (if we ever delete properties,
* we need to remove the gap inside the array). */
for (props_count = 0; props_count < DRM_OBJECT_MAX_PROPERTY &&
obj->properties->ids[props_count] != 0; props_count++)
;

/* This ioctl is called twice, once to determine how much space is
* needed, and the 2nd time to fill it. */
if ((arg->count_props >= props_count) && props_count) {
copied = 0;
props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
prop_values_ptr = (uint64_t __user *)(unsigned long)
(arg->prop_values_ptr);
for (i = 0; i < props_count; i++) {
if (put_user(obj->properties->ids[i],
props_ptr + copied)) {
ret = -EFAULT;
goto out;
}
if (put_user(obj->properties->values[i],
prop_values_ptr + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
}
arg->count_props = props_count;
out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}

int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_obj_set_property *arg = data;
struct drm_mode_object *arg_obj;
struct drm_mode_object *prop_obj;
struct drm_property *property;
int ret = -EINVAL;
int i;

if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;

mutex_lock(&dev->mode_config.mutex);

arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
if (!arg_obj)
goto out;
if (!arg_obj->properties)
goto out;

for (i = 0; i < DRM_OBJECT_MAX_PROPERTY; i++)
if (arg_obj->properties->ids[i] == arg->prop_id)
break;

if (i == DRM_OBJECT_MAX_PROPERTY)
goto out;

prop_obj = drm_mode_object_find(dev, arg->prop_id,
DRM_MODE_OBJECT_PROPERTY);
if (!prop_obj)
goto out;
property = obj_to_property(prop_obj);

if (!drm_property_change_is_valid(property, arg->value))
goto out;

switch (arg_obj->type) {
case DRM_MODE_OBJECT_CONNECTOR:
ret = drm_mode_connector_set_obj_prop(arg_obj, property,
arg->value);
break;
}

out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}

int drm_mode_connector_attach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder)
{
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
};

#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
Expand Down
2 changes: 2 additions & 0 deletions include/drm/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,8 @@ struct drm_prime_handle {
#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane)
#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane)
#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)

/**
* Device specific ioctls should only be in their respective headers
Expand Down
13 changes: 13 additions & 0 deletions include/drm/drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,12 @@ extern int drm_connector_property_set_value(struct drm_connector *connector,
extern int drm_connector_property_get_value(struct drm_connector *connector,
struct drm_property *property,
uint64_t *value);
extern int drm_object_property_set_value(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t val);
extern int drm_object_property_get_value(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t *value);
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
extern void drm_framebuffer_set_object(struct drm_device *dev,
unsigned long handle);
Expand All @@ -917,6 +923,9 @@ extern bool drm_crtc_in_use(struct drm_crtc *crtc);

extern void drm_connector_attach_property(struct drm_connector *connector,
struct drm_property *property, uint64_t init_val);
extern void drm_object_attach_property(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t init_val);
extern struct drm_property *drm_property_create(struct drm_device *dev, int flags,
const char *name, int num_values);
extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
Expand Down Expand Up @@ -1029,6 +1038,10 @@ extern int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);

extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
int *bpp);
Expand Down
15 changes: 15 additions & 0 deletions include/drm/drm_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,21 @@ struct drm_mode_connector_set_property {
__u32 connector_id;
};

struct drm_mode_obj_get_properties {
__u64 props_ptr;
__u64 prop_values_ptr;
__u32 count_props;
__u32 obj_id;
__u32 obj_type;
};

struct drm_mode_obj_set_property {
__u64 value;
__u32 prop_id;
__u32 obj_id;
__u32 obj_type;
};

struct drm_mode_get_blob {
__u32 blob_id;
__u32 length;
Expand Down

0 comments on commit c543188

Please sign in to comment.