/*
* Arm PrimeCell PL110 Color LCD Controller
*
- * Copyright (c) 2005 CodeSourcery, LLC.
+ * Copyright (c) 2005-2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the GNU LGPL
typedef struct {
uint32_t base;
DisplayState *ds;
- void *pic;
+ /* The Versatile/PB uses a slightly modified PL110 controller. */
+ int versatile;
uint32_t timing[4];
uint32_t cr;
uint32_t upbase;
int invalidate;
uint32_t pallette[256];
uint32_t raw_pallette[128];
- int irq;
+ qemu_irq irq;
} pl110_state;
static const unsigned char pl110_id[] =
{ 0x10, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
+/* The Arm documentation (DDI0224C) says the CLDC on the Versatile board
+ has a different ID. However Linux only looks for the normal ID. */
+#if 0
+static const unsigned char pl110_versatile_id[] =
+{ 0x93, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
+#else
+#define pl110_versatile_id pl110_id
+#endif
+
static inline uint32_t rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
{
return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
return (s->cr & PL110_CR_EN) && (s->cr & PL110_CR_PWR);
}
-void pl110_update_display(void *opaque)
+static void pl110_update_display(void *opaque)
{
pl110_state *s = (pl110_state *)opaque;
drawfn* fntable;
int src_width;
uint8_t *dest;
uint8_t *src;
- int first, last;
+ int first, last = 0;
int dirty, new_dirty;
int i;
return;
switch (s->ds->depth) {
+ case 0:
+ return;
case 8:
fntable = pl110_draw_fn_8;
dest_width = 1;
dest_width = 4;
break;
default:
- fprintf(stderr, "qemu: Bad color depth\n");
+ fprintf(stderr, "pl110: Bad color depth\n");
exit(1);
}
if (s->cr & PL110_CR_BEBO)
addr = base;
dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG);
+ new_dirty = dirty;
for (i = 0; i < s->rows; i++) {
- new_dirty = 0;
- if ((addr & TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
+ if ((addr & ~TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
uint32_t tmp;
+ new_dirty = 0;
for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) {
new_dirty |= cpu_physical_memory_get_dirty(addr + tmp,
VGA_DIRTY_FLAG);
dpy_update(s->ds, 0, first, s->cols, last - first + 1);
}
-void pl110_invalidate_display(void * opaque)
+static void pl110_invalidate_display(void * opaque)
{
pl110_state *s = (pl110_state *)opaque;
s->invalidate = 1;
{
if (width != s->cols || height != s->rows) {
if (pl110_enabled(s)) {
- dpy_resize(s->ds, s->cols, s->rows);
+ dpy_resize(s->ds, width, height);
}
}
s->cols = width;
offset -= s->base;
if (offset >= 0xfe0 && offset < 0x1000) {
- return pl110_id[(offset - 0xfe0) >> 2];
+ if (s->versatile)
+ return pl110_versatile_id[(offset - 0xfe0) >> 2];
+ else
+ return pl110_id[(offset - 0xfe0) >> 2];
}
if (offset >= 0x200 && offset < 0x400) {
return s->raw_pallette[(offset - 0x200) >> 2];
n = (offset - 0x200) >> 2;
s->raw_pallette[(offset - 0x200) >> 2] = val;
pl110_update_pallette(s, n);
+ return;
}
switch (offset >> 2) {
case 0: /* LCDTiming0 */
s->lpbase = val;
break;
case 6: /* LCDIMSC */
+ if (s->versatile)
+ goto control;
+ imsc:
s->int_mask = val;
pl110_update(s);
break;
case 7: /* LCDControl */
+ if (s->versatile)
+ goto imsc;
+ control:
s->cr = val;
s->bpp = (val >> 1) & 7;
if (pl110_enabled(s)) {
pl110_write
};
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq)
+void *pl110_init(DisplayState *ds, uint32_t base, qemu_irq irq,
+ int versatile)
{
pl110_state *s;
int iomemtype;
s = (pl110_state *)qemu_mallocz(sizeof(pl110_state));
iomemtype = cpu_register_io_memory(0, pl110_readfn,
pl110_writefn, s);
- cpu_register_physical_memory(base, 0x007fffff, iomemtype);
+ cpu_register_physical_memory(base, 0x00001000, iomemtype);
s->base = base;
s->ds = ds;
- s->pic = pic;
+ s->versatile = versatile;
s->irq = irq;
+ graphic_console_init(ds, pl110_update_display, pl110_invalidate_display,
+ NULL, s);
/* ??? Save/restore. */
return s;
}