mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 06:57:57 +00:00
4f8b350be0
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
163 lines
5.2 KiB
Diff
163 lines
5.2 KiB
Diff
From a9a47ea599c12d29526138cd6e48f6c9eac19358 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 366/806] 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,
|