#include "pixel_ops.h"
/* FIXME: For graphic_rotate. Should probably be done in common code. */
#include "sysemu.h"
+#include "framebuffer.h"
-typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int, int);
-
-struct pxa2xx_lcdc_s {
- target_phys_addr_t base;
+struct PXA2xxLCDState {
qemu_irq irq;
int irqlevel;
int up;
uint8_t palette[1024];
uint8_t pbuffer[1024];
- void (*redraw)(struct pxa2xx_lcdc_s *s, uint8_t *fb,
+ void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
int *miny, int *maxy);
target_phys_addr_t descriptor;
int orientation;
};
-struct __attribute__ ((__packed__)) pxa_frame_descriptor_s {
+typedef struct __attribute__ ((__packed__)) {
uint32_t fdaddr;
uint32_t fsaddr;
uint32_t fidr;
uint32_t ldcmd;
-};
+} PXAFrameDescriptor;
#define LCCR0 0x000 /* LCD Controller Control register 0 */
#define LCCR1 0x004 /* LCD Controller Control register 1 */
#define LDCMD_PAL (1 << 26)
/* Route internal interrupt lines to the global IC */
-static void pxa2xx_lcdc_int_update(struct pxa2xx_lcdc_s *s)
+static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
{
int level = 0;
level |= (s->status[0] & LCSR0_LDD) && !(s->control[0] & LCCR0_LDM);
}
/* Set Branch Status interrupt high and poke associated registers */
-static inline void pxa2xx_dma_bs_set(struct pxa2xx_lcdc_s *s, int ch)
+static inline void pxa2xx_dma_bs_set(PXA2xxLCDState *s, int ch)
{
int unmasked;
if (ch == 0) {
}
/* Set Start Of Frame Status interrupt high and poke associated registers */
-static inline void pxa2xx_dma_sof_set(struct pxa2xx_lcdc_s *s, int ch)
+static inline void pxa2xx_dma_sof_set(PXA2xxLCDState *s, int ch)
{
int unmasked;
if (!(s->dma_ch[ch].command & LDCMD_SOFINT))
}
/* Set End Of Frame Status interrupt high and poke associated registers */
-static inline void pxa2xx_dma_eof_set(struct pxa2xx_lcdc_s *s, int ch)
+static inline void pxa2xx_dma_eof_set(PXA2xxLCDState *s, int ch)
{
int unmasked;
if (!(s->dma_ch[ch].command & LDCMD_EOFINT))
}
/* Set Bus Error Status interrupt high and poke associated registers */
-static inline void pxa2xx_dma_ber_set(struct pxa2xx_lcdc_s *s, int ch)
+static inline void pxa2xx_dma_ber_set(PXA2xxLCDState *s, int ch)
{
s->status[0] |= LCSR0_BERCH(ch) | LCSR0_BER;
if (s->irqlevel)
}
/* Set Read Status interrupt high and poke associated registers */
-static inline void pxa2xx_dma_rdst_set(struct pxa2xx_lcdc_s *s)
+static inline void pxa2xx_dma_rdst_set(PXA2xxLCDState *s)
{
s->status[0] |= LCSR0_RDST;
if (s->irqlevel && !(s->control[0] & LCCR0_RDSTM))
}
/* Load new Frame Descriptors from DMA */
-static void pxa2xx_descriptor_load(struct pxa2xx_lcdc_s *s)
+static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
{
- struct pxa_frame_descriptor_s *desc[PXA_LCDDMA_CHANS];
+ PXAFrameDescriptor desc;
target_phys_addr_t descptr;
int i;
for (i = 0; i < PXA_LCDDMA_CHANS; i ++) {
- desc[i] = 0;
s->dma_ch[i].source = 0;
if (!s->dma_ch[i].up)
descptr = s->dma_ch[i].descriptor;
if (!(descptr >= PXA2XX_SDRAM_BASE && descptr +
- sizeof(*desc[i]) <= PXA2XX_SDRAM_BASE + phys_ram_size))
+ sizeof(desc) <= PXA2XX_SDRAM_BASE + ram_size))
continue;
- descptr -= PXA2XX_SDRAM_BASE;
- desc[i] = (struct pxa_frame_descriptor_s *) (phys_ram_base + descptr);
- s->dma_ch[i].descriptor = desc[i]->fdaddr;
- s->dma_ch[i].source = desc[i]->fsaddr;
- s->dma_ch[i].id = desc[i]->fidr;
- s->dma_ch[i].command = desc[i]->ldcmd;
+ cpu_physical_memory_read(descptr, (void *)&desc, sizeof(desc));
+ s->dma_ch[i].descriptor = tswap32(desc.fdaddr);
+ s->dma_ch[i].source = tswap32(desc.fsaddr);
+ s->dma_ch[i].id = tswap32(desc.fidr);
+ s->dma_ch[i].command = tswap32(desc.ldcmd);
}
}
static uint32_t pxa2xx_lcdc_read(void *opaque, target_phys_addr_t offset)
{
- struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
int ch;
- offset -= s->base;
switch (offset) {
case LCCR0:
default:
fail:
- cpu_abort(cpu_single_env,
- "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
+ hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
}
return 0;
static void pxa2xx_lcdc_write(void *opaque,
target_phys_addr_t offset, uint32_t value)
{
- struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
int ch;
- offset -= s->base;
switch (offset) {
case LCCR0:
default:
fail:
- cpu_abort(cpu_single_env,
- "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
+ hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
}
}
-static CPUReadMemoryFunc *pxa2xx_lcdc_readfn[] = {
+static CPUReadMemoryFunc * const pxa2xx_lcdc_readfn[] = {
pxa2xx_lcdc_read,
pxa2xx_lcdc_read,
pxa2xx_lcdc_read
};
-static CPUWriteMemoryFunc *pxa2xx_lcdc_writefn[] = {
+static CPUWriteMemoryFunc * const pxa2xx_lcdc_writefn[] = {
pxa2xx_lcdc_write,
pxa2xx_lcdc_write,
pxa2xx_lcdc_write
};
/* 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)
+static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
{
int i, n, format, r, g, b, alpha;
uint32_t *dest, *src;
}
break;
}
- switch (s->ds->depth) {
+ switch (ds_get_bits_per_pixel(s->ds)) {
case 8:
*dest = rgb_to_pixel8(r, g, b) | alpha;
break;
}
}
-static void pxa2xx_lcdc_dma0_redraw_horiz(struct pxa2xx_lcdc_s *s,
- uint8_t *fb, int *miny, int *maxy)
+static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
+ target_phys_addr_t addr, int *miny, int *maxy)
{
- int y, src_width, dest_width, dirty[2];
- uint8_t *src, *dest;
- ram_addr_t x, addr, new_addr, start, end;
+ int src_width, dest_width;
drawfn fn = 0;
if (s->dest_width)
fn = s->line_fn[s->transp][s->bpp];
if (!fn)
return;
- src = fb;
src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */
if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
src_width *= 3;
else if (s->bpp > pxa_lcdc_8bpp)
src_width *= 2;
- dest = s->ds->data;
dest_width = s->xres * s->dest_width;
-
- addr = (ram_addr_t) (fb - phys_ram_base);
- start = addr + s->yres * src_width;
- end = addr;
- dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG);
- for (y = 0; y < s->yres; y ++) {
- new_addr = addr + src_width;
- for (x = addr + TARGET_PAGE_SIZE; x < new_addr;
- x += TARGET_PAGE_SIZE) {
- dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG);
- dirty[0] |= dirty[1];
- }
- if (dirty[0] || s->invalidated) {
- fn((uint32_t *) s->dma_ch[0].palette,
- dest, src, s->xres, s->dest_width);
- if (addr < start)
- start = addr;
- end = new_addr;
- if (y < *miny)
- *miny = y;
- if (y >= *maxy)
- *maxy = y + 1;
- }
- addr = new_addr;
- dirty[0] = dirty[1];
- src += src_width;
- dest += dest_width;
- }
-
- if (end > start)
- cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
+ *miny = 0;
+ framebuffer_update_display(s->ds,
+ addr, s->xres, s->yres,
+ src_width, dest_width, s->dest_width,
+ s->invalidated,
+ fn, s->dma_ch[0].palette, miny, maxy);
}
-static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s,
- uint8_t *fb, int *miny, int *maxy)
+static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
+ target_phys_addr_t addr, int *miny, int *maxy)
{
- int y, src_width, dest_width, dirty[2];
- uint8_t *src, *dest;
- ram_addr_t x, addr, new_addr, start, end;
+ int src_width, dest_width;
drawfn fn = 0;
if (s->dest_width)
fn = s->line_fn[s->transp][s->bpp];
if (!fn)
return;
- src = fb;
src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */
if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
src_width *= 3;
src_width *= 2;
dest_width = s->yres * s->dest_width;
- dest = s->ds->data + dest_width * (s->xres - 1);
-
- addr = (ram_addr_t) (fb - phys_ram_base);
- start = addr + s->yres * src_width;
- end = addr;
- dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG);
- for (y = 0; y < s->yres; y ++) {
- new_addr = addr + src_width;
- for (x = addr + TARGET_PAGE_SIZE; x < new_addr;
- x += TARGET_PAGE_SIZE) {
- dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG);
- dirty[0] |= dirty[1];
- }
- if (dirty[0] || s->invalidated) {
- fn((uint32_t *) s->dma_ch[0].palette,
- dest, src, s->xres, -dest_width);
- if (addr < start)
- start = addr;
- end = new_addr;
- if (y < *miny)
- *miny = y;
- if (y >= *maxy)
- *maxy = y + 1;
- }
- addr = new_addr;
- dirty[0] = dirty[1];
- src += src_width;
- dest += s->dest_width;
- }
-
- if (end > start)
- cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
+ *miny = 0;
+ framebuffer_update_display(s->ds,
+ addr, s->xres, s->yres,
+ src_width, s->dest_width, -dest_width,
+ s->invalidated,
+ fn, s->dma_ch[0].palette,
+ miny, maxy);
}
-static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s)
+static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
{
int width, height;
if (!(s->control[0] & LCCR0_ENB))
if (width != s->xres || height != s->yres) {
if (s->orientation)
- dpy_resize(s->ds, height, width);
+ qemu_console_resize(s->ds, height, width);
else
- dpy_resize(s->ds, width, height);
+ qemu_console_resize(s->ds, width, height);
s->invalidated = 1;
s->xres = width;
s->yres = height;
static void pxa2xx_update_display(void *opaque)
{
- struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
- uint8_t *fb;
+ PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
target_phys_addr_t fbptr;
int miny, maxy;
int ch;
}
fbptr = s->dma_ch[ch].source;
if (!(fbptr >= PXA2XX_SDRAM_BASE &&
- fbptr <= PXA2XX_SDRAM_BASE + phys_ram_size)) {
+ fbptr <= PXA2XX_SDRAM_BASE + ram_size)) {
pxa2xx_dma_ber_set(s, ch);
continue;
}
- fbptr -= PXA2XX_SDRAM_BASE;
- fb = phys_ram_base + fbptr;
if (s->dma_ch[ch].command & LDCMD_PAL) {
- memcpy(s->dma_ch[ch].pbuffer, fb,
- MAX(LDCMD_LENGTH(s->dma_ch[ch].command),
- sizeof(s->dma_ch[ch].pbuffer)));
+ cpu_physical_memory_read(fbptr, s->dma_ch[ch].pbuffer,
+ MAX(LDCMD_LENGTH(s->dma_ch[ch].command),
+ sizeof(s->dma_ch[ch].pbuffer)));
pxa2xx_palette_parse(s, ch, s->bpp);
} else {
/* Do we need to reparse palette */
/* ACK frame start */
pxa2xx_dma_sof_set(s, ch);
- s->dma_ch[ch].redraw(s, fb, &miny, &maxy);
+ s->dma_ch[ch].redraw(s, fbptr, &miny, &maxy);
s->invalidated = 0;
/* ACK frame completed */
s->status[0] |= LCSR0_LDD;
}
- if (s->orientation)
- dpy_update(s->ds, miny, 0, maxy, s->xres);
- else
- dpy_update(s->ds, 0, miny, s->xres, maxy);
+ if (miny >= 0) {
+ if (s->orientation)
+ dpy_update(s->ds, miny, 0, maxy, s->xres);
+ else
+ dpy_update(s->ds, 0, miny, s->xres, maxy);
+ }
pxa2xx_lcdc_int_update(s);
qemu_irq_raise(s->vsync_cb);
static void pxa2xx_invalidate_display(void *opaque)
{
- struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
s->invalidated = 1;
}
static void pxa2xx_lcdc_orientation(void *opaque, int angle)
{
- struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
if (angle) {
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque)
{
- struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
int i;
qemu_put_be32(f, s->irqlevel);
static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
{
- struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+ PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
int i;
s->irqlevel = qemu_get_be32(f);
#define BITS 32
#include "pxa2xx_template.h"
-struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq,
- DisplayState *ds)
+PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
{
int iomemtype;
- struct pxa2xx_lcdc_s *s;
+ PXA2xxLCDState *s;
- s = (struct pxa2xx_lcdc_s *) qemu_mallocz(sizeof(struct pxa2xx_lcdc_s));
- s->base = base;
+ s = (PXA2xxLCDState *) qemu_mallocz(sizeof(PXA2xxLCDState));
s->invalidated = 1;
s->irq = irq;
- s->ds = ds;
pxa2xx_lcdc_orientation(s, graphic_rotate);
- iomemtype = cpu_register_io_memory(0, pxa2xx_lcdc_readfn,
+ iomemtype = cpu_register_io_memory(pxa2xx_lcdc_readfn,
pxa2xx_lcdc_writefn, s);
cpu_register_physical_memory(base, 0x00100000, iomemtype);
- graphic_console_init(ds, pxa2xx_update_display,
- pxa2xx_invalidate_display, pxa2xx_screen_dump, NULL, s);
+ s->ds = graphic_console_init(pxa2xx_update_display,
+ pxa2xx_invalidate_display,
+ pxa2xx_screen_dump, NULL, s);
- switch (s->ds->depth) {
+ switch (ds_get_bits_per_pixel(s->ds)) {
case 0:
s->dest_width = 0;
break;
return s;
}
-void pxa2xx_lcd_vsync_notifier(struct pxa2xx_lcdc_s *s, qemu_irq handler)
+void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler)
{
s->vsync_cb = handler;
}