/* Copyright (C) 2012, Aaron Lindsay This file is part of Aedrix. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include struct bcm2835_config { volatile uint32 width; volatile uint32 height; volatile uint32 vwidth; volatile uint32 vheight; volatile uint32 pitch; volatile uint32 color_depth; volatile uint32 xoffset; volatile uint32 yoffset; volatile uint32 fb_base_addr; volatile uint32 size; }; #define MAILBOX_BUFFER_SIZE (32*4*2) #define FB_WIDTH 1024 #define FB_HEIGHT 768 struct fbdev bcm2835_fb_device; int bcm2835_videocore_init(struct fb *f, unsigned int color_depth) { struct bcm2835_config *cfg; uint32 result; void *mailbox_buffer_orig, *mailbox_buffer; if (!(mailbox_buffer_orig = kmalloc(MAILBOX_BUFFER_SIZE))) { return -1; } /* Round mailbox buffer to multiple of 0x10 because the low 4 bits of the mailbox are used to send the channel, and therefore can't hold the low 4 bits of the address */ if ((uint32)mailbox_buffer_orig & 0xf) mailbox_buffer = (void *)((uint32)mailbox_buffer_orig & ~0xf) + 0x10; else mailbox_buffer = mailbox_buffer_orig; cfg = (struct bcm2835_config *)mailbox_buffer; cfg->width = FB_WIDTH; cfg->height = FB_HEIGHT; cfg->vwidth = FB_WIDTH; cfg->vheight = FB_HEIGHT; cfg->pitch = 0; cfg->color_depth = color_depth; cfg->xoffset = 0; cfg->yoffset = 0; cfg->fb_base_addr = 0; cfg->size = 0; mailbox_write(MBOX_FB, (uint32)cfg); result = mailbox_read(MBOX_FB); if (result) { print("Error: did not request a proper framebuffer\n"); return -1; } if (!cfg->fb_base_addr) { int i; print("BCM2835 VideoCore returned success from framebuffer " "setup mailbox call, but framebuffer address is " "not yet available. Waiting...\n"); for (i = 0; i < 1<<30 && !cfg->fb_base_addr; i++); if (!cfg->fb_base_addr) { print("Error: VideoCore did not provide framebuffer " "base address.\n"); return -1; } print("VideoCore provided framebuffer base address after %d loops.\n", i); } f->device = &bcm2835_fb_device; f->device->fbaddr = (void*)cfg->fb_base_addr; f->width = cfg->width; f->device->pixelwidth = cfg->width; f->height = cfg->height; f->device->pixelheight = cfg->height; f->color_depth = color_depth; f->device->color_depth = color_depth; return 0; }