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