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 25 struct 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 39 struct 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 82 typedef 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 #if HOST_BIG_ENDIAN 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 209 static 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 234 static 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 259 static 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 284 static 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 312 static 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 350 static 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 */ 372 static 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 420 static 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 */ 447 static 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 515 static 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 536 static 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 562 static 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 */ 589 static 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 */ 601 static 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 */ 620 static 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 */ 640 static 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 */ 660 static 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 */ 683 static 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 */ 706 static 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 */ 716 static 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 751 static 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 846 static 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 1002 static 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 */ 1009 static 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 1105 static 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 1114 static 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 1143 static 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 1173 static 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 1204 static 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 1236 static 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 1257 static 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 1340 static void pxa2xx_invalidate_display(void *opaque) 1341 { 1342 PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; 1343 s->invalidated = 1; 1344 } 1345 1346 static 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 1370 static 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 1386 static 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 1396 static 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 1420 static const GraphicHwOps pxa2xx_ops = { 1421 .invalidate = pxa2xx_invalidate_display, 1422 .gfx_update = pxa2xx_update_display, 1423 }; 1424 1425 PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, 1426 hwaddr base, qemu_irq irq) 1427 { 1428 PXA2xxLCDState *s; 1429 1430 s = g_new0(PXA2xxLCDState, 1); 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 1448 void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler) 1449 { 1450 s->vsync_cb = handler; 1451 } 1452