aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorVasily Khoruzhick <anarsoul@gmail.com>2011-06-17 13:04:36 +0300
committerAndrzej Zaborowski <andrew.zaborowski@intel.com>2011-07-04 22:12:21 +0200
commit9312805d33e8b106bae356d13a8071fb37d75554 (patch)
tree557cb02fdb8e8ff07c75e3b4d5a91f07cd6e5598 /hw
parent462a8bc6468912b79629f20f18798558342ce315 (diff)
pxa2xx_lcd: add proper rotation support
Until now, pxa2xx_lcd only supported 90deg rotation, but some machines (for example Zipit Z2) needs 270deg rotation. Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/framebuffer.c3
-rw-r--r--hw/pxa2xx_lcd.c109
2 files changed, 100 insertions, 12 deletions
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 24cdf25d0b..56cf16e27a 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -78,6 +78,9 @@ void framebuffer_update_display(
dest = ds_get_data(ds);
if (dest_col_pitch < 0)
dest -= dest_col_pitch * (cols - 1);
+ if (dest_row_pitch < 0) {
+ dest -= dest_row_pitch * (rows - 1);
+ }
first = -1;
addr = pd;
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index e5248023f8..a5f8c51169 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -665,7 +665,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
}
}
-static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
+static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
target_phys_addr_t addr, int *miny, int *maxy)
{
int src_width, dest_width;
@@ -692,7 +692,7 @@ static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
fn, s->dma_ch[0].palette, miny, maxy);
}
-static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
+static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
target_phys_addr_t addr, int *miny, int *maxy)
{
int src_width, dest_width;
@@ -720,6 +720,67 @@ static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
miny, maxy);
}
+static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
+ target_phys_addr_t addr, int *miny, int *maxy)
+{
+ int src_width, dest_width;
+ drawfn fn = NULL;
+ if (s->dest_width) {
+ fn = s->line_fn[s->transp][s->bpp];
+ }
+ if (!fn) {
+ return;
+ }
+
+ 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->xres * s->dest_width;
+ *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_rot270(PXA2xxLCDState *s,
+ target_phys_addr_t addr, int *miny, int *maxy)
+{
+ int src_width, dest_width;
+ drawfn fn = NULL;
+ if (s->dest_width) {
+ fn = s->line_fn[s->transp][s->bpp];
+ }
+ if (!fn) {
+ return;
+ }
+
+ 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;
+ *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(PXA2xxLCDState *s)
{
int width, height;
@@ -730,10 +791,11 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
height = LCCR2_LPP(s->control[2]) + 1;
if (width != s->xres || height != s->yres) {
- if (s->orientation)
+ if (s->orientation == 90 || s->orientation == 270) {
qemu_console_resize(s->ds, height, width);
- else
+ } else {
qemu_console_resize(s->ds, width, height);
+ }
s->invalidated = 1;
s->xres = width;
s->yres = height;
@@ -797,10 +859,24 @@ static void pxa2xx_update_display(void *opaque)
}
if (miny >= 0) {
- if (s->orientation)
- dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
- else
- dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
+ switch (s->orientation) {
+ case 0:
+ dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
+ break;
+ case 90:
+ dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
+ break;
+ case 180:
+ maxy = s->yres - maxy - 1;
+ miny = s->yres - miny - 1;
+ dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
+ break;
+ case 270:
+ maxy = s->yres - maxy - 1;
+ miny = s->yres - miny - 1;
+ dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
+ break;
+ }
}
pxa2xx_lcdc_int_update(s);
@@ -822,10 +898,19 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle)
{
PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
- if (angle) {
- s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
- } else {
- s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz;
+ switch (angle) {
+ case 0:
+ s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
+ break;
+ case 90:
+ s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90;
+ break;
+ case 180:
+ s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180;
+ break;
+ case 270:
+ s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270;
+ break;
}
s->orientation = angle;