Statistics
| Branch: | Revision:

root / hw / syborg_fb.c @ c1ded3dc

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 c227f099 Anthony Liguori
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 c227f099 Anthony Liguori
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 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const 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 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const 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 81a322d4 Gerd Hoffmann
static int 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 0be71e32 Alex Williamson
    register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1,
530 4af39611 Paul Brook
                    syborg_fb_save, syborg_fb_load, s);
531 81a322d4 Gerd Hoffmann
    return 0;
532 4af39611 Paul Brook
}
533 4af39611 Paul Brook
534 ee6847d1 Gerd Hoffmann
static SysBusDeviceInfo syborg_fb_info = {
535 ee6847d1 Gerd Hoffmann
    .init = syborg_fb_init,
536 ee6847d1 Gerd Hoffmann
    .qdev.name  = "syborg,framebuffer",
537 ee6847d1 Gerd Hoffmann
    .qdev.size  = sizeof(SyborgFBState),
538 ee6847d1 Gerd Hoffmann
    .qdev.props = (Property[]) {
539 c230c4e3 Gerd Hoffmann
        DEFINE_PROP_UINT32("width",  SyborgFBState, cols, 0),
540 c230c4e3 Gerd Hoffmann
        DEFINE_PROP_UINT32("height", SyborgFBState, rows, 0),
541 c230c4e3 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
542 ee6847d1 Gerd Hoffmann
    }
543 ee6847d1 Gerd Hoffmann
};
544 ee6847d1 Gerd Hoffmann
545 4af39611 Paul Brook
static void syborg_fb_register_devices(void)
546 4af39611 Paul Brook
{
547 ee6847d1 Gerd Hoffmann
    sysbus_register_withprop(&syborg_fb_info);
548 4af39611 Paul Brook
}
549 4af39611 Paul Brook
550 4af39611 Paul Brook
device_init(syborg_fb_register_devices)