* This code is licensed under the GPLv2.
*/
-#include "vl.h"
+#include "hw.h"
+#include "console.h"
+#include "pxa.h"
+#include "pixel_ops.h"
+/* FIXME: For graphic_rotate. Should probably be done in common code. */
+#include "sysemu.h"
typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int, int);
uint32_t command;
} dma_ch[7];
- void (*vsync_cb)(void *opaque);
- void *opaque;
+ qemu_irq vsync_cb;
int orientation;
};
pxa2xx_lcdc_write
};
-static inline
-uint32_t rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
-}
-
-static inline
-uint32_t rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
-}
-
-static inline
-uint32_t rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
-}
-
-static inline
-uint32_t rgb_to_pixel24(unsigned int r, unsigned int g, unsigned b)
-{
- return (r << 16) | (g << 8) | b;
-}
-
-static inline
-uint32_t rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
-{
- return (r << 16) | (g << 8) | b;
-}
-
/* Load new palette for a given DMA channel, convert to internal format */
static void pxa2xx_palette_parse(struct pxa2xx_lcdc_s *s, int ch, int bpp)
{
dest, src, s->xres, -dest_width);
if (addr < start)
start = addr;
- if (new_addr > end)
- end = new_addr;
+ end = new_addr;
if (y < *miny)
*miny = y;
if (y >= *maxy)
dpy_update(s->ds, 0, miny, s->xres, maxy);
pxa2xx_lcdc_int_update(s);
- if (s->vsync_cb)
- s->vsync_cb(s->opaque);
+ qemu_irq_raise(s->vsync_cb);
}
static void pxa2xx_invalidate_display(void *opaque)
/* TODO */
}
-void pxa2xx_lcdc_orientation(void *opaque, int angle)
+static void pxa2xx_lcdc_orientation(void *opaque, int angle)
{
struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
pxa2xx_lcdc_resize(s);
}
+static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque)
+{
+ struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ int i;
+
+ qemu_put_be32(f, s->irqlevel);
+ qemu_put_be32(f, s->transp);
+
+ for (i = 0; i < 6; i ++)
+ qemu_put_be32s(f, &s->control[i]);
+ for (i = 0; i < 2; i ++)
+ qemu_put_be32s(f, &s->status[i]);
+ for (i = 0; i < 2; i ++)
+ qemu_put_be32s(f, &s->ovl1c[i]);
+ for (i = 0; i < 2; i ++)
+ qemu_put_be32s(f, &s->ovl2c[i]);
+ qemu_put_be32s(f, &s->ccr);
+ qemu_put_be32s(f, &s->cmdcr);
+ qemu_put_be32s(f, &s->trgbr);
+ qemu_put_be32s(f, &s->tcr);
+ qemu_put_be32s(f, &s->liidr);
+ qemu_put_8s(f, &s->bscntr);
+
+ for (i = 0; i < 7; i ++) {
+ qemu_put_betl(f, s->dma_ch[i].branch);
+ qemu_put_byte(f, s->dma_ch[i].up);
+ qemu_put_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
+
+ qemu_put_betl(f, s->dma_ch[i].descriptor);
+ qemu_put_betl(f, s->dma_ch[i].source);
+ qemu_put_be32s(f, &s->dma_ch[i].id);
+ qemu_put_be32s(f, &s->dma_ch[i].command);
+ }
+}
+
+static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
+{
+ struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ int i;
+
+ s->irqlevel = qemu_get_be32(f);
+ s->transp = qemu_get_be32(f);
+
+ for (i = 0; i < 6; i ++)
+ qemu_get_be32s(f, &s->control[i]);
+ for (i = 0; i < 2; i ++)
+ qemu_get_be32s(f, &s->status[i]);
+ for (i = 0; i < 2; i ++)
+ qemu_get_be32s(f, &s->ovl1c[i]);
+ for (i = 0; i < 2; i ++)
+ qemu_get_be32s(f, &s->ovl2c[i]);
+ qemu_get_be32s(f, &s->ccr);
+ qemu_get_be32s(f, &s->cmdcr);
+ qemu_get_be32s(f, &s->trgbr);
+ qemu_get_be32s(f, &s->tcr);
+ qemu_get_be32s(f, &s->liidr);
+ qemu_get_8s(f, &s->bscntr);
+
+ for (i = 0; i < 7; i ++) {
+ s->dma_ch[i].branch = qemu_get_betl(f);
+ s->dma_ch[i].up = qemu_get_byte(f);
+ qemu_get_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
+
+ s->dma_ch[i].descriptor = qemu_get_betl(f);
+ s->dma_ch[i].source = qemu_get_betl(f);
+ qemu_get_be32s(f, &s->dma_ch[i].id);
+ qemu_get_be32s(f, &s->dma_ch[i].command);
+ }
+
+ s->bpp = LCCR3_BPP(s->control[3]);
+ s->xres = s->yres = s->pal_for = -1;
+
+ return 0;
+}
+
#define BITS 8
#include "pxa2xx_template.h"
#define BITS 15
iomemtype = cpu_register_io_memory(0, pxa2xx_lcdc_readfn,
pxa2xx_lcdc_writefn, s);
- cpu_register_physical_memory(base, 0x000fffff, iomemtype);
+ cpu_register_physical_memory(base, 0x00100000, iomemtype);
graphic_console_init(ds, pxa2xx_update_display,
pxa2xx_invalidate_display, pxa2xx_screen_dump, s);
fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
exit(1);
}
+
+ register_savevm("pxa2xx_lcdc", 0, 0,
+ pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
+
return s;
}
-void pxa2xx_lcd_vsync_cb(struct pxa2xx_lcdc_s *s,
- void (*cb)(void *opaque), void *opaque) {
- s->vsync_cb = cb;
- s->opaque = opaque;
+void pxa2xx_lcd_vsync_notifier(struct pxa2xx_lcdc_s *s, qemu_irq handler)
+{
+ s->vsync_cb = handler;
}