Statistics
| Branch: | Revision:

root / hw / syborg_fb.c @ cde844fa

History | View | Annotate | Download (13.3 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 0520a049 Benoît Canet
    MemoryRegion iomem;
69 4af39611 Paul Brook
    DisplayState *ds;
70 4af39611 Paul Brook
    /*QEMUConsole *console;*/
71 4af39611 Paul Brook
    uint32_t need_update : 1;
72 4af39611 Paul Brook
    uint32_t need_int : 1;
73 4af39611 Paul Brook
    uint32_t enabled : 1;
74 4af39611 Paul Brook
    uint32_t int_status;
75 4af39611 Paul Brook
    uint32_t int_enable;
76 4af39611 Paul Brook
    qemu_irq irq;
77 4af39611 Paul Brook
78 4af39611 Paul Brook
    uint32_t base;
79 4af39611 Paul Brook
    uint32_t pitch;
80 ee6847d1 Gerd Hoffmann
    uint32_t rows;
81 ee6847d1 Gerd Hoffmann
    uint32_t cols;
82 4af39611 Paul Brook
    int blank;
83 4af39611 Paul Brook
    int bpp;
84 4af39611 Paul Brook
    int rgb; /* 0 = BGR, 1 = RGB */
85 4af39611 Paul Brook
    int endian; /* 0 = Little, 1 = Big */
86 4af39611 Paul Brook
    uint32_t raw_palette[256];
87 4af39611 Paul Brook
    uint32_t palette[256];
88 4af39611 Paul Brook
} SyborgFBState;
89 4af39611 Paul Brook
90 4af39611 Paul Brook
enum {
91 4af39611 Paul Brook
    BPP_SRC_1,
92 4af39611 Paul Brook
    BPP_SRC_2,
93 4af39611 Paul Brook
    BPP_SRC_4,
94 4af39611 Paul Brook
    BPP_SRC_8,
95 4af39611 Paul Brook
    BPP_SRC_16,
96 4af39611 Paul Brook
    BPP_SRC_32,
97 4af39611 Paul Brook
    /* TODO: Implement these.  */
98 4af39611 Paul Brook
    BPP_SRC_15 = -1,
99 4af39611 Paul Brook
    BPP_SRC_24 = -2
100 4af39611 Paul Brook
};
101 4af39611 Paul Brook
102 4af39611 Paul Brook
#include "pixel_ops.h"
103 4af39611 Paul Brook
104 4af39611 Paul Brook
#define BITS 8
105 4af39611 Paul Brook
#include "pl110_template.h"
106 4af39611 Paul Brook
#define BITS 15
107 4af39611 Paul Brook
#include "pl110_template.h"
108 4af39611 Paul Brook
#define BITS 16
109 4af39611 Paul Brook
#include "pl110_template.h"
110 4af39611 Paul Brook
#define BITS 24
111 4af39611 Paul Brook
#include "pl110_template.h"
112 4af39611 Paul Brook
#define BITS 32
113 4af39611 Paul Brook
#include "pl110_template.h"
114 4af39611 Paul Brook
115 4af39611 Paul Brook
/* Update interrupts.  */
116 4af39611 Paul Brook
static void syborg_fb_update(SyborgFBState *s)
117 4af39611 Paul Brook
{
118 4af39611 Paul Brook
    if ((s->int_status & s->int_enable) != 0) {
119 4af39611 Paul Brook
        DPRINTF("Raise IRQ\n");
120 4af39611 Paul Brook
        qemu_irq_raise(s->irq);
121 4af39611 Paul Brook
    } else {
122 4af39611 Paul Brook
        DPRINTF("Lower IRQ\n");
123 4af39611 Paul Brook
        qemu_irq_lower(s->irq);
124 4af39611 Paul Brook
    }
125 4af39611 Paul Brook
}
126 4af39611 Paul Brook
127 4af39611 Paul Brook
static int syborg_fb_enabled(const SyborgFBState *s)
128 4af39611 Paul Brook
{
129 4af39611 Paul Brook
    return s->enabled;
130 4af39611 Paul Brook
}
131 4af39611 Paul Brook
132 4af39611 Paul Brook
static void syborg_fb_update_palette(SyborgFBState *s)
133 4af39611 Paul Brook
{
134 4af39611 Paul Brook
    int n, i;
135 4af39611 Paul Brook
    uint32_t raw;
136 4af39611 Paul Brook
    unsigned int r, g, b;
137 4af39611 Paul Brook
138 4af39611 Paul Brook
    switch (s->bpp) {
139 4af39611 Paul Brook
    case BPP_SRC_1: n = 2; break;
140 4af39611 Paul Brook
    case BPP_SRC_2: n = 4; break;
141 4af39611 Paul Brook
    case BPP_SRC_4: n = 16; break;
142 4af39611 Paul Brook
    case BPP_SRC_8: n = 256; break;
143 4af39611 Paul Brook
    default: return;
144 4af39611 Paul Brook
    }
145 4af39611 Paul Brook
146 4af39611 Paul Brook
    for (i = 0; i < n; i++) {
147 4af39611 Paul Brook
        raw = s->raw_palette[i];
148 4af39611 Paul Brook
        r = (raw >> 16) & 0xff;
149 4af39611 Paul Brook
        g = (raw >> 8) & 0xff;
150 4af39611 Paul Brook
        b = raw & 0xff;
151 4af39611 Paul Brook
        switch (ds_get_bits_per_pixel(s->ds)) {
152 4af39611 Paul Brook
        case 8:
153 4af39611 Paul Brook
            s->palette[i] = rgb_to_pixel8(r, g, b);
154 4af39611 Paul Brook
            break;
155 4af39611 Paul Brook
        case 15:
156 4af39611 Paul Brook
            s->palette[i] = rgb_to_pixel15(r, g, b);
157 4af39611 Paul Brook
            break;
158 4af39611 Paul Brook
        case 16:
159 4af39611 Paul Brook
            s->palette[i] = rgb_to_pixel16(r, g, b);
160 4af39611 Paul Brook
            break;
161 4af39611 Paul Brook
        case 24:
162 4af39611 Paul Brook
        case 32:
163 4af39611 Paul Brook
            s->palette[i] = rgb_to_pixel32(r, g, b);
164 4af39611 Paul Brook
            break;
165 4af39611 Paul Brook
        default:
166 4af39611 Paul Brook
            abort();
167 4af39611 Paul Brook
        }
168 4af39611 Paul Brook
    }
169 4af39611 Paul Brook
170 4af39611 Paul Brook
}
171 4af39611 Paul Brook
172 4af39611 Paul Brook
static void syborg_fb_update_display(void *opaque)
173 4af39611 Paul Brook
{
174 4af39611 Paul Brook
    SyborgFBState *s = (SyborgFBState *)opaque;
175 4af39611 Paul Brook
    drawfn* fntable;
176 4af39611 Paul Brook
    drawfn fn;
177 4af39611 Paul Brook
    int dest_width;
178 4af39611 Paul Brook
    int src_width;
179 4af39611 Paul Brook
    int bpp_offset;
180 4af39611 Paul Brook
    int first;
181 4af39611 Paul Brook
    int last;
182 4af39611 Paul Brook
183 4af39611 Paul Brook
    if (!syborg_fb_enabled(s))
184 4af39611 Paul Brook
        return;
185 4af39611 Paul Brook
186 4af39611 Paul Brook
    switch (ds_get_bits_per_pixel(s->ds)) {
187 4af39611 Paul Brook
    case 0:
188 4af39611 Paul Brook
        return;
189 4af39611 Paul Brook
    case 8:
190 4af39611 Paul Brook
        fntable = pl110_draw_fn_8;
191 4af39611 Paul Brook
        dest_width = 1;
192 4af39611 Paul Brook
        break;
193 4af39611 Paul Brook
    case 15:
194 4af39611 Paul Brook
        fntable = pl110_draw_fn_15;
195 4af39611 Paul Brook
        dest_width = 2;
196 4af39611 Paul Brook
        break;
197 4af39611 Paul Brook
    case 16:
198 4af39611 Paul Brook
        fntable = pl110_draw_fn_16;
199 4af39611 Paul Brook
        dest_width = 2;
200 4af39611 Paul Brook
        break;
201 4af39611 Paul Brook
    case 24:
202 4af39611 Paul Brook
        fntable = pl110_draw_fn_24;
203 4af39611 Paul Brook
        dest_width = 3;
204 4af39611 Paul Brook
        break;
205 4af39611 Paul Brook
    case 32:
206 4af39611 Paul Brook
        fntable = pl110_draw_fn_32;
207 4af39611 Paul Brook
        dest_width = 4;
208 4af39611 Paul Brook
        break;
209 4af39611 Paul Brook
    default:
210 4af39611 Paul Brook
        fprintf(stderr, "syborg_fb: Bad color depth\n");
211 4af39611 Paul Brook
        exit(1);
212 4af39611 Paul Brook
    }
213 4af39611 Paul Brook
214 4af39611 Paul Brook
    if (s->need_int) {
215 4af39611 Paul Brook
        s->int_status |= FB_INT_BASE_UPDATE_DONE;
216 4af39611 Paul Brook
        syborg_fb_update(s);
217 4af39611 Paul Brook
        s->need_int = 0;
218 4af39611 Paul Brook
    }
219 4af39611 Paul Brook
220 4af39611 Paul Brook
    if (s->rgb) {
221 4fbf5556 Peter Maydell
        bpp_offset = 24;
222 4af39611 Paul Brook
    } else {
223 4af39611 Paul Brook
        bpp_offset = 0;
224 4af39611 Paul Brook
    }
225 4af39611 Paul Brook
    if (s->endian) {
226 4fbf5556 Peter Maydell
        bpp_offset += 8;
227 4fbf5556 Peter Maydell
    }
228 4fbf5556 Peter Maydell
    /* Our bpp constants mostly match the PL110/PL111 but
229 4fbf5556 Peter Maydell
     * not for the 16 bit case
230 4fbf5556 Peter Maydell
     */
231 4fbf5556 Peter Maydell
    switch (s->bpp) {
232 4fbf5556 Peter Maydell
    case BPP_SRC_16:
233 4af39611 Paul Brook
        bpp_offset += 6;
234 4fbf5556 Peter Maydell
        break;
235 4fbf5556 Peter Maydell
    default:
236 4fbf5556 Peter Maydell
        bpp_offset += s->bpp;
237 4af39611 Paul Brook
    }
238 4fbf5556 Peter Maydell
    fn = fntable[bpp_offset];
239 4af39611 Paul Brook
240 4af39611 Paul Brook
    if (s->pitch) {
241 4af39611 Paul Brook
        src_width = s->pitch;
242 4af39611 Paul Brook
    } else {
243 4af39611 Paul Brook
        src_width = s->cols;
244 4af39611 Paul Brook
        switch (s->bpp) {
245 4af39611 Paul Brook
        case BPP_SRC_1:
246 4af39611 Paul Brook
            src_width >>= 3;
247 4af39611 Paul Brook
            break;
248 4af39611 Paul Brook
        case BPP_SRC_2:
249 4af39611 Paul Brook
            src_width >>= 2;
250 4af39611 Paul Brook
            break;
251 4af39611 Paul Brook
        case BPP_SRC_4:
252 4af39611 Paul Brook
            src_width >>= 1;
253 4af39611 Paul Brook
            break;
254 4af39611 Paul Brook
        case BPP_SRC_8:
255 4af39611 Paul Brook
            break;
256 4af39611 Paul Brook
        case BPP_SRC_15:
257 4af39611 Paul Brook
        case BPP_SRC_16:
258 4af39611 Paul Brook
            src_width <<= 1;
259 4af39611 Paul Brook
            break;
260 4af39611 Paul Brook
        case BPP_SRC_24:
261 4af39611 Paul Brook
            src_width *= 3;
262 4af39611 Paul Brook
            break;
263 4af39611 Paul Brook
        case BPP_SRC_32:
264 4af39611 Paul Brook
            src_width <<= 2;
265 4af39611 Paul Brook
            break;
266 4af39611 Paul Brook
        }
267 4af39611 Paul Brook
    }
268 4af39611 Paul Brook
    dest_width *= s->cols;
269 4af39611 Paul Brook
    first = 0;
270 4af39611 Paul Brook
    /* TODO: Implement blanking.  */
271 4af39611 Paul Brook
    if (!s->blank) {
272 4af39611 Paul Brook
        if (s->need_update && s->bpp <= BPP_SRC_8) {
273 4af39611 Paul Brook
            syborg_fb_update_palette(s);
274 4af39611 Paul Brook
        }
275 4af39611 Paul Brook
        framebuffer_update_display(s->ds,
276 4af39611 Paul Brook
                                   s->base, s->cols, s->rows,
277 4af39611 Paul Brook
                                   src_width, dest_width, 0,
278 4af39611 Paul Brook
                                   s->need_update,
279 4af39611 Paul Brook
                                   fn, s->palette,
280 4af39611 Paul Brook
                                   &first, &last);
281 4af39611 Paul Brook
        if (first >= 0) {
282 4af39611 Paul Brook
            dpy_update(s->ds, 0, first, s->cols, last - first + 1);
283 4af39611 Paul Brook
        }
284 4af39611 Paul Brook
285 4af39611 Paul Brook
        s->int_status |= FB_INT_VSYNC;
286 4af39611 Paul Brook
        syborg_fb_update(s);
287 4af39611 Paul Brook
    }
288 4af39611 Paul Brook
289 4af39611 Paul Brook
    s->need_update = 0;
290 4af39611 Paul Brook
}
291 4af39611 Paul Brook
292 4af39611 Paul Brook
static void syborg_fb_invalidate_display(void * opaque)
293 4af39611 Paul Brook
{
294 4af39611 Paul Brook
    SyborgFBState *s = (SyborgFBState *)opaque;
295 4af39611 Paul Brook
    s->need_update = 1;
296 4af39611 Paul Brook
}
297 4af39611 Paul Brook
298 0520a049 Benoît Canet
static uint64_t syborg_fb_read(void *opaque, target_phys_addr_t offset,
299 0520a049 Benoît Canet
                               unsigned size)
300 4af39611 Paul Brook
{
301 4af39611 Paul Brook
    SyborgFBState *s = opaque;
302 4af39611 Paul Brook
303 4af39611 Paul Brook
    DPRINTF("read reg %d\n", (int)offset);
304 4af39611 Paul Brook
    offset &= 0xfff;
305 4af39611 Paul Brook
    switch (offset >> 2) {
306 4af39611 Paul Brook
    case FB_ID:
307 4af39611 Paul Brook
        return SYBORG_ID_FRAMEBUFFER;
308 4af39611 Paul Brook
309 4af39611 Paul Brook
    case FB_BASE:
310 4af39611 Paul Brook
        return s->base;
311 4af39611 Paul Brook
312 4af39611 Paul Brook
    case FB_HEIGHT:
313 4af39611 Paul Brook
        return s->rows;
314 4af39611 Paul Brook
315 4af39611 Paul Brook
    case FB_WIDTH:
316 4af39611 Paul Brook
        return s->cols;
317 4af39611 Paul Brook
318 4af39611 Paul Brook
    case FB_ORIENTATION:
319 4af39611 Paul Brook
        return 0;
320 4af39611 Paul Brook
321 4af39611 Paul Brook
    case FB_BLANK:
322 4af39611 Paul Brook
        return s->blank;
323 4af39611 Paul Brook
324 4af39611 Paul Brook
    case FB_INT_MASK:
325 4af39611 Paul Brook
        return s->int_enable;
326 4af39611 Paul Brook
327 4af39611 Paul Brook
    case FB_INTERRUPT_CAUSE:
328 4af39611 Paul Brook
        return s->int_status;
329 4af39611 Paul Brook
330 4af39611 Paul Brook
    case FB_BPP:
331 4af39611 Paul Brook
        switch (s->bpp) {
332 4af39611 Paul Brook
        case BPP_SRC_1: return 1;
333 4af39611 Paul Brook
        case BPP_SRC_2: return 2;
334 4af39611 Paul Brook
        case BPP_SRC_4: return 4;
335 4af39611 Paul Brook
        case BPP_SRC_8: return 8;
336 4af39611 Paul Brook
        case BPP_SRC_15: return 15;
337 4af39611 Paul Brook
        case BPP_SRC_16: return 16;
338 4af39611 Paul Brook
        case BPP_SRC_24: return 24;
339 4af39611 Paul Brook
        case BPP_SRC_32: return 32;
340 4af39611 Paul Brook
        default: return 0;
341 4af39611 Paul Brook
        }
342 4af39611 Paul Brook
343 4af39611 Paul Brook
    case FB_COLOR_ORDER:
344 4af39611 Paul Brook
        return s->rgb;
345 4af39611 Paul Brook
346 4af39611 Paul Brook
    case FB_BYTE_ORDER:
347 4af39611 Paul Brook
        return s->endian;
348 4af39611 Paul Brook
349 4af39611 Paul Brook
    case FB_PIXEL_ORDER:
350 4af39611 Paul Brook
        return 0;
351 4af39611 Paul Brook
352 4af39611 Paul Brook
    case FB_ROW_PITCH:
353 4af39611 Paul Brook
        return s->pitch;
354 4af39611 Paul Brook
355 4af39611 Paul Brook
    case FB_ENABLED:
356 4af39611 Paul Brook
        return s->enabled;
357 4af39611 Paul Brook
358 4af39611 Paul Brook
    default:
359 4af39611 Paul Brook
        if ((offset >> 2) >= FB_PALETTE_START
360 4af39611 Paul Brook
            && (offset >> 2) <= FB_PALETTE_END) {
361 4af39611 Paul Brook
            return s->raw_palette[(offset >> 2) - FB_PALETTE_START];
362 4af39611 Paul Brook
        } else {
363 4af39611 Paul Brook
            cpu_abort (cpu_single_env, "syborg_fb_read: Bad offset %x\n",
364 4af39611 Paul Brook
                         (int)offset);
365 4af39611 Paul Brook
        }
366 4af39611 Paul Brook
        return 0;
367 4af39611 Paul Brook
    }
368 4af39611 Paul Brook
}
369 4af39611 Paul Brook
370 c227f099 Anthony Liguori
static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
371 0520a049 Benoît Canet
                            uint64_t val, unsigned size)
372 4af39611 Paul Brook
{
373 4af39611 Paul Brook
    SyborgFBState *s = opaque;
374 4af39611 Paul Brook
375 4af39611 Paul Brook
    DPRINTF("write reg %d = %d\n", (int)offset, val);
376 4af39611 Paul Brook
    s->need_update = 1;
377 4af39611 Paul Brook
    offset &= 0xfff;
378 4af39611 Paul Brook
    switch (offset >> 2) {
379 4af39611 Paul Brook
    case FB_BASE:
380 4af39611 Paul Brook
        s->base = val;
381 4af39611 Paul Brook
        s->need_int = 1;
382 4af39611 Paul Brook
        s->need_update = 1;
383 4af39611 Paul Brook
        syborg_fb_update(s);
384 4af39611 Paul Brook
        break;
385 4af39611 Paul Brook
386 4af39611 Paul Brook
    case FB_HEIGHT:
387 4af39611 Paul Brook
        s->rows = val;
388 4af39611 Paul Brook
        break;
389 4af39611 Paul Brook
390 4af39611 Paul Brook
    case FB_WIDTH:
391 4af39611 Paul Brook
        s->cols = val;
392 4af39611 Paul Brook
        break;
393 4af39611 Paul Brook
394 4af39611 Paul Brook
    case FB_ORIENTATION:
395 4af39611 Paul Brook
        /* TODO: Implement rotation.  */
396 4af39611 Paul Brook
        break;
397 4af39611 Paul Brook
398 4af39611 Paul Brook
    case FB_BLANK:
399 4af39611 Paul Brook
        s->blank = val & 1;
400 4af39611 Paul Brook
        break;
401 4af39611 Paul Brook
402 4af39611 Paul Brook
    case FB_INT_MASK:
403 4af39611 Paul Brook
        s->int_enable = val;
404 4af39611 Paul Brook
        syborg_fb_update(s);
405 4af39611 Paul Brook
        break;
406 4af39611 Paul Brook
407 4af39611 Paul Brook
    case FB_INTERRUPT_CAUSE:
408 4af39611 Paul Brook
        s->int_status &= ~val;
409 4af39611 Paul Brook
        syborg_fb_update(s);
410 4af39611 Paul Brook
        break;
411 4af39611 Paul Brook
412 4af39611 Paul Brook
    case FB_BPP:
413 4af39611 Paul Brook
        switch (val) {
414 4af39611 Paul Brook
        case 1: val = BPP_SRC_1; break;
415 4af39611 Paul Brook
        case 2: val = BPP_SRC_2; break;
416 4af39611 Paul Brook
        case 4: val = BPP_SRC_4; break;
417 4af39611 Paul Brook
        case 8: val = BPP_SRC_8; break;
418 4af39611 Paul Brook
        /* case 15: val = BPP_SRC_15; break; */
419 4af39611 Paul Brook
        case 16: val = BPP_SRC_16; break;
420 4af39611 Paul Brook
        /* case 24: val = BPP_SRC_24; break; */
421 4af39611 Paul Brook
        case 32: val = BPP_SRC_32; break;
422 4af39611 Paul Brook
        default: val = s->bpp; break;
423 4af39611 Paul Brook
        }
424 4af39611 Paul Brook
        s->bpp = val;
425 4af39611 Paul Brook
        break;
426 4af39611 Paul Brook
427 4af39611 Paul Brook
    case FB_COLOR_ORDER:
428 4af39611 Paul Brook
        s->rgb = (val != 0);
429 4af39611 Paul Brook
        break;
430 4af39611 Paul Brook
431 4af39611 Paul Brook
    case FB_BYTE_ORDER:
432 4af39611 Paul Brook
        s->endian = (val != 0);
433 4af39611 Paul Brook
        break;
434 4af39611 Paul Brook
435 4af39611 Paul Brook
    case FB_PIXEL_ORDER:
436 4af39611 Paul Brook
        /* TODO: Implement this.  */
437 4af39611 Paul Brook
        break;
438 4af39611 Paul Brook
439 4af39611 Paul Brook
    case FB_ROW_PITCH:
440 4af39611 Paul Brook
        s->pitch = val;
441 4af39611 Paul Brook
        break;
442 4af39611 Paul Brook
443 4af39611 Paul Brook
    case FB_ENABLED:
444 4af39611 Paul Brook
        s->enabled = val;
445 4af39611 Paul Brook
        break;
446 4af39611 Paul Brook
447 4af39611 Paul Brook
    default:
448 4af39611 Paul Brook
        if ((offset >> 2) >= FB_PALETTE_START
449 4af39611 Paul Brook
            && (offset >> 2) <= FB_PALETTE_END) {
450 4af39611 Paul Brook
            s->raw_palette[(offset >> 2) - FB_PALETTE_START] = val;
451 4af39611 Paul Brook
        } else {
452 4af39611 Paul Brook
            cpu_abort (cpu_single_env, "syborg_fb_write: Bad offset %x\n",
453 4af39611 Paul Brook
                      (int)offset);
454 4af39611 Paul Brook
        }
455 4af39611 Paul Brook
        break;
456 4af39611 Paul Brook
    }
457 4af39611 Paul Brook
}
458 4af39611 Paul Brook
459 0520a049 Benoît Canet
static const MemoryRegionOps syborg_fb_ops = {
460 0520a049 Benoît Canet
    .read = syborg_fb_read,
461 0520a049 Benoît Canet
    .write = syborg_fb_write,
462 0520a049 Benoît Canet
    .endianness = DEVICE_NATIVE_ENDIAN,
463 4af39611 Paul Brook
};
464 4af39611 Paul Brook
465 4af39611 Paul Brook
static void syborg_fb_save(QEMUFile *f, void *opaque)
466 4af39611 Paul Brook
{
467 4af39611 Paul Brook
    SyborgFBState *s = opaque;
468 4af39611 Paul Brook
    int i;
469 4af39611 Paul Brook
470 4af39611 Paul Brook
    qemu_put_be32(f, s->need_int);
471 4af39611 Paul Brook
    qemu_put_be32(f, s->int_status);
472 4af39611 Paul Brook
    qemu_put_be32(f, s->int_enable);
473 4af39611 Paul Brook
    qemu_put_be32(f, s->enabled);
474 4af39611 Paul Brook
    qemu_put_be32(f, s->base);
475 4af39611 Paul Brook
    qemu_put_be32(f, s->pitch);
476 4af39611 Paul Brook
    qemu_put_be32(f, s->rows);
477 4af39611 Paul Brook
    qemu_put_be32(f, s->cols);
478 4af39611 Paul Brook
    qemu_put_be32(f, s->bpp);
479 4af39611 Paul Brook
    qemu_put_be32(f, s->rgb);
480 4af39611 Paul Brook
    for (i = 0; i < 256; i++) {
481 4af39611 Paul Brook
        qemu_put_be32(f, s->raw_palette[i]);
482 4af39611 Paul Brook
    }
483 4af39611 Paul Brook
}
484 4af39611 Paul Brook
485 4af39611 Paul Brook
static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id)
486 4af39611 Paul Brook
{
487 4af39611 Paul Brook
    SyborgFBState *s = opaque;
488 4af39611 Paul Brook
    int i;
489 4af39611 Paul Brook
490 4af39611 Paul Brook
    if (version_id != 1)
491 4af39611 Paul Brook
        return -EINVAL;
492 4af39611 Paul Brook
493 4af39611 Paul Brook
    s->need_int = qemu_get_be32(f);
494 4af39611 Paul Brook
    s->int_status = qemu_get_be32(f);
495 4af39611 Paul Brook
    s->int_enable = qemu_get_be32(f);
496 4af39611 Paul Brook
    s->enabled = qemu_get_be32(f);
497 4af39611 Paul Brook
    s->base = qemu_get_be32(f);
498 4af39611 Paul Brook
    s->pitch = qemu_get_be32(f);
499 4af39611 Paul Brook
    s->rows = qemu_get_be32(f);
500 4af39611 Paul Brook
    s->cols = qemu_get_be32(f);
501 4af39611 Paul Brook
    s->bpp = qemu_get_be32(f);
502 4af39611 Paul Brook
    s->rgb = qemu_get_be32(f);
503 4af39611 Paul Brook
    for (i = 0; i < 256; i++) {
504 4af39611 Paul Brook
        s->raw_palette[i] = qemu_get_be32(f);
505 4af39611 Paul Brook
    }
506 4af39611 Paul Brook
    s->need_update = 1;
507 4af39611 Paul Brook
508 4af39611 Paul Brook
    return 0;
509 4af39611 Paul Brook
}
510 4af39611 Paul Brook
511 81a322d4 Gerd Hoffmann
static int syborg_fb_init(SysBusDevice *dev)
512 4af39611 Paul Brook
{
513 4af39611 Paul Brook
    SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
514 4af39611 Paul Brook
515 4af39611 Paul Brook
    sysbus_init_irq(dev, &s->irq);
516 0520a049 Benoît Canet
    memory_region_init_io(&s->iomem, &syborg_fb_ops, s,
517 0520a049 Benoît Canet
                          "framebuffer", 0x1000);
518 0520a049 Benoît Canet
    sysbus_init_mmio_region(dev, &s->iomem);
519 4af39611 Paul Brook
520 4af39611 Paul Brook
    s->ds = graphic_console_init(syborg_fb_update_display,
521 4af39611 Paul Brook
                                 syborg_fb_invalidate_display,
522 4af39611 Paul Brook
                                 NULL, NULL, s);
523 4af39611 Paul Brook
524 ee6847d1 Gerd Hoffmann
    if (s->cols != 0 && s->rows != 0) {
525 ee6847d1 Gerd Hoffmann
        qemu_console_resize(s->ds, s->cols, s->rows);
526 4af39611 Paul Brook
    }
527 4af39611 Paul Brook
528 ee6847d1 Gerd Hoffmann
    if (!s->cols)
529 ee6847d1 Gerd Hoffmann
        s->cols = ds_get_width(s->ds);
530 ee6847d1 Gerd Hoffmann
    if (!s->rows)
531 ee6847d1 Gerd Hoffmann
        s->rows = ds_get_height(s->ds);
532 4af39611 Paul Brook
533 0be71e32 Alex Williamson
    register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1,
534 4af39611 Paul Brook
                    syborg_fb_save, syborg_fb_load, s);
535 81a322d4 Gerd Hoffmann
    return 0;
536 4af39611 Paul Brook
}
537 4af39611 Paul Brook
538 ee6847d1 Gerd Hoffmann
static SysBusDeviceInfo syborg_fb_info = {
539 ee6847d1 Gerd Hoffmann
    .init = syborg_fb_init,
540 ee6847d1 Gerd Hoffmann
    .qdev.name  = "syborg,framebuffer",
541 ee6847d1 Gerd Hoffmann
    .qdev.size  = sizeof(SyborgFBState),
542 ee6847d1 Gerd Hoffmann
    .qdev.props = (Property[]) {
543 c230c4e3 Gerd Hoffmann
        DEFINE_PROP_UINT32("width",  SyborgFBState, cols, 0),
544 c230c4e3 Gerd Hoffmann
        DEFINE_PROP_UINT32("height", SyborgFBState, rows, 0),
545 c230c4e3 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
546 ee6847d1 Gerd Hoffmann
    }
547 ee6847d1 Gerd Hoffmann
};
548 ee6847d1 Gerd Hoffmann
549 4af39611 Paul Brook
static void syborg_fb_register_devices(void)
550 4af39611 Paul Brook
{
551 ee6847d1 Gerd Hoffmann
    sysbus_register_withprop(&syborg_fb_info);
552 4af39611 Paul Brook
}
553 4af39611 Paul Brook
554 4af39611 Paul Brook
device_init(syborg_fb_register_devices)