diff options
author | Bad Diode <bd@badd10de.dev> | 2021-09-13 18:37:26 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-09-13 18:37:26 +0200 |
commit | 162a1ee7f91aac21329d7acf290f9d350fb083bd (patch) | |
tree | 3db6e1393b6d6d9c9e439799dd1c9196319b5586 | |
parent | f7826ed2b13f5c7290ce6c73f554bae588d1ace1 (diff) | |
download | uxnrpi-162a1ee7f91aac21329d7acf290f9d350fb083bd.tar.gz uxnrpi-162a1ee7f91aac21329d7acf290f9d350fb083bd.zip |
Update FB initialization to use mbox instead of structs
The framebuffer initialization was breaking randomly, I suspect because
the memory access of the static fb_request was not 16 bit aligned. For
simplicity, I went back to the volatile mbox array implementation.
Additionally, now on fb_init the rgb order is requested to properly
adjust the palette on docolors.
-rw-r--r-- | src/common.h | 53 | ||||
-rw-r--r-- | src/main.c | 14 | ||||
-rw-r--r-- | src/ppu.c | 98 |
3 files changed, 72 insertions, 93 deletions
diff --git a/src/common.h b/src/common.h index ad3aad8..0057950 100644 --- a/src/common.h +++ b/src/common.h | |||
@@ -171,40 +171,6 @@ uart_hex(unsigned int d) { | |||
171 | // VideoCore Mailboxes. | 171 | // VideoCore Mailboxes. |
172 | // | 172 | // |
173 | 173 | ||
174 | typedef struct MboxTagHeader { | ||
175 | u32 id; | ||
176 | u32 buf_size; | ||
177 | u32 code; | ||
178 | } MboxTagHeader; | ||
179 | |||
180 | typedef struct MboxScreenTag { | ||
181 | MboxTagHeader header; | ||
182 | u32 width; | ||
183 | u32 height; | ||
184 | } MboxScreenTag; | ||
185 | |||
186 | typedef struct MboxDepthTag { | ||
187 | MboxTagHeader header; | ||
188 | u32 depth; | ||
189 | } MboxDepthTag; | ||
190 | |||
191 | typedef struct MboxFramebufferTag { | ||
192 | MboxTagHeader header; | ||
193 | u32 fb_addr; | ||
194 | u32 fb_size; | ||
195 | } MboxFramebufferTag; | ||
196 | |||
197 | typedef struct MboxFramebufferRequest { | ||
198 | u32 buf_size; | ||
199 | u32 code; | ||
200 | MboxScreenTag screen_tag; | ||
201 | MboxScreenTag virtual_screen_tag; | ||
202 | MboxDepthTag depth_tag; | ||
203 | MboxFramebufferTag framebuffer_tag; | ||
204 | u32 end_tag; | ||
205 | u8 padding[8]; | ||
206 | } MboxFramebufferRequest; | ||
207 | |||
208 | typedef struct MailboxRegs { | 174 | typedef struct MailboxRegs { |
209 | vu32 read; | 175 | vu32 read; |
210 | vu32 reserved[5]; | 176 | vu32 reserved[5]; |
@@ -236,10 +202,21 @@ typedef enum MboxChannels { | |||
236 | #define MBOX_FULL 0x80000000 | 202 | #define MBOX_FULL 0x80000000 |
237 | #define MBOX_EMPTY 0x40000000 | 203 | #define MBOX_EMPTY 0x40000000 |
238 | 204 | ||
205 | // Mailbox tags. | ||
206 | #define MBOX_TAG_SET_SCREEN 0x48003 | ||
207 | #define MBOX_TAG_SET_VSCREEN 0x48004 | ||
208 | #define MBOX_TAG_SET_DEPTH 0x48005 | ||
209 | #define MBOX_TAG_SET_RGB 0x48006 | ||
210 | #define MBOX_TAG_GET_FB 0x40001 | ||
211 | #define MBOX_TAG_END 0 | ||
212 | |||
213 | // Mailbox request buffer. Needs to be 16 bit aligned to avoid issues. | ||
214 | volatile u32 __attribute__((aligned(16))) mbox[64]; | ||
215 | |||
239 | static inline void | 216 | static inline void |
240 | mb_write(u8 channel, void *data) { | 217 | mb_write(u8 channel) { |
241 | while (MBOX->status & MBOX_FULL); | 218 | while (MBOX->status & MBOX_FULL); |
242 | MBOX->write = ((uintptr_t)data & ~0xF) | (channel & 0xF); | 219 | MBOX->write = ((uintptr_t)mbox & ~0xF) | (channel & 0xF); |
243 | } | 220 | } |
244 | 221 | ||
245 | static inline u32 | 222 | static inline u32 |
@@ -254,8 +231,8 @@ mb_read(u8 channel) { | |||
254 | } | 231 | } |
255 | 232 | ||
256 | static inline int | 233 | static inline int |
257 | mb_call(unsigned char ch, void *msg) { | 234 | mb_call(unsigned char ch) { |
258 | mb_write(ch, msg); | 235 | mb_write(ch); |
259 | return mb_read(ch); | 236 | return mb_read(ch); |
260 | } | 237 | } |
261 | 238 | ||
@@ -40,15 +40,11 @@ docolors(Device *d) { | |||
40 | u8 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; | 40 | u8 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; |
41 | u8 b = ((d->dat[0xc + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; | 41 | u8 b = ((d->dat[0xc + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; |
42 | 42 | ||
43 | // NOTE: This is a bit of a hack. We probably want to check the RGB byte | 43 | if (rgb_order) { |
44 | // order on the mailbox request. | 44 | palette[i] = (b << 16) | (g << 8) | r; |
45 | #if RPI_VERSION == 3 | 45 | } else { |
46 | palette[i] = (b << 16) | (g << 8) | r; | 46 | palette[i] = (r << 16) | (g << 8) | b; |
47 | #endif | 47 | } |
48 | |||
49 | #if RPI_VERSION == 4 | ||
50 | palette[i] = (r << 16) | (g << 8) | b; | ||
51 | #endif | ||
52 | } | 48 | } |
53 | for(size_t i = 4; i < 16; ++i) { | 49 | for(size_t i = 4; i < 16; ++i) { |
54 | palette[i] = palette[i / 4]; | 50 | palette[i] = palette[i / 4]; |
@@ -24,6 +24,7 @@ static u32 palette[16]; | |||
24 | static u8 pixels_buf[SCREEN_WIDTH * SCREEN_HEIGHT]; | 24 | static u8 pixels_buf[SCREEN_WIDTH * SCREEN_HEIGHT]; |
25 | static u8 dirty_lines[SCREEN_HEIGHT]; | 25 | static u8 dirty_lines[SCREEN_HEIGHT]; |
26 | static u8 reqdraw = 0; | 26 | static u8 reqdraw = 0; |
27 | static u32 rgb_order; | ||
27 | 28 | ||
28 | static Uint8 blending[5][16] = { | 29 | static Uint8 blending[5][16] = { |
29 | {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, | 30 | {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, |
@@ -84,57 +85,62 @@ redraw_screen(void) { | |||
84 | } | 85 | } |
85 | } | 86 | } |
86 | 87 | ||
88 | void | ||
89 | fb_init(void) { | ||
90 | mbox[0] = 25 * 4; | ||
91 | mbox[1] = MBOX_REQUEST; | ||
92 | |||
93 | // Screen request. | ||
94 | mbox[2] = MBOX_TAG_SET_SCREEN; | ||
95 | mbox[3] = 8; | ||
96 | mbox[4] = 0; | ||
97 | mbox[5] = SCREEN_WIDTH; | ||
98 | mbox[6] = SCREEN_HEIGHT; | ||
99 | |||
100 | // Virtual screen. | ||
101 | mbox[7] = MBOX_TAG_SET_VSCREEN; | ||
102 | mbox[8] = 8; | ||
103 | mbox[9] = 0; | ||
104 | mbox[10] = SCREEN_WIDTH; | ||
105 | mbox[11] = SCREEN_HEIGHT; | ||
106 | |||
107 | // Bit depth. | ||
108 | mbox[12] = MBOX_TAG_SET_DEPTH; | ||
109 | mbox[13] = 4; | ||
110 | mbox[14] = 0; | ||
111 | mbox[15] = 32; | ||
112 | |||
113 | // RGB order. | ||
114 | mbox[16] = MBOX_TAG_SET_RGB; | ||
115 | mbox[17] = 4; | ||
116 | mbox[18] = 0; | ||
117 | mbox[19] = 1; | ||
118 | |||
119 | // Framebuffer request. | ||
120 | mbox[20] = MBOX_TAG_GET_FB; | ||
121 | mbox[21] = 8; | ||
122 | mbox[22] = 0; | ||
123 | mbox[23] = 0; | ||
124 | mbox[24] = 0; | ||
125 | |||
126 | // End tag. | ||
127 | mbox[25] = MBOX_TAG_END; | ||
128 | |||
129 | if (mb_call(MBOX_CH_PROP) && mbox[15] == 32 && mbox[23] != 0) { | ||
130 | framebuffer = (u32*)((uintptr_t)(mbox[23]) & 0x3FFFFFFF); | ||
131 | rgb_order = mbox[19]; | ||
132 | uart_puts("Framebuffer initialized\n"); | ||
133 | } else { | ||
134 | uart_puts("Unable to initialize framebuffer\n"); | ||
135 | } | ||
136 | } | ||
137 | |||
87 | int | 138 | int |
88 | ppu_init(Ppu *p, Uint8 hor, Uint8 ver) { | 139 | ppu_init(Ppu *p, Uint8 hor, Uint8 ver) { |
89 | p->width = 8 * hor; | 140 | p->width = 8 * hor; |
90 | p->height = 8 * ver; | 141 | p->height = 8 * ver; |
91 | 142 | ||
92 | // Initialize the framebuffer. | 143 | fb_init(); |
93 | static MboxFramebufferRequest fb_request = { | ||
94 | .buf_size = 96, | ||
95 | .code = MBOX_REQUEST, | ||
96 | .screen_tag = { | ||
97 | .header = { | ||
98 | .id = 0x48003, | ||
99 | .buf_size = 8, | ||
100 | }, | ||
101 | .width = SCREEN_WIDTH, | ||
102 | .height = SCREEN_HEIGHT, | ||
103 | }, | ||
104 | .virtual_screen_tag = { | ||
105 | .header = { | ||
106 | .id = 0x48004, | ||
107 | .buf_size = 8, | ||
108 | }, | ||
109 | .width = SCREEN_WIDTH, | ||
110 | .height = SCREEN_HEIGHT, | ||
111 | }, | ||
112 | .depth_tag = { | ||
113 | .header = { | ||
114 | .id = 0x48005, | ||
115 | .buf_size = 4, | ||
116 | }, | ||
117 | .depth = 32, | ||
118 | }, | ||
119 | .framebuffer_tag = { | ||
120 | .header = { | ||
121 | .id = 0x40001, | ||
122 | .buf_size = 8, | ||
123 | }, | ||
124 | .fb_addr = 0, | ||
125 | .fb_size = 0, | ||
126 | } | ||
127 | }; | ||
128 | |||
129 | if (mb_call(MBOX_CH_PROP, &fb_request) | ||
130 | && fb_request.depth_tag.depth == 32 | ||
131 | && fb_request.framebuffer_tag.fb_addr != 0) { | ||
132 | fb_request.framebuffer_tag.fb_addr &= 0x3FFFFFFF; | ||
133 | framebuffer = (u32*)((uintptr_t)fb_request.framebuffer_tag.fb_addr); | ||
134 | } else { | ||
135 | uart_puts("Unable initialize framebuffer\n"); | ||
136 | return 0; | ||
137 | } | ||
138 | 144 | ||
139 | p->pixels = pixels_buf; | 145 | p->pixels = pixels_buf; |
140 | 146 | ||