framebuffer virtual resolution setting
[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 int prop_blankscr(int onoff);
64 int prop_setvres(int xsz, int ysz);
65 void *prop_allocbuf(void);
66
67 uint32_t mb_read(int chan);
68 void mb_write(int chan, uint32_t val);
69
70 int main(void)
71 {
72         int i;
73         uint16_t *fb;
74
75         prop_setvres(640, 480);
76         fb = prop_allocbuf();
77
78         for(i=0; i<640 * 480; i++) {
79                 *fb++ = (i & 0xff) | ((i & 0xff) << 8);
80         }
81
82         return 0;
83 }
84
85 static uint32_t propbuf[64] __attribute__((aligned(16)));
86
87 static int send_prop(uint32_t *buf)
88 {
89         mb_write(MB_CHAN_PROP, (uint32_t)buf >> 4);
90         mb_read(MB_CHAN_PROP);
91         return propbuf[1] == PROP_RESP_OK ? 0 : -1;
92 }
93
94 int prop_blankscr(int onoff)
95 {
96         uint32_t *pb = propbuf;
97
98         *pb++ = 0;
99         *pb++ = 0;
100         *pb++ = PROP_TAG_BLANKSCR;
101         *pb++ = 4;      /* data size */
102         *pb++ = PROP_CODE_REQ;
103         *pb++ = onoff ? 1 : 0;
104         *pb++ = PROP_TAG_END;
105         *pb++ = 0;      /* padding */
106         propbuf[0] = (char*)pb - (char*)propbuf;
107
108         return send_prop(propbuf);
109 }
110
111 int prop_setvres(int xsz, int ysz)
112 {
113         uint32_t *pb = propbuf;
114
115         *pb++ = 0;
116         *pb++ = 0;
117         *pb++ = PROP_TAG_VIRTRES | PROP_TAG_SET;
118         *pb++ = 8;      /* data size */
119         *pb++ = PROP_CODE_REQ;
120         *pb++ = xsz;
121         *pb++ = ysz;
122         *pb++ = PROP_TAG_END;
123         propbuf[0] = (char*)pb - (char*)propbuf;
124
125         return send_prop(propbuf);
126 }
127
128 void *prop_allocbuf(void)
129 {
130         uint32_t *pb = propbuf;
131         uint32_t *data;
132
133         *pb++ = 0;
134         *pb++ = 0;
135         *pb++ = PROP_TAG_ALLOCBUF;
136         *pb++ = 8;      /* data size */
137         *pb++ = PROP_CODE_REQ;
138         data = pb;
139         *pb++ = 16;     /* alignment */
140         *pb++ = 0;
141         *pb++ = PROP_TAG_END;
142         propbuf[0] = (char*)pb - (char*)propbuf;
143
144         if(send_prop(propbuf) == -1) {
145                 return 0;
146         }
147
148         return (void*)bus2phys(*data);
149 }
150
151 uint32_t mb_read(int chan)
152 {
153         uint32_t val;
154         do {
155                 while(REG_MB_STAT & MB_STAT_EMPTY);
156                 val = REG_MB_READ;
157         } while((val & 0xf) != chan);
158         return val >> 4;
159 }
160
161 void mb_write(int chan, uint32_t val)
162 {
163         while(REG_MB_STAT & MB_STAT_FULL);
164         REG_MB_WRITE = (val << 4) | chan;
165 }