openwrt/target/linux/brcm2708/patches-4.19/950-0369-video-bcm2708_fb-Try-allocating-on-the-ARM-and-passi.patch
Álvaro Fernández Rojas 19226502bf brcm2708: update to latest patches from the RPi foundation
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2019-08-02 18:51:32 +02:00

163 lines
5.2 KiB
Diff

From 2f1aba45a3100491bc06f5ce8b9d1e49a5bc261d Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 27 Feb 2019 17:30:33 +0000
Subject: [PATCH 369/725] video: bcm2708_fb: Try allocating on the ARM and
passing to VPU
Currently the VPU allocates the contiguous buffer for the
framebuffer.
Try an alternate path first where we use dma_alloc_coherent
and pass the buffer to the VPU. Should the VPU firmware not
support that path, then free the buffer and revert to the
old behaviour of using the VPU allocation.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
---
drivers/video/fbdev/bcm2708_fb.c | 102 ++++++++++++++++++---
include/soc/bcm2835/raspberrypi-firmware.h | 1 +
2 files changed, 91 insertions(+), 12 deletions(-)
--- a/drivers/video/fbdev/bcm2708_fb.c
+++ b/drivers/video/fbdev/bcm2708_fb.c
@@ -98,6 +98,11 @@ struct bcm2708_fb {
struct bcm2708_fb_stats stats;
unsigned long fb_bus_address;
struct { u32 base, length; } gpu;
+
+ bool disable_arm_alloc;
+ unsigned int image_size;
+ dma_addr_t dma_addr;
+ void *cpuaddr;
};
#define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
@@ -283,23 +288,88 @@ static int bcm2708_fb_set_par(struct fb_
.xoffset = info->var.xoffset,
.yoffset = info->var.yoffset,
.tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
- .base = 0,
- .screen_size = 0,
- .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
- .pitch = 0,
+ /* base and screen_size will be initialised later */
+ .tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
+ /* pitch will be initialised later */
};
- int ret;
+ int ret, image_size;
+
print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
info->var.xres, info->var.yres, info->var.xres_virtual,
info->var.yres_virtual, (int)info->screen_size,
info->var.bits_per_pixel);
- ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
+ /* Try allocating our own buffer. We can specify all the parameters */
+ image_size = ((info->var.xres * info->var.yres) *
+ info->var.bits_per_pixel) >> 3;
+
+ if (!fb->disable_arm_alloc &&
+ (image_size != fb->image_size || !fb->dma_addr)) {
+ if (fb->dma_addr) {
+ dma_free_coherent(info->device, fb->image_size,
+ fb->cpuaddr, fb->dma_addr);
+ fb->image_size = 0;
+ fb->cpuaddr = NULL;
+ fb->dma_addr = 0;
+ }
+
+ fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
+ &fb->dma_addr, GFP_KERNEL);
+
+ if (!fb->cpuaddr) {
+ fb->dma_addr = 0;
+ fb->disable_arm_alloc = true;
+ } else {
+ fb->image_size = image_size;
+ }
+ }
+
+ if (fb->cpuaddr) {
+ fbinfo.base = fb->dma_addr;
+ fbinfo.screen_size = image_size;
+ fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
+
+ ret = rpi_firmware_property_list(fb->fw, &fbinfo,
+ sizeof(fbinfo));
+ if (ret || fbinfo.base != fb->dma_addr) {
+ /* Firmware either failed, or assigned a different base
+ * address (ie it doesn't support being passed an FB
+ * allocation).
+ * Destroy the allocation, and don't try again.
+ */
+ dma_free_coherent(info->device, fb->image_size,
+ fb->cpuaddr, fb->dma_addr);
+ fb->image_size = 0;
+ fb->cpuaddr = NULL;
+ fb->dma_addr = 0;
+ fb->disable_arm_alloc = true;
+ }
+ } else {
+ /* Our allocation failed - drop into the old scheme of
+ * allocation by the VPU.
+ */
+ ret = -ENOMEM;
+ }
+
if (ret) {
- dev_err(info->device,
- "Failed to allocate GPU framebuffer (%d)\n", ret);
- return ret;
+ /* Old scheme:
+ * - FRAMEBUFFER_ALLOCATE passes 0 for base and screen_size.
+ * - GET_PITCH instead of SET_PITCH.
+ */
+ fbinfo.base = 0;
+ fbinfo.screen_size = 0;
+ fbinfo.tag6.tag = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH;
+ fbinfo.pitch = 0;
+
+ ret = rpi_firmware_property_list(fb->fw, &fbinfo,
+ sizeof(fbinfo));
+ if (ret) {
+ dev_err(info->device,
+ "Failed to allocate GPU framebuffer (%d)\n",
+ ret);
+ return ret;
+ }
}
if (info->var.bits_per_pixel <= 8)
@@ -314,9 +384,17 @@ static int bcm2708_fb_set_par(struct fb_
fb->fb.fix.smem_start = fbinfo.base;
fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
fb->fb.screen_size = fbinfo.screen_size;
- if (fb->fb.screen_base)
- iounmap(fb->fb.screen_base);
- fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
+
+ if (!fb->dma_addr) {
+ if (fb->fb.screen_base)
+ iounmap(fb->fb.screen_base);
+
+ fb->fb.screen_base = ioremap_wc(fbinfo.base,
+ fb->fb.screen_size);
+ } else {
+ fb->fb.screen_base = fb->cpuaddr;
+ }
+
if (!fb->fb.screen_base) {
/* the console may currently be locked */
console_trylock();
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -128,6 +128,7 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,