diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2018-07-30 12:53:06 +0200 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2018-07-30 12:53:06 +0200 |
commit | b1ec9ed6aa985be432f9ba29696029dc6779258e (patch) | |
tree | bff16f0376a11d219d923bbd08e1fc879b0f7a35 /drivers/gpu/drm/armada | |
parent | drm/armada: switch primary plane to atomic modeset (diff) | |
download | linux-b1ec9ed6aa985be432f9ba29696029dc6779258e.tar.xz linux-b1ec9ed6aa985be432f9ba29696029dc6779258e.zip |
drm/armada: switch overlay plane to atomic modeset
Switch the overlay plane away from the transitional helpers and legacy
methods, and use atomic helpers instead to implement the legacy
set_plane ioctl methods.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/armada')
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.c | 89 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.h | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_overlay.c | 172 |
3 files changed, 32 insertions, 248 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index a25094bbeb2c..ebcb99316c94 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -117,80 +117,6 @@ static void armada_drm_crtc_update(struct armada_crtc *dcrtc, bool enable) dcrtc->base + LCD_SPU_DUMB_CTRL); } -static void armada_drm_plane_work_call(struct armada_crtc *dcrtc, - struct armada_plane_work *work, - void (*fn)(struct armada_crtc *, struct armada_plane_work *)) -{ - struct armada_plane *dplane = drm_to_armada_plane(work->plane); - struct drm_pending_vblank_event *event; - struct drm_framebuffer *fb; - - if (fn) - fn(dcrtc, work); - drm_crtc_vblank_put(&dcrtc->crtc); - - event = work->event; - fb = work->old_fb; - if (event || fb) { - struct drm_device *dev = dcrtc->crtc.dev; - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); - if (event) - drm_crtc_send_vblank_event(&dcrtc->crtc, event); - if (fb) - __armada_drm_queue_unref_work(dev, fb); - spin_unlock_irqrestore(&dev->event_lock, flags); - } - - if (work->need_kfree) - kfree(work); - - wake_up(&dplane->frame_wait); -} - -static void armada_drm_plane_work_run(struct armada_crtc *dcrtc, - struct drm_plane *plane) -{ - struct armada_plane *dplane = drm_to_armada_plane(plane); - struct armada_plane_work *work = xchg(&dplane->work, NULL); - - /* Handle any pending frame work. */ - if (work) - armada_drm_plane_work_call(dcrtc, work, work->fn); -} - -int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, - struct armada_plane_work *work) -{ - struct armada_plane *plane = drm_to_armada_plane(work->plane); - int ret; - - ret = drm_crtc_vblank_get(&dcrtc->crtc); - if (ret) - return ret; - - ret = cmpxchg(&plane->work, NULL, work) ? -EBUSY : 0; - if (ret) - drm_crtc_vblank_put(&dcrtc->crtc); - - return ret; -} - -int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout) -{ - return wait_event_timeout(plane->frame_wait, !plane->work, timeout); -} - -void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc, - struct armada_plane *dplane) -{ - struct armada_plane_work *work = xchg(&dplane->work, NULL); - - if (work) - armada_drm_plane_work_call(dcrtc, work, work->cancel); -} - static void armada_drm_crtc_queue_state_event(struct drm_crtc *crtc) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); @@ -247,7 +173,6 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) { struct drm_pending_vblank_event *event; void __iomem *base = dcrtc->base; - struct drm_plane *ovl_plane; if (stat & DMA_FF_UNDERFLOW) DRM_ERROR("video underflow on crtc %u\n", dcrtc->num); @@ -257,10 +182,6 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) if (stat & VSYNC_IRQ) drm_crtc_handle_vblank(&dcrtc->crtc); - ovl_plane = dcrtc->plane; - if (ovl_plane) - armada_drm_plane_work_run(dcrtc, ovl_plane); - spin_lock(&dcrtc->irq_lock); if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { int i = stat & GRA_FRAME_IRQ0 ? 0 : 1; @@ -462,19 +383,9 @@ static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc, { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct drm_pending_vblank_event *event; - struct drm_plane *plane; DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); - /* - * For transition only - we must wait for completion of our - * untransitioned paths before changing anything. - */ - plane = dcrtc->plane; - if (plane) - WARN_ON(!armada_drm_plane_work_wait(drm_to_armada_plane(plane), - HZ)); - drm_crtc_vblank_off(crtc); armada_drm_crtc_update(dcrtc, false); diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index afc9266bc1e2..5b607d45f469 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -35,29 +35,12 @@ struct armada_crtc; struct armada_plane; struct armada_variant; -struct armada_plane_work { - void (*fn)(struct armada_crtc *, struct armada_plane_work *); - void (*cancel)(struct armada_crtc *, struct armada_plane_work *); - bool need_kfree; - struct drm_plane *plane; - struct drm_framebuffer *old_fb; - struct drm_pending_vblank_event *event; - struct armada_regs regs[24]; -}; - struct armada_plane { struct drm_plane base; wait_queue_head_t frame_wait; - struct armada_plane_work *work; }; #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) -int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, - struct armada_plane_work *work); -int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); -void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc, - struct armada_plane *plane); - struct armada_crtc { struct drm_crtc crtc; const struct armada_variant *variant; @@ -73,8 +56,6 @@ struct armada_crtc { bool interlaced; bool cursor_update; - struct drm_plane *plane; - struct armada_gem_object *cursor_obj; int cursor_x; int cursor_y; diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 7de8b6bd7847..ec2043b6f61f 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -27,9 +27,6 @@ struct armada_ovl_plane { struct armada_plane base; - struct armada_plane_work works[2]; - bool next_work; - bool wait_vblank; }; #define drm_to_armada_ovl_plane(p) \ container_of(p, struct armada_ovl_plane, base.base) @@ -74,18 +71,6 @@ static inline u32 armada_csc(struct drm_plane_state *state) } /* === Plane support === */ -static void armada_ovl_plane_work(struct armada_crtc *dcrtc, - struct armada_plane_work *work) -{ - unsigned long flags; - - trace_armada_ovl_plane_work(&dcrtc->crtc, work->plane); - - spin_lock_irqsave(&dcrtc->irq_lock, flags); - armada_drm_crtc_update_regs(dcrtc, work->regs); - spin_unlock_irqrestore(&dcrtc->irq_lock, flags); -} - static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { @@ -109,8 +94,6 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane, dcrtc = drm_to_armada_crtc(state->crtc); regs = dcrtc->regs + dcrtc->regs_idx; - drm_to_armada_ovl_plane(plane)->wait_vblank = false; - idx = 0; if (!old_state->visible && state->visible) armada_reg_queue_mod(regs, idx, @@ -173,8 +156,6 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane, CFG_SWAPYU | CFG_YUV2RGB) | CFG_DMA_FTOGGLE | CFG_DMA_TSTMODE | CFG_DMA_ENA; - - drm_to_armada_ovl_plane(plane)->wait_vblank = true; } else if (old_state->visible != state->visible) { cfg = state->visible ? CFG_DMA_ENA : 0; cfg_mask = CFG_DMA_ENA; @@ -262,9 +243,6 @@ static void armada_drm_overlay_plane_atomic_disable(struct drm_plane *plane, LCD_SPU_SRAM_PARA1); dcrtc->regs_idx += idx; - - if (dcrtc->plane == plane) - dcrtc->plane = NULL; } static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = { @@ -275,108 +253,50 @@ static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = { .atomic_disable = armada_drm_overlay_plane_atomic_disable, }; -static int armada_overlay_commit(struct drm_plane *plane, - struct drm_plane_state *state) -{ - struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); - const struct drm_plane_helper_funcs *plane_funcs; - struct armada_crtc *dcrtc = drm_to_armada_crtc(state->crtc); - struct armada_plane_work *work; - int ret; - - plane_funcs = plane->helper_private; - ret = plane_funcs->atomic_check(plane, state); - if (ret) - goto put_state; - - work = &dplane->works[dplane->next_work]; - - if (plane->state->fb != state->fb) { - /* - * Take a reference on the new framebuffer - we want to - * hold on to it while the hardware is displaying it. - */ - drm_framebuffer_reference(state->fb); - - work->old_fb = plane->state->fb; - } else { - work->old_fb = NULL; - } - - /* Point of no return */ - swap(plane->state, state); - - /* No CRTC, can't update */ - if (!plane->state->crtc) - goto put_state; - - dcrtc->regs_idx = 0; - dcrtc->regs = work->regs; - - plane_funcs->atomic_update(plane, state); - - /* If nothing was updated, short-circuit */ - if (dcrtc->regs_idx == 0) - goto put_state; - - armada_reg_queue_end(dcrtc->regs, dcrtc->regs_idx); - - /* Wait for pending work to complete */ - if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0) - armada_drm_plane_work_cancel(dcrtc, &dplane->base); - - /* Just updating the position/size? */ - if (!dplane->wait_vblank) { - armada_ovl_plane_work(dcrtc, work); - goto put_state; - } - - dcrtc->plane = plane; - - /* Queue it for update on the next interrupt if we are enabled */ - ret = armada_drm_plane_work_queue(dcrtc, work); - if (ret) { - DRM_ERROR("failed to queue plane work: %d\n", ret); - ret = 0; - } - - dplane->next_work = !dplane->next_work; - -put_state: - plane->funcs->atomic_destroy_state(plane, state); - return ret; -} - static int -armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, +armada_overlay_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, struct drm_modeset_acquire_ctx *ctx) { - struct drm_plane_state *state; + struct drm_atomic_state *state; + struct drm_plane_state *plane_state; + int ret = 0; trace_armada_ovl_plane_update(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h); - /* Construct new state for the overlay plane */ - state = plane->funcs->atomic_duplicate_state(plane); + state = drm_atomic_state_alloc(plane->dev); if (!state) return -ENOMEM; - state->crtc = crtc; - drm_atomic_set_fb_for_plane(state, fb); - state->crtc_x = crtc_x; - state->crtc_y = crtc_y; - state->crtc_h = crtc_h; - state->crtc_w = crtc_w; - state->src_x = src_x; - state->src_y = src_y; - state->src_h = src_h; - state->src_w = src_w; - - return armada_overlay_commit(plane, state); + state->acquire_ctx = ctx; + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto fail; + } + + ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); + if (ret != 0) + goto fail; + + drm_atomic_set_fb_for_plane(plane_state, fb); + plane_state->crtc_x = crtc_x; + plane_state->crtc_y = crtc_y; + plane_state->crtc_h = crtc_h; + plane_state->crtc_w = crtc_w; + plane_state->src_x = src_x; + plane_state->src_y = src_y; + plane_state->src_h = src_h; + plane_state->src_w = src_w; + + ret = drm_atomic_nonblocking_commit(state); +fail: + drm_atomic_state_put(state); + return ret; } static void armada_ovl_plane_destroy(struct drm_plane *plane) @@ -388,25 +308,6 @@ static void armada_ovl_plane_destroy(struct drm_plane *plane) kfree(dplane); } -static int armada_ovl_plane_set_property(struct drm_plane *plane, - struct drm_property *property, uint64_t val) -{ - struct drm_plane_state *state; - int ret; - - state = plane->funcs->atomic_duplicate_state(plane); - if (!state) - return -ENOMEM; - - ret = plane->funcs->atomic_set_property(plane, state, property, val); - if (ret) { - plane->funcs->atomic_destroy_state(plane, state); - return ret; - } - - return armada_overlay_commit(plane, state); -} - static void armada_overlay_reset(struct drm_plane *plane) { struct armada_overlay_state *state; @@ -510,9 +411,6 @@ static int armada_overlay_set_property(struct drm_plane *plane, drm_to_overlay_state(state)->contrast = val; } else if (property == priv->saturation_prop) { drm_to_overlay_state(state)->saturation = val; - } else if (property == plane->color_encoding_property) { - /* transitional only */ - state->color_encoding = val; } else { return -EINVAL; } @@ -572,10 +470,9 @@ static int armada_overlay_get_property(struct drm_plane *plane, } static const struct drm_plane_funcs armada_ovl_plane_funcs = { - .update_plane = armada_ovl_plane_update, - .disable_plane = drm_plane_helper_disable, + .update_plane = armada_overlay_plane_update, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = armada_ovl_plane_destroy, - .set_property = armada_ovl_plane_set_property, .reset = armada_overlay_reset, .atomic_duplicate_state = armada_overlay_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, @@ -670,11 +567,6 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) return ret; } - dplane->works[0].plane = &dplane->base.base; - dplane->works[0].fn = armada_ovl_plane_work; - dplane->works[1].plane = &dplane->base.base; - dplane->works[1].fn = armada_ovl_plane_work; - drm_plane_helper_add(&dplane->base.base, &armada_overlay_plane_helper_funcs); |