summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/gma500/gma_display.c
diff options
context:
space:
mode:
authorPaul Kocialkowski <paul.kocialkowski@bootlin.com>2019-11-06 10:44:00 +0100
committerPatrik Jakobsson <patrik.r.jakobsson@gmail.com>2019-11-07 10:16:31 +0100
commitf76c22ce8fbbd03394eb9e2cd8c490d9ad2a116c (patch)
tree68d7d42f8a51cc5d2c83b4dbd54fe1960b225411 /drivers/gpu/drm/gma500/gma_display.c
parentb20e9afb38d0b7f407bde1f9a4f5080626666482 (diff)
downloadlinux-f76c22ce8fbbd03394eb9e2cd8c490d9ad2a116c.tar.bz2
drm/gma500: Add page flip support on psb/cdv
Legacy (non-atomic) page flip support is added to the driver by using the mode_set_base CRTC function, that allows configuring a new framebuffer for display. Since the function requires the primary plane's fb to be set already, this is done prior to calling the function in the page flip helper and reverted if the flip fails. The vblank interrupt handler is also refactored to support passing an event. The PIPE_TE_STATUS bit is also considered to indicate vblank on medfield only, as explained in psb_enable_vblank. It was tested by running weston on both poulsbo and cedartrail. Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com> Reviewed-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191106094400.445834-3-paul.kocialkowski@bootlin.com
Diffstat (limited to 'drivers/gpu/drm/gma500/gma_display.c')
-rw-r--r--drivers/gpu/drm/gma500/gma_display.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
index bc07ae2a9a1d..17f136985d21 100644
--- a/drivers/gpu/drm/gma500/gma_display.c
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -503,6 +503,52 @@ void gma_crtc_destroy(struct drm_crtc *crtc)
kfree(gma_crtc);
}
+int gma_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct drm_framebuffer *current_fb = crtc->primary->fb;
+ struct drm_framebuffer *old_fb = crtc->primary->old_fb;
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+ int ret;
+
+ if (!crtc_funcs->mode_set_base)
+ return -EINVAL;
+
+ /* Using mode_set_base requires the new fb to be set already. */
+ crtc->primary->fb = fb;
+
+ if (event) {
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ gma_crtc->page_flip_event = event;
+
+ /* Call this locked if we want an event at vblank interrupt. */
+ ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
+ if (ret) {
+ gma_crtc->page_flip_event = NULL;
+ drm_crtc_vblank_put(crtc);
+ }
+
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ } else {
+ ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
+ }
+
+ /* Restore previous fb in case of failure. */
+ if (ret)
+ crtc->primary->fb = current_fb;
+
+ return ret;
+}
+
int gma_crtc_set_config(struct drm_mode_set *set,
struct drm_modeset_acquire_ctx *ctx)
{