Commit 9312805d authored by Vasily Khoruzhick's avatar Vasily Khoruzhick Committed by Andrzej Zaborowski
Browse files

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: default avatarVasily Khoruzhick <anarsoul@gmail.com>
Signed-off-by: default avatarAndrzej Zaborowski <andrew.zaborowski@intel.com>
parent 462a8bc6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;

+97 −12
Original line number Diff line number Diff line
@@ -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;
+25 −9
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
    QEMUPutMouseEntry *entry;
    QEMUPutMouseEvent *mouse_event;
    void *mouse_event_opaque;
    int width;
    int width, height;

    if (QTAILQ_EMPTY(&mouse_handlers)) {
        return;
@@ -160,15 +160,31 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
    mouse_event_opaque = entry->qemu_put_mouse_event_opaque;

    if (mouse_event) {
        if (graphic_rotate) {
        if (entry->qemu_put_mouse_event_absolute) {
            width = 0x7fff;
            height = 0x7fff;
        } else {
            width = graphic_width - 1;
            height = graphic_height - 1;
        }
            mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state);
        } else {
            mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);

        switch (graphic_rotate) {
        case 0:
            mouse_event(mouse_event_opaque,
                        dx, dy, dz, buttons_state);
            break;
        case 90:
            mouse_event(mouse_event_opaque,
                        width - dy, dx, dz, buttons_state);
            break;
        case 180:
            mouse_event(mouse_event_opaque,
                        width - dx, height - dy, dz, buttons_state);
            break;
        case 270:
            mouse_event(mouse_event_opaque,
                        dy, height - dx, dz, buttons_state);
            break;
        }
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -787,6 +787,15 @@ STEXI
Rotate graphical output 90 deg left (only PXA LCD).
ETEXI

DEF("rotate", HAS_ARG, QEMU_OPTION_rotate,
    "-rotate <deg>   rotate graphical output some deg left (only PXA LCD)\n",
    QEMU_ARCH_ALL)
STEXI
@item -rotate
@findex -rotate
Rotate graphical output some deg left (only PXA LCD).
ETEXI

DEF("vga", HAS_ARG, QEMU_OPTION_vga,
    "-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
    "                select video card type\n", QEMU_ARCH_ALL)
+10 −1
Original line number Diff line number Diff line
@@ -2300,7 +2300,16 @@ int main(int argc, char **argv, char **envp)
#endif
                break;
            case QEMU_OPTION_portrait:
                graphic_rotate = 1;
                graphic_rotate = 90;
                break;
            case QEMU_OPTION_rotate:
                graphic_rotate = strtol(optarg, (char **) &optarg, 10);
                if (graphic_rotate != 0 && graphic_rotate != 90 &&
                    graphic_rotate != 180 && graphic_rotate != 270) {
                    fprintf(stderr,
                        "qemu: only 90, 180, 270 deg rotation is available\n");
                    exit(1);
                }
                break;
            case QEMU_OPTION_kernel:
                kernel_filename = optarg;