On Tue, Mar 20, 2012 at 10:48 AM, Paulo Zanoni <przanoni@xxxxxxxxx> wrote: > From: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> > > Code based on the connector properties code. > > Two new ioctls: > - DRM_IOCTL_MODE_CRTC_GETPROPERTIES > - DRM_IOCTL_MODE_CRTC_SETPROPERTY > > The i915 driver needs this for the rotation and overscan compensation > properties. Other drivers might need this too. > > v2: replace BUG_ON() for WARN(), fix bugs, add functions to get/set > the value > Is there any reason why these can't just be exposed as connector properties? While the hw features you are exposing are technically part of the crtc block, so are most of the existing connector properties (scalers, etc.). Plus, while the scalers/transforms are part of the crtc hw, they only really make sense on certain connectors. E.g., underscan isn't particularly useful on non-TMDS capable connectors. Alex > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> > --- > drivers/gpu/drm/drm_crtc.c | 150 ++++++++++++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/drm_drv.c | 4 +- > include/drm/drm.h | 2 + > include/drm/drm_crtc.h | 28 ++++++++- > include/drm/drm_mode.h | 13 ++++ > 5 files changed, 195 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 6260fc3..df00c29 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -2712,6 +2712,55 @@ int drm_connector_property_get_value(struct drm_connector *connector, > } > EXPORT_SYMBOL(drm_connector_property_get_value); > > +void drm_crtc_attach_property(struct drm_crtc *crtc, > + struct drm_property *property, uint64_t init_val) > +{ > + int i; > + > + for (i = 0; i < DRM_CRTC_MAX_PROPERTY; i++) { > + if (crtc->property_ids[i] == 0) { > + crtc->property_ids[i] = property->base.id; > + crtc->property_values[i] = init_val; > + return; > + } > + } > + > + WARN(1, "Failed to attach crtc property\n"); > +} > +EXPORT_SYMBOL(drm_crtc_attach_property); > + > +int drm_crtc_property_set_value(struct drm_crtc *crtc, > + struct drm_property *property, uint64_t value) > +{ > + int i; > + > + for (i = 0; i < DRM_CRTC_MAX_PROPERTY; i++) { > + if (crtc->property_ids[i] == property->base.id) { > + crtc->property_values[i] = value; > + return 0; > + } > + } > + > + return -EINVAL; > +} > +EXPORT_SYMBOL(drm_crtc_property_set_value); > + > +int drm_crtc_property_get_value(struct drm_crtc *crtc, > + struct drm_property *property, uint64_t *val) > +{ > + int i; > + > + for (i = 0; i < DRM_CRTC_MAX_PROPERTY; i++) { > + if (crtc->property_ids[i] == property->base.id) { > + *val = crtc->property_values[i]; > + return 0; > + } > + } > + > + return -EINVAL; > +} > +EXPORT_SYMBOL(drm_crtc_property_get_value); > + > int drm_mode_getproperty_ioctl(struct drm_device *dev, > void *data, struct drm_file *file_priv) > { > @@ -2983,6 +3032,107 @@ out: > return ret; > } > > +int drm_mode_crtc_get_properties_ioctl(struct drm_device *dev, void *data, > + struct drm_file *file_priv) > +{ > + struct drm_mode_crtc_get_properties *arg = data; > + struct drm_mode_object *obj; > + struct drm_crtc *crtc; > + 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->crtc_id, DRM_MODE_OBJECT_CRTC); > + if (!obj) { > + ret = -EINVAL; > + goto out; > + } > + crtc = obj_to_crtc(obj); > + > + for (props_count = 0; props_count < DRM_CRTC_MAX_PROPERTY && > + crtc->property_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(crtc->property_ids[i], > + props_ptr + copied)) { > + ret = -EFAULT; > + goto out; > + } > + if (put_user(crtc->property_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_crtc_set_property_ioctl(struct drm_device *dev, void *data, > + struct drm_file *file_priv) > +{ > + struct drm_mode_crtc_set_property *arg = data; > + struct drm_mode_object *obj; > + struct drm_property *property; > + struct drm_crtc *crtc; > + int ret = -EINVAL; > + int i; > + > + if (!drm_core_check_feature(dev, DRIVER_MODESET)) > + return -EINVAL; > + > + mutex_lock(&dev->mode_config.mutex); > + > + obj = drm_mode_object_find(dev, arg->crtc_id, DRM_MODE_OBJECT_CRTC); > + if (!obj) > + goto out; > + crtc = obj_to_crtc(obj); > + > + for (i = 0; i < DRM_CRTC_MAX_PROPERTY; i++) > + if (crtc->property_ids[i] == arg->prop_id) > + break; > + > + if (i == DRM_CRTC_MAX_PROPERTY) > + goto out; > + > + obj = drm_mode_object_find(dev, arg->prop_id, DRM_MODE_OBJECT_PROPERTY); > + if (!obj) > + goto out; > + property = obj_to_property(obj); > + > + if (!drm_property_change_is_valid(property, arg->value)) > + goto out; > + > + if (crtc->funcs->set_property) > + ret = crtc->funcs->set_property(crtc, property, arg->value); > + if (!ret) { > + crtc->property_values[i] = arg->value; > + } > +out: > + mutex_unlock(&dev->mode_config.mutex); > + return ret; > +} > + > int drm_mode_connector_attach_encoder(struct drm_connector *connector, > struct drm_encoder *encoder) > { > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c > index d166bd0..815e3a9 100644 > --- a/drivers/gpu/drm/drm_drv.c > +++ b/drivers/gpu/drm/drm_drv.c > @@ -159,7 +159,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_CRTC_GETPROPERTIES, drm_mode_crtc_get_properties_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), > + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CRTC_SETPROPERTY, drm_mode_crtc_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED) > }; > > #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) > diff --git a/include/drm/drm.h b/include/drm/drm.h > index 34a7b89..a397a93 100644 > --- a/include/drm/drm.h > +++ b/include/drm/drm.h > @@ -718,6 +718,8 @@ struct drm_get_cap { > #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_CRTC_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_crtc_get_properties) > +#define DRM_IOCTL_MODE_CRTC_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_crtc_set_property) > > /** > * Device specific ioctls should only be in their respective headers > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h > index 21681fe..a2d660d 100644 > --- a/include/drm/drm_crtc.h > +++ b/include/drm/drm_crtc.h > @@ -283,6 +283,8 @@ struct drm_encoder; > struct drm_pending_vblank_event; > struct drm_plane; > > +#define DRM_CRTC_MAX_PROPERTY 16 > + > /** > * drm_crtc_funcs - control CRTCs for a given device > * @reset: reset CRTC after state has been invalidate (e.g. resume) > @@ -297,7 +299,8 @@ struct drm_plane; > * @mode_fixup: fixup proposed mode > * @mode_set: set the desired mode on the CRTC > * @gamma_set: specify color ramp for CRTC > - * @destroy: deinit and free object. > + * @destroy: deinit and free object > + * @set_property: called when a property is changed > * > * The drm_crtc_funcs structure is the central CRTC management structure > * in the DRM. Each CRTC controls one or more connectors (note that the name > @@ -341,6 +344,9 @@ struct drm_crtc_funcs { > int (*page_flip)(struct drm_crtc *crtc, > struct drm_framebuffer *fb, > struct drm_pending_vblank_event *event); > + > + int (*set_property)(struct drm_crtc *crtc, > + struct drm_property *property, uint64_t val); > }; > > /** > @@ -360,6 +366,8 @@ struct drm_crtc_funcs { > * @framedur_ns: precise line timing > * @pixeldur_ns: precise pixel timing > * @helper_private: mid-layer private data > + * @property_ids: property tracking for this CRTC > + * @property_values: property values > * > * Each CRTC may have one or more connectors associated with it. This structure > * allows the CRTC to be controlled. > @@ -395,6 +403,9 @@ struct drm_crtc { > > /* if you are using the helper */ > void *helper_private; > + > + u32 property_ids[DRM_CRTC_MAX_PROPERTY]; > + uint64_t property_values[DRM_CRTC_MAX_PROPERTY]; > }; > > > @@ -895,6 +906,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_crtc_property_set_value(struct drm_crtc *crtc, > + struct drm_property *property, > + uint64_t value); > +extern int drm_crtc_property_get_value(struct drm_crtc *crtc, > + 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); > @@ -909,6 +926,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_crtc_attach_property(struct drm_crtc *crtc, > + 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, > @@ -1019,6 +1039,12 @@ 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_crtc_get_properties_ioctl(struct drm_device *dev, > + void *data, > + struct drm_file *file_priv); > +extern int drm_mode_crtc_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); > diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h > index 2a2acda..890b930 100644 > --- a/include/drm/drm_mode.h > +++ b/include/drm/drm_mode.h > @@ -252,6 +252,19 @@ struct drm_mode_connector_set_property { > __u32 connector_id; > }; > > +struct drm_mode_crtc_get_properties { > + __u64 props_ptr; > + __u64 prop_values_ptr; > + __u32 count_props; > + __u32 crtc_id; > +}; > + > +struct drm_mode_crtc_set_property { > + __u64 value; > + __u32 prop_id; > + __u32 crtc_id; > +}; > + > struct drm_mode_get_blob { > __u32 blob_id; > __u32 length; > -- > 1.7.9.1 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel