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 "hw/hw.h"
  14#include "ui/console.h"
  15#include "hw/arm/pxa.h"
  16#include "ui/pixel_ops.h"
  17/* FIXME: For graphic_rotate. Should probably be done in common code.  */
  18#include "sysemu/sysemu.h"
  19#include "framebuffer.h"
  20
  21struct DMAChannel {
  22    uint32_t branch;
  23    uint8_t up;
  24    uint8_t palette[1024];
  25    uint8_t pbuffer[1024];
  26    void (*redraw)(PXA2xxLCDState *s, hwaddr addr,
  27                   int *miny, int *maxy);
  28
  29    uint32_t descriptor;
  30    uint32_t source;
  31    uint32_t id;
  32    uint32_t command;
  33};
  34
  35struct PXA2xxLCDState {
  36    MemoryRegion *sysmem;
  37    MemoryRegion iomem;
  38    MemoryRegionSection fbsection;
  39    qemu_irq irq;
  40    int irqlevel;
  41
  42    int invalidated;
  43    QemuConsole *con;
  44    drawfn *line_fn[2];
  45    int dest_width;
  46    int xres, yres;
  47    int pal_for;
  48    int transp;
  49    enum {
  50        pxa_lcdc_2bpp = 1,
  51        pxa_lcdc_4bpp = 2,
  52        pxa_lcdc_8bpp = 3,
  53        pxa_lcdc_16bpp = 4,
  54        pxa_lcdc_18bpp = 5,
  55        pxa_lcdc_18pbpp = 6,
  56        pxa_lcdc_19bpp = 7,
  57        pxa_lcdc_19pbpp = 8,
  58        pxa_lcdc_24bpp = 9,
  59        pxa_lcdc_25bpp = 10,
  60    } bpp;
  61
  62    uint32_t control[6];
  63    uint32_t status[2];
  64    uint32_t ovl1c[2];
  65    uint32_t ovl2c[2];
  66    uint32_t ccr;
  67    uint32_t cmdcr;
  68    uint32_t trgbr;
  69    uint32_t tcr;
  70    uint32_t liidr;
  71    uint8_t bscntr;
  72
  73    struct DMAChannel dma_ch[7];
  74
  75    qemu_irq vsync_cb;
  76    int orientation;
  77};
  78
  79typedef struct QEMU_PACKED {
  80    uint32_t fdaddr;
  81    uint32_t fsaddr;
  82    uint32_t fidr;
  83    uint32_t ldcmd;
  84} PXAFrameDescriptor;
  85
  86#define LCCR0   0x000   /* LCD Controller Control register 0 */
  87#define LCCR1   0x004   /* LCD Controller Control register 1 */
  88#define LCCR2   0x008   /* LCD Controller Control register 2 */
  89#define LCCR3   0x00c   /* LCD Controller Control register 3 */
  90#define LCCR4   0x010   /* LCD Controller Control register 4 */
  91#define LCCR5   0x014   /* LCD Controller Control register 5 */
  92
  93#define FBR0    0x020   /* DMA Channel 0 Frame Branch register */
  94#define FBR1    0x024   /* DMA Channel 1 Frame Branch register */
  95#define FBR2    0x028   /* DMA Channel 2 Frame Branch register */
  96#define FBR3    0x02c   /* DMA Channel 3 Frame Branch register */
  97#define FBR4    0x030   /* DMA Channel 4 Frame Branch register */
  98#define FBR5    0x110   /* DMA Channel 5 Frame Branch register */
  99#define FBR6    0x114   /* DMA Channel 6 Frame Branch register */
 100
 101#define LCSR1   0x034   /* LCD Controller Status register 1 */
 102#define LCSR0   0x038   /* LCD Controller Status register 0 */
 103#define LIIDR   0x03c   /* LCD Controller Interrupt ID register */
 104
 105#define TRGBR   0x040   /* TMED RGB Seed register */
 106#define TCR     0x044   /* TMED Control register */
 107
 108#define OVL1C1  0x050   /* Overlay 1 Control register 1 */
 109#define OVL1C2  0x060   /* Overlay 1 Control register 2 */
 110#define OVL2C1  0x070   /* Overlay 2 Control register 1 */
 111#define OVL2C2  0x080   /* Overlay 2 Control register 2 */
 112#define CCR     0x090   /* Cursor Control register */
 113
 114#define CMDCR   0x100   /* Command Control register */
 115#define PRSR    0x104   /* Panel Read Status register */
 116
 117#define PXA_LCDDMA_CHANS        7
 118#define DMA_FDADR               0x00    /* Frame Descriptor Address register */
 119#define DMA_FSADR               0x04    /* Frame Source Address register */
 120#define DMA_FIDR                0x08    /* Frame ID register */
 121#define DMA_LDCMD               0x0c    /* Command register */
 122
 123/* LCD Buffer Strength Control register */
 124#define BSCNTR  0x04000054
 125
 126/* Bitfield masks */
 127#define LCCR0_ENB       (1 << 0)
 128#define LCCR0_CMS       (1 << 1)
 129#define LCCR0_SDS       (1 << 2)
 130#define LCCR0_LDM       (1 << 3)
 131#define LCCR0_SOFM0     (1 << 4)
 132#define LCCR0_IUM       (1 << 5)
 133#define LCCR0_EOFM0     (1 << 6)
 134#define LCCR0_PAS       (1 << 7)
 135#define LCCR0_DPD       (1 << 9)
 136#define LCCR0_DIS       (1 << 10)
 137#define LCCR0_QDM       (1 << 11)
 138#define LCCR0_PDD       (0xff << 12)
 139#define LCCR0_BSM0      (1 << 20)
 140#define LCCR0_OUM       (1 << 21)
 141#define LCCR0_LCDT      (1 << 22)
 142#define LCCR0_RDSTM     (1 << 23)
 143#define LCCR0_CMDIM     (1 << 24)
 144#define LCCR0_OUC       (1 << 25)
 145#define LCCR0_LDDALT    (1 << 26)
 146#define LCCR1_PPL(x)    ((x) & 0x3ff)
 147#define LCCR2_LPP(x)    ((x) & 0x3ff)
 148#define LCCR3_API       (15 << 16)
 149#define LCCR3_BPP(x)    ((((x) >> 24) & 7) | (((x) >> 26) & 8))
 150#define LCCR3_PDFOR(x)  (((x) >> 30) & 3)
 151#define LCCR4_K1(x)     (((x) >> 0) & 7)
 152#define LCCR4_K2(x)     (((x) >> 3) & 7)
 153#define LCCR4_K3(x)     (((x) >> 6) & 7)
 154#define LCCR4_PALFOR(x) (((x) >> 15) & 3)
 155#define LCCR5_SOFM(ch)  (1 << (ch - 1))
 156#define LCCR5_EOFM(ch)  (1 << (ch + 7))
 157#define LCCR5_BSM(ch)   (1 << (ch + 15))
 158#define LCCR5_IUM(ch)   (1 << (ch + 23))
 159#define OVLC1_EN        (1 << 31)
 160#define CCR_CEN         (1 << 31)
 161#define FBR_BRA         (1 << 0)
 162#define FBR_BINT        (1 << 1)
 163#define FBR_SRCADDR     (0xfffffff << 4)
 164#define LCSR0_LDD       (1 << 0)
 165#define LCSR0_SOF0      (1 << 1)
 166#define LCSR0_BER       (1 << 2)
 167#define LCSR0_ABC       (1 << 3)
 168#define LCSR0_IU0       (1 << 4)
 169#define LCSR0_IU1       (1 << 5)
 170#define LCSR0_OU        (1 << 6)
 171#define LCSR0_QD        (1 << 7)
 172#define LCSR0_EOF0      (1 << 8)
 173#define LCSR0_BS0       (1 << 9)
 174#define LCSR0_SINT      (1 << 10)
 175#define LCSR0_RDST      (1 << 11)
 176#define LCSR0_CMDINT    (1 << 12)
 177#define LCSR0_BERCH(x)  (((x) & 7) << 28)
 178#define LCSR1_SOF(ch)   (1 << (ch - 1))
 179#define LCSR1_EOF(ch)   (1 << (ch + 7))
 180#define LCSR1_BS(ch)    (1 << (ch + 15))
 181#define LCSR1_IU(ch)    (1 << (ch + 23))
 182#define LDCMD_LENGTH(x) ((x) & 0x001ffffc)
 183#define LDCMD_EOFINT    (1 << 21)
 184#define LDCMD_SOFINT    (1 << 22)
 185#define LDCMD_PAL       (1 << 26)
 186
 187/* Route internal interrupt lines to the global IC */
 188static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
 189{
 190    int level = 0;
 191    level |= (s->status[0] & LCSR0_LDD)    && !(s->control[0] & LCCR0_LDM);
 192    level |= (s->status[0] & LCSR0_SOF0)   && !(s->control[0] & LCCR0_SOFM0);
 193    level |= (s->status[0] & LCSR0_IU0)    && !(s->control[0] & LCCR0_IUM);
 194    level |= (s->status[0] & LCSR0_IU1)    && !(s->control[5] & LCCR5_IUM(1));
 195    level |= (s->status[0] & LCSR0_OU)     && !(s->control[0] & LCCR0_OUM);
 196    level |= (s->status[0] & LCSR0_QD)     && !(s->control[0] & LCCR0_QDM);
 197    level |= (s->status[0] & LCSR0_EOF0)   && !(s->control[0] & LCCR0_EOFM0);
 198    level |= (s->status[0] & LCSR0_BS0)    && !(s->control[0] & LCCR0_BSM0);
 199    level |= (s->status[0] & LCSR0_RDST)   && !(s->control[0] & LCCR0_RDSTM);
 200    level |= (s->status[0] & LCSR0_CMDINT) && !(s->control[0] & LCCR0_CMDIM);
 201    level |= (s->status[1] & ~s->control[5]);
 202
 203    qemu_set_irq(s->irq, !!level);
 204    s->irqlevel = level;
 205}
 206
 207/* Set Branch Status interrupt high and poke associated registers */
 208static inline void pxa2xx_dma_bs_set(PXA2xxLCDState *s, int ch)
 209{
 210    int unmasked;
 211    if (ch == 0) {
 212        s->status[0] |= LCSR0_BS0;
 213        unmasked = !(s->control[0] & LCCR0_BSM0);
 214    } else {
 215        s->status[1] |= LCSR1_BS(ch);
 216        unmasked = !(s->control[5] & LCCR5_BSM(ch));
 217    }
 218
 219    if (unmasked) {
 220        if (s->irqlevel)
 221            s->status[0] |= LCSR0_SINT;
 222        else
 223            s->liidr = s->dma_ch[ch].id;
 224    }
 225}
 226
 227/* Set Start Of Frame Status interrupt high and poke associated registers */
 228static inline void pxa2xx_dma_sof_set(PXA2xxLCDState *s, int ch)
 229{
 230    int unmasked;
 231    if (!(s->dma_ch[ch].command & LDCMD_SOFINT))
 232        return;
 233
 234    if (ch == 0) {
 235        s->status[0] |= LCSR0_SOF0;
 236        unmasked = !(s->control[0] & LCCR0_SOFM0);
 237    } else {
 238        s->status[1] |= LCSR1_SOF(ch);
 239        unmasked = !(s->control[5] & LCCR5_SOFM(ch));
 240    }
 241
 242    if (unmasked) {
 243        if (s->irqlevel)
 244            s->status[0] |= LCSR0_SINT;
 245        else
 246            s->liidr = s->dma_ch[ch].id;
 247    }
 248}
 249
 250/* Set End Of Frame Status interrupt high and poke associated registers */
 251static inline void pxa2xx_dma_eof_set(PXA2xxLCDState *s, int ch)
 252{
 253    int unmasked;
 254    if (!(s->dma_ch[ch].command & LDCMD_EOFINT))
 255        return;
 256
 257    if (ch == 0) {
 258        s->status[0] |= LCSR0_EOF0;
 259        unmasked = !(s->control[0] & LCCR0_EOFM0);
 260    } else {
 261        s->status[1] |= LCSR1_EOF(ch);
 262        unmasked = !(s->control[5] & LCCR5_EOFM(ch));
 263    }
 264
 265    if (unmasked) {
 266        if (s->irqlevel)
 267            s->status[0] |= LCSR0_SINT;
 268        else
 269            s->liidr = s->dma_ch[ch].id;
 270    }
 271}
 272
 273/* Set Bus Error Status interrupt high and poke associated registers */
 274static inline void pxa2xx_dma_ber_set(PXA2xxLCDState *s, int ch)
 275{
 276    s->status[0] |= LCSR0_BERCH(ch) | LCSR0_BER;
 277    if (s->irqlevel)
 278        s->status[0] |= LCSR0_SINT;
 279    else
 280        s->liidr = s->dma_ch[ch].id;
 281}
 282
 283/* Load new Frame Descriptors from DMA */
 284static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
 285{
 286    PXAFrameDescriptor desc;
 287    hwaddr descptr;
 288    int i;
 289
 290    for (i = 0; i < PXA_LCDDMA_CHANS; i ++) {
 291        s->dma_ch[i].source = 0;
 292
 293        if (!s->dma_ch[i].up)
 294            continue;
 295
 296        if (s->dma_ch[i].branch & FBR_BRA) {
 297            descptr = s->dma_ch[i].branch & FBR_SRCADDR;
 298            if (s->dma_ch[i].branch & FBR_BINT)
 299                pxa2xx_dma_bs_set(s, i);
 300            s->dma_ch[i].branch &= ~FBR_BRA;
 301        } else
 302            descptr = s->dma_ch[i].descriptor;
 303
 304        if (!((descptr >= PXA2XX_SDRAM_BASE && descptr +
 305                 sizeof(desc) <= PXA2XX_SDRAM_BASE + ram_size) ||
 306                (descptr >= PXA2XX_INTERNAL_BASE && descptr + sizeof(desc) <=
 307                 PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) {
 308            continue;
 309        }
 310
 311        cpu_physical_memory_read(descptr, &desc, sizeof(desc));
 312        s->dma_ch[i].descriptor = tswap32(desc.fdaddr);
 313        s->dma_ch[i].source = tswap32(desc.fsaddr);
 314        s->dma_ch[i].id = tswap32(desc.fidr);
 315        s->dma_ch[i].command = tswap32(desc.ldcmd);
 316    }
 317}
 318
 319static uint64_t pxa2xx_lcdc_read(void *opaque, hwaddr offset,
 320                                 unsigned size)
 321{
 322    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 323    int ch;
 324
 325    switch (offset) {
 326    case LCCR0:
 327        return s->control[0];
 328    case LCCR1:
 329        return s->control[1];
 330    case LCCR2:
 331        return s->control[2];
 332    case LCCR3:
 333        return s->control[3];
 334    case LCCR4:
 335        return s->control[4];
 336    case LCCR5:
 337        return s->control[5];
 338
 339    case OVL1C1:
 340        return s->ovl1c[0];
 341    case OVL1C2:
 342        return s->ovl1c[1];
 343    case OVL2C1:
 344        return s->ovl2c[0];
 345    case OVL2C2:
 346        return s->ovl2c[1];
 347
 348    case CCR:
 349        return s->ccr;
 350
 351    case CMDCR:
 352        return s->cmdcr;
 353
 354    case TRGBR:
 355        return s->trgbr;
 356    case TCR:
 357        return s->tcr;
 358
 359    case 0x200 ... 0x1000:      /* DMA per-channel registers */
 360        ch = (offset - 0x200) >> 4;
 361        if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS))
 362            goto fail;
 363
 364        switch (offset & 0xf) {
 365        case DMA_FDADR:
 366            return s->dma_ch[ch].descriptor;
 367        case DMA_FSADR:
 368            return s->dma_ch[ch].source;
 369        case DMA_FIDR:
 370            return s->dma_ch[ch].id;
 371        case DMA_LDCMD:
 372            return s->dma_ch[ch].command;
 373        default:
 374            goto fail;
 375        }
 376
 377    case FBR0:
 378        return s->dma_ch[0].branch;
 379    case FBR1:
 380        return s->dma_ch[1].branch;
 381    case FBR2:
 382        return s->dma_ch[2].branch;
 383    case FBR3:
 384        return s->dma_ch[3].branch;
 385    case FBR4:
 386        return s->dma_ch[4].branch;
 387    case FBR5:
 388        return s->dma_ch[5].branch;
 389    case FBR6:
 390        return s->dma_ch[6].branch;
 391
 392    case BSCNTR:
 393        return s->bscntr;
 394
 395    case PRSR:
 396        return 0;
 397
 398    case LCSR0:
 399        return s->status[0];
 400    case LCSR1:
 401        return s->status[1];
 402    case LIIDR:
 403        return s->liidr;
 404
 405    default:
 406    fail:
 407        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
 408    }
 409
 410    return 0;
 411}
 412
 413static void pxa2xx_lcdc_write(void *opaque, hwaddr offset,
 414                              uint64_t value, unsigned size)
 415{
 416    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 417    int ch;
 418
 419    switch (offset) {
 420    case LCCR0:
 421        /* ACK Quick Disable done */
 422        if ((s->control[0] & LCCR0_ENB) && !(value & LCCR0_ENB))
 423            s->status[0] |= LCSR0_QD;
 424
 425        if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT))
 426            printf("%s: internal frame buffer unsupported\n", __FUNCTION__);
 427
 428        if ((s->control[3] & LCCR3_API) &&
 429                (value & LCCR0_ENB) && !(value & LCCR0_LCDT))
 430            s->status[0] |= LCSR0_ABC;
 431
 432        s->control[0] = value & 0x07ffffff;
 433        pxa2xx_lcdc_int_update(s);
 434
 435        s->dma_ch[0].up = !!(value & LCCR0_ENB);
 436        s->dma_ch[1].up = (s->ovl1c[0] & OVLC1_EN) || (value & LCCR0_SDS);
 437        break;
 438
 439    case LCCR1:
 440        s->control[1] = value;
 441        break;
 442
 443    case LCCR2:
 444        s->control[2] = value;
 445        break;
 446
 447    case LCCR3:
 448        s->control[3] = value & 0xefffffff;
 449        s->bpp = LCCR3_BPP(value);
 450        break;
 451
 452    case LCCR4:
 453        s->control[4] = value & 0x83ff81ff;
 454        break;
 455
 456    case LCCR5:
 457        s->control[5] = value & 0x3f3f3f3f;
 458        break;
 459
 460    case OVL1C1:
 461        if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN))
 462            printf("%s: Overlay 1 not supported\n", __FUNCTION__);
 463
 464        s->ovl1c[0] = value & 0x80ffffff;
 465        s->dma_ch[1].up = (value & OVLC1_EN) || (s->control[0] & LCCR0_SDS);
 466        break;
 467
 468    case OVL1C2:
 469        s->ovl1c[1] = value & 0x000fffff;
 470        break;
 471
 472    case OVL2C1:
 473        if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN))
 474            printf("%s: Overlay 2 not supported\n", __FUNCTION__);
 475
 476        s->ovl2c[0] = value & 0x80ffffff;
 477        s->dma_ch[2].up = !!(value & OVLC1_EN);
 478        s->dma_ch[3].up = !!(value & OVLC1_EN);
 479        s->dma_ch[4].up = !!(value & OVLC1_EN);
 480        break;
 481
 482    case OVL2C2:
 483        s->ovl2c[1] = value & 0x007fffff;
 484        break;
 485
 486    case CCR:
 487        if (!(s->ccr & CCR_CEN) && (value & CCR_CEN))
 488            printf("%s: Hardware cursor unimplemented\n", __FUNCTION__);
 489
 490        s->ccr = value & 0x81ffffe7;
 491        s->dma_ch[5].up = !!(value & CCR_CEN);
 492        break;
 493
 494    case CMDCR:
 495        s->cmdcr = value & 0xff;
 496        break;
 497
 498    case TRGBR:
 499        s->trgbr = value & 0x00ffffff;
 500        break;
 501
 502    case TCR:
 503        s->tcr = value & 0x7fff;
 504        break;
 505
 506    case 0x200 ... 0x1000:      /* DMA per-channel registers */
 507        ch = (offset - 0x200) >> 4;
 508        if (!(ch >= 0 && ch < PXA_LCDDMA_CHANS))
 509            goto fail;
 510
 511        switch (offset & 0xf) {
 512        case DMA_FDADR:
 513            s->dma_ch[ch].descriptor = value & 0xfffffff0;
 514            break;
 515
 516        default:
 517            goto fail;
 518        }
 519        break;
 520
 521    case FBR0:
 522        s->dma_ch[0].branch = value & 0xfffffff3;
 523        break;
 524    case FBR1:
 525        s->dma_ch[1].branch = value & 0xfffffff3;
 526        break;
 527    case FBR2:
 528        s->dma_ch[2].branch = value & 0xfffffff3;
 529        break;
 530    case FBR3:
 531        s->dma_ch[3].branch = value & 0xfffffff3;
 532        break;
 533    case FBR4:
 534        s->dma_ch[4].branch = value & 0xfffffff3;
 535        break;
 536    case FBR5:
 537        s->dma_ch[5].branch = value & 0xfffffff3;
 538        break;
 539    case FBR6:
 540        s->dma_ch[6].branch = value & 0xfffffff3;
 541        break;
 542
 543    case BSCNTR:
 544        s->bscntr = value & 0xf;
 545        break;
 546
 547    case PRSR:
 548        break;
 549
 550    case LCSR0:
 551        s->status[0] &= ~(value & 0xfff);
 552        if (value & LCSR0_BER)
 553            s->status[0] &= ~LCSR0_BERCH(7);
 554        break;
 555
 556    case LCSR1:
 557        s->status[1] &= ~(value & 0x3e3f3f);
 558        break;
 559
 560    default:
 561    fail:
 562        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
 563    }
 564}
 565
 566static const MemoryRegionOps pxa2xx_lcdc_ops = {
 567    .read = pxa2xx_lcdc_read,
 568    .write = pxa2xx_lcdc_write,
 569    .endianness = DEVICE_NATIVE_ENDIAN,
 570};
 571
 572/* Load new palette for a given DMA channel, convert to internal format */
 573static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
 574{
 575    DisplaySurface *surface = qemu_console_surface(s->con);
 576    int i, n, format, r, g, b, alpha;
 577    uint32_t *dest;
 578    uint8_t *src;
 579    s->pal_for = LCCR4_PALFOR(s->control[4]);
 580    format = s->pal_for;
 581
 582    switch (bpp) {
 583    case pxa_lcdc_2bpp:
 584        n = 4;
 585        break;
 586    case pxa_lcdc_4bpp:
 587        n = 16;
 588        break;
 589    case pxa_lcdc_8bpp:
 590        n = 256;
 591        break;
 592    default:
 593        format = 0;
 594        return;
 595    }
 596
 597    src = (uint8_t *) s->dma_ch[ch].pbuffer;
 598    dest = (uint32_t *) s->dma_ch[ch].palette;
 599    alpha = r = g = b = 0;
 600
 601    for (i = 0; i < n; i ++) {
 602        switch (format) {
 603        case 0: /* 16 bpp, no transparency */
 604            alpha = 0;
 605            if (s->control[0] & LCCR0_CMS) {
 606                r = g = b = *(uint16_t *) src & 0xff;
 607            }
 608            else {
 609                r = (*(uint16_t *) src & 0xf800) >> 8;
 610                g = (*(uint16_t *) src & 0x07e0) >> 3;
 611                b = (*(uint16_t *) src & 0x001f) << 3;
 612            }
 613            src += 2;
 614            break;
 615        case 1: /* 16 bpp plus transparency */
 616            alpha = *(uint32_t *) src & (1 << 24);
 617            if (s->control[0] & LCCR0_CMS)
 618                r = g = b = *(uint32_t *) src & 0xff;
 619            else {
 620                r = (*(uint32_t *) src & 0xf80000) >> 16;
 621                g = (*(uint32_t *) src & 0x00fc00) >> 8;
 622                b = (*(uint32_t *) src & 0x0000f8);
 623            }
 624            src += 4;
 625            break;
 626        case 2: /* 18 bpp plus transparency */
 627            alpha = *(uint32_t *) src & (1 << 24);
 628            if (s->control[0] & LCCR0_CMS)
 629                r = g = b = *(uint32_t *) src & 0xff;
 630            else {
 631                r = (*(uint32_t *) src & 0xfc0000) >> 16;
 632                g = (*(uint32_t *) src & 0x00fc00) >> 8;
 633                b = (*(uint32_t *) src & 0x0000fc);
 634            }
 635            src += 4;
 636            break;
 637        case 3: /* 24 bpp plus transparency */
 638            alpha = *(uint32_t *) src & (1 << 24);
 639            if (s->control[0] & LCCR0_CMS)
 640                r = g = b = *(uint32_t *) src & 0xff;
 641            else {
 642                r = (*(uint32_t *) src & 0xff0000) >> 16;
 643                g = (*(uint32_t *) src & 0x00ff00) >> 8;
 644                b = (*(uint32_t *) src & 0x0000ff);
 645            }
 646            src += 4;
 647            break;
 648        }
 649        switch (surface_bits_per_pixel(surface)) {
 650        case 8:
 651            *dest = rgb_to_pixel8(r, g, b) | alpha;
 652            break;
 653        case 15:
 654            *dest = rgb_to_pixel15(r, g, b) | alpha;
 655            break;
 656        case 16:
 657            *dest = rgb_to_pixel16(r, g, b) | alpha;
 658            break;
 659        case 24:
 660            *dest = rgb_to_pixel24(r, g, b) | alpha;
 661            break;
 662        case 32:
 663            *dest = rgb_to_pixel32(r, g, b) | alpha;
 664            break;
 665        }
 666        dest ++;
 667    }
 668}
 669
 670static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
 671                hwaddr addr, int *miny, int *maxy)
 672{
 673    DisplaySurface *surface = qemu_console_surface(s->con);
 674    int src_width, dest_width;
 675    drawfn fn = NULL;
 676    if (s->dest_width)
 677        fn = s->line_fn[s->transp][s->bpp];
 678    if (!fn)
 679        return;
 680
 681    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
 682    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
 683        src_width *= 3;
 684    else if (s->bpp > pxa_lcdc_16bpp)
 685        src_width *= 4;
 686    else if (s->bpp > pxa_lcdc_8bpp)
 687        src_width *= 2;
 688
 689    dest_width = s->xres * s->dest_width;
 690    *miny = 0;
 691    if (s->invalidated) {
 692        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
 693                                          addr, s->yres, src_width);
 694    }
 695    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
 696                               src_width, dest_width, s->dest_width,
 697                               s->invalidated,
 698                               fn, s->dma_ch[0].palette, miny, maxy);
 699}
 700
 701static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
 702               hwaddr addr, int *miny, int *maxy)
 703{
 704    DisplaySurface *surface = qemu_console_surface(s->con);
 705    int src_width, dest_width;
 706    drawfn fn = NULL;
 707    if (s->dest_width)
 708        fn = s->line_fn[s->transp][s->bpp];
 709    if (!fn)
 710        return;
 711
 712    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
 713    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp)
 714        src_width *= 3;
 715    else if (s->bpp > pxa_lcdc_16bpp)
 716        src_width *= 4;
 717    else if (s->bpp > pxa_lcdc_8bpp)
 718        src_width *= 2;
 719
 720    dest_width = s->yres * s->dest_width;
 721    *miny = 0;
 722    if (s->invalidated) {
 723        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
 724                                          addr, s->yres, src_width);
 725    }
 726    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
 727                               src_width, s->dest_width, -dest_width,
 728                               s->invalidated,
 729                               fn, s->dma_ch[0].palette,
 730                               miny, maxy);
 731}
 732
 733static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
 734                hwaddr addr, int *miny, int *maxy)
 735{
 736    DisplaySurface *surface = qemu_console_surface(s->con);
 737    int src_width, dest_width;
 738    drawfn fn = NULL;
 739    if (s->dest_width) {
 740        fn = s->line_fn[s->transp][s->bpp];
 741    }
 742    if (!fn) {
 743        return;
 744    }
 745
 746    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
 747    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
 748        src_width *= 3;
 749    } else if (s->bpp > pxa_lcdc_16bpp) {
 750        src_width *= 4;
 751    } else if (s->bpp > pxa_lcdc_8bpp) {
 752        src_width *= 2;
 753    }
 754
 755    dest_width = s->xres * s->dest_width;
 756    *miny = 0;
 757    if (s->invalidated) {
 758        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
 759                                          addr, s->yres, src_width);
 760    }
 761    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
 762                               src_width, -dest_width, -s->dest_width,
 763                               s->invalidated,
 764                               fn, s->dma_ch[0].palette, miny, maxy);
 765}
 766
 767static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
 768               hwaddr addr, int *miny, int *maxy)
 769{
 770    DisplaySurface *surface = qemu_console_surface(s->con);
 771    int src_width, dest_width;
 772    drawfn fn = NULL;
 773    if (s->dest_width) {
 774        fn = s->line_fn[s->transp][s->bpp];
 775    }
 776    if (!fn) {
 777        return;
 778    }
 779
 780    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
 781    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
 782        src_width *= 3;
 783    } else if (s->bpp > pxa_lcdc_16bpp) {
 784        src_width *= 4;
 785    } else if (s->bpp > pxa_lcdc_8bpp) {
 786        src_width *= 2;
 787    }
 788
 789    dest_width = s->yres * s->dest_width;
 790    *miny = 0;
 791    if (s->invalidated) {
 792        framebuffer_update_memory_section(&s->fbsection, s->sysmem,
 793                                          addr, s->yres, src_width);
 794    }
 795    framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
 796                               src_width, -s->dest_width, dest_width,
 797                               s->invalidated,
 798                               fn, s->dma_ch[0].palette,
 799                               miny, maxy);
 800}
 801
 802static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
 803{
 804    int width, height;
 805    if (!(s->control[0] & LCCR0_ENB))
 806        return;
 807
 808    width = LCCR1_PPL(s->control[1]) + 1;
 809    height = LCCR2_LPP(s->control[2]) + 1;
 810
 811    if (width != s->xres || height != s->yres) {
 812        if (s->orientation == 90 || s->orientation == 270) {
 813            qemu_console_resize(s->con, height, width);
 814        } else {
 815            qemu_console_resize(s->con, width, height);
 816        }
 817        s->invalidated = 1;
 818        s->xres = width;
 819        s->yres = height;
 820    }
 821}
 822
 823static void pxa2xx_update_display(void *opaque)
 824{
 825    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 826    hwaddr fbptr;
 827    int miny, maxy;
 828    int ch;
 829    if (!(s->control[0] & LCCR0_ENB))
 830        return;
 831
 832    pxa2xx_descriptor_load(s);
 833
 834    pxa2xx_lcdc_resize(s);
 835    miny = s->yres;
 836    maxy = 0;
 837    s->transp = s->dma_ch[2].up || s->dma_ch[3].up;
 838    /* Note: With overlay planes the order depends on LCCR0 bit 25.  */
 839    for (ch = 0; ch < PXA_LCDDMA_CHANS; ch ++)
 840        if (s->dma_ch[ch].up) {
 841            if (!s->dma_ch[ch].source) {
 842                pxa2xx_dma_ber_set(s, ch);
 843                continue;
 844            }
 845            fbptr = s->dma_ch[ch].source;
 846            if (!((fbptr >= PXA2XX_SDRAM_BASE &&
 847                     fbptr <= PXA2XX_SDRAM_BASE + ram_size) ||
 848                    (fbptr >= PXA2XX_INTERNAL_BASE &&
 849                     fbptr <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) {
 850                pxa2xx_dma_ber_set(s, ch);
 851                continue;
 852            }
 853
 854            if (s->dma_ch[ch].command & LDCMD_PAL) {
 855                cpu_physical_memory_read(fbptr, s->dma_ch[ch].pbuffer,
 856                    MAX(LDCMD_LENGTH(s->dma_ch[ch].command),
 857                        sizeof(s->dma_ch[ch].pbuffer)));
 858                pxa2xx_palette_parse(s, ch, s->bpp);
 859            } else {
 860                /* Do we need to reparse palette */
 861                if (LCCR4_PALFOR(s->control[4]) != s->pal_for)
 862                    pxa2xx_palette_parse(s, ch, s->bpp);
 863
 864                /* ACK frame start */
 865                pxa2xx_dma_sof_set(s, ch);
 866
 867                s->dma_ch[ch].redraw(s, fbptr, &miny, &maxy);
 868                s->invalidated = 0;
 869
 870                /* ACK frame completed */
 871                pxa2xx_dma_eof_set(s, ch);
 872            }
 873        }
 874
 875    if (s->control[0] & LCCR0_DIS) {
 876        /* ACK last frame completed */
 877        s->control[0] &= ~LCCR0_ENB;
 878        s->status[0] |= LCSR0_LDD;
 879    }
 880
 881    if (miny >= 0) {
 882        switch (s->orientation) {
 883        case 0:
 884            dpy_gfx_update(s->con, 0, miny, s->xres, maxy - miny + 1);
 885            break;
 886        case 90:
 887            dpy_gfx_update(s->con, miny, 0, maxy - miny + 1, s->xres);
 888            break;
 889        case 180:
 890            maxy = s->yres - maxy - 1;
 891            miny = s->yres - miny - 1;
 892            dpy_gfx_update(s->con, 0, maxy, s->xres, miny - maxy + 1);
 893            break;
 894        case 270:
 895            maxy = s->yres - maxy - 1;
 896            miny = s->yres - miny - 1;
 897            dpy_gfx_update(s->con, maxy, 0, miny - maxy + 1, s->xres);
 898            break;
 899        }
 900    }
 901    pxa2xx_lcdc_int_update(s);
 902
 903    qemu_irq_raise(s->vsync_cb);
 904}
 905
 906static void pxa2xx_invalidate_display(void *opaque)
 907{
 908    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 909    s->invalidated = 1;
 910}
 911
 912static void pxa2xx_lcdc_orientation(void *opaque, int angle)
 913{
 914    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 915
 916    switch (angle) {
 917    case 0:
 918        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
 919        break;
 920    case 90:
 921        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90;
 922        break;
 923    case 180:
 924        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180;
 925        break;
 926    case 270:
 927        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270;
 928        break;
 929    }
 930
 931    s->orientation = angle;
 932    s->xres = s->yres = -1;
 933    pxa2xx_lcdc_resize(s);
 934}
 935
 936static const VMStateDescription vmstate_dma_channel = {
 937    .name = "dma_channel",
 938    .version_id = 0,
 939    .minimum_version_id = 0,
 940    .fields = (VMStateField[]) {
 941        VMSTATE_UINT32(branch, struct DMAChannel),
 942        VMSTATE_UINT8(up, struct DMAChannel),
 943        VMSTATE_BUFFER(pbuffer, struct DMAChannel),
 944        VMSTATE_UINT32(descriptor, struct DMAChannel),
 945        VMSTATE_UINT32(source, struct DMAChannel),
 946        VMSTATE_UINT32(id, struct DMAChannel),
 947        VMSTATE_UINT32(command, struct DMAChannel),
 948        VMSTATE_END_OF_LIST()
 949    }
 950};
 951
 952static int pxa2xx_lcdc_post_load(void *opaque, int version_id)
 953{
 954    PXA2xxLCDState *s = opaque;
 955
 956    s->bpp = LCCR3_BPP(s->control[3]);
 957    s->xres = s->yres = s->pal_for = -1;
 958
 959    return 0;
 960}
 961
 962static const VMStateDescription vmstate_pxa2xx_lcdc = {
 963    .name = "pxa2xx_lcdc",
 964    .version_id = 0,
 965    .minimum_version_id = 0,
 966    .post_load = pxa2xx_lcdc_post_load,
 967    .fields = (VMStateField[]) {
 968        VMSTATE_INT32(irqlevel, PXA2xxLCDState),
 969        VMSTATE_INT32(transp, PXA2xxLCDState),
 970        VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6),
 971        VMSTATE_UINT32_ARRAY(status, PXA2xxLCDState, 2),
 972        VMSTATE_UINT32_ARRAY(ovl1c, PXA2xxLCDState, 2),
 973        VMSTATE_UINT32_ARRAY(ovl2c, PXA2xxLCDState, 2),
 974        VMSTATE_UINT32(ccr, PXA2xxLCDState),
 975        VMSTATE_UINT32(cmdcr, PXA2xxLCDState),
 976        VMSTATE_UINT32(trgbr, PXA2xxLCDState),
 977        VMSTATE_UINT32(tcr, PXA2xxLCDState),
 978        VMSTATE_UINT32(liidr, PXA2xxLCDState),
 979        VMSTATE_UINT8(bscntr, PXA2xxLCDState),
 980        VMSTATE_STRUCT_ARRAY(dma_ch, PXA2xxLCDState, 7, 0,
 981                             vmstate_dma_channel, struct DMAChannel),
 982        VMSTATE_END_OF_LIST()
 983    }
 984};
 985
 986#define BITS 8
 987#include "pxa2xx_template.h"
 988#define BITS 15
 989#include "pxa2xx_template.h"
 990#define BITS 16
 991#include "pxa2xx_template.h"
 992#define BITS 24
 993#include "pxa2xx_template.h"
 994#define BITS 32
 995#include "pxa2xx_template.h"
 996
 997static const GraphicHwOps pxa2xx_ops = {
 998    .invalidate  = pxa2xx_invalidate_display,
 999    .gfx_update  = pxa2xx_update_display,
1000};
1001
1002PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
1003                                 hwaddr base, qemu_irq irq)
1004{
1005    PXA2xxLCDState *s;
1006    DisplaySurface *surface;
1007
1008    s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
1009    s->invalidated = 1;
1010    s->irq = irq;
1011    s->sysmem = sysmem;
1012
1013    pxa2xx_lcdc_orientation(s, graphic_rotate);
1014
1015    memory_region_init_io(&s->iomem, NULL, &pxa2xx_lcdc_ops, s,
1016                          "pxa2xx-lcd-controller", 0x00100000);
1017    memory_region_add_subregion(sysmem, base, &s->iomem);
1018
1019    s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
1020    surface = qemu_console_surface(s->con);
1021
1022    switch (surface_bits_per_pixel(surface)) {
1023    case 0:
1024        s->dest_width = 0;
1025        break;
1026    case 8:
1027        s->line_fn[0] = pxa2xx_draw_fn_8;
1028        s->line_fn[1] = pxa2xx_draw_fn_8t;
1029        s->dest_width = 1;
1030        break;
1031    case 15:
1032        s->line_fn[0] = pxa2xx_draw_fn_15;
1033        s->line_fn[1] = pxa2xx_draw_fn_15t;
1034        s->dest_width = 2;
1035        break;
1036    case 16:
1037        s->line_fn[0] = pxa2xx_draw_fn_16;
1038        s->line_fn[1] = pxa2xx_draw_fn_16t;
1039        s->dest_width = 2;
1040        break;
1041    case 24:
1042        s->line_fn[0] = pxa2xx_draw_fn_24;
1043        s->line_fn[1] = pxa2xx_draw_fn_24t;
1044        s->dest_width = 3;
1045        break;
1046    case 32:
1047        s->line_fn[0] = pxa2xx_draw_fn_32;
1048        s->line_fn[1] = pxa2xx_draw_fn_32t;
1049        s->dest_width = 4;
1050        break;
1051    default:
1052        fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
1053        exit(1);
1054    }
1055
1056    vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
1057
1058    return s;
1059}
1060
1061void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler)
1062{
1063    s->vsync_cb = handler;
1064}
1065