From 93bf62580a68533dc8252b9a2a055c02f34ecb67 Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Thu, 24 Mar 2022 09:38:08 -0700 Subject: Modularized --- kernel/graphics/lfb.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++ kernel/graphics/mbox.c | 37 +++++++++ 2 files changed, 255 insertions(+) create mode 100644 kernel/graphics/lfb.c create mode 100644 kernel/graphics/mbox.c (limited to 'kernel/graphics') diff --git a/kernel/graphics/lfb.c b/kernel/graphics/lfb.c new file mode 100644 index 0000000..8c41b1c --- /dev/null +++ b/kernel/graphics/lfb.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include + +unsigned char *lfb; /* raw frame buffer address */ + +#define SCR_WIDTH 1920 +#define SCR_HEIGHT 1080 + +/** + * Set screen resolution + */ +void lfb_init(void) +{ + mbox[0] = 35*4; + mbox[1] = MBOX_REQUEST; + + mbox[2] = 0x48003; //set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = SCR_WIDTH; //FrameBufferInfo.width + mbox[6] = SCR_HEIGHT; //FrameBufferInfo.height + + mbox[7] = 0x48004; //set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = SCR_WIDTH; //FrameBufferInfo.virtual_width + mbox[11] = SCR_HEIGHT; //FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; //set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; //FrameBufferInfo.x_offset + mbox[16] = 0; //FrameBufferInfo.y.offset + + mbox[17] = 0x48005; //set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; //FrameBufferInfo.depth + + mbox[21] = 0x48006; //set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; //RGB, not BGR preferably + + mbox[25] = 0x40001; //get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; //FrameBufferInfo.pointer + mbox[29] = 0; //FrameBufferInfo.size + + mbox[30] = 0x40008; //get pitch + mbox[31] = 4; + mbox[32] = 4; + mbox[33] = 0; //FrameBufferInfo.pitch + + mbox[34] = MBOX_TAG_LAST; + + //this might not return exactly what we asked for, could be + //the closest supported resolution instead + if(mbox_call(MBOX_CH_PROP) && mbox[20]==32 && mbox[28]!=0) { + mbox[28]&=0x3FFFFFFF; //convert GPU address to ARM address + gwidth=mbox[5]; //get actual physical width + gheight=mbox[6]; //get actual physical height + gpitch=mbox[33]; //get number of bytes per line + gisrgb=mbox[24]; //get the actual channel order + lfb=(void*)((unsigned long)mbox[28]); + } else { + uart_string("Unable to set screen resolution to 1024x768x32\n"); + } +} + +void clear_screen(void) +{ + unsigned char *ptr=lfb; + for(unsigned int y = 0; y < gheight; y++) { + for(unsigned int x = 0; x < gwidth; x++) { + *(unsigned int*)ptr = 0x000000; + ptr += 4; + } + } +} + +/** + * Show a picture + */ +void lfb_showpicture(void) +{ + clear_screen(); +#define FWIDTH 240 +#define FHEIGHT 80 + draw_cbox(SCR_WIDTH-FWIDTH, SCR_HEIGHT-FHEIGHT*2, FWIDTH, FHEIGHT, 0x0057b7); + draw_cbox(SCR_WIDTH-FWIDTH, SCR_HEIGHT-FHEIGHT, FWIDTH, FHEIGHT, 0xffd700); +} + +void draw_cpixel(unsigned int lx, unsigned int ly, unsigned int c) +{ + unsigned char* ptr = lfb; + ptr += (gpitch*ly+lx*4); + *((unsigned int*)ptr) = gisrgb ? (unsigned int)((c&0xFF)<<16 | (c&0xFF00) | (c&0xFF0000)>>16) : c; +} + +void draw_cbox(unsigned int lx, unsigned int ly, unsigned int dx, unsigned int dy, unsigned int c) +{ + unsigned char* ptr = lfb; + ptr += (gpitch*ly+lx*4); + for(unsigned int y = 0; y < dy; y++) { + for(unsigned int x = 0; x < dx; x++) { + *((unsigned int*)ptr) = gisrgb ? (unsigned int)((c&0xFF)<<16 | (c&0xFF00) | (c&0xFF0000)>>16) : c; + ptr += 4; + } + ptr += gpitch - dx*4; + } +} + +void draw_cbyte(unsigned int lx, unsigned int ly, unsigned char letter, unsigned int c) +{ + unsigned int x, y; + unsigned char* ptr = lfb; + ptr += (gpitch*ly*GLYPH_Y+lx*4*GLYPH_X); + unsigned char ltr = (letter & 0xF) + 0x30; + if (ltr > 0x39) { + ltr += 7; + } + for(y=0; y> ((GLYPH_X-1)-x)) & glyphs[y+GLYPH_Y*(ltr)]) { + *((unsigned int*)ptr) = gisrgb ? (unsigned int)((c&0xFF)<<16 | (c&0xFF00) | (c&0xFF0000)>>16) : c; + } else { + *((unsigned int*)ptr) = 0x000000; + } + ptr += 4; + } + ptr += gpitch - GLYPH_X*4; + } +} + +void draw_byte(unsigned int lx, unsigned int ly, unsigned char letter) +{ + draw_cbyte(lx, ly, letter, 0xFFFFFF); +} + +void draw_cletter(unsigned int lx, unsigned int ly, unsigned char letter, unsigned int c) +{ + unsigned int x, y; + unsigned char* ptr = lfb; + ptr += (gpitch*ly*GLYPH_Y+lx*4*GLYPH_X); + unsigned char ltr = letter & 0x7F; + for(y=0; y> ((GLYPH_X-1)-x)) & glyphs[y+GLYPH_Y*(ltr)]) { + *((unsigned int*)ptr) = gisrgb ? (unsigned int)((c&0xFF)<<16 | (c&0xFF00) | (c&0xFF0000)>>16) : c; + } else { + *((unsigned int*)ptr) = 0x000000; + } + ptr += 4; + } + ptr += gpitch - GLYPH_X*4; + } +} + +void draw_letter(unsigned int lx, unsigned int ly, unsigned char letter) +{ + draw_cletter(lx, ly, letter, 0xFFFFFF); +} + +void draw_cstring(unsigned int lx, unsigned int ly, char* s, unsigned int c) +{ + unsigned int x = lx % GG_MAX_X, y = ly % GG_MAX_Y; + unsigned int idx = 0; + while(s[idx] != 0) { + draw_cletter(x++, y, s[idx++], c); + if (x > GG_MAX_X) { + y += 1; + x = 0; + } + // CHECK Y EVENTUALLY + } +} + +void draw_string(unsigned int lx, unsigned int ly, char* s) +{ + draw_cstring(lx, ly, s, 0xFFFFFF); +} + +void draw_chex32(unsigned int lx, unsigned int ly, unsigned long val, unsigned int c) +{ + unsigned int x = lx % GG_MAX_X, y = ly % GG_MAX_Y; + for(unsigned int i = 0; i < GLYPH_X; i++) { + draw_cbyte(x++, y, 0xF & (val >> ((GLYPH_X-1)-i)*4), c); + if (x > GG_MAX_X) { + y += 1; + x = 0; + } + // CHECK Y EVENTUALLY + } +} + +void draw_hex32(unsigned int lx, unsigned int ly, unsigned long val) +{ + draw_chex32(lx, ly, val, 0xFFFFFF); +} + +unsigned long draw_cu10(unsigned int lx, unsigned int ly, unsigned long val, unsigned int c) +{ + string_t vals = u32_to_str(val); + unsigned long len = strlen(vals); + draw_cstring(lx, ly, vals, c); + return len; +} + +unsigned long draw_u10(unsigned int lx, unsigned int ly, unsigned long val) +{ + return draw_cu10(lx, ly, val, 0xFFFFFF); +} diff --git a/kernel/graphics/mbox.c b/kernel/graphics/mbox.c new file mode 100644 index 0000000..0dac497 --- /dev/null +++ b/kernel/graphics/mbox.c @@ -0,0 +1,37 @@ +#include + +/* mailbox message buffer */ +volatile unsigned int __attribute__((aligned(16))) mbox[36]; + +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +/** + * Make a mailbox call. Returns 0 on failure, non-zero on success + */ +int mbox_call(unsigned char ch) +{ + unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF)); + /* wait until we can write to the mailbox */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while(1) { + /* is there a response? */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if(r == *MBOX_READ) + /* is it a valid successful response? */ + return mbox[1]==MBOX_RESPONSE; + } + return 0; +} -- cgit v1.2.1