From: Varad Gautam <varad.gau...@collabora.com>

split the driver to fit into atomic semantics, and switch to using
the atomic transition layer helpers for legacy modesetting.

Signed-off-by: Varad Gautam <varad.gau...@collabora.com>
---
 drivers/gpu/drm/cirrus/cirrus_drv.h  |   1 +
 drivers/gpu/drm/cirrus/cirrus_main.c |   3 +
 drivers/gpu/drm/cirrus/cirrus_mode.c | 350 ++++++++++++++++++++++-------------
 3 files changed, 227 insertions(+), 127 deletions(-)

diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h 
b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 29de4f0dbd01..d680815f23e6 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -168,6 +168,7 @@ struct cirrus_bo {
        struct drm_gem_object gem;
        struct ttm_place placements[3];
        int pin_count;
+       u64 gpu_addr;
 };
 #define gem_to_cirrus_bo(gobj) container_of((gobj), struct cirrus_bo, gem)
 
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c 
b/drivers/gpu/drm/cirrus/cirrus_main.c
index c92ccb00db62..7d0431bbc6e3 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -9,6 +9,7 @@
  *          Dave Airlie
  */
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 
 #include "cirrus_drv.h"
@@ -82,6 +83,8 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
 
 static const struct drm_mode_config_funcs cirrus_mode_funcs = {
        .fb_create = cirrus_user_framebuffer_create,
+       .atomic_check = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
 };
 
 /* Unmap the framebuffer from the core and release the memory */
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c 
b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 2994dd391850..eda3c4d18b37 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -15,6 +15,8 @@
  * Copyright 1999-2001 Jeff Garzik <jgar...@pobox.com>
  */
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
 
@@ -91,95 +93,20 @@ static void cirrus_crtc_dpms(struct drm_crtc *crtc, int 
mode)
        WREG_GFX(0xe, gr0e);
 }
 
-static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
-{
-       struct cirrus_device *cdev = crtc->dev->dev_private;
-       u32 addr;
-       u8 tmp;
-
-       addr = offset >> 2;
-       WREG_CRT(0x0c, (u8)((addr >> 8) & 0xff));
-       WREG_CRT(0x0d, (u8)(addr & 0xff));
-
-       WREG8(CRT_INDEX, 0x1b);
-       tmp = RREG8(CRT_DATA);
-       tmp &= 0xf2;
-       tmp |= (addr >> 16) & 0x01;
-       tmp |= (addr >> 15) & 0x0c;
-       WREG_CRT(0x1b, tmp);
-       WREG8(CRT_INDEX, 0x1d);
-       tmp = RREG8(CRT_DATA);
-       tmp &= 0x7f;
-       tmp |= (addr >> 12) & 0x80;
-       WREG_CRT(0x1d, tmp);
-}
-
-/* cirrus is different - we will force move buffers out of VRAM */
-static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
-                               struct drm_framebuffer *fb,
-                               int x, int y, int atomic)
-{
-       struct cirrus_device *cdev = crtc->dev->dev_private;
-       struct drm_gem_object *obj;
-       struct cirrus_framebuffer *cirrus_fb;
-       struct cirrus_bo *bo;
-       int ret;
-       u64 gpu_addr;
-
-       /* push the previous fb to system ram */
-       if (!atomic && fb) {
-               cirrus_fb = to_cirrus_framebuffer(fb);
-               obj = cirrus_fb->obj;
-               bo = gem_to_cirrus_bo(obj);
-               cirrus_bo_unpin(bo);
-               cirrus_bo_push_sysram(bo);
-       }
-
-       cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
-       obj = cirrus_fb->obj;
-       bo = gem_to_cirrus_bo(obj);
-
-       ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
-       if (ret)
-               return ret;
-
-       if (&cdev->mode_info.gfbdev->gfb == cirrus_fb) {
-               /* if pushing console in kmap it */
-               ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
-               if (ret)
-                       DRM_ERROR("failed to kmap fbcon\n");
-       }
-
-       cirrus_set_start_address(crtc, (u32)gpu_addr);
-       return 0;
-}
-
-static int cirrus_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-                            struct drm_framebuffer *old_fb)
-{
-       return cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
-}
-
 /*
- * The meat of this driver. The core passes us a mode and we have to program
- * it. The modesetting here is the bare minimum required to satisfy the qemu
- * emulation of this hardware, and running this against a real device is
- * likely to result in an inadequately programmed mode. We've already had
- * the opportunity to modify the mode, so whatever we receive here should
- * be something that can be correctly programmed and displayed
+ * The core passes us a mode and we have to program it. The modesetting here
+ * is the bare minimum required to satisfy the qemu emulation of this
+ * hardware, and running this against a real device is likely to result in
+ * an inadequately programmed mode.
  */
-static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
-                               struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode,
-                               int x, int y, struct drm_framebuffer *old_fb)
+static void cirrus_mode_set_nofb(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct cirrus_device *cdev = dev->dev_private;
-       const struct drm_framebuffer *fb = crtc->primary->fb;
+       struct drm_display_mode *mode = &crtc->mode;
        int hsyncstart, hsyncend, htotal, hdispend;
        int vtotal, vdispend;
        int tmp;
-       int sr07 = 0, hdr = 0;
 
        htotal = mode->htotal / 8;
        hsyncend = mode->hsync_end / 8;
@@ -244,54 +171,11 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
        /* Disable Hercules/CGA compatibility */
        WREG_CRT(VGA_CRTC_MODE, 0x03);
 
-       WREG8(SEQ_INDEX, 0x7);
-       sr07 = RREG8(SEQ_DATA);
-       sr07 &= 0xe0;
-       hdr = 0;
-       switch (fb->format->cpp[0] * 8) {
-       case 8:
-               sr07 |= 0x11;
-               break;
-       case 16:
-               sr07 |= 0x17;
-               hdr = 0xc1;
-               break;
-       case 24:
-               sr07 |= 0x15;
-               hdr = 0xc5;
-               break;
-       case 32:
-               sr07 |= 0x19;
-               hdr = 0xc5;
-               break;
-       default:
-               return -1;
-       }
-
-       WREG_SEQ(0x7, sr07);
-
-       /* Program the pitch */
-       tmp = fb->pitches[0] / 8;
-       WREG_CRT(VGA_CRTC_OFFSET, tmp);
-
-       /* Enable extended blanking and pitch bits, and enable full memory */
-       tmp = 0x22;
-       tmp |= (fb->pitches[0] >> 7) & 0x10;
-       tmp |= (fb->pitches[0] >> 6) & 0x40;
-       WREG_CRT(0x1b, tmp);
-
        /* Enable high-colour modes */
        WREG_GFX(VGA_GFX_MODE, 0x40);
 
        /* And set graphics mode */
        WREG_GFX(VGA_GFX_MISC, 0x01);
-
-       WREG_HDR(hdr);
-       cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
-
-       /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
-       outb(0x20, 0x3c0);
-       return 0;
 }
 
 /*
@@ -347,17 +231,34 @@ static const struct drm_crtc_funcs cirrus_crtc_funcs = {
        .gamma_set = cirrus_crtc_gamma_set,
        .set_config = drm_crtc_helper_set_config,
        .destroy = cirrus_crtc_destroy,
+       .reset = drm_atomic_helper_crtc_reset,
+       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
 static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
        .dpms = cirrus_crtc_dpms,
-       .mode_set = cirrus_crtc_mode_set,
-       .mode_set_base = cirrus_crtc_mode_set_base,
+       .mode_set = drm_helper_crtc_mode_set,
+       .mode_set_base = drm_helper_crtc_mode_set_base,
+       .mode_set_nofb = cirrus_mode_set_nofb,
        .prepare = cirrus_crtc_prepare,
        .commit = cirrus_crtc_commit,
        .load_lut = cirrus_crtc_load_lut,
 };
 
+static int cirrus_plane_update(struct drm_plane *plane,
+                              struct drm_crtc *crtc,
+                              struct drm_framebuffer *fb, int crtc_x,
+                              int crtc_y, unsigned int crtc_w,
+                              unsigned int crtc_h, uint32_t src_x,
+                              uint32_t src_y, uint32_t src_w, uint32_t src_h,
+                              struct drm_modeset_acquire_ctx *ctx)
+{
+       return drm_plane_helper_update(plane, crtc, fb,
+                                      crtc_x, crtc_y, crtc_w,
+                                      crtc_h, src_x, src_y, src_w, src_h);
+}
+
 static const uint32_t cirrus_plane_formats[] = {
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_ARGB8888,
@@ -366,12 +267,202 @@ static const uint32_t cirrus_plane_formats[] = {
 };
 
 static const struct drm_plane_funcs cirrus_plane_funcs = {
-       .update_plane   = drm_primary_helper_update,
+       .update_plane   = cirrus_plane_update,
        .disable_plane  = drm_primary_helper_disable,
        .destroy        = drm_primary_helper_destroy,
+       .reset  = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
 };
 
+static int cirrus_plane_prepare_fb(struct drm_plane *plane,
+                                  struct drm_plane_state *new_state)
+{
+       struct cirrus_device *cdev = plane->dev->dev_private;
+       struct drm_gem_object *obj;
+       struct cirrus_framebuffer *cirrus_fb;
+       struct cirrus_bo *bo;
+       int ret;
+
+       if (!new_state->fb)
+               return 0;
+
+       if (plane->old_fb) {
+               cirrus_fb = to_cirrus_framebuffer(plane->old_fb);
+               obj = cirrus_fb->obj;
+               bo = gem_to_cirrus_bo(obj);
+               cirrus_bo_push_sysram(bo);
+       }
+
+       cirrus_fb = to_cirrus_framebuffer(new_state->fb);
+       obj = cirrus_fb->obj;
+       bo = gem_to_cirrus_bo(obj);
+
+       ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &bo->gpu_addr);
+       if (ret)
+               return ret;
+
+       if (&cdev->mode_info.gfbdev->gfb == cirrus_fb) {
+               /* if pushing console in kmap it */
+               ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void cirrus_plane_cleanup_fb(struct drm_plane *plane,
+                                   struct drm_plane_state *old_state)
+{
+       struct drm_gem_object *obj;
+       struct cirrus_bo *bo;
+
+       if (!plane->state->fb) {
+               /* we never executed prepare_fb, so there's nothing to
+                * unpin.
+                */
+               return;
+       }
+
+       obj = to_cirrus_framebuffer(plane->state->fb)->obj;
+       bo = gem_to_cirrus_bo(obj);
+
+       cirrus_bo_unpin(bo);
+}
+
+static int cirrus_plane_atomic_check(struct drm_plane *plane,
+                                    struct drm_plane_state *state)
+{
+       struct cirrus_device *cdev = plane->dev->dev_private;
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_crtc *crtc = state->crtc ? state->crtc : plane->crtc;
+       struct drm_crtc_state *crtc_state;
+       struct drm_rect clip = { 0 };
+       int ret;
+
+       if (!crtc || !fb)
+               return 0;
+
+       if (!cirrus_check_framebuffer(cdev, fb->width, fb->height,
+                                     fb->format->cpp[0], fb->pitches[0]))
+               return -EINVAL;
+
+       crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+       if (!crtc_state)
+               return -EINVAL;
+
+       clip.x2 = crtc_state->adjusted_mode.hdisplay;
+       clip.y2 = crtc_state->adjusted_mode.vdisplay;
+
+       ret = drm_plane_helper_check_state(state, &clip,
+                                          DRM_PLANE_HELPER_NO_SCALING,
+                                          DRM_PLANE_HELPER_NO_SCALING,
+                                          false, true);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void cirrus_plane_atomic_disable(struct drm_plane *plane,
+                                       struct drm_plane_state *old_state)
+{
+       return;
+}
+
+static void cirrus_set_framebuffer_regs(struct drm_plane *plane)
+{
+       struct cirrus_device *cdev = plane->dev->dev_private;
+       struct drm_framebuffer *fb = plane->state->fb;
+       int sr07 = 0, hdr = 0, tmp;
+
+       WREG8(SEQ_INDEX, 0x7);
+       sr07 = RREG8(SEQ_DATA);
+       sr07 &= 0xe0;
+       switch (fb->format->cpp[0] * 8) {
+       case 8:
+               sr07 |= 0x11;
+               break;
+       case 16:
+               sr07 |= 0x17;
+               hdr = 0xc1;
+               break;
+       case 24:
+               sr07 |= 0x15;
+               hdr = 0xc5;
+               break;
+       case 32:
+               sr07 |= 0x19;
+               hdr = 0xc5;
+               break;
+       default:
+               /* Should never reach here. */
+               break;
+       }
+
+       WREG_SEQ(0x7, sr07);
+
+       /* Program the pitch */
+       tmp = fb->pitches[0] / 8;
+       WREG_CRT(VGA_CRTC_OFFSET, tmp);
+
+       /* Enable extended blanking and pitch bits, and enable full memory */
+       tmp = 0x22;
+       tmp |= (fb->pitches[0] >> 7) & 0x10;
+       tmp |= (fb->pitches[0] >> 6) & 0x40;
+       WREG_CRT(0x1b, tmp);
+
+       WREG_HDR(hdr);
+}
+
+static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
+{
+       struct cirrus_device *cdev = crtc->dev->dev_private;
+       u32 addr;
+       u8 tmp;
+
+       addr = offset >> 2;
+       WREG_CRT(0x0c, (u8)((addr >> 8) & 0xff));
+       WREG_CRT(0x0d, (u8)(addr & 0xff));
+
+       WREG8(CRT_INDEX, 0x1b);
+       tmp = RREG8(CRT_DATA);
+       tmp &= 0xf2;
+       tmp |= (addr >> 16) & 0x01;
+       tmp |= (addr >> 15) & 0x0c;
+       WREG_CRT(0x1b, tmp);
+       WREG8(CRT_INDEX, 0x1d);
+       tmp = RREG8(CRT_DATA);
+       tmp &= 0x7f;
+       tmp |= (addr >> 12) & 0x80;
+       WREG_CRT(0x1d, tmp);
+}
+
+static void cirrus_plane_atomic_update(struct drm_plane *plane,
+                                      struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = plane->state;
+       struct drm_gem_object *obj;
+       struct cirrus_bo *bo;
+
+       cirrus_set_framebuffer_regs(plane);
+
+       obj = to_cirrus_framebuffer(state->fb)->obj;
+       bo = gem_to_cirrus_bo(obj);
+       cirrus_set_start_address(state->crtc, (u32)bo->gpu_addr);
+
+       /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
+       outb(0x20, 0x3c0);
+}
+
+
 static const struct drm_plane_helper_funcs cirrus_plane_helper_funcs = {
+       .prepare_fb = cirrus_plane_prepare_fb,
+       .cleanup_fb = cirrus_plane_cleanup_fb,
+       .atomic_check = cirrus_plane_atomic_check,
+       .atomic_disable = cirrus_plane_atomic_disable,
+       .atomic_update = cirrus_plane_atomic_update,
 };
 
 /* CRTC setup */
@@ -546,6 +637,9 @@ static const struct drm_connector_funcs 
cirrus_vga_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = cirrus_connector_destroy,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static struct drm_connector *cirrus_vga_init(struct drm_device *dev)
@@ -602,6 +696,8 @@ int cirrus_modeset_init(struct cirrus_device *cdev)
 
        drm_mode_connector_attach_encoder(connector, encoder);
 
+       drm_mode_config_reset(cdev->dev);
+
        ret = cirrus_fbdev_init(cdev);
        if (ret) {
                DRM_ERROR("cirrus_fbdev_init failed\n");
-- 
2.13.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to