qemu/hw/display/pxa2xx_lcd.c
<<
>>
Prefs
   1/*
   2 * Intel XScale PXA255/270 LCDC emulation.
   3 *
   4 * Copyright (c) 2006 Openedhand Ltd.
   5 * Written by Andrzej Zaborowski <balrog@zabor.org>
   6 *
   7 * This code is licensed under the GPLv2.
   8 *
   9 * Contributions after 2012-01-13 are licensed under the terms of the
  10 * GNU GPL, version 2 or (at your option) any later version.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "qemu/log.h"
  15#include "hw/irq.h"
  16#include "migration/vmstate.h"
  17#include "ui/console.h"
  18#include "hw/arm/pxa.h"
  19#include "ui/pixel_ops.h"
  20#include "hw/boards.h"
  21/* FIXME: For graphic_rotate. Should probably be done in common code.  */
  22#include "sysemu/sysemu.h"
  23#include "framebuffer.h"
  24
  25struct DMAChannel {
  26    uint32_t branch;
  27    uint8_t up;
  28    uint8_t palette[1024];
  29    uint8_t pbuffer[1024];
  30    void (*redraw)(PXA2xxLCDState *s, hwaddr addr,
  31                   int *miny, int *maxy);
  32
  33    uint32_t descriptor;
  34    uint32_t source;
  35    uint32_t id;
  36    uint32_t command;
  37};
  38
  39struct PXA2xxLCDState {
  40    MemoryRegion *sysmem;
  41    MemoryRegion iomem;
  42    MemoryRegionSection fbsection;
  43    qemu_irq irq;
  44    int irqlevel;
  45
  46    int invalidated;
  47    QemuConsole *con;
  48    int dest_width;
  49    int xres, yres;
  50    int pal_for;
  51    int transp;
  52    enum {
  53        pxa_lcdc_2bpp = 1,
  54        pxa_lcdc_4bpp = 2,
  55        pxa_lcdc_8bpp = 3,
  56        pxa_lcdc_16bpp = 4,
  57        pxa_lcdc_18bpp = 5,
  58        pxa_lcdc_18pbpp = 6,
  59        pxa_lcdc_19bpp = 7,
  60        pxa_lcdc_19pbpp = 8,
  61        pxa_lcdc_24bpp = 9,
  62        pxa_lcdc_25bpp = 10,
  63    } bpp;
  64
  65    uint32_t control[6];
  66    uint32_t status[2];
  67    uint32_t ovl1c[2];
  68    uint32_t ovl2c[2];
  69    uint32_t ccr;
  70    uint32_t cmdcr;
  71    uint32_t trgbr;
  72    uint32_t tcr;
  73    uint32_t liidr;
  74    uint8_t bscntr;
  75
  76    struct DMAChannel dma_ch[7];
  77
  78    qemu_irq vsync_cb;
  79    int orientation;
  80};
  81
  82typedef struct QEMU_PACKED {
  83    uint32_t fdaddr;
  84    uint32_t fsaddr;
  85    uint32_t fidr;
  86    uint32_t ldcmd;
  87} PXAFrameDescriptor;
  88
  89#define LCCR0   0x000   /* LCD Controller Control register 0 */
  90#define LCCR1   0x004   /* LCD Controller Control register 1 */
  91#define LCCR2   0x008   /* LCD Controller Control register 2 */
  92#define LCCR3   0x00c   /* LCD Controller Control register 3 */
  93#define LCCR4   0x010   /* LCD Controller Control register 4 */
  94#define LCCR5   0x014   /* LCD Controller Control register 5 */
  95
  96#define FBR0    0x020   /* DMA Channel 0 Frame Branch register */
  97#define FBR1    0x024   /* DMA Channel 1 Frame Branch register */
  98#define FBR2    0x028   /* DMA Channel 2 Frame Branch register */
  99#define FBR3    0x02c   /* DMA Channel 3 Frame Branch register */
 100#define FBR4    0x030   /* DMA Channel 4 Frame Branch register */
 101#define FBR5    0x110   /* DMA Channel 5 Frame Branch register */
 102#define FBR6    0x114   /* DMA Channel 6 Frame Branch register */
 103
 104#define LCSR1   0x034   /* LCD Controller Status register 1 */
 105#define LCSR0   0x038   /* LCD Controller Status register 0 */
 106#define LIIDR   0x03c   /* LCD Controller Interrupt ID register */
 107
 108#define TRGBR   0x040   /* TMED RGB Seed register */
 109#define TCR     0x044   /* TMED Control register */
 110
 111#define OVL1C1  0x050   /* Overlay 1 Control register 1 */
 112#define OVL1C2  0x060   /* Overlay 1 Control register 2 */
 113#define OVL2C1  0x070   /* Overlay 2 Control register 1 */
 114#define OVL2C2  0x080   /* Overlay 2 Control register 2 */
 115#define CCR     0x090   /* Cursor Control register */
 116
 117#define CMDCR   0x100   /* Command Control register */
 118#define PRSR    0x104   /* Panel Read Status register */
 119
 120#define PXA_LCDDMA_CHANS        7
 121#define DMA_FDADR               0x00    /* Frame Descriptor Address register */
 122#define DMA_FSADR               0x04    /* Frame Source Address register */
 123#define DMA_FIDR                0x08    /* Frame ID register */
 124#define DMA_LDCMD               0x0c    /* Command register */
 125
 126/* LCD Buffer Strength Control register */
 127#define BSCNTR  0x04000054
 128
 129/* Bitfield masks */
 130#define LCCR0_ENB       (1 << 0)
 131#define LCCR0_CMS       (1 << 1)
 132#define LCCR0_SDS       (1 << 2)
 133#define LCCR0_LDM       (1 << 3)
 134#define LCCR0_SOFM0     (1 << 4)
 135#define LCCR0_IUM       (1 << 5)
 136#define LCCR0_EOFM0     (1 << 6)
 137#define LCCR0_PAS       (1 << 7)
 138#define LCCR0_DPD       (1 << 9)
 139#define LCCR0_DIS       (1 << 10)
 140#define LCCR0_QDM       (1 << 11)
 141#define LCCR0_PDD       (0xff << 12)
 142#define LCCR0_BSM0      (1 << 20)
 143#define LCCR0_OUM       (1 << 21)
 144#define LCCR0_LCDT      (1 << 22)
 145#define LCCR0_RDSTM     (1 << 23)
 146#define LCCR0_CMDIM     (1 << 24)
 147#define LCCR0_OUC       (1 << 25)
 148#define LCCR0_LDDALT    (1 << 26)
 149#define LCCR1_PPL(x)    ((x) & 0x3ff)
 150#define LCCR2_LPP(x)    ((x) & 0x3ff)
 151#define LCCR3_API       (15 << 16)
 152#define LCCR3_BPP(x)    ((((x) >> 24) & 7) | (((x) >> 26) & 8))
 153#define LCCR3_PDFOR(x)  (((x) >> 30) & 3)
 154#define LCCR4_K1(x)     (((x) >> 0) & 7)
 155#define LCCR4_K2(x)     (((x) >> 3) & 7)
 156#define LCCR4_K3(x)     (((x) >> 6) & 7)
 157#define LCCR4_PALFOR(x) (((x) >> 15) & 3)
 158#define LCCR5_SOFM(ch)  (1 << (ch - 1))
 159#define LCCR5_EOFM(ch)  (1 << (ch + 7))
 160#define LCCR5_BSM(ch)   (1 << (ch + 15))
 161#define LCCR5_IUM(ch)   (1 << (ch + 23))
 162#define OVLC1_EN        (1 << 31)
 163#define CCR_CEN         (1 << 31)
 164#define FBR_BRA         (1 << 0)
 165#define FBR_BINT        (1 << 1)
 166#define FBR_SRCADDR     (0xfffffff << 4)
 167#define LCSR0_LDD       (1 << 0)
 168#define LCSR0_SOF0      (1 << 1)
 169#define LCSR0_BER       (1 << 2)
 170#define LCSR0_ABC       (1 << 3)
 171#define LCSR0_IU0       (1 << 4)
 172#define LCSR0_IU1       (1 << 5)
 173#define LCSR0_OU        (1 << 6)
 174#define LCSR0_QD        (1 << 7)
 175#define LCSR0_EOF0      (1 << 8)
 176#define LCSR0_BS0       (1 << 9)
 177#define LCSR0_SINT      (1 << 10)
 178#define LCSR0_RDST      (1 << 11)
 179#define LCSR0_CMDINT    (1 << 12)
 180#define LCSR0_BERCH(x)  (((x) & 7) << 28)
 181#define LCSR1_SOF(ch)   (1 << (ch - 1))
 182#define LCSR1_EOF(ch)   (1 << (ch + 7))
 183#define LCSR1_BS(ch)    (1 << (ch + 15))
 184#define LCSR1_IU(ch)    (1 << (ch + 23))
 185#define LDCMD_LENGTH(x) ((x) & 0x001ffffc)
 186#define LDCMD_EOFINT    (1 << 21)
 187#define LDCMD_SOFINT    (1 << 22)
 188#define LDCMD_PAL       (1 << 26)
 189
 190/* Size of a pixel in the QEMU UI output surface, in bytes */
 191#define DEST_PIXEL_WIDTH 4
 192
 193/* Line drawing code to handle the various possible guest pixel formats */
 194
 195# define SKIP_PIXEL(to) do { to += deststep; } while (0)
 196# define COPY_PIXEL(to, from)    \
 197    do {                         \
 198        *(uint32_t *) to = from; \
 199        SKIP_PIXEL(to);          \
 200    } while (0)
 201
 202#ifdef HOST_WORDS_BIGENDIAN
 203# define SWAP_WORDS 1
 204#endif
 205
 206#define FN_2(x) FN(x + 1) FN(x)
 207#define FN_4(x) FN_2(x + 2) FN_2(x)
 208
 209static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
 210                              int width, int deststep)
 211{
 212    uint32_t *palette = opaque;
 213    uint32_t data;
 214    while (width > 0) {
 215        data = *(uint32_t *) src;
 216#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
 217#ifdef SWAP_WORDS
 218        FN_4(12)
 219        FN_4(8)
 220        FN_4(4)
 221        FN_4(0)
 222#else
 223        FN_4(0)
 224        FN_4(4)
 225        FN_4(8)
 226        FN_4(12)
 227#endif
 228#undef FN
 229        width -= 16;
 230        src += 4;
 231    }
 232}
 233
 234static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
 235                              int width, int deststep)
 236{
 237    uint32_t *palette = opaque;
 238    uint32_t data;
 239    while (width > 0) {
 240        data = *(uint32_t *) src;
 241#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
 242#ifdef SWAP_WORDS
 243        FN_2(6)
 244        FN_2(4)
 245        FN_2(2)
 246        FN_2(0)
 247#else
 248        FN_2(0)
 249        FN_2(2)
 250        FN_2(4)
 251        FN_2(6)
 252#endif
 253#undef FN
 254        width -= 8;
 255        src += 4;
 256    }
 257}
 258
 259static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
 260                              int width, int deststep)
 261{
 262    uint32_t *palette = opaque;
 263    uint32_t data;
 264    while (width > 0) {
 265        data = *(uint32_t *) src;
 266#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
 267#ifdef SWAP_WORDS
 268        FN(24)
 269        FN(16)
 270        FN(8)
 271        FN(0)
 272#else
 273        FN(0)
 274        FN(8)
 275        FN(16)
 276        FN(24)
 277#endif
 278#undef FN
 279        width -= 4;
 280        src += 4;
 281    }
 282}
 283
 284static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
 285                               int width, int deststep)
 286{
 287    uint32_t data;
 288    unsigned int r, g, b;
 289    while (width > 0) {
 290        data = *(uint32_t *) src;
 291#ifdef SWAP_WORDS
 292        data = bswap32(data);
 293#endif
 294        b = (data & 0x1f) << 3;
 295        data >>= 5;
 296        g = (data & 0x3f) << 2;
 297        data >>= 6;
 298        r = (data & 0x1f) << 3;
 299        data >>= 5;
 300        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 301        b = (data & 0x1f) << 3;
 302        data >>= 5;
 303        g = (data & 0x3f) << 2;
 304        data >>= 6;
 305        r = (data & 0x1f) << 3;
 306        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 307        width -= 2;
 308        src += 4;
 309    }
 310}
 311
 312static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
 313                                int width, int deststep)
 314{
 315    uint32_t data;
 316    unsigned int r, g, b;
 317    while (width > 0) {
 318        data = *(uint32_t *) src;
 319#ifdef SWAP_WORDS
 320        data = bswap32(data);
 321#endif
 322        b = (data & 0x1f) << 3;
 323        data >>= 5;
 324        g = (data & 0x1f) << 3;
 325        data >>= 5;
 326        r = (data & 0x1f) << 3;
 327        data >>= 5;
 328        if (data & 1) {
 329            SKIP_PIXEL(dest);
 330        } else {
 331            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 332        }
 333        data >>= 1;
 334        b = (data & 0x1f) << 3;
 335        data >>= 5;
 336        g = (data & 0x1f) << 3;
 337        data >>= 5;
 338        r = (data & 0x1f) << 3;
 339        data >>= 5;
 340        if (data & 1) {
 341            SKIP_PIXEL(dest);
 342        } else {
 343            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 344        }
 345        width -= 2;
 346        src += 4;
 347    }
 348}
 349
 350static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
 351                               int width, int deststep)
 352{
 353    uint32_t data;
 354    unsigned int r, g, b;
 355    while (width > 0) {
 356        data = *(uint32_t *) src;
 357#ifdef SWAP_WORDS
 358        data = bswap32(data);
 359#endif
 360        b = (data & 0x3f) << 2;
 361        data >>= 6;
 362        g = (data & 0x3f) << 2;
 363        data >>= 6;
 364        r = (data & 0x3f) << 2;
 365        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 366        width -= 1;
 367        src += 4;
 368    }
 369}
 370
 371/* The wicked packed format */
 372static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
 373                                int width, int deststep)
 374{
 375    uint32_t data[3];
 376    unsigned int r, g, b;
 377    while (width > 0) {
 378        data[0] = *(uint32_t *) src;
 379        src += 4;
 380        data[1] = *(uint32_t *) src;
 381        src += 4;
 382        data[2] = *(uint32_t *) src;
 383        src += 4;
 384#ifdef SWAP_WORDS
 385        data[0] = bswap32(data[0]);
 386        data[1] = bswap32(data[1]);
 387        data[2] = bswap32(data[2]);
 388#endif
 389        b = (data[0] & 0x3f) << 2;
 390        data[0] >>= 6;
 391        g = (data[0] & 0x3f) << 2;
 392        data[0] >>= 6;
 393        r = (data[0] & 0x3f) << 2;
 394        data[0] >>= 12;
 395        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 396        b = (data[0] & 0x3f) << 2;
 397        data[0] >>= 6;
 398        g = ((data[1] & 0xf) << 4) | (data[0] << 2);
 399        data[1] >>= 4;
 400        r = (data[1] & 0x3f) << 2;
 401        data[1] >>= 12;
 402        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 403        b = (data[1] & 0x3f) << 2;
 404        data[1] >>= 6;
 405        g = (data[1] & 0x3f) << 2;
 406        data[1] >>= 6;
 407        r = ((data[2] & 0x3) << 6) | (data[1] << 2);
 408        data[2] >>= 8;
 409        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 410        b = (data[2] & 0x3f) << 2;
 411        data[2] >>= 6;
 412        g = (data[2] & 0x3f) << 2;
 413        data[2] >>= 6;
 414        r = data[2] << 2;
 415        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 416        width -= 4;
 417    }
 418}
 419
 420static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
 421                               int width, int deststep)
 422{
 423    uint32_t data;
 424    unsigned int r, g, b;
 425    while (width > 0) {
 426        data = *(uint32_t *) src;
 427#ifdef SWAP_WORDS
 428        data = bswap32(data);
 429#endif
 430        b = (data & 0x3f) << 2;
 431        data >>= 6;
 432        g = (data & 0x3f) << 2;
 433        data >>= 6;
 434        r = (data & 0x3f) << 2;
 435        data >>= 6;
 436        if (data & 1) {
 437            SKIP_PIXEL(dest);
 438        } else {
 439            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 440        }
 441        width -= 1;
 442        src += 4;
 443    }
 444}
 445
 446/* The wicked packed format */
 447static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
 448                                int width, int deststep)
 449{
 450    uint32_t data[3];
 451    unsigned int r, g, b;
 452    while (width > 0) {
 453        data[0] = *(uint32_t *) src;
 454        src += 4;
 455        data[1] = *(uint32_t *) src;
 456        src += 4;
 457        data[2] = *(uint32_t *) src;
 458        src += 4;
 459# ifdef SWAP_WORDS
 460        data[0] = bswap32(data[0]);
 461        data[1] = bswap32(data[1]);
 462        data[2] = bswap32(data[2]);
 463# endif
 464        b = (data[0] & 0x3f) << 2;
 465        data[0] >>= 6;
 466        g = (data[0] & 0x3f) << 2;
 467        data[0] >>= 6;
 468        r = (data[0] & 0x3f) << 2;
 469        data[0] >>= 6;
 470        if (data[0] & 1) {
 471            SKIP_PIXEL(dest);
 472        } else {
 473            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 474        }
 475        data[0] >>= 6;
 476        b = (data[0] & 0x3f) << 2;
 477        data[0] >>= 6;
 478        g = ((data[1] & 0xf) << 4) | (data[0] << 2);
 479        data[1] >>= 4;
 480        r = (data[1] & 0x3f) << 2;
 481        data[1] >>= 6;
 482        if (data[1] & 1) {
 483            SKIP_PIXEL(dest);
 484        } else {
 485            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 486        }
 487        data[1] >>= 6;
 488        b = (data[1] & 0x3f) << 2;
 489        data[1] >>= 6;
 490        g = (data[1] & 0x3f) << 2;
 491        data[1] >>= 6;
 492        r = ((data[2] & 0x3) << 6) | (data[1] << 2);
 493        data[2] >>= 2;
 494        if (data[2] & 1) {
 495            SKIP_PIXEL(dest);
 496        } else {
 497            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 498        }
 499        data[2] >>= 6;
 500        b = (data[2] & 0x3f) << 2;
 501        data[2] >>= 6;
 502        g = (data[2] & 0x3f) << 2;
 503        data[2] >>= 6;
 504        r = data[2] << 2;
 505        data[2] >>= 6;
 506        if (data[2] & 1) {
 507            SKIP_PIXEL(dest);
 508        } else {
 509            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 510        }
 511        width -= 4;
 512    }
 513}
 514
 515static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
 516                               int width, int deststep)
 517{
 518    uint32_t data;
 519    unsigned int r, g, b;
 520    while (width > 0) {
 521        data = *(uint32_t *) src;
 522#ifdef SWAP_WORDS
 523        data = bswap32(data);
 524#endif
 525        b = data & 0xff;
 526        data >>= 8;
 527        g = data & 0xff;
 528        data >>= 8;
 529        r = data & 0xff;
 530        COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 531        width -= 1;
 532        src += 4;
 533    }
 534}
 535
 536static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
 537                                int width, int deststep)
 538{
 539    uint32_t data;
 540    unsigned int r, g, b;
 541    while (width > 0) {
 542        data = *(uint32_t *) src;
 543#ifdef SWAP_WORDS
 544        data = bswap32(data);
 545#endif
 546        b = (data & 0x7f) << 1;
 547        data >>= 7;
 548        g = data & 0xff;
 549        data >>= 8;
 550        r = data & 0xff;
 551        data >>= 8;
 552        if (data & 1) {
 553            SKIP_PIXEL(dest);
 554        } else {
 555            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 556        }
 557        width -= 1;
 558        src += 4;
 559    }
 560}
 561
 562static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
 563                               int width, int deststep)
 564{
 565    uint32_t data;
 566    unsigned int r, g, b;
 567    while (width > 0) {
 568        data = *(uint32_t *) src;
 569#ifdef SWAP_WORDS
 570        data = bswap32(data);
 571#endif
 572        b = data & 0xff;
 573        data >>= 8;
 574        g = data & 0xff;
 575        data >>= 8;
 576        r = data & 0xff;
 577        data >>= 8;
 578        if (data & 1) {
 579            SKIP_PIXEL(dest);
 580        } else {
 581            COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
 582        }
 583        width -= 1;
 584        src += 4;
 585    }
 586}
 587
 588/* Overlay planes disabled, no transparency */
 589static drawfn pxa2xx_draw_fn_32[16] = {
 590    [0 ... 0xf]       = NULL,
 591    [pxa_lcdc_2bpp]   = pxa2xx_draw_line2,
 592    [pxa_lcdc_4bpp]   = pxa2xx_draw_line4,
 593    [pxa_lcdc_8bpp]   = pxa2xx_draw_line8,
 594    [pxa_lcdc_16bpp]  = pxa2xx_draw_line16,
 595    [pxa_lcdc_18bpp]  = pxa2xx_draw_line18,
 596    [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
 597    [pxa_lcdc_24bpp]  = pxa2xx_draw_line24,
 598};
 599
 600/* Overlay planes enabled, transparency used */
 601static drawfn pxa2xx_draw_fn_32t[16] = {
 602    [0 ... 0xf]       = NULL,
 603    [pxa_lcdc_4bpp]   = pxa2xx_draw_line4,
 604    [pxa_lcdc_8bpp]   = pxa2xx_draw_line8,
 605    [pxa_lcdc_16bpp]  = pxa2xx_draw_line16t,
 606    [pxa_lcdc_19bpp]  = pxa2xx_draw_line19,
 607    [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
 608    [pxa_lcdc_24bpp]  = pxa2xx_draw_line24t,
 609    [pxa_lcdc_25bpp]  = pxa2xx_draw_line25,
 610};
 611
 612#undef COPY_PIXEL
 613#undef SKIP_PIXEL
 614
 615#ifdef SWAP_WORDS
 616# undef SWAP_WORDS
 617#endif
 618
 619/* Route internal interrupt lines to the global IC */
 620static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
 621{
 622    int level = 0;
 623    level |= (s->status[0] & LCSR0_LDD)    && !(s->control[0] & LCCR0_LDM);
 624    level |= (s->status[0] & LCSR0_SOF0)   && !(s->control[0] & LCCR0_SOFM0);
 625    level |= (s->status[0] & LCSR0_IU0)    && !(s->control[0] & LCCR0_IUM);
 626    level |= (s->status[0] & LCSR0_IU1)    && !(s->control[5] & LCCR5_IUM(1));
 627    level |= (s->status[0] & LCSR0_OU)     && !(s->control[0] & LCCR0_OUM);
 628    level |= (s->status[0] & LCSR0_QD)     && !(s->control[0] & LCCR0_QDM);
 629    level |= (s->status[0] & LCSR0_EOF0)   && !(s->control[0] & LCCR0_EOFM0);
 630    level |= (s->status[0] & LCSR0_BS0)    && !(s->control[0] & LCCR0_BSM0);
 631    level |= (s->status[0] & LCSR0_RDST)   && !(s->control[0] & LCCR0_RDSTM);
 632    level |= (s->status[0] & LCSR0_CMDINT) && !(s->control[0] & LCCR0_CMDIM);
 633    level |= (s->status[1] & ~s->control[5]);
 634
 635    qemu_set_irq(s->irq, !!level);
 636    s->irqlevel = level;
 637}
 638
 639/* Set Branch Status interrupt high and poke associated registers */
 640static inline void pxa2xx_dma_bs_set(PXA2xxLCDState *s, int ch)
 641{
 642    int unmasked;
 643    if (ch == 0) {
 644        s->status[0] |= LCSR0_BS0;
 645        unmasked = !(s->control[0] & LCCR0_BSM0);
 646    } else {
 647        s->status[1] |= LCSR1_BS(ch);
 648        unmasked = !(s->control[5] & LCCR5_BSM(ch));
 649    }
 650
 651    if (unmasked) {
 652        if (s->irqlevel)
 653            s->status[0] |= LCSR0_SINT;
 654        else
 655            s->liidr = s->dma_ch[ch].id;
 656    }
 657}
 658
 659/* Set Start Of Frame Status interrupt high and poke associated registers */
 660static inline void pxa2xx_dma_sof_set(PXA2xxLCDState *s, int ch)
 661{
 662    int unmasked;
 663    if (!(s->dma_ch[ch].command & LDCMD_SOFINT))
 664        return;
 665
 666    if (ch == 0) {
 667        s->status[0] |= LCSR0_SOF0;
 668        unmasked = !(s->control[0] & LCCR0_SOFM0);
 669    } else {
 670        s->status[1] |= LCSR1_SOF(ch);
 671        unmasked = !(s->control[5] & LCCR5_SOFM(ch));
 672    }
 673
 674    if (unmasked) {
 675        if (s->irqlevel)
 676            s->status[0] |= LCSR0_SINT;
 677        else
 678            s->liidr = s->dma_ch[ch].id;
 679    }
 680}
 681
 682/* Set End Of Frame Status interrupt high and poke associated registers */
 683static inline void pxa2xx_dma_eof_set(PXA2xxLCDState *s, int ch)
 684{
 685    int unmasked;
 686    if (!(s->dma_ch[ch].command & LDCMD_EOFINT))
 687        return;
 688
 689    if (ch == 0) {
 690        s->status[0] |= LCSR0_EOF0;
 691        unmasked = !(s->control[0] & LCCR0_EOFM0);
 692    } else {
 693        s->status[1] |= LCSR1_EOF(ch);
 694        unmasked = !(s->control[5] & LCCR5_EOFM(ch));
 695    }
 696
 697    if (unmasked) {
 698        if (s->irqlevel)
 699            s->status[0] |= LCSR0_SINT;
 700        else
 701            s->liidr = s->dma_ch[ch].id;
 702    }
 703}
 704
 705/* Set Bus Error Status interrupt high and poke associated registers */
 706static inline void pxa2xx_dma_ber_set(PXA2xxLCDState *s, int ch)
 707{
 708    s->status[0] |= LCSR0_BERCH(ch) | LCSR0_BER;
 709    if (s->irqlevel)
 710        s->status[0] |= LCSR0_SINT;
 711    else
 712        s->liidr = s->dma_ch[ch].id;
 713}
 714
 715/* Load new Frame Descriptors from DMA */
 716static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
 717{
 718    PXAFrameDescriptor desc;
 719    hwaddr descptr;
 720    int i;
 721
 722    for (i = 0; i < PXA_LCDDMA_CHANS; i ++) {
 723        s->dma_ch[i].source = 0;
 724
 725        if (!s->dma_ch[i].up)
 726            continue;
 727
 728        if (s->dma_ch[i].branch & FBR_BRA) {
 729            descptr = s->dma_ch[i].branch & FBR_SRCADDR;
 730            if (s->dma_ch[i].branch & FBR_BINT)
 731                pxa2xx_dma_bs_set(s, i);
 732            s->dma_ch[i].branch &= ~FBR_BRA;
 733        } else
 734            descptr = s->dma_ch[i].descriptor;
 735
 736        if (!((descptr >= PXA2XX_SDRAM_BASE && descptr +
 737                 sizeof(desc) <= PXA2XX_SDRAM_BASE + current_machine->ram_size) ||
 738                (descptr >= PXA2XX_INTERNAL_BASE && descptr + sizeof(desc) <=
 739                 PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) {
 740            continue;
 741        }
 742
 743        cpu_physical_memory_read(descptr, &desc, sizeof(desc));
 744        s->dma_ch[i].descriptor = le32_to_cpu(desc.fdaddr);
 745        s->dma_ch[i].source = le32_to_cpu(desc.fsaddr);
 746        s->dma_ch[i].id = le32_to_cpu(desc.fidr);
 747        s->dma_ch[i].command = le32_to_cpu(desc.ldcmd);
 748    }
 749}
 750
 751static uint64_t pxa2xx_lcdc_read(void *opaque, hwaddr offset,
 752                                 unsigned size)
 753{
 754    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 755    int ch;
 756
 757    switch (offset) {
 758    case LCCR0:
 759        return s->control[0];
 760    case LCCR1:
 761        return s->control[1];
 762    case LCCR2:
 763        return s->control[2];
 764    case LCCR3:
 765        return s->control[3];
 766    case LCCR4:
 767        return s->control[4];
 768    case LCCR5:
 769        return s->control[5];
 770
 771    case OVL1C1:
 772        return s->ovl1c[0];
 773    case OVL1C2:
 774        return s->ovl1c[1];
 775    case OVL2C1:
 776        return s->ovl2c[0];
 777    case OVL2C2:
 778        return s->ovl2c[1];
 779
 780    case CCR:
 781        return s->ccr;
 782
 783    case CMDCR:
 784        return s->cmdcr;
 785
 786    case TRGBR:
 787        return s->trgbr;
 788    case TCR:
 789        return s->tcr;
 790
 791    case 0x200 ... 0x1000:      /* DMA per-channel registers */
 792        ch = (offset - 0x200) >> 4;
 793        if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS))
 794            goto fail;
 795
 796        switch (offset & 0xf) {
 797        case DMA_FDADR:
 798            return s->dma_ch[ch].descriptor;
 799        case DMA_FSADR:
 800            return s->dma_ch[ch].source;
 801        case DMA_FIDR:
 802            return s->dma_ch[ch].id;
 803        case DMA_LDCMD:
 804            return s->dma_ch[ch].command;
 805        default:
 806            goto fail;
 807        }
 808
 809    case FBR0:
 810        return s->dma_ch[0].branch;
 811    case FBR1:
 812        return s->dma_ch[1].branch;
 813    case FBR2:
 814        return s->dma_ch[2].branch;
 815    case FBR3:
 816        return s->dma_ch[3].branch;
 817    case FBR4:
 818        return s->dma_ch[4].branch;
 819    case FBR5:
 820        return s->dma_ch[5].branch;
 821    case FBR6:
 822        return s->dma_ch[6].branch;
 823
 824    case BSCNTR:
 825        return s->bscntr;
 826
 827    case PRSR:
 828        return 0;
 829
 830    case LCSR0:
 831        return s->status[0];
 832    case LCSR1:
 833        return s->status[1];
 834    case LIIDR:
 835        return s->liidr;
 836
 837    default:
 838    fail:
 839        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
 840                      __func__, offset);
 841    }
 842
 843    return 0;
 844}
 845
 846static void pxa2xx_lcdc_write(void *opaque, hwaddr offset,
 847                              uint64_t value, unsigned size)
 848{
 849    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 850    int ch;
 851
 852    switch (offset) {
 853    case LCCR0:
 854        /* ACK Quick Disable done */
 855        if ((s->control[0] & LCCR0_ENB) && !(value & LCCR0_ENB))
 856            s->status[0] |= LCSR0_QD;
 857
 858        if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT)) {
 859            qemu_log_mask(LOG_UNIMP,
 860                          "%s: internal frame buffer unsupported\n", __func__);
 861        }
 862        if ((s->control[3] & LCCR3_API) &&
 863                (value & LCCR0_ENB) && !(value & LCCR0_LCDT))
 864            s->status[0] |= LCSR0_ABC;
 865
 866        s->control[0] = value & 0x07ffffff;
 867        pxa2xx_lcdc_int_update(s);
 868
 869        s->dma_ch[0].up = !!(value & LCCR0_ENB);
 870        s->dma_ch[1].up = (s->ovl1c[0] & OVLC1_EN) || (value & LCCR0_SDS);
 871        break;
 872
 873    case LCCR1:
 874        s->control[1] = value;
 875        break;
 876
 877    case LCCR2:
 878        s->control[2] = value;
 879        break;
 880
 881    case LCCR3:
 882        s->control[3] = value & 0xefffffff;
 883        s->bpp = LCCR3_BPP(value);
 884        break;
 885
 886    case LCCR4:
 887        s->control[4] = value & 0x83ff81ff;
 888        break;
 889
 890    case LCCR5:
 891        s->control[5] = value & 0x3f3f3f3f;
 892        break;
 893
 894    case OVL1C1:
 895        if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN)) {
 896            qemu_log_mask(LOG_UNIMP, "%s: Overlay 1 not supported\n", __func__);
 897        }
 898        s->ovl1c[0] = value & 0x80ffffff;
 899        s->dma_ch[1].up = (value & OVLC1_EN) || (s->control[0] & LCCR0_SDS);
 900        break;
 901
 902    case OVL1C2:
 903        s->ovl1c[1] = value & 0x000fffff;
 904        break;
 905
 906    case OVL2C1:
 907        if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN)) {
 908            qemu_log_mask(LOG_UNIMP, "%s: Overlay 2 not supported\n", __func__);
 909        }
 910        s->ovl2c[0] = value & 0x80ffffff;
 911        s->dma_ch[2].up = !!(value & OVLC1_EN);
 912        s->dma_ch[3].up = !!(value & OVLC1_EN);
 913        s->dma_ch[4].up = !!(value & OVLC1_EN);
 914        break;
 915
 916    case OVL2C2:
 917        s->ovl2c[1] = value & 0x007fffff;
 918        break;
 919
 920    case CCR:
 921        if (!(s->ccr & CCR_CEN) && (value & CCR_CEN)) {
 922            qemu_log_mask(LOG_UNIMP,
 923                          "%s: Hardware cursor unimplemented\n", __func__);
 924        }
 925        s->ccr = value & 0x81ffffe7;
 926        s->dma_ch[5].up = !!(value & CCR_CEN);
 927        break;
 928
 929    case CMDCR:
 930        s->cmdcr = value & 0xff;
 931        break;
 932
 933    case TRGBR:
 934        s->trgbr = value & 0x00ffffff;
 935        break;
 936
 937    case TCR:
 938        s->tcr = value & 0x7fff;
 939        break;
 940
 941    case 0x200 ... 0x1000:      /* DMA per-channel registers */
 942        ch = (offset - 0x200) >> 4;
 943        if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS))
 944            goto fail;
 945
 946        switch (offset & 0xf) {
 947        case DMA_FDADR:
 948            s->dma_ch[ch].descriptor = value & 0xfffffff0;
 949            break;
 950
 951        default:
 952            goto fail;
 953        }
 954        break;
 955
 956    case FBR0:
 957        s->dma_ch[0].branch = value & 0xfffffff3;
 958        break;
 959    case FBR1:
 960        s->dma_ch[1].branch = value & 0xfffffff3;
 961        break;
 962    case FBR2:
 963        s->dma_ch[2].branch = value & 0xfffffff3;
 964        break;
 965    case FBR3:
 966        s->dma_ch[3].branch = value & 0xfffffff3;
 967        break;
 968    case FBR4:
 969        s->dma_ch[4].branch = value & 0xfffffff3;
 970        break;
 971    case FBR5:
 972        s->dma_ch[5].branch = value & 0xfffffff3;
 973        break;
 974    case FBR6:
 975        s->dma_ch[6].branch = value & 0xfffffff3;
 976        break;
 977
 978    case BSCNTR:
 979        s->bscntr = value & 0xf;
 980        break;
 981
 982    case PRSR:
 983        break;
 984
 985    case LCSR0:
 986        s->status[0] &= ~(value & 0xfff);
 987        if (value & LCSR0_BER)
 988            s->status[0] &= ~LCSR0_BERCH(7);
 989        break;
 990
 991    case LCSR1:
 992        s->status[1] &= ~(value & 0x3e3f3f);
 993        break;
 994
 995    default:
 996    fail:
 997        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
 998                      __func__, offset);
 999    }
1000}
1001
1002static const MemoryRegionOps pxa2xx_lcdc_ops = {
1003    .read = pxa2xx_lcdc_read,
1004    .write = pxa2xx_lcdc_write,
1005    .endianness = DEVICE_NATIVE_ENDIAN,
1006};
1007
1008/* Load new palette for a given DMA channel, convert to internal format */
1009static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
1010{
1011    DisplaySurface *surface = qemu_console_surface(s->con);
1012    int i, n, format, r, g, b, alpha;
1013    uint32_t *dest;
1014    uint8_t *src;
1015    s->pal_for = LCCR4_PALFOR(s->control[4]);
1016    format = s->pal_for;
1017
1018    switch (bpp) {
1019    case pxa_lcdc_2bpp:
1020        n = 4;
1021        break;
1022    case pxa_lcdc_4bpp:
1023        n = 16;
1024        break;
1025    case pxa_lcdc_8bpp:
1026        n = 256;
1027        break;
1028    default:
1029        return;
1030    }
1031
1032    src = (uint8_t *) s->dma_ch[ch].pbuffer;
1033    dest = (uint32_t *) s->dma_ch[ch].palette;
1034    alpha = r = g = b = 0;
1035
1036    for (i = 0; i < n; i ++) {
1037        switch (format) {
1038        case 0: /* 16 bpp, no transparency */
1039            alpha = 0;
1040            if (s->control[0] & LCCR0_CMS) {
1041                r = g = b = *(uint16_t *) src & 0xff;
1042            }
1043            else {
1044                r = (*(uint16_t *) src & 0xf800) >> 8;
1045                g = (*(uint16_t *) src & 0x07e0) >> 3;
1046                b = (*(uint16_t *) src & 0x001f) << 3;
1047            }
1048            src += 2;
1049            break;
1050        case 1: /* 16 bpp plus transparency */
1051            alpha = *(uint32_t *) src & (1 << 24);
1052            if (s->control[0] & LCCR0_CMS)
1053                r = g = b = *(uint32_t *) src & 0xff;
1054            else {
1055                r = (*(uint32_t *) src & 0xf80000) >> 16;
1056                g = (*(uint32_t *) src & 0x00fc00) >> 8;
1057                b = (*(uint32_t *) src & 0x0000f8);
1058            }
1059            src += 4;
1060            break;
1061        case 2: /* 18 bpp plus transparency */
1062            alpha = *(uint32_t *) src & (1 << 24);
1063            if (s->control[0] & LCCR0_CMS)
1064                r = g = b = *(uint32_t *) src & 0xff;
1065            else {
1066                r = (*(uint32_t *) src & 0xfc0000) >> 16;
1067                g = (*(uint32_t *) src & 0x00fc00) >> 8;
1068                b = (*(uint32_t *) src & 0x0000fc);
1069            }
1070            src += 4;
1071            break;
1072        case 3: /* 24 bpp plus transparency */
1073            alpha = *(uint32_t *) src & (1 << 24);
1074            if (s->control[0] & LCCR0_CMS)
1075                r = g = b = *(uint32_t *) src & 0xff;
1076            else {
1077                r = (*(uint32_t *) src & 0xff0000) >> 16;
1078                g = (*(uint32_t *) src & 0x00ff00) >> 8;
1079                b = (*(uint32_t *) src & 0x0000ff);
1080            }
1081            src += 4;
1082            break;
1083        }
1084        switch (surface_bits_per_pixel(surface)) {
1085        case 8:
1086            *dest = rgb_to_pixel8(r, g, b) | alpha;
1087            break;
1088        case 15:
1089            *dest = rgb_to_pixel15(r, g, b) | alpha;
1090            break;
1091        case 16:
1092            *dest = rgb_to_pixel16(r, g, b) | alpha;
1093            break;
1094        case 24:
1095            *dest = rgb_to_pixel24(r, g, b) | alpha;
1096            break;
1097        case 32:
1098            *dest = rgb_to_pixel32(r, g, b) | alpha;
1099            break;
1100        }
1101        dest ++;
1102    }
1103}
1104
1105static inline drawfn pxa2xx_drawfn(PXA2xxLCDState *s)
1106{
1107    if (s->transp) {
1108        return pxa2xx_draw_fn_32t[s->bpp];
1109    } else {
1110        return pxa2xx_draw_fn_32[s->bpp];
1111    }
1112}
1113
1114static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
1115                hwaddr addr, int *miny, int *maxy)
1116{
1117    DisplaySurface *surface = qemu_console_surface(s->con);
1118    int src_width, dest_width;
1119    drawfn fn = pxa2xx_drawfn(s);
1120    if (!fn)
1121        return;
1122
1123    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
1124    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
1125        src_width *= 3;
1126    else if (s->bpp > pxa_lcdc_16bpp)
1127        src_width *= 4;
1128    else if (s->bpp > pxa_lcdc_8bpp)
1129        src_width *= 2;
1130
1131    dest_width = s->xres * DEST_PIXEL_WIDTH;
1132    *miny = 0;
1133    if (s->invalidated) {
1134        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
1135                                          addr, s->yres, src_width);
1136    }
1137    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
1138                               src_width, dest_width, DEST_PIXEL_WIDTH,
1139                               s->invalidated,
1140                               fn, s->dma_ch[0].palette, miny, maxy);
1141}
1142
1143static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
1144               hwaddr addr, int *miny, int *maxy)
1145{
1146    DisplaySurface *surface = qemu_console_surface(s->con);
1147    int src_width, dest_width;
1148    drawfn fn = pxa2xx_drawfn(s);
1149    if (!fn)
1150        return;
1151
1152    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
1153    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
1154        src_width *= 3;
1155    else if (s->bpp > pxa_lcdc_16bpp)
1156        src_width *= 4;
1157    else if (s->bpp > pxa_lcdc_8bpp)
1158        src_width *= 2;
1159
1160    dest_width = s->yres * DEST_PIXEL_WIDTH;
1161    *miny = 0;
1162    if (s->invalidated) {
1163        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
1164                                          addr, s->yres, src_width);
1165    }
1166    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
1167                               src_width, DEST_PIXEL_WIDTH, -dest_width,
1168                               s->invalidated,
1169                               fn, s->dma_ch[0].palette,
1170                               miny, maxy);
1171}
1172
1173static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
1174                hwaddr addr, int *miny, int *maxy)
1175{
1176    DisplaySurface *surface = qemu_console_surface(s->con);
1177    int src_width, dest_width;
1178    drawfn fn = pxa2xx_drawfn(s);
1179    if (!fn) {
1180        return;
1181    }
1182
1183    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
1184    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
1185        src_width *= 3;
1186    } else if (s->bpp > pxa_lcdc_16bpp) {
1187        src_width *= 4;
1188    } else if (s->bpp > pxa_lcdc_8bpp) {
1189        src_width *= 2;
1190    }
1191
1192    dest_width = s->xres * DEST_PIXEL_WIDTH;
1193    *miny = 0;
1194    if (s->invalidated) {
1195        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
1196                                          addr, s->yres, src_width);
1197    }
1198    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
1199                               src_width, -dest_width, -DEST_PIXEL_WIDTH,
1200                               s->invalidated,
1201                               fn, s->dma_ch[0].palette, miny, maxy);
1202}
1203
1204static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
1205               hwaddr addr, int *miny, int *maxy)
1206{
1207    DisplaySurface *surface = qemu_console_surface(s->con);
1208    int src_width, dest_width;
1209    drawfn fn = pxa2xx_drawfn(s);
1210    if (!fn) {
1211        return;
1212    }
1213
1214    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
1215    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
1216        src_width *= 3;
1217    } else if (s->bpp > pxa_lcdc_16bpp) {
1218        src_width *= 4;
1219    } else if (s->bpp > pxa_lcdc_8bpp) {
1220        src_width *= 2;
1221    }
1222
1223    dest_width = s->yres * DEST_PIXEL_WIDTH;
1224    *miny = 0;
1225    if (s->invalidated) {
1226        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
1227                                          addr, s->yres, src_width);
1228    }
1229    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
1230                               src_width, -DEST_PIXEL_WIDTH, dest_width,
1231                               s->invalidated,
1232                               fn, s->dma_ch[0].palette,
1233                               miny, maxy);
1234}
1235
1236static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
1237{
1238    int width, height;
1239    if (!(s->control[0] & LCCR0_ENB))
1240        return;
1241
1242    width = LCCR1_PPL(s->control[1]) + 1;
1243    height = LCCR2_LPP(s->control[2]) + 1;
1244
1245    if (width != s->xres || height != s->yres) {
1246        if (s->orientation == 90 || s->orientation == 270) {
1247            qemu_console_resize(s->con, height, width);
1248        } else {
1249            qemu_console_resize(s->con, width, height);
1250        }
1251        s->invalidated = 1;
1252        s->xres = width;
1253        s->yres = height;
1254    }
1255}
1256
1257static void pxa2xx_update_display(void *opaque)
1258{
1259    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
1260    hwaddr fbptr;
1261    int miny, maxy;
1262    int ch;
1263    if (!(s->control[0] & LCCR0_ENB))
1264        return;
1265
1266    pxa2xx_descriptor_load(s);
1267
1268    pxa2xx_lcdc_resize(s);
1269    miny = s->yres;
1270    maxy = 0;
1271    s->transp = s->dma_ch[2].up || s->dma_ch[3].up;
1272    /* Note: With overlay planes the order depends on LCCR0 bit 25.  */
1273    for (ch = 0; ch < PXA_LCDDMA_CHANS; ch ++)
1274        if (s->dma_ch[ch].up) {
1275            if (!s->dma_ch[ch].source) {
1276                pxa2xx_dma_ber_set(s, ch);
1277                continue;
1278            }
1279            fbptr = s->dma_ch[ch].source;
1280            if (!((fbptr >= PXA2XX_SDRAM_BASE &&
1281                     fbptr <= PXA2XX_SDRAM_BASE + current_machine->ram_size) ||
1282                    (fbptr >= PXA2XX_INTERNAL_BASE &&
1283                     fbptr <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) {
1284                pxa2xx_dma_ber_set(s, ch);
1285                continue;
1286            }
1287
1288            if (s->dma_ch[ch].command & LDCMD_PAL) {
1289                cpu_physical_memory_read(fbptr, s->dma_ch[ch].pbuffer,
1290                    MAX(LDCMD_LENGTH(s->dma_ch[ch].command),
1291                        sizeof(s->dma_ch[ch].pbuffer)));
1292                pxa2xx_palette_parse(s, ch, s->bpp);
1293            } else {
1294                /* Do we need to reparse palette */
1295                if (LCCR4_PALFOR(s->control[4]) != s->pal_for)
1296                    pxa2xx_palette_parse(s, ch, s->bpp);
1297
1298                /* ACK frame start */
1299                pxa2xx_dma_sof_set(s, ch);
1300
1301                s->dma_ch[ch].redraw(s, fbptr, &miny, &maxy);
1302                s->invalidated = 0;
1303
1304                /* ACK frame completed */
1305                pxa2xx_dma_eof_set(s, ch);
1306            }
1307        }
1308
1309    if (s->control[0] & LCCR0_DIS) {
1310        /* ACK last frame completed */
1311        s->control[0] &= ~LCCR0_ENB;
1312        s->status[0] |= LCSR0_LDD;
1313    }
1314
1315    if (miny >= 0) {
1316        switch (s->orientation) {
1317        case 0:
1318            dpy_gfx_update(s->con, 0, miny, s->xres, maxy - miny + 1);
1319            break;
1320        case 90:
1321            dpy_gfx_update(s->con, miny, 0, maxy - miny + 1, s->xres);
1322            break;
1323        case 180:
1324            maxy = s->yres - maxy - 1;
1325            miny = s->yres - miny - 1;
1326            dpy_gfx_update(s->con, 0, maxy, s->xres, miny - maxy + 1);
1327            break;
1328        case 270:
1329            maxy = s->yres - maxy - 1;
1330            miny = s->yres - miny - 1;
1331            dpy_gfx_update(s->con, maxy, 0, miny - maxy + 1, s->xres);
1332            break;
1333        }
1334    }
1335    pxa2xx_lcdc_int_update(s);
1336
1337    qemu_irq_raise(s->vsync_cb);
1338}
1339
1340static void pxa2xx_invalidate_display(void *opaque)
1341{
1342    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
1343    s->invalidated = 1;
1344}
1345
1346static void pxa2xx_lcdc_orientation(void *opaque, int angle)
1347{
1348    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
1349
1350    switch (angle) {
1351    case 0:
1352        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
1353        break;
1354    case 90:
1355        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90;
1356        break;
1357    case 180:
1358        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180;
1359        break;
1360    case 270:
1361        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270;
1362        break;
1363    }
1364
1365    s->orientation = angle;
1366    s->xres = s->yres = -1;
1367    pxa2xx_lcdc_resize(s);
1368}
1369
1370static const VMStateDescription vmstate_dma_channel = {
1371    .name = "dma_channel",
1372    .version_id = 0,
1373    .minimum_version_id = 0,
1374    .fields = (VMStateField[]) {
1375        VMSTATE_UINT32(branch, struct DMAChannel),
1376        VMSTATE_UINT8(up, struct DMAChannel),
1377        VMSTATE_BUFFER(pbuffer, struct DMAChannel),
1378        VMSTATE_UINT32(descriptor, struct DMAChannel),
1379        VMSTATE_UINT32(source, struct DMAChannel),
1380        VMSTATE_UINT32(id, struct DMAChannel),
1381        VMSTATE_UINT32(command, struct DMAChannel),
1382        VMSTATE_END_OF_LIST()
1383    }
1384};
1385
1386static int pxa2xx_lcdc_post_load(void *opaque, int version_id)
1387{
1388    PXA2xxLCDState *s = opaque;
1389
1390    s->bpp = LCCR3_BPP(s->control[3]);
1391    s->xres = s->yres = s->pal_for = -1;
1392
1393    return 0;
1394}
1395
1396static const VMStateDescription vmstate_pxa2xx_lcdc = {
1397    .name = "pxa2xx_lcdc",
1398    .version_id = 0,
1399    .minimum_version_id = 0,
1400    .post_load = pxa2xx_lcdc_post_load,
1401    .fields = (VMStateField[]) {
1402        VMSTATE_INT32(irqlevel, PXA2xxLCDState),
1403        VMSTATE_INT32(transp, PXA2xxLCDState),
1404        VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6),
1405        VMSTATE_UINT32_ARRAY(status, PXA2xxLCDState, 2),
1406        VMSTATE_UINT32_ARRAY(ovl1c, PXA2xxLCDState, 2),
1407        VMSTATE_UINT32_ARRAY(ovl2c, PXA2xxLCDState, 2),
1408        VMSTATE_UINT32(ccr, PXA2xxLCDState),
1409        VMSTATE_UINT32(cmdcr, PXA2xxLCDState),
1410        VMSTATE_UINT32(trgbr, PXA2xxLCDState),
1411        VMSTATE_UINT32(tcr, PXA2xxLCDState),
1412        VMSTATE_UINT32(liidr, PXA2xxLCDState),
1413        VMSTATE_UINT8(bscntr, PXA2xxLCDState),
1414        VMSTATE_STRUCT_ARRAY(dma_ch, PXA2xxLCDState, 7, 0,
1415                             vmstate_dma_channel, struct DMAChannel),
1416        VMSTATE_END_OF_LIST()
1417    }
1418};
1419
1420static const GraphicHwOps pxa2xx_ops = {
1421    .invalidate  = pxa2xx_invalidate_display,
1422    .gfx_update  = pxa2xx_update_display,
1423};
1424
1425PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
1426                                 hwaddr base, qemu_irq irq)
1427{
1428    PXA2xxLCDState *s;
1429
1430    s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
1431    s->invalidated = 1;
1432    s->irq = irq;
1433    s->sysmem = sysmem;
1434
1435    pxa2xx_lcdc_orientation(s, graphic_rotate);
1436
1437    memory_region_init_io(&s->iomem, NULL, &pxa2xx_lcdc_ops, s,
1438                          "pxa2xx-lcd-controller", 0x00100000);
1439    memory_region_add_subregion(sysmem, base, &s->iomem);
1440
1441    s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
1442
1443    vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
1444
1445    return s;
1446}
1447
1448void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler)
1449{
1450    s->vsync_cb = handler;
1451}
1452