aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-09-07 16:46:30 +0200
committerBad Diode <bd@badd10de.dev>2021-09-07 16:46:30 +0200
commite4d111a55e8f1d9b49e67dc98d9d2cdf418d9221 (patch)
treef7d551fb922d6bde5d27b006e413dc0bf59afab0
parent11a95bd16da3ba212ebbd64300c9136cee555bc1 (diff)
downloaduxnrpi-e4d111a55e8f1d9b49e67dc98d9d2cdf418d9221.tar.gz
uxnrpi-e4d111a55e8f1d9b49e67dc98d9d2cdf418d9221.zip
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
-rw-r--r--src/common.h105
-rw-r--r--src/main.c5
-rw-r--r--src/ppu.c54
3 files changed, 160 insertions, 4 deletions
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
60gpio_pin_set_func(u8 pin, GpioFunc func) { 60gpio_pin_set_func(u8 pin, GpioFunc func) {
61 u8 start = (pin * 3) % 30; 61 u8 start = (pin * 3) % 30;
62 u8 reg = pin / 10; 62 u8 reg = pin / 10;
63
64 u32 selector = GPIO->func_select[reg]; 63 u32 selector = GPIO->func_select[reg];
65 selector &= ~(7 << start); 64 selector &= ~(7 << start);
66 selector |= (func << start); 65 selector |= (func << start);
67
68 GPIO->func_select[reg] = selector; 66 GPIO->func_select[reg] = selector;
69} 67}
70 68
@@ -144,4 +142,107 @@ uart_puts(char *s) {
144 } 142 }
145} 143}
146 144
145static inline void
146uart_hex(unsigned int d) {
147 unsigned int n;
148 uart_puts("0x");
149 for(int c = 28; c >= 0; c -= 4) {
150 n = (d>>c) & 0xF;
151 n += n> 9 ? 0x37 : 0x30;
152 uart_putc(n);
153 }
154}
155
156//
157// VideoCore Mailboxes.
158//
159
160typedef struct MboxTagHeader {
161 u32 id;
162 u32 buf_size;
163 u32 code;
164} MboxTagHeader;
165
166typedef struct MboxScreenTag {
167 MboxTagHeader header;
168 u32 width;
169 u32 height;
170} MboxScreenTag;
171
172typedef struct MboxDepthTag {
173 MboxTagHeader header;
174 u32 depth;
175} MboxDepthTag;
176
177typedef struct MboxFramebufferTag {
178 MboxTagHeader header;
179 u32 fb_addr;
180 u32 fb_size;
181} MboxFramebufferTag;
182
183typedef struct MboxFramebufferRequest {
184 u32 buf_size;
185 u32 code;
186 MboxScreenTag screen_tag;
187 MboxScreenTag virtual_screen_tag;
188 MboxDepthTag depth_tag;
189 MboxFramebufferTag framebuffer_tag;
190 u32 end_tag;
191 u8 padding[8];
192} MboxFramebufferRequest;
193
194typedef struct MailboxRegs {
195 vu32 read;
196 vu32 reserved[5];
197 vu32 status;
198 vu32 config;
199 vu32 write;
200} MailboxRegs;
201
202#define MBOX ((MailboxRegs *)(MEM_BASE + 0x0000B880))
203
204typedef enum MboxChannels {
205 MBOX_CH_POWER = 0,
206 MBOX_CH_FB = 1,
207 MBOX_CH_VUART = 2,
208 MBOX_CH_VCHIQ = 3,
209 MBOX_CH_LEDS = 4,
210 MBOX_CH_BTNS = 5,
211 MBOX_CH_TOUCH = 6,
212 MBOX_CH_COUNT = 7,
213 MBOX_CH_PROP = 8,
214} MboxChannels;
215
216// Property channel response type.
217#define MBOX_REQUEST 0
218#define MBOX_RESPONSE_OK 0x80000000
219#define MBOX_RESPONSE_ERR 0x80000001
220
221// Mailbox status codes.
222#define MBOX_FULL 0x80000000
223#define MBOX_EMPTY 0x40000000
224
225static inline void
226mb_write(u8 channel, void *data) {
227 while(MBOX->status & MBOX_FULL);
228 MBOX->write = ((uintptr_t)data & ~0xF) | (channel & 0xF);
229}
230
231static inline u32
232mb_read(u8 channel) {
233 while(true) {
234 while(MBOX->status & MBOX_EMPTY);
235 u32 data = MBOX->read;
236 if ((u8)(data & 0xF) == channel) {
237 return data & 0xFFFFFFF0;
238 }
239 }
240}
241
242static inline int
243mb_call(unsigned char ch, void *msg) {
244 mb_write(ch, msg);
245 return mb_read(ch);
246}
247
147#endif // COMMON_RPIBM_H 248#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 @@
1#include "common.h" 1#include "common.h"
2#include "ppu.c"
2 3
3void main(void) { 4void main(void) {
4 // Initialize uart. 5 // Initialize uart.
5 uart_init(); 6 uart_init();
6 7
7 uart_puts("Hello World!\n"); 8 ppu_init();
8 9
9 // Echo input to standard output.
10 while(1) { 10 while(1) {
11 // Echo input to standard output.
11 uart_putc(uart_getc()); 12 uart_putc(uart_getc());
12 } 13 }
13} 14}
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 @@
1#include "common.h"
2
3static u32 *framebuffer = 0;
4
5void
6ppu_init(void) {
7 static MboxFramebufferRequest fb_request = {
8 .buf_size = 96,
9 .code = MBOX_REQUEST,
10 .screen_tag = {
11 .header = {
12 .id = 0x48003,
13 .buf_size = 8,
14 },
15 .width = 1024,
16 .height = 1024,
17 },
18 .virtual_screen_tag = {
19 .header = {
20 .id = 0x48004,
21 .buf_size = 8,
22 },
23 .width = 1024,
24 .height = 1024,
25 },
26 .depth_tag = {
27 .header = {
28 .id = 0x48005,
29 .buf_size = 4,
30 },
31 .depth = 32,
32 },
33 .framebuffer_tag = {
34 .header = {
35 .id = 0x40001,
36 .buf_size = 8,
37 },
38 .fb_addr = 0,
39 .fb_size = 0,
40 }
41 };
42
43 if (mb_call(MBOX_CH_PROP, &fb_request)
44 && fb_request.depth_tag.depth == 32
45 && fb_request.framebuffer_tag.fb_addr != 0) {
46 fb_request.framebuffer_tag.fb_addr &= 0x3FFFFFFF;
47 framebuffer = (u32*)((uintptr_t)fb_request.framebuffer_tag.fb_addr);
48 for (size_t i = 0; i < 1024 * 100; i++) {
49 framebuffer[i] = 0xffaa22; // 0xBBGGRR
50 }
51 } else {
52 uart_puts("Unable initialize framebuffer\n");
53 }
54}