diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.19/950-0366-video-bcm2708_fb-Try-allocating-on-the-ARM-and-passi.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.19/950-0366-video-bcm2708_fb-Try-allocating-on-the-ARM-and-passi.patch | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.19/950-0366-video-bcm2708_fb-Try-allocating-on-the-ARM-and-passi.patch b/target/linux/brcm2708/patches-4.19/950-0366-video-bcm2708_fb-Try-allocating-on-the-ARM-and-passi.patch new file mode 100644 index 0000000000..e60ef7d42a --- /dev/null +++ b/target/linux/brcm2708/patches-4.19/950-0366-video-bcm2708_fb-Try-allocating-on-the-ARM-and-passi.patch @@ -0,0 +1,162 @@ +From 35d5da12994c5b91a1d73cd1d03773e2a4252dc0 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/782] 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, |