1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-11-05 11:17:12 +02:00
iris/boot-programs/lcd.ccp

188 lines
5.4 KiB
Plaintext
Raw Normal View History

2009-06-10 22:42:01 +03:00
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
2009-06-24 01:47:13 +03:00
// boot-programs/lcd.ccp: Display driver.
2009-06-10 22:42:01 +03:00
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
2009-06-10 23:54:12 +03:00
#include "devices.hh"
2009-06-22 18:48:05 +03:00
#define ARCH
#include "arch.hh"
2009-06-10 22:42:01 +03:00
2009-07-21 13:17:52 +03:00
__asm__ volatile (".globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"")
// I'm too lazy to do this right. The address of charset is really the address of the array.
extern unsigned charset
2009-07-23 13:06:32 +03:00
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
2009-07-20 01:23:45 +03:00
2009-07-21 13:17:52 +03:00
enum types:
LCD_EOF_CB = 32
2009-07-23 13:06:32 +03:00
LCD_LOG
2009-07-21 13:17:52 +03:00
2009-07-20 01:23:45 +03:00
// For now, support only 16 bpp.
// Screen is 800x480 tft.
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
#define frame_size (v * h * Bpp)
struct Descriptor:
unsigned next
unsigned frame
unsigned id
unsigned cmd
static void reset (unsigned physical_descriptor):
2009-06-10 22:42:01 +03:00
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
2009-07-05 11:52:44 +03:00
LCD_VSYNC = vs
LCD_HSYNC = hs
LCD_DAV = (vs << 16) | (vs + v)
LCD_DAH = (hs << 16) | (hs + h)
LCD_VAT = ((hs + h) << 16) | (vs + v)
#define MODE_TFT_GEN 0
#define VSYNC_N (1 << 8)
2009-07-20 01:23:45 +03:00
LCD_CFG = MODE_TFT_GEN | VSYNC_N
2009-07-05 11:52:44 +03:00
cpm_stop_lcd ()
2009-06-10 22:42:01 +03:00
2009-07-05 11:52:44 +03:00
unsigned pixclock = fps * (hs + h) * (vs + v)
2009-07-20 01:23:45 +03:00
unsigned pllout = cpm_get_pllout ()
2009-07-05 11:52:44 +03:00
CPM_CFCR2 = pllout / pixclock - 1
unsigned val = pllout / (pixclock * 4) - 1
2009-07-20 01:23:45 +03:00
assert (pllout / (val + 1) <= 150000000)
assert (val <= 0xf)
2009-07-05 11:52:44 +03:00
cpm_set_lcdclk_div (val)
CPM_CFCR |= CPM_CFCR_UPE
cpm_start_lcd ()
2009-06-10 22:42:01 +03:00
2009-07-20 01:23:45 +03:00
LCD_DA0 = physical_descriptor
2009-07-05 11:52:44 +03:00
lcd_set_ena ()
lcd_enable_eof_intr ()
2009-06-10 22:42:01 +03:00
2009-07-23 13:06:32 +03:00
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
if ch < 32 || ch > 126:
ch = 127
ch -= 32
unsigned char *c = &((unsigned char *)&charset)[ch * 6]
2009-07-21 13:17:52 +03:00
unsigned lookup[2] = { bg, fg }
for unsigned k = 0; k < 6; ++k:
for unsigned r = 0; r < 8; ++r:
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[c[k] & (1 << r) ? 1 : 0]
static unsigned log_x = 1, log_y = 1
static void inc_logx ():
if ++log_x >= 800 / 6:
log_x = 1
if ++log_y >= 480 / 8:
log_y = 1
2009-07-23 13:06:32 +03:00
static void log_char (unsigned ch):
switch ch:
case '\n':
while log_x < 800 / 6:
putchar (log_x++, log_y, ' ')
inc_logx ()
break
default:
putchar (log_x, log_y, ch)
inc_logx ()
static void log_str (char const *str):
while *str:
log_char (*str++)
static void log_num (unsigned n):
char const *encode = "0123456789abcdef"
log_char ('[')
for unsigned i = 0; i < 8; ++i:
2009-07-24 15:25:53 +03:00
log_char (encode[(n >> (4 * (7 - i))) & 0xf])
2009-07-23 13:06:32 +03:00
log_char (']')
static void log_msg (Message *msg):
log_str ("prot:")
log_num (msg->protected_data)
log_str ("data:")
for unsigned i = 0; i < 4; ++i:
log_num (msg->data[i])
log_str ("cap:")
for unsigned i = 0; i < 4; ++i:
log_num (msg->cap[i])
log_char ('\n')
2009-07-21 13:17:52 +03:00
2009-06-10 22:42:01 +03:00
int main ():
2009-06-10 23:54:12 +03:00
map_lcd ()
map_cpm ()
2009-06-10 22:42:01 +03:00
2009-07-23 13:06:32 +03:00
Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
2009-07-20 01:23:45 +03:00
unsigned physical = alloc_range (__my_memory, pages)
assert (physical)
for unsigned i = 0; i < pages; ++i:
memory_create_page (6, __my_memory)
alloc_physical (6, physical + i * PAGE_SIZE, 0, 1)
memory_map (__my_memory, 6, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE, 1)
2009-07-20 01:23:45 +03:00
for unsigned y = 0; y < 480; ++y:
unsigned g = (y << 6) / 480
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
for unsigned x = 0; x < 800; ++x:
unsigned r = (x << 5) / 800
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
if r != olr:
olr = r
r = 0x1f
unsigned oyb = b
if y > 0:
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
if b != ob || b != oyb:
ob = b
b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
memory_mapping (6, __my_memory, &descriptor)
unsigned physical_descriptor = page_physical_address (cap_copy (6)) + ((unsigned)&descriptor & ~PAGE_MASK)
2009-07-23 13:06:32 +03:00
descriptor.next = physical_descriptor
descriptor.frame = physical
descriptor.id = 0xdeadbeef
descriptor.cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
unsigned dptr = (unsigned)&descriptor
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
2009-07-20 01:23:45 +03:00
reset (physical_descriptor)
2009-07-21 13:17:52 +03:00
Capability eof_cb = 0
receiver_create_capability (6, __my_receiver, LCD_EOF_CB)
invoke_11 (__my_parent, cap_copy (6), INIT_SET_LCD)
2009-06-22 17:13:00 +03:00
receiver_create_capability (15, __my_receiver, LCD_LOG)
__asm__ volatile ("li $a0, 1\nli $a1, 15\nbreak" ::: "a0", "a1", "memory")
2009-07-23 13:06:32 +03:00
2009-06-10 22:42:01 +03:00
while true:
Message msg
wait (&msg, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE)
2009-07-23 13:06:32 +03:00
//log_msg (&msg)
2009-06-10 22:42:01 +03:00
switch msg.protected_data:
2009-07-05 11:52:44 +03:00
case IRQ_LCD:
2009-07-20 01:23:45 +03:00
lcd_clr_eof ()
2009-07-21 13:17:52 +03:00
if eof_cb:
2009-07-23 13:06:32 +03:00
register_interrupt (IRQ_LCD)
2009-07-21 13:17:52 +03:00
invoke_00 (eof_cb)
2009-06-10 22:42:01 +03:00
break
2009-07-21 13:17:52 +03:00
case LCD_EOF_CB:
eof_cb = msg.cap[0]
2009-07-23 13:06:32 +03:00
if eof_cb:
register_interrupt (IRQ_LCD)
break
case LCD_LOG:
log_char (msg.data[0])
2009-06-10 22:42:01 +03:00
break