From: Zhao Junwang <zhjw...@gmail.com>

-register driver's own primary plane
-use drm_crtc_init_with_planes instead drm_crtc_init

-the new atomic_infrastructure needs ->mode_set_nofb callback

Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
Cc: Gerd Hoffmann <kraxel at redhat.com>
Cc: Matthew Garrett <mjg59 at coreos.com>
Cc: Dave Airlie <airlied at redhat.com>
Signed-off-by: Zhao Junwang <zhjwpku at gmail.com>
---
 drivers/gpu/drm/cirrus/cirrus_drv.c  |    1 -
 drivers/gpu/drm/cirrus/cirrus_drv.h  |    3 +-
 drivers/gpu/drm/cirrus/cirrus_main.c |    2 +-
 drivers/gpu/drm/cirrus/cirrus_mode.c |  201 +++++++++++++++++++++-------------
 4 files changed, 129 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c 
b/drivers/gpu/drm/cirrus/cirrus_drv.c
index 08bd176..80f1cd2 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -40,7 +40,6 @@ static const struct pci_device_id pciidlist[] = {
        {0,}
 };

-
 static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev)
 {
        struct apertures_struct *ap;
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h 
b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 7050615..bd1ff51 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -135,8 +135,9 @@ struct cirrus_device {
        resource_size_t                 rmmio_size;
        void __iomem                    *rmmio;

-       struct cirrus_mc                        mc;
+       struct cirrus_mc                mc;
        struct cirrus_mode_info         mode_info;
+       struct drm_plane                primary;

        int                             num_crtc;
        int fb_mtrr;
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c 
b/drivers/gpu/drm/cirrus/cirrus_main.c
index e4b9766..d95de34 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -308,10 +308,10 @@ cirrus_dumb_mmap_offset(struct drm_file *file,

        drm_gem_object_unreference(obj);
        ret = 0;
+
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
        return ret;
-
 }

 bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int 
height,
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c 
b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 61385f2..7a7c874 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -27,6 +27,10 @@
 #define PALETTE_INDEX 0x8
 #define PALETTE_DATA 0x9

+static const uint32_t cirrus_primary_formats[] = {
+       DRM_FORMAT_RGB888,
+};
+
 /*
  * This file contains setup code for the CRTC.
  */
@@ -126,77 +130,11 @@ static void cirrus_set_start_address(struct drm_crtc 
*crtc, unsigned offset)
        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);
-               ret = cirrus_bo_reserve(bo, false);
-               if (ret)
-                       return ret;
-               cirrus_bo_push_sysram(bo);
-               cirrus_bo_unreserve(bo);
-       }
-
-       cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
-       obj = cirrus_fb->obj;
-       bo = gem_to_cirrus_bo(obj);
-
-       ret = cirrus_bo_reserve(bo, false);
-       if (ret)
-               return ret;
-
-       ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
-       if (ret) {
-               cirrus_bo_unreserve(bo);
-               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_bo_unreserve(bo);
-
-       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
- */
-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_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct cirrus_device *cdev = dev->dev_private;
+       struct drm_display_mode *mode = &crtc->mode;
        int hsyncstart, hsyncend, htotal, hdispend;
        int vtotal, vdispend;
        int tmp;
@@ -286,7 +224,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
                hdr = 0xc5;
                break;
        default:
-               return -1;
+               return;
        }

        WREG_SEQ(0x7, sr07);
@@ -308,11 +246,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
        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;
 }

 /*
@@ -373,8 +309,9 @@ static const struct drm_crtc_funcs cirrus_crtc_funcs = {
 static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
        .dpms = cirrus_crtc_dpms,
        .mode_fixup = cirrus_crtc_mode_fixup,
-       .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_crtc_mode_set_nofb,
        .prepare = cirrus_crtc_prepare,
        .commit = cirrus_crtc_commit,
        .load_lut = cirrus_crtc_load_lut,
@@ -394,7 +331,8 @@ static void cirrus_crtc_init(struct drm_device *dev)
        if (cirrus_crtc == NULL)
                return;

-       drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs);
+       drm_crtc_init_with_planes(dev, &cirrus_crtc->base, &cdev->primary,
+                                 NULL, &cirrus_crtc_funcs);

        drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
        cdev->mode_info.crtc = cirrus_crtc;
@@ -408,6 +346,119 @@ static void cirrus_crtc_init(struct drm_device *dev)
        drm_crtc_helper_add(&cirrus_crtc->base, &cirrus_helper_funcs);
 }

+static int cirrus_plane_prepare_fb(struct drm_plane *plane,
+                               struct drm_framebuffer *fb,
+                               const struct drm_plane_state *new_state)
+{
+       struct cirrus_device *cdev =
+               container_of(plane, struct cirrus_device, primary);
+       struct cirrus_framebuffer *cirrus_fb;
+       struct drm_gem_object *obj;
+       struct cirrus_bo *bo;
+       int ret;
+
+       cirrus_fb = to_cirrus_framebuffer(fb);
+       obj = cirrus_fb->obj;
+       bo = gem_to_cirrus_bo(obj);
+
+       ret = cirrus_bo_reserve(bo, false);
+       if (ret)
+               return ret;
+
+       ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+       if (ret) {
+               cirrus_bo_unreserve(bo);
+               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_bo_unreserve(bo);
+
+       return 0;
+}
+
+static void cirrus_plane_cleanup_fb(struct drm_plane *plane,
+                               struct drm_framebuffer *old_fb,
+                               const struct drm_plane_state *old_state)
+{
+       struct cirrus_framebuffer *cirrus_fb;
+       struct drm_gem_object *obj;
+       struct cirrus_bo *bo;
+
+       cirrus_fb = to_cirrus_framebuffer(old_fb);
+       obj = cirrus_fb->obj;
+       bo = gem_to_cirrus_bo(obj);
+
+       cirrus_bo_reserve(bo, false);
+       cirrus_bo_push_sysram(bo);
+       cirrus_bo_unreserve(bo);
+}
+
+static int cirrus_plane_atomic_check(struct drm_plane *plane,
+                               struct drm_plane_state *plane_state)
+{
+       return 0;
+}
+
+static void cirrus_plane_atomic_update(struct drm_plane *plane,
+                               struct drm_plane_state *old_state)
+{
+       struct cirrus_framebuffer *cirrus_fb;
+       struct drm_gem_object *obj;
+       struct cirrus_bo *bo;
+       u64 gpu_addr;
+
+       cirrus_fb = to_cirrus_framebuffer(plane->state->fb);
+       obj = cirrus_fb->obj;
+       bo = gem_to_cirrus_bo(obj);
+       gpu_addr = bo->bo.offset;
+
+       cirrus_set_start_address(plane->state->crtc, (u32)gpu_addr);
+}
+
+static void cirrus_plane_atomic_disable(struct drm_plane *plane,
+                               struct drm_plane_state *old_state)
+{
+}
+
+static const struct drm_plane_funcs cirrus_plane_funcs = {
+       .update_plane = drm_plane_helper_update,
+       .disable_plane = drm_plane_helper_disable,
+};
+
+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_update = cirrus_plane_atomic_update,
+       .atomic_disable = cirrus_plane_atomic_disable,
+};
+
+static void cirrus_plane_init(struct drm_device *dev)
+{
+       struct cirrus_device *cirrus = dev->dev_private;
+       struct drm_plane *primary = &cirrus->primary;
+       int r;
+
+       r = drm_universal_plane_init(dev, primary, 0,
+                                    &cirrus_plane_funcs,
+                                    cirrus_primary_formats,
+                                    ARRAY_SIZE(cirrus_primary_formats),
+                                    DRM_PLANE_TYPE_PRIMARY);
+
+       if (r) {
+               DRM_DEBUG_KMS("Failed to init primary plane.\n");
+               return;
+       }
+
+       drm_plane_helper_add(primary, &cirrus_plane_helper_funcs);
+}
+
 /** Sets the color ramps on behalf of fbcon */
 void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                              u16 blue, int regno)
@@ -430,7 +481,6 @@ void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 
*red, u16 *green,
        *blue = cirrus_crtc->lut_b[regno];
 }

-
 static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder,
                                      const struct drm_display_mode *mode,
                                      struct drm_display_mode *adjusted_mode)
@@ -583,6 +633,7 @@ int cirrus_modeset_init(struct cirrus_device *cdev)
        /* don't prefer a shadow on virt GPU */
        cdev->dev->mode_config.prefer_shadow = 0;

+       cirrus_plane_init(cdev->dev);
        cirrus_crtc_init(cdev->dev);

        encoder = cirrus_encoder_init(cdev->dev);
-- 
1.7.10.4


Reply via email to