From e4d111a55e8f1d9b49e67dc98d9d2cdf418d9221 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 7 Sep 2021 16:46:30 +0200 Subject: Add working framebuffer request Resources: - https://jsandler18.github.io/extra/prop-channel.html - https://jsandler18.github.io/extra/mailbox.html - https://github.com/bztsrc/raspi3-tutorial/tree/master/09_framebuffer - https://www.youtube.com/watch?v=hSJWbmiQfck --- src/common.h | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/main.c | 5 +-- src/ppu.c | 54 ++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 src/ppu.c diff --git a/src/common.h b/src/common.h index a6af346..0bd365a 100644 --- a/src/common.h +++ b/src/common.h @@ -60,11 +60,9 @@ static inline void gpio_pin_set_func(u8 pin, GpioFunc func) { u8 start = (pin * 3) % 30; u8 reg = pin / 10; - u32 selector = GPIO->func_select[reg]; selector &= ~(7 << start); selector |= (func << start); - GPIO->func_select[reg] = selector; } @@ -144,4 +142,107 @@ uart_puts(char *s) { } } +static inline void +uart_hex(unsigned int d) { + unsigned int n; + uart_puts("0x"); + for(int c = 28; c >= 0; c -= 4) { + n = (d>>c) & 0xF; + n += n> 9 ? 0x37 : 0x30; + uart_putc(n); + } +} + +// +// VideoCore Mailboxes. +// + +typedef struct MboxTagHeader { + u32 id; + u32 buf_size; + u32 code; +} MboxTagHeader; + +typedef struct MboxScreenTag { + MboxTagHeader header; + u32 width; + u32 height; +} MboxScreenTag; + +typedef struct MboxDepthTag { + MboxTagHeader header; + u32 depth; +} MboxDepthTag; + +typedef struct MboxFramebufferTag { + MboxTagHeader header; + u32 fb_addr; + u32 fb_size; +} MboxFramebufferTag; + +typedef struct MboxFramebufferRequest { + u32 buf_size; + u32 code; + MboxScreenTag screen_tag; + MboxScreenTag virtual_screen_tag; + MboxDepthTag depth_tag; + MboxFramebufferTag framebuffer_tag; + u32 end_tag; + u8 padding[8]; +} MboxFramebufferRequest; + +typedef struct MailboxRegs { + vu32 read; + vu32 reserved[5]; + vu32 status; + vu32 config; + vu32 write; +} MailboxRegs; + +#define MBOX ((MailboxRegs *)(MEM_BASE + 0x0000B880)) + +typedef enum MboxChannels { + MBOX_CH_POWER = 0, + MBOX_CH_FB = 1, + MBOX_CH_VUART = 2, + MBOX_CH_VCHIQ = 3, + MBOX_CH_LEDS = 4, + MBOX_CH_BTNS = 5, + MBOX_CH_TOUCH = 6, + MBOX_CH_COUNT = 7, + MBOX_CH_PROP = 8, +} MboxChannels; + +// Property channel response type. +#define MBOX_REQUEST 0 +#define MBOX_RESPONSE_OK 0x80000000 +#define MBOX_RESPONSE_ERR 0x80000001 + +// Mailbox status codes. +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +static inline void +mb_write(u8 channel, void *data) { + while(MBOX->status & MBOX_FULL); + MBOX->write = ((uintptr_t)data & ~0xF) | (channel & 0xF); +} + +static inline u32 +mb_read(u8 channel) { + while(true) { + while(MBOX->status & MBOX_EMPTY); + u32 data = MBOX->read; + if ((u8)(data & 0xF) == channel) { + return data & 0xFFFFFFF0; + } + } +} + +static inline int +mb_call(unsigned char ch, void *msg) { + mb_write(ch, msg); + return mb_read(ch); +} + #endif // COMMON_RPIBM_H diff --git a/src/main.c b/src/main.c index aac605b..22723c0 100644 --- a/src/main.c +++ b/src/main.c @@ -1,13 +1,14 @@ #include "common.h" +#include "ppu.c" void main(void) { // Initialize uart. uart_init(); - uart_puts("Hello World!\n"); + ppu_init(); - // Echo input to standard output. while(1) { + // Echo input to standard output. uart_putc(uart_getc()); } } diff --git a/src/ppu.c b/src/ppu.c new file mode 100644 index 0000000..99574d7 --- /dev/null +++ b/src/ppu.c @@ -0,0 +1,54 @@ +#include "common.h" + +static u32 *framebuffer = 0; + +void +ppu_init(void) { + static MboxFramebufferRequest fb_request = { + .buf_size = 96, + .code = MBOX_REQUEST, + .screen_tag = { + .header = { + .id = 0x48003, + .buf_size = 8, + }, + .width = 1024, + .height = 1024, + }, + .virtual_screen_tag = { + .header = { + .id = 0x48004, + .buf_size = 8, + }, + .width = 1024, + .height = 1024, + }, + .depth_tag = { + .header = { + .id = 0x48005, + .buf_size = 4, + }, + .depth = 32, + }, + .framebuffer_tag = { + .header = { + .id = 0x40001, + .buf_size = 8, + }, + .fb_addr = 0, + .fb_size = 0, + } + }; + + if (mb_call(MBOX_CH_PROP, &fb_request) + && fb_request.depth_tag.depth == 32 + && fb_request.framebuffer_tag.fb_addr != 0) { + fb_request.framebuffer_tag.fb_addr &= 0x3FFFFFFF; + framebuffer = (u32*)((uintptr_t)fb_request.framebuffer_tag.fb_addr); + for (size_t i = 0; i < 1024 * 100; i++) { + framebuffer[i] = 0xffaa22; // 0xBBGGRR + } + } else { + uart_puts("Unable initialize framebuffer\n"); + } +} -- cgit v1.2.1