devices -> drivers
This commit is contained in:
69
drivers/bcm2835_mailbox.c
Normal file
69
drivers/bcm2835_mailbox.c
Normal 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;
|
||||
}
|
94
drivers/bcm2835_videocore.c
Normal file
94
drivers/bcm2835_videocore.c
Normal 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 <drivers/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;
|
||||
}
|
20
drivers/kernel.mk
Normal file
20
drivers/kernel.mk
Normal file
@ -0,0 +1,20 @@
|
||||
DIRNAME := drivers
|
||||
SUBDIRS :=
|
||||
|
||||
include $(BASEDIR)/header.mk
|
||||
|
||||
OBJS_$(d)_$(CONFIG_VEXPRESS_A9) := \
|
||||
$(d)/pl011.o \
|
||||
$(d)/pl111.o
|
||||
|
||||
OBJS_$(d)_$(CONFIG_INTEGRATOR_CP) := \
|
||||
$(d)/pl110.o \
|
||||
|
||||
OBJS_$(d)_$(CONFIG_RPI) := \
|
||||
$(d)/pi_mini_uart.o \
|
||||
$(d)/bcm2835_mailbox.o \
|
||||
$(d)/bcm2835_videocore.o
|
||||
|
||||
KOBJS += $(OBJS_$(d)_y)
|
||||
|
||||
include $(BASEDIR)/footer.mk
|
105
drivers/pi_mini_uart.c
Normal file
105
drivers/pi_mini_uart.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
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>
|
||||
|
||||
#define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000)
|
||||
|
||||
/* Auxiliary IO registers (includes both mini-UART and SPI) */
|
||||
#define AUX_IRQ VC_MMU_IO_OFFSET(0x7E215000)
|
||||
#define AUX_ENABLES VC_MMU_IO_OFFSET(0x7E215004)
|
||||
#define AUX_MU_IO_REG VC_MMU_IO_OFFSET(0x7E215040)
|
||||
#define AUX_MU_IER_REG VC_MMU_IO_OFFSET(0x7E215044)
|
||||
#define AUX_MU_IIR_REG VC_MMU_IO_OFFSET(0x7E215048)
|
||||
#define AUX_MU_LCR_REG VC_MMU_IO_OFFSET(0x7E21504C)
|
||||
#define AUX_MU_MCR_REG VC_MMU_IO_OFFSET(0x7E215050)
|
||||
#define AUX_MU_LSR_REG VC_MMU_IO_OFFSET(0x7E215054)
|
||||
#define AUX_MU_MSR_REG VC_MMU_IO_OFFSET(0x7E215058)
|
||||
#define AUX_MU_SCRATCH VC_MMU_IO_OFFSET(0x7E21505C)
|
||||
#define AUX_MU_CNTL_REG VC_MMU_IO_OFFSET(0x7E215060)
|
||||
#define AUX_MU_STAT_REG VC_MMU_IO_OFFSET(0x7E215064)
|
||||
#define AUX_MU_BAUD_REG VC_MMU_IO_OFFSET(0x7E215068)
|
||||
#define AUX_SPI0_CNTL0_REG VC_MMU_IO_OFFSET(0x7E215080)
|
||||
#define AUX_SPI0_CNTL1_REG VC_MMU_IO_OFFSET(0x7E215084)
|
||||
#define AUX_SPI0_STAT_REG VC_MMU_IO_OFFSET(0x7E215088)
|
||||
#define AUX_SPI0_IO_REG VC_MMU_IO_OFFSET(0x7E215090)
|
||||
#define AUX_SPI0_PEEK_REG VC_MMU_IO_OFFSET(0x7E215094)
|
||||
#define AUX_SPI1_CNTL0_REG VC_MMU_IO_OFFSET(0x7E2150C0)
|
||||
#define AUX_SPI1_CNTL1_REG VC_MMU_IO_OFFSET(0x7E2150C4)
|
||||
#define AUX_SPI1_STAT_REG VC_MMU_IO_OFFSET(0x7E2150C8)
|
||||
#define AUX_SPI1_IO_REG VC_MMU_IO_OFFSET(0x7E2150D0)
|
||||
#define AUX_SPI1_PEEK_REG VC_MMU_IO_OFFSET(0x7E2150D4)
|
||||
|
||||
/* Constants for mini-UART operation */
|
||||
#define MINI_UART_TX_EMPTY 0x20
|
||||
|
||||
/* General GPIO pin registers */
|
||||
#define GPFSEL1 VC_MMU_IO_OFFSET(0x7E200004)
|
||||
#define GPSET0 VC_MMU_IO_OFFSET(0x7E20001C)
|
||||
#define GPCLR0 VC_MMU_IO_OFFSET(0x7E200028)
|
||||
#define GPPUD VC_MMU_IO_OFFSET(0x7E200094)
|
||||
#define GPPUDCLK0 VC_MMU_IO_OFFSET(0x7E200098)
|
||||
|
||||
void mini_uart_init() {
|
||||
uint32 aux_enables;
|
||||
uint32 gpfsel1;
|
||||
unsigned int i;
|
||||
|
||||
/* Enable the mini-UART */
|
||||
aux_enables = (*(uint32 *)AUX_ENABLES) & 0x7;
|
||||
*(uint32 *)AUX_ENABLES = aux_enables | 0x1;
|
||||
|
||||
//TODO are these all necessary?
|
||||
*(uint32 *)AUX_MU_IER_REG = 0; //disable interrupts
|
||||
*(uint32 *)AUX_MU_CNTL_REG = 0; //disable RX and TX
|
||||
*(uint32 *)AUX_MU_LCR_REG = 3; //set to 8-bit mode (though this only takes setting bit 0, no clue why bit 1 is set too)
|
||||
*(uint32 *)AUX_MU_MCR_REG = 0; //"If clear the UART1_RTS line is high If set the UART1_RTS line is low"
|
||||
*(uint32 *)AUX_MU_IER_REG = 0; //disable interrupts again?
|
||||
*(uint32 *)AUX_MU_IIR_REG = 0xC6; //why are we setting the interrupt status - this looks like a read-only register?
|
||||
//also, the manual says setting bits 2&3 simultaneously shouldn't be possible...
|
||||
|
||||
// baudrate = system_clock_freq / ( 8 * (baudrate_reg + 1))
|
||||
// baudrate_reg = system_clock_freq / baudrate / 8 - 1
|
||||
// baudrate_reg = 250000000 / 115200 / 8 - 1 = 270
|
||||
*(uint32 *)AUX_MU_BAUD_REG = 270;
|
||||
|
||||
//set the GPIO pin to the alternate function for this UART
|
||||
gpfsel1 = (*(uint32 *)GPFSEL1) & ~(7<<12); //get the GPIO Function Select 1 register, and keep all the bits except those that are for GPIO pin 14
|
||||
gpfsel1 |= 2<<12; // set to 010 (GPIO Pin 14 takes alternate function 5)
|
||||
*(uint32 *)GPFSEL1 = gpfsel1;
|
||||
|
||||
//Follow the procedure for change pull-up/pull-down status (see page 101 of the BCM2835 ARM Peripherals datasheet)
|
||||
*(uint32 *)GPPUD = 0; //disable pull-up/pull-down for those pins which receive a write to their bit in GPPUDCLK0/1
|
||||
for(i = 0; i < 150; i++) asm(""); //wait at least 150 cycles
|
||||
*(uint32 *)GPPUDCLK0 = 1<<14; //"Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify" (in our case, this is 14)
|
||||
for(i = 0; i < 150; i++) asm(""); //wait at least 150 cycles
|
||||
// *(uint32 *)GPPUD = 0; //remove the signal (shouldn't really be necessary since it was 0 anyway in our case)
|
||||
*(uint32 *)GPPUDCLK0 = 0; //clear the clock
|
||||
|
||||
*(uint32 *)AUX_MU_CNTL_REG = 2; //enable TX
|
||||
}
|
||||
|
||||
void mini_uart_putc(char c) {
|
||||
/* Wait until the serial buffer is empty */
|
||||
while (!(*(volatile uint32*)AUX_MU_LSR_REG & MINI_UART_TX_EMPTY));
|
||||
|
||||
/* When it's empty, write our character */
|
||||
*(volatile uint32*)AUX_MU_IO_REG = c;
|
||||
}
|
34
drivers/pl011.c
Normal file
34
drivers/pl011.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
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>
|
||||
|
||||
#define PL011_SERIAL_BASE 0x10009000
|
||||
#define PL011_SERIAL_FLAG_REGISTER 0x18
|
||||
#define PL011_SERIAL_BUFFER_FULL (1 << 5)
|
||||
|
||||
void pl011_putc(char c)
|
||||
{
|
||||
/* Wait until the serial buffer is empty */
|
||||
while (*(volatile uint32*)(PL011_SERIAL_BASE + PL011_SERIAL_FLAG_REGISTER) & (PL011_SERIAL_BUFFER_FULL));
|
||||
|
||||
/* When it's empty, put our character at the base */
|
||||
*(volatile uint32*)PL011_SERIAL_BASE = c;
|
||||
}
|
90
drivers/pl110.c
Normal file
90
drivers/pl110.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
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 <mm.h>
|
||||
#include <math.h>
|
||||
|
||||
#define PL110_CR_EN 0x001
|
||||
#define PL110_CR_PWR 0x800
|
||||
#define PL110_IOBASE 0xc0000000
|
||||
#define PL110_PALBASE (PL110_IOBASE + 0x200)
|
||||
|
||||
struct pl110_control {
|
||||
uint32 volatile timing0; //0
|
||||
uint32 volatile timing1; //4
|
||||
uint32 volatile timing2; //8
|
||||
uint32 volatile timing3; //c
|
||||
uint32 volatile upbase; //10
|
||||
uint32 volatile lpbase; //14
|
||||
uint32 volatile intrenable; //18
|
||||
uint32 volatile control; //1c
|
||||
};
|
||||
|
||||
struct fbdev pl110_fb_device;
|
||||
|
||||
int pl110_init(struct fb *f, unsigned int color_depth) {
|
||||
unsigned int width, height;
|
||||
unsigned int fb_size, power;
|
||||
struct pl110_control *plio = (struct pl110_control*)PL110_IOBASE;
|
||||
struct page *p;
|
||||
|
||||
/* 640x480 pixels */
|
||||
width = 640;
|
||||
height = 480;
|
||||
plio->timing0 = 0x3f1f3f9c;
|
||||
plio->timing1 = 0x080b61df;
|
||||
|
||||
/* Allocate memory for framebuffer */
|
||||
fb_size = width * height * (color_depth / 8);
|
||||
power = log(fb_size) - log(MM_PAGE_SIZE);
|
||||
if ((unsigned int)1<<power < fb_size)
|
||||
power++;
|
||||
p = mm_get_free_pages(power);
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
plio->upbase = (uint32)p->address;
|
||||
|
||||
if (color_depth == FB_COLOR_DEPTH_8) {
|
||||
plio->control = 0x1827;
|
||||
} else if (color_depth == FB_COLOR_DEPTH_16) {
|
||||
plio->control = 0x1829;
|
||||
} else if (color_depth == FB_COLOR_DEPTH_24) {
|
||||
plio->control = 0x182B;
|
||||
} else {
|
||||
//assume 16 if nothing else fit
|
||||
color_depth = 16;
|
||||
plio->control = 0x1829;
|
||||
}
|
||||
|
||||
f->device = &pl110_fb_device;
|
||||
f->device->fbaddr = (void*)plio->upbase;
|
||||
f->width = width;
|
||||
f->device->pixelwidth = width;
|
||||
f->height = height;
|
||||
f->device->pixelheight = height;
|
||||
|
||||
f->color_depth = color_depth;
|
||||
f->device->color_depth = color_depth;
|
||||
|
||||
return 0;
|
||||
}
|
89
drivers/pl111.c
Normal file
89
drivers/pl111.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
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 <mm.h>
|
||||
#include <math.h>
|
||||
|
||||
#define PL111_CR_EN 0x001
|
||||
#define PL111_CR_PWR 0x800
|
||||
#define PL111_IOBASE 0x10020000
|
||||
#define PL111_PALBASE (PL111_IOBASE + 0x200)
|
||||
|
||||
struct pl111_control {
|
||||
uint32 volatile timing0; //0
|
||||
uint32 volatile timing1; //4
|
||||
uint32 volatile timing2; //8
|
||||
uint32 volatile timing3; //c
|
||||
uint32 volatile upbase; //10
|
||||
uint32 volatile lpbase; //14
|
||||
uint32 volatile control; //18
|
||||
};
|
||||
|
||||
struct fbdev pl111_fb_device;
|
||||
|
||||
int pl111_init(struct fb *f, unsigned int color_depth) {
|
||||
unsigned int width, height;
|
||||
unsigned int fb_size, power;
|
||||
struct pl111_control *plio = (struct pl111_control*)PL111_IOBASE;
|
||||
struct page *p;
|
||||
|
||||
/* 640x480 pixels */
|
||||
width = 640;
|
||||
height = 480;
|
||||
plio->timing0 = 0x3f1f3f9c;
|
||||
plio->timing1 = 0x080b61df;
|
||||
|
||||
/* Allocate memory for framebuffer */
|
||||
fb_size = width * height * (color_depth / 8);
|
||||
power = log(fb_size) - log(MM_PAGE_SIZE);
|
||||
if ((unsigned int)1<<power < fb_size)
|
||||
power++;
|
||||
p = mm_get_free_pages(power);
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
plio->upbase = (uint32)p->address;
|
||||
|
||||
if (color_depth == FB_COLOR_DEPTH_8) {
|
||||
plio->control = 0x1827;
|
||||
} else if (color_depth == FB_COLOR_DEPTH_16) {
|
||||
plio->control = 0x1829;
|
||||
} else if (color_depth == FB_COLOR_DEPTH_24) {
|
||||
plio->control = 0x182B;
|
||||
} else {
|
||||
//assume 16 if nothing else fit
|
||||
color_depth = 16;
|
||||
plio->control = 0x1829;
|
||||
}
|
||||
|
||||
f->device = &pl111_fb_device;
|
||||
f->device->fbaddr = (void*)plio->upbase;
|
||||
f->width = width;
|
||||
f->device->pixelwidth = width;
|
||||
f->height = height;
|
||||
f->device->pixelheight = height;
|
||||
|
||||
f->color_depth = color_depth;
|
||||
f->device->color_depth = color_depth;
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user