From 88a48e297b3a3bac6022c03babfb038f1a886cea Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:50 -0500 Subject: drm: add atomic properties Once 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). Signed-off-by: Rob Clark [danvet: Squash in fixup patch to check for DRM_MODE_PROP_ATOMIC instaed of the CAP define when filtering properties. Reported by Tvrtko Uruslin, acked by Rob.] Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Documentation') diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 4b592ffbafee..7fa4f9873cf7 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -239,6 +239,14 @@ Driver supports dedicated render nodes. + + DRIVER_ATOMIC + + 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. + + -- cgit v1.2.3-59-g8ed1b From 6b4959f43a04e12d39c5700607727f2cbcfeac31 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:53 -0500 Subject: drm/atomic: atomic plane properties Expose the core plane state as properties, so they can be updated via atomic ioctl. v2: atomic property flag Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- 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(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 7fa4f9873cf7..8d8dc7124bb5 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2572,7 +2572,7 @@ void intel_crt_init(struct drm_device *dev) Description/Restrictions - DRM + DRM Generic “EDID” BLOB | IMMUTABLE @@ -2602,7 +2602,7 @@ void intel_crt_init(struct drm_device *dev) Contains tiling information for a connector. - Plane + Plane “type” ENUM | IMMUTABLE { "Overlay", "Primary", "Cursor" } @@ -2610,6 +2610,76 @@ void intel_crt_init(struct drm_device *dev) Plane type + “SRC_X” + RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source x coordinate in 16.16 fixed point (atomic) + + + “SRC_Y” + RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source y coordinate in 16.16 fixed point (atomic) + + + “SRC_W” + RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source width in 16.16 fixed point (atomic) + + + “SRC_H” + RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source height in 16.16 fixed point (atomic) + + + “CRTC_X” + SIGNED_RANGE + Min=INT_MIN, Max=INT_MAX + Plane + Scanout CRTC (destination) x coordinate (atomic) + + + “CRTC_Y” + SIGNED_RANGE + Min=INT_MIN, Max=INT_MAX + Plane + Scanout CRTC (destination) y coordinate (atomic) + + + “CRTC_W” + RANGE + Min=0, Max=UINT_MAX + Plane + Scanout CRTC (destination) width (atomic) + + + “CRTC_H” + RANGE + Min=0, Max=UINT_MAX + Plane + Scanout CRTC (destination) height (atomic) + + + “FB_ID” + OBJECT + DRM_MODE_OBJECT_FB + Plane + Scanout framebuffer (atomic) + + + “CRTC_ID” + OBJECT + DRM_MODE_OBJECT_CRTC + Plane + CRTC that plane is attached to (atomic) + + DVI-I “subconnector” ENUM diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 1c472b1baeb8..131d47f6f7a2 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -366,9 +366,41 @@ 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; + struct drm_device *dev = plane->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->prop_fb_id) { + struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val); + drm_atomic_set_fb_for_plane(state, fb); + if (fb) + drm_framebuffer_unreference(fb); + } else if (property == config->prop_crtc_id) { + struct drm_crtc *crtc = drm_crtc_find(dev, val); + return drm_atomic_set_crtc_for_plane(state, crtc); + } else if (property == config->prop_crtc_x) { + state->crtc_x = U642I64(val); + } else if (property == config->prop_crtc_y) { + state->crtc_y = U642I64(val); + } else if (property == config->prop_crtc_w) { + state->crtc_w = val; + } else if (property == config->prop_crtc_h) { + state->crtc_h = val; + } else if (property == config->prop_src_x) { + state->src_x = val; + } else if (property == config->prop_src_y) { + state->src_y = val; + } else if (property == config->prop_src_w) { + state->src_w = val; + } else if (property == config->prop_src_h) { + state->src_h = val; + } else if (plane->funcs->atomic_set_property) { + return plane->funcs->atomic_set_property(plane, state, + property, val); + } else { + return -EINVAL; + } + + return 0; } EXPORT_SYMBOL(drm_atomic_plane_set_property); @@ -392,9 +424,36 @@ 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) + struct drm_device *dev = plane->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->prop_fb_id) { + *val = (state->fb) ? state->fb->base.id : 0; + } else if (property == config->prop_crtc_id) { + *val = (state->crtc) ? state->crtc->base.id : 0; + } else if (property == config->prop_crtc_x) { + *val = I642U64(state->crtc_x); + } else if (property == config->prop_crtc_y) { + *val = I642U64(state->crtc_y); + } else if (property == config->prop_crtc_w) { + *val = state->crtc_w; + } else if (property == config->prop_crtc_h) { + *val = state->crtc_h; + } else if (property == config->prop_src_x) { + *val = state->src_x; + } else if (property == config->prop_src_y) { + *val = state->src_y; + } else if (property == config->prop_src_w) { + *val = state->src_w; + } else if (property == config->prop_src_h) { + *val = state->src_h; + } else if (plane->funcs->atomic_get_property) { return plane->funcs->atomic_get_property(plane, state, property, val); - return -EINVAL; + } else { + return -EINVAL; + } + + return 0; } EXPORT_SYMBOL(drm_atomic_plane_get_property); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f33863a40d42..46fa0945b53e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1169,6 +1169,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, enum drm_plane_type type) { + struct drm_mode_config *config = &dev->mode_config; int ret; ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); @@ -1193,15 +1194,28 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->possible_crtcs = possible_crtcs; plane->type = type; - list_add_tail(&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_total_plane++; + list_add_tail(&plane->head, &config->plane_list); + config->num_total_plane++; if (plane->type == DRM_PLANE_TYPE_OVERLAY) - dev->mode_config.num_overlay_plane++; + config->num_overlay_plane++; drm_object_attach_property(&plane->base, - dev->mode_config.plane_type_property, + config->plane_type_property, plane->type); + if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { + drm_object_attach_property(&plane->base, config->prop_fb_id, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_id, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_x, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_y, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_w, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_h, 0); + drm_object_attach_property(&plane->base, config->prop_src_x, 0); + drm_object_attach_property(&plane->base, config->prop_src_y, 0); + drm_object_attach_property(&plane->base, config->prop_src_w, 0); + drm_object_attach_property(&plane->base, config->prop_src_h, 0); + } + return 0; } EXPORT_SYMBOL(drm_universal_plane_init); @@ -1323,7 +1337,7 @@ void drm_plane_force_disable(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_force_disable); -static int drm_mode_create_standard_connector_properties(struct drm_device *dev) +static int drm_mode_create_standard_properties(struct drm_device *dev) { struct drm_property *prop; @@ -1360,20 +1374,72 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.tile_property = prop; - return 0; -} - -static int drm_mode_create_standard_plane_properties(struct drm_device *dev) -{ - struct drm_property *type; - - /* - * Standard properties (apply to all planes) - */ - type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, + prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "type", drm_plane_type_enum_list, ARRAY_SIZE(drm_plane_type_enum_list)); - dev->mode_config.plane_type_property = type; + if (!prop) + return -ENOMEM; + dev->mode_config.plane_type_property = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_X", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_x = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_Y", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_y = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_W", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_w = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_H", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_h = prop; + + prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_X", INT_MIN, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_x = prop; + + prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_Y", INT_MIN, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_y = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_W", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_w = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_H", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_h = prop; + + prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, + "FB_ID", DRM_MODE_OBJECT_FB); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_fb_id = prop; + + prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_ID", DRM_MODE_OBJECT_CRTC); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_id = prop; return 0; } @@ -5264,8 +5330,7 @@ void drm_mode_config_init(struct drm_device *dev) idr_init(&dev->mode_config.tile_idr); drm_modeset_lock_all(dev); - drm_mode_create_standard_connector_properties(dev); - drm_mode_create_standard_plane_properties(dev); + drm_mode_create_standard_properties(dev); drm_modeset_unlock_all(dev); /* Just to be sure */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b5ab673add29..fc4767fa723b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -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; -- cgit v1.2.3-59-g8ed1b From ae16c597b61ae4613b13a0c3fac302e8d8827ac7 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:54 -0500 Subject: drm/atomic: atomic connector properties Expose the core connector state as properties so it can be updated via atomic ioctl. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- 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(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 8d8dc7124bb5..2f4a29906425 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2572,8 +2572,8 @@ void intel_crt_init(struct drm_device *dev) Description/Restrictions - DRM - Generic + DRM + Connector “EDID” BLOB | IMMUTABLE 0 @@ -2602,6 +2602,13 @@ void intel_crt_init(struct drm_device *dev) Contains tiling information for a connector. + “CRTC_ID” + OBJECT + DRM_MODE_OBJECT_CRTC + Connector + CRTC that connector is attached to (atomic) + + Plane “type” ENUM | IMMUTABLE diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 131d47f6f7a2..57cc68177f09 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -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, diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 46fa0945b53e..3cb1fa09ac9e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -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; -- cgit v1.2.3-59-g8ed1b