Skip to content

Commit e91617d

Browse files
committed
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 <[email protected]>
1 parent 78eb13b commit e91617d

File tree

2 files changed

+104
-9
lines changed

2 files changed

+104
-9
lines changed

drivers/video/fbdev/bcm2708_fb.c

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ struct bcm2708_fb {
9898
struct bcm2708_fb_stats stats;
9999
unsigned long fb_bus_address;
100100
struct { u32 base, length; } gpu;
101+
102+
bool disable_arm_alloc;
103+
unsigned int image_size;
104+
dma_addr_t dma_addr;
105+
void *cpuaddr;
101106
};
102107

103108
#define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
@@ -285,21 +290,102 @@ static int bcm2708_fb_set_par(struct fb_info *info)
285290
.tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
286291
.base = 0,
287292
.screen_size = 0,
288-
.tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
293+
.tag6 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH, 4, 0 },
289294
.pitch = 0,
290295
};
291-
int ret;
296+
int ret, image_size;
297+
292298

293299
print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
294300
info->var.xres, info->var.yres, info->var.xres_virtual,
295301
info->var.yres_virtual, (int)info->screen_size,
296302
info->var.bits_per_pixel);
297303

298-
ret = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo));
304+
/* Try allocating our own buffer. We can specify all the parameters */
305+
image_size = ((info->var.xres * info->var.yres) *
306+
info->var.bits_per_pixel) >> 3;
307+
308+
if (!fb->disable_arm_alloc &&
309+
(image_size != fb->image_size || !fb->dma_addr)) {
310+
if (fb->dma_addr) {
311+
dma_free_coherent(info->device, fb->image_size,
312+
fb->cpuaddr, fb->dma_addr);
313+
fb->image_size = 0;
314+
fb->cpuaddr = NULL;
315+
fb->dma_addr = 0;
316+
}
317+
318+
fb->cpuaddr = dma_alloc_coherent(info->device, image_size,
319+
&fb->dma_addr, GFP_ATOMIC);
320+
321+
if (!fb->cpuaddr) {
322+
fb->dma_addr = 0;
323+
fb->disable_arm_alloc = true;
324+
} else {
325+
fb->image_size = image_size;
326+
}
327+
}
328+
329+
if (fb->cpuaddr) {
330+
fbinfo.base = fb->dma_addr;
331+
fbinfo.screen_size = image_size;
332+
fbinfo.pitch = (info->var.xres * info->var.bits_per_pixel) >> 3;
333+
334+
ret = rpi_firmware_property_list(fb->fw, &fbinfo,
335+
sizeof(fbinfo));
336+
if (ret || fbinfo.base != fb->dma_addr) {
337+
/* Firmware either failed, or assigned a different base
338+
* address (ie it doesn't support being passed an FB
339+
* allocation).
340+
* Destroy the allocation, and don't try again.
341+
*/
342+
dma_free_coherent(info->device, fb->image_size,
343+
fb->cpuaddr, fb->dma_addr);
344+
fb->image_size = 0;
345+
fb->cpuaddr = NULL;
346+
fb->dma_addr = 0;
347+
fb->disable_arm_alloc = true;
348+
}
349+
} else {
350+
/* Our allocation failed - drop into the old scheme of
351+
* allocation by the VPU.
352+
*/
353+
ret = -ENOMEM;
354+
}
355+
299356
if (ret) {
300-
dev_err(info->device,
301-
"Failed to allocate GPU framebuffer (%d)\n", ret);
302-
return ret;
357+
/* Old scheme */
358+
const struct fb_alloc_tags fbinfo_old = {
359+
.tag1 = { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT,
360+
8, 0, },
361+
.xres = info->var.xres,
362+
.yres = info->var.yres,
363+
.tag2 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT,
364+
8, 0, },
365+
.xres_virtual = info->var.xres_virtual,
366+
.yres_virtual = info->var.yres_virtual,
367+
.tag3 = { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0 },
368+
.bpp = info->var.bits_per_pixel,
369+
.tag4 = { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET,
370+
8, 0 },
371+
.xoffset = info->var.xoffset,
372+
.yoffset = info->var.yoffset,
373+
.tag5 = { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0 },
374+
.base = 0,
375+
.screen_size = 0,
376+
.tag6 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0 },
377+
.pitch = 0,
378+
};
379+
fbinfo = fbinfo_old;
380+
381+
ret = rpi_firmware_property_list(fb->fw, &fbinfo,
382+
sizeof(fbinfo));
383+
if (ret) {
384+
dev_err(info->device,
385+
"Failed to allocate GPU framebuffer (%d)\n",
386+
ret);
387+
return ret;
388+
}
303389
}
304390

305391
if (info->var.bits_per_pixel <= 8)
@@ -314,9 +400,17 @@ static int bcm2708_fb_set_par(struct fb_info *info)
314400
fb->fb.fix.smem_start = fbinfo.base;
315401
fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual;
316402
fb->fb.screen_size = fbinfo.screen_size;
317-
if (fb->fb.screen_base)
318-
iounmap(fb->fb.screen_base);
319-
fb->fb.screen_base = ioremap_wc(fbinfo.base, fb->fb.screen_size);
403+
404+
if (!fb->dma_addr) {
405+
if (fb->fb.screen_base)
406+
iounmap(fb->fb.screen_base);
407+
408+
fb->fb.screen_base = ioremap_wc(fbinfo.base,
409+
fb->fb.screen_size);
410+
} else {
411+
fb->fb.screen_base = fb->cpuaddr;
412+
}
413+
320414
if (!fb->fb.screen_base) {
321415
/* the console may currently be locked */
322416
console_trylock();

include/soc/bcm2835/raspberrypi-firmware.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ enum rpi_firmware_property_tag {
128128
RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
129129
RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
130130
RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
131+
RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
131132
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
132133
RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
133134
RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,

0 commit comments

Comments
 (0)