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