From a9e6f9f7d603ef769b4cd33e0a2b61ba48a1058e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 May 2017 01:27:10 +0300 Subject: [PATCH] drm: omapdrm: Use DRM core's atomic commit helper The DRM core atomic helper now supports asynchronous commits natively. The custom omapdrm implementation isn't needed anymore, remove it. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 112 ++++------------------------- drivers/gpu/drm/omapdrm/omap_drv.h | 9 +-- 2 files changed, 15 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 663e930a7b0f..b4ef3025e3e3 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -17,8 +17,6 @@ * this program. If not, see . */ -#include - #include #include #include @@ -54,13 +52,6 @@ static void omap_fb_output_poll_changed(struct drm_device *dev) drm_fb_helper_hotplug_event(priv->fbdev); } -struct omap_atomic_state_commit { - struct work_struct work; - struct drm_device *dev; - struct drm_atomic_state *state; - u32 crtcs; -}; - static void omap_atomic_wait_for_completion(struct drm_device *dev, struct drm_atomic_state *old_state) { @@ -81,15 +72,14 @@ static void omap_atomic_wait_for_completion(struct drm_device *dev, } } -static void omap_atomic_complete(struct omap_atomic_state_commit *commit) +static void omap_atomic_commit_tail(struct drm_atomic_state *old_state) { - struct drm_device *dev = commit->dev; + struct drm_device *dev = old_state->dev; struct omap_drm_private *priv = dev->dev_private; - struct drm_atomic_state *old_state = commit->state; - /* Apply the atomic update. */ priv->dispc_ops->runtime_get(); + /* Apply the atomic update. */ drm_atomic_helper_commit_modeset_disables(dev, old_state); /* With the current dss dispc implementation we have to enable @@ -108,101 +98,28 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) drm_atomic_helper_commit_planes(dev, old_state, 0); + drm_atomic_helper_commit_hw_done(old_state); + + /* + * Wait for completion of the page flips to ensure that old buffers + * can't be touched by the hardware anymore before cleaning up planes. + */ omap_atomic_wait_for_completion(dev, old_state); drm_atomic_helper_cleanup_planes(dev, old_state); priv->dispc_ops->runtime_put(); - - drm_atomic_state_put(old_state); - - /* Complete the commit, wake up any waiter. */ - spin_lock(&priv->commit.lock); - priv->commit.pending &= ~commit->crtcs; - spin_unlock(&priv->commit.lock); - - wake_up_all(&priv->commit.wait); - - kfree(commit); -} - -static void omap_atomic_work(struct work_struct *work) -{ - struct omap_atomic_state_commit *commit = - container_of(work, struct omap_atomic_state_commit, work); - - omap_atomic_complete(commit); } -static bool omap_atomic_is_pending(struct omap_drm_private *priv, - struct omap_atomic_state_commit *commit) -{ - bool pending; - - spin_lock(&priv->commit.lock); - pending = priv->commit.pending & commit->crtcs; - spin_unlock(&priv->commit.lock); - - return pending; -} - -static int omap_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, bool nonblock) -{ - struct omap_drm_private *priv = dev->dev_private; - struct omap_atomic_state_commit *commit; - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; - int i, ret; - - ret = drm_atomic_helper_prepare_planes(dev, state); - if (ret) - return ret; - - /* Allocate the commit object. */ - commit = kzalloc(sizeof(*commit), GFP_KERNEL); - if (commit == NULL) { - ret = -ENOMEM; - goto error; - } - - INIT_WORK(&commit->work, omap_atomic_work); - commit->dev = dev; - commit->state = state; - - /* Wait until all affected CRTCs have completed previous commits and - * mark them as pending. - */ - for_each_crtc_in_state(state, crtc, crtc_state, i) - commit->crtcs |= drm_crtc_mask(crtc); - - wait_event(priv->commit.wait, !omap_atomic_is_pending(priv, commit)); - - spin_lock(&priv->commit.lock); - priv->commit.pending |= commit->crtcs; - spin_unlock(&priv->commit.lock); - - /* Swap the state, this is the point of no return. */ - drm_atomic_helper_swap_state(state, true); - - drm_atomic_state_get(state); - if (nonblock) - schedule_work(&commit->work); - else - omap_atomic_complete(commit); - - return 0; - -error: - drm_atomic_helper_cleanup_planes(dev, state); - return ret; -} +static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs = { + .atomic_commit_tail = omap_atomic_commit_tail, +}; static const struct drm_mode_config_funcs omap_mode_config_funcs = { .fb_create = omap_framebuffer_create, .output_poll_changed = omap_fb_output_poll_changed, .atomic_check = drm_atomic_helper_check, - .atomic_commit = omap_atomic_commit, + .atomic_commit = drm_atomic_helper_commit, }; static int get_connector_type(struct omap_dss_device *dssdev) @@ -385,6 +302,7 @@ static int omap_modeset_init(struct drm_device *dev) dev->mode_config.max_height = 2048; dev->mode_config.funcs = &omap_mode_config_funcs; + dev->mode_config.helper_private = &omap_mode_config_helper_funcs; drm_mode_config_reset(dev); @@ -674,8 +592,6 @@ static int pdev_probe(struct platform_device *pdev) priv->omaprev = pdata->omaprev; priv->wq = alloc_ordered_workqueue("omapdrm", 0); - init_waitqueue_head(&priv->commit.wait); - spin_lock_init(&priv->commit.lock); spin_lock_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 7a4c57eb6536..54e6055ea1d3 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -93,13 +93,6 @@ struct omap_drm_private { spinlock_t wait_lock; /* protects the wait_list */ struct list_head wait_list; /* list of omap_irq_wait */ uint32_t irq_mask; /* enabled irqs in addition to wait_list */ - - /* atomic commit */ - struct { - wait_queue_head_t wait; - u32 pending; - spinlock_t lock; /* Protects commit.pending */ - } commit; }; -- 2.20.1