1
0

Add BCM2835 (Raspberry Pi) framebuffer and mailbox implementations

This commit is contained in:
Aaron Lindsay 2012-09-30 22:48:44 -04:00
parent 925192fca1
commit af22b6fe46
6 changed files with 237 additions and 6 deletions

69
devices/bcm2835_mailbox.c Normal file
View File

@ -0,0 +1,69 @@
/*
Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
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 <types.h>
/* Mailbox Memory-Mapped Registers */
#define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000)
#define MBOX0_READ VC_MMU_IO_OFFSET(0x7E00B880)
/* MBOX0_READ layout:
31-4 data The 28 bits of data sent to the CPU
3-0 channel The mailbox channel number from which the data originated */
#define MBOX0_PEEK VC_MMU_IO_OFFSET(0x7E00B890) //Read from the mailbox without removing data from it.
#define MBOX0_SENDER VC_MMU_IO_OFFSET(0x7E00B894) //Sender ID (bottom 2 bits only)
#define MBOX0_STATUS VC_MMU_IO_OFFSET(0x7E00B898)
/* MBOX0_STATUS layout:
31 full Set if the mailbox is full, and thus no more data can be written to it.
30 empty Set if the mailbox is empty, and thus no more data is available to be read from it.
29-0 unused? */
#define MBOX0_CONFIG VC_MMU_IO_OFFSET(0x7E00B89C)
#define MBOX0_WRITE VC_MMU_IO_OFFSET(0x7E00B8A0) //also MBOX1_READ?
/* MBOX0_WRITE layout:
31-4 data The 28 bits of data to be sent
3-0 channel The mailbox channel to send data to */
#define MBOX0_STATUS_FULL 0x80000000
#define MBOX0_STATUS_EMPTY 0x40000000
uint32 mailbox_read(uint32 channel) {
uint32 mbox_msg;
while (1) {
int i;
for (i = 0; *(volatile uint32 *)MBOX0_STATUS & MBOX0_STATUS_EMPTY; i++) {
if (i >= 1<<20)
return 0xFFFFFFFF;
}
mbox_msg = *(volatile uint32 *)MBOX0_READ;
if ((mbox_msg & 0xf) == channel)
return mbox_msg & ~0xf;
}
}
void mailbox_write(uint32 channel, uint32 data) {
channel &= 0xf;
data &= ~0xf;
while (*(volatile uint32 *)MBOX0_STATUS & MBOX0_STATUS_FULL);
*(volatile uint32 *)MBOX0_WRITE = channel | data;
}

View File

@ -0,0 +1,94 @@
/*
Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
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 <types.h>
#include <framebuffer.h>
#include <kmalloc.h>
#include <print.h>
#include <devices/bcm2835_mailbox.h>
struct bcm2835_config {
uint32 width;
uint32 height;
uint32 vwidth;
uint32 vheight;
uint32 pitch;
uint32 color_depth;
uint32 xoffset;
uint32 yoffset;
uint32 fb_base_addr;
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 || !cfg->fb_base_addr) {
print("Error: did not request a proper framebuffer\n");
return -1;
}
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;
}

View File

@ -6,7 +6,9 @@ include $(BASEDIR)/header.mk
OBJS_$(d) := $(d)/pl011.o \ OBJS_$(d) := $(d)/pl011.o \
$(d)/pl110.o \ $(d)/pl110.o \
$(d)/pl111.o \ $(d)/pl111.o \
$(d)/pi_mini_uart.o $(d)/pi_mini_uart.o \
$(d)/bcm2835_mailbox.o \
$(d)/bcm2835_videocore.o
KOBJS += $(OBJS_$(d)) KOBJS += $(OBJS_$(d))

View File

@ -0,0 +1,38 @@
/*
Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
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.
*/
#ifndef BCM2835_MAILBOX_H
#define BCM2835_MAILBOX_H
#include <types.h>
/* BCM2835 Mailbox Channels */
#define MBOX_PM 0 //Power management interface
#define MBOX_FB 1 //Framebuffer
#define MBOX_VUART 2 //Virtual UART
#define MBOX_YCHIQ 3 //VCHIQ interface
#define MBOX_LEDS 4 //LEDs interface
#define MBOX_BUTTONS 5 //Buttons interface
#define MBOX_TOUCHSCRN 6 //Touch screen interface
uint32 mailbox_read(uint32 channel);
void mailbox_write(uint32 channel, uint32 data);
#endif /* BCM2835_MAILBOX_H */

View File

@ -0,0 +1,28 @@
/*
Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
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 <framebuffer.h>
#ifndef BCM2835_VIDEOCORE_H
#define BCM2835_VIDEOCORE_H
int bcm2835_videocore_init(struct fb *f, unsigned int color_depth);
#endif /* BCM2835_VIDEOCORE_H */

View File

@ -25,7 +25,7 @@
#include <print.h> #include <print.h>
#include <devices/pi_mini_uart.h> #include <devices/pi_mini_uart.h>
#include <devices/pl111.h> #include <devices/bcm2835_videocore.h>
#include <framebuffer.h> #include <framebuffer.h>
#include <console.h> #include <console.h>
@ -33,10 +33,10 @@ struct fb myfb;
void video(void) { void video(void) {
unsigned int x, y; unsigned int x, y;
pl111_init(&myfb, 24); bcm2835_videocore_init(&myfb, 16);
x = 0, y = 0;
for (y=0; y<480; y++) for (y = 0; y < myfb.height; y++)
for (x=0; x<640; x++) for (x = 0; x < myfb.width; x++)
fb_write_pixel(&myfb, x, y, 0x3f, 0x0, 0x6f); fb_write_pixel(&myfb, x, y, 0x3f, 0x0, 0x6f);
console_init(&myfb); console_init(&myfb);