gpu: vc4-fkms: Switch to the newer mailbox frame buffer API.
authorDave Stevenson <dave.stevenson@raspberrypi.org>
Tue, 26 Mar 2019 14:43:06 +0000 (14:43 +0000)
committerpopcornmix <popcornmix@gmail.com>
Wed, 1 Jul 2020 15:32:58 +0000 (16:32 +0100)
The old mailbox FB API was ideally deprecated but still used by
the FKMS driver.
Update to the newer API.

NB This needs current firmware that accepts ARM allocated buffers
through the newer API.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
drivers/gpu/drm/vc4/vc4_firmware_kms.c

index eb5eb67..512036c 100644 (file)
 #include "vc4_regs.h"
 #include <soc/bcm2835/raspberrypi-firmware.h>
 
+struct fb_alloc_tags {
+       struct rpi_firmware_property_tag_header tag1;
+       u32 xres, yres;
+       struct rpi_firmware_property_tag_header tag2;
+       u32 xres_virtual, yres_virtual;
+       struct rpi_firmware_property_tag_header tag3;
+       u32 bpp;
+       struct rpi_firmware_property_tag_header tag4;
+       u32 xoffset, yoffset;
+       struct rpi_firmware_property_tag_header tag5;
+       u32 base, screen_size;
+       struct rpi_firmware_property_tag_header tag6;
+       u32 pitch;
+       struct rpi_firmware_property_tag_header tag7;
+       u32 alpha_mode;
+       struct rpi_firmware_property_tag_header tag8;
+       u32 layer;
+};
+
 /* The firmware delivers a vblank interrupt to us through the SMI
  * hardware, which has only this one register.
  */
@@ -123,45 +142,39 @@ static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
                                            struct drm_plane_state *old_state)
 {
        struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
-       struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
        struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
-       volatile struct fbinfo_s *fbinfo = vc4_plane->fbinfo;
+       u32 format = fb->format->format;
+       struct fb_alloc_tags fbinfo = {
+               .tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
+                         8, 0, },
+                       .xres = state->crtc_w,
+                       .yres = state->crtc_h,
+               .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
+                         8, 0, },
+                       .xres_virtual = state->crtc_w,
+                       .yres_virtual = state->crtc_h,
+               .tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
+                       .bpp = 32,
+               .tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0 },
+                       .xoffset = 0,
+                       .yoffset = 0,
+               .tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
+                       .base = bo->paddr + fb->offsets[0],
+                       .screen_size = state->crtc_w * state->crtc_h * 4,
+               .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
+                       .pitch = fb->pitches[0],
+               .tag7 = { RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE, 4, 0 },
+                       .alpha_mode = format == DRM_FORMAT_ARGB8888 ? 0 : 2,
+               .tag8 = { RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER, 4, 0 },
+                       .layer = -127,
+       };
        u32 bpp = 32;
        int ret;
 
-       fbinfo->xres = state->crtc_w;
-       fbinfo->yres = state->crtc_h;
-       fbinfo->xres_virtual = state->crtc_w;
-       fbinfo->yres_virtual = state->crtc_h;
-       fbinfo->bpp = bpp;
-       fbinfo->xoffset = state->crtc_x;
-       fbinfo->yoffset = state->crtc_y;
-       fbinfo->base = bo->paddr + fb->offsets[0];
-       fbinfo->pitch = fb->pitches[0];
-
        if (fb->modifier == DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)
-               fbinfo->bpp |= BIT(31);
-
-       /* A bug in the firmware makes it so that if the fb->base is
-        * set to nonzero, the configured pitch gets overwritten with
-        * the previous pitch.  So, to get the configured pitch
-        * recomputed, we have to make it allocate itself a new buffer
-        * in VC memory, first.
-        */
-       if (vc4_plane->pitch != fb->pitches[0]) {
-               u32 saved_base = fbinfo->base;
-               fbinfo->base = 0;
-
-               ret = rpi_firmware_transaction(vc4->firmware,
-                                              RPI_FIRMWARE_CHAN_FB,
-                                              vc4_plane->fbinfo_bus_addr);
-               fbinfo->base = saved_base;
-
-               vc4_plane->pitch = fbinfo->pitch;
-               WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]);
-       }
+               fbinfo.bpp |= BIT(31);
 
        DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%pad/%d\n",
                         plane->base.id, plane->name,
@@ -170,14 +183,13 @@ static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
                         bpp,
                         state->crtc_x,
                         state->crtc_y,
-                        &fbinfo->base,
+                        &fbinfo.base,
                         fb->pitches[0]);
 
-       ret = rpi_firmware_transaction(vc4->firmware,
-                                      RPI_FIRMWARE_CHAN_FB,
-                                      vc4_plane->fbinfo_bus_addr);
-       WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]);
-       WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[0]);
+       ret = rpi_firmware_property_list(vc4->firmware, &fbinfo,
+                                        sizeof(fbinfo));
+       WARN_ON_ONCE(fbinfo.pitch != fb->pitches[0]);
+       WARN_ON_ONCE(fbinfo.base != bo->paddr + fb->offsets[0]);
 
        /* If the CRTC is on (or going to be on) and we're enabled,
         * then unblank.  Otherwise, stay blank until CRTC enable.
@@ -333,10 +345,10 @@ static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = {
 static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
                                             enum drm_plane_type type)
 {
+       /* Primary and cursor planes only */
        struct drm_plane *plane = NULL;
        struct vc4_fkms_plane *vc4_plane;
-       u32 xrgb8888 = DRM_FORMAT_XRGB8888;
-       u32 argb8888 = DRM_FORMAT_ARGB8888;
+       u32 formats[] = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
        int ret = 0;
        bool primary = (type == DRM_PLANE_TYPE_PRIMARY);
        static const uint64_t modifiers[] = {
@@ -358,22 +370,15 @@ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
        plane = &vc4_plane->base;
        ret = drm_universal_plane_init(dev, plane, 0xff,
                                       &vc4_plane_funcs,
-                                      primary ? &xrgb8888 : &argb8888, 1,
-                                      modifiers,
+                                      formats, primary ? 2 : 1, modifiers,
                                       type, primary ? "primary" : "cursor");
 
-       if (type == DRM_PLANE_TYPE_PRIMARY) {
-               vc4_plane->fbinfo =
-                       dma_alloc_coherent(dev->dev,
-                                          sizeof(*vc4_plane->fbinfo),
-                                          &vc4_plane->fbinfo_bus_addr,
-                                          GFP_KERNEL);
-               memset(vc4_plane->fbinfo, 0, sizeof(*vc4_plane->fbinfo));
-
+       if (type == DRM_PLANE_TYPE_PRIMARY)
                drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs);
-       } else {
+       else
                drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs);
-       }
+
+       drm_plane_create_alpha_property(plane);
 
        return plane;
 fail: