root / hw / syborg_fb.c @ c230c4e3
History | View | Annotate | Download (13.1 kB)
1 | 4af39611 | Paul Brook | /*
|
---|---|---|---|
2 | 4af39611 | Paul Brook | * Syborg Framebuffer
|
3 | 4af39611 | Paul Brook | *
|
4 | 4af39611 | Paul Brook | * Copyright (c) 2009 CodeSourcery
|
5 | 4af39611 | Paul Brook | *
|
6 | 4af39611 | Paul Brook | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 4af39611 | Paul Brook | * of this software and associated documentation files (the "Software"), to deal
|
8 | 4af39611 | Paul Brook | * in the Software without restriction, including without limitation the rights
|
9 | 4af39611 | Paul Brook | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 4af39611 | Paul Brook | * copies of the Software, and to permit persons to whom the Software is
|
11 | 4af39611 | Paul Brook | * furnished to do so, subject to the following conditions:
|
12 | 4af39611 | Paul Brook | *
|
13 | 4af39611 | Paul Brook | * The above copyright notice and this permission notice shall be included in
|
14 | 4af39611 | Paul Brook | * all copies or substantial portions of the Software.
|
15 | 4af39611 | Paul Brook | *
|
16 | 4af39611 | Paul Brook | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 4af39611 | Paul Brook | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 4af39611 | Paul Brook | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 4af39611 | Paul Brook | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 4af39611 | Paul Brook | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 4af39611 | Paul Brook | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 4af39611 | Paul Brook | * THE SOFTWARE.
|
23 | 4af39611 | Paul Brook | */
|
24 | 4af39611 | Paul Brook | |
25 | 4af39611 | Paul Brook | #include "sysbus.h" |
26 | 4af39611 | Paul Brook | #include "console.h" |
27 | 4af39611 | Paul Brook | #include "syborg.h" |
28 | 4af39611 | Paul Brook | #include "framebuffer.h" |
29 | 4af39611 | Paul Brook | |
30 | 4af39611 | Paul Brook | //#define DEBUG_SYBORG_FB
|
31 | 4af39611 | Paul Brook | |
32 | 4af39611 | Paul Brook | #ifdef DEBUG_SYBORG_FB
|
33 | 4af39611 | Paul Brook | #define DPRINTF(fmt, ...) \
|
34 | 4af39611 | Paul Brook | do { printf("syborg_fb: " fmt , ## __VA_ARGS__); } while (0) |
35 | 4af39611 | Paul Brook | #define BADF(fmt, ...) \
|
36 | 4af39611 | Paul Brook | do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__); \ |
37 | 4af39611 | Paul Brook | exit(1);} while (0) |
38 | 4af39611 | Paul Brook | #else
|
39 | 4af39611 | Paul Brook | #define DPRINTF(fmt, ...) do {} while(0) |
40 | 4af39611 | Paul Brook | #define BADF(fmt, ...) \
|
41 | 4af39611 | Paul Brook | do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__);} while (0) |
42 | 4af39611 | Paul Brook | #endif
|
43 | 4af39611 | Paul Brook | |
44 | 4af39611 | Paul Brook | enum {
|
45 | 4af39611 | Paul Brook | FB_ID = 0,
|
46 | 4af39611 | Paul Brook | FB_BASE = 1,
|
47 | 4af39611 | Paul Brook | FB_HEIGHT = 2,
|
48 | 4af39611 | Paul Brook | FB_WIDTH = 3,
|
49 | 4af39611 | Paul Brook | FB_ORIENTATION = 4,
|
50 | 4af39611 | Paul Brook | FB_BLANK = 5,
|
51 | 4af39611 | Paul Brook | FB_INT_MASK = 6,
|
52 | 4af39611 | Paul Brook | FB_INTERRUPT_CAUSE = 7,
|
53 | 4af39611 | Paul Brook | FB_BPP = 8,
|
54 | 4af39611 | Paul Brook | FB_COLOR_ORDER = 9,
|
55 | 4af39611 | Paul Brook | FB_BYTE_ORDER = 10,
|
56 | 4af39611 | Paul Brook | FB_PIXEL_ORDER = 11,
|
57 | 4af39611 | Paul Brook | FB_ROW_PITCH = 12,
|
58 | 4af39611 | Paul Brook | FB_ENABLED = 13,
|
59 | 4af39611 | Paul Brook | FB_PALETTE_START = 0x400 >> 2, |
60 | 4af39611 | Paul Brook | FB_PALETTE_END = FB_PALETTE_START+256-1, |
61 | 4af39611 | Paul Brook | }; |
62 | 4af39611 | Paul Brook | |
63 | 4af39611 | Paul Brook | #define FB_INT_VSYNC (1U << 0) |
64 | 4af39611 | Paul Brook | #define FB_INT_BASE_UPDATE_DONE (1U << 1) |
65 | 4af39611 | Paul Brook | |
66 | 4af39611 | Paul Brook | typedef struct { |
67 | 4af39611 | Paul Brook | SysBusDevice busdev; |
68 | 4af39611 | Paul Brook | DisplayState *ds; |
69 | 4af39611 | Paul Brook | /*QEMUConsole *console;*/
|
70 | 4af39611 | Paul Brook | uint32_t need_update : 1;
|
71 | 4af39611 | Paul Brook | uint32_t need_int : 1;
|
72 | 4af39611 | Paul Brook | uint32_t enabled : 1;
|
73 | 4af39611 | Paul Brook | uint32_t int_status; |
74 | 4af39611 | Paul Brook | uint32_t int_enable; |
75 | 4af39611 | Paul Brook | qemu_irq irq; |
76 | 4af39611 | Paul Brook | |
77 | 4af39611 | Paul Brook | uint32_t base; |
78 | 4af39611 | Paul Brook | uint32_t pitch; |
79 | ee6847d1 | Gerd Hoffmann | uint32_t rows; |
80 | ee6847d1 | Gerd Hoffmann | uint32_t cols; |
81 | 4af39611 | Paul Brook | int blank;
|
82 | 4af39611 | Paul Brook | int bpp;
|
83 | 4af39611 | Paul Brook | int rgb; /* 0 = BGR, 1 = RGB */ |
84 | 4af39611 | Paul Brook | int endian; /* 0 = Little, 1 = Big */ |
85 | 4af39611 | Paul Brook | uint32_t raw_palette[256];
|
86 | 4af39611 | Paul Brook | uint32_t palette[256];
|
87 | 4af39611 | Paul Brook | } SyborgFBState; |
88 | 4af39611 | Paul Brook | |
89 | 4af39611 | Paul Brook | enum {
|
90 | 4af39611 | Paul Brook | BPP_SRC_1, |
91 | 4af39611 | Paul Brook | BPP_SRC_2, |
92 | 4af39611 | Paul Brook | BPP_SRC_4, |
93 | 4af39611 | Paul Brook | BPP_SRC_8, |
94 | 4af39611 | Paul Brook | BPP_SRC_16, |
95 | 4af39611 | Paul Brook | BPP_SRC_32, |
96 | 4af39611 | Paul Brook | /* TODO: Implement these. */
|
97 | 4af39611 | Paul Brook | BPP_SRC_15 = -1,
|
98 | 4af39611 | Paul Brook | BPP_SRC_24 = -2
|
99 | 4af39611 | Paul Brook | }; |
100 | 4af39611 | Paul Brook | |
101 | 4af39611 | Paul Brook | #include "pixel_ops.h" |
102 | 4af39611 | Paul Brook | |
103 | 4af39611 | Paul Brook | #define BITS 8 |
104 | 4af39611 | Paul Brook | #include "pl110_template.h" |
105 | 4af39611 | Paul Brook | #define BITS 15 |
106 | 4af39611 | Paul Brook | #include "pl110_template.h" |
107 | 4af39611 | Paul Brook | #define BITS 16 |
108 | 4af39611 | Paul Brook | #include "pl110_template.h" |
109 | 4af39611 | Paul Brook | #define BITS 24 |
110 | 4af39611 | Paul Brook | #include "pl110_template.h" |
111 | 4af39611 | Paul Brook | #define BITS 32 |
112 | 4af39611 | Paul Brook | #include "pl110_template.h" |
113 | 4af39611 | Paul Brook | |
114 | 4af39611 | Paul Brook | /* Update interrupts. */
|
115 | 4af39611 | Paul Brook | static void syborg_fb_update(SyborgFBState *s) |
116 | 4af39611 | Paul Brook | { |
117 | 4af39611 | Paul Brook | if ((s->int_status & s->int_enable) != 0) { |
118 | 4af39611 | Paul Brook | DPRINTF("Raise IRQ\n");
|
119 | 4af39611 | Paul Brook | qemu_irq_raise(s->irq); |
120 | 4af39611 | Paul Brook | } else {
|
121 | 4af39611 | Paul Brook | DPRINTF("Lower IRQ\n");
|
122 | 4af39611 | Paul Brook | qemu_irq_lower(s->irq); |
123 | 4af39611 | Paul Brook | } |
124 | 4af39611 | Paul Brook | } |
125 | 4af39611 | Paul Brook | |
126 | 4af39611 | Paul Brook | static int syborg_fb_enabled(const SyborgFBState *s) |
127 | 4af39611 | Paul Brook | { |
128 | 4af39611 | Paul Brook | return s->enabled;
|
129 | 4af39611 | Paul Brook | } |
130 | 4af39611 | Paul Brook | |
131 | 4af39611 | Paul Brook | static void syborg_fb_update_palette(SyborgFBState *s) |
132 | 4af39611 | Paul Brook | { |
133 | 4af39611 | Paul Brook | int n, i;
|
134 | 4af39611 | Paul Brook | uint32_t raw; |
135 | 4af39611 | Paul Brook | unsigned int r, g, b; |
136 | 4af39611 | Paul Brook | |
137 | 4af39611 | Paul Brook | switch (s->bpp) {
|
138 | 4af39611 | Paul Brook | case BPP_SRC_1: n = 2; break; |
139 | 4af39611 | Paul Brook | case BPP_SRC_2: n = 4; break; |
140 | 4af39611 | Paul Brook | case BPP_SRC_4: n = 16; break; |
141 | 4af39611 | Paul Brook | case BPP_SRC_8: n = 256; break; |
142 | 4af39611 | Paul Brook | default: return; |
143 | 4af39611 | Paul Brook | } |
144 | 4af39611 | Paul Brook | |
145 | 4af39611 | Paul Brook | for (i = 0; i < n; i++) { |
146 | 4af39611 | Paul Brook | raw = s->raw_palette[i]; |
147 | 4af39611 | Paul Brook | r = (raw >> 16) & 0xff; |
148 | 4af39611 | Paul Brook | g = (raw >> 8) & 0xff; |
149 | 4af39611 | Paul Brook | b = raw & 0xff;
|
150 | 4af39611 | Paul Brook | switch (ds_get_bits_per_pixel(s->ds)) {
|
151 | 4af39611 | Paul Brook | case 8: |
152 | 4af39611 | Paul Brook | s->palette[i] = rgb_to_pixel8(r, g, b); |
153 | 4af39611 | Paul Brook | break;
|
154 | 4af39611 | Paul Brook | case 15: |
155 | 4af39611 | Paul Brook | s->palette[i] = rgb_to_pixel15(r, g, b); |
156 | 4af39611 | Paul Brook | break;
|
157 | 4af39611 | Paul Brook | case 16: |
158 | 4af39611 | Paul Brook | s->palette[i] = rgb_to_pixel16(r, g, b); |
159 | 4af39611 | Paul Brook | break;
|
160 | 4af39611 | Paul Brook | case 24: |
161 | 4af39611 | Paul Brook | case 32: |
162 | 4af39611 | Paul Brook | s->palette[i] = rgb_to_pixel32(r, g, b); |
163 | 4af39611 | Paul Brook | break;
|
164 | 4af39611 | Paul Brook | default:
|
165 | 4af39611 | Paul Brook | abort(); |
166 | 4af39611 | Paul Brook | } |
167 | 4af39611 | Paul Brook | } |
168 | 4af39611 | Paul Brook | |
169 | 4af39611 | Paul Brook | } |
170 | 4af39611 | Paul Brook | |
171 | 4af39611 | Paul Brook | static void syborg_fb_update_display(void *opaque) |
172 | 4af39611 | Paul Brook | { |
173 | 4af39611 | Paul Brook | SyborgFBState *s = (SyborgFBState *)opaque; |
174 | 4af39611 | Paul Brook | drawfn* fntable; |
175 | 4af39611 | Paul Brook | drawfn fn; |
176 | 4af39611 | Paul Brook | int dest_width;
|
177 | 4af39611 | Paul Brook | int src_width;
|
178 | 4af39611 | Paul Brook | int bpp_offset;
|
179 | 4af39611 | Paul Brook | int first;
|
180 | 4af39611 | Paul Brook | int last;
|
181 | 4af39611 | Paul Brook | |
182 | 4af39611 | Paul Brook | if (!syborg_fb_enabled(s))
|
183 | 4af39611 | Paul Brook | return;
|
184 | 4af39611 | Paul Brook | |
185 | 4af39611 | Paul Brook | switch (ds_get_bits_per_pixel(s->ds)) {
|
186 | 4af39611 | Paul Brook | case 0: |
187 | 4af39611 | Paul Brook | return;
|
188 | 4af39611 | Paul Brook | case 8: |
189 | 4af39611 | Paul Brook | fntable = pl110_draw_fn_8; |
190 | 4af39611 | Paul Brook | dest_width = 1;
|
191 | 4af39611 | Paul Brook | break;
|
192 | 4af39611 | Paul Brook | case 15: |
193 | 4af39611 | Paul Brook | fntable = pl110_draw_fn_15; |
194 | 4af39611 | Paul Brook | dest_width = 2;
|
195 | 4af39611 | Paul Brook | break;
|
196 | 4af39611 | Paul Brook | case 16: |
197 | 4af39611 | Paul Brook | fntable = pl110_draw_fn_16; |
198 | 4af39611 | Paul Brook | dest_width = 2;
|
199 | 4af39611 | Paul Brook | break;
|
200 | 4af39611 | Paul Brook | case 24: |
201 | 4af39611 | Paul Brook | fntable = pl110_draw_fn_24; |
202 | 4af39611 | Paul Brook | dest_width = 3;
|
203 | 4af39611 | Paul Brook | break;
|
204 | 4af39611 | Paul Brook | case 32: |
205 | 4af39611 | Paul Brook | fntable = pl110_draw_fn_32; |
206 | 4af39611 | Paul Brook | dest_width = 4;
|
207 | 4af39611 | Paul Brook | break;
|
208 | 4af39611 | Paul Brook | default:
|
209 | 4af39611 | Paul Brook | fprintf(stderr, "syborg_fb: Bad color depth\n");
|
210 | 4af39611 | Paul Brook | exit(1);
|
211 | 4af39611 | Paul Brook | } |
212 | 4af39611 | Paul Brook | |
213 | 4af39611 | Paul Brook | if (s->need_int) {
|
214 | 4af39611 | Paul Brook | s->int_status |= FB_INT_BASE_UPDATE_DONE; |
215 | 4af39611 | Paul Brook | syborg_fb_update(s); |
216 | 4af39611 | Paul Brook | s->need_int = 0;
|
217 | 4af39611 | Paul Brook | } |
218 | 4af39611 | Paul Brook | |
219 | 4af39611 | Paul Brook | if (s->rgb) {
|
220 | 4af39611 | Paul Brook | bpp_offset = 18;
|
221 | 4af39611 | Paul Brook | } else {
|
222 | 4af39611 | Paul Brook | bpp_offset = 0;
|
223 | 4af39611 | Paul Brook | } |
224 | 4af39611 | Paul Brook | if (s->endian) {
|
225 | 4af39611 | Paul Brook | bpp_offset += 6;
|
226 | 4af39611 | Paul Brook | } |
227 | 4af39611 | Paul Brook | |
228 | 4af39611 | Paul Brook | fn = fntable[s->bpp + bpp_offset]; |
229 | 4af39611 | Paul Brook | |
230 | 4af39611 | Paul Brook | if (s->pitch) {
|
231 | 4af39611 | Paul Brook | src_width = s->pitch; |
232 | 4af39611 | Paul Brook | } else {
|
233 | 4af39611 | Paul Brook | src_width = s->cols; |
234 | 4af39611 | Paul Brook | switch (s->bpp) {
|
235 | 4af39611 | Paul Brook | case BPP_SRC_1:
|
236 | 4af39611 | Paul Brook | src_width >>= 3;
|
237 | 4af39611 | Paul Brook | break;
|
238 | 4af39611 | Paul Brook | case BPP_SRC_2:
|
239 | 4af39611 | Paul Brook | src_width >>= 2;
|
240 | 4af39611 | Paul Brook | break;
|
241 | 4af39611 | Paul Brook | case BPP_SRC_4:
|
242 | 4af39611 | Paul Brook | src_width >>= 1;
|
243 | 4af39611 | Paul Brook | break;
|
244 | 4af39611 | Paul Brook | case BPP_SRC_8:
|
245 | 4af39611 | Paul Brook | break;
|
246 | 4af39611 | Paul Brook | case BPP_SRC_15:
|
247 | 4af39611 | Paul Brook | case BPP_SRC_16:
|
248 | 4af39611 | Paul Brook | src_width <<= 1;
|
249 | 4af39611 | Paul Brook | break;
|
250 | 4af39611 | Paul Brook | case BPP_SRC_24:
|
251 | 4af39611 | Paul Brook | src_width *= 3;
|
252 | 4af39611 | Paul Brook | break;
|
253 | 4af39611 | Paul Brook | case BPP_SRC_32:
|
254 | 4af39611 | Paul Brook | src_width <<= 2;
|
255 | 4af39611 | Paul Brook | break;
|
256 | 4af39611 | Paul Brook | } |
257 | 4af39611 | Paul Brook | } |
258 | 4af39611 | Paul Brook | dest_width *= s->cols; |
259 | 4af39611 | Paul Brook | first = 0;
|
260 | 4af39611 | Paul Brook | /* TODO: Implement blanking. */
|
261 | 4af39611 | Paul Brook | if (!s->blank) {
|
262 | 4af39611 | Paul Brook | if (s->need_update && s->bpp <= BPP_SRC_8) {
|
263 | 4af39611 | Paul Brook | syborg_fb_update_palette(s); |
264 | 4af39611 | Paul Brook | } |
265 | 4af39611 | Paul Brook | framebuffer_update_display(s->ds, |
266 | 4af39611 | Paul Brook | s->base, s->cols, s->rows, |
267 | 4af39611 | Paul Brook | src_width, dest_width, 0,
|
268 | 4af39611 | Paul Brook | s->need_update, |
269 | 4af39611 | Paul Brook | fn, s->palette, |
270 | 4af39611 | Paul Brook | &first, &last); |
271 | 4af39611 | Paul Brook | if (first >= 0) { |
272 | 4af39611 | Paul Brook | dpy_update(s->ds, 0, first, s->cols, last - first + 1); |
273 | 4af39611 | Paul Brook | } |
274 | 4af39611 | Paul Brook | |
275 | 4af39611 | Paul Brook | s->int_status |= FB_INT_VSYNC; |
276 | 4af39611 | Paul Brook | syborg_fb_update(s); |
277 | 4af39611 | Paul Brook | } |
278 | 4af39611 | Paul Brook | |
279 | 4af39611 | Paul Brook | s->need_update = 0;
|
280 | 4af39611 | Paul Brook | } |
281 | 4af39611 | Paul Brook | |
282 | 4af39611 | Paul Brook | static void syborg_fb_invalidate_display(void * opaque) |
283 | 4af39611 | Paul Brook | { |
284 | 4af39611 | Paul Brook | SyborgFBState *s = (SyborgFBState *)opaque; |
285 | 4af39611 | Paul Brook | s->need_update = 1;
|
286 | 4af39611 | Paul Brook | } |
287 | 4af39611 | Paul Brook | |
288 | 4af39611 | Paul Brook | static uint32_t syborg_fb_read(void *opaque, target_phys_addr_t offset) |
289 | 4af39611 | Paul Brook | { |
290 | 4af39611 | Paul Brook | SyborgFBState *s = opaque; |
291 | 4af39611 | Paul Brook | |
292 | 4af39611 | Paul Brook | DPRINTF("read reg %d\n", (int)offset); |
293 | 4af39611 | Paul Brook | offset &= 0xfff;
|
294 | 4af39611 | Paul Brook | switch (offset >> 2) { |
295 | 4af39611 | Paul Brook | case FB_ID:
|
296 | 4af39611 | Paul Brook | return SYBORG_ID_FRAMEBUFFER;
|
297 | 4af39611 | Paul Brook | |
298 | 4af39611 | Paul Brook | case FB_BASE:
|
299 | 4af39611 | Paul Brook | return s->base;
|
300 | 4af39611 | Paul Brook | |
301 | 4af39611 | Paul Brook | case FB_HEIGHT:
|
302 | 4af39611 | Paul Brook | return s->rows;
|
303 | 4af39611 | Paul Brook | |
304 | 4af39611 | Paul Brook | case FB_WIDTH:
|
305 | 4af39611 | Paul Brook | return s->cols;
|
306 | 4af39611 | Paul Brook | |
307 | 4af39611 | Paul Brook | case FB_ORIENTATION:
|
308 | 4af39611 | Paul Brook | return 0; |
309 | 4af39611 | Paul Brook | |
310 | 4af39611 | Paul Brook | case FB_BLANK:
|
311 | 4af39611 | Paul Brook | return s->blank;
|
312 | 4af39611 | Paul Brook | |
313 | 4af39611 | Paul Brook | case FB_INT_MASK:
|
314 | 4af39611 | Paul Brook | return s->int_enable;
|
315 | 4af39611 | Paul Brook | |
316 | 4af39611 | Paul Brook | case FB_INTERRUPT_CAUSE:
|
317 | 4af39611 | Paul Brook | return s->int_status;
|
318 | 4af39611 | Paul Brook | |
319 | 4af39611 | Paul Brook | case FB_BPP:
|
320 | 4af39611 | Paul Brook | switch (s->bpp) {
|
321 | 4af39611 | Paul Brook | case BPP_SRC_1: return 1; |
322 | 4af39611 | Paul Brook | case BPP_SRC_2: return 2; |
323 | 4af39611 | Paul Brook | case BPP_SRC_4: return 4; |
324 | 4af39611 | Paul Brook | case BPP_SRC_8: return 8; |
325 | 4af39611 | Paul Brook | case BPP_SRC_15: return 15; |
326 | 4af39611 | Paul Brook | case BPP_SRC_16: return 16; |
327 | 4af39611 | Paul Brook | case BPP_SRC_24: return 24; |
328 | 4af39611 | Paul Brook | case BPP_SRC_32: return 32; |
329 | 4af39611 | Paul Brook | default: return 0; |
330 | 4af39611 | Paul Brook | } |
331 | 4af39611 | Paul Brook | |
332 | 4af39611 | Paul Brook | case FB_COLOR_ORDER:
|
333 | 4af39611 | Paul Brook | return s->rgb;
|
334 | 4af39611 | Paul Brook | |
335 | 4af39611 | Paul Brook | case FB_BYTE_ORDER:
|
336 | 4af39611 | Paul Brook | return s->endian;
|
337 | 4af39611 | Paul Brook | |
338 | 4af39611 | Paul Brook | case FB_PIXEL_ORDER:
|
339 | 4af39611 | Paul Brook | return 0; |
340 | 4af39611 | Paul Brook | |
341 | 4af39611 | Paul Brook | case FB_ROW_PITCH:
|
342 | 4af39611 | Paul Brook | return s->pitch;
|
343 | 4af39611 | Paul Brook | |
344 | 4af39611 | Paul Brook | case FB_ENABLED:
|
345 | 4af39611 | Paul Brook | return s->enabled;
|
346 | 4af39611 | Paul Brook | |
347 | 4af39611 | Paul Brook | default:
|
348 | 4af39611 | Paul Brook | if ((offset >> 2) >= FB_PALETTE_START |
349 | 4af39611 | Paul Brook | && (offset >> 2) <= FB_PALETTE_END) {
|
350 | 4af39611 | Paul Brook | return s->raw_palette[(offset >> 2) - FB_PALETTE_START]; |
351 | 4af39611 | Paul Brook | } else {
|
352 | 4af39611 | Paul Brook | cpu_abort (cpu_single_env, "syborg_fb_read: Bad offset %x\n",
|
353 | 4af39611 | Paul Brook | (int)offset);
|
354 | 4af39611 | Paul Brook | } |
355 | 4af39611 | Paul Brook | return 0; |
356 | 4af39611 | Paul Brook | } |
357 | 4af39611 | Paul Brook | } |
358 | 4af39611 | Paul Brook | |
359 | 4af39611 | Paul Brook | static void syborg_fb_write(void *opaque, target_phys_addr_t offset, |
360 | 4af39611 | Paul Brook | uint32_t val) |
361 | 4af39611 | Paul Brook | { |
362 | 4af39611 | Paul Brook | SyborgFBState *s = opaque; |
363 | 4af39611 | Paul Brook | |
364 | 4af39611 | Paul Brook | DPRINTF("write reg %d = %d\n", (int)offset, val); |
365 | 4af39611 | Paul Brook | s->need_update = 1;
|
366 | 4af39611 | Paul Brook | offset &= 0xfff;
|
367 | 4af39611 | Paul Brook | switch (offset >> 2) { |
368 | 4af39611 | Paul Brook | case FB_BASE:
|
369 | 4af39611 | Paul Brook | s->base = val; |
370 | 4af39611 | Paul Brook | s->need_int = 1;
|
371 | 4af39611 | Paul Brook | s->need_update = 1;
|
372 | 4af39611 | Paul Brook | syborg_fb_update(s); |
373 | 4af39611 | Paul Brook | break;
|
374 | 4af39611 | Paul Brook | |
375 | 4af39611 | Paul Brook | case FB_HEIGHT:
|
376 | 4af39611 | Paul Brook | s->rows = val; |
377 | 4af39611 | Paul Brook | break;
|
378 | 4af39611 | Paul Brook | |
379 | 4af39611 | Paul Brook | case FB_WIDTH:
|
380 | 4af39611 | Paul Brook | s->cols = val; |
381 | 4af39611 | Paul Brook | break;
|
382 | 4af39611 | Paul Brook | |
383 | 4af39611 | Paul Brook | case FB_ORIENTATION:
|
384 | 4af39611 | Paul Brook | /* TODO: Implement rotation. */
|
385 | 4af39611 | Paul Brook | break;
|
386 | 4af39611 | Paul Brook | |
387 | 4af39611 | Paul Brook | case FB_BLANK:
|
388 | 4af39611 | Paul Brook | s->blank = val & 1;
|
389 | 4af39611 | Paul Brook | break;
|
390 | 4af39611 | Paul Brook | |
391 | 4af39611 | Paul Brook | case FB_INT_MASK:
|
392 | 4af39611 | Paul Brook | s->int_enable = val; |
393 | 4af39611 | Paul Brook | syborg_fb_update(s); |
394 | 4af39611 | Paul Brook | break;
|
395 | 4af39611 | Paul Brook | |
396 | 4af39611 | Paul Brook | case FB_INTERRUPT_CAUSE:
|
397 | 4af39611 | Paul Brook | s->int_status &= ~val; |
398 | 4af39611 | Paul Brook | syborg_fb_update(s); |
399 | 4af39611 | Paul Brook | break;
|
400 | 4af39611 | Paul Brook | |
401 | 4af39611 | Paul Brook | case FB_BPP:
|
402 | 4af39611 | Paul Brook | switch (val) {
|
403 | 4af39611 | Paul Brook | case 1: val = BPP_SRC_1; break; |
404 | 4af39611 | Paul Brook | case 2: val = BPP_SRC_2; break; |
405 | 4af39611 | Paul Brook | case 4: val = BPP_SRC_4; break; |
406 | 4af39611 | Paul Brook | case 8: val = BPP_SRC_8; break; |
407 | 4af39611 | Paul Brook | /* case 15: val = BPP_SRC_15; break; */
|
408 | 4af39611 | Paul Brook | case 16: val = BPP_SRC_16; break; |
409 | 4af39611 | Paul Brook | /* case 24: val = BPP_SRC_24; break; */
|
410 | 4af39611 | Paul Brook | case 32: val = BPP_SRC_32; break; |
411 | 4af39611 | Paul Brook | default: val = s->bpp; break; |
412 | 4af39611 | Paul Brook | } |
413 | 4af39611 | Paul Brook | s->bpp = val; |
414 | 4af39611 | Paul Brook | break;
|
415 | 4af39611 | Paul Brook | |
416 | 4af39611 | Paul Brook | case FB_COLOR_ORDER:
|
417 | 4af39611 | Paul Brook | s->rgb = (val != 0);
|
418 | 4af39611 | Paul Brook | break;
|
419 | 4af39611 | Paul Brook | |
420 | 4af39611 | Paul Brook | case FB_BYTE_ORDER:
|
421 | 4af39611 | Paul Brook | s->endian = (val != 0);
|
422 | 4af39611 | Paul Brook | break;
|
423 | 4af39611 | Paul Brook | |
424 | 4af39611 | Paul Brook | case FB_PIXEL_ORDER:
|
425 | 4af39611 | Paul Brook | /* TODO: Implement this. */
|
426 | 4af39611 | Paul Brook | break;
|
427 | 4af39611 | Paul Brook | |
428 | 4af39611 | Paul Brook | case FB_ROW_PITCH:
|
429 | 4af39611 | Paul Brook | s->pitch = val; |
430 | 4af39611 | Paul Brook | break;
|
431 | 4af39611 | Paul Brook | |
432 | 4af39611 | Paul Brook | case FB_ENABLED:
|
433 | 4af39611 | Paul Brook | s->enabled = val; |
434 | 4af39611 | Paul Brook | break;
|
435 | 4af39611 | Paul Brook | |
436 | 4af39611 | Paul Brook | default:
|
437 | 4af39611 | Paul Brook | if ((offset >> 2) >= FB_PALETTE_START |
438 | 4af39611 | Paul Brook | && (offset >> 2) <= FB_PALETTE_END) {
|
439 | 4af39611 | Paul Brook | s->raw_palette[(offset >> 2) - FB_PALETTE_START] = val;
|
440 | 4af39611 | Paul Brook | } else {
|
441 | 4af39611 | Paul Brook | cpu_abort (cpu_single_env, "syborg_fb_write: Bad offset %x\n",
|
442 | 4af39611 | Paul Brook | (int)offset);
|
443 | 4af39611 | Paul Brook | } |
444 | 4af39611 | Paul Brook | break;
|
445 | 4af39611 | Paul Brook | } |
446 | 4af39611 | Paul Brook | } |
447 | 4af39611 | Paul Brook | |
448 | 4af39611 | Paul Brook | static CPUReadMemoryFunc *syborg_fb_readfn[] = {
|
449 | 4af39611 | Paul Brook | syborg_fb_read, |
450 | 4af39611 | Paul Brook | syborg_fb_read, |
451 | 4af39611 | Paul Brook | syborg_fb_read |
452 | 4af39611 | Paul Brook | }; |
453 | 4af39611 | Paul Brook | |
454 | 4af39611 | Paul Brook | static CPUWriteMemoryFunc *syborg_fb_writefn[] = {
|
455 | 4af39611 | Paul Brook | syborg_fb_write, |
456 | 4af39611 | Paul Brook | syborg_fb_write, |
457 | 4af39611 | Paul Brook | syborg_fb_write |
458 | 4af39611 | Paul Brook | }; |
459 | 4af39611 | Paul Brook | |
460 | 4af39611 | Paul Brook | static void syborg_fb_save(QEMUFile *f, void *opaque) |
461 | 4af39611 | Paul Brook | { |
462 | 4af39611 | Paul Brook | SyborgFBState *s = opaque; |
463 | 4af39611 | Paul Brook | int i;
|
464 | 4af39611 | Paul Brook | |
465 | 4af39611 | Paul Brook | qemu_put_be32(f, s->need_int); |
466 | 4af39611 | Paul Brook | qemu_put_be32(f, s->int_status); |
467 | 4af39611 | Paul Brook | qemu_put_be32(f, s->int_enable); |
468 | 4af39611 | Paul Brook | qemu_put_be32(f, s->enabled); |
469 | 4af39611 | Paul Brook | qemu_put_be32(f, s->base); |
470 | 4af39611 | Paul Brook | qemu_put_be32(f, s->pitch); |
471 | 4af39611 | Paul Brook | qemu_put_be32(f, s->rows); |
472 | 4af39611 | Paul Brook | qemu_put_be32(f, s->cols); |
473 | 4af39611 | Paul Brook | qemu_put_be32(f, s->bpp); |
474 | 4af39611 | Paul Brook | qemu_put_be32(f, s->rgb); |
475 | 4af39611 | Paul Brook | for (i = 0; i < 256; i++) { |
476 | 4af39611 | Paul Brook | qemu_put_be32(f, s->raw_palette[i]); |
477 | 4af39611 | Paul Brook | } |
478 | 4af39611 | Paul Brook | } |
479 | 4af39611 | Paul Brook | |
480 | 4af39611 | Paul Brook | static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id) |
481 | 4af39611 | Paul Brook | { |
482 | 4af39611 | Paul Brook | SyborgFBState *s = opaque; |
483 | 4af39611 | Paul Brook | int i;
|
484 | 4af39611 | Paul Brook | |
485 | 4af39611 | Paul Brook | if (version_id != 1) |
486 | 4af39611 | Paul Brook | return -EINVAL;
|
487 | 4af39611 | Paul Brook | |
488 | 4af39611 | Paul Brook | s->need_int = qemu_get_be32(f); |
489 | 4af39611 | Paul Brook | s->int_status = qemu_get_be32(f); |
490 | 4af39611 | Paul Brook | s->int_enable = qemu_get_be32(f); |
491 | 4af39611 | Paul Brook | s->enabled = qemu_get_be32(f); |
492 | 4af39611 | Paul Brook | s->base = qemu_get_be32(f); |
493 | 4af39611 | Paul Brook | s->pitch = qemu_get_be32(f); |
494 | 4af39611 | Paul Brook | s->rows = qemu_get_be32(f); |
495 | 4af39611 | Paul Brook | s->cols = qemu_get_be32(f); |
496 | 4af39611 | Paul Brook | s->bpp = qemu_get_be32(f); |
497 | 4af39611 | Paul Brook | s->rgb = qemu_get_be32(f); |
498 | 4af39611 | Paul Brook | for (i = 0; i < 256; i++) { |
499 | 4af39611 | Paul Brook | s->raw_palette[i] = qemu_get_be32(f); |
500 | 4af39611 | Paul Brook | } |
501 | 4af39611 | Paul Brook | s->need_update = 1;
|
502 | 4af39611 | Paul Brook | |
503 | 4af39611 | Paul Brook | return 0; |
504 | 4af39611 | Paul Brook | } |
505 | 4af39611 | Paul Brook | |
506 | 4af39611 | Paul Brook | static void syborg_fb_init(SysBusDevice *dev) |
507 | 4af39611 | Paul Brook | { |
508 | 4af39611 | Paul Brook | SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev); |
509 | 4af39611 | Paul Brook | int iomemtype;
|
510 | 4af39611 | Paul Brook | |
511 | 4af39611 | Paul Brook | sysbus_init_irq(dev, &s->irq); |
512 | 1eed09cb | Avi Kivity | iomemtype = cpu_register_io_memory(syborg_fb_readfn, |
513 | 4af39611 | Paul Brook | syborg_fb_writefn, s); |
514 | 4af39611 | Paul Brook | sysbus_init_mmio(dev, 0x1000, iomemtype);
|
515 | 4af39611 | Paul Brook | |
516 | 4af39611 | Paul Brook | s->ds = graphic_console_init(syborg_fb_update_display, |
517 | 4af39611 | Paul Brook | syborg_fb_invalidate_display, |
518 | 4af39611 | Paul Brook | NULL, NULL, s); |
519 | 4af39611 | Paul Brook | |
520 | ee6847d1 | Gerd Hoffmann | if (s->cols != 0 && s->rows != 0) { |
521 | ee6847d1 | Gerd Hoffmann | qemu_console_resize(s->ds, s->cols, s->rows); |
522 | 4af39611 | Paul Brook | } |
523 | 4af39611 | Paul Brook | |
524 | ee6847d1 | Gerd Hoffmann | if (!s->cols)
|
525 | ee6847d1 | Gerd Hoffmann | s->cols = ds_get_width(s->ds); |
526 | ee6847d1 | Gerd Hoffmann | if (!s->rows)
|
527 | ee6847d1 | Gerd Hoffmann | s->rows = ds_get_height(s->ds); |
528 | 4af39611 | Paul Brook | |
529 | 4af39611 | Paul Brook | register_savevm("syborg_framebuffer", -1, 1, |
530 | 4af39611 | Paul Brook | syborg_fb_save, syborg_fb_load, s); |
531 | 4af39611 | Paul Brook | } |
532 | 4af39611 | Paul Brook | |
533 | ee6847d1 | Gerd Hoffmann | static SysBusDeviceInfo syborg_fb_info = {
|
534 | ee6847d1 | Gerd Hoffmann | .init = syborg_fb_init, |
535 | ee6847d1 | Gerd Hoffmann | .qdev.name = "syborg,framebuffer",
|
536 | ee6847d1 | Gerd Hoffmann | .qdev.size = sizeof(SyborgFBState),
|
537 | ee6847d1 | Gerd Hoffmann | .qdev.props = (Property[]) { |
538 | c230c4e3 | Gerd Hoffmann | DEFINE_PROP_UINT32("width", SyborgFBState, cols, 0), |
539 | c230c4e3 | Gerd Hoffmann | DEFINE_PROP_UINT32("height", SyborgFBState, rows, 0), |
540 | c230c4e3 | Gerd Hoffmann | DEFINE_PROP_END_OF_LIST(), |
541 | ee6847d1 | Gerd Hoffmann | } |
542 | ee6847d1 | Gerd Hoffmann | }; |
543 | ee6847d1 | Gerd Hoffmann | |
544 | 4af39611 | Paul Brook | static void syborg_fb_register_devices(void) |
545 | 4af39611 | Paul Brook | { |
546 | ee6847d1 | Gerd Hoffmann | sysbus_register_withprop(&syborg_fb_info); |
547 | 4af39611 | Paul Brook | } |
548 | 4af39611 | Paul Brook | |
549 | 4af39611 | Paul Brook | device_init(syborg_fb_register_devices) |