From b721bcc62759ae7a2d9730d1121974702be96d7c Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Tue, 26 Mar 2019 14:43:06 +0000
Subject: [PATCH] gpu: vc4-fkms: Switch to the newer mailbox frame
 buffer API.

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 | 109 +++++++++++++------------
 1 file changed, 57 insertions(+), 52 deletions(-)

--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
@@ -30,6 +30,25 @@
 #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_upd
 					    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_upd
 			 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_fun
 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_
 	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:
