?? pxa2xx_lcd.c
字號:
case FBR1: s->dma_ch[1].branch = value & 0xfffffff3; break; case FBR2: s->dma_ch[2].branch = value & 0xfffffff3; break; case FBR3: s->dma_ch[3].branch = value & 0xfffffff3; break; case FBR4: s->dma_ch[4].branch = value & 0xfffffff3; break; case FBR5: s->dma_ch[5].branch = value & 0xfffffff3; break; case FBR6: s->dma_ch[6].branch = value & 0xfffffff3; break; case BSCNTR: s->bscntr = value & 0xf; break; case PRSR: break; case LCSR0: s->status[0] &= ~(value & 0xfff); if (value & LCSR0_BER) s->status[0] &= ~LCSR0_BERCH(7); break; case LCSR1: s->status[1] &= ~(value & 0x3e3f3f); break; default: fail: cpu_abort(cpu_single_env, "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); }}static CPUReadMemoryFunc *pxa2xx_lcdc_readfn[] = { pxa2xx_lcdc_read, pxa2xx_lcdc_read, pxa2xx_lcdc_read};static CPUWriteMemoryFunc *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){ int i, n, format, r, g, b, alpha; uint32_t *dest, *src; s->pal_for = LCCR4_PALFOR(s->control[4]); format = s->pal_for; switch (bpp) { case pxa_lcdc_2bpp: n = 4; break; case pxa_lcdc_4bpp: n = 16; break; case pxa_lcdc_8bpp: n = 256; break; default: format = 0; return; } src = (uint32_t *) s->dma_ch[ch].pbuffer; dest = (uint32_t *) s->dma_ch[ch].palette; alpha = r = g = b = 0; for (i = 0; i < n; i ++) { switch (format) { case 0: /* 16 bpp, no transparency */ alpha = 0; if (s->control[0] & LCCR0_CMS) r = g = b = *src & 0xff; else { r = (*src & 0xf800) >> 8; g = (*src & 0x07e0) >> 3; b = (*src & 0x001f) << 3; } break; case 1: /* 16 bpp plus transparency */ alpha = *src & (1 << 24); if (s->control[0] & LCCR0_CMS) r = g = b = *src & 0xff; else { r = (*src & 0xf800) >> 8; g = (*src & 0x07e0) >> 3; b = (*src & 0x001f) << 3; } break; case 2: /* 18 bpp plus transparency */ alpha = *src & (1 << 24); if (s->control[0] & LCCR0_CMS) r = g = b = *src & 0xff; else { r = (*src & 0xf80000) >> 16; g = (*src & 0x00fc00) >> 8; b = (*src & 0x0000f8); } break; case 3: /* 24 bpp plus transparency */ alpha = *src & (1 << 24); if (s->control[0] & LCCR0_CMS) r = g = b = *src & 0xff; else { r = (*src & 0xff0000) >> 16; g = (*src & 0x00ff00) >> 8; b = (*src & 0x0000ff); } break; } switch (s->ds->depth) { case 8: *dest = rgb_to_pixel8(r, g, b) | alpha; break; case 15: *dest = rgb_to_pixel15(r, g, b) | alpha; break; case 16: *dest = rgb_to_pixel16(r, g, b) | alpha; break; case 24: *dest = rgb_to_pixel24(r, g, b) | alpha; break; case 32: *dest = rgb_to_pixel32(r, g, b) | alpha; break; } src ++; dest ++; }}static void pxa2xx_lcdc_dma0_redraw_horiz(struct pxa2xx_lcdc_s *s, uint8_t *fb, 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; 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_16bpp) src_width *= 4; 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);}static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s, uint8_t *fb, 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; 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_16bpp) src_width *= 4; else if (s->bpp > pxa_lcdc_8bpp) 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);}static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s){ int width, height; if (!(s->control[0] & LCCR0_ENB)) return; width = LCCR1_PPL(s->control[1]) + 1; height = LCCR2_LPP(s->control[2]) + 1; if (width != s->xres || height != s->yres) { if (s->orientation) dpy_resize(s->ds, height, width); else dpy_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; target_phys_addr_t fbptr; int miny, maxy; int ch; if (!(s->control[0] & LCCR0_ENB)) return; pxa2xx_descriptor_load(s); pxa2xx_lcdc_resize(s); miny = s->yres; maxy = 0; s->transp = s->dma_ch[2].up || s->dma_ch[3].up; /* Note: With overlay planes the order depends on LCCR0 bit 25. */ for (ch = 0; ch < PXA_LCDDMA_CHANS; ch ++) if (s->dma_ch[ch].up) { if (!s->dma_ch[ch].source) { pxa2xx_dma_ber_set(s, ch); continue; } fbptr = s->dma_ch[ch].source; if (!(fbptr >= PXA2XX_SDRAM_BASE && fbptr <= PXA2XX_SDRAM_BASE + phys_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))); pxa2xx_palette_parse(s, ch, s->bpp); } else { /* Do we need to reparse palette */ if (LCCR4_PALFOR(s->control[4]) != s->pal_for) pxa2xx_palette_parse(s, ch, s->bpp); /* ACK frame start */ pxa2xx_dma_sof_set(s, ch); s->dma_ch[ch].redraw(s, fb, &miny, &maxy); s->invalidated = 0; /* ACK frame completed */ pxa2xx_dma_eof_set(s, ch); } } if (s->control[0] & LCCR0_DIS) { /* ACK last frame completed */ s->control[0] &= ~LCCR0_ENB; 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); 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; s->invalidated = 1;}static void pxa2xx_screen_dump(void *opaque, const char *filename){ /* TODO */}static void pxa2xx_lcdc_orientation(void *opaque, int angle){ struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque; if (angle) { s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert; } else { s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz; } s->orientation = angle; s->xres = s->yres = -1; 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#include "pxa2xx_template.h"#define BITS 16#include "pxa2xx_template.h"#define BITS 24#include "pxa2xx_template.h"#define BITS 32#include "pxa2xx_template.h"struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq, DisplayState *ds){ int iomemtype; struct pxa2xx_lcdc_s *s; s = (struct pxa2xx_lcdc_s *) qemu_mallocz(sizeof(struct pxa2xx_lcdc_s)); s->base = base; s->invalidated = 1; s->irq = irq; s->ds = ds; pxa2xx_lcdc_orientation(s, graphic_rotate); iomemtype = cpu_register_io_memory(0, 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, s); switch (s->ds->depth) { case 0: s->dest_width = 0; break; case 8: s->line_fn[0] = pxa2xx_draw_fn_8; s->line_fn[1] = pxa2xx_draw_fn_8t; s->dest_width = 1; break; case 15: s->line_fn[0] = pxa2xx_draw_fn_15; s->line_fn[1] = pxa2xx_draw_fn_15t; s->dest_width = 2; break; case 16: s->line_fn[0] = pxa2xx_draw_fn_16; s->line_fn[1] = pxa2xx_draw_fn_16t; s->dest_width = 2; break; case 24: s->line_fn[0] = pxa2xx_draw_fn_24; s->line_fn[1] = pxa2xx_draw_fn_24t; s->dest_width = 3; break; case 32: s->line_fn[0] = pxa2xx_draw_fn_32; s->line_fn[1] = pxa2xx_draw_fn_32t; s->dest_width = 4; break; default: 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_notifier(struct pxa2xx_lcdc_s *s, qemu_irq handler){ s->vsync_cb = handler;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -