Atomic/nuclear modeset/pageflip
Subsystems (18)
cover Atomic/nuclear modeset/pageflip
Previous revision of series:
http://lists.freedesktop.org/archives/dri-devel/2013-November/049594.html
And if you prefer, in git form:
http://cgit.freedesktop.org/~robclark/linux/log/?h=cold-fusiongit://people.freedesktop.org/~robclark/linux cold-fusion
Compared to previous revision:
* rebased on primary-plane RFC series. As a result, nearly none of the drivers actually compile at the moment :-P
But it is in the end a good thing... it reduces some code paths (now only having to care about fbs on planes, and it avoids exposing an intermediate ABI state to userspace so avoids the need for some compat glue later).
* state objects now carry their own ref to fbs. This cleaned up most of the refcnt'ing issues, so I'm pretty happy how that turned out. With that plus all the other major hacks cleaned up, I'm happy enough to drop the "RFC" tag.
There are, I think, two remaining issues to solve:
* we either need to add an event ptr param to plane->update_plane() or come up with another way to handle events on planes.
* I kinda would still like to add to the atomic ioctl some way to indicate ok/error on a bit finer granularity than per-ioctl. Ie. perhaps an array where userspace can ask for results per KMS object (crtc/plane)? Something along these lines would give the kernel a bit more flexibility to deal with some of the edge cases which come up when you gang crtcs for ultra high resolution displays. In short, it would let the driver "steal" some of the planes if needed from userspace.
This would also, conveniently, be pretty similar to how (AFAIU) hw compositor and ADF work on android. Which seems like it would be useful to eventually enable android devices to use an upstream display driver.
For this we could pretty easily just throw in a placeholder that we could replace later with an optional ptr to __user array. I think that would be fine for an initial version, but I just wanted to throw this idea out there, because I think it will become important.
Note that this series is really only the beginning of atomic. Once this is merged, there are some various vague thoughts about next steps:
* finish converting remaining callers of drm_mode_set_config_internal() to use atomic
* replace driver usage of plane->fb with plane->state->fb.. drop plane->fb, somewhere along the way deprecate/drop ->page_flip() and possibly current incarnation of ->update_plane()..
* perhaps some more fine grained event notification or other such extensions.
* I know there are a few things I plan on ripping out / simplifying in drm/msm as a result of atomic, but just waiting until this is merge to avoid carrying such
.......
So, that all said, I am a bit curious about how we might eventually land this series some day. Especially once we include changes to update all points in various drivers that access crtc->fb to crtc->primary->fb it will be one big hairy merge-conflict-prone branch. Not the sort of thing that I'd really like to have to rebase for the next five kernel cycles if at all avoidable.
We certainly could merge everything but the new ioctl, or hide the ioctl behind an experimental module param for now. I'm less concerned about that (either option would be pretty easy), and more about merging the infrastructure changes.
Rob Clark (13):
drm: fix typo
drm: add atomic fxns
drm: convert crtc to ww_mutex
drm: add object property type
drm: add signed-range property type
drm: helpers to find mode objects
drm: split propvals out and blob property support
drm: allow FB's in drm_mode_object_find
drm: convert plane to properties/state
drm: convert crtc to properties/state
drm: push locking down into restore_fbdev_mode drm/msm: add atomic support
drm: spiff out FB refcnting traces
Ville Syrjälä (3):
drm: Allow drm_mode_object_find() to look up an object of any type
drm: Refactor object property check code
drm: Atomic modeset ioctl
drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/armada/armada_crtc.c | 15 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/armada/armada_output.c | 3 +- drivers/gpu/drm/armada/armada_overlay.c | 15 +- drivers/gpu/drm/ast/ast_drv.c | 6 + drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_drv.c | 6 + drivers/gpu/drm/cirrus/cirrus_drv.h | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 702 +++++++++++ drivers/gpu/drm/drm_crtc.c | 1667 +++++++++++++++++++-------- drivers/gpu/drm/drm_crtc_helper.c | 2 +- drivers/gpu/drm/drm_drv.c | 1 + drivers/gpu/drm/drm_fb_cma_helper.c | 9 +- drivers/gpu/drm/drm_fb_helper.c | 28 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 11 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 11 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/cdv_intel_dp.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 10 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 12 +- drivers/gpu/drm/gma500/psb_drv.c | 11 +- drivers/gpu/drm/gma500/psb_drv.h | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_drv.h | 4 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 10 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 23 +- drivers/gpu/drm/i2c/ch7006_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 8 + drivers/gpu/drm/i915/intel_crt.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 16 +- drivers/gpu/drm/i915/intel_dp.c | 7 +- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_fbdev.c | 6 +- drivers/gpu/drm/i915/intel_hdmi.c | 7 +- drivers/gpu/drm/i915/intel_lvds.c | 4 +- drivers/gpu/drm/i915/intel_sdvo.c | 23 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/i915/intel_tv.c | 11 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 7 + drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 69 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 15 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 66 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 15 +- drivers/gpu/drm/msm/msm_atomic.c | 141 +++ drivers/gpu/drm/msm/msm_drv.c | 33 +- drivers/gpu/drm/msm/msm_drv.h | 8 + drivers/gpu/drm/msm/msm_gem.c | 24 +- drivers/gpu/drm/msm/msm_gem.h | 13 + drivers/gpu/drm/msm/msm_kms.h | 1 + drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/dispnv04/overlay.c | 14 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 3 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 7 + drivers/gpu/drm/nouveau/nouveau_drm.h | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 27 +- drivers/gpu/drm/omapdrm/omap_drv.c | 16 +- drivers/gpu/drm/omapdrm/omap_drv.h | 5 +- drivers/gpu/drm/omapdrm/omap_plane.c | 11 +- drivers/gpu/drm/qxl/qxl_display.c | 6 +- drivers/gpu/drm/qxl/qxl_drv.c | 9 + drivers/gpu/drm/radeon/radeon_connectors.c | 9 +- drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/radeon/radeon_drv.c | 9 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 3 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 12 +- drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 7 + drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 1 + drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 + drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +- drivers/gpu/drm/udl/udl_connector.c | 6 +- drivers/gpu/drm/udl/udl_drv.c | 8 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drmP.h | 88 +- include/drm/drm_atomic.h | 172 +++ include/drm/drm_crtc.h | 379 +++++- include/drm/drm_fb_helper.h | 3 +- include/uapi/drm/drm.h | 12 + include/uapi/drm/drm_mode.h | 38 + 106 files changed, 3214 insertions(+), 792 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic.c create mode 100644 drivers/gpu/drm/msm/msm_atomic.c create mode 100644 include/drm/drm_atomic.h
Signature · 6 lines
1.8.5.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/16 drm: fix typo
--- drivers/gpu/drm/drm_crtc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/drm_crtc_helper.c +1 -1
@@ -305,7 +305,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)list_for_each_entry (encoder, &dev->mode_config.encoder_list, head) {if (!drm_helper_encoder_in_use (encoder)) {drm_encoder_disable (encoder); -/* disconnector encoder from any connector */ +/* disconnect encoder from any connector */ encoder->crtc =NULL ; } }
Signature · 1 line
1.8.5.3
PATCH 2/16 drm: add atomic fxns
In reply to Rob ClarkThe 'atomic' mechanism allows for multiple properties to be updated, checked, and commited atomically. This will be the basis of atomic- modeset and nuclear-pageflip.
The basic flow is:
state = dev->atomic_begin();
for (... one or more ...)
obj->set_property(obj, state, prop, value);
if (dev->atomic_check(state))
dev->atomic_commit(state);
dev->atomic_end(state);The split of check and commit steps is to allow for ioctls with a test-only flag (which would skip the commit step).
--- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/armada/armada_crtc.c | 4 +- drivers/gpu/drm/armada/armada_output.c | 3 +- drivers/gpu/drm/armada/armada_overlay.c | 4 +- drivers/gpu/drm/ast/ast_drv.c | 6 ++ drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/cirrus/cirrus_drv.c | 6 ++ drivers/gpu/drm/cirrus/cirrus_drv.h | 1 + drivers/gpu/drm/drm_atomic.c | 135 ++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 141 +++++++++++++++++----------- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 ++ drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 4 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 4 +- drivers/gpu/drm/gma500/psb_drv.c | 7 ++ drivers/gpu/drm/gma500/psb_drv.h | 1 + drivers/gpu/drm/gma500/psb_intel_drv.h | 4 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 4 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 8 ++ drivers/gpu/drm/i915/intel_crt.c | 4 +- drivers/gpu/drm/i915/intel_dp.c | 4 +- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_hdmi.c | 4 +- drivers/gpu/drm/i915/intel_lvds.c | 4 +- drivers/gpu/drm/i915/intel_sdvo.c | 4 +- drivers/gpu/drm/i915/intel_tv.c | 5 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 7 ++ drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 4 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 4 +- drivers/gpu/drm/msm/msm_drv.c | 6 ++ drivers/gpu/drm/msm/msm_drv.h | 1 + drivers/gpu/drm/nouveau/dispnv04/overlay.c | 6 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 7 ++ drivers/gpu/drm/nouveau/nouveau_drm.h | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 7 +- drivers/gpu/drm/omapdrm/omap_drv.c | 6 ++ drivers/gpu/drm/omapdrm/omap_drv.h | 5 +- drivers/gpu/drm/omapdrm/omap_plane.c | 4 +- drivers/gpu/drm/qxl/qxl_display.c | 4 +- drivers/gpu/drm/qxl/qxl_drv.c | 9 ++ drivers/gpu/drm/radeon/radeon_connectors.c | 9 +- drivers/gpu/drm/radeon/radeon_drv.c | 9 ++ drivers/gpu/drm/rcar-du/rcar_du_drv.c | 7 ++ drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 7 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +- drivers/gpu/drm/udl/udl_connector.c | 6 +- drivers/gpu/drm/udl/udl_drv.c | 8 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +- include/drm/drmP.h | 77 +++++++++++++++ include/drm/drm_atomic.h | 100 ++++++++++++++++++++ include/drm/drm_crtc.h | 14 +-- 66 files changed, 630 insertions(+), 113 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic.c create mode 100644 include/drm/drm_atomic.h
drivers/gpu/drm/Makefile +2 -1
@@ -13,7 +13,8 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \ - drm_rect.o drm_vma_manager.o drm_flip_work.o + drm_rect.o drm_vma_manager.o drm_flip_work.o \ + drm_atomic.o drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drivers/gpu/drm/armada/armada_crtc.c +2 -2
@@ -958,8 +958,8 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, }static int -armada_drm_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +armada_drm_crtc_set_property (struct drm_crtc *crtc,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {struct armada_private *priv = crtc->dev->dev_private;struct armada_crtc *dcrtc =drm_to_armada_crtc (crtc);
drivers/gpu/drm/armada/armada_output.c +2 -1
@@ -54,7 +54,8 @@ static void armada_drm_connector_destroy(struct drm_connector *conn) }static int armada_drm_connector_set_property (struct drm_connector *conn, -struct drm_property *property,uint64_t value) +void *state,struct drm_property *property,uint64_t value, +void *blob_data) {struct armada_connector *dconn =drm_to_armada_conn (conn);
drivers/gpu/drm/armada/armada_overlay.c +2 -2
@@ -282,8 +282,8 @@ static void armada_plane_destroy(struct drm_plane *plane)kfree (plane); } -static int armada_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +static int armada_plane_set_property (struct drm_plane *plane,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {struct armada_private *priv = plane->dev->dev_private;struct armada_plane *dplane =drm_to_armada_plane (plane);
drivers/gpu/drm/ast/ast_drv.c +6 -0
@@ -216,6 +216,12 @@ static struct drm_driver driver = { .dumb_map_offset = ast_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, };static int __init ast_init (void )
drivers/gpu/drm/ast/ast_drv.h +1 -0
@@ -29,6 +29,7 @@#define __AST_DRV_H__#include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h>
drivers/gpu/drm/cirrus/cirrus_drv.c +6 -0
@@ -101,6 +101,12 @@ static struct drm_driver driver = { .dumb_create = cirrus_dumb_create, .dumb_map_offset = cirrus_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, };static struct pci_driver cirrus_pci_driver = {
drivers/gpu/drm/cirrus/cirrus_drv.h +1 -0
@@ -14,6 +14,7 @@#include <video/vga.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h>
drivers/gpu/drm/drm_atomic.c new file +135 -0
135 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +87 -54
200 lines not on this page · raw message
drivers/gpu/drm/exynos/exynos_drm_crtc.c +3 -1
@@ -254,8 +254,10 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) }static int exynos_drm_crtc_set_property (struct drm_crtc *crtc, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_device *dev = crtc->dev;struct exynos_drm_private *dev_priv = dev->dev_private;
drivers/gpu/drm/exynos/exynos_drm_drv.c +7 -0
@@ -13,6 +13,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <linux/anon_inodes.h>
@@ -303,6 +304,12 @@ static struct drm_driver exynos_drm_driver = { .dumb_create = exynos_drm_gem_dumb_create, .dumb_map_offset = exynos_drm_gem_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = exynos_dmabuf_prime_export,
drivers/gpu/drm/exynos/exynos_drm_plane.c +3 -1
@@ -217,8 +217,10 @@ static void exynos_plane_destroy(struct drm_plane *plane) }static int exynos_plane_set_property (struct drm_plane *plane, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_device *dev = plane->dev;struct exynos_plane *exynos_plane =to_exynos_plane (plane);
drivers/gpu/drm/gma500/cdv_intel_crt.c +3 -1
@@ -212,8 +212,10 @@ static int cdv_intel_crt_get_modes(struct drm_connector *connector) }static int cdv_intel_crt_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {return 0 ; }
drivers/gpu/drm/gma500/cdv_intel_dp.c +3 -1
@@ -1645,8 +1645,10 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector)static int cdv_intel_dp_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_psb_private *dev_priv = connector->dev->dev_private;struct gma_encoder *encoder =gma_attached_encoder (connector);
drivers/gpu/drm/gma500/cdv_intel_hdmi.c +3 -1
@@ -157,8 +157,10 @@ static enum drm_connector_status cdv_hdmi_detect( }static int cdv_hdmi_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/cdv_intel_lvds.c +3 -1
@@ -452,8 +452,10 @@ static void cdv_intel_lvds_destroy(struct drm_connector *connector) }static int cdv_intel_lvds_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/mdfld_dsi_output.c +3 -1
@@ -243,8 +243,10 @@ mdfld_dsi_connector_detect(struct drm_connector *connector, bool force) }static int mdfld_dsi_connector_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/psb_drv.c +7 -0
@@ -676,6 +676,13 @@ static struct drm_driver driver = { .preclose = psb_driver_preclose, .postclose = psb_driver_close, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .gem_free_object = psb_gem_free_object, .gem_vm_ops = &psb_gem_vm_ops, .dumb_create = psb_gem_dumb_create,
drivers/gpu/drm/gma500/psb_drv.h +1 -0
@@ -25,6 +25,7 @@#include <drm/drmP.h> #include <drm/drm_global.h> #include <drm/gma_drm.h> +#include <drm/drm_atomic.h> #include "psb_reg.h" #include "psb_intel_drv.h" #include "gma_display.h"
drivers/gpu/drm/gma500/psb_intel_drv.h +3 -1
@@ -256,8 +256,10 @@ extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,extern int psb_intel_lvds_mode_valid (struct drm_connector *connector,struct drm_display_mode *mode);extern int psb_intel_lvds_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value); +uint64_t value, +void *blob_data);extern void psb_intel_lvds_destroy (struct drm_connector *connector);extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
drivers/gpu/drm/gma500/psb_intel_lvds.c +3 -1
@@ -569,8 +569,10 @@ void psb_intel_lvds_destroy(struct drm_connector *connector) }int psb_intel_lvds_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/psb_intel_sdvo.c +3 -1
@@ -1705,8 +1705,10 @@ static bool psb_intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)static int psb_intel_sdvo_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct psb_intel_sdvo *psb_intel_sdvo =intel_attached_sdvo (connector);struct psb_intel_sdvo_connector *psb_intel_sdvo_connector =to_psb_intel_sdvo_connector (connector);
drivers/gpu/drm/i915/i915_drv.c +8 -0
@@ -951,6 +951,14 @@ static struct drm_driver driver = { .dumb_create = i915_gem_dumb_create, .dumb_map_offset = i915_gem_mmap_gtt, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .ioctls = i915_ioctls, .fops = &i915_driver_fops, .name = DRIVER_NAME,
drivers/gpu/drm/i915/intel_crt.c +3 -1
@@ -700,8 +700,10 @@ static int intel_crt_get_modes(struct drm_connector *connector) }static int intel_crt_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {return 0 ; }
drivers/gpu/drm/i915/intel_dp.c +3 -1
@@ -3308,8 +3308,10 @@ intel_dp_detect_audio(struct drm_connector *connector)static int intel_dp_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_i915_private *dev_priv = connector->dev->dev_private;struct intel_connector *intel_connector =to_intel_connector (connector);
drivers/gpu/drm/i915/intel_drv.h +1 -0
@@ -31,6 +31,7 @@#include "i915_drv.h" #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_helper.h> #include <drm/drm_dp_helper.h>
drivers/gpu/drm/i915/intel_hdmi.c +3 -1
@@ -980,8 +980,10 @@ intel_hdmi_detect_audio(struct drm_connector *connector)static int intel_hdmi_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct intel_hdmi *intel_hdmi =intel_attached_hdmi (connector); struct intel_digital_port *intel_dig_port =
drivers/gpu/drm/i915/intel_lvds.c +3 -1
@@ -493,8 +493,10 @@ static void intel_lvds_destroy(struct drm_connector *connector) }static int intel_lvds_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct intel_connector *intel_connector =to_intel_connector (connector);struct drm_device *dev = connector->dev;
drivers/gpu/drm/i915/intel_sdvo.c +3 -1
@@ -2052,8 +2052,10 @@ static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)static int intel_sdvo_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct intel_sdvo *intel_sdvo =intel_attached_sdvo (connector);struct intel_sdvo_connector *intel_sdvo_connector =to_intel_sdvo_connector (connector);
drivers/gpu/drm/i915/intel_tv.c +3 -2
@@ -1446,8 +1446,9 @@ intel_tv_destroy(struct drm_connector *connector)static int -intel_tv_set_property (struct drm_connector *connector,struct drm_property *property, -uint64_t val) +intel_tv_set_property (struct drm_connector *connector,void *state, +struct drm_property *property, +uint64_t val,void *blob_data) {struct drm_device *dev = connector->dev;struct intel_tv *intel_tv =intel_attached_tv (connector);
drivers/gpu/drm/mgag200/mgag200_drv.c +7 -0
@@ -103,6 +103,13 @@ static struct drm_driver driver = { .dumb_create = mgag200_dumb_create, .dumb_map_offset = mgag200_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, };static struct pci_driver mgag200_pci_driver = {
drivers/gpu/drm/mgag200/mgag200_drv.h +1 -0
@@ -16,6 +16,7 @@#include <video/vga.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_placement.h>
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +2 -2
@@ -467,8 +467,8 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc,return msm_gem_queue_inactive_cb (obj, &mdp4_crtc->pageflip_cb); } -static int mdp4_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +static int mdp4_crtc_set_property (struct drm_crtc *crtc,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +2 -2
@@ -84,8 +84,8 @@ void mdp4_plane_install_properties(struct drm_plane *plane,// XXX } -int mdp4_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +int mdp4_plane_set_property (struct drm_plane *plane,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +2 -2
@@ -385,8 +385,8 @@ static int mdp5_crtc_page_flip(struct drm_crtc *crtc,return msm_gem_queue_inactive_cb (obj, &mdp5_crtc->pageflip_cb); } -static int mdp5_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +static int mdp5_crtc_set_property (struct drm_crtc *crtc,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +2 -2
@@ -99,8 +99,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane,// XXX } -int mdp5_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +int mdp5_plane_set_property (struct drm_plane *plane,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/msm_drv.c +6 -0
@@ -815,6 +815,12 @@ static struct drm_driver msm_driver = { .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, .gem_prime_vmap = msm_gem_prime_vmap, .gem_prime_vunmap = msm_gem_prime_vunmap, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, #ifdef CONFIG_DEBUG_FS .debugfs_init = msm_debugfs_init, .debugfs_cleanup = msm_debugfs_cleanup,
drivers/gpu/drm/msm/msm_drv.h +1 -0
@@ -50,6 +50,7 @@ static inline struct device *msm_iommu_get_ctx(const char *ctx_name)#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/msm_drm.h> struct msm_kms ;
drivers/gpu/drm/nouveau/dispnv04/overlay.c +3 -3
@@ -220,9 +220,9 @@ nv10_set_params(struct nouveau_plane *plane) }static int -nv_set_property (struct drm_plane *plane, -struct drm_property *property, -uint64_t value) +nv_set_property (struct drm_plane *plane,void *state, +struct drm_property *property, +uint64_t value,void *blob_data) {struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
drivers/gpu/drm/nouveau/nouveau_connector.c +2 -1
@@ -447,7 +447,8 @@ nouveau_connector_force(struct drm_connector *connector)static int nouveau_connector_set_property (struct drm_connector *connector, -struct drm_property *property,uint64_t value) +void *state,struct drm_property *property, +uint64_t value,void *blob_data) {struct nouveau_display *disp =nouveau_display (connector->dev);struct nouveau_connector *nv_connector =nouveau_connector (connector);
drivers/gpu/drm/nouveau/nouveau_drm.c +7 -0
@@ -833,6 +833,13 @@ driver = { .dumb_map_offset = nouveau_display_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .name = DRIVER_NAME, .desc =DRIVER_DESC , #ifdef GIT_REVISION
drivers/gpu/drm/nouveau/nouveau_drm.h +1 -0
@@ -29,6 +29,7 @@#include <subdev/vm.h> #include <drmP.h> +#include <drm/drm_atomic.h> #include <drm/nouveau_drm.h> #include <drm/ttm/ttm_bo_api.h>
drivers/gpu/drm/omapdrm/omap_crtc.c +4 -3
@@ -362,8 +362,8 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,return 0 ; } -static int omap_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +static int omap_crtc_set_property (struct drm_crtc *crtc,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {struct omap_crtc *omap_crtc =to_omap_crtc (crtc);struct omap_drm_private *priv = crtc->dev->dev_private;
@@ -373,7 +373,8 @@ static int omap_crtc_set_property(struct drm_crtc *crtc, !!(val & ((1LL <<DRM_ROTATE_90 ) | (1LL <<DRM_ROTATE_270 ))); } -return omap_plane_set_property (omap_crtc->plane, property, val); +return omap_plane_set_property (omap_crtc->plane, state, + property, val, blob_data); }static const struct drm_crtc_funcs omap_crtc_funcs = {
drivers/gpu/drm/omapdrm/omap_drv.c +6 -0
@@ -645,6 +645,12 @@ static struct drm_driver omap_drm_driver = { .dumb_create = omap_gem_dumb_create, .dumb_map_offset = omap_gem_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .ioctls = ioctls, .num_ioctls = DRM_OMAP_NUM_IOCTLS, .fops = &omapdriver_fops,
drivers/gpu/drm/omapdrm/omap_drv.h +3 -2
@@ -25,6 +25,7 @@#include <linux/types.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/omap_drm.h> #include <linux/platform_data/omap_drm.h>
@@ -176,8 +177,8 @@ int omap_plane_mode_set(struct drm_plane *plane, void (*fxn)(void *), void *arg);void omap_plane_install_properties (struct drm_plane *plane,struct drm_mode_object *obj); -int omap_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val); +int omap_plane_set_property (struct drm_plane *plane,void *state, +struct drm_property *property,uint64_t val,void *blob_data);struct drm_encoder *omap_encoder_init (struct drm_device *dev,struct omap_dss_device *dssdev);
drivers/gpu/drm/omapdrm/omap_plane.c +2 -2
@@ -327,8 +327,8 @@ void omap_plane_install_properties(struct drm_plane *plane,drm_object_attach_property (obj, prop,0 ); } -int omap_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +int omap_plane_set_property (struct drm_plane *plane,void *state, +struct drm_property *property,uint64_t val,void *blob_data) {struct omap_plane *omap_plane =to_omap_plane (plane);struct omap_drm_private *priv = plane->dev->dev_private;
drivers/gpu/drm/qxl/qxl_display.c +3 -1
@@ -821,8 +821,10 @@ static enum drm_connector_status qxl_conn_detect( }static int qxl_conn_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {DRM_DEBUG ("\n" );return 0 ;
drivers/gpu/drm/qxl/qxl_drv.c +9 -0
@@ -34,6 +34,7 @@#include "drmP.h" #include "drm/drm.h" #include "drm_crtc_helper.h" +#include "drm_atomic.h" #include "qxl_drv.h" #include "qxl_object.h"
@@ -221,6 +222,14 @@ static struct drm_driver qxl_driver = { .dumb_create = qxl_mode_dumb_create, .dumb_map_offset = qxl_mode_dumb_mmap, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, +#if defined(CONFIG_DEBUG_FS ) .debugfs_init = qxl_debugfs_init, .debugfs_cleanup = qxl_debugfs_takedown,
drivers/gpu/drm/radeon/radeon_connectors.c +6 -3
@@ -359,8 +359,9 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn } } -static int radeon_connector_set_property (struct drm_connector *connector,struct drm_property *property, -uint64_t val) +static int radeon_connector_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, +uint64_t val,void *blob_data) {struct drm_device *dev = connector->dev;struct radeon_device *rdev = dev->dev_private;
@@ -682,8 +683,10 @@ static void radeon_connector_destroy(struct drm_connector *connector) }static int radeon_lvds_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_device *dev = connector->dev;struct radeon_encoder *radeon_encoder;
drivers/gpu/drm/radeon/radeon_drv.c +9 -0
@@ -34,6 +34,7 @@#include "radeon_drv.h" #include <drm/drm_pciids.h> +#include <drm/drm_atomic.h> #include <linux/console.h> #include <linux/module.h> #include <linux/pm_runtime.h>
@@ -554,6 +555,14 @@ static struct drm_driver kms_driver = { .dumb_create = radeon_mode_dumb_create, .dumb_map_offset = radeon_mode_dumb_mmap, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .fops = &radeon_driver_kms_fops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
drivers/gpu/drm/rcar-du/rcar_du_drv.c +7 -0
@@ -21,6 +21,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -175,6 +176,12 @@ static struct drm_driver rcar_du_driver = { .dumb_create = rcar_du_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .fops = &rcar_du_fops, .name = "rcar-du", .desc = "Renesas R-Car Display Unit",
drivers/gpu/drm/rcar-du/rcar_du_plane.c +3 -1
@@ -397,8 +397,10 @@ done: }static int rcar_du_plane_set_property (struct drm_plane *plane, +void *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct rcar_du_plane *rplane =to_rcar_plane (plane);struct rcar_du_group *rgrp = rplane->group;
drivers/gpu/drm/shmobile/shmob_drm_drv.c +7 -0
@@ -21,6 +21,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_gem_cma_helper.h> #include "shmob_drm_crtc.h"
@@ -285,6 +286,12 @@ static struct drm_driver shmob_drm_driver = { .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .fops = &shmob_drm_fops, .name = "shmob-drm", .desc = "Renesas SH Mobile DRM",
drivers/gpu/drm/tilcdc/tilcdc_drv.c +6 -0
@@ -519,6 +519,12 @@ static struct drm_driver tilcdc_driver = { .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, #ifdef CONFIG_DEBUG_FS .debugfs_init = tilcdc_debugfs_init, .debugfs_cleanup = tilcdc_debugfs_cleanup,
drivers/gpu/drm/tilcdc/tilcdc_drv.h +1 -0
@@ -31,6 +31,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
drivers/gpu/drm/tilcdc/tilcdc_slave.c +2 -1
@@ -206,7 +206,8 @@ static struct drm_encoder *slave_connector_best_encoder( }static int slave_connector_set_property (struct drm_connector *connector, -struct drm_property *property,uint64_t value) +void *state,struct drm_property *property, +uint64_t value,void *blob_data) {struct drm_encoder *encoder =to_slave_connector (connector)->encoder; return get_slave_funcs(encoder)->set_property(encoder,
drivers/gpu/drm/udl/udl_connector.c +3 -3
@@ -115,9 +115,9 @@ udl_best_single_encoder(struct drm_connector *connector)return encoder; } -static int udl_connector_set_property (struct drm_connector *connector, -struct drm_property *property, -uint64_t val) +static int udl_connector_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, +uint64_t val,void *blob_data) {return 0 ; }
drivers/gpu/drm/udl/udl_drv.c +8 -0
@@ -9,6 +9,7 @@#include <linux/module.h> #include <drm/drm_usb.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "udl_drv.h" static struct drm_driver driver;
@@ -88,6 +89,13 @@ static struct drm_driver driver = { .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = udl_gem_prime_import, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE,
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +7 -0
@@ -1349,6 +1349,13 @@ static struct drm_driver driver = { .prime_fd_to_handle = vmw_prime_fd_to_handle, .prime_handle_to_fd = vmw_prime_handle_to_fd, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC,
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +1 -0
@@ -30,6 +30,7 @@#include "vmwgfx_reg.h" #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/vmwgfx_drm.h> #include <drm/drm_hashtab.h> #include <linux/suspend.h>
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +3 -1
@@ -2009,8 +2009,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, }int vmw_du_connector_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {return 0 ; }
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +3 -1
@@ -141,8 +141,10 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force);int vmw_du_connector_fill_modes (struct drm_connector *connector,uint32_t max_width,uint32_t max_height);int vmw_du_connector_set_property (struct drm_connector *connector, +void *state,struct drm_property *property, -uint64_t val); +uint64_t val, +void *blob_data);/*
include/drm/drmP.h +77 -0
83 lines not on this page · raw message
include/drm/drm_atomic.h new file +100 -0
100 lines not on this page · raw message
include/drm/drm_crtc.h +8 -6
@@ -378,8 +378,9 @@ struct drm_crtc_funcs {struct drm_pending_vblank_event *event, uint32_t flags); -int (*set_property)(struct drm_crtc *crtc, -struct drm_property *property,uint64_t val); +int (*set_property)(struct drm_crtc *crtc,void *state, +struct drm_property *property,uint64_t val, +void *blob_data); };/**
@@ -489,8 +490,8 @@ struct drm_connector_funcs {enum drm_connector_status (*detect)(struct drm_connector *connector,bool force);int (*fill_modes)(struct drm_connector *connector,uint32_t max_width,uint32_t max_height); -int (*set_property)(struct drm_connector *connector,struct drm_property *property, -uint64_t val); +int (*set_property)(struct drm_connector *connector,void *state, +struct drm_property *property,uint64_t val,void *blob_data);void (*destroy)(struct drm_connector *connector);void (*force)(struct drm_connector *connector); };
@@ -661,8 +662,9 @@ struct drm_plane_funcs {int (*disable_plane)(struct drm_plane *plane);void (*destroy)(struct drm_plane *plane); -int (*set_property)(struct drm_plane *plane, -struct drm_property *property,uint64_t val); +int (*set_property)(struct drm_plane *plane,void *state, +struct drm_property *property,uint64_t val, +void *blob_data); };enum drm_plane_type {
Signature · 1 line
1.8.5.3
PATCH 3/16 drm: convert crtc to ww_mutex
In reply to Rob ClarkFor atomic, it will be quite convenient to not have to care so much about locking order. And 'state' gives us a convenient place to stash a ww_ctx for any sort of update that needs to grab multiple crtc locks.
Because we will want to eventually make locking even more fine grained (giving locks to planes, connectors, etc), split out drm_modeset_lock so that the atomic state won't eventually have to keep separate lists of locked planes/crtcs/etc.
The state keeps track of which locks it has aquired, and for the benefit of NONBLOCK operations, supports transfering "locked" resources to driver worker/thread to complete the asynchronous state change.
--- drivers/gpu/drm/drm_atomic.c | 141 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/drm_crtc.c | 107 +++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_display.c | 12 +-- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +-- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +- include/drm/drmP.h | 5 -- include/drm/drm_atomic.h | 18 +++++ include/drm/drm_crtc.h | 75 +++++++++++++++++-- include/uapi/drm/drm_mode.h | 3 + 9 files changed, 342 insertions(+), 37 deletions(-)
drivers/gpu/drm/drm_atomic.c +138 -3
@@ -49,9 +49,14 @@ void *drm_atomic_begin(struct drm_device *dev, uint32_t flags) state = ptr; ptr = &state[1 ]; +ww_acquire_init (&state->ww_ctx, &crtc_ww_class); +INIT_LIST_HEAD (&state->locked); + +mutex_init (&state->mutex);kref_init (&state->refcount); state->dev = dev; state->flags = flags; +return state; }EXPORT_SYMBOL (drm_atomic_begin);
@@ -87,10 +92,108 @@ EXPORT_SYMBOL(drm_atomic_set_event);*/ int drm_atomic_check (struct drm_device *dev,void *state) { + a->checked = true;return 0 ;/* for now */ }EXPORT_SYMBOL (drm_atomic_check); +/* Note that we drop and re-acquire the locks w/ ww_mutex directly, +* since we keep the crtc in our list with in_atomic == true. +*/ + +static void drop_locks (struct drm_atomic_state *a, +struct ww_acquire_ctx *ww_ctx) +{ +struct drm_modeset_lock *lock; + +mutex_lock (&a->mutex); +list_for_each_entry (lock, &a->locked, head) +ww_mutex_unlock (&lock->mutex); +mutex_unlock (&a->mutex); + +ww_acquire_fini (ww_ctx); +} + +static void grab_locks (struct drm_atomic_state *a, +struct ww_acquire_ctx *ww_ctx) +{ +struct drm_modeset_lock *lock, *slow_locked, *contended; +int ret; + + lock = slow_locked = contended =NULL ; + + +ww_acquire_init (ww_ctx, &crtc_ww_class); + +/* +* We need to do proper rain^Hww dance.. another context +* could sneak in a grab the lock in order to check +* crtc->in_atomic, and we get -EDEADLK. But the winner +* will realize the mistake when it sees crtc->in_atomic +* already set, and then drop lock and return -EBUSY. +* So we just need to keep dancing until we win. +*/ +retry: + ret =0 ; +list_for_each_entry (lock, &a->locked, head) { +if (lock == slow_locked) { + slow_locked =NULL ; +continue ; + } + contended = lock; + ret =ww_mutex_lock (&lock->mutex, ww_ctx); +if (ret) + goto fail; + } + +fail: +if (ret == -EDEADLK ) { +/* we lost out in a seqno race, backoff, lock and retry.. */ + +list_for_each_entry (lock, &a->locked, head) { +if (lock == contended) +break ; +ww_mutex_unlock (&lock->mutex); + } + +if (slow_locked) +ww_mutex_unlock (&slow_locked->mutex); + +ww_mutex_lock_slow (&contended->mutex, ww_ctx); + slow_locked = contended; + goto retry; + } +WARN_ON (ret);/* if we get EALREADY then something is fubar */ +} + +static void commit_locks (struct drm_atomic_state *a, +struct ww_acquire_ctx *ww_ctx) +{ +/* and properly release them (clear in_atomic, remove from list): */ +mutex_lock (&a->mutex); +while (!list_empty (&a->locked)) { +struct drm_modeset_lock *lock; + + lock =list_first_entry (&a->locked, + struct drm_modeset_lock, head); + +drm_modeset_unlock (lock); + } +mutex_unlock (&a->mutex); +ww_acquire_fini (ww_ctx); + a->committed = true; +} + +static int atomic_commit (struct drm_atomic_state *a, +struct ww_acquire_ctx *ww_ctx) +{ +int ret =0 ; + +commit_locks (a, ww_ctx); + +return ret; +} +/** * drm_atomic_commit - commit state * @dev: DRM device
@@ -104,11 +207,26 @@ EXPORT_SYMBOL(drm_atomic_check);*/ int drm_atomic_commit (struct drm_device *dev,void *state) { -return 0 ;/* for now */ +struct drm_atomic_state *a = state; +return atomic_commit (a, &a->ww_ctx); }EXPORT_SYMBOL (drm_atomic_commit);/** +* drm_atomic_commit_unlocked - like drm_atomic_commit +* but can be called back by driver in other thread. Manages the lock +* transfer from initiating thread. +*/ +int drm_atomic_commit_unlocked (struct drm_device *dev,void *state) +{ +struct drm_atomic_state *a = state; +struct ww_acquire_ctx ww_ctx; +grab_locks (a, &ww_ctx); +return atomic_commit (a, &ww_ctx); +} +EXPORT_SYMBOL (drm_atomic_commit_unlocked); + +/** * drm_atomic_end - conclude the atomic update * @dev: DRM device * @state: the driver private state object
@@ -117,15 +235,32 @@ EXPORT_SYMBOL(drm_atomic_commit);*/ void drm_atomic_end (struct drm_device *dev,void *state) { +struct drm_atomic_state *a = state; + +/* if commit is happening from another thread, it will +* block grabbing locks until we drop (and not set +* a->committed until after), so this is not a race: +*/ +if (!a->committed) +drop_locks (a, &a->ww_ctx); +drm_atomic_state_unreference (state); }EXPORT_SYMBOL (drm_atomic_end);void _drm_atomic_state_free (struct kref *kref) { -struct drm_atomic_state *state = +struct drm_atomic_state *a = container_of(kref, struct drm_atomic_state, refcount); -kfree (state); + +/* in case we haven't already: */ +if (!a->committed) { +grab_locks (a, &a->ww_ctx); +commit_locks (a, &a->ww_ctx); + } + +mutex_destroy (&a->mutex); +kfree (a); }EXPORT_SYMBOL (_drm_atomic_state_free);
drivers/gpu/drm/drm_crtc.c +98 -9
173 lines not on this page · raw message
drivers/gpu/drm/i915/intel_display.c +6 -6
@@ -2285,7 +2285,7 @@ void intel_display_handle_reset(struct drm_device *dev)list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) {struct intel_crtc *intel_crtc =to_intel_crtc (crtc); -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );/* * FIXME: Once we have proper support for primary planes (and * disabling them without disabling the entire crtc) allow again
@@ -2296,7 +2296,7 @@ void intel_display_handle_reset(struct drm_device *dev) crtc->primary->fb, crtc->x, crtc->y); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); } }
@@ -7817,7 +7817,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL ); old->dpms_mode = connector->dpms; old->load_detect_temp = false;
@@ -7848,7 +7848,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,return false; } -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL ); intel_encoder->new_crtc =to_intel_crtc (crtc);to_intel_connector (connector)->new_encoder = intel_encoder;
@@ -7927,7 +7927,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,drm_framebuffer_unreference (old->release_fb); } -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);return ; }
@@ -7935,7 +7935,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,if (old->dpms_mode !=DRM_MODE_DPMS_ON ) connector->funcs->dpms (connector, old->dpms_mode); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); } static int i9xx_pll_refclk(struct drm_device *dev,
drivers/gpu/drm/omapdrm/omap_crtc.c +5 -5
@@ -307,13 +307,13 @@ static void page_flip_worker(struct work_struct *work)struct drm_display_mode *mode = &crtc->mode;struct drm_gem_object *bo; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );omap_plane_mode_set (omap_crtc->plane, crtc, crtc->fb,0 ,0 , mode->hdisplay, mode->vdisplay, crtc->x <<16 , crtc->y <<16 , mode->hdisplay <<16 , mode->vdisplay <<16 , vblank_cb, crtc); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); bo =omap_framebuffer_bo (crtc->fb,0 );drm_gem_object_unreference_unlocked (bo);
@@ -447,7 +447,7 @@ static void apply_worker(struct work_struct *work)* the callbacks and list modification all serialized * with respect to modesetting ioctls from userspace. */ -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );dispc_runtime_get ();/*
@@ -492,7 +492,7 @@ static void apply_worker(struct work_struct *work) out:dispc_runtime_put (); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); } int omap_crtc_apply(struct drm_crtc *crtc,
@@ -500,7 +500,7 @@ int omap_crtc_apply(struct drm_crtc *crtc, {struct omap_crtc *omap_crtc =to_omap_crtc (crtc); -WARN_ON (!mutex_is_locked (&crtc->mutex)); +WARN_ON (!drm_modeset_is_locked (&crtc->mutex));/* no need to queue it again if it is already queued: */ if (apply->queued)
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +4 -4
@@ -187,7 +187,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,* can do this since the caller in the drm core doesn't check anything * which is protected by any looks. */ -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);drm_modeset_lock_all (dev_priv->dev);/* A lot of the code assumes this */
@@ -252,7 +252,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ret =0 ; out:drm_modeset_unlock_all (dev_priv->dev); -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );return ret; }
@@ -273,7 +273,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)* can do this since the caller in the drm core doesn't check anything * which is protected by any looks. */ -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);drm_modeset_lock_all (dev_priv->dev); vmw_cursor_update_position(dev_priv, shown,
@@ -281,7 +281,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) du->cursor_y + du->hotspot_y);drm_modeset_unlock_all (dev_priv->dev); -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );return 0 ; }
include/drm/drmP.h +0 -5
@@ -1318,11 +1318,6 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)return ret; } -static inline bool drm_modeset_is_locked (struct drm_device *dev) -{ -return mutex_is_locked (&dev->mode_config.mutex); -} -static inline bool drm_is_render_client (struct drm_file *file_priv) {return file_priv->minor->type ==DRM_MINOR_RENDER ;
include/drm/drm_atomic.h +18 -0
@@ -73,6 +73,7 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_pending_vblank_event *event);int drm_atomic_check (struct drm_device *dev,void *state);int drm_atomic_commit (struct drm_device *dev,void *state); +int drm_atomic_commit_unlocked (struct drm_device *dev,void *state);void drm_atomic_end (struct drm_device *dev,void *state);/**
@@ -82,6 +83,23 @@ struct drm_atomic_state {struct kref refcount;struct drm_device *dev;uint32_t flags; + +bool committed; +bool checked;/* just for debugging */ + +struct ww_acquire_ctx ww_ctx; +/* list of 'struct drm_modeset_lock': */ +struct list_head locked; + +/* currently simply for protecting against 'locked' list manipulation +* between original thread calling atomic->end() and driver thread +* calling back drm_atomic_commit_unlocked(). +* +* Other spots are sufficiently synchronized by virtue of holding +* the lock's ww_mutex. But during the lock/resource hand-over to the +* driver thread (drop_locks()/grab_locks()), we cannot rely on this. +*/ +struct mutex mutex; }; static inline void
include/drm/drm_crtc.h +70 -5
105 lines not on this page · raw message
include/uapi/drm/drm_mode.h +3 -0
@@ -496,4 +496,7 @@ struct drm_mode_destroy_dumb { uint32_t handle; }; +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_NOLOCK 0x8000/* only used internally */ +#endif
Signature · 1 line
1.8.5.3
PATCH 4/16 drm: add object property type
In reply to Rob ClarkAn object property is an id (idr) for a drm mode object. This will allow a property to be used set/get a framebuffer, CRTC, etc.
--- drivers/gpu/drm/drm_crtc.c | 60 +++++++++++++++++++++++++++++++++++---------- include/drm/drm_crtc.h | 27 ++++++++++++++++++++ include/uapi/drm/drm_mode.h | 14 +++++++++++ 3 files changed, 88 insertions(+), 13 deletions(-)
drivers/gpu/drm/drm_crtc.c +47 -13
@@ -3207,6 +3207,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,if (!property)return NULL ; + property->dev = dev; +if (num_values) { property->values =kzalloc (sizeof (uint64_t )*num_values,GFP_KERNEL );if (!property->values)
@@ -3227,6 +3229,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, }list_add_tail (&property->head, &dev->mode_config.property_list); + +BUG_ON (!drm_property_type_valid (property)); +return property; fail:kfree (property->values);
@@ -3310,19 +3315,38 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags }EXPORT_SYMBOL (drm_property_create_range); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type) +{ +struct drm_property *property; + + flags |=DRM_MODE_PROP_OBJECT ; + + property =drm_property_create (dev, flags, name,1 ); +if (!property) +return NULL ; + + property->values[0 ] = type; + +return property; +} +EXPORT_SYMBOL (drm_property_create_object); +int drm_property_add_enum (struct drm_property *property,int index,uint64_t value,const char *name) {struct drm_property_enum *prop_enum; -if (!(property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK ))) +if (!(drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )))return -EINVAL ;/* * Bitmask enum properties have the additional constraint of values * from 0 to 63 */ -if ((property->flags &DRM_MODE_PROP_BITMASK ) && (value >63 )) +if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK ) && + (value >63 ))return -EINVAL ;if (!list_empty (&property->enum_blob_list)) {
@@ -3447,10 +3471,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } property =obj_to_property (obj); -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {list_for_each_entry (prop_enum, &property->enum_blob_list, head) enum_count++; - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {list_for_each_entry (prop_blob, &property->enum_blob_list, head) blob_count++; }
@@ -3472,7 +3497,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } out_resp->count_values = value_count; -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied =0 ; enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long )out_resp->enum_blob_ptr;
@@ -3494,7 +3520,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->count_enum_blobs = enum_count; } -if (property->flags &DRM_MODE_PROP_BLOB ) { +if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { copied =0 ; blob_id_ptr = (uint32_t __user *)(unsigned long )out_resp->enum_blob_ptr;
@@ -3625,19 +3651,25 @@ static bool drm_property_change_is_valid(struct drm_property *property, {if (property->flags &DRM_MODE_PROP_IMMUTABLE )return false; -if (property->flags &DRM_MODE_PROP_RANGE ) { + +if (drm_property_type_is (property,DRM_MODE_PROP_RANGE )) {if (value < property->values[0 ] || value > property->values[1 ])return false;return true; - }else if (property->flags &DRM_MODE_PROP_BITMASK ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {int i;uint64_t valid_mask =0 ;for (i =0 ; i < property->num_values; i++) valid_mask |= (1ULL << property->values[i]);return !(value & ~valid_mask); - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {/* Only the driver knows */ return true; + }else if (drm_property_type_is (property,DRM_MODE_PROP_OBJECT )) { +/* a zero value for an object property translates to null: */ +if (value ==0 ) +return true; +return drm_property_get_obj (property, value) !=NULL ; }else {int i;for (i =0 ; i < property->num_values; i++)
@@ -3714,9 +3746,9 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,return ret; } -static int drm_mode_set_obj_prop (struct drm_device *dev, -struct drm_mode_object *obj,void *state, -struct drm_property *property,uint64_t value,void *blob_data) +static int drm_mode_set_obj_prop (struct drm_mode_object *obj, +void *state,struct drm_property *property, +uint64_t value,void *blob_data) {if (drm_property_change_is_valid (property, value)) {switch (obj->type) {
@@ -3730,6 +3762,8 @@ static int drm_mode_set_obj_prop(struct drm_device *dev,return drm_mode_plane_set_obj_prop (obj_to_plane (obj), state, property, value, blob_data); } + }else { +DRM_DEBUG ("invalid value: %s = %llx\n" , property->name, value); }return -EINVAL ;
@@ -3764,7 +3798,7 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, void *state,return -ENOENT ; property =obj_to_property (prop_obj); -return drm_mode_set_obj_prop (dev, arg_obj, state, property, +return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data); }
include/drm/drm_crtc.h +27 -0
@@ -308,6 +308,7 @@ struct drm_property {char name[DRM_PROP_NAME_LEN ];uint32_t num_values;uint64_t *values; +struct drm_device *dev;struct list_head enum_blob_list; };
@@ -1204,6 +1205,23 @@ extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,extern void drm_mode_connector_list_update (struct drm_connector *connector);extern int drm_mode_connector_update_edid_property (struct drm_connector *connector,struct edid *edid); + +static inline bool drm_property_type_is (struct drm_property *property, +uint32_t type) +{ +/* instanceof for props.. handles extended type vs original types: */ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) == type; +return property->flags & type; +} + +static inline bool drm_property_type_valid (struct drm_property *property) +{ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return !(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +return !!(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +} +extern int drm_object_property_set_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t val);
@@ -1237,6 +1255,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,struct drm_property *drm_property_create_range (struct drm_device *dev,int flags,const char *name,uint64_t min,uint64_t max); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type);extern void drm_property_destroy (struct drm_device *dev,struct drm_property *property);extern int drm_property_add_enum (struct drm_property *property,int index,uint64_t value,const char *name);
@@ -1255,6 +1275,13 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, int gamma_size);extern struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type); + +static inline struct drm_mode_object * +drm_property_get_obj (struct drm_property *property,uint64_t value) +{ +return drm_mode_object_find (property->dev, value, property->values[0 ]); +} +/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);
include/uapi/drm/drm_mode.h +14 -0
@@ -251,6 +251,20 @@ struct drm_mode_get_connector {#define DRM_MODE_PROP_BLOB (1<<4)#define DRM_MODE_PROP_BITMASK (1<<5)/* bitmask of enumerated types */ +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, +* grab a chunk of the bits to use as integer type id. +*/ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE (n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +struct drm_mode_property_enum {__u64 value;char name[DRM_PROP_NAME_LEN ];
Signature · 1 line
1.8.5.3
PATCH 5/16 drm: add signed-range property type
In reply to Rob ClarkLike range, but values are signed.
--- drivers/gpu/drm/drm_crtc.c | 29 +++++++++++++++++++++++++---- include/drm/drm_crtc.h | 12 ++++++++++++ include/uapi/drm/drm_mode.h | 1 + 3 files changed, 38 insertions(+), 4 deletions(-)
drivers/gpu/drm/drm_crtc.c +25 -4
@@ -3296,14 +3296,12 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev, }EXPORT_SYMBOL (drm_property_create_bitmask); -struct drm_property *drm_property_create_range (struct drm_device *dev,int flags, -const char *name, +static struct drm_property *property_create_range (struct drm_device *dev, +int flags,const char *name,uint64_t min,uint64_t max) {struct drm_property *property; - flags |=DRM_MODE_PROP_RANGE ; - property =drm_property_create (dev, flags, name,2 );if (!property)return NULL ;
@@ -3313,8 +3311,25 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flagsreturn property; } + +struct drm_property *drm_property_create_range (struct drm_device *dev,int flags, +const char *name, +uint64_t min,uint64_t max) +{ +return property_create_range (dev,DRM_MODE_PROP_RANGE | flags, + name, min, max); +}EXPORT_SYMBOL (drm_property_create_range); +struct drm_property *drm_property_create_signed_range (struct drm_device *dev, +int flags,const char *name, +int64_t min,int64_t max) +{ +return property_create_range (dev,DRM_MODE_PROP_SIGNED_RANGE | flags, + name,I642U64 (min),I642U64 (max)); +} +EXPORT_SYMBOL (drm_property_create_signed_range); +struct drm_property *drm_property_create_object (struct drm_device *dev,int flags,const char *name,uint32_t type) {
@@ -3656,6 +3671,12 @@ static bool drm_property_change_is_valid(struct drm_property *property,if (value < property->values[0 ] || value > property->values[1 ])return false;return true; + }else if (drm_property_type_is (property,DRM_MODE_PROP_SIGNED_RANGE )) { +int64_t svalue =U642I64 (value); +if (svalue <U642I64 (property->values[0 ]) || + svalue >U642I64 (property->values[1 ])) +return false; +return true; }else if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {int i;uint64_t valid_mask =0 ;
include/drm/drm_crtc.h +12 -0
@@ -66,6 +66,15 @@ struct drm_object_properties {uint64_t values[DRM_OBJECT_MAX_PROPERTY ]; }; +static inline int64_t U642I64 (uint64_t val) +{ +return (int64_t )*((int64_t *)&val); +} +static inline uint64_t I642U64 (int64_t val) +{ +return (uint64_t )*((uint64_t *)&val); +} +/* * Note on terminology: here, for brevity and convenience, we refer to connector * control chips as 'CRTCs'. They can control any type of connector, VGA, LVDS,
@@ -1255,6 +1264,9 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,struct drm_property *drm_property_create_range (struct drm_device *dev,int flags,const char *name,uint64_t min,uint64_t max); +struct drm_property *drm_property_create_signed_range (struct drm_device *dev, +int flags,const char *name, +int64_t min,int64_t max);struct drm_property *drm_property_create_object (struct drm_device *dev,int flags,const char *name,uint32_t type);extern void drm_property_destroy (struct drm_device *dev,struct drm_property *property);
include/uapi/drm/drm_mode.h +1 -0
@@ -264,6 +264,7 @@ struct drm_mode_get_connector {#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0#define DRM_MODE_PROP_TYPE (n) ((n) << 6)#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2)struct drm_mode_property_enum {__u64 value;
Signature · 1 line
1.8.5.3
PATCH 6/16 drm: helpers to find mode objects
In reply to Rob ClarkAdd a few more useful helpers to find mode objects.
--- drivers/gpu/drm/drm_crtc.c | 97 ++++++++++++++-------------------------------- include/drm/drm_crtc.h | 33 ++++++++++++++++ 2 files changed, 63 insertions(+), 67 deletions(-)
drivers/gpu/drm/drm_crtc.c +30 -67
@@ -1949,7 +1949,6 @@ int drm_mode_getcrtc(struct drm_device *dev, {struct drm_mode_crtc *crtc_resp = data;struct drm_crtc *crtc; -struct drm_mode_object *obj;int ret =0 ;if (!drm_core_check_feature (dev,DRIVER_MODESET ))
@@ -1957,13 +1956,11 @@ int drm_mode_getcrtc(struct drm_device *dev,drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_resp->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_resp->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); crtc_resp->x = crtc->x; crtc_resp->y = crtc->y;
@@ -2017,7 +2014,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_connector *out_resp = data; -struct drm_mode_object *obj;struct drm_connector *connector;struct drm_display_mode *mode;int mode_count =0 ;
@@ -2041,13 +2037,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,mutex_lock (&dev->mode_config.mutex); - obj =drm_mode_object_find (dev, out_resp->connector_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_resp->connector_id); +if (!connector) { ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj); props_count = connector->properties.count;
@@ -2149,7 +2143,6 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_encoder *enc_resp = data; -struct drm_mode_object *obj;struct drm_encoder *encoder;int ret =0 ;
@@ -2157,13 +2150,11 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, enc_resp->encoder_id, -DRM_MODE_OBJECT_ENCODER ); -if (!obj) { + encoder =drm_encoder_find (dev, enc_resp->encoder_id); +if (!encoder) { ret = -ENOENT ; goto out; } - encoder =obj_to_encoder (obj);if (encoder->crtc) enc_resp->crtc_id = encoder->crtc->base.id;
@@ -2252,7 +2243,6 @@ int drm_mode_getplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_plane *plane_resp = data; -struct drm_mode_object *obj;struct drm_plane *plane;uint32_t __user *format_ptr;int ret =0 ;
@@ -2261,13 +2251,11 @@ int drm_mode_getplane(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, plane_resp->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_resp->plane_id); +if (!plane) { ret = -ENOENT ; goto out; } - plane =obj_to_plane (obj);if (plane->crtc) plane_resp->crtc_id = plane->crtc->base.id;
@@ -2317,7 +2305,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_set_plane *plane_req = data; -struct drm_mode_object *obj;struct drm_plane *plane;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;
@@ -2332,14 +2319,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,* First, find the plane, crtc, and fb objects. If not available, * we don't bother to call the driver. */ - obj =drm_mode_object_find (dev, plane_req->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_req->plane_id); +if (!plane) {DRM_DEBUG_KMS ("Unknown plane ID %d\n" , plane_req->plane_id);return -ENOENT ; } - plane =obj_to_plane (obj);/* No fb means shut it down */ if (!plane_req->fb_id) {
@@ -2352,15 +2337,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, plane_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, plane_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown crtc ID %d\n" , plane_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); fb =drm_framebuffer_lookup (dev, plane_req->fb_id);if (!fb) {
@@ -2502,7 +2485,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, {struct drm_mode_config *config = &dev->mode_config;struct drm_mode_crtc *crtc_req = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_connector **connector_set =NULL , *connector;struct drm_framebuffer *fb =NULL ;
@@ -2520,14 +2502,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,return -ERANGE ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , crtc_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);DRM_DEBUG_KMS ("[CRTC:%d]\n" , crtc->base.id);if (crtc_req->mode_valid) {
@@ -2610,15 +2590,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, out_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_id); +if (!connector) {DRM_DEBUG_KMS ("Connector id %d unknown\n" , out_id); ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj);DRM_DEBUG_KMS ("[CONNECTOR:%d:%s]\n" , connector->base.id,drm_get_connector_name (connector));
@@ -2650,7 +2628,6 @@ static int drm_mode_cursor_common(struct drm_device *dev,struct drm_mode_cursor2 *req, struct drm_file *file_priv) { - struct drm_mode_object *obj; struct drm_crtc *crtc;int ret =0 ;
@@ -2660,12 +2637,11 @@ static int drm_mode_cursor_common(struct drm_device *dev,if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))return -EINVAL ; - obj =drm_mode_object_find (dev, req->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , req->crtc_id);return -ENOENT ; } - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (req->flags &DRM_MODE_CURSOR_BO ) {
@@ -3460,7 +3436,6 @@ EXPORT_SYMBOL(drm_object_property_get_value);int drm_mode_getproperty_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_property *out_resp = data;struct drm_property *property;int enum_count =0 ;
@@ -3479,12 +3454,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->prop_id,DRM_MODE_OBJECT_PROPERTY ); -if (!obj) { + property =drm_property_find (dev, out_resp->prop_id); +if (!property) { ret = -ENOENT ; goto done; } - property =obj_to_property (obj);if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) ||drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {
@@ -3600,7 +3574,6 @@ static void drm_property_destroy_blob(struct drm_device *dev,int drm_mode_getblob_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_blob *out_resp = data;struct drm_property_blob *blob;int ret =0 ;
@@ -3610,12 +3583,11 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->blob_id,DRM_MODE_OBJECT_BLOB ); -if (!obj) { + blob =drm_property_blob_find (dev, out_resp->blob_id); +if (!blob) { ret = -ENOENT ; goto done; } - blob =obj_to_blob (obj);if (out_resp->length == blob->length) { blob_ptr = (void __user *)(unsigned long )out_resp->data;
@@ -3796,7 +3768,6 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, void *state, uint32_t prop_id, uint64_t value, void *blob_data) { struct drm_mode_object *arg_obj; -struct drm_mode_object *prop_obj;struct drm_property *property;int i;
@@ -3813,11 +3784,9 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, void *state,if (i == arg_obj->properties->count)return -EINVAL ; - prop_obj =drm_mode_object_find (dev, prop_id, -DRM_MODE_OBJECT_PROPERTY ); -if (!prop_obj) + property =drm_property_find (dev, prop_id); +if (!property)return -ENOENT ; - property =obj_to_property (prop_obj);return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data);
@@ -3965,7 +3934,6 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;
@@ -3975,12 +3943,11 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);if (crtc->funcs->gamma_set ==NULL ) { ret = -ENOSYS ;
@@ -4024,7 +3991,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;
@@ -4034,12 +4000,11 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);/* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) {
@@ -4074,7 +4039,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_page_flip *page_flip = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;struct drm_pending_vblank_event *e =NULL ;
@@ -4088,10 +4052,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,if ((page_flip->flags &DRM_MODE_PAGE_FLIP_ASYNC ) && !dev->mode_config.async_page_flip)return -EINVAL ; - obj =drm_mode_object_find (dev, page_flip->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) + crtc =drm_crtc_find (dev, page_flip->crtc_id); +if (!crtc)return -ENOENT ; - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (crtc->primary->fb ==NULL ) {
include/drm/drm_crtc.h +33 -0
@@ -1386,6 +1386,15 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);extern const char *drm_get_format_name (uint32_t format);/* Helpers */ + +static inline struct drm_plane *drm_plane_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PLANE ); +return mo ?obj_to_plane (mo) :NULL ; +} +static inline struct drm_crtc *drm_crtc_find (struct drm_device *dev,uint32_t id) {
@@ -1402,4 +1411,28 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,return mo ?obj_to_encoder (mo) :NULL ; } +static inline struct drm_connector *drm_connector_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_CONNECTOR ); +return mo ?obj_to_connector (mo) :NULL ; +} + +static inline struct drm_property *drm_property_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PROPERTY ); +return mo ?obj_to_property (mo) :NULL ; +} + +static inline struct drm_property_blob * +drm_property_blob_find (struct drm_device *dev,uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_BLOB ); +return mo ?obj_to_blob (mo) :NULL ; +} +#endif /* __DRM_CRTC_H__ */
Signature · 1 line
1.8.5.3
PATCH 7/16 drm: split propvals out and blob property support
In reply to Rob ClarkSplit property values out into a different struct, so we can later move property values into state structs. This will allow the property values to stay in sync w/ the state updates which are either discarded or atomically committed.
And since we are touching all the same code, add support for mutable blob properties, which will also be needed for atomic modeset.
--- drivers/gpu/drm/drm_crtc.c | 79 +++++++++++++++++++++-------- drivers/gpu/drm/drm_fb_helper.c | 3 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 3 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 3 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 6 ++- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 8 +-- drivers/gpu/drm/gma500/psb_intel_lvds.c | 6 ++- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 19 +++++-- drivers/gpu/drm/i2c/ch7006_drv.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 3 +- drivers/gpu/drm/i915/intel_dp.c | 3 +- drivers/gpu/drm/i915/intel_hdmi.c | 3 +- drivers/gpu/drm/i915/intel_sdvo.c | 19 +++++-- drivers/gpu/drm/i915/intel_tv.c | 6 ++- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 3 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 +- drivers/gpu/drm/omapdrm/omap_drv.c | 6 ++- drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 3 +- drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 4 +- include/drm/drm_crtc.h | 11 +++- 21 files changed, 142 insertions(+), 57 deletions(-)
drivers/gpu/drm/drm_crtc.c +58 -21
@@ -175,6 +175,14 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) }EXPORT_SYMBOL (drm_warn_on_modeset_not_all_locked); +static int drm_mode_set_obj_prop (struct drm_mode_object *obj, +void *state,struct drm_property *property, +uint64_t value,void *blob_data); +static struct drm_property_blob *drm_property_create_blob (struct drm_device *dev, +int length,void *data); +static void drm_property_destroy_blob (struct drm_device *dev, +struct drm_property_blob *blob); +/* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN (fnname, list) \ const char *fnname(int val) \
@@ -747,6 +755,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, goto out; crtc->base.properties = &crtc->properties; + crtc->base.propvals = &crtc->propvals;list_add_tail (&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++;
@@ -864,6 +873,7 @@ int drm_connector_init(struct drm_device *dev, goto out; connector->base.properties = &connector->properties; + connector->base.propvals = &connector->propvals; connector->dev = dev; connector->funcs = funcs; connector->connector_type = connector_type;
@@ -1037,6 +1047,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, goto out; plane->base.properties = &plane->properties; + plane->base.propvals = &plane->propvals; plane->dev = dev; plane->funcs = funcs; plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
@@ -2107,7 +2118,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, goto out; } -if (put_user (connector->properties.values[i], +if (put_user (connector->propvals.values[i], prop_values + copied)) { ret = -EFAULT ; goto out;
@@ -3396,19 +3407,33 @@ void drm_object_attach_property(struct drm_mode_object *obj, } obj->properties->ids[count] = property->base.id; - obj->properties->values[count] = init_val; + obj->propvals->values[count] = init_val; obj->properties->count++; }EXPORT_SYMBOL (drm_object_attach_property);int drm_object_property_set_value (struct drm_mode_object *obj, -struct drm_property *property,uint64_t val) +struct drm_object_property_values *propvals, +struct drm_property *property,uint64_t val, +void *blob_data) {int i;for (i =0 ; i < obj->properties->count; i++) {if (obj->properties->ids[i] == property->base.id) { - obj->properties->values[i] = val; +struct drm_device *dev = property->dev; +if (property->flags &DRM_MODE_PROP_BLOB ) { +struct drm_property_blob *blob, *old_blob =NULL ; + old_blob =drm_property_blob_find (dev, propvals->values[i]); + blob =drm_property_create_blob (dev, val, blob_data); +if (!blob) +return -ENOMEM ; + propvals->values[i] = blob->base.id; +if (old_blob) +drm_property_destroy_blob (dev, old_blob); + }else { + propvals->values[i] = val; + }return 0 ; } }
@@ -3424,7 +3449,7 @@ int drm_object_property_get_value(struct drm_mode_object *obj,for (i =0 ; i < obj->properties->count; i++) {if (obj->properties->ids[i] == property->base.id) { - *val = obj->properties->values[i]; + *val = obj->propvals->values[i];return 0 ; } }
@@ -3607,27 +3632,35 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, struct edid *edid) {struct drm_device *dev = connector->dev; -int ret, size; +struct drm_mode_object *obj = &connector->base; +struct drm_property *edid_prop = dev->mode_config.edid_property; +int i, ret, size; -if (connector->edid_blob_ptr) -drm_property_destroy_blob (dev, connector->edid_blob_ptr); +/* property_blob will be recreated by drm_object_property_set_value(): */ + connector->edid_blob_ptr =NULL ;/* Delete edid, when there is none. */ if (!edid) { - connector->edid_blob_ptr =NULL ; - ret =drm_object_property_set_value (&connector->base, dev->mode_config.edid_property,0 ); + ret =drm_object_property_set_value (obj, + &connector->propvals, edid_prop,0 ,NULL );return ret; } size =EDID_LENGTH * (1 + edid->extensions); - connector->edid_blob_ptr =drm_property_create_blob (connector->dev, - size, edid); -if (!connector->edid_blob_ptr) -return -EINVAL ; - ret =drm_object_property_set_value (&connector->base, - dev->mode_config.edid_property, - connector->edid_blob_ptr->base.id); + ret =drm_object_property_set_value (obj, + &connector->propvals, edid_prop, size, edid); +if (ret) +return ret; + +/* find the blob object created for us by drm_object_property_set_value(): */ +for (i =0 ; i < obj->properties->count; i++) { +if (obj->properties->ids[i] == edid_prop->base.id) { + connector->edid_blob_ptr =drm_property_blob_find (dev, + connector->propvals.values[i]); +break ; + } + }return ret; }
@@ -3705,7 +3738,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_connector *connector,/* store the property value if successful */ if (!ret) -drm_object_property_set_value (&connector->base, property, value); +drm_object_property_set_value (&connector->base, + &connector->propvals, property, value, blob_data); +return ret; }
@@ -3719,7 +3754,8 @@ static int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc, ret = crtc->funcs->set_property (crtc, state, property, value, blob_data);if (!ret) -drm_object_property_set_value (&crtc->base, property, value); +drm_object_property_set_value (&crtc->base, &crtc->propvals, + property, value,NULL );return ret; }
@@ -3734,7 +3770,8 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane, ret = plane->funcs->set_property (plane, state, property, value, blob_data);if (!ret) -drm_object_property_set_value (&plane->base, property, value); +drm_object_property_set_value (&plane->base, &plane->propvals, + property, value,NULL );return ret; }
@@ -3834,7 +3871,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, ret = -EFAULT ; goto out; } -if (put_user (obj->properties->values[i], +if (put_user (obj->propvals->values[i], prop_values_ptr + copied)) { ret = -EFAULT ; goto out;
drivers/gpu/drm/drm_fb_helper.c +2 -1
@@ -438,7 +438,8 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) connector = fb_helper->connector_info[j]->connector; connector->funcs->dpms (connector, dpms_mode);drm_object_property_set_value (&connector->base, - dev->mode_config.dpms_property, dpms_mode); + &connector->propvals, + dev->mode_config.dpms_property, dpms_mode,NULL ); } }drm_modeset_unlock_all (dev);
drivers/gpu/drm/gma500/cdv_intel_dp.c +2 -1
@@ -1655,7 +1655,8 @@ cdv_intel_dp_set_property(struct drm_connector *connector,struct cdv_intel_dp *intel_dp = encoder->dev_priv;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
drivers/gpu/drm/gma500/cdv_intel_hdmi.c +2 -1
@@ -191,7 +191,8 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,return 0 ;if (drm_object_property_set_value (&connector->base, - property, value)) + &connector->propvals, + property, value, blob_data))return -1 ; centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
drivers/gpu/drm/gma500/cdv_intel_lvds.c +4 -2
@@ -486,8 +486,9 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,return 0 ;if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data))return -1 ; if (crtc->saved_mode.hdisplay != 0 &&
@@ -501,8 +502,9 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector, } }else if (!strcmp (property->name,"backlight" ) && encoder) {if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data))return -1 ;else gma_backlight_set (encoder->dev, value);
drivers/gpu/drm/gma500/mdfld_dsi_output.c +5 -3
@@ -276,7 +276,8 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, goto set_prop_done;if (drm_object_property_set_value (&connector->base, - property, value)) + &connector->propvals, + property, value, blob_data)) goto set_prop_error; centerechange = (val == DRM_MODE_SCALE_NO_SCALE) ||
@@ -300,8 +301,9 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, } } }else if (!strcmp (property->name,"backlight" ) && encoder) { -if (drm_object_property_set_value (&connector->base, property, - value)) +if (drm_object_property_set_value (&connector->base, + &connector->propvals, + property, value, blob_data)) goto set_prop_error;else gma_backlight_set (encoder->dev, value);
drivers/gpu/drm/gma500/psb_intel_lvds.c +4 -2
@@ -606,8 +606,9 @@ int psb_intel_lvds_set_property(struct drm_connector *connector, goto set_prop_done;if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data)) goto set_prop_error; if (crtc->saved_mode.hdisplay != 0 &&
@@ -621,8 +622,9 @@ int psb_intel_lvds_set_property(struct drm_connector *connector, } }else if (!strcmp (property->name,"backlight" )) {if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data)) goto set_prop_error;else gma_backlight_set (encoder->dev, value);
drivers/gpu/drm/gma500/psb_intel_sdvo.c +14 -5
@@ -1717,7 +1717,8 @@ psb_intel_sdvo_set_property(struct drm_connector *connector,uint8_t cmd;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
@@ -1773,7 +1774,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, temp_value = val;if (psb_intel_sdvo_connector->left == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->right, val); + &connector->propvals, + psb_intel_sdvo_connector->right, + val, blob_data);if (psb_intel_sdvo_connector->left_margin == temp_value)return 0 ;
@@ -1785,7 +1788,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (psb_intel_sdvo_connector->right == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->left, val); + &connector->propvals, + psb_intel_sdvo_connector->left, + val, blob_data);if (psb_intel_sdvo_connector->right_margin == temp_value)return 0 ;
@@ -1797,7 +1802,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (psb_intel_sdvo_connector->top == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->bottom, val); + &connector->propvals, + psb_intel_sdvo_connector->bottom, + val, blob_data);if (psb_intel_sdvo_connector->top_margin == temp_value)return 0 ;
@@ -1809,7 +1816,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (psb_intel_sdvo_connector->bottom == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->top, val); + &connector->propvals, + psb_intel_sdvo_connector->top, + val, blob_data);if (psb_intel_sdvo_connector->bottom_margin == temp_value)return 0 ;
drivers/gpu/drm/i2c/ch7006_drv.c +2 -2
@@ -214,9 +214,9 @@ static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encodelse priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; -drm_object_property_set_value (&connector->base, +drm_object_property_set_value (&connector->base, &connector->propvals, encoder->dev->mode_config.tv_subconnector_property, - priv->subconnector); + priv->subconnector,NULL );return priv->subconnector ? connector_status_connected : connector_status_disconnected;
drivers/gpu/drm/i915/intel_display.c +2 -1
@@ -9249,8 +9249,9 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) connector->dpms =DRM_MODE_DPMS_ON ;drm_object_property_set_value (&connector->base, + &connector->propvals, dpms_property, -DRM_MODE_DPMS_ON ); +DRM_MODE_DPMS_ON ,NULL ); intel_encoder =to_intel_encoder (connector->encoder); intel_encoder->connectors_active = true;
drivers/gpu/drm/i915/intel_dp.c +2 -1
@@ -3319,7 +3319,8 @@ intel_dp_set_property(struct drm_connector *connector,struct intel_dp *intel_dp =enc_to_intel_dp (&intel_encoder->base);int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
drivers/gpu/drm/i915/intel_hdmi.c +2 -1
@@ -991,7 +991,8 @@ intel_hdmi_set_property(struct drm_connector *connector,struct drm_i915_private *dev_priv = connector->dev->dev_private;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
drivers/gpu/drm/i915/intel_sdvo.c +14 -5
@@ -2064,7 +2064,8 @@ intel_sdvo_set_property(struct drm_connector *connector,uint8_t cmd;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
@@ -2141,7 +2142,9 @@ intel_sdvo_set_property(struct drm_connector *connector, temp_value = val;if (intel_sdvo_connector->left == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->right, val); + &connector->propvals, + intel_sdvo_connector->right, + val, blob_data);if (intel_sdvo_connector->left_margin == temp_value)return 0 ;
@@ -2153,7 +2156,9 @@ intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (intel_sdvo_connector->right == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->left, val); + &connector->propvals, + intel_sdvo_connector->left, + val, blob_data);if (intel_sdvo_connector->right_margin == temp_value)return 0 ;
@@ -2165,7 +2170,9 @@ intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (intel_sdvo_connector->top == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->bottom, val); + &connector->propvals, + intel_sdvo_connector->bottom, + val, blob_data);if (intel_sdvo_connector->top_margin == temp_value)return 0 ;
@@ -2177,7 +2184,9 @@ intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (intel_sdvo_connector->bottom == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->top, val); + &connector->propvals, + intel_sdvo_connector->top, + val, blob_data);if (intel_sdvo_connector->bottom_margin == temp_value)return 0 ;
drivers/gpu/drm/i915/intel_tv.c +4 -2
@@ -1299,7 +1299,8 @@ static void intel_tv_find_better_format(struct drm_connector *connector) intel_tv->tv_format = tv_mode->name;drm_object_property_set_value (&connector->base, - connector->dev->mode_config.tv_mode_property, i); + &connector->propvals, + connector->dev->mode_config.tv_mode_property, i,NULL ); }/**
@@ -1456,7 +1457,8 @@ intel_tv_set_property(struct drm_connector *connector, void *state,int ret =0 ;bool changed = false; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret <0 ) goto out;
drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +2 -1
@@ -196,8 +196,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) }drm_object_property_set_value (&connector->base, + &connector->propvals, conf->tv_subconnector_property, - tv_enc->subconnector); + tv_enc->subconnector,NULL );if (!reliable) {return connector_status_unknown;
drivers/gpu/drm/nouveau/nouveau_connector.c +3 -1
@@ -227,10 +227,12 @@ nouveau_connector_set_encoder(struct drm_connector *connector,if (nv_connector->type ==DCB_CONNECTOR_DVI_I ) {drm_object_property_set_value (&connector->base, + &connector->propvals, dev->mode_config.dvi_i_subconnector_property, nv_encoder->dcb->type ==DCB_OUTPUT_TMDS ?DRM_MODE_SUBCONNECTOR_DVID : -DRM_MODE_SUBCONNECTOR_DVIA ); +DRM_MODE_SUBCONNECTOR_DVIA , +NULL ); } }
drivers/gpu/drm/omapdrm/omap_drv.c +4 -2
@@ -573,12 +573,14 @@ static void dev_lastclose(struct drm_device *dev)*/ for (i =0 ; i < priv->num_crtcs; i++) {drm_object_property_set_value (&priv->crtcs[i]->base, - priv->rotation_prop,0 ); + &priv->crtcs[i]->propvals, + priv->rotation_prop,0 ,NULL ); }for (i =0 ; i < priv->num_planes; i++) {drm_object_property_set_value (&priv->planes[i]->base, - priv->rotation_prop,0 ); + &priv->planes[i]->propvals, + priv->rotation_prop,0 ,NULL ); } }
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c +2 -1
@@ -118,7 +118,8 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,drm_helper_connector_dpms (connector,DRM_MODE_DPMS_OFF );drm_object_property_set_value (&connector->base, - rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ); + &connector->propvals, + rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ,NULL ); ret =drm_mode_connector_attach_encoder (connector, &renc->encoder);if (ret <0 )
drivers/gpu/drm/rcar-du/rcar_du_vgacon.c +2 -1
@@ -83,7 +83,8 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,drm_helper_connector_dpms (connector,DRM_MODE_DPMS_OFF );drm_object_property_set_value (&connector->base, - rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ); + &connector->propvals, + rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ,NULL ); ret =drm_mode_connector_attach_encoder (connector, &renc->encoder);if (ret <0 )
drivers/gpu/drm/shmobile/shmob_drm_crtc.c +2 -2
@@ -749,8 +749,8 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev, connector->encoder = encoder;drm_helper_connector_dpms (connector,DRM_MODE_DPMS_OFF ); -drm_object_property_set_value (&connector->base, - sdev->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ); +drm_object_property_set_value (&connector->base, &connector->propvals, + sdev->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ,NULL );return 0 ;
include/drm/drm_crtc.h +10 -1
@@ -42,6 +42,7 @@ struct drm_framebuffer;struct drm_object_properties ;struct drm_file ;struct drm_clip_rect ; +struct drm_object_property_values ;#define DRM_MODE_OBJECT_CRTC 0xcccccccc#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
@@ -57,12 +58,16 @@ struct drm_mode_object {uint32_t id;uint32_t type;struct drm_object_properties *properties; +struct drm_object_property_values *propvals; };#define DRM_OBJECT_MAX_PROPERTY 24struct drm_object_properties {int count;uint32_t ids[DRM_OBJECT_MAX_PROPERTY ]; +}; + +struct drm_object_property_values {uint64_t values[DRM_OBJECT_MAX_PROPERTY ]; };
@@ -535,6 +540,7 @@ struct drm_crtc {void *helper_private;struct drm_object_properties properties; +struct drm_object_property_values propvals; };
@@ -700,6 +706,7 @@ struct drm_connector {struct drm_property_blob *edid_blob_ptr;struct drm_object_properties properties; +struct drm_object_property_values propvals;uint8_t polled;/* DRM_CONNECTOR_POLL_* */
@@ -782,6 +789,7 @@ struct drm_plane {const struct drm_plane_funcs *funcs;struct drm_object_properties properties; +struct drm_object_property_values propvals;enum drm_plane_type type; };
@@ -1232,8 +1240,9 @@ static inline bool drm_property_type_valid(struct drm_property *property) }extern int drm_object_property_set_value (struct drm_mode_object *obj, +struct drm_object_property_values *propvals,struct drm_property *property, -uint64_t val); +uint64_t val,void *blob_data);extern int drm_object_property_get_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t *value);
Signature · 1 line
1.8.5.3
PATCH 8/16 drm: Allow drm_mode_object_find() to look up an object of any type
In reply to Rob ClarkFrom: Ville Syrjälä <[email protected]>
To avoid having to pass object types from userspace for atomic mode setting ioctl, allow drm_mode_object_find() to look up an object of any type. This will only work as long as the all object types share the ID space.
--- drivers/gpu/drm/drm_crtc.c | 3 ++- include/drm/drm_crtc.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_crtc.c +2 -1
@@ -479,7 +479,8 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,mutex_lock (&dev->mode_config.idr_mutex); obj =idr_find (&dev->mode_config.crtc_idr, id); -if (!obj || (obj->type != type) || (obj->id != id)) +if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || + (obj->id != id)) obj =NULL ;mutex_unlock (&dev->mode_config.idr_mutex);
include/drm/drm_crtc.h +1 -0
@@ -53,6 +53,7 @@ struct drm_object_property_values;#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee#define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd +#define DRM_MODE_OBJECT_ANY 0struct drm_mode_object {uint32_t id;
Signature · 6 lines
1.8.5.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 9/16 drm: Refactor object property check code
In reply to Rob ClarkFrom: Ville Syrjälä <[email protected]>
Refactor the code to check whether an object has a specific property to a new function.
v1: original
v2: rebase on atomic -- Rob Clark
v3: EINVAL->ENOENT
--- drivers/gpu/drm/drm_crtc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
drivers/gpu/drm/drm_crtc.c +14 -11
@@ -3800,6 +3800,19 @@ static int drm_mode_set_obj_prop(struct drm_mode_object *obj,return -EINVAL ; } +static bool object_has_prop (const struct drm_mode_object *obj,u32 prop_id) +{ +int i; + +if (!obj->properties) +return false; + +for (i =0 ; i < obj->properties->count; i++) +if (obj->properties->ids[i] == prop_id) +return true; +return false; +} +/* call with mode_config mutex held */ static int drm_mode_set_obj_prop_id(struct drm_device *dev, void *state, uint32_t obj_id, uint32_t obj_type,
@@ -3807,20 +3820,10 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, void *state, {struct drm_mode_object *arg_obj;struct drm_property *property; -int i; arg_obj =drm_mode_object_find (dev, obj_id, obj_type); -if (!arg_obj) +if (!(arg_obj &&object_has_prop (arg_obj, prop_id)))return -ENOENT ; -if (!arg_obj->properties) -return -EINVAL ; - -for (i =0 ; i < arg_obj->properties->count; i++) -if (arg_obj->properties->ids[i] == prop_id) -break ; - -if (i == arg_obj->properties->count) -return -EINVAL ; property =drm_property_find (dev, prop_id);if (!property)
Signature · 6 lines
1.8.5.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 10/16 drm: allow FB's in drm_mode_object_find
In reply to Rob ClarkWe do actually want to permit FB's in atomic case, since FB will be looked up like any other object property value in a few code paths (like property value validation).
So split out into an internal function without the WARN_ON() which we can use in those special cases.
--- drivers/gpu/drm/drm_crtc.c | 33 ++++++++++++++++++++++----------- include/drm/drm_crtc.h | 6 ------ 2 files changed, 22 insertions(+), 17 deletions(-)
drivers/gpu/drm/drm_crtc.c +22 -11
@@ -459,6 +459,21 @@ static void drm_mode_object_put(struct drm_device *dev,mutex_unlock (&dev->mode_config.idr_mutex); } +static struct drm_mode_object *_object_find (struct drm_device *dev, +uint32_t id,uint32_t type) +{ +struct drm_mode_object *obj =NULL ; + +mutex_lock (&dev->mode_config.idr_mutex); + obj =idr_find (&dev->mode_config.crtc_idr, id); +if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || + (obj->id != id)) + obj =NULL ; +mutex_unlock (&dev->mode_config.idr_mutex); + +return obj; +} +/** * drm_mode_object_find - look up a drm object with static lifetime * @dev: drm device
@@ -471,23 +486,19 @@ static void drm_mode_object_put(struct drm_device *dev,struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type) { -struct drm_mode_object *obj =NULL ; -/* Framebuffers are reference counted and need their own lookup * function.*/ WARN_ON (type ==DRM_MODE_OBJECT_FB ); - -mutex_lock (&dev->mode_config.idr_mutex); - obj =idr_find (&dev->mode_config.crtc_idr, id); -if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || - (obj->id != id)) - obj =NULL ; -mutex_unlock (&dev->mode_config.idr_mutex); - -return obj; +return _object_find (dev, id, type); }EXPORT_SYMBOL (drm_mode_object_find); +static struct drm_mode_object * +drm_property_get_obj (struct drm_property *property,uint64_t value) +{ +return _object_find (property->dev, value, property->values[0 ]); +} +/** * drm_framebuffer_init - initialize a framebuffer * @dev: DRM device
include/drm/drm_crtc.h +0 -6
@@ -1298,12 +1298,6 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,extern struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type); -static inline struct drm_mode_object * -drm_property_get_obj (struct drm_property *property,uint64_t value) -{ -return drm_mode_object_find (property->dev, value, property->values[0 ]); -} -/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);
Signature · 1 line
1.8.5.3
PATCH 11/16 drm: convert plane to properties/state
In reply to Rob ClarkBreak the mutable state of a plane out into a separate structure and use atomic properties mechanism to set plane attributes. This makes it easier to have some helpers for plane->set_property() and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multiple set_property() calls and for easy atomic commit or roll- back.
The same should be done for CRTC, encoder, and connector, but this patch only includes the first part (plane).
--- drivers/gpu/drm/armada/armada_overlay.c | 11 +- drivers/gpu/drm/drm_atomic.c | 211 ++++++++++++++- drivers/gpu/drm/drm_crtc.c | 403 ++++++++++++++++++++--------- drivers/gpu/drm/drm_fb_helper.c | 17 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 7 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 8 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/omapdrm/omap_plane.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + include/drm/drm_atomic.h | 28 +- include/drm/drm_crtc.h | 111 +++++++- 15 files changed, 689 insertions(+), 139 deletions(-)
drivers/gpu/drm/armada/armada_overlay.c +10 -1
@@ -7,6 +7,7 @@* published by the Free Software Foundation. */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h"
@@ -287,7 +288,12 @@ static int armada_plane_set_property(struct drm_plane *plane, void *state, {struct armada_private *priv = plane->dev->dev_private;struct armada_plane *dplane =drm_to_armada_plane (plane); +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);bool update_attr = false; +int ret =0 ; + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == priv->colorkey_prop) {#define CCC (v) ((v) << 24 | (v) << 16 | (v) << 8)
@@ -341,13 +347,16 @@ static int armada_plane_set_property(struct drm_plane *plane, void *state, }else if (property == priv->saturation_prop) { dplane->prop.saturation = val; update_attr = true; + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }if (update_attr && dplane->base.crtc)armada_ovl_update_attr (&dplane->prop,drm_to_armada_crtc (dplane->base.crtc)); -return 0 ; +return ret; }static const struct drm_plane_funcs armada_plane_funcs = {
drivers/gpu/drm/drm_atomic.c +209 -2
253 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +280 -123
532 lines not on this page · raw message
drivers/gpu/drm/drm_fb_helper.c +16 -1
@@ -286,13 +286,28 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;bool error = false; +void *state;int i;drm_warn_on_modeset_not_all_locked (dev); + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to restore fbdev mode\n" ); +return true; + } +list_for_each_entry (plane, &dev->mode_config.plane_list, head)if (plane->type !=DRM_PLANE_TYPE_PRIMARY ) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to restore fbdev mode\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state);for (i =0 ; i < fb_helper->crtc_count; i++) {struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
drivers/gpu/drm/exynos/exynos_drm_plane.c +6 -1
@@ -10,6 +10,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/exynos_drm.h> #include "exynos_drm_drv.h"
@@ -225,13 +226,17 @@ static int exynos_plane_set_property(struct drm_plane *plane,struct drm_device *dev = plane->dev;struct exynos_plane *exynos_plane =to_exynos_plane (plane);struct exynos_drm_private *dev_priv = dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == dev_priv->plane_zpos_property) { exynos_plane->overlay.zpos = val;return 0 ; } -return -EINVAL ; +return drm_plane_set_property (plane, pstate, property, val, blob_data); }static struct drm_plane_funcs exynos_plane_funcs = {
drivers/gpu/drm/i915/intel_sprite.c +1 -0
@@ -1037,6 +1037,7 @@ static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane, .destroy = intel_destroy_plane, + .set_property = drm_atomic_plane_set_property, };static uint32_t ilk_plane_formats[] = {
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +4 -2
@@ -87,8 +87,10 @@ void mdp4_plane_install_properties(struct drm_plane *plane,int mdp4_plane_set_property (struct drm_plane *plane,void *state,struct drm_property *property,uint64_t val,void *blob_data) { -// XXX -return -EINVAL ; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); }static const struct drm_plane_funcs mdp4_plane_funcs = {
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +4 -2
@@ -102,8 +102,10 @@ void mdp5_plane_install_properties(struct drm_plane *plane,int mdp5_plane_set_property (struct drm_plane *plane,void *state,struct drm_property *property,uint64_t val,void *blob_data) { -// XXX -return -EINVAL ; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); }static const struct drm_plane_funcs mdp5_plane_funcs = {
drivers/gpu/drm/nouveau/dispnv04/overlay.c +7 -1
@@ -24,6 +24,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h>
@@ -225,6 +226,10 @@ nv_set_property(struct drm_plane *plane, void *state, uint64_t value, void *blob_data) { struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == nv_plane->props.colorkey) nv_plane->colorkey = value;
@@ -239,7 +244,8 @@ nv_set_property(struct drm_plane *plane, void *state,else if (property == nv_plane->props.iturbt_709) nv_plane->iturbt_709 = value;else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);if (nv_plane->set_params) nv_plane->set_params (nv_plane);
drivers/gpu/drm/omapdrm/omap_drv.c +1 -1
@@ -579,7 +579,7 @@ static void dev_lastclose(struct drm_device *dev)for (i =0 ; i < priv->num_planes; i++) {drm_object_property_set_value (&priv->planes[i]->base, - &priv->planes[i]->propvals, + &priv->planes[i]->state->propvals, priv->rotation_prop,0 ,NULL ); } }
drivers/gpu/drm/omapdrm/omap_plane.c +7 -0
@@ -332,8 +332,12 @@ int omap_plane_set_property(struct drm_plane *plane, void *state, {struct omap_plane *omap_plane =to_omap_plane (plane);struct omap_drm_private *priv = plane->dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);int ret = -EINVAL ; +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +if (property == priv->rotation_prop) {DBG ("%s: rotation: %02x" , omap_plane->name, (uint32_t )val); omap_plane->win.rotation = val;
@@ -342,6 +346,9 @@ int omap_plane_set_property(struct drm_plane *plane, void *state,DBG ("%s: zorder: %02x" , omap_plane->name, (uint32_t )val); omap_plane->info.zorder = val; ret =apply (plane); + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }return ret;
drivers/gpu/drm/rcar-du/rcar_du_plane.c +7 -1
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -404,6 +405,10 @@ static int rcar_du_plane_set_property(struct drm_plane *plane, {struct rcar_du_plane *rplane =to_rcar_plane (plane);struct rcar_du_group *rgrp = rplane->group; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == rgrp->planes.alpha)rcar_du_plane_set_alpha (rplane, value);
@@ -412,7 +417,8 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,else if (property == rgrp->planes.zpos)rcar_du_plane_set_zpos (rplane, value);else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);return 0 ; }
drivers/gpu/drm/shmobile/shmob_drm_plane.c +2 -0
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -228,6 +229,7 @@ static void shmob_drm_plane_destroy(struct drm_plane *plane)static const struct drm_plane_funcs shmob_drm_plane_funcs = { .update_plane = shmob_drm_plane_update, .disable_plane = shmob_drm_plane_disable, + .set_property = drm_atomic_plane_set_property, .destroy = shmob_drm_plane_destroy, };
include/drm/drm_atomic.h +27 -1
@@ -62,7 +62,8 @@* struct drm_atomic_funcs - helper funcs used by the atomic helpers */ struct drm_atomic_funcs { -int dummy;/* for now */ +int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); +int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;
@@ -76,6 +77,29 @@ int drm_atomic_commit(struct drm_device *dev, void *state);int drm_atomic_commit_unlocked (struct drm_device *dev,void *state);void drm_atomic_end (struct drm_device *dev,void *state); +int drm_atomic_plane_set_property (struct drm_plane *plane,void *state, +struct drm_property *property,uint64_t val,void *blob_data); +struct drm_plane_state *drm_atomic_get_plane_state (struct drm_plane *plane, +void *state); + +static inline int +drm_atomic_check_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->check_plane_state (plane, pstate); +} + +static inline int +drm_atomic_commit_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->commit_plane_state (plane, pstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */
@@ -83,6 +107,8 @@ struct drm_atomic_state {struct kref refcount;struct drm_device *dev;uint32_t flags; +struct drm_plane **planes; +struct drm_plane_state **pstates;bool committed;bool checked;/* just for debugging */
include/drm/drm_crtc.h +108 -3
161 lines not on this page · raw message
Signature · 1 line
1.8.5.3
PATCH 12/16 drm: convert crtc to properties/state
In reply to Rob ClarkBreak the mutable state of a crtc out into a separate structure and use atomic properties mechanism to set crtc attributes. This makes it easier to have some helpers for crtc->set_property() and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multiple set_property() calls and for easy atomic commit or roll- back.
--- drivers/gpu/drm/armada/armada_crtc.c | 11 +- drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 231 ++++++++++- drivers/gpu/drm/drm_crtc.c | 616 ++++++++++++++++++----------- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 12 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/qxl/qxl_display.c | 2 + drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 2 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 1 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drm_atomic.h | 28 ++ include/drm/drm_crtc.h | 103 ++++- 26 files changed, 777 insertions(+), 266 deletions(-)
drivers/gpu/drm/armada/armada_crtc.c +10 -1
@@ -9,6 +9,7 @@#include <linux/clk.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h"
@@ -963,7 +964,12 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, void *state, {struct armada_private *priv = crtc->dev->dev_private;struct armada_crtc *dcrtc =drm_to_armada_crtc (crtc); +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state);bool update_csc = false; +int ret =0 ; + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == priv->csc_yuv_prop) { dcrtc->csc_yuv_mode = val;
@@ -971,6 +977,9 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, void *state, }else if (property == priv->csc_rgb_prop) { dcrtc->csc_rgb_mode = val; update_csc = true; + }else { + ret =drm_crtc_set_property (crtc, cstate, property, + val, blob_data); }if (update_csc) {
@@ -981,7 +990,7 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, void *state,writel_relaxed (val, dcrtc->base +LCD_SPU_IOPAD_CONTROL ); } -return 0 ; +return ret; }static struct drm_crtc_funcs armada_crtc_funcs = {
drivers/gpu/drm/ast/ast_mode.c +1 -0
@@ -619,6 +619,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { .cursor_move = ast_cursor_move, .reset = ast_crtc_reset, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .gamma_set = ast_crtc_gamma_set, .destroy = ast_crtc_destroy, };
drivers/gpu/drm/cirrus/cirrus_mode.c +1 -0
@@ -363,6 +363,7 @@ static void cirrus_crtc_destroy(struct drm_crtc *crtc)static const struct drm_crtc_funcs cirrus_crtc_funcs = { .gamma_set = cirrus_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = cirrus_crtc_destroy, };
drivers/gpu/drm/drm_atomic.c +228 -3
322 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +378 -238
778 lines not on this page · raw message
drivers/gpu/drm/exynos/exynos_drm_crtc.c +6 -1
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "exynos_drm_crtc.h" #include "exynos_drm_drv.h"
@@ -262,6 +263,10 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,struct drm_device *dev = crtc->dev;struct exynos_drm_private *dev_priv = dev->dev_private;struct exynos_drm_crtc *exynos_crtc =to_exynos_crtc (crtc); +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == dev_priv->crtc_mode_property) {enum exynos_crtc_mode mode = val;
@@ -286,7 +291,7 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,return 0 ; } -return -EINVAL ; +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); }static struct drm_crtc_funcs exynos_crtc_funcs = {
drivers/gpu/drm/gma500/cdv_intel_display.c +1 -0
@@ -1022,6 +1022,7 @@ const struct drm_crtc_funcs cdv_intel_crtc_funcs = { .cursor_move = gma_crtc_cursor_move, .gamma_set = gma_crtc_gamma_set, .set_config = gma_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = gma_crtc_destroy, };
drivers/gpu/drm/gma500/psb_intel_display.c +1 -0
@@ -444,6 +444,7 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = { .cursor_move = gma_crtc_cursor_move, .gamma_set = gma_crtc_gamma_set, .set_config = gma_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = gma_crtc_destroy, };
drivers/gpu/drm/i915/intel_display.c +1 -0
@@ -10174,6 +10174,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, .set_config = intel_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, };
drivers/gpu/drm/mgag200/mgag200_mode.c +1 -0
@@ -1296,6 +1296,7 @@ static const struct drm_crtc_funcs mga_crtc_funcs = { .cursor_move = mga_crtc_cursor_move, .gamma_set = mga_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = mga_crtc_destroy, };
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +4 -2
@@ -470,8 +470,10 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc,static int mdp4_crtc_set_property (struct drm_crtc *crtc,void *state,struct drm_property *property,uint64_t val,void *blob_data) { -// XXX -return -EINVAL ; +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); }#define CURSOR_WIDTH 64
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +4 -2
@@ -388,8 +388,10 @@ static int mdp5_crtc_page_flip(struct drm_crtc *crtc,static int mdp5_crtc_set_property (struct drm_crtc *crtc,void *state,struct drm_property *property,uint64_t val,void *blob_data) { -// XXX -return -EINVAL ; +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); }static const struct drm_crtc_funcs mdp5_crtc_funcs = {
drivers/gpu/drm/nouveau/dispnv04/crtc.c +1 -0
@@ -1086,6 +1086,7 @@ static const struct drm_crtc_funcs nv04_crtc_funcs = { .cursor_move = nv04_crtc_cursor_move, .gamma_set = nv_crtc_gamma_set, .set_config = nouveau_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = nouveau_crtc_page_flip, .destroy = nv_crtc_destroy, };
drivers/gpu/drm/nouveau/nv50_display.c +1 -0
@@ -1329,6 +1329,7 @@ static const struct drm_crtc_funcs nv50_crtc_func = { .cursor_move = nv50_crtc_cursor_move, .gamma_set = nv50_crtc_gamma_set, .set_config = nouveau_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = nv50_crtc_destroy, .page_flip = nouveau_crtc_page_flip, };
drivers/gpu/drm/omapdrm/omap_crtc.c +10 -2
@@ -367,14 +367,22 @@ static int omap_crtc_set_property(struct drm_crtc *crtc, void *state, {struct omap_crtc *omap_crtc =to_omap_crtc (crtc);struct omap_drm_private *priv = crtc->dev->dev_private; +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); +int ret; + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == priv->rotation_prop) { - crtc->invert_dimensions = + cstate->invert_dimensions = !!(val & ((1LL <<DRM_ROTATE_90 ) | (1LL <<DRM_ROTATE_270 ))); } -return omap_plane_set_property (omap_crtc->plane, state, + ret =omap_plane_set_property (omap_crtc->plane, state, property, val, blob_data); +if (ret) + ret =drm_crtc_set_property (crtc, cstate, property, val, blob_data); +return ret; }static const struct drm_crtc_funcs omap_crtc_funcs = {
drivers/gpu/drm/omapdrm/omap_drv.c +1 -1
@@ -573,7 +573,7 @@ static void dev_lastclose(struct drm_device *dev)*/ for (i =0 ; i < priv->num_crtcs; i++) {drm_object_property_set_value (&priv->crtcs[i]->base, - &priv->crtcs[i]->propvals, + &priv->crtcs[i]->state->propvals, priv->rotation_prop,0 ,NULL ); }
drivers/gpu/drm/qxl/qxl_display.c +2 -0
@@ -29,6 +29,7 @@#include "qxl_drv.h" #include "qxl_object.h" #include "drm_crtc_helper.h" +#include "drm_atomic.h" static bool qxl_head_enabled (struct qxl_head *head) {
@@ -373,6 +374,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { .cursor_set2 = qxl_crtc_cursor_set2, .cursor_move = qxl_crtc_cursor_move, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = qxl_crtc_destroy, };
drivers/gpu/drm/radeon/radeon_display.c +2 -0
@@ -32,6 +32,7 @@#include <linux/pm_runtime.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_edid.h> static void avivo_crtc_load_lut (struct drm_crtc *crtc)
@@ -544,6 +545,7 @@ static const struct drm_crtc_funcs radeon_crtc_funcs = { .cursor_move = radeon_crtc_cursor_move, .gamma_set = radeon_crtc_gamma_set, .set_config = radeon_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = radeon_crtc_destroy, .page_flip = radeon_crtc_page_flip, };
drivers/gpu/drm/rcar-du/rcar_du_crtc.c +2 -0
@@ -17,6 +17,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -527,6 +528,7 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,static const struct drm_crtc_funcs crtc_funcs = { .destroy = drm_crtc_cleanup, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = rcar_du_crtc_page_flip, };
drivers/gpu/drm/shmobile/shmob_drm_crtc.c +2 -0
@@ -17,6 +17,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -506,6 +507,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,static const struct drm_crtc_funcs crtc_funcs = { .destroy = drm_crtc_cleanup, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = shmob_drm_crtc_page_flip, };
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +1 -0
@@ -411,6 +411,7 @@ static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,static const struct drm_crtc_funcs tilcdc_crtc_funcs = { .destroy = tilcdc_crtc_destroy, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = tilcdc_crtc_page_flip, };
drivers/gpu/drm/udl/udl_modeset.c +2 -0
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "udl_drv.h" /*
@@ -383,6 +384,7 @@ static struct drm_crtc_helper_funcs udl_helper_funcs = {static const struct drm_crtc_funcs udl_crtc_funcs = { .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = udl_crtc_destroy, };
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +1 -0
@@ -300,6 +300,7 @@ static struct drm_crtc_funcs vmw_legacy_crtc_funcs = { .cursor_move = vmw_du_crtc_cursor_move, .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_ldu_crtc_destroy, + .set_property = drm_atomic_crtc_set_property, .set_config = vmw_ldu_crtc_set_config, };
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +1 -0
@@ -397,6 +397,7 @@ static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_sou_crtc_destroy, .set_config = vmw_sou_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = vmw_du_page_flip, };
include/drm/drm_atomic.h +28 -0
@@ -64,6 +64,9 @@struct drm_atomic_funcs {int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate);int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); + +int (*check_crtc_state)(struct drm_crtc *crtc,struct drm_crtc_state *cstate); +int (*commit_crtc_state)(struct drm_crtc *crtc,struct drm_crtc_state *cstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;
@@ -100,6 +103,29 @@ drm_atomic_commit_plane_state(struct drm_plane *plane,return funcs->commit_plane_state (plane, pstate); } +int drm_atomic_crtc_set_property (struct drm_crtc *crtc,void *state, +struct drm_property *property,uint64_t val,void *blob_data); +struct drm_crtc_state *drm_atomic_get_crtc_state (struct drm_crtc *crtc, +void *state); + +static inline int +drm_atomic_check_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +const struct drm_atomic_funcs *funcs = + crtc->dev->driver->atomic_funcs; +return funcs->check_crtc_state (crtc, cstate); +} + +static inline int +drm_atomic_commit_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +const struct drm_atomic_funcs *funcs = + crtc->dev->driver->atomic_funcs; +return funcs->commit_crtc_state (crtc, cstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */
@@ -109,6 +135,8 @@ struct drm_atomic_state {uint32_t flags;struct drm_plane **planes;struct drm_plane_state **pstates; +struct drm_crtc **crtcs; +struct drm_crtc_state **cstates;bool committed;bool checked;/* just for debugging */
include/drm/drm_crtc.h +87 -16
184 lines not on this page · raw message
Signature · 1 line
1.8.5.3
PATCH 13/16 drm: push locking down into restore_fbdev_mode
In reply to Rob ClarkAll the call-sites save one need locking. By pushing it down and adding a lockless flag, we can use the new spiffy atomic ww_mutex crtc locking and simplify all the call-sites.
--- drivers/gpu/drm/armada/armada_fbdev.c | 4 +--- drivers/gpu/drm/drm_fb_cma_helper.c | 9 ++------- drivers/gpu/drm/drm_fb_helper.c | 12 +++++++----- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +--- drivers/gpu/drm/gma500/psb_drv.c | 4 +--- drivers/gpu/drm/i915/intel_fbdev.c | 6 +----- drivers/gpu/drm/msm/msm_drv.c | 7 ++----- drivers/gpu/drm/omapdrm/omap_drv.c | 4 +--- include/drm/drm_fb_helper.h | 3 ++- 9 files changed, 18 insertions(+), 35 deletions(-)
drivers/gpu/drm/armada/armada_fbdev.c +1 -3
@@ -181,10 +181,8 @@ void armada_fbdev_lastclose(struct drm_device *dev) {struct armada_private *priv = dev->dev_private; -drm_modeset_lock_all (dev);if (priv->fbdev) -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode (priv->fbdev, false); }void armada_fbdev_fini (struct drm_device *dev)
drivers/gpu/drm/drm_fb_cma_helper.c +2 -7
@@ -429,13 +429,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);*/ void drm_fbdev_cma_restore_mode (struct drm_fbdev_cma *fbdev_cma) { -if (fbdev_cma) { -struct drm_device *dev = fbdev_cma->fb_helper.dev; - -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (&fbdev_cma->fb_helper); -drm_modeset_unlock_all (dev); - } +if (fbdev_cma) +drm_fb_helper_restore_fbdev_mode (&fbdev_cma->fb_helper, false); }EXPORT_SYMBOL_GPL (drm_fbdev_cma_restore_mode);
drivers/gpu/drm/drm_fb_helper.c +7 -5
@@ -276,12 +276,15 @@ EXPORT_SYMBOL(drm_fb_helper_debug_leave);/** * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration * @fb_helper: fbcon to restore +* @lockless: true in drm_fb_helper_force_kernel_mode() path, to avoid +* blocking in panic case, everywhere else should use false * * This should be called from driver's drm ->lastclose callback * when implementing an fbcon on top of kms using this helper. This ensures that * the user isn't greeted with a black screen when e.g. X dies. */ -bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper) +bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper, +bool lockless) {struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;
@@ -289,9 +292,8 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)void *state;int i; -drm_warn_on_modeset_not_all_locked (dev); - - state = dev->driver->atomic_begin (dev,0 ); + state = dev->driver->atomic_begin (dev, lockless ? +DRM_MODE_ATOMIC_NOLOCK :0 );if (IS_ERR (state)) {DRM_ERROR ("failed to restore fbdev mode\n" );return true;
@@ -344,7 +346,7 @@ static bool drm_fb_helper_force_kernel_mode(void)if (helper->dev->switch_power_state ==DRM_SWITCH_POWER_OFF )continue ; - ret =drm_fb_helper_restore_fbdev_mode (helper); + ret =drm_fb_helper_restore_fbdev_mode (helper, true);if (ret) error = true; }
drivers/gpu/drm/exynos/exynos_drm_fbdev.c +1 -3
@@ -354,7 +354,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)if (!private || !private->fb_helper)return ; -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (private->fb_helper); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode (private->fb_helper, false); }
drivers/gpu/drm/gma500/psb_drv.c +1 -3
@@ -153,11 +153,9 @@ static void psb_lastclose(struct drm_device *dev)struct drm_psb_private *dev_priv = dev->dev_private;struct psb_fbdev *fbdev = dev_priv->fbdev; -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (&fbdev->psb_fb_helper); + ret =drm_fb_helper_restore_fbdev_mode (&fbdev->psb_fb_helper, false);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); -drm_modeset_unlock_all (dev);return ; }
drivers/gpu/drm/i915/intel_fbdev.c +1 -5
@@ -493,11 +493,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)if (INTEL_INFO (dev)->num_pipes ==0 )return ; -drm_modeset_lock_all (dev); - - ret =drm_fb_helper_restore_fbdev_mode (&dev_priv->fbdev->helper); + ret =drm_fb_helper_restore_fbdev_mode (&dev_priv->fbdev->helper, false);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); - -drm_modeset_unlock_all (dev); }
drivers/gpu/drm/msm/msm_drv.c +2 -5
@@ -382,11 +382,8 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)static void msm_lastclose (struct drm_device *dev) {struct msm_drm_private *priv = dev->dev_private; -if (priv->fbdev) { -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); - } +if (priv->fbdev) +drm_fb_helper_restore_fbdev_mode (priv->fbdev, false); }static irqreturn_t msm_irq (int irq,void *arg)
drivers/gpu/drm/omapdrm/omap_drv.c +1 -3
@@ -584,9 +584,7 @@ static void dev_lastclose(struct drm_device *dev) } } -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); + ret =drm_fb_helper_restore_fbdev_mode (priv->fbdev, false);if (ret)DBG ("failed to restore crtc mode" ); }
include/drm/drm_fb_helper.h +2 -1
@@ -108,7 +108,8 @@ int drm_fb_helper_set_par(struct fb_info *info);int drm_fb_helper_check_var (struct fb_var_screeninfo *var,struct fb_info *info); -bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper); +bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper, +bool lockless);void drm_fb_helper_fill_var (struct fb_info *info,struct drm_fb_helper *fb_helper,uint32_t fb_width,uint32_t fb_height); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
Signature · 1 line
1.8.5.3
PATCH 14/16 drm: Atomic modeset ioctl
In reply to Rob ClarkFrom: Ville Syrjälä <[email protected]>
The atomic modeset ioctl cna 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. For setting values to blob properties, the property value indicates the length of the data, and the actual data is passed via another blob pointer.
The caller can demand non-blocking operation from the ioctl, and if the driver can't satisfy that requirement an error will be returned.
The caller can also request to receive asynchronous completion events after the operation has reached the hardware. An event is sent for each object specified by the caller, whether or not the actual state of that object changed. Each event also carries a framebuffer ID, which indicates to user space that the specified object is no longer accessing that framebuffer.
--- drivers/gpu/drm/drm_crtc.c | 156 ++++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_drv.c | 1 + include/drm/drmP.h | 6 ++ include/drm/drm_crtc.h | 2 + include/uapi/drm/drm.h | 12 ++++ include/uapi/drm/drm_mode.h | 20 ++++++ 6 files changed, 197 insertions(+)
drivers/gpu/drm/drm_crtc.c +156 -0
@@ -4877,3 +4877,159 @@ void drm_mode_config_cleanup(struct drm_device *dev)idr_destroy (&dev->mode_config.crtc_idr); }EXPORT_SYMBOL (drm_mode_config_cleanup); + +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); +uint64_t __user *blob_values_ptr = (uint64_t __user *)(unsigned long )(arg->blob_values_ptr); +unsigned int copied_objs, copied_props, copied_blobs; +void *state; +int ret =0 ; +unsigned int i, j; + +if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS ) +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 ; + +retry: + copied_objs =0 ; + copied_props =0 ; + copied_blobs =0 ; + + state = dev->driver->atomic_begin (dev, arg->flags); +if (IS_ERR (state)) { + ret =PTR_ERR (state); + goto out; + } + +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 out; + } + + obj =drm_mode_object_find (dev, obj_id,DRM_MODE_OBJECT_ANY ); +if (!obj || !obj->properties) { + ret = -ENOENT ; + goto out; + } + +if ((obj->type ==DRM_MODE_OBJECT_CRTC ) && + (arg->flags &DRM_MODE_PAGE_FLIP_EVENT )) { +struct drm_pending_vblank_event *e = +create_vblank_event (dev, file_priv, arg->user_data); +if (!e) { + ret = -ENOMEM ; + goto out; + } + ret = dev->driver->atomic_set_event (dev, state, obj, e); +if (ret) { +destroy_vblank_event (dev, file_priv, e); + goto out; + } + } + +if (get_user (count_props, count_props_ptr + copied_objs)) { + ret = -EFAULT ; + goto out; + } + + copied_objs++; + +for (j =0 ; j < count_props; j++) { +uint32_t prop_id; +uint64_t prop_value; +struct drm_property *prop; +void *blob_data =NULL ; + +if (get_user (prop_id, props_ptr + copied_props)) { + ret = -EFAULT ; + goto out; + } + +if (!object_has_prop (obj, prop_id)) { + ret = -EINVAL ; + goto out; + } + + prop =drm_property_find (dev, prop_id); +if (!prop) { + ret = -ENOENT ; + goto out; + } + +if (get_user (prop_value, prop_values_ptr + copied_props)) { + ret = -EFAULT ; + goto out; + } + +if (!drm_property_change_is_valid (prop, prop_value)) { + ret = -EINVAL ; + goto out; + } + +if ((prop->flags &DRM_MODE_PROP_BLOB ) && prop_value) { +uint64_t blob_ptr; + +if (get_user (blob_ptr, blob_values_ptr + copied_blobs)) { + ret = -EFAULT ; + goto out; + } + + blob_data =kmalloc (prop_value,GFP_KERNEL ); +if (!blob_data) { + ret = -ENOMEM ; + goto out; + } + +if (copy_from_user (blob_data, (void __user *)(unsigned long )blob_ptr, prop_value)) { +kfree (blob_data); + ret = -EFAULT ; + goto out; + } + } + +/* User space sends the blob pointer even if we +* don't use it (length==0). +*/ +if (prop->flags &DRM_MODE_PROP_BLOB ) + copied_blobs++; + +/* The driver will be in charge of blob_data from now on. */ + ret =drm_mode_set_obj_prop (obj, state, prop, + prop_value, blob_data); +if (ret) + goto out; + + copied_props++; + } + } + + ret = dev->driver->atomic_check (dev, state); +if (ret) + goto out; + +if (arg->flags &DRM_MODE_ATOMIC_TEST_ONLY ) + goto out; + + ret = dev->driver->atomic_commit (dev, state); + + out: + dev->driver->atomic_end (dev, state); +if (ret == -EDEADLK ) + goto retry; + +return ret; +}
drivers/gpu/drm/drm_drv.c +1 -0
@@ -167,6 +167,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/drmP.h +6 -0
@@ -1171,6 +1171,12 @@ struct drm_vblank_crtc {once per disable */ }; +struct drm_pending_atomic_event { +struct drm_pending_event base; +int pipe; +struct drm_event_atomic event; +}; +/** * DRM device structure. This structure represent a complete card that * may contain multiple heads.
include/drm/drm_crtc.h +2 -0
@@ -1517,6 +1517,8 @@ extern int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);extern int drm_mode_obj_set_property_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv); +extern 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 +12 -0
@@ -768,6 +768,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
@@ -809,6 +810,17 @@ struct drm_event_vblank {__u32 reserved; }; +struct drm_event_atomic { +struct drm_event base; +__u64 user_data; +__u32 tv_sec; +__u32 tv_usec; +__u32 sequence; +__u32 obj_id; +__u32 old_fb_id; +__u32 reserved; +}; +/* typedef area */ #ifndef __KERNEL__typedef struct drm_clip_rect drm_clip_rect_t ;
include/uapi/drm/drm_mode.h +20 -0
@@ -511,7 +511,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_NOLOCK 0x8000/* only used internally */ +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK) + +/* FIXME come up with some sane error reporting mechanism? */ +struct drm_mode_atomic { +__u32 flags; +__u32 count_objs; +__u64 objs_ptr; +__u64 count_props_ptr; +__u64 props_ptr; +__u64 prop_values_ptr; +__u64 blob_values_ptr; +__u64 user_data; +}; +#endif
Signature · 6 lines
1.8.5.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 15/16 drm/msm: add atomic support
In reply to Rob ClarkTODO: probably can split this up into prep patch which splits the msm_queue_fence_cb out of gem..
--- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 59 ++++++------- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 6 ++ drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 5 -- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 56 ++++++------ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 6 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 5 -- drivers/gpu/drm/msm/msm_atomic.c | 141 ++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.c | 22 ++++- drivers/gpu/drm/msm/msm_drv.h | 7 ++ drivers/gpu/drm/msm/msm_gem.c | 24 +---- drivers/gpu/drm/msm/msm_gem.h | 13 +++ drivers/gpu/drm/msm/msm_kms.h | 1 + 15 files changed, 254 insertions(+), 95 deletions(-) create mode 100644 drivers/gpu/drm/msm/msm_atomic.c
drivers/gpu/drm/msm/Makefile +1 -0
@@ -27,6 +27,7 @@ msm-y := \ mdp/mdp5/mdp5_kms.o \ mdp/mdp5/mdp5_plane.o \ mdp/mdp5/mdp5_smp.o \ + msm_atomic.o \ msm_drv.o \ msm_fb.o \ msm_gem.o \
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +27 -32
148 lines not on this page · raw message
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +6 -0
@@ -131,6 +131,11 @@ static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,return mdp4_dtv_round_pixclk (encoder, rate); } +static void mdp4_flush (struct msm_kms *kms,struct drm_crtc *crtc) +{ +mdp4_crtc_flush (crtc); +} +static void mdp4_preclose (struct msm_kms *kms,struct drm_file *file) {struct mdp4_kms *mdp4_kms =to_mdp4_kms (to_mdp_kms (kms));
@@ -158,6 +163,7 @@ static const struct mdp_kms_funcs kms_funcs = { .disable_vblank = mdp4_disable_vblank, .get_format = mdp_get_format, .round_pixclk = mdp4_round_pixclk, + .flush = mdp4_flush, .preclose = mdp4_preclose, .destroy = mdp4_destroy, },
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +1 -0
@@ -180,6 +180,7 @@ enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane);struct drm_plane *mdp4_plane_init (struct drm_device *dev,enum mdp4_pipe pipe_id,bool private_plane); +void mdp4_crtc_flush (struct drm_crtc *crtc);uint32_t mdp4_crtc_vblank (struct drm_crtc *crtc);void mdp4_crtc_cancel_pending_flip (struct drm_crtc *crtc,struct drm_file *file);void mdp4_crtc_set_config (struct drm_crtc *crtc,uint32_t config);
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +0 -5
@@ -48,11 +48,6 @@ static int mdp4_plane_update(struct drm_plane *plane, mdp4_plane->enabled = true; -if (plane->fb) -drm_framebuffer_unreference (plane->fb); - -drm_framebuffer_reference (fb); -return mdp4_plane_mode_set (plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +25 -31
140 lines not on this page · raw message
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +6 -0
@@ -91,6 +91,11 @@ static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,return rate; } +static void mdp5_flush (struct msm_kms *kms,struct drm_crtc *crtc) +{ +mdp5_crtc_flush (crtc); +} +static void mdp5_preclose (struct msm_kms *kms,struct drm_file *file) {struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms));
@@ -118,6 +123,7 @@ static const struct mdp_kms_funcs kms_funcs = { .disable_vblank = mdp5_disable_vblank, .get_format = mdp_get_format, .round_pixclk = mdp5_round_pixclk, + .flush = mdp5_flush, .preclose = mdp5_preclose, .destroy = mdp5_destroy, },
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +1 -1
@@ -197,8 +197,8 @@ enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);struct drm_plane *mdp5_plane_init (struct drm_device *dev,enum mdp5_pipe pipe,bool private_plane); +void mdp5_crtc_flush (struct drm_crtc *crtc);uint32_t mdp5_crtc_vblank (struct drm_crtc *crtc); -void mdp5_crtc_cancel_pending_flip (struct drm_crtc *crtc,struct drm_file *file);void mdp5_crtc_set_intf (struct drm_crtc *crtc,int intf,enum mdp5_intf intf_id);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +0 -5
@@ -48,11 +48,6 @@ static int mdp5_plane_update(struct drm_plane *plane, mdp5_plane->enabled = true; -if (plane->fb) -drm_framebuffer_unreference (plane->fb); - -drm_framebuffer_reference (fb); -return mdp5_plane_mode_set (plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h);
drivers/gpu/drm/msm/msm_atomic.c new file +141 -0
141 lines not on this page · raw message
drivers/gpu/drm/msm/msm_drv.c +21 -1
@@ -600,6 +600,26 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,return ret; } +int msm_queue_fence_cb (struct drm_device *dev, +struct msm_fence_cb *cb,uint32_t fence) +{ +struct msm_drm_private *priv = dev->dev_private; +int ret =0 ; + +mutex_lock (&dev->struct_mutex); +if (!list_empty (&cb->work.entry)) { + ret = -EINVAL ; + }else if (fence > priv->completed_fence) { + cb->fence = fence; +list_add_tail (&cb->work.entry, &priv->fence_cbs); + }else { +queue_work (priv->wq, &cb->work); + } +mutex_unlock (&dev->struct_mutex); + +return ret; +} +/* called from workqueue */ void msm_update_fence (struct drm_device *dev,uint32_t fence) {
@@ -815,7 +835,7 @@ static struct drm_driver msm_driver = { .atomic_begin = drm_atomic_begin, .atomic_set_event = drm_atomic_set_event, .atomic_check = drm_atomic_check, - .atomic_commit = drm_atomic_commit, + .atomic_commit = msm_atomic_commit, .atomic_end = drm_atomic_end, .atomic_funcs = &drm_atomic_funcs,#ifdef CONFIG_DEBUG_FS
drivers/gpu/drm/msm/msm_drv.h +7 -0
@@ -110,6 +110,9 @@ struct msm_drm_private {unsigned int num_connectors;struct drm_connector *connectors[8 ]; +/* crtc's pending atomic update: */ +uint32_t pending_crtcs; +/* VRAM carveout, used when no IOMMU: */ struct {unsigned long size;
@@ -143,11 +146,15 @@ int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);int msm_wait_fence_interruptable (struct drm_device *dev,uint32_t fence,struct timespec *timeout); +int msm_queue_fence_cb (struct drm_device *dev, +struct msm_fence_cb *cb,uint32_t fence);void msm_update_fence (struct drm_device *dev,uint32_t fence);int msm_ioctl_gem_submit (struct drm_device *dev,void *data,struct drm_file *file); +int msm_atomic_commit (struct drm_device *dev,void *state); +int msm_gem_mmap (struct file *filp,struct vm_area_struct *vma);int msm_gem_fault (struct vm_area_struct *vma,struct vm_fault *vmf);uint64_t msm_gem_mmap_offset (struct drm_gem_object *obj);
drivers/gpu/drm/msm/msm_gem.c +4 -20
@@ -390,23 +390,11 @@ void *msm_gem_vaddr(struct drm_gem_object *obj)int msm_gem_queue_inactive_cb (struct drm_gem_object *obj,struct msm_fence_cb *cb) { -struct drm_device *dev = obj->dev; -struct msm_drm_private *priv = dev->dev_private;struct msm_gem_object *msm_obj =to_msm_bo (obj); -int ret =0 ; +uint32_t fence =msm_gem_fence (msm_obj, +MSM_PREP_READ |MSM_PREP_WRITE ); -mutex_lock (&dev->struct_mutex); -if (!list_empty (&cb->work.entry)) { - ret = -EINVAL ; - }else if (is_active (msm_obj)) { - cb->fence =max (msm_obj->read_fence, msm_obj->write_fence); -list_add_tail (&cb->work.entry, &priv->fence_cbs); - }else { -queue_work (priv->wq, &cb->work); - } -mutex_unlock (&dev->struct_mutex); - -return ret; +return msm_queue_fence_cb (obj->dev, cb, fence); } void msm_gem_move_to_active(struct drm_gem_object *obj,
@@ -445,12 +433,8 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,int ret =0 ;if (is_active (msm_obj)) { -uint32_t fence =0 ; +uint32_t fence =msm_gem_fence (msm_obj, op); -if (op &MSM_PREP_READ ) - fence = msm_obj->write_fence; -if (op &MSM_PREP_WRITE ) - fence =max (fence, msm_obj->read_fence);if (op &MSM_PREP_NOSYNC ) timeout =NULL ;
drivers/gpu/drm/msm/msm_gem.h +13 -0
@@ -70,6 +70,19 @@ static inline bool is_active(struct msm_gem_object *msm_obj)return msm_obj->gpu !=NULL ; } +static inline uint32_t msm_gem_fence (struct msm_gem_object *msm_obj, +uint32_t op) +{ +uint32_t fence =0 ; + +if (op &MSM_PREP_READ ) + fence = msm_obj->write_fence; +if (op &MSM_PREP_WRITE ) + fence =max (fence, msm_obj->read_fence); + +return fence; +} +#define MAX_CMDS 4/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
drivers/gpu/drm/msm/msm_kms.h +1 -0
@@ -42,6 +42,7 @@ struct msm_kms_funcs {const struct msm_format *(*get_format)(struct msm_kms *kms,uint32_t format);long (*round_pixclk)(struct msm_kms *kms,unsigned long rate,struct drm_encoder *encoder); +void (*flush)(struct msm_kms *kms,struct drm_crtc *crtc);/* cleanup: */ void (*preclose)(struct msm_kms *kms,struct drm_file *file);void (*destroy)(struct msm_kms *kms);
Signature · 1 line
1.8.5.3
PATCH 16/16 drm: spiff out FB refcnting traces
In reply to Rob ClarkI find myself making this change locally whenever debugging FB reference counting. Which seems a bit silly.
--- drivers/gpu/drm/drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_crtc.c +3 -3
@@ -600,7 +600,7 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);*/ void drm_framebuffer_unreference (struct drm_framebuffer *fb) { -DRM_DEBUG ("FB ID: %d\n" , fb->base.id); +DRM_DEBUG ("%p: FB ID: %d (%d)\n" , fb, fb->base.id, fb->refcount.refcount.counter);kref_put (&fb->refcount, drm_framebuffer_free); }EXPORT_SYMBOL (drm_framebuffer_unreference);
@@ -611,7 +611,7 @@ EXPORT_SYMBOL(drm_framebuffer_unreference);*/ void drm_framebuffer_reference (struct drm_framebuffer *fb) { -DRM_DEBUG ("FB ID: %d\n" , fb->base.id); +DRM_DEBUG ("%p: FB ID: %d (%d)\n" , fb, fb->base.id, fb->refcount.refcount.counter);kref_get (&fb->refcount); }EXPORT_SYMBOL (drm_framebuffer_reference);
@@ -623,7 +623,7 @@ static void drm_framebuffer_free_bug(struct kref *kref)static void __drm_framebuffer_unreference (struct drm_framebuffer *fb) { -DRM_DEBUG ("FB ID: %d\n" , fb->base.id); +DRM_DEBUG ("%p: FB ID: %d (%d)\n" , fb, fb->base.id, fb->refcount.refcount.counter);kref_put (&fb->refcount, drm_framebuffer_free_bug); }
Signature · 1 line
1.8.5.3
Quoted 33 lines · Rob Clark
Previous revision of series:
http://lists.freedesktop.org/archives/dri-devel/2013-November/049594.htmlAnd if you prefer, in git form:
http://cgit.freedesktop.org/~robclark/linux/log/?h=cold-fusiongit://people.freedesktop.org/~robclark/linuxcold-fusionCompared to previous revision:
* rebased on primary-plane RFC series. As a result, nearly none of the drivers actually compile at the moment :-PBut it is in the end a good thing... it reduces some code paths (now only having to care about fbs on planes, and it avoids exposing an intermediate ABI state to userspace so avoids the need for some compat glue later).
* state objects now carry their own ref to fbs. This cleaned up most of the refcnt'ing issues, so I'm pretty happy how that turned out. With that plus all the other major hacks cleaned up, I'm happy enough to drop the "RFC" tag.
There are, I think, two remaining issues to solve:
* we either need to add an event ptr param toplane->update_plane()or come up with another way to handle events on planes.* I kinda would still like to add to the atomic ioctl some way to indicate ok/error on a bit finer granularity than per-ioctl. Ie. perhaps an array where userspace can ask for results per KMS object (crtc/plane)? Something along these lines would give the kernel a bit more flexibility to deal with some of the edge cases which come up when you gang crtcs for ultra high resolution displays. In short, it would let the driver "steal" some of the planes if needed from userspace.
Quoted 8 lines
This would also, conveniently, be pretty similar to how (AFAIU) hw compositor and ADF work on android. Which seems like it would be useful to eventually enable android devices to use an upstream display driver.
For this we could pretty easily just throw in a placeholder that we could replace later with an optional ptr to
__userarray. I think that would be fine for an initial version, but I just wanted to throw this idea out there, because I think it will become important.
Hm, do you have some pointers to read up on this? I still think a more elaborate fail scheme is overkill, but maybe reading a bit of android code convinces me differently ;-)
Quoted 25 lines
Note that this series is really only the beginning of atomic. Once this is merged, there are some various vague thoughts about next steps:
* finish converting remaining callers ofdrm_mode_set_config_internal()to use atomic* replace driver usage of
plane->fbwithplane->state->fb.. dropplane->fb, somewhere along the way deprecate/drop ->page_flip() and possibly current incarnation of ->update_plane()..* perhaps some more fine grained event notification or other such extensions.
* I know there are a few things I plan on ripping out / simplifying in drm/msm as a result of atomic, but just waiting until this is merge to avoid carrying such
.......
So, that all said, I am a bit curious about how we might eventually land this series some day. Especially once we include changes to update all points in various drivers that access
crtc->fbtocrtc->primary->fbit will be one big hairy merge-conflict-prone branch. Not the sort of thing that I'd really like to have to rebase for the next five kernel cycles if at all avoidable.
Quoted 4 lines
We certainly could merge everything but the new ioctl, or hide the ioctl behind an experimental module param for now. I'm less concerned about that (either option would be pretty easy), and more about merging the infrastructure changes.
On the i915 side I think all the various pieces we need are finally coming together, and I hope a lot of that goes in for 3.16. So I think we can soonish jump on board with providing real proof-of-concepts based on your ioctl.
For merging the core stuff I think we should concentrate first on getting Matt's universal planes stuff in asap. I've scanned through his series with a cursory look and atm it has a few change-the-world flag days. I'll try to do an in-depth review later on looking for ways to make the transition smoother. cursor planes seem to be the main culprit in this ...
Everything else should be doable by shoveling helper code into the existing drm functions to handle primary and cursor planes without any invasive driver changes. With the exception of the crtc->fb to crtc->primary->fb transition maybe. But since that's a pure sed job it should be doable (cocinelle job maybe).
For merging the actual atomic stuff I wonder a bit whether we shouldn't make this fully opt-in. Atomic without driver support is a bit pointless after all ;-) Of course we need to hide the thing behind a module option and maybe do a add_tain(TAINT_CRAP); in the ioctl. Then we can throw the switch once we have a few drivers ported and userspace ready and all tested.
-Daniel
Quoted 139 lines
Rob Clark (13):
drm: fix typo
drm: add atomic fxns
drm: convert crtc toww_mutex
drm: add object property type
drm: add signed-range property type
drm: helpers to find mode objects
drm: split propvals out and blob property support
drm: allow FB's indrm_mode_object_find
drm: convert plane to properties/state
drm: convert crtc to properties/state
drm: push locking down intorestore_fbdev_modedrm/msm: add atomic support
drm: spiff out FB refcnting tracesVille Syrjälä (3):
drm: Allowdrm_mode_object_find()to look up an object of any type
drm: Refactor object property check code
drm: Atomic modeset ioctldrivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/armada/armada_crtc.c | 15 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/armada/armada_output.c | 3 +- drivers/gpu/drm/armada/armada_overlay.c | 15 +- drivers/gpu/drm/ast/ast_drv.c | 6 + drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_drv.c | 6 + drivers/gpu/drm/cirrus/cirrus_drv.h | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 702 +++++++++++ drivers/gpu/drm/drm_crtc.c | 1667 +++++++++++++++++++-------- drivers/gpu/drm/drm_crtc_helper.c | 2 +- drivers/gpu/drm/drm_drv.c | 1 + drivers/gpu/drm/drm_fb_cma_helper.c | 9 +- drivers/gpu/drm/drm_fb_helper.c | 28 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 11 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 11 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/cdv_intel_dp.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 10 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 12 +- drivers/gpu/drm/gma500/psb_drv.c | 11 +- drivers/gpu/drm/gma500/psb_drv.h | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_drv.h | 4 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 10 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 23 +- drivers/gpu/drm/i2c/ch7006_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 8 + drivers/gpu/drm/i915/intel_crt.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 16 +- drivers/gpu/drm/i915/intel_dp.c | 7 +- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_fbdev.c | 6 +- drivers/gpu/drm/i915/intel_hdmi.c | 7 +- drivers/gpu/drm/i915/intel_lvds.c | 4 +- drivers/gpu/drm/i915/intel_sdvo.c | 23 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/i915/intel_tv.c | 11 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 7 + drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 69 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 15 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 66 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 15 +- drivers/gpu/drm/msm/msm_atomic.c | 141 +++ drivers/gpu/drm/msm/msm_drv.c | 33 +- drivers/gpu/drm/msm/msm_drv.h | 8 + drivers/gpu/drm/msm/msm_gem.c | 24 +- drivers/gpu/drm/msm/msm_gem.h | 13 + drivers/gpu/drm/msm/msm_kms.h | 1 + drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/dispnv04/overlay.c | 14 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 3 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 7 + drivers/gpu/drm/nouveau/nouveau_drm.h | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 27 +- drivers/gpu/drm/omapdrm/omap_drv.c | 16 +- drivers/gpu/drm/omapdrm/omap_drv.h | 5 +- drivers/gpu/drm/omapdrm/omap_plane.c | 11 +- drivers/gpu/drm/qxl/qxl_display.c | 6 +- drivers/gpu/drm/qxl/qxl_drv.c | 9 + drivers/gpu/drm/radeon/radeon_connectors.c | 9 +- drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/radeon/radeon_drv.c | 9 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 3 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 12 +- drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 7 + drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 1 + drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 + drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +- drivers/gpu/drm/udl/udl_connector.c | 6 +- drivers/gpu/drm/udl/udl_drv.c | 8 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drmP.h | 88 +- include/drm/drm_atomic.h | 172 +++ include/drm/drm_crtc.h | 379 +++++- include/drm/drm_fb_helper.h | 3 +- include/uapi/drm/drm.h | 12 + include/uapi/drm/drm_mode.h | 38 + 106 files changed, 3214 insertions(+), 792 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic.c create mode 100644 drivers/gpu/drm/msm/msm_atomic.c create mode 100644 include/drm/drm_atomic.hSignature · 6 lines
1.8.5.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Quoted 38 lines · Daniel Vetter
Quoted 37 lines · Rob Clark
Previous revision of series:
http://lists.freedesktop.org/archives/dri-devel/2013-November/049594.htmlAnd if you prefer, in git form:
http://cgit.freedesktop.org/~robclark/linux/log/?h=cold-fusiongit://people.freedesktop.org/~robclark/linuxcold-fusionCompared to previous revision:
* rebased on primary-plane RFC series. As a result, nearly none of the drivers actually compile at the moment :-PBut it is in the end a good thing... it reduces some code paths (now only having to care about fbs on planes, and it avoids exposing an intermediate ABI state to userspace so avoids the need for some compat glue later).
* state objects now carry their own ref to fbs. This cleaned up most of the refcnt'ing issues, so I'm pretty happy how that turned out. With that plus all the other major hacks cleaned up, I'm happy enough to drop the "RFC" tag.
There are, I think, two remaining issues to solve:
* we either need to add an event ptr param toplane->update_plane()or come up with another way to handle events on planes.* I kinda would still like to add to the atomic ioctl some way to indicate ok/error on a bit finer granularity than per-ioctl. Ie. perhaps an array where userspace can ask for results per KMS object (crtc/plane)? Something along these lines would give the kernel a bit more flexibility to deal with some of the edge cases which come up when you gang crtcs for ultra high resolution displays. In short, it would let the driver "steal" some of the planes if needed from userspace.
This would also, conveniently, be pretty similar to how (AFAIU) hw compositor and ADF work on android. Which seems like it would be useful to eventually enable android devices to use an upstream display driver.
Quoted 8 lines
Quoted 4 lines
For this we could pretty easily just throw in a placeholder that we could replace later with an optional ptr to
__userarray. I think that would be fine for an initial version, but I just wanted to throw this idea out there, because I think it will become important.Hm, do you have some pointers to read up on this? I still think a more elaborate fail scheme is overkill, but maybe reading a bit of android code convinces me differently ;-)
sadly no pointers to anything to read (but ofc would be interested if anyone else does)..
Mostly it comes out of thinking through what I'll need to support ultra-wide displays.. the hw seems to have support for doubling up pipes into blenders (planes into crtcs) as well as blenders into encoders. And afaiu, I get to deal with one hw generation which needs me to use two pipes if an overlay spans the middle of the screen, while a later generation only needs double-wide pipes for overlays beyond a certain width.
The sanest way I can think to deal with this is if the kernel has a way to tell userspace that it can do certain layers in the requested overlay config but needs other layers to fall back to gpu compositing.
Without something like this, every frame will just fall back to 100%
gpu composition, which really isn't the desired result.
Quoted 35 lines
Quoted 25 lines
Note that this series is really only the beginning of atomic. Once this is merged, there are some various vague thoughts about next steps:
* finish converting remaining callers ofdrm_mode_set_config_internal()to use atomic* replace driver usage of
plane->fbwithplane->state->fb.. dropplane->fb, somewhere along the way deprecate/drop ->page_flip() and possibly current incarnation of ->update_plane()..* perhaps some more fine grained event notification or other such extensions.
* I know there are a few things I plan on ripping out / simplifying in drm/msm as a result of atomic, but just waiting until this is merge to avoid carrying such
.......
So, that all said, I am a bit curious about how we might eventually land this series some day. Especially once we include changes to update all points in various drivers that access
crtc->fbtocrtc->primary->fbit will be one big hairy merge-conflict-prone branch. Not the sort of thing that I'd really like to have to rebase for the next five kernel cycles if at all avoidable.Quoted 4 lines
We certainly could merge everything but the new ioctl, or hide the ioctl behind an experimental module param for now. I'm less concerned about that (either option would be pretty easy), and more about merging the infrastructure changes.
On the i915 side I think all the various pieces we need are finally coming together, and I hope a lot of that goes in for 3.16. So I think we can soonish jump on board with providing real proof-of-concepts based on your ioctl.
Quoted 5 lines
For merging the core stuff I think we should concentrate first on getting Matt's universal planes stuff in asap. I've scanned through his series with a cursory look and atm it has a few change-the-world flag days. I'll try to do an in-depth review later on looking for ways to make the transition smoother. cursor planes seem to be the main culprit in this ...
it would be nice if there was a way to get things merged sooner than 3.18 or so.. but we do need at least the *initial* primary plane work first.
Some of the stuff like cursor planes should really happen independently from atomic. And maybe at the same time we want to expose cursor properties, or at least somehow property-ify cursors. The part that really needs to be in before atomic is the crtc->primary->fb bit.
Quoted 6 lines
Everything else should be doable by shoveling helper code into the existing drm functions to handle primary and cursor planes without any invasive driver changes. With the exception of the
crtc->fbtocrtc->primary->fbtransition maybe. But since that's a pure sed job it should be doable (cocinelle job maybe).
Quoted 6 lines
For merging the actual atomic stuff I wonder a bit whether we shouldn't make this fully opt-in. Atomic without driver support is a bit pointless after all ;-) Of course we need to hide the thing behind a module option and maybe do a
add_tain(TAINT_CRAP); in the ioctl. Then we can throw the switch once we have a few drivers ported and userspace ready and all tested.
yeah, some combination of module param and possibly a driver cap flag would be reasonable.
fwiw I had even initially thought about entirely keeping the legacy .page_flip()/.update_plane()/etc codepaths in place to even make the new atomic infrastructure opt-in, but it started getting pretty ugly before I killed off that idea.
BR,
-R
Quoted 146 lines
-Daniel
Quoted 132 lines
Rob Clark (13):
drm: fix typo
drm: add atomic fxns
drm: convert crtc toww_mutex
drm: add object property type
drm: add signed-range property type
drm: helpers to find mode objects
drm: split propvals out and blob property support
drm: allow FB's indrm_mode_object_find
drm: convert plane to properties/state
drm: convert crtc to properties/state
drm: push locking down intorestore_fbdev_modedrm/msm: add atomic support
drm: spiff out FB refcnting tracesVille Syrjälä (3):
drm: Allowdrm_mode_object_find()to look up an object of any type
drm: Refactor object property check code
drm: Atomic modeset ioctldrivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/armada/armada_crtc.c | 15 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/armada/armada_output.c | 3 +- drivers/gpu/drm/armada/armada_overlay.c | 15 +- drivers/gpu/drm/ast/ast_drv.c | 6 + drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_drv.c | 6 + drivers/gpu/drm/cirrus/cirrus_drv.h | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 702 +++++++++++ drivers/gpu/drm/drm_crtc.c | 1667 +++++++++++++++++++-------- drivers/gpu/drm/drm_crtc_helper.c | 2 +- drivers/gpu/drm/drm_drv.c | 1 + drivers/gpu/drm/drm_fb_cma_helper.c | 9 +- drivers/gpu/drm/drm_fb_helper.c | 28 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 11 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 11 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/cdv_intel_dp.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 10 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 12 +- drivers/gpu/drm/gma500/psb_drv.c | 11 +- drivers/gpu/drm/gma500/psb_drv.h | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_drv.h | 4 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 10 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 23 +- drivers/gpu/drm/i2c/ch7006_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 8 + drivers/gpu/drm/i915/intel_crt.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 16 +- drivers/gpu/drm/i915/intel_dp.c | 7 +- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_fbdev.c | 6 +- drivers/gpu/drm/i915/intel_hdmi.c | 7 +- drivers/gpu/drm/i915/intel_lvds.c | 4 +- drivers/gpu/drm/i915/intel_sdvo.c | 23 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/i915/intel_tv.c | 11 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 7 + drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 69 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 15 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 66 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 15 +- drivers/gpu/drm/msm/msm_atomic.c | 141 +++ drivers/gpu/drm/msm/msm_drv.c | 33 +- drivers/gpu/drm/msm/msm_drv.h | 8 + drivers/gpu/drm/msm/msm_gem.c | 24 +- drivers/gpu/drm/msm/msm_gem.h | 13 + drivers/gpu/drm/msm/msm_kms.h | 1 + drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/dispnv04/overlay.c | 14 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 3 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 7 + drivers/gpu/drm/nouveau/nouveau_drm.h | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 27 +- drivers/gpu/drm/omapdrm/omap_drv.c | 16 +- drivers/gpu/drm/omapdrm/omap_drv.h | 5 +- drivers/gpu/drm/omapdrm/omap_plane.c | 11 +- drivers/gpu/drm/qxl/qxl_display.c | 6 +- drivers/gpu/drm/qxl/qxl_drv.c | 9 + drivers/gpu/drm/radeon/radeon_connectors.c | 9 +- drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/radeon/radeon_drv.c | 9 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 3 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 12 +- drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 7 + drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 1 + drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 + drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +- drivers/gpu/drm/udl/udl_connector.c | 6 +- drivers/gpu/drm/udl/udl_drv.c | 8 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drmP.h | 88 +- include/drm/drm_atomic.h | 172 +++ include/drm/drm_crtc.h | 379 +++++- include/drm/drm_fb_helper.h | 3 +- include/uapi/drm/drm.h | 12 + include/uapi/drm/drm_mode.h | 38 + 106 files changed, 3214 insertions(+), 792 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic.c create mode 100644 drivers/gpu/drm/msm/msm_atomic.c create mode 100644 include/drm/drm_atomic.hQuoted 7 lines
--
1.8.5.3_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Quoted 17 lines · Rob Clark
Quoted 11 lines · Daniel Vetter
On Tue, Mar 18, 2014 at 05:22:37PM -0400, Rob Clark wrote:
On the i915 side I think all the various pieces we need are finally coming together, and I hope a lot of that goes in for 3.16. So I think we can soonish jump on board with providing real proof-of-concepts based on your ioctl.For merging the core stuff I think we should concentrate first on getting Matt's universal planes stuff in asap. I've scanned through his series with a cursory look and atm it has a few change-the-world flag days. I'll try to do an in-depth review later on looking for ways to make the transition smoother. cursor planes seem to be the main culprit in this ...
it would be nice if there was a way to get things merged sooner than 3.18 or so.. but we do need at least the *initial* primary plane work first.
Quoted 5 lines
Some of the stuff like cursor planes should really happen independently from atomic. And maybe at the same time we want to expose cursor properties, or at least somehow property-ify cursors. The part that really needs to be in before atomic is the
crtc->primary->fbbit.
Hm, just wanted to dump a comment on Matt's series that imo cursor planes should happen first before we enable universal planes. And the resulting unification is really kinda neat for atomic imo.
Still pondering the details but I don't think there's too much fuzz involved in exposing cursor planes. We can't do it without any driver changes at all since there's no generic way to go from cursor fb to buffer manager object id. But beyond that there's shouldn't be anything needed.
I'm hashing out a slightly more detailed plan atm. -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Quoted 8 lines · Rob Clark
Quoted 2 lines
Hm, do you have some pointers to read up on this? I still think a more elaborate fail scheme is overkill, but maybe reading a bit of android
code
Quoted 1 line
convinces me differently ;-)
sadly no pointers to anything to read (but ofc would be interested if anyone else does)..
The hardware composer HAL is probably the best reference for what Android needs from display. It's defined and documented here (see struct hwc_composer_device_1):
*https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/hwcomposer.h
<https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/hwcomposer.h>*
(You can disregard any HWC 1.0 specific behavior in that documentation, that's only around for legacy reasons and we strongly encourage vendors not to implement HWC 1.0 anymore.)
Vendors need to ship a compliant HWC HAL implementation on their devices.
We don't mandate anything about their userspace/kernel interface beyond
that.
Quoted 8 lines
* I kinda would still like to add to the atomic ioctl some way to indicate ok/error on a bit finer granularity than per-ioctl. Ie. perhaps an array where userspace can ask for results per KMS object (crtc/plane)? Something along these lines would give the kernel a bit more flexibility to deal with some of the edge cases which come up when you gang crtcs for ultra high resolution displays. In short, it would let the driver "steal" some of the planes if needed from userspace.
Quoted 9 lines
This would also, conveniently, be pretty similar to how (AFAIU) hw compositor and ADF work on android. Which seems like it would be useful to eventually enable android devices to use an upstream display driver.
For this we could pretty easily just throw in a placeholder that we could replace later with an optional ptr to
__userarray. I think that would be fine for an initial version, but I just wanted to throw this idea out there, because I think it will become important.
SurfaceFlinger needs the HWC HAL to return a retire fence fd on each flip, for each display. Per-interface return data would be a good fit for this, but per-CRTC or per-plane would work too (userspace could assemble a per-interface fence by merging finer-grained fences).
It's up to the vendor whether their HWC HAL does fine-grained error handling and renegotiation like you're describing. Typically they don't, they just push that complexity into userspace instead. e.g. if the display controller needs to gang together two planes for a given configuration, the HWC HAL's prepare() op will already know to set aside that extra plane and plan accordingly.
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 11 lines · Greg Hackmann
Quoted 8 lines · Rob Clark
Quoted 5 lines
Hm, do you have some pointers to read up on this? I still think a more elaborate fail scheme is overkill, but maybe reading a bit of android code
convinces me differently ;-)sadly no pointers to anything to read (but ofc would be interested if anyone else does)..
Quoted 6 lines
The hardware composer HAL is probably the best reference for what Android needs from display. It's defined and documented here (see struct
hwc_composer_device_1):
cool, thx for the link
Quoted 30 lines
(You can disregard any HWC 1.0 specific behavior in that documentation, that's only around for legacy reasons and we strongly encourage vendors not to implement HWC 1.0 anymore.)
Vendors need to ship a compliant HWC HAL implementation on their devices. We don't mandate anything about their userspace/kernel interface beyond that.
Quoted 16 lines
* I kinda would still like to add to the atomic ioctl some way to
indicate
ok/error on a bit finer granularity than per-ioctl. Ie. perhaps an array where userspace can ask for results per KMS object (crtc/plane)? Something along these lines would give the kernel a bit more
flexibility
to deal with some of the edge cases which come up when you gang crtcs for ultra high resolution displays. In short, it would let the driver "steal" some of the planes if needed from userspace.This would also, conveniently, be pretty similar to how (AFAIU) hw compositor and ADF work on android. Which seems like it would be
useful
to eventually enable android devices to use an upstream display driver.Quoted 4 lines
For this we could pretty easily just throw in a placeholder that we could replace later with an optional ptr to
__userarray. I think that would be fine for an initial version, but I just wanted to throw this idea out there, because I think it will become important.
Quoted 4 lines
SurfaceFlinger needs the HWC HAL to return a retire fence fd on each flip, for each display. Per-interface return data would be a good fit for this, but per-CRTC or per-plane would work too (userspace could assemble a per-interface fence by merging finer-grained fences).
oh, that's right.. I'm glad you reminded me, I do remember now talk of a field which drivers could use to return some opaque (to drm core) handle/value/token/whatever..
hmm, for the non-vsync'd multi-display case, does it matter much one ioctl per display vs one globally?
If no, I'd vote for just one output field in the ioctl struct which can be whatever the driver wants it to.. that would be pretty simple.
Quoted 6 lines
It's up to the vendor whether their HWC HAL does fine-grained error handling and renegotiation like you're describing. Typically they don't, they just push that complexity into userspace instead. e.g. if the display controller needs to gang together two planes for a given configuration, the HWC HAL's
prepare()op will already know to set aside that extra plane and plan accordingly.
Well, I suspect that this is in the HWC HAL at all is a strong indication that we should think about including this somehow in the atomic ioctl.. considering that the trend for wayland compositors is a fairly generic userspace just using kms+gbm directly. I suspect the alternative will only be an atomic2 ioctl at some point ;-)
A crazy idea.. if atomic ioctl could atomically both write and then read some properties. Maybe kill two birds with one stone by letting userspace both specify a set of properties it wants to write, and also a set to read.
BR,
-R
Quoted 1 line
Quoted 9 lines · Rob Clark
oh, that's right.. I'm glad you reminded me, I do remember now talk of a field which drivers could use to return some opaque (to drm core) handle/value/token/whatever..
hmm, for the non-vsync'd multi-display case, does it matter much one ioctl per display vs one globally?
If no, I'd vote for just one output field in the ioctl struct which can be whatever the driver wants it to.. that would be pretty simple.
If you're planning to support generic clients, you'd at least need some way to indicate the output contains an fd that the client's responsible for closing. Otherwise it would leak a fence (or whatever fd-backed object that's being returned) each time it updates the display.
Quoted 8 lines
Quoted 1 line
It's up to the vendor whether their HWC HAL does fine-grained error
handling
Quoted 1 line
and renegotiation like you're describing. Typically they don't, they
just
Quoted 1 line
push that complexity into userspace instead. e.g. if the display
controller
Quoted 1 line
needs to gang together two planes for a given configuration, the HWC
HAL's
Quoted 9 lines
Quoted 2 lines
prepare()op will already know to set aside that extra plane and plan accordingly.Well, I suspect that this is in the HWC HAL at all is a strong indication that we should think about including this somehow in the atomic ioctl.. considering that the trend for wayland compositors is a fairly generic userspace just using kms+gbm directly. I suspect the alternative will only be an atomic2 ioctl at some point ;-)
These policies are complicated enough that I'm skeptical you could push them into the kernel without making the drivers really large and complicated. A typical HWC HAL will have thousands of lines of code plus pull in other helper libraries, and the bulk of that will be for planning the composition in the prepare() op. Maybe you could break some of that out into common helper code, but IME and IMO the hardware constraints are too different from SoC to SoC for that to scale.
That said, I'd be happy to be proven wrong -- if the hypothetical atomic2 ioctl has a kernel counterpart that I'm comfortable recommending to vendors, being able to write a single generic HWC HAL would be good for Android too.
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 50 lines · Greg Hackmann
Quoted 8 lines · Rob Clark
Quoted 2 lines
Hm, do you have some pointers to read up on this? I still think a more elaborate fail scheme is overkill, but maybe reading a bit of android
code
Quoted 1 line
convinces me differently ;-)
sadly no pointers to anything to read (but ofc would be interested if anyone else does)..
The hardware composer HAL is probably the best reference for what Android needs from display. It's defined and documented here (see struct
hwc_composer_device_1):*https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/hwcomposer.h
<https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/hwcomposer.h>*(You can disregard any HWC 1.0 specific behavior in that documentation, that's only around for legacy reasons and we strongly encourage vendors not to implement HWC 1.0 anymore.)
Vendors need to ship a compliant HWC HAL implementation on their devices.
We don't mandate anything about their userspace/kernel interface beyond
that.Quoted 8 lines
* I kinda would still like to add to the atomic ioctl some way to indicate ok/error on a bit finer granularity than per-ioctl. Ie. perhaps an array where userspace can ask for results per KMS object (crtc/plane)? Something along these lines would give the kernel a bit more flexibility to deal with some of the edge cases which come up when you gang crtcs for ultra high resolution displays. In short, it would let the driver "steal" some of the planes if needed from userspace.
Quoted 9 lines
This would also, conveniently, be pretty similar to how (AFAIU) hw compositor and ADF work on android. Which seems like it would be useful to eventually enable android devices to use an upstream display driver.
For this we could pretty easily just throw in a placeholder that we could replace later with an optional ptr to
__userarray. I think that would be fine for an initial version, but I just wanted to throw this idea out there, because I think it will become important.SurfaceFlinger needs the HWC HAL to return a retire fence fd on each flip, for each display. Per-interface return data would be a good fit for this, but per-CRTC or per-plane would work too (userspace could assemble a per-interface fence by merging finer-grained fences).
Quoted 6 lines
It's up to the vendor whether their HWC HAL does fine-grained error handling and renegotiation like you're describing. Typically they don't, they just push that complexity into userspace instead. e.g. if the display controller needs to gang together two planes for a given configuration, the HWC HAL's
prepare()op will already know to set aside that extra plane and plan accordingly.
I've read through the hwc interface stuff and some question only marginally related to atomic pageflips poppped up.
- You have an explicit callback for vblank events (well, just the interrupt, afaics no support to get a vblank event for a specific frame in the future). Any reason not to use android syncpoint fences for this like everywhere else? Or is the idea behind all the fences hwc throws around just to synchronize read/write access from cpu/render/codec/whatever and not so much timing?
- If I read this correct you mandate that the fences fields gets filled out in the prepare hook, i.e. before we commit the new state to hardware. You also mandate that the fences get eventually signalled even when surfaceflinger decides to not commit the new state. I see two consequences from that:
- You create fences before the kernel is committed to execute the relevant event which will trigger the fence.
- Userspace seems to be required to trigger fences manually to unblock things in case the hw state isn't committed.
This seems to be squarely at odds with the hw fences Maarten Lankhorst, which currently have two guarantees:
- Fences can only be created when the kernel commits to execute the event that will trigger the fence.
- A global ordering is imposed upon all fence updates (and so scheduled depencies when one fences needs to wait for another).
Together this ensures that we never schedule a deadlock in hw fences and that no hw fence ever depends upon userspace signalling some fences.
How do you tackle these issues with surfaceflinger/hwc? Or if this blows up and the hw deadlocks it's the integrates problem to track it down (or just reset the gpu and everything else to get unstuck)?
Cheers, Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Quoted 8 lines · Daniel Vetter
- You have an explicit callback for vblank events (well, just the interrupt, afaics no support to get a vblank event for a specific frame in the future). Any reason not to use android syncpoint fences for this like everywhere else? Or is the idea behind all the fences hwc throws around just to synchronize read/write access from cpu/render/codec/whatever and not so much timing?
Vsync events are used to kick off Android's rendering loop. The upshot is that when SurfaceFlinger requests vsync events from the HWC HAL, it needs to deliver them at every vsync even if the display hasn't changed.
Fences tell a consumer when the producer's done with the buffer, and aren't really meant for timing. (Or probably even useful for timing, since they don't pass along any timestamping information about when the event happened.)
- If I read this correct you mandate that the fences fields gets filled
Quoted 4 lines
out in the prepare hook, i.e. before we commit the new state to hardware. You also mandate that the fences get eventually signalled even when surfaceflinger decides to not commit the new state.
The HWC HAL needs to fill in the release fences during set(). The mandate w.r.t. fences is that if SurfaceFlinger calls
prepare(A)
set(A)
prepare(B)
set(B)
and something inside set(B) fails for some reason, the HWC HAL must ensure that the fences returned by set(A) eventually fire anyway. That situation really shouldn't happen unless something goes horribly wrong, since the expectation is that prepare(B) will pick a composition that set(B) can display.
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 33 lines · Greg Hackmann
Quoted 7 lines · Daniel Vetter
- You have an explicit callback for vblank events (well, just the interrupt, afaics no support to get a vblank event for a specific frame in the future). Any reason not to use android syncpoint fences for this like everywhere else? Or is the idea behind all the fences hwc throws around just to synchronize read/write access from cpu/render/codec/whatever and not so much timing?
Vsync events are used to kick off Android's rendering loop. The upshot is that when SurfaceFlinger requests vsync events from the HWC HAL, it needs to deliver them at every vsync even if the display hasn't changed.
Fences tell a consumer when the producer's done with the buffer, and aren't really meant for timing. (Or probably even useful for timing, since they don't pass along any timestamping information about when the event happened.)
Quoted 4 lines
- If I read this correct you mandate that the fences fields gets filled out in the prepare hook, i.e. before we commit the new state to hardware. You also mandate that the fences get eventually signalled even when surfaceflinger decides to not commit the new state.
The HWC HAL needs to fill in the release fences during
set(). The mandate w.r.t. fences is that if SurfaceFlinger callsprepare(A)
set(A)
prepare(B)
set(B)
Quoted 5 lines
and something inside set(B) fails for some reason, the HWC HAL must ensure that the fences returned by set(A) eventually fire anyway. That situation really shouldn't happen unless something goes horribly wrong, since the expectation is that prepare(B) will pick a composition that set(B) can display.
Ah, thanks for the clarification, I was mixing up comments for ->set() and ->prepare when reading the interface spec. So that wording sounds like it's just to avoid resource leaks in case of a catastrophe so that framebuffers frome older set calls get eventually reused. Makes sense and with that I think we still can have useful compatibility between Maarten's fences and android syncpoints.
I still see some fun with userspace potentially being required to signal fences or fences created before the event is committed (e.g. when using a buffer for scanout, which means it'll get used until it's eventually replaced by something else). Just means there needs to be some scheduler to keep things from stalling forever. -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch