[RFC 06/11] drm: convert plane to properties
From: Rob ClarkUse atomic properties mechanism to set plane attributes. This by itself doesn't accomplish anything, but it avoids having multiple code paths to do the same thing when nuclear-pageflip and atomic- modeset are introduced. --- drivers/gpu/drm/drm_crtc.c | 278 +--- include/drm/drm_crtc.h | 25 +++- 2 files changed, 289 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b1ccfea..da29732 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -38,6 +38,14 @@ #include "drm_edid.h" #include "drm_fourcc.h" +static int drm_mode_set_obj_prop(struct drm_mode_object *obj, + void *state, struct drm_property *property, uint64_t value); + +static inline bool dev_supports_atomic(struct drm_device *dev) +{ + return !!dev->driver->atomic_begin; +} + /* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN(fnname, list) \ char *fnname(int val) \ @@ -376,8 +384,10 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); * * Scans all the CRTCs and planes in @dev's mode_config. If they're * using @fb, removes it, setting it to NULL. + * + * Legacy version.. remove when all drivers converted to 'atomic' API */ -void drm_framebuffer_remove(struct drm_framebuffer *fb) +static void drm_framebuffer_remove_legacy(struct drm_framebuffer *fb) { struct drm_device *dev = fb->dev; struct drm_crtc *crtc; @@ -414,6 +424,71 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) drm_framebuffer_unreference(fb); } + +/** + * drm_framebuffer_remove - remove and unreference a framebuffer object + * @fb: framebuffer to remove + * + * LOCKING: + * Caller must hold mode config lock. + * + * Scans all the CRTCs and planes in @dev's mode_config. If they're + * using @fb, removes it, setting it to NULL. + */ +void drm_framebuffer_remove(struct drm_framebuffer *fb) +{ + struct drm_device *dev = fb->dev; + struct drm_mode_config *config = >mode_config; + struct drm_crtc *crtc; + struct drm_plane *plane; + struct drm_mode_set set; + void *state; + int ret; + + if (!dev_supports_atomic(dev)) { + drm_framebuffer_remove_legacy(fb); + return; + } + + state = dev->driver->atomic_begin(dev, NULL); + if (IS_ERR(state)) { + DRM_ERROR("failed to disable crtc and/or plane when fb was deleted\n"); + return; + } + + /* remove from any CRTC */ + list_for_each_entry(crtc, >mode_config.crtc_list, head) { + if (crtc->fb == fb) { + /* should turn off the crtc */ + memset(, 0, sizeof(struct drm_mode_set)); + set.crtc = crtc; + set.fb = NULL; + ret = crtc->funcs->set_config(); + if (ret) + DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); + } + } + + list_for_each_entry(plane, >mode_config.plane_list, head) { + if (plane->fb == fb) { + /* should turn off the crtc */ + drm_mode_plane_set_obj_prop(plane, state, config->prop_crtc_id, 0); + drm_mode_plane_set_obj_prop(plane, state, config->prop_fb_id, 0); + } + } + + /* just disabling stuff shouldn't fail, hopefully: */ + if(dev->driver->atomic_check(dev, state)) + DRM_ERROR("failed to disable crtc and/or plane when fb was deleted\n"); + else + dev->driver->atomic_commit(dev, state, NULL); + + dev->driver->atomic_end(dev, state); + + list_del(>filp_head); + + drm_framebuffer_unreference(fb); +} EXPORT_SYMBOL(drm_framebuffer_remove); /** @@ -663,6 +738,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, bool priv) { + struct drm_mode_config *config = >mode_config; int ret; mutex_lock(>mode_config.mutex); @@ -699,6 +775,20 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, INIT_LIST_HEAD(>head); } + if (!dev_supports_atomic(dev)) + goto out; + + drm_object_attach_property(>base, config->prop_fb_id, 0); + drm_object_attach_property(>base, config->prop_crtc_id, 0); + drm_object_attach_property(>base, config->prop_crtc_x, 0); + drm_object_attach_property(>base, config->prop_crtc_y, 0); + drm_object_attach_property(>base, config->prop_crtc_w, 0); + drm_object_attach_property(>base, config->prop_crtc_h, 0); + drm_object_attach_property(>base, config->prop_src_x, 0); +
[RFC 06/11] drm: convert plane to properties
From: Rob Clark r...@ti.com Use atomic properties mechanism to set plane attributes. This by itself doesn't accomplish anything, but it avoids having multiple code paths to do the same thing when nuclear-pageflip and atomic- modeset are introduced. --- drivers/gpu/drm/drm_crtc.c | 278 +--- include/drm/drm_crtc.h | 25 +++- 2 files changed, 289 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b1ccfea..da29732 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -38,6 +38,14 @@ #include drm_edid.h #include drm_fourcc.h +static int drm_mode_set_obj_prop(struct drm_mode_object *obj, + void *state, struct drm_property *property, uint64_t value); + +static inline bool dev_supports_atomic(struct drm_device *dev) +{ + return !!dev-driver-atomic_begin; +} + /* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN(fnname, list) \ char *fnname(int val) \ @@ -376,8 +384,10 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); * * Scans all the CRTCs and planes in @dev's mode_config. If they're * using @fb, removes it, setting it to NULL. + * + * Legacy version.. remove when all drivers converted to 'atomic' API */ -void drm_framebuffer_remove(struct drm_framebuffer *fb) +static void drm_framebuffer_remove_legacy(struct drm_framebuffer *fb) { struct drm_device *dev = fb-dev; struct drm_crtc *crtc; @@ -414,6 +424,71 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) drm_framebuffer_unreference(fb); } + +/** + * drm_framebuffer_remove - remove and unreference a framebuffer object + * @fb: framebuffer to remove + * + * LOCKING: + * Caller must hold mode config lock. + * + * Scans all the CRTCs and planes in @dev's mode_config. If they're + * using @fb, removes it, setting it to NULL. + */ +void drm_framebuffer_remove(struct drm_framebuffer *fb) +{ + struct drm_device *dev = fb-dev; + struct drm_mode_config *config = dev-mode_config; + struct drm_crtc *crtc; + struct drm_plane *plane; + struct drm_mode_set set; + void *state; + int ret; + + if (!dev_supports_atomic(dev)) { + drm_framebuffer_remove_legacy(fb); + return; + } + + state = dev-driver-atomic_begin(dev, NULL); + if (IS_ERR(state)) { + DRM_ERROR(failed to disable crtc and/or plane when fb was deleted\n); + return; + } + + /* remove from any CRTC */ + list_for_each_entry(crtc, dev-mode_config.crtc_list, head) { + if (crtc-fb == fb) { + /* should turn off the crtc */ + memset(set, 0, sizeof(struct drm_mode_set)); + set.crtc = crtc; + set.fb = NULL; + ret = crtc-funcs-set_config(set); + if (ret) + DRM_ERROR(failed to reset crtc %p when fb was deleted\n, crtc); + } + } + + list_for_each_entry(plane, dev-mode_config.plane_list, head) { + if (plane-fb == fb) { + /* should turn off the crtc */ + drm_mode_plane_set_obj_prop(plane, state, config-prop_crtc_id, 0); + drm_mode_plane_set_obj_prop(plane, state, config-prop_fb_id, 0); + } + } + + /* just disabling stuff shouldn't fail, hopefully: */ + if(dev-driver-atomic_check(dev, state)) + DRM_ERROR(failed to disable crtc and/or plane when fb was deleted\n); + else + dev-driver-atomic_commit(dev, state, NULL); + + dev-driver-atomic_end(dev, state); + + list_del(fb-filp_head); + + drm_framebuffer_unreference(fb); +} EXPORT_SYMBOL(drm_framebuffer_remove); /** @@ -663,6 +738,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, bool priv) { + struct drm_mode_config *config = dev-mode_config; int ret; mutex_lock(dev-mode_config.mutex); @@ -699,6 +775,20 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, INIT_LIST_HEAD(plane-head); } + if (!dev_supports_atomic(dev)) + goto out; + + 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,
[RFC 06/11] drm: convert plane to properties
From: Rob Clark r...@ti.com Use atomic properties mechanism to set plane attributes. This by itself doesn't accomplish anything, but it avoids having multiple code paths to do the same thing when nuclear-pageflip and atomic- modeset are introduced. --- drivers/gpu/drm/drm_crtc.c | 257 ++-- include/drm/drm_crtc.h | 32 -- 2 files changed, 179 insertions(+), 110 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 245c462..81a63fe 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -38,6 +38,9 @@ #include drm_edid.h #include drm_fourcc.h +static int drm_mode_set_obj_prop(struct drm_mode_object *obj, + void *state, struct drm_property *property, uint64_t value); + /* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN(fnname, list) \ char *fnname(int val) \ @@ -380,11 +383,19 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); void drm_framebuffer_remove(struct drm_framebuffer *fb) { struct drm_device *dev = fb-dev; + struct drm_mode_config *config = dev-mode_config; struct drm_crtc *crtc; struct drm_plane *plane; struct drm_mode_set set; + void *state; int ret; + state = dev-driver-atomic_begin(dev, NULL); + if (IS_ERR(state)) { + DRM_ERROR(failed to disable crtc and/or plane when fb was deleted\n); + return; + } + /* remove from any CRTC */ list_for_each_entry(crtc, dev-mode_config.crtc_list, head) { if (crtc-fb == fb) { @@ -401,15 +412,19 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) list_for_each_entry(plane, dev-mode_config.plane_list, head) { if (plane-fb == fb) { /* should turn off the crtc */ - ret = plane-funcs-disable_plane(plane); - if (ret) - DRM_ERROR(failed to disable plane with busy fb\n); - /* disconnect the plane from the fb and crtc: */ - plane-fb = NULL; - plane-crtc = NULL; + drm_mode_plane_set_obj_prop(plane, state, config-prop_crtc_id, 0); + drm_mode_plane_set_obj_prop(plane, state, config-prop_fb_id, 0); } } + /* just disabling stuff shouldn't fail, hopefully: */ + if(dev-driver-atomic_check(dev, state)) + DRM_ERROR(failed to disable crtc and/or plane when fb was deleted\n); + else + dev-driver-atomic_commit(dev, state, NULL); + + dev-driver-atomic_end(dev, state); + list_del(fb-filp_head); drm_framebuffer_unreference(fb); @@ -663,6 +678,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, bool priv) { + struct drm_mode_config *config = dev-mode_config; int ret; mutex_lock(dev-mode_config.mutex); @@ -699,6 +715,17 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, INIT_LIST_HEAD(plane-head); } + 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); + out: mutex_unlock(dev-mode_config.mutex); @@ -772,23 +799,91 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_destroy); -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 *edid; - struct drm_property *dpms; + 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, +
[RFC 06/11] drm: convert plane to properties
From: Rob ClarkUse atomic properties mechanism to set plane attributes. This by itself doesn't accomplish anything, but it avoids having multiple code paths to do the same thing when nuclear-pageflip and atomic- modeset are introduced. --- drivers/gpu/drm/drm_crtc.c | 257 ++-- include/drm/drm_crtc.h | 32 -- 2 files changed, 179 insertions(+), 110 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 245c462..81a63fe 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -38,6 +38,9 @@ #include "drm_edid.h" #include "drm_fourcc.h" +static int drm_mode_set_obj_prop(struct drm_mode_object *obj, + void *state, struct drm_property *property, uint64_t value); + /* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN(fnname, list) \ char *fnname(int val) \ @@ -380,11 +383,19 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); void drm_framebuffer_remove(struct drm_framebuffer *fb) { struct drm_device *dev = fb->dev; + struct drm_mode_config *config = >mode_config; struct drm_crtc *crtc; struct drm_plane *plane; struct drm_mode_set set; + void *state; int ret; + state = dev->driver->atomic_begin(dev, NULL); + if (IS_ERR(state)) { + DRM_ERROR("failed to disable crtc and/or plane when fb was deleted\n"); + return; + } + /* remove from any CRTC */ list_for_each_entry(crtc, >mode_config.crtc_list, head) { if (crtc->fb == fb) { @@ -401,15 +412,19 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) list_for_each_entry(plane, >mode_config.plane_list, head) { if (plane->fb == fb) { /* should turn off the crtc */ - ret = plane->funcs->disable_plane(plane); - if (ret) - DRM_ERROR("failed to disable plane with busy fb\n"); - /* disconnect the plane from the fb and crtc: */ - plane->fb = NULL; - plane->crtc = NULL; + drm_mode_plane_set_obj_prop(plane, state, config->prop_crtc_id, 0); + drm_mode_plane_set_obj_prop(plane, state, config->prop_fb_id, 0); } } + /* just disabling stuff shouldn't fail, hopefully: */ + if(dev->driver->atomic_check(dev, state)) + DRM_ERROR("failed to disable crtc and/or plane when fb was deleted\n"); + else + dev->driver->atomic_commit(dev, state, NULL); + + dev->driver->atomic_end(dev, state); + list_del(>filp_head); drm_framebuffer_unreference(fb); @@ -663,6 +678,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, bool priv) { + struct drm_mode_config *config = >mode_config; int ret; mutex_lock(>mode_config.mutex); @@ -699,6 +715,17 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, INIT_LIST_HEAD(>head); } + drm_object_attach_property(>base, config->prop_fb_id, 0); + drm_object_attach_property(>base, config->prop_crtc_id, 0); + drm_object_attach_property(>base, config->prop_crtc_x, 0); + drm_object_attach_property(>base, config->prop_crtc_y, 0); + drm_object_attach_property(>base, config->prop_crtc_w, 0); + drm_object_attach_property(>base, config->prop_crtc_h, 0); + drm_object_attach_property(>base, config->prop_src_x, 0); + drm_object_attach_property(>base, config->prop_src_y, 0); + drm_object_attach_property(>base, config->prop_src_w, 0); + drm_object_attach_property(>base, config->prop_src_h, 0); + out: mutex_unlock(>mode_config.mutex); @@ -772,23 +799,91 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_destroy); -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 *edid; - struct drm_property *dpms; + 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,