Atomic Properties (v2)
cover Atomic Properties (v2)
Welcome to v2 of the atomic-properties series. This is the part where we start exposing atomic to userspace. This patchset applies on top of the topic/atomic-core branch. A few patches from v1 of the patchset have already been picked up on topic/atomic-core (and are not re-sent).
The first step here is to, for drivers supporting atomic, expose all the core plane/CRTC/connector state as properties. Once this is in place, all that remains is the atomic ioctl to allow userspace to atomically set a bunch of properties on a bunch of objects (last patch).
All of the core properties have their set/get/check's handled by the drm_atomic core, so drivers needn't be bothered about that.
NOTE: that there is one notable omission here. The 'MODE' property on the CRTC. Without this, you can do atomic pageflip but not yet atomic modeset. I am debating between three paths for handling MODE:
1) Add back blob property support to atomic ioctl
2) Add ioctls to create/destroy blob properties, and then simply pass blob property id to atomic ioctl.
3) Stick our head in the sands and expose mode as a bunch of descrete properties.
Of these, at the moment I prefer #2, since it is more consistent with how userspace currently reads blob properties, and it avoids making the atomic ioctl function even more gnarly.
The whole patchset can also be found at:
http://cgit.freedesktop.org/~robclark/linux/log/?h=atomic-properties
git://people.freedesktop.org/~robclark/linux atomic-properties
Compared to v1 of this patchset:
1) few bits of comments/re-arranging
2) drop modeconfig->funcs vfunc for set_property, instead use a driver feature flag so core can figure out whether to take atomic property or legacy property path
3) add DRM_CLIENT_CAP_ATOMIC to hide atomic properties from legacy userspace
4) add drm.atomic moduleparam to (for now) hide the atomic ioctl while it is still experimental.
5) misc bits of refactoring, and addressing other review comments.
Rob Clark (11):
drm: add atomic_set_property wrappers
drm: add atomic_get_property
drm: tweak getconnector locking
drm: refactor getproperties/getconnector
drm: add atomic properties
drm/atomic: atomic_check functions
drm: small property creation cleanup
drm/atomic: atomic plane properties
drm/atomic: atomic connector properties
drm/msm: atomic property support
drm: Atomic modeset ioctl
Documentation/DocBook/drm.tmpl | 91 ++- drivers/gpu/drm/drm_atomic.c | 757 ++++++++++++++++++++- drivers/gpu/drm/drm_atomic_helper.c | 16 +- drivers/gpu/drm/drm_crtc.c | 274 +++++--- drivers/gpu/drm/drm_drv.c | 4 + drivers/gpu/drm/drm_ioctl.c | 11 + drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 2 + drivers/gpu/drm/msm/msm_drv.c | 1 + include/drm/drmP.h | 4 + include/drm/drm_atomic.h | 21 + include/drm/drm_crtc.h | 43 +- include/uapi/drm/drm.h | 8 + include/uapi/drm/drm_mode.h | 30 + 18 files changed, 1148 insertions(+), 119 deletions(-)
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/11 drm: add atomic_set_property wrappers
As we add properties for all the standard plane/crtc/connector attributes (in preperation for the atomic ioctl), we are going to want to handle core state in core (rather than per driver). Intercepting the core properties will be easier if the atomic_set_property vfuncs are not called directly, but instead have a mandatory wrapper function (which will later serve as the point to intercept core properties).
v2: more verbose comments and copypasta comment fix
--- drivers/gpu/drm/drm_atomic.c | 90 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 12 ++--- include/drm/drm_atomic.h | 9 ++++ include/drm/drm_crtc.h | 3 ++ 4 files changed, 108 insertions(+), 6 deletions(-)
drivers/gpu/drm/drm_atomic.c +90 -0
@@ -217,6 +217,32 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,EXPORT_SYMBOL (drm_atomic_get_crtc_state);/** +* drm_atomic_crtc_set_property - set property on CRTC +* @crtc: the drm CRTC to set a property on +* @state: the state object to update with the new property value +* @property: the property to set +* @val: the new property value +* +* Use this instead of calling crtc->atomic_set_property directly. +* This function handles generic/core properties and calls out to +* driver's ->atomic_set_property() for driver properties. To ensure +* consistent behavior you must call this function rather than the +* driver hook directly. +* +* RETURNS: +* Zero on success, error code on failure +*/ +int drm_atomic_crtc_set_property (struct drm_crtc *crtc, +struct drm_crtc_state *state,struct drm_property *property, +uint64_t val) +{ +if (crtc->funcs->atomic_set_property) +return crtc->funcs->atomic_set_property (crtc, state, property, val); +return -EINVAL ; +} +EXPORT_SYMBOL (drm_atomic_crtc_set_property); + +/** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object * @plane: plane to get state object for
@@ -272,6 +298,32 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,EXPORT_SYMBOL (drm_atomic_get_plane_state);/** +* drm_atomic_plane_set_property - set property on plane +* @plane: the drm plane to set a property on +* @state: the state object to update with the new property value +* @property: the property to set +* @val: the new property value +* +* Use this instead of calling plane->atomic_set_property directly. +* This function handles generic/core properties and calls out to +* driver's ->atomic_set_property() for driver properties. To ensure +* consistent behavior you must call this function rather than the +* driver hook directly. +* +* RETURNS: +* Zero on success, error code on failure +*/ +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state,struct drm_property *property, +uint64_t val) +{ +if (plane->funcs->atomic_set_property) +return plane->funcs->atomic_set_property (plane, state, property, val); +return -EINVAL ; +} +EXPORT_SYMBOL (drm_atomic_plane_set_property); + +/** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object * @connector: connector to get state object for
@@ -343,6 +395,44 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,EXPORT_SYMBOL (drm_atomic_get_connector_state);/** +* drm_atomic_connector_set_property - set property on connector. +* @connector: the drm connector to set a property on +* @state: the state object to update with the new property value +* @property: the property to set +* @val: the new property value +* +* Use this instead of calling connector->atomic_set_property directly. +* This function handles generic/core properties and calls out to +* driver's ->atomic_set_property() for driver properties. To ensure +* consistent behavior you must call this function rather than the +* driver hook directly. +* +* RETURNS: +* Zero on success, error code on failure +*/ +int drm_atomic_connector_set_property (struct drm_connector *connector, +struct drm_connector_state *state,struct drm_property *property, +uint64_t val) +{ +struct drm_device *dev = connector->dev; +struct drm_mode_config *config = &dev->mode_config; + +if (property == config->dpms_property) { +/* setting DPMS property requires special handling, which +* is done in legacy setprop path for us. Disallow (for +* now?) atomic writes to DPMS property: +*/ +return -EINVAL ; + }else if (connector->funcs->atomic_set_property) { +return connector->funcs->atomic_set_property (connector, + state, property, val); + }else { +return -EINVAL ; + } +} +EXPORT_SYMBOL (drm_atomic_connector_set_property); + +/** * drm_atomic_set_crtc_for_plane - set crtc for plane * @plane_state: the plane whose incoming state to update * @crtc: crtc to use for the plane
drivers/gpu/drm/drm_atomic_helper.c +6 -6
@@ -1613,8 +1613,8 @@ retry: goto fail; } - ret = crtc->funcs->atomic_set_property (crtc, crtc_state, - property, val); + ret =drm_atomic_crtc_set_property (crtc, crtc_state, + property, val);if (ret) goto fail;
@@ -1672,8 +1672,8 @@ retry: goto fail; } - ret = plane->funcs->atomic_set_property (plane, plane_state, - property, val); + ret =drm_atomic_plane_set_property (plane, plane_state, + property, val);if (ret) goto fail;
@@ -1731,8 +1731,8 @@ retry: goto fail; } - ret = connector->funcs->atomic_set_property (connector, connector_state, - property, val); + ret =drm_atomic_connector_set_property (connector, connector_state, + property, val);if (ret) goto fail;
include/drm/drm_atomic.h +9 -0
@@ -38,12 +38,21 @@ void drm_atomic_state_free(struct drm_atomic_state *state);struct drm_crtc_state *__must_check drm_atomic_get_crtc_state (struct drm_atomic_state *state,struct drm_crtc *crtc); +int drm_atomic_crtc_set_property (struct drm_crtc *crtc, +struct drm_crtc_state *state,struct drm_property *property, +uint64_t val);struct drm_plane_state *__must_check drm_atomic_get_plane_state (struct drm_atomic_state *state,struct drm_plane *plane); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state,struct drm_property *property, +uint64_t val);struct drm_connector_state *__must_check drm_atomic_get_connector_state (struct drm_atomic_state *state,struct drm_connector *connector); +int drm_atomic_connector_set_property (struct drm_connector *connector, +struct drm_connector_state *state,struct drm_property *property, +uint64_t val); int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
include/drm/drm_crtc.h +3 -0
@@ -311,6 +311,7 @@ struct drm_crtc_state {* @atomic_duplicate_state: duplicate the atomic state for this CRTC * @atomic_destroy_state: destroy an atomic state for this CRTC * @atomic_set_property: set a property on an atomic state for this CRTC +* (do not call directly, use drm_atomic_crtc_set_property()) * * 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
@@ -497,6 +498,7 @@ struct drm_connector_state {* @atomic_duplicate_state: duplicate the atomic state for this connector * @atomic_destroy_state: destroy an atomic state for this connector * @atomic_set_property: set a property on an atomic state for this connector +* (do not call directly, use drm_atomic_connector_set_property()) * * Each CRTC may have one or more connectors attached to it. The functions * below allow the core DRM code to control connectors, enumerate available modes,
@@ -760,6 +762,7 @@ struct drm_plane_state {* @atomic_duplicate_state: duplicate the atomic state for this plane * @atomic_destroy_state: destroy an atomic state for this plane * @atomic_set_property: set a property on an atomic state for this plane +* (do not call directly, use drm_atomic_plane_set_property()) */ struct drm_plane_funcs { int (*update_plane)(struct drm_plane *plane,
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/11 drm: add atomic_get_property
In reply to Rob ClarkSince we won't be using the obj->properties->values[] array to shadow property values for atomic drivers, we are going to need a vfunc for getting prop values. Add that along w/ mandatory wrapper fxns.
v2: more comments and copypasta comment typo fix
--- drivers/gpu/drm/drm_atomic.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic.h | 9 +++++ include/drm/drm_crtc.h | 18 +++++++++ 3 files changed, 115 insertions(+)
drivers/gpu/drm/drm_atomic.c +88 -0
@@ -243,6 +243,32 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,EXPORT_SYMBOL (drm_atomic_crtc_set_property);/** +* drm_atomic_crtc_get_property - get property on CRTC +* @crtc: the drm CRTC to get a property on +* @state: the state object with the property value to read +* @property: the property to get +* @val: the property value (returned by reference) +* +* Use this instead of calling crtc->atomic_get_property directly. +* This function handles generic/core properties and calls out to +* driver's ->atomic_get_property() for driver properties. To ensure +* consistent behavior you must call this function rather than the +* driver hook directly. +* +* RETURNS: +* Zero on success, error code on failure +*/ +int drm_atomic_crtc_get_property (struct drm_crtc *crtc, +const struct drm_crtc_state *state, +struct drm_property *property,uint64_t *val) +{ +if (crtc->funcs->atomic_get_property) +return crtc->funcs->atomic_get_property (crtc, state, property, val); +return -EINVAL ; +} +EXPORT_SYMBOL (drm_atomic_crtc_get_property); + +/** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object * @plane: plane to get state object for
@@ -324,6 +350,32 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,EXPORT_SYMBOL (drm_atomic_plane_set_property);/** +* drm_atomic_plane_get_property - get property on plane +* @plane: the drm plane to get a property on +* @state: the state object with the property value to read +* @property: the property to get +* @val: the property value (returned by reference) +* +* Use this instead of calling plane->atomic_get_property directly. +* This function handles generic/core properties and calls out to +* driver's ->atomic_get_property() for driver properties. To ensure +* consistent behavior you must call this function rather than the +* driver hook directly. +* +* RETURNS: +* Zero on success, error code on failure +*/ +int drm_atomic_plane_get_property (struct drm_plane *plane, +const struct drm_plane_state *state, +struct drm_property *property,uint64_t *val) +{ +if (plane->funcs->atomic_get_property) +return plane->funcs->atomic_get_property (plane, state, property, val); +return -EINVAL ; +} +EXPORT_SYMBOL (drm_atomic_plane_get_property); + +/** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object * @connector: connector to get state object for
@@ -433,6 +485,42 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,EXPORT_SYMBOL (drm_atomic_connector_set_property);/** +* drm_atomic_connector_get_property - get property on connector +* @connector: the drm connector to get a property on +* @state: the state object with the property value to read +* @property: the property to get +* @val: the property value (returned by reference) +* +* Use this instead of calling connector->atomic_get_property directly. +* This function handles generic/core properties and calls out to +* driver's ->atomic_get_property() for driver properties. To ensure +* consistent behavior you must call this function rather than the +* driver hook directly. +* +* RETURNS: +* Zero on success, error code on failure +*/ +int drm_atomic_connector_get_property (struct drm_connector *connector, +const struct drm_connector_state *state, +struct drm_property *property,uint64_t *val) +{ +struct drm_device *dev = connector->dev; +struct drm_mode_config *config = &dev->mode_config; + +if (property == config->dpms_property) { + *val = connector->dpms; + }else if (connector->funcs->atomic_get_property) { +return connector->funcs->atomic_get_property (connector, + state, property, val); + }else { +return -EINVAL ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_atomic_connector_get_property); + +/** * drm_atomic_set_crtc_for_plane - set crtc for plane * @plane_state: the plane whose incoming state to update * @crtc: crtc to use for the plane
include/drm/drm_atomic.h +9 -0
@@ -41,18 +41,27 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,int drm_atomic_crtc_set_property (struct drm_crtc *crtc,struct drm_crtc_state *state,struct drm_property *property,uint64_t val); +int drm_atomic_crtc_get_property (struct drm_crtc *crtc, +const struct drm_crtc_state *state, +struct drm_property *property,uint64_t *val);struct drm_plane_state *__must_check drm_atomic_get_plane_state (struct drm_atomic_state *state,struct drm_plane *plane);int drm_atomic_plane_set_property (struct drm_plane *plane,struct drm_plane_state *state,struct drm_property *property,uint64_t val); +int drm_atomic_plane_get_property (struct drm_plane *plane, +const struct drm_plane_state *state, +struct drm_property *property,uint64_t *val);struct drm_connector_state *__must_check drm_atomic_get_connector_state (struct drm_atomic_state *state,struct drm_connector *connector);int drm_atomic_connector_set_property (struct drm_connector *connector,struct drm_connector_state *state,struct drm_property *property,uint64_t val); +int drm_atomic_connector_get_property (struct drm_connector *connector, +const struct drm_connector_state *state, +struct drm_property *property,uint64_t *val); int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
include/drm/drm_crtc.h +18 -0
@@ -312,6 +312,8 @@ struct drm_crtc_state {* @atomic_destroy_state: destroy an atomic state for this CRTC * @atomic_set_property: set a property on an atomic state for this CRTC * (do not call directly, use drm_atomic_crtc_set_property()) +* @atomic_get_property: get a property on an atomic state for this CRTC +* (do not call directly, use drm_atomic_crtc_get_property()) * * 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
@@ -371,6 +373,10 @@ struct drm_crtc_funcs {struct drm_crtc_state *state, struct drm_property *property, uint64_t val); +int (*atomic_get_property)(struct drm_crtc *crtc, +const struct drm_crtc_state *state, +struct drm_property *property, +uint64_t *val); };/**
@@ -499,6 +505,8 @@ struct drm_connector_state {* @atomic_destroy_state: destroy an atomic state for this connector * @atomic_set_property: set a property on an atomic state for this connector * (do not call directly, use drm_atomic_connector_set_property()) +* @atomic_get_property: get a property on an atomic state for this connector +* (do not call directly, use drm_atomic_connector_get_property()) * * Each CRTC may have one or more connectors attached to it. The functions * below allow the core DRM code to control connectors, enumerate available modes,
@@ -532,6 +540,10 @@ struct drm_connector_funcs {struct drm_connector_state *state, struct drm_property *property, uint64_t val); +int (*atomic_get_property)(struct drm_connector *connector, +const struct drm_connector_state *state, +struct drm_property *property, +uint64_t *val); };/**
@@ -763,6 +775,8 @@ struct drm_plane_state {* @atomic_destroy_state: destroy an atomic state for this plane * @atomic_set_property: set a property on an atomic state for this plane * (do not call directly, use drm_atomic_plane_set_property()) +* @atomic_get_property: get a property on an atomic state for this plane +* (do not call directly, use drm_atomic_plane_get_property()) */ struct drm_plane_funcs { int (*update_plane)(struct drm_plane *plane,
@@ -786,6 +800,10 @@ struct drm_plane_funcs {struct drm_plane_state *state, struct drm_property *property, uint64_t val); +int (*atomic_get_property)(struct drm_plane *plane, +const struct drm_plane_state *state, +struct drm_property *property, +uint64_t *val); };enum drm_plane_type {
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/11 drm: tweak getconnector locking
In reply to Rob ClarkWe need to hold connection_mutex as we read the properties. Easiest thing is just widen the scope where connection_mutex is held.
--- drivers/gpu/drm/drm_crtc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_crtc.c +2 -3
@@ -2031,6 +2031,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,DRM_DEBUG_KMS ("[CONNECTOR:%d:?]\n" , out_resp->connector_id);mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL ); connector =drm_connector_find (dev, out_resp->connector_id);if (!connector) {
@@ -2062,14 +2063,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out_resp->mm_height = connector->display_info.height_mm; out_resp->subpixel = connector->display_info.subpixel_order; out_resp->connection = connector->status; -drm_modeset_lock (&dev->mode_config.connection_mutex,NULL ); - encoder =drm_connector_get_encoder (connector);if (encoder) out_resp->encoder_id = encoder->base.id;else out_resp->encoder_id =0 ; -drm_modeset_unlock (&dev->mode_config.connection_mutex);/* * This ioctl is called twice, once to determine how much space is
@@ -2135,6 +2133,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out_resp->count_encoders = encoders_count; out: +drm_modeset_unlock (&dev->mode_config.connection_mutex);mutex_unlock (&dev->mode_config.mutex);return ret;
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 4/11 drm: refactor getproperties/getconnector
In reply to Rob ClarkBoth need to iterate a mode objects properties. Split that out into a helper shared by both ioctl handlers, since this is going to become more complicated when we add atomic properties (which will need filtering from legacy userspace).
--- drivers/gpu/drm/drm_crtc.c | 105 ++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 63 deletions(-)
drivers/gpu/drm/drm_crtc.c +42 -63
@@ -1991,6 +1991,38 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connereturn connector->encoder; } +/* helper for getconnector and getproperties ioctls */ +static int get_properties (struct drm_mode_object *obj, +uint32_t __user *prop_ptr,uint64_t __user *prop_values, +uint32_t *arg_count_props) +{ +int props_count = obj->properties->count; +int i, ret, copied =0 ; + +if ((*arg_count_props >= props_count) && props_count) { + copied =0 ; +for (i =0 ; i < props_count; i++) { +struct drm_property *prop = obj->properties->properties[i]; +uint64_t val; + + ret =drm_object_property_get_value (obj, prop, &val); +if (ret) +return ret; + +if (put_user (prop->base.id, prop_ptr + copied)) +return -EFAULT ; + +if (put_user (val, prop_values + copied)) +return -EFAULT ; + + copied++; + } + } + *arg_count_props = props_count; + +return 0 ; +} +/** * drm_mode_getconnector - get connector configuration * @dev: drm device for the ioctl
@@ -2012,15 +2044,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,struct drm_encoder *encoder;struct drm_display_mode *mode;int mode_count =0 ; -int props_count =0 ;int encoders_count =0 ;int ret =0 ;int copied =0 ;int i;struct drm_mode_modeinfo u_mode;struct drm_mode_modeinfo __user *mode_ptr; -uint32_t __user *prop_ptr; -uint64_t __user *prop_values;uint32_t __user *encoder_ptr;if (!drm_core_check_feature (dev,DRIVER_MODESET ))
@@ -2039,8 +2068,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, goto out; } - props_count = connector->properties.count; -for (i =0 ; i <DRM_CONNECTOR_MAX_ENCODER ; i++)if (connector->encoder_ids[i] !=0 ) encoders_count++;
@@ -2091,30 +2118,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, } out_resp->count_modes = mode_count; -if ((out_resp->count_props >= props_count) && props_count) { - copied =0 ; - prop_ptr = (uint32_t __user *)(unsigned long )(out_resp->props_ptr); - prop_values = (uint64_t __user *)(unsigned long )(out_resp->prop_values_ptr); -for (i =0 ; i < connector->properties.count; i++) { -struct drm_property *prop = connector->properties.properties[i]; -uint64_t val; - - ret =drm_object_property_get_value (&connector->base, prop, &val); -if (ret) - goto out; - -if (put_user (prop->base.id, prop_ptr + copied)) { - ret = -EFAULT ; - goto out; - } -if (put_user (val, prop_values + copied)) { - ret = -EFAULT ; - goto out; - } - copied++; - } - } - out_resp->count_props = props_count; + ret =get_properties (&connector->base, + (uint32_t __user *)(unsigned long )(out_resp->props_ptr), + (uint64_t __user *)(unsigned long )(out_resp->prop_values_ptr), + &out_resp->count_props); +if (ret) + goto out;if ((out_resp->count_encoders >= encoders_count) && encoders_count) { copied =0 ;
@@ -4388,11 +4397,6 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,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 ;
@@ -4409,36 +4413,11 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, goto out; } - props_count = obj->properties->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++) { -struct drm_property *prop = obj->properties->properties[i]; -uint64_t val; - - ret =drm_object_property_get_value (obj, prop, &val); -if (ret) - goto out; + ret =get_properties (obj, + (uint32_t __user *)(unsigned long )(arg->props_ptr), + (uint64_t __user *)(unsigned long )(arg->prop_values_ptr), + &arg->count_props); -if (put_user (prop->base.id, props_ptr + copied)) { - ret = -EFAULT ; - goto out; - } - -if (put_user (val, prop_values_ptr + copied)) { - ret = -EFAULT ; - goto out; - } - copied++; - } - } - arg->count_props = props_count; out:drm_modeset_unlock_all (dev);return ret;
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 5/11 drm: add atomic properties
In reply to Rob ClarkOnce a driver is using atomic helpers for modeset, the next step is to switch over to atomic properties. To do this, make sure that any modeset objects have their ->atomic_{get,set}_property() vfuncs suitably populated if they have custom properties (you did already remember to plug in atomic-helper func for the legacy ->set_property() vfuncs, right?), and then set DRIVER_ATOMIC bit in driver_features flag.
A new cap is introduced, DRM_CLIENT_CAP_ATOMIC, for the purposes of shielding legacy userspace from atomic properties. Mostly for the benefit of legacy DDX drivers that do silly things like getting/setting each property at startup (since some of the new atomic properties will be able to trigger modeset).
--- Documentation/DocBook/drm.tmpl | 8 ++++++++ drivers/gpu/drm/drm_atomic.c | 45 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 31 ++++++++++++++++++++++------- drivers/gpu/drm/drm_drv.c | 4 ++++ drivers/gpu/drm/drm_ioctl.c | 10 ++++++++++ include/drm/drmP.h | 4 ++++ include/drm/drm_atomic.h | 3 +++ include/drm/drm_crtc.h | 2 +- include/uapi/drm/drm.h | 7 +++++++ include/uapi/drm/drm_mode.h | 7 +++++++ 10 files changed, 113 insertions(+), 8 deletions(-)
Documentation/DocBook/drm.tmpl +8 -0
@@ -239,6 +239,14 @@ Driver supports dedicated render nodes. </para></listitem> </varlistentry> + <varlistentry> + <term>DRIVER_ATOMIC</term> + <listitem><para> + Driver supports atomic properties. In this case the driver + must implement appropriate obj->atomic_get_property() vfuncs + for any modeset objects with driver specific properties. + </para></listitem> + </varlistentry> </variablelist> </sect3> <sect3>
drivers/gpu/drm/drm_atomic.c +45 -0
51 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +24 -7
@@ -38,6 +38,7 @@#include <drm/drm_edid.h> #include <drm/drm_fourcc.h> #include <drm/drm_modeset_lock.h> +#include <drm/drm_atomic.h> #include "drm_crtc_internal.h" #include "drm_internal.h"
@@ -1992,19 +1993,25 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *conne }/* helper for getconnector and getproperties ioctls */ -static int get_properties (struct drm_mode_object *obj, +static int get_properties (struct drm_mode_object *obj,bool atomic,uint32_t __user *prop_ptr,uint64_t __user *prop_values,uint32_t *arg_count_props) { -int props_count = obj->properties->count; -int i, ret, copied =0 ; +int props_count; +int i, ret, copied; + + props_count = obj->properties->count; +if (!atomic) + props_count -= obj->properties->atomic_count;if ((*arg_count_props >= props_count) && props_count) { - copied =0 ; -for (i =0 ; i < props_count; i++) { +for (i =0 , copied =0 ; copied < props_count; i++) {struct drm_property *prop = obj->properties->properties[i];uint64_t val; +if ((prop->flags &DRM_CLIENT_CAP_ATOMIC ) && !atomic) +continue ; + ret =drm_object_property_get_value (obj, prop, &val);if (ret)return ret;
@@ -2118,7 +2125,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, } out_resp->count_modes = mode_count; - ret =get_properties (&connector->base, + ret =get_properties (&connector->base, file_priv->atomic, (uint32_t __user *)(unsigned long )(out_resp->props_ptr), (uint64_t __user *)(unsigned long )(out_resp->prop_values_ptr), &out_resp->count_props);
@@ -3832,6 +3839,8 @@ void drm_object_attach_property(struct drm_mode_object *obj, obj->properties->properties[count] = property; obj->properties->values[count] = init_val; obj->properties->count++; +if (property->flags &DRM_MODE_PROP_ATOMIC ) + obj->properties->atomic_count++; }EXPORT_SYMBOL (drm_object_attach_property);
@@ -3883,6 +3892,14 @@ int drm_object_property_get_value(struct drm_mode_object *obj, {int i; +/* read-only properties bypass atomic mechanism and still store +* their value in obj->properties->values[].. mostly to avoid +* having to deal w/ EDID and similar props in atomic paths: +*/ +if (drm_core_check_feature (property->dev,DRIVER_ATOMIC ) && + !(property->flags &DRM_MODE_PROP_IMMUTABLE )) +return drm_atomic_get_property (obj, property, val); +for (i =0 ; i < obj->properties->count; i++) {if (obj->properties->properties[i] == property) { *val = obj->properties->values[i];
@@ -4413,7 +4430,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, goto out; } - ret =get_properties (obj, + ret =get_properties (obj, file_priv->atomic, (uint32_t __user *)(unsigned long )(arg->props_ptr), (uint64_t __user *)(unsigned long )(arg->prop_values_ptr), &arg->count_props);
drivers/gpu/drm/drm_drv.c +4 -0
@@ -40,15 +40,19 @@unsigned int drm_debug =0 ;/* 1 to enable debug output */ EXPORT_SYMBOL (drm_debug); +bool drm_atomic =0 ; +MODULE_AUTHOR (CORE_AUTHOR );MODULE_DESCRIPTION (CORE_DESC );MODULE_LICENSE ("GPL and additional rights" );MODULE_PARM_DESC (debug,"Enable debug output" ); +MODULE_PARM_DESC (atomic,"Enable experimental atomic KMS API" );MODULE_PARM_DESC (vblankoffdelay,"Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)" );MODULE_PARM_DESC (timestamp_precision_usec,"Max. error on timestamps [usecs]" );MODULE_PARM_DESC (timestamp_monotonic,"Use monotonic timestamps" );module_param_named (debug, drm_debug, int,0600 ); +module_param_named_unsafe (atomic, drm_atomic, bool,0600 );static DEFINE_SPINLOCK (drm_minor_lock);static struct idr drm_minors_idr;
drivers/gpu/drm/drm_ioctl.c +10 -0
@@ -345,6 +345,16 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)return -EINVAL ; file_priv->universal_planes = req->value;break ; +case DRM_CLIENT_CAP_ATOMIC : +/* for now, hide behind experimental drm.atomic moduleparam */ +if (!drm_atomic) +return -EINVAL ; +if (!drm_core_check_feature (dev,DRIVER_ATOMIC )) +return -EINVAL ; +if (req->value >1 ) +return -EINVAL ; + file_priv->atomic = req->value; +break ;default :return -EINVAL ; }
include/drm/drmP.h +4 -0
@@ -143,6 +143,7 @@ void drm_err(const char *format, ...);#define DRIVER_MODESET 0x2000#define DRIVER_PRIME 0x4000#define DRIVER_RENDER 0x8000 +#define DRIVER_ATOMIC 0x10000/***********************************************************************/ /** \name Macros to make printk easier */
@@ -283,6 +284,8 @@ struct drm_file {* in the plane list */ unsigned universal_planes:1; +/* true if client understands atomic properties */ + unsigned atomic:1;struct pid *pid;kuid_t uid;
@@ -950,6 +953,7 @@ extern void drm_master_put(struct drm_master **master);extern void drm_put_dev (struct drm_device *dev);extern void drm_unplug_dev (struct drm_device *dev);extern unsigned int drm_debug; +extern bool drm_atomic;/* Debugfs support */ #if defined(CONFIG_DEBUG_FS )
include/drm/drm_atomic.h +3 -0
@@ -63,6 +63,9 @@ int drm_atomic_connector_get_property(struct drm_connector *connector,const struct drm_connector_state *state, struct drm_property *property, uint64_t *val); +int drm_atomic_get_property (struct drm_mode_object *obj, +struct drm_property *property,uint64_t *val); +int __must_check drm_atomic_set_crtc_for_plane (struct drm_plane_state *plane_state,struct drm_crtc *crtc);
include/drm/drm_crtc.h +1 -1
@@ -63,7 +63,7 @@ struct drm_mode_object {#define DRM_OBJECT_MAX_PROPERTY 24struct drm_object_properties { -int count; +int count, atomic_count;/* NOTE: if we ever start dynamically destroying properties (ie. * not at drm_mode_config_cleanup() time), then we'd have to do * a better job of detaching property from mode objects to avoid
include/uapi/drm/drm.h +7 -0
@@ -654,6 +654,13 @@ struct drm_get_cap {*/ #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 +/** +* DRM_CLIENT_CAP_ATOMIC +* +* If set to 1, the DRM core will expose atomic properties to userspace +*/ +#define DRM_CLIENT_CAP_ATOMIC 3 +/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap {__u64 capability;
include/uapi/drm/drm_mode.h +7 -0
@@ -272,6 +272,13 @@ struct drm_mode_get_connector {#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) +/* the PROP_ATOMIC flag is used to hide properties from userspace that +* is not aware of atomic properties. This is mostly to work around +* older userspace (DDX drivers) that read/write each prop they find, +* witout being aware that this could be triggering a lengthy modeset. +*/ +#define DRM_MODE_PROP_ATOMIC 0x80000000 +struct drm_mode_property_enum {__u64 value;char name[DRM_PROP_NAME_LEN ];
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 6/11 drm/atomic: atomic_check functions
In reply to Rob ClarkAdd functions to check core plane/crtc state.
v2: comments, int-overflow checks, call from core rather than
helpers to be sure drivers can't find a way to bypass core checks
--- drivers/gpu/drm/drm_atomic.c | 139 ++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/drm_atomic_helper.c | 4 +- 2 files changed, 137 insertions(+), 6 deletions(-)
drivers/gpu/drm/drm_atomic.c +135 -4
@@ -269,6 +269,29 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc,EXPORT_SYMBOL (drm_atomic_crtc_get_property);/** +* drm_atomic_crtc_check - check crtc state +* @crtc: crtc to check +* @state: crtc state to check +* +* Provides core sanity checks for crtc state. +* +* RETURNS: +* Zero on success, error code on failure +*/ +static int drm_atomic_crtc_check (struct drm_crtc *crtc, +struct drm_crtc_state *state) +{ +/* NOTE: we explicitly don't enforce constraints such as primary +* layer covering entire screen, since that is something we want +* to allow (on hw that supports it). For hw that does not, it +* should be checked in driver's crtc->atomic_check() vfunc. +* +* TODO: Add generic modeset state checks once we support those. +*/ +return 0 ; +} + +/** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object * @plane: plane to get state object for
@@ -376,6 +399,82 @@ int drm_atomic_plane_get_property(struct drm_plane *plane,EXPORT_SYMBOL (drm_atomic_plane_get_property);/** +* drm_atomic_plane_check - check plane state +* @plane: plane to check +* @state: plane state to check +* +* Provides core sanity checks for plane state. +* +* RETURNS: +* Zero on success, error code on failure +*/ +static int drm_atomic_plane_check (struct drm_plane *plane, +struct drm_plane_state *state) +{ +unsigned int fb_width, fb_height; +unsigned int i; + +/* either *both* CRTC and FB must be set, or neither */ +if (WARN_ON (state->crtc && !state->fb)) { +DRM_DEBUG_KMS ("CRTC set but no FB\n" ); +return -EINVAL ; + }else if (WARN_ON (state->fb && !state->crtc)) { +DRM_DEBUG_KMS ("FB set but no CRTC\n" ); +return -EINVAL ; + } + +/* if disabled, we don't care about the rest of the state: */ +if (!state->crtc) +return 0 ; + +/* Check whether this plane is usable on this CRTC */ +if (!(plane->possible_crtcs &drm_crtc_mask (state->crtc))) { +DRM_DEBUG_KMS ("Invalid crtc for plane\n" ); +return -EINVAL ; + } + +/* Check whether this plane supports the fb pixel format. */ +for (i =0 ; i < plane->format_count; i++) +if (state->fb->pixel_format == plane->format_types[i]) +break ; +if (i == plane->format_count) { +DRM_DEBUG_KMS ("Invalid pixel format %s\n" , +drm_get_format_name (state->fb->pixel_format)); +return -EINVAL ; + } + +/* Give drivers some help against integer overflows */ +if (state->crtc_w >INT_MAX || + state->crtc_x >INT_MAX - (int32_t ) state->crtc_w || + state->crtc_h >INT_MAX || + state->crtc_y >INT_MAX - (int32_t ) state->crtc_h) { +DRM_DEBUG_KMS ("Invalid CRTC coordinates %ux%u+%d+%d\n" , + state->crtc_w, state->crtc_h, + state->crtc_x, state->crtc_y); +return -ERANGE ; + } + + fb_width = state->fb->width <<16 ; + fb_height = state->fb->height <<16 ; + +/* Make sure source coordinates are inside the fb. */ +if (state->src_w > fb_width || + state->src_x > fb_width - state->src_w || + state->src_h > fb_height || + state->src_y > fb_height - state->src_h) { +DRM_DEBUG_KMS ("Invalid source coordinates " +"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n" , + state->src_w >>16 , ((state->src_w &0xffff ) *15625 ) >>10 , + state->src_h >>16 , ((state->src_h &0xffff ) *15625 ) >>10 , + state->src_x >>16 , ((state->src_x &0xffff ) *15625 ) >>10 , + state->src_y >>16 , ((state->src_y &0xffff ) *15625 ) >>10 ); +return -ENOSPC ; + } + +return 0 ; +} + +/** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object * @connector: connector to get state object for
@@ -801,14 +900,46 @@ EXPORT_SYMBOL(drm_atomic_legacy_backoff);*/ int drm_atomic_check_only (struct drm_atomic_state *state) { -struct drm_mode_config *config = &state->dev->mode_config; +struct drm_device *dev = state->dev; +struct drm_mode_config *config = &dev->mode_config; +int nplanes = config->num_total_plane; +int ncrtcs = config->num_crtc; +int i, ret =0 ;DRM_DEBUG_KMS ("checking %p\n" , state); +for (i =0 ; i < nplanes; i++) { +struct drm_plane *plane = state->planes[i]; + +if (!plane) +continue ; + + ret =drm_atomic_plane_check (plane, state->plane_states[i]); +if (ret) { +DRM_DEBUG_KMS ("[PLANE:%d] atomic core check failed\n" , + plane->base.id); +return ret; + } + } + +for (i =0 ; i < ncrtcs; i++) { +struct drm_crtc *crtc = state->crtcs[i]; + +if (!crtc) +continue ; + + ret =drm_atomic_crtc_check (crtc, state->crtc_states[i]); +if (ret) { +DRM_DEBUG_KMS ("[CRTC:%d] atomic core check failed\n" , + crtc->base.id); +return ret; + } + } +if (config->funcs->atomic_check) -return config->funcs->atomic_check (state->dev, state); -else -return 0 ; + ret = config->funcs->atomic_check (state->dev, state); + +return ret; }EXPORT_SYMBOL (drm_atomic_check_only);
drivers/gpu/drm/drm_atomic_helper.c +2 -2
@@ -467,7 +467,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, ret = funcs->atomic_check (plane, plane_state);if (ret) { -DRM_DEBUG_KMS ("[PLANE:%d] atomic check failed\n" , +DRM_DEBUG_KMS ("[PLANE:%d] atomic driver check failed\n" , plane->base.id);return ret; }
@@ -487,7 +487,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, ret = funcs->atomic_check (crtc, state->crtc_states[i]);if (ret) { -DRM_DEBUG_KMS ("[CRTC:%d] atomic check failed\n" , +DRM_DEBUG_KMS ("[CRTC:%d] atomic driver check failed\n" , crtc->base.id);return ret; }
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 7/11 drm: small property creation cleanup
In reply to Rob ClarkGetting ready to add a lot more standard properties for atomic.
--- drivers/gpu/drm/drm_crtc.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-)
drivers/gpu/drm/drm_crtc.c +17 -10
@@ -1325,33 +1325,40 @@ EXPORT_SYMBOL(drm_plane_force_disable);static int drm_mode_create_standard_connector_properties (struct drm_device *dev) { -struct drm_property *edid; -struct drm_property *dpms; -struct drm_property *dev_path; +struct drm_property *prop;/* * Standard properties (apply to all connectors) */ - edid =drm_property_create (dev,DRM_MODE_PROP_BLOB | + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB |DRM_MODE_PROP_IMMUTABLE ,"EDID" ,0 ); - dev->mode_config.edid_property = edid; +if (!prop) +return -ENOMEM ; + dev->mode_config.edid_property = prop; - dpms =drm_property_create_enum (dev,0 , + prop =drm_property_create_enum (dev,0 ,"DPMS" , drm_dpms_enum_list,ARRAY_SIZE (drm_dpms_enum_list)); - dev->mode_config.dpms_property = dpms; +if (!prop) +return -ENOMEM ; + dev->mode_config.dpms_property = prop; - dev_path =drm_property_create (dev, + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB |DRM_MODE_PROP_IMMUTABLE ,"PATH" ,0 ); - dev->mode_config.path_property = dev_path; +if (!prop) +return -ENOMEM ; + dev->mode_config.path_property = prop; - dev->mode_config.tile_property =drm_property_create (dev, + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB |DRM_MODE_PROP_IMMUTABLE ,"TILE" ,0 ); +if (!prop) +return -ENOMEM ; + dev->mode_config.tile_property = prop;return 0 ; }
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 8/11 drm/atomic: atomic plane properties
In reply to Rob ClarkExpose the core plane state as properties, so they can be updated via atomic ioctl.
v2: atomic property flag
--- Documentation/DocBook/drm.tmpl | 74 ++++++++++++++++++++++++++++- drivers/gpu/drm/drm_atomic.c | 69 +++++++++++++++++++++++++-- drivers/gpu/drm/drm_crtc.c | 103 +++++++++++++++++++++++++++++++++-------- include/drm/drm_crtc.h | 10 ++++ 4 files changed, 230 insertions(+), 26 deletions(-)
Documentation/DocBook/drm.tmpl +72 -2
@@ -2572,7 +2572,7 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >Description/Restrictions</td> </tr> <tr> - <td rowspan="25" valign="top" >DRM</td> + <td rowspan="35" valign="top" >DRM</td> <td rowspan="4" valign="top" >Generic</td> <td valign="top" >“EDID”</td> <td valign="top" >BLOB | IMMUTABLE</td>
@@ -2602,7 +2602,7 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >Contains tiling information for a connector.</td> </tr> <tr> - <td rowspan="1" valign="top" >Plane</td> + <td rowspan="11" valign="top" >Plane</td> <td valign="top" >“type”</td> <td valign="top" >ENUM | IMMUTABLE</td> <td valign="top" >{ "Overlay", "Primary", "Cursor" }</td>
@@ -2610,6 +2610,76 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >Plane type</td> </tr> <tr> + <td valign="top" >“SRC_X”</td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=UINT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout source x coordinate in 16.16 fixed point (atomic)</td> + </tr> + <tr> + <td valign="top" >“SRC_Y”</td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=UINT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout source y coordinate in 16.16 fixed point (atomic)</td> + </tr> + <tr> + <td valign="top" >“SRC_W”</td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=UINT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout source width in 16.16 fixed point (atomic)</td> + </tr> + <tr> + <td valign="top" >“SRC_H”</td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=UINT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout source height in 16.16 fixed point (atomic)</td> + </tr> + <tr> + <td valign="top" >“CRTC_X”</td> + <td valign="top" >SIGNED_RANGE</td> + <td valign="top" >Min=INT_MIN, Max=INT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout CRTC (destination) x coordinate (atomic)</td> + </tr> + <tr> + <td valign="top" >“CRTC_Y”</td> + <td valign="top" >SIGNED_RANGE</td> + <td valign="top" >Min=INT_MIN, Max=INT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout CRTC (destination) y coordinate (atomic)</td> + </tr> + <tr> + <td valign="top" >“CRTC_W”</td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=UINT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout CRTC (destination) width (atomic)</td> + </tr> + <tr> + <td valign="top" >“CRTC_H”</td> + <td valign="top" >RANGE</td> + <td valign="top" >Min=0, Max=UINT_MAX</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout CRTC (destination) height (atomic)</td> + </tr> + <tr> + <td valign="top" >“FB_ID”</td> + <td valign="top" >OBJECT</td> + <td valign="top" >DRM_MODE_OBJECT_FB</td> + <td valign="top" >Plane</td> + <td valign="top" >Scanout framebuffer (atomic)</td> + </tr> + <tr> + <td valign="top" >“CRTC_ID”</td> + <td valign="top" >OBJECT</td> + <td valign="top" >DRM_MODE_OBJECT_CRTC</td> + <td valign="top" >Plane</td> + <td valign="top" >CRTC that plane is attached to (atomic)</td> + </tr> + <tr> <td rowspan="2" valign="top" >DVI-I</td> <td valign="top" >“subconnector”</td> <td valign="top" >ENUM</td>
drivers/gpu/drm/drm_atomic.c +64 -5
82 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +84 -19
140 lines not on this page · raw message
include/drm/drm_crtc.h +10 -0
@@ -1099,6 +1099,16 @@ struct drm_mode_config {struct drm_property *tile_property;struct drm_property *plane_type_property;struct drm_property *rotation_property; +struct drm_property *prop_src_x; +struct drm_property *prop_src_y; +struct drm_property *prop_src_w; +struct drm_property *prop_src_h; +struct drm_property *prop_crtc_x; +struct drm_property *prop_crtc_y; +struct drm_property *prop_crtc_w; +struct drm_property *prop_crtc_h; +struct drm_property *prop_fb_id; +struct drm_property *prop_crtc_id;/* DVI-I properties */ struct drm_property *dvi_i_subconnector_property;
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 9/11 drm/atomic: atomic connector properties
In reply to Rob ClarkExpose the core connector state as properties so it can be updated via atomic ioctl.
--- Documentation/DocBook/drm.tmpl | 11 +++++++++-- drivers/gpu/drm/drm_atomic.c | 9 +++++++-- drivers/gpu/drm/drm_crtc.c | 13 +++++++++---- 3 files changed, 25 insertions(+), 8 deletions(-)
Documentation/DocBook/drm.tmpl +9 -2
@@ -2572,8 +2572,8 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >Description/Restrictions</td> </tr> <tr> - <td rowspan="35" valign="top" >DRM</td> - <td rowspan="4" valign="top" >Generic</td> + <td rowspan="36" valign="top" >DRM</td> + <td rowspan="5" valign="top" >Connector</td> <td valign="top" >“EDID”</td> <td valign="top" >BLOB | IMMUTABLE</td> <td valign="top" >0</td>
@@ -2602,6 +2602,13 @@ void intel_crt_init(struct drm_device *dev) <td valign="top" >Contains tiling information for a connector.</td> </tr> <tr> + <td valign="top" >“CRTC_ID”</td> + <td valign="top" >OBJECT</td> + <td valign="top" >DRM_MODE_OBJECT_CRTC</td> + <td valign="top" >Connector</td> + <td valign="top" >CRTC that connector is attached to (atomic)</td> + </tr> + <tr> <td rowspan="11" valign="top" >Plane</td> <td valign="top" >“type”</td> <td valign="top" >ENUM | IMMUTABLE</td>
drivers/gpu/drm/drm_atomic.c +7 -2
@@ -627,7 +627,10 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,struct drm_device *dev = connector->dev;struct drm_mode_config *config = &dev->mode_config; -if (property == config->dpms_property) { +if (property == config->prop_crtc_id) { +struct drm_crtc *crtc =drm_crtc_find (dev, val); +return drm_atomic_set_crtc_for_connector (state, crtc); + }else if (property == config->dpms_property) {/* setting DPMS property requires special handling, which * is done in legacy setprop path for us. Disallow (for * now?) atomic writes to DPMS property:
@@ -665,7 +668,9 @@ int drm_atomic_connector_get_property(struct drm_connector *connector,struct drm_device *dev = connector->dev;struct drm_mode_config *config = &dev->mode_config; -if (property == config->dpms_property) { +if (property == config->prop_crtc_id) { + *val = (state->crtc) ? state->crtc->base.id :0 ; + }else if (property == config->dpms_property) { *val = connector->dpms; }else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector,
drivers/gpu/drm/drm_crtc.c +9 -4
@@ -831,6 +831,7 @@ int drm_connector_init(struct drm_device *dev, const struct drm_connector_funcs *funcs, int connector_type) { +struct drm_mode_config *config = &dev->mode_config;int ret;struct ida *connector_ida = &drm_connector_enum_list[connector_type].ida;
@@ -869,16 +870,20 @@ int drm_connector_init(struct drm_device *dev,/* We should add connectors at the end to avoid upsetting the connector * index too much. */ -list_add_tail (&connector->head, &dev->mode_config.connector_list); - dev->mode_config.num_connector++; +list_add_tail (&connector->head, &config->connector_list); + config->num_connector++;if (connector_type !=DRM_MODE_CONNECTOR_VIRTUAL )drm_object_attach_property (&connector->base, - dev->mode_config.edid_property, + config->edid_property,0 );drm_object_attach_property (&connector->base, - dev->mode_config.dpms_property,0 ); + config->dpms_property,0 ); + +if (drm_core_check_feature (dev,DRIVER_ATOMIC )) { +drm_object_attach_property (&connector->base, config->prop_crtc_id,0 ); + } connector->debugfs_entry =NULL ;
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 10/11 drm/msm: atomic property support
In reply to Rob ClarkNot too much to do, as we haven't exposed any driver custom properties yet, so all we need to do is plug in the helpers and set the feature flag.
--- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 2 ++ drivers/gpu/drm/msm/msm_drv.c | 1 + 7 files changed, 8 insertions(+)
drivers/gpu/drm/msm/hdmi/hdmi_connector.c +1 -0
@@ -399,6 +399,7 @@ static const struct drm_connector_funcs hdmi_connector_funcs = { .detect = hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = hdmi_connector_destroy, + .set_property = drm_atomic_helper_connector_set_property, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +1 -0
@@ -497,6 +497,7 @@ static const struct drm_crtc_funcs mdp4_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = mdp4_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, + .set_property = drm_atomic_helper_crtc_set_property, .cursor_set = mdp4_crtc_cursor_set, .cursor_move = mdp4_crtc_cursor_move, .reset = drm_atomic_helper_crtc_reset,
drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c +1 -0
@@ -98,6 +98,7 @@ static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { .detect = mdp4_lvds_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = mdp4_lvds_connector_destroy, + .set_property = drm_atomic_helper_connector_set_property, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +1 -0
@@ -60,6 +60,7 @@ static const struct drm_plane_funcs mdp4_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, .destroy = mdp4_plane_destroy, + .set_property = drm_atomic_helper_plane_set_property, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +1 -0
@@ -382,6 +382,7 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = mdp5_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, + .set_property = drm_atomic_helper_crtc_set_property, .reset = drm_atomic_helper_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +2 -0
@@ -137,6 +137,8 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, .destroy = mdp5_plane_destroy, + .set_property = drm_atomic_helper_plane_set_property, +/* TODO expose zpos property and override atomic_get/set: */ .reset = mdp5_plane_reset, .atomic_duplicate_state = mdp5_plane_duplicate_state, .atomic_destroy_state = mdp5_plane_destroy_state,
drivers/gpu/drm/msm/msm_drv.c +1 -0
@@ -827,6 +827,7 @@ static struct drm_driver msm_driver = {DRIVER_GEM |DRIVER_PRIME |DRIVER_RENDER | +DRIVER_ATOMIC | DRIVER_MODESET, .load = msm_load, .unload = msm_unload,
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 11/11 drm: Atomic modeset ioctl
In reply to Rob ClarkThe atomic modeset ioctl can be used to push any number of new values for object properties. The driver can then check the full device configuration as single unit, and try to apply the changes atomically.
The ioctl simply takes a list of object IDs and property IDs and their values.
Originally based on a patch from Ville Syrjälä, although it has mutated (mutilated?) enough since then that you probably shouldn't blame it on him ;-)
The atomic support is hidden behind the DRM_CLIENT_CAP_ATOMIC cap (to protect legacy userspace) and drm.atomic module param (for now).
--- drivers/gpu/drm/drm_atomic.c | 331 +++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 4 +- drivers/gpu/drm/drm_ioctl.c | 1 + include/drm/drm_crtc.h | 10 +- include/uapi/drm/drm.h | 1 + include/uapi/drm/drm_mode.h | 23 +++ 6 files changed, 366 insertions(+), 4 deletions(-)
drivers/gpu/drm/drm_atomic.c +331 -0
@@ -56,6 +56,11 @@ drm_atomic_state_alloc(struct drm_device *dev)if (!state)return NULL ; +/* TODO legacy paths should maybe do a better job about +* setting this appropriately? +*/ + state->allow_modeset = true; + state->num_connector =ACCESS_ONCE (dev->mode_config.num_connector); state->crtcs = kcalloc(dev->mode_config.num_crtc,
@@ -1003,6 +1008,22 @@ int drm_atomic_check_only(struct drm_atomic_state *state)if (config->funcs->atomic_check) ret = config->funcs->atomic_check (state->dev, state); +if (!state->allow_modeset) { +for (i =0 ; i < ncrtcs; i++) { +struct drm_crtc *crtc = state->crtcs[i]; +struct drm_crtc_state *crtc_state = state->crtc_states[i]; + +if (!crtc) +continue ; + +if (crtc_state->mode_changed) { +DRM_DEBUG_KMS ("[CRTC:%d] requires full modeset\n" , + crtc->base.id); +return -EINVAL ; + } + } + } +return ret; }EXPORT_SYMBOL (drm_atomic_check_only);
@@ -1068,3 +1089,313 @@ int drm_atomic_async_commit(struct drm_atomic_state *state)return config->funcs->atomic_commit (state->dev, state, true); }EXPORT_SYMBOL (drm_atomic_async_commit); + +/* +* The big monstor ioctl +*/ + +static struct drm_pending_vblank_event *create_vblank_event ( +struct drm_device *dev,struct drm_file *file_priv,uint64_t user_data) +{ +struct drm_pending_vblank_event *e =NULL ; +unsigned long flags; + +spin_lock_irqsave (&dev->event_lock, flags); +if (file_priv->event_space <sizeof e->event) { +spin_unlock_irqrestore (&dev->event_lock, flags); + goto out; + } + file_priv->event_space -=sizeof e->event; +spin_unlock_irqrestore (&dev->event_lock, flags); + + e =kzalloc (sizeof *e,GFP_KERNEL ); +if (e ==NULL ) { +spin_lock_irqsave (&dev->event_lock, flags); + file_priv->event_space +=sizeof e->event; +spin_unlock_irqrestore (&dev->event_lock, flags); + goto out; + } + + e->event.base.type =DRM_EVENT_FLIP_COMPLETE ; + e->event.base.length =sizeof e->event; + e->event.user_data = user_data; + e->base.event = &e->event.base; + e->base.file_priv = file_priv; + e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + +out: +return e; +} + +static void destroy_vblank_event (struct drm_device *dev, +struct drm_file *file_priv,struct drm_pending_vblank_event *e) +{ +unsigned long flags; + +spin_lock_irqsave (&dev->event_lock, flags); + file_priv->event_space +=sizeof e->event; +spin_unlock_irqrestore (&dev->event_lock, flags); +kfree (e); +} + +static int atomic_set_prop (struct drm_atomic_state *state, +struct drm_mode_object *obj,struct drm_property *prop, +uint64_t prop_value) +{ +struct drm_mode_object *ref; +int ret; + +if (!drm_property_change_valid_get (prop, prop_value, &ref)) +return -EINVAL ; + +switch (obj->type) { +case DRM_MODE_OBJECT_CONNECTOR : { +struct drm_connector *connector =obj_to_connector (obj); +struct drm_connector_state *connector_state; + + connector_state =drm_atomic_get_connector_state (state, connector); +if (IS_ERR (connector_state)) { + ret =PTR_ERR (connector_state); +break ; + } + + ret =drm_atomic_connector_set_property (connector, + connector_state, prop, prop_value); +break ; + } +case DRM_MODE_OBJECT_CRTC : { +struct drm_crtc *crtc =obj_to_crtc (obj); +struct drm_crtc_state *crtc_state; + + crtc_state =drm_atomic_get_crtc_state (state, crtc); +if (IS_ERR (crtc_state)) { + ret =PTR_ERR (crtc_state); +break ; + } + + ret =drm_atomic_crtc_set_property (crtc, + crtc_state, prop, prop_value); +break ; + } +case DRM_MODE_OBJECT_PLANE : { +struct drm_plane *plane =obj_to_plane (obj); +struct drm_plane_state *plane_state; + + plane_state =drm_atomic_get_plane_state (state, plane); +if (IS_ERR (plane_state)) { + ret =PTR_ERR (plane_state); +break ; + } + + ret =drm_atomic_plane_set_property (plane, + plane_state, prop, prop_value); +break ; + } +default : + ret = -EINVAL ; +break ; + } + +drm_property_change_valid_put (prop, ref); +return ret; +} + +int drm_mode_atomic_ioctl (struct drm_device *dev, +void *data,struct drm_file *file_priv) +{ +struct drm_mode_atomic *arg = data; +uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long )(arg->objs_ptr); +uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long )(arg->count_props_ptr); +uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long )(arg->props_ptr); +uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long )(arg->prop_values_ptr); +unsigned int copied_objs, copied_props; +struct drm_atomic_state *state; +struct drm_modeset_acquire_ctx ctx; +struct drm_plane *plane; +unsigned plane_mask =0 ; +int ret =0 ; +unsigned int i, j; + +/* disallow for drivers not supporting atomic: */ +if (!drm_core_check_feature (dev,DRIVER_ATOMIC )) +return -EINVAL ; + +/* disallow for userspace that has not enabled atomic cap (even +* though this may be a bit overkill, since legacy userspace +* wouldn't know how to call this ioctl) +*/ +if (!file_priv->atomic) +return -EINVAL ; + +if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS ) +return -EINVAL ; + +if (arg->reserved) +return -EINVAL ; + +if ((arg->flags &DRM_MODE_PAGE_FLIP_ASYNC ) && + !dev->mode_config.async_page_flip) +return -EINVAL ; + +/* can't test and expect an event at the same time. */ +if ((arg->flags &DRM_MODE_ATOMIC_TEST_ONLY ) && + (arg->flags &DRM_MODE_PAGE_FLIP_EVENT )) +return -EINVAL ; + +drm_modeset_acquire_init (&ctx,0 ); + + state =drm_atomic_state_alloc (dev); +if (!state) +return -ENOMEM ; + + state->acquire_ctx = &ctx; + state->allow_modeset = !!(arg->flags &DRM_MODE_ATOMIC_ALLOW_MODESET ); + +retry: + copied_objs =0 ; + copied_props =0 ; + +for (i =0 ; i < arg->count_objs; i++) { +uint32_t obj_id, count_props; +struct drm_mode_object *obj; + +if (get_user (obj_id, objs_ptr + copied_objs)) { + ret = -EFAULT ; + goto fail; + } + + obj =drm_mode_object_find (dev, obj_id,DRM_MODE_OBJECT_ANY ); +if (!obj || !obj->properties) { + ret = -ENOENT ; + goto fail; + } + +if (obj->type ==DRM_MODE_OBJECT_PLANE ) { + plane =obj_to_plane (obj); + plane_mask |= (1 <<drm_plane_index (plane)); + plane->old_fb = plane->fb; + } + +if (get_user (count_props, count_props_ptr + copied_objs)) { + ret = -EFAULT ; + goto fail; + } + + copied_objs++; + +for (j =0 ; j < count_props; j++) { +uint32_t prop_id; +uint64_t prop_value; +struct drm_property *prop; + +if (get_user (prop_id, props_ptr + copied_props)) { + ret = -EFAULT ; + goto fail; + } + + prop =drm_property_find (dev, prop_id); +if (!prop) { + ret = -ENOENT ; + goto fail; + } + +if (get_user (prop_value, prop_values_ptr + copied_props)) { + ret = -EFAULT ; + goto fail; + } + + ret =atomic_set_prop (state, obj, prop, prop_value); +if (ret) + goto fail; + + copied_props++; + } + } + +if (arg->flags &DRM_MODE_PAGE_FLIP_EVENT ) { +int ncrtcs = dev->mode_config.num_crtc; + +for (i =0 ; i < ncrtcs; i++) { +struct drm_crtc_state *crtc_state = state->crtc_states[i]; +struct drm_pending_vblank_event *e; + +if (!crtc_state) +continue ; + + e =create_vblank_event (dev, file_priv, arg->user_data); +if (!e) { + ret = -ENOMEM ; + goto fail; + } + + crtc_state->event = e; + } + } + +if (arg->flags &DRM_MODE_ATOMIC_TEST_ONLY ) { + ret =drm_atomic_check_only (state); +/* _check_only() does not free state, unlike _commit() */ +drm_atomic_state_free (state); + }else if (arg->flags &DRM_MODE_ATOMIC_NONBLOCK ) { + ret =drm_atomic_async_commit (state); + }else { + ret =drm_atomic_commit (state); + } + +/* if succeeded, fixup legacy plane crtc/fb ptrs before dropping +* locks (ie. while it is still safe to deref plane->state). We +* need to do this here because the driver entry points cannot +* distinguish between legacy and atomic ioctls. +*/ +drm_for_each_plane_mask (plane, dev, plane_mask) { +if (ret ==0 ) { +struct drm_framebuffer *new_fb = plane->state->fb; +if (new_fb) +drm_framebuffer_reference (new_fb); + plane->fb = new_fb; + plane->crtc = plane->state->crtc; + }else { + plane->old_fb =NULL ; + } +if (plane->old_fb) { +drm_framebuffer_unreference (plane->old_fb); + plane->old_fb =NULL ; + } + } + +drm_modeset_drop_locks (&ctx); +drm_modeset_acquire_fini (&ctx); + +return ret; + +fail: +if (ret == -EDEADLK ) + goto backoff; + +if (arg->flags &DRM_MODE_PAGE_FLIP_EVENT ) { +int ncrtcs = dev->mode_config.num_crtc; + +for (i =0 ; i < ncrtcs; i++) { +struct drm_crtc_state *crtc_state = state->crtc_states[i]; + +if (!crtc_state) +continue ; + +destroy_vblank_event (dev, file_priv, crtc_state->event); + crtc_state->event =NULL ; + } + } + +drm_atomic_state_free (state); + +drm_modeset_drop_locks (&ctx); +drm_modeset_acquire_fini (&ctx); + +return ret; + +backoff: +drm_atomic_state_clear (state); +drm_modeset_backoff (&ctx); + + goto retry; +}
drivers/gpu/drm/drm_crtc.c +2 -2
@@ -4303,7 +4303,7 @@ EXPORT_SYMBOL(drm_mode_connector_update_edid_property);* object to which the property is attached has a chance to take it's own * reference). */ -static bool drm_property_change_valid_get (struct drm_property *property, +bool drm_property_change_valid_get (struct drm_property *property,uint64_t value,struct drm_mode_object **ref) {int i;
@@ -4365,7 +4365,7 @@ static bool drm_property_change_valid_get(struct drm_property *property,return false; } -static void drm_property_change_valid_put (struct drm_property *property, +void drm_property_change_valid_put (struct drm_property *property,struct drm_mode_object *ref) {if (!ref)
drivers/gpu/drm/drm_ioctl.c +1 -0
@@ -630,6 +630,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {DRM_IOCTL_DEF (DRM_IOCTL_MODE_OBJ_GETPROPERTIES , drm_mode_obj_get_properties_ioctl,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 ),DRM_IOCTL_DEF (DRM_IOCTL_MODE_CURSOR2 , drm_mode_cursor2_ioctl,DRM_MASTER |DRM_CONTROL_ALLOW |DRM_UNLOCKED ), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), };#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
include/drm/drm_crtc.h +8 -2
@@ -902,7 +902,7 @@ struct drm_bridge {/** * struct struct drm_atomic_state - the global state object for atomic updates * @dev: parent DRM device -* @flags: state flags like async update +* @allow_modeset: allow full modeset * @planes: pointer to array of plane pointers * @plane_states: pointer to array of plane states pointers * @crtcs: pointer to array of CRTC pointers
@@ -914,7 +914,7 @@ struct drm_bridge {*/ struct drm_atomic_state {struct drm_device *dev; -uint32_t flags; +bool allow_modeset :1 ;struct drm_plane **planes;struct drm_plane_state **plane_states;struct drm_crtc **crtcs;
@@ -1346,6 +1346,10 @@ extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);extern int drm_mode_create_aspect_ratio_property (struct drm_device *dev);extern int drm_mode_create_dirty_info_property (struct drm_device *dev);extern int drm_mode_create_suggested_offset_properties (struct drm_device *dev); +extern bool drm_property_change_valid_get (struct drm_property *property, +uint64_t value,struct drm_mode_object **ref); +extern void drm_property_change_valid_put (struct drm_property *property, +struct drm_mode_object *ref);extern int drm_mode_connector_attach_encoder (struct drm_connector *connector,struct drm_encoder *encoder);
@@ -1437,6 +1441,8 @@ extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,extern int drm_mode_plane_set_obj_prop (struct drm_plane *plane,struct drm_property *property,uint64_t value); +extern int drm_mode_atomic_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);
include/uapi/drm/drm.h +1 -0
@@ -784,6 +784,7 @@ struct drm_prime_handle {#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)#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)/** * Device specific ioctls should only be in their respective headers
include/uapi/drm/drm_mode.h +23 -0
@@ -526,4 +526,27 @@ struct drm_mode_destroy_dumb { uint32_t handle; }; +/* page-flip flags are valid, plus: */ +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 + +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK |\ + DRM_MODE_ATOMIC_ALLOW_MODESET) + +struct drm_mode_atomic { +__u32 flags; +__u32 count_objs; +__u64 objs_ptr; +__u64 count_props_ptr; +__u64 props_ptr; +__u64 prop_values_ptr; +__u64 reserved; +__u64 user_data; +}; +#endif
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/1 drm/atomic: Hide drm.ko internal interfaces
This is just a bit fallout from patch polishing and moving the get_prop logic fully into the core:
- Drop EXPORT_SYMBOL and make the helpers static.
- Drop kerneldoc since not used by drivers.
- Move the cross-file function declarations only used by drm.ko internally to an internal header.
v2: keep the gist of the comments, requested by Rob.
--- drivers/gpu/drm/drm_atomic.c | 54 +++++-------------------------------- drivers/gpu/drm/drm_crtc_internal.h | 6 +++++ drivers/gpu/drm/drm_ioctl.c | 1 + include/drm/drm_atomic.h | 12 --------- 4 files changed, 14 insertions(+), 59 deletions(-)
drivers/gpu/drm/drm_atomic.c +7 -47
@@ -247,21 +247,11 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, }EXPORT_SYMBOL (drm_atomic_crtc_set_property); -/** -* drm_atomic_crtc_get_property - get property on CRTC -* @crtc: the drm CRTC to get a property on -* @state: the state object with the property value to read -* @property: the property to get -* @val: the property value (returned by reference) -* -* Use this instead of calling crtc->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. -* -* RETURNS: -* Zero on success, error code on failure */ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state,
@@ -271,7 +261,6 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc,return crtc->funcs->atomic_get_property (crtc, state, property, val);return -EINVAL ; } -EXPORT_SYMBOL (drm_atomic_crtc_get_property);/** * drm_atomic_crtc_check - check crtc state
@@ -409,23 +398,14 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, }EXPORT_SYMBOL (drm_atomic_plane_set_property); -/** -* drm_atomic_plane_get_property - get property on plane -* @plane: the drm plane to get a property on -* @state: the state object with the property value to read -* @property: the property to get -* @val: the property value (returned by reference) -* -* Use this instead of calling plane->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. -* -* RETURNS: -* Zero on success, error code on failure */ -int drm_atomic_plane_get_property (struct drm_plane *plane, +static int +drm_atomic_plane_get_property (struct drm_plane *plane,const struct drm_plane_state *state,struct drm_property *property,uint64_t *val) {
@@ -460,7 +440,6 @@ int drm_atomic_plane_get_property(struct drm_plane *plane,return 0 ; } -EXPORT_SYMBOL (drm_atomic_plane_get_property);/** * drm_atomic_plane_check - check plane state
@@ -650,23 +629,14 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, }EXPORT_SYMBOL (drm_atomic_connector_set_property); -/** -* drm_atomic_connector_get_property - get property on connector -* @connector: the drm connector to get a property on -* @state: the state object with the property value to read -* @property: the property to get -* @val: the property value (returned by reference) -* -* Use this instead of calling connector->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. -* -* RETURNS: -* Zero on success, error code on failure */ -int drm_atomic_connector_get_property (struct drm_connector *connector, +static int +drm_atomic_connector_get_property (struct drm_connector *connector,const struct drm_connector_state *state,struct drm_property *property,uint64_t *val) {
@@ -686,17 +656,7 @@ int drm_atomic_connector_get_property(struct drm_connector *connector,return 0 ; } -EXPORT_SYMBOL (drm_atomic_connector_get_property); -/** -* drm_atomic_get_property - helper to read atomic property -* @obj: drm mode object whose property to read -* @property: the property to read -* @val: the read value, returned by reference -* -* RETURNS: -* Zero on success, error code on failure -*/ int drm_atomic_get_property (struct drm_mode_object *obj,struct drm_property *property,uint64_t *val) {
drivers/gpu/drm/drm_crtc_internal.h +6 -0
@@ -36,3 +36,9 @@ int drm_mode_object_get(struct drm_device *dev,void drm_mode_object_put (struct drm_device *dev,struct drm_mode_object *object); +/* drm_atomic.c */ +int drm_atomic_get_property (struct drm_mode_object *obj, +struct drm_property *property,uint64_t *val); +int drm_mode_atomic_ioctl (struct drm_device *dev, +void *data,struct drm_file *file_priv); +
drivers/gpu/drm/drm_ioctl.c +1 -0
@@ -32,6 +32,7 @@#include <drm/drm_core.h> #include "drm_legacy.h" #include "drm_internal.h" +#include "drm_crtc_internal.h" #include <linux/pci.h> #include <linux/export.h>
include/drm/drm_atomic.h +0 -12
@@ -41,30 +41,18 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,int drm_atomic_crtc_set_property (struct drm_crtc *crtc,struct drm_crtc_state *state,struct drm_property *property,uint64_t val); -int drm_atomic_crtc_get_property (struct drm_crtc *crtc, -const struct drm_crtc_state *state, -struct drm_property *property,uint64_t *val);struct drm_plane_state *__must_check drm_atomic_get_plane_state (struct drm_atomic_state *state,struct drm_plane *plane);int drm_atomic_plane_set_property (struct drm_plane *plane,struct drm_plane_state *state,struct drm_property *property,uint64_t val); -int drm_atomic_plane_get_property (struct drm_plane *plane, -const struct drm_plane_state *state, -struct drm_property *property,uint64_t *val);struct drm_connector_state *__must_check drm_atomic_get_connector_state (struct drm_atomic_state *state,struct drm_connector *connector);int drm_atomic_connector_set_property (struct drm_connector *connector,struct drm_connector_state *state,struct drm_property *property,uint64_t val); -int drm_atomic_connector_get_property (struct drm_connector *connector, -const struct drm_connector_state *state, -struct drm_property *property,uint64_t *val); - -int drm_atomic_get_property (struct drm_mode_object *obj, -struct drm_property *property,uint64_t *val); int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
Signature · 6 lines
2.1.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel