a046c121efef19c376b9c1db6b321f73af95f6b8
[rpikern] / src / main.c
1 /* mailbox registers (MB 0: input  1: output)
2  * function | MB 0 | MB 1
3  *  rd/wr   | 00   | 20      ( upper 28: data, lower 4: channel )
4  *  peek    | 10   | 30
5  *  sender  | 14   | 34
6  *  status  | 18   | 38
7  *  config  | 1c   | 3c
8  *
9  * channel 1: framebuffer
10  * channel 8: request
11  *
12  * read: read status reg loop while empty flag is set
13  * write: read status loop while full flag is set
14  */
15 #include <string.h>
16 #include <stdint.h>
17
18 #ifdef RPI1
19 #define IOBASEADDR      0x20000000
20 #else
21 #define IOBASEADDR      0x3f000000
22 #endif
23
24 #define phys2bus(addr)  ((addr) | 0x40000000)
25 #define bus2phys(addr)  ((addr) & 0x3fffffff)
26
27 #define IOREG_ADDR(x)   (IOBASEADDR | (x))
28 #define REG_MB_READ             *((volatile uint32_t*)IOREG_ADDR(0xb880))
29 #define REG_MB_STAT             *((volatile uint32_t*)IOREG_ADDR(0xb898))
30 #define REG_MB_WRITE    *((volatile uint32_t*)IOREG_ADDR(0xb8a0))
31
32 #define MB_STAT_FULL    0x80000000
33 #define MB_STAT_EMPTY   0x40000000
34
35 #define MB_CHAN_FRAMEBUF        1
36 #define MB_CHAN_PROP            8
37
38 #define PROP_CODE_REQ   0
39 #define PROP_RESP_OK    0x80000000
40
41
42 #define PROP_TAG_END                    0
43
44 #define PROP_TAG_SET                    0x08000
45 #define PROP_TAG_TEST                   0x04000
46 #define PROP_TAG_GET                    0
47
48 #define PROP_TAG_ALLOCBUF               0x40001
49 #define PROP_TAG_BLANKSCR               0x40002
50 #define PROP_TAG_PHYSRES                0x40003
51 #define PROP_TAG_VIRTRES                0x40004
52 #define PROP_TAG_DEPTH                  0x40005
53 #define PROP_TAG_PIXEL_ORDER    0x40006
54 #define PROP_TAG_ALPHA_MODE             0x40007
55 #define PROP_TAG_PITCH                  0x40008
56 #define PROP_TAG_VOFFS                  0x40009
57 #define PROP_TAG_OVERSCAN               0x4000a
58 #define PROP_TAG_PALETTE                0x4000b
59 #define PROP_TAG_CUR_INFO               0x00010
60 #define PROP_TAG_CUR_STATE              0x00011
61
62
63 void panic(void);
64 int prop_blankscr(int onoff);
65 int prop_setres(int xsz, int ysz);
66 int prop_getres(int *xsz, int *ysz);
67 int prop_setvres(int xsz, int ysz);
68 int prop_getvres(int *xsz, int *ysz);
69 int prop_setdepth(int bpp);
70 int prop_getdepth(void);
71 int prop_getpitch(void);
72 void *prop_allocbuf(int *size);
73
74 uint32_t mb_read(int chan);
75 void mb_write(int chan, uint32_t val);
76
77 void dbgled(int x);
78 void exit(int x);
79
80 int main(void)
81 {
82         int i, j, bpp, fbsize, pitch;
83         uint16_t *fb;
84
85         if(prop_setres(640, 480) == -1) panic();
86         if(prop_setvres(640, 480) == -1) panic();
87         if(prop_setdepth(16) == -1) panic();
88         if(!(fb = prop_allocbuf(&fbsize))) panic();
89         bpp = prop_getdepth();
90         pitch = prop_getpitch();
91
92         if(bpp != 16) panic();
93
94         for(i=0; i<480; i++) {
95                 for(j=0; j<640; j++) {
96                         int xor = i ^ j;
97                         int r = (xor >> 1) & 0xff;
98                         int g = xor & 0xff;
99                         int b = (xor << 1) & 0xff;
100
101                         *fb++ = ((r << 8) & 0xf800) | ((g << 3) & 0x7e0) | ((b >> 3) & 0x1f);
102                 }
103
104                 //fb += pitch / 2 - 640;
105         }
106
107         return 0;
108 }
109
110 void panic(void)
111 {
112         dbgled(2);
113         exit(0);
114 }
115
116 static uint32_t propbuf[64] __attribute__((aligned(16)));
117
118 static int send_prop(uint32_t *buf)
119 {
120         mb_write(MB_CHAN_PROP, (uint32_t)buf >> 4);
121         mb_read(MB_CHAN_PROP);
122         return propbuf[1] == PROP_RESP_OK ? 0 : -1;
123 }
124
125 int prop_blankscr(int onoff)
126 {
127         uint32_t *pb = propbuf;
128
129         *pb++ = 32;
130         *pb++ = 0;
131         *pb++ = PROP_TAG_BLANKSCR;
132         *pb++ = 4;      /* data size */
133         *pb++ = PROP_CODE_REQ;
134         *pb++ = onoff ? 1 : 0;
135         *pb++ = PROP_TAG_END;
136         *pb++ = 0;      /* padding */
137
138         return send_prop(propbuf);
139 }
140
141 int prop_setres(int xsz, int ysz)
142 {
143         uint32_t *pb = propbuf;
144
145         *pb++ = 32;
146         *pb++ = 0;
147         *pb++ = PROP_TAG_PHYSRES | PROP_TAG_SET;
148         *pb++ = 8;      /* data size */
149         *pb++ = PROP_CODE_REQ;
150         *pb++ = xsz;
151         *pb++ = ysz;
152         *pb++ = PROP_TAG_END;
153
154         return send_prop(propbuf);
155 }
156
157 int prop_getres(int *xsz, int *ysz)
158 {
159         uint32_t *pb = propbuf;
160         uint32_t *data;
161
162         *pb++ = 32;
163         *pb++ = 0;
164         *pb++ = PROP_TAG_PHYSRES;
165         *pb++ = 8;
166         *pb++ = PROP_CODE_REQ;
167         data = pb;
168         *pb++ = 0;
169         *pb++ = 0;
170         *pb++ = PROP_TAG_END;
171
172         if(send_prop(propbuf) == -1) {
173                 return -1;
174         }
175         *xsz = data[0];
176         *ysz = data[1];
177         return 0;
178 }
179
180 int prop_setvres(int xsz, int ysz)
181 {
182         uint32_t *pb = propbuf;
183
184         *pb++ = 32;
185         *pb++ = 0;
186         *pb++ = PROP_TAG_VIRTRES | PROP_TAG_SET;
187         *pb++ = 8;      /* data size */
188         *pb++ = PROP_CODE_REQ;
189         *pb++ = xsz;
190         *pb++ = ysz;
191         *pb++ = PROP_TAG_END;
192
193         return send_prop(propbuf);
194 }
195
196 int prop_getvres(int *xsz, int *ysz)
197 {
198         uint32_t *pb = propbuf;
199         uint32_t *data;
200
201         *pb++ = 32;
202         *pb++ = 0;
203         *pb++ = PROP_TAG_VIRTRES;
204         *pb++ = 8;
205         *pb++ = PROP_CODE_REQ;
206         data = pb;
207         *pb++ = 0;
208         *pb++ = 0;
209         *pb++ = PROP_TAG_END;
210
211         if(send_prop(propbuf) == -1) {
212                 return -1;
213         }
214         *xsz = data[0];
215         *ysz = data[1];
216         return 0;
217 }
218
219 int prop_setdepth(int bpp)
220 {
221         uint32_t *pb = propbuf;
222
223         *pb++ = 32;
224         *pb++ = 0;
225         *pb++ = PROP_TAG_DEPTH | PROP_TAG_SET;
226         *pb++ = 4;
227         *pb++ = PROP_CODE_REQ;
228         *pb++ = bpp;
229         *pb++ = PROP_TAG_END;
230         *pb++ = 0;      /* padding */
231
232         return send_prop(propbuf);
233 }
234
235 int prop_getdepth(void)
236 {
237         uint32_t *pb = propbuf;
238         uint32_t *data;
239
240         *pb++ = 32;
241         *pb++ = 0;
242         *pb++ = PROP_TAG_DEPTH;
243         *pb++ = 4;      /* data size */
244         *pb++ = PROP_CODE_REQ;
245         data = pb;
246         *pb++ = 0;
247         *pb++ = PROP_TAG_END;
248         *pb++ = 0;      /* padding */
249
250         if(send_prop(propbuf) == -1) {
251                 return 0;
252         }
253         return *data;
254 }
255
256 int prop_getpitch(void)
257 {
258         uint32_t *pb = propbuf;
259         uint32_t *data;
260
261         *pb++ = 32;
262         *pb++ = 0;
263         *pb++ = PROP_TAG_PITCH;
264         *pb++ = 4;      /* data size */
265         *pb++ = PROP_CODE_REQ;
266         data = pb;
267         *pb++ = 0;
268         *pb++ = PROP_TAG_END;
269         *pb++ = 0;      /* padding */
270
271         if(send_prop(propbuf) == -1) {
272                 return 0;
273         }
274         return *data;
275 }
276
277 void *prop_allocbuf(int *size)
278 {
279         uint32_t *pb = propbuf;
280         uint32_t *data;
281
282         *pb++ = 32;
283         *pb++ = 0;
284         *pb++ = PROP_TAG_ALLOCBUF;
285         *pb++ = 8;      /* data size */
286         *pb++ = PROP_CODE_REQ;
287         data = pb;
288         *pb++ = 16;     /* alignment */
289         *pb++ = 0;
290         *pb++ = PROP_TAG_END;
291
292         if(send_prop(propbuf) == -1) {
293                 return 0;
294         }
295         *size = data[1];
296         return (void*)bus2phys(data[0]);
297 }
298
299 uint32_t mb_read(int chan)
300 {
301         uint32_t val;
302         do {
303                 while(REG_MB_STAT & MB_STAT_EMPTY);
304                 val = REG_MB_READ;
305         } while((val & 0xf) != chan);
306         return val >> 4;
307 }
308
309 void mb_write(int chan, uint32_t val)
310 {
311         while(REG_MB_STAT & MB_STAT_FULL);
312         REG_MB_WRITE = (val << 4) | chan;
313 }