symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/omap_dss.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * OMAP2 Display Subsystem.
       
     3  *
       
     4  * Copyright (C) 2008 Nokia Corporation
       
     5  * Written by Andrzej Zaborowski <andrew@openedhand.com>
       
     6  *
       
     7  * This program is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU General Public License as
       
     9  * published by the Free Software Foundation; either version 2 or
       
    10  * (at your option) version 3 of the License.
       
    11  *
       
    12  * This program is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    15  * GNU General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License
       
    18  * along with this program; if not, write to the Free Software
       
    19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       
    20  * MA 02111-1307 USA
       
    21  */
       
    22 #include "hw.h"
       
    23 #include "console.h"
       
    24 #include "omap.h"
       
    25 
       
    26 struct omap_dss_s {
       
    27     qemu_irq irq;
       
    28     qemu_irq drq;
       
    29     DisplayState *state;
       
    30 
       
    31     int autoidle;
       
    32     int control;
       
    33     int enable;
       
    34 
       
    35     struct omap_dss_panel_s {
       
    36         int enable;
       
    37         int nx;
       
    38         int ny;
       
    39 
       
    40         int x;
       
    41         int y;
       
    42     } dig, lcd;
       
    43 
       
    44     struct {
       
    45         uint32_t idlemode;
       
    46         uint32_t irqst;
       
    47         uint32_t irqen;
       
    48         uint32_t control;
       
    49         uint32_t config;
       
    50         uint32_t capable;
       
    51         uint32_t timing[4];
       
    52         int line;
       
    53         uint32_t bg[2];
       
    54         uint32_t trans[2];
       
    55 
       
    56         struct omap_dss_plane_s {
       
    57             int enable;
       
    58             int bpp;
       
    59             int posx;
       
    60             int posy;
       
    61             int nx;
       
    62             int ny;
       
    63 
       
    64             target_phys_addr_t addr[3];
       
    65 
       
    66             uint32_t attr;
       
    67             uint32_t tresh;
       
    68             int rowinc;
       
    69             int colinc;
       
    70             int wininc;
       
    71         } l[3];
       
    72 
       
    73         int invalidate;
       
    74         uint16_t palette[256];
       
    75     } dispc;
       
    76 
       
    77     struct {
       
    78         int idlemode;
       
    79         uint32_t control;
       
    80         int enable;
       
    81         int pixels;
       
    82         int busy;
       
    83         int skiplines;
       
    84         uint16_t rxbuf;
       
    85         uint32_t config[2];
       
    86         uint32_t time[4];
       
    87         uint32_t data[6];
       
    88         uint16_t vsync;
       
    89         uint16_t hsync;
       
    90         struct rfbi_chip_s *chip[2];
       
    91     } rfbi;
       
    92 };
       
    93 
       
    94 static void omap_dispc_interrupt_update(struct omap_dss_s *s)
       
    95 {
       
    96     qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen);
       
    97 }
       
    98 
       
    99 static void omap_rfbi_reset(struct omap_dss_s *s)
       
   100 {
       
   101     s->rfbi.idlemode = 0;
       
   102     s->rfbi.control = 2;
       
   103     s->rfbi.enable = 0;
       
   104     s->rfbi.pixels = 0;
       
   105     s->rfbi.skiplines = 0;
       
   106     s->rfbi.busy = 0;
       
   107     s->rfbi.config[0] = 0x00310000;
       
   108     s->rfbi.config[1] = 0x00310000;
       
   109     s->rfbi.time[0] = 0;
       
   110     s->rfbi.time[1] = 0;
       
   111     s->rfbi.time[2] = 0;
       
   112     s->rfbi.time[3] = 0;
       
   113     s->rfbi.data[0] = 0;
       
   114     s->rfbi.data[1] = 0;
       
   115     s->rfbi.data[2] = 0;
       
   116     s->rfbi.data[3] = 0;
       
   117     s->rfbi.data[4] = 0;
       
   118     s->rfbi.data[5] = 0;
       
   119     s->rfbi.vsync = 0;
       
   120     s->rfbi.hsync = 0;
       
   121 }
       
   122 
       
   123 void omap_dss_reset(struct omap_dss_s *s)
       
   124 {
       
   125     s->autoidle = 0;
       
   126     s->control = 0;
       
   127     s->enable = 0;
       
   128 
       
   129     s->dig.enable = 0;
       
   130     s->dig.nx = 1;
       
   131     s->dig.ny = 1;
       
   132 
       
   133     s->lcd.enable = 0;
       
   134     s->lcd.nx = 1;
       
   135     s->lcd.ny = 1;
       
   136 
       
   137     s->dispc.idlemode = 0;
       
   138     s->dispc.irqst = 0;
       
   139     s->dispc.irqen = 0;
       
   140     s->dispc.control = 0;
       
   141     s->dispc.config = 0;
       
   142     s->dispc.capable = 0x161;
       
   143     s->dispc.timing[0] = 0;
       
   144     s->dispc.timing[1] = 0;
       
   145     s->dispc.timing[2] = 0;
       
   146     s->dispc.timing[3] = 0;
       
   147     s->dispc.line = 0;
       
   148     s->dispc.bg[0] = 0;
       
   149     s->dispc.bg[1] = 0;
       
   150     s->dispc.trans[0] = 0;
       
   151     s->dispc.trans[1] = 0;
       
   152 
       
   153     s->dispc.l[0].enable = 0;
       
   154     s->dispc.l[0].bpp = 0;
       
   155     s->dispc.l[0].addr[0] = 0;
       
   156     s->dispc.l[0].addr[1] = 0;
       
   157     s->dispc.l[0].addr[2] = 0;
       
   158     s->dispc.l[0].posx = 0;
       
   159     s->dispc.l[0].posy = 0;
       
   160     s->dispc.l[0].nx = 1;
       
   161     s->dispc.l[0].ny = 1;
       
   162     s->dispc.l[0].attr = 0;
       
   163     s->dispc.l[0].tresh = 0;
       
   164     s->dispc.l[0].rowinc = 1;
       
   165     s->dispc.l[0].colinc = 1;
       
   166     s->dispc.l[0].wininc = 0;
       
   167 
       
   168     omap_rfbi_reset(s);
       
   169     omap_dispc_interrupt_update(s);
       
   170 }
       
   171 
       
   172 static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
       
   173 {
       
   174     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
       
   175 
       
   176     switch (addr) {
       
   177     case 0x00:	/* DSS_REVISIONNUMBER */
       
   178         return 0x20;
       
   179 
       
   180     case 0x10:	/* DSS_SYSCONFIG */
       
   181         return s->autoidle;
       
   182 
       
   183     case 0x14:	/* DSS_SYSSTATUS */
       
   184         return 1;						/* RESETDONE */
       
   185 
       
   186     case 0x40:	/* DSS_CONTROL */
       
   187         return s->control;
       
   188 
       
   189     case 0x50:	/* DSS_PSA_LCD_REG_1 */
       
   190     case 0x54:	/* DSS_PSA_LCD_REG_2 */
       
   191     case 0x58:	/* DSS_PSA_VIDEO_REG */
       
   192         /* TODO: fake some values when appropriate s->control bits are set */
       
   193         return 0;
       
   194 
       
   195     case 0x5c:	/* DSS_STATUS */
       
   196         return 1 + (s->control & 1);
       
   197 
       
   198     default:
       
   199         break;
       
   200     }
       
   201     OMAP_BAD_REG(addr);
       
   202     return 0;
       
   203 }
       
   204 
       
   205 static void omap_diss_write(void *opaque, target_phys_addr_t addr,
       
   206                 uint32_t value)
       
   207 {
       
   208     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
       
   209 
       
   210     switch (addr) {
       
   211     case 0x00:	/* DSS_REVISIONNUMBER */
       
   212     case 0x14:	/* DSS_SYSSTATUS */
       
   213     case 0x50:	/* DSS_PSA_LCD_REG_1 */
       
   214     case 0x54:	/* DSS_PSA_LCD_REG_2 */
       
   215     case 0x58:	/* DSS_PSA_VIDEO_REG */
       
   216     case 0x5c:	/* DSS_STATUS */
       
   217         OMAP_RO_REG(addr);
       
   218         break;
       
   219 
       
   220     case 0x10:	/* DSS_SYSCONFIG */
       
   221         if (value & 2)						/* SOFTRESET */
       
   222             omap_dss_reset(s);
       
   223         s->autoidle = value & 1;
       
   224         break;
       
   225 
       
   226     case 0x40:	/* DSS_CONTROL */
       
   227         s->control = value & 0x3dd;
       
   228         break;
       
   229 
       
   230     default:
       
   231         OMAP_BAD_REG(addr);
       
   232     }
       
   233 }
       
   234 
       
   235 static CPUReadMemoryFunc *omap_diss1_readfn[] = {
       
   236     omap_badwidth_read32,
       
   237     omap_badwidth_read32,
       
   238     omap_diss_read,
       
   239 };
       
   240 
       
   241 static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
       
   242     omap_badwidth_write32,
       
   243     omap_badwidth_write32,
       
   244     omap_diss_write,
       
   245 };
       
   246 
       
   247 static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
       
   248 {
       
   249     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
       
   250 
       
   251     switch (addr) {
       
   252     case 0x000:	/* DISPC_REVISION */
       
   253         return 0x20;
       
   254 
       
   255     case 0x010:	/* DISPC_SYSCONFIG */
       
   256         return s->dispc.idlemode;
       
   257 
       
   258     case 0x014:	/* DISPC_SYSSTATUS */
       
   259         return 1;						/* RESETDONE */
       
   260 
       
   261     case 0x018:	/* DISPC_IRQSTATUS */
       
   262         return s->dispc.irqst;
       
   263 
       
   264     case 0x01c:	/* DISPC_IRQENABLE */
       
   265         return s->dispc.irqen;
       
   266 
       
   267     case 0x040:	/* DISPC_CONTROL */
       
   268         return s->dispc.control;
       
   269 
       
   270     case 0x044:	/* DISPC_CONFIG */
       
   271         return s->dispc.config;
       
   272 
       
   273     case 0x048:	/* DISPC_CAPABLE */
       
   274         return s->dispc.capable;
       
   275 
       
   276     case 0x04c:	/* DISPC_DEFAULT_COLOR0 */
       
   277         return s->dispc.bg[0];
       
   278     case 0x050:	/* DISPC_DEFAULT_COLOR1 */
       
   279         return s->dispc.bg[1];
       
   280     case 0x054:	/* DISPC_TRANS_COLOR0 */
       
   281         return s->dispc.trans[0];
       
   282     case 0x058:	/* DISPC_TRANS_COLOR1 */
       
   283         return s->dispc.trans[1];
       
   284 
       
   285     case 0x05c:	/* DISPC_LINE_STATUS */
       
   286         return 0x7ff;
       
   287     case 0x060:	/* DISPC_LINE_NUMBER */
       
   288         return s->dispc.line;
       
   289 
       
   290     case 0x064:	/* DISPC_TIMING_H */
       
   291         return s->dispc.timing[0];
       
   292     case 0x068:	/* DISPC_TIMING_V */
       
   293         return s->dispc.timing[1];
       
   294     case 0x06c:	/* DISPC_POL_FREQ */
       
   295         return s->dispc.timing[2];
       
   296     case 0x070:	/* DISPC_DIVISOR */
       
   297         return s->dispc.timing[3];
       
   298 
       
   299     case 0x078:	/* DISPC_SIZE_DIG */
       
   300         return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
       
   301     case 0x07c:	/* DISPC_SIZE_LCD */
       
   302         return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
       
   303 
       
   304     case 0x080:	/* DISPC_GFX_BA0 */
       
   305         return s->dispc.l[0].addr[0];
       
   306     case 0x084:	/* DISPC_GFX_BA1 */
       
   307         return s->dispc.l[0].addr[1];
       
   308     case 0x088:	/* DISPC_GFX_POSITION */
       
   309         return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx;
       
   310     case 0x08c:	/* DISPC_GFX_SIZE */
       
   311         return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1);
       
   312     case 0x0a0:	/* DISPC_GFX_ATTRIBUTES */
       
   313         return s->dispc.l[0].attr;
       
   314     case 0x0a4:	/* DISPC_GFX_FIFO_TRESHOLD */
       
   315         return s->dispc.l[0].tresh;
       
   316     case 0x0a8:	/* DISPC_GFX_FIFO_SIZE_STATUS */
       
   317         return 256;
       
   318     case 0x0ac:	/* DISPC_GFX_ROW_INC */
       
   319         return s->dispc.l[0].rowinc;
       
   320     case 0x0b0:	/* DISPC_GFX_PIXEL_INC */
       
   321         return s->dispc.l[0].colinc;
       
   322     case 0x0b4:	/* DISPC_GFX_WINDOW_SKIP */
       
   323         return s->dispc.l[0].wininc;
       
   324     case 0x0b8:	/* DISPC_GFX_TABLE_BA */
       
   325         return s->dispc.l[0].addr[2];
       
   326 
       
   327     case 0x0bc:	/* DISPC_VID1_BA0 */
       
   328     case 0x0c0:	/* DISPC_VID1_BA1 */
       
   329     case 0x0c4:	/* DISPC_VID1_POSITION */
       
   330     case 0x0c8:	/* DISPC_VID1_SIZE */
       
   331     case 0x0cc:	/* DISPC_VID1_ATTRIBUTES */
       
   332     case 0x0d0:	/* DISPC_VID1_FIFO_TRESHOLD */
       
   333     case 0x0d4:	/* DISPC_VID1_FIFO_SIZE_STATUS */
       
   334     case 0x0d8:	/* DISPC_VID1_ROW_INC */
       
   335     case 0x0dc:	/* DISPC_VID1_PIXEL_INC */
       
   336     case 0x0e0:	/* DISPC_VID1_FIR */
       
   337     case 0x0e4:	/* DISPC_VID1_PICTURE_SIZE */
       
   338     case 0x0e8:	/* DISPC_VID1_ACCU0 */
       
   339     case 0x0ec:	/* DISPC_VID1_ACCU1 */
       
   340     case 0x0f0 ... 0x140:	/* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
       
   341     case 0x14c:	/* DISPC_VID2_BA0 */
       
   342     case 0x150:	/* DISPC_VID2_BA1 */
       
   343     case 0x154:	/* DISPC_VID2_POSITION */
       
   344     case 0x158:	/* DISPC_VID2_SIZE */
       
   345     case 0x15c:	/* DISPC_VID2_ATTRIBUTES */
       
   346     case 0x160:	/* DISPC_VID2_FIFO_TRESHOLD */
       
   347     case 0x164:	/* DISPC_VID2_FIFO_SIZE_STATUS */
       
   348     case 0x168:	/* DISPC_VID2_ROW_INC */
       
   349     case 0x16c:	/* DISPC_VID2_PIXEL_INC */
       
   350     case 0x170:	/* DISPC_VID2_FIR */
       
   351     case 0x174:	/* DISPC_VID2_PICTURE_SIZE */
       
   352     case 0x178:	/* DISPC_VID2_ACCU0 */
       
   353     case 0x17c:	/* DISPC_VID2_ACCU1 */
       
   354     case 0x180 ... 0x1d0:	/* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
       
   355     case 0x1d4:	/* DISPC_DATA_CYCLE1 */
       
   356     case 0x1d8:	/* DISPC_DATA_CYCLE2 */
       
   357     case 0x1dc:	/* DISPC_DATA_CYCLE3 */
       
   358         return 0;
       
   359 
       
   360     default:
       
   361         break;
       
   362     }
       
   363     OMAP_BAD_REG(addr);
       
   364     return 0;
       
   365 }
       
   366 
       
   367 static void omap_disc_write(void *opaque, target_phys_addr_t addr,
       
   368                 uint32_t value)
       
   369 {
       
   370     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
       
   371 
       
   372     switch (addr) {
       
   373     case 0x010:	/* DISPC_SYSCONFIG */
       
   374         if (value & 2)						/* SOFTRESET */
       
   375             omap_dss_reset(s);
       
   376         s->dispc.idlemode = value & 0x301b;
       
   377         break;
       
   378 
       
   379     case 0x018:	/* DISPC_IRQSTATUS */
       
   380         s->dispc.irqst &= ~value;
       
   381         omap_dispc_interrupt_update(s);
       
   382         break;
       
   383 
       
   384     case 0x01c:	/* DISPC_IRQENABLE */
       
   385         s->dispc.irqen = value & 0xffff;
       
   386         omap_dispc_interrupt_update(s);
       
   387         break;
       
   388 
       
   389     case 0x040:	/* DISPC_CONTROL */
       
   390         s->dispc.control = value & 0x07ff9fff;
       
   391         s->dig.enable = (value >> 1) & 1;
       
   392         s->lcd.enable = (value >> 0) & 1;
       
   393         if (value & (1 << 12))			/* OVERLAY_OPTIMIZATION */
       
   394             if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
       
   395                  fprintf(stderr, "%s: Overlay Optimization when no overlay "
       
   396                                  "region effectively exists leads to "
       
   397                                  "unpredictable behaviour!\n", __FUNCTION__);
       
   398         if (value & (1 << 6)) {				/* GODIGITAL */
       
   399             /* XXX: Shadowed fields are:
       
   400              * s->dispc.config
       
   401              * s->dispc.capable
       
   402              * s->dispc.bg[0]
       
   403              * s->dispc.bg[1]
       
   404              * s->dispc.trans[0]
       
   405              * s->dispc.trans[1]
       
   406              * s->dispc.line
       
   407              * s->dispc.timing[0]
       
   408              * s->dispc.timing[1]
       
   409              * s->dispc.timing[2]
       
   410              * s->dispc.timing[3]
       
   411              * s->lcd.nx
       
   412              * s->lcd.ny
       
   413              * s->dig.nx
       
   414              * s->dig.ny
       
   415              * s->dispc.l[0].addr[0]
       
   416              * s->dispc.l[0].addr[1]
       
   417              * s->dispc.l[0].addr[2]
       
   418              * s->dispc.l[0].posx
       
   419              * s->dispc.l[0].posy
       
   420              * s->dispc.l[0].nx
       
   421              * s->dispc.l[0].ny
       
   422              * s->dispc.l[0].tresh
       
   423              * s->dispc.l[0].rowinc
       
   424              * s->dispc.l[0].colinc
       
   425              * s->dispc.l[0].wininc
       
   426              * All they need to be loaded here from their shadow registers.
       
   427              */
       
   428         }
       
   429         if (value & (1 << 5)) {				/* GOLCD */
       
   430              /* XXX: Likewise for LCD here.  */
       
   431         }
       
   432         s->dispc.invalidate = 1;
       
   433         break;
       
   434 
       
   435     case 0x044:	/* DISPC_CONFIG */
       
   436         s->dispc.config = value & 0x3fff;
       
   437         /* XXX:
       
   438          * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
       
   439          * bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
       
   440          */
       
   441         s->dispc.invalidate = 1;
       
   442         break;
       
   443 
       
   444     case 0x048:	/* DISPC_CAPABLE */
       
   445         s->dispc.capable = value & 0x3ff;
       
   446         break;
       
   447 
       
   448     case 0x04c:	/* DISPC_DEFAULT_COLOR0 */
       
   449         s->dispc.bg[0] = value & 0xffffff;
       
   450         s->dispc.invalidate = 1;
       
   451         break;
       
   452     case 0x050:	/* DISPC_DEFAULT_COLOR1 */
       
   453         s->dispc.bg[1] = value & 0xffffff;
       
   454         s->dispc.invalidate = 1;
       
   455         break;
       
   456     case 0x054:	/* DISPC_TRANS_COLOR0 */
       
   457         s->dispc.trans[0] = value & 0xffffff;
       
   458         s->dispc.invalidate = 1;
       
   459         break;
       
   460     case 0x058:	/* DISPC_TRANS_COLOR1 */
       
   461         s->dispc.trans[1] = value & 0xffffff;
       
   462         s->dispc.invalidate = 1;
       
   463         break;
       
   464 
       
   465     case 0x060:	/* DISPC_LINE_NUMBER */
       
   466         s->dispc.line = value & 0x7ff;
       
   467         break;
       
   468 
       
   469     case 0x064:	/* DISPC_TIMING_H */
       
   470         s->dispc.timing[0] = value & 0x0ff0ff3f;
       
   471         break;
       
   472     case 0x068:	/* DISPC_TIMING_V */
       
   473         s->dispc.timing[1] = value & 0x0ff0ff3f;
       
   474         break;
       
   475     case 0x06c:	/* DISPC_POL_FREQ */
       
   476         s->dispc.timing[2] = value & 0x0003ffff;
       
   477         break;
       
   478     case 0x070:	/* DISPC_DIVISOR */
       
   479         s->dispc.timing[3] = value & 0x00ff00ff;
       
   480         break;
       
   481 
       
   482     case 0x078:	/* DISPC_SIZE_DIG */
       
   483         s->dig.nx = ((value >>  0) & 0x7ff) + 1;		/* PPL */
       
   484         s->dig.ny = ((value >> 16) & 0x7ff) + 1;		/* LPP */
       
   485         s->dispc.invalidate = 1;
       
   486         break;
       
   487     case 0x07c:	/* DISPC_SIZE_LCD */
       
   488         s->lcd.nx = ((value >>  0) & 0x7ff) + 1;		/* PPL */
       
   489         s->lcd.ny = ((value >> 16) & 0x7ff) + 1;		/* LPP */
       
   490         s->dispc.invalidate = 1;
       
   491         break;
       
   492     case 0x080:	/* DISPC_GFX_BA0 */
       
   493         s->dispc.l[0].addr[0] = (target_phys_addr_t) value;
       
   494         s->dispc.invalidate = 1;
       
   495         break;
       
   496     case 0x084:	/* DISPC_GFX_BA1 */
       
   497         s->dispc.l[0].addr[1] = (target_phys_addr_t) value;
       
   498         s->dispc.invalidate = 1;
       
   499         break;
       
   500     case 0x088:	/* DISPC_GFX_POSITION */
       
   501         s->dispc.l[0].posx = ((value >>  0) & 0x7ff);		/* GFXPOSX */
       
   502         s->dispc.l[0].posy = ((value >> 16) & 0x7ff);		/* GFXPOSY */
       
   503         s->dispc.invalidate = 1;
       
   504         break;
       
   505     case 0x08c:	/* DISPC_GFX_SIZE */
       
   506         s->dispc.l[0].nx = ((value >>  0) & 0x7ff) + 1;		/* GFXSIZEX */
       
   507         s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1;		/* GFXSIZEY */
       
   508         s->dispc.invalidate = 1;
       
   509         break;
       
   510     case 0x0a0:	/* DISPC_GFX_ATTRIBUTES */
       
   511         s->dispc.l[0].attr = value & 0x7ff;
       
   512         if (value & (3 << 9))
       
   513             fprintf(stderr, "%s: Big-endian pixel format not supported\n",
       
   514                             __FUNCTION__);
       
   515         s->dispc.l[0].enable = value & 1;
       
   516         s->dispc.l[0].bpp = (value >> 1) & 0xf;
       
   517         s->dispc.invalidate = 1;
       
   518         break;
       
   519     case 0x0a4:	/* DISPC_GFX_FIFO_TRESHOLD */
       
   520         s->dispc.l[0].tresh = value & 0x01ff01ff;
       
   521         break;
       
   522     case 0x0ac:	/* DISPC_GFX_ROW_INC */
       
   523         s->dispc.l[0].rowinc = value;
       
   524         s->dispc.invalidate = 1;
       
   525         break;
       
   526     case 0x0b0:	/* DISPC_GFX_PIXEL_INC */
       
   527         s->dispc.l[0].colinc = value;
       
   528         s->dispc.invalidate = 1;
       
   529         break;
       
   530     case 0x0b4:	/* DISPC_GFX_WINDOW_SKIP */
       
   531         s->dispc.l[0].wininc = value;
       
   532         break;
       
   533     case 0x0b8:	/* DISPC_GFX_TABLE_BA */
       
   534         s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
       
   535         s->dispc.invalidate = 1;
       
   536         break;
       
   537 
       
   538     case 0x0bc:	/* DISPC_VID1_BA0 */
       
   539     case 0x0c0:	/* DISPC_VID1_BA1 */
       
   540     case 0x0c4:	/* DISPC_VID1_POSITION */
       
   541     case 0x0c8:	/* DISPC_VID1_SIZE */
       
   542     case 0x0cc:	/* DISPC_VID1_ATTRIBUTES */
       
   543     case 0x0d0:	/* DISPC_VID1_FIFO_TRESHOLD */
       
   544     case 0x0d8:	/* DISPC_VID1_ROW_INC */
       
   545     case 0x0dc:	/* DISPC_VID1_PIXEL_INC */
       
   546     case 0x0e0:	/* DISPC_VID1_FIR */
       
   547     case 0x0e4:	/* DISPC_VID1_PICTURE_SIZE */
       
   548     case 0x0e8:	/* DISPC_VID1_ACCU0 */
       
   549     case 0x0ec:	/* DISPC_VID1_ACCU1 */
       
   550     case 0x0f0 ... 0x140:	/* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
       
   551     case 0x14c:	/* DISPC_VID2_BA0 */
       
   552     case 0x150:	/* DISPC_VID2_BA1 */
       
   553     case 0x154:	/* DISPC_VID2_POSITION */
       
   554     case 0x158:	/* DISPC_VID2_SIZE */
       
   555     case 0x15c:	/* DISPC_VID2_ATTRIBUTES */
       
   556     case 0x160:	/* DISPC_VID2_FIFO_TRESHOLD */
       
   557     case 0x168:	/* DISPC_VID2_ROW_INC */
       
   558     case 0x16c:	/* DISPC_VID2_PIXEL_INC */
       
   559     case 0x170:	/* DISPC_VID2_FIR */
       
   560     case 0x174:	/* DISPC_VID2_PICTURE_SIZE */
       
   561     case 0x178:	/* DISPC_VID2_ACCU0 */
       
   562     case 0x17c:	/* DISPC_VID2_ACCU1 */
       
   563     case 0x180 ... 0x1d0:	/* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
       
   564     case 0x1d4:	/* DISPC_DATA_CYCLE1 */
       
   565     case 0x1d8:	/* DISPC_DATA_CYCLE2 */
       
   566     case 0x1dc:	/* DISPC_DATA_CYCLE3 */
       
   567         break;
       
   568 
       
   569     default:
       
   570         OMAP_BAD_REG(addr);
       
   571     }
       
   572 }
       
   573 
       
   574 static CPUReadMemoryFunc *omap_disc1_readfn[] = {
       
   575     omap_badwidth_read32,
       
   576     omap_badwidth_read32,
       
   577     omap_disc_read,
       
   578 };
       
   579 
       
   580 static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
       
   581     omap_badwidth_write32,
       
   582     omap_badwidth_write32,
       
   583     omap_disc_write,
       
   584 };
       
   585 
       
   586 static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
       
   587 {
       
   588     target_phys_addr_t fb;
       
   589     uint32_t pd;
       
   590 
       
   591     /* TODO */
       
   592     fb = s->dispc.l[0].addr[0];
       
   593 
       
   594     pd = cpu_get_physical_page_desc(fb);
       
   595     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
       
   596         /* TODO */
       
   597         cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
       
   598                         __FUNCTION__);
       
   599     else
       
   600         /* FIXME: This is broken if it spans multiple RAM regions.  */
       
   601         return host_ram_addr((pd & TARGET_PAGE_MASK) +
       
   602                              (fb & ~TARGET_PAGE_MASK));
       
   603 }
       
   604 
       
   605 static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
       
   606 {
       
   607     if (!s->rfbi.busy)
       
   608         return;
       
   609 
       
   610     /* TODO: in non-Bypass mode we probably need to just deassert the DRQ.  */
       
   611 
       
   612     s->rfbi.busy = 0;
       
   613 }
       
   614 
       
   615 static void omap_rfbi_transfer_start(struct omap_dss_s *s)
       
   616 {
       
   617     void *data;
       
   618     size_t len;
       
   619     int pitch;
       
   620 
       
   621     if (!s->rfbi.enable || s->rfbi.busy)
       
   622         return;
       
   623 
       
   624     if (s->rfbi.control & (1 << 1)) {				/* BYPASS */
       
   625         /* TODO: in non-Bypass mode we probably need to just assert the
       
   626          * DRQ and wait for DMA to write the pixels.  */
       
   627         fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
       
   628         return;
       
   629     }
       
   630 
       
   631     if (!(s->dispc.control & (1 << 11)))			/* RFBIMODE */
       
   632         return;
       
   633     /* TODO: check that LCD output is enabled in DISPC.  */
       
   634 
       
   635     s->rfbi.busy = 1;
       
   636 
       
   637     data = omap_rfbi_get_buffer(s);
       
   638 
       
   639     /* TODO bpp */
       
   640     len = s->rfbi.pixels * 2;
       
   641     s->rfbi.pixels = 0;
       
   642 
       
   643     /* TODO: negative values */
       
   644     pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
       
   645 
       
   646     if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
       
   647         s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
       
   648     if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
       
   649         s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
       
   650 
       
   651     omap_rfbi_transfer_stop(s);
       
   652 
       
   653     /* TODO */
       
   654     s->dispc.irqst |= 1;					/* FRAMEDONE */
       
   655     omap_dispc_interrupt_update(s);
       
   656 }
       
   657 
       
   658 static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
       
   659 {
       
   660     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
       
   661 
       
   662     switch (addr) {
       
   663     case 0x00:	/* RFBI_REVISION */
       
   664         return 0x10;
       
   665 
       
   666     case 0x10:	/* RFBI_SYSCONFIG */
       
   667         return s->rfbi.idlemode;
       
   668 
       
   669     case 0x14:	/* RFBI_SYSSTATUS */
       
   670         return 1 | (s->rfbi.busy << 8);				/* RESETDONE */
       
   671 
       
   672     case 0x40:	/* RFBI_CONTROL */
       
   673         return s->rfbi.control;
       
   674 
       
   675     case 0x44:	/* RFBI_PIXELCNT */
       
   676         return s->rfbi.pixels;
       
   677 
       
   678     case 0x48:	/* RFBI_LINE_NUMBER */
       
   679         return s->rfbi.skiplines;
       
   680 
       
   681     case 0x58:	/* RFBI_READ */
       
   682     case 0x5c:	/* RFBI_STATUS */
       
   683         return s->rfbi.rxbuf;
       
   684 
       
   685     case 0x60:	/* RFBI_CONFIG0 */
       
   686         return s->rfbi.config[0];
       
   687     case 0x64:	/* RFBI_ONOFF_TIME0 */
       
   688         return s->rfbi.time[0];
       
   689     case 0x68:	/* RFBI_CYCLE_TIME0 */
       
   690         return s->rfbi.time[1];
       
   691     case 0x6c:	/* RFBI_DATA_CYCLE1_0 */
       
   692         return s->rfbi.data[0];
       
   693     case 0x70:	/* RFBI_DATA_CYCLE2_0 */
       
   694         return s->rfbi.data[1];
       
   695     case 0x74:	/* RFBI_DATA_CYCLE3_0 */
       
   696         return s->rfbi.data[2];
       
   697 
       
   698     case 0x78:	/* RFBI_CONFIG1 */
       
   699         return s->rfbi.config[1];
       
   700     case 0x7c:	/* RFBI_ONOFF_TIME1 */
       
   701         return s->rfbi.time[2];
       
   702     case 0x80:	/* RFBI_CYCLE_TIME1 */
       
   703         return s->rfbi.time[3];
       
   704     case 0x84:	/* RFBI_DATA_CYCLE1_1 */
       
   705         return s->rfbi.data[3];
       
   706     case 0x88:	/* RFBI_DATA_CYCLE2_1 */
       
   707         return s->rfbi.data[4];
       
   708     case 0x8c:	/* RFBI_DATA_CYCLE3_1 */
       
   709         return s->rfbi.data[5];
       
   710 
       
   711     case 0x90:	/* RFBI_VSYNC_WIDTH */
       
   712         return s->rfbi.vsync;
       
   713     case 0x94:	/* RFBI_HSYNC_WIDTH */
       
   714         return s->rfbi.hsync;
       
   715     }
       
   716     OMAP_BAD_REG(addr);
       
   717     return 0;
       
   718 }
       
   719 
       
   720 static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
       
   721                 uint32_t value)
       
   722 {
       
   723     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
       
   724 
       
   725     switch (addr) {
       
   726     case 0x10:	/* RFBI_SYSCONFIG */
       
   727         if (value & 2)						/* SOFTRESET */
       
   728             omap_rfbi_reset(s);
       
   729         s->rfbi.idlemode = value & 0x19;
       
   730         break;
       
   731 
       
   732     case 0x40:	/* RFBI_CONTROL */
       
   733         s->rfbi.control = value & 0xf;
       
   734         s->rfbi.enable = value & 1;
       
   735         if (value & (1 << 4) &&					/* ITE */
       
   736                         !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
       
   737             omap_rfbi_transfer_start(s);
       
   738         break;
       
   739 
       
   740     case 0x44:	/* RFBI_PIXELCNT */
       
   741         s->rfbi.pixels = value;
       
   742         break;
       
   743 
       
   744     case 0x48:	/* RFBI_LINE_NUMBER */
       
   745         s->rfbi.skiplines = value & 0x7ff;
       
   746         break;
       
   747 
       
   748     case 0x4c:	/* RFBI_CMD */
       
   749         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
       
   750             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
       
   751         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
       
   752             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
       
   753         break;
       
   754     case 0x50:	/* RFBI_PARAM */
       
   755         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
       
   756             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
       
   757         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
       
   758             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
       
   759         break;
       
   760     case 0x54:	/* RFBI_DATA */
       
   761         /* TODO: take into account the format set up in s->rfbi.config[?] and
       
   762          * s->rfbi.data[?], but special-case the most usual scenario so that
       
   763          * speed doesn't suffer.  */
       
   764         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
       
   765             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
       
   766             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
       
   767         }
       
   768         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
       
   769             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
       
   770             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
       
   771         }
       
   772         if (!-- s->rfbi.pixels)
       
   773             omap_rfbi_transfer_stop(s);
       
   774         break;
       
   775     case 0x58:	/* RFBI_READ */
       
   776         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
       
   777             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
       
   778         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
       
   779             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
       
   780         if (!-- s->rfbi.pixels)
       
   781             omap_rfbi_transfer_stop(s);
       
   782         break;
       
   783 
       
   784     case 0x5c:	/* RFBI_STATUS */
       
   785         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
       
   786             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
       
   787         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
       
   788             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
       
   789         if (!-- s->rfbi.pixels)
       
   790             omap_rfbi_transfer_stop(s);
       
   791         break;
       
   792 
       
   793     case 0x60:	/* RFBI_CONFIG0 */
       
   794         s->rfbi.config[0] = value & 0x003f1fff;
       
   795         break;
       
   796 
       
   797     case 0x64:	/* RFBI_ONOFF_TIME0 */
       
   798         s->rfbi.time[0] = value & 0x3fffffff;
       
   799         break;
       
   800     case 0x68:	/* RFBI_CYCLE_TIME0 */
       
   801         s->rfbi.time[1] = value & 0x0fffffff;
       
   802         break;
       
   803     case 0x6c:	/* RFBI_DATA_CYCLE1_0 */
       
   804         s->rfbi.data[0] = value & 0x0f1f0f1f;
       
   805         break;
       
   806     case 0x70:	/* RFBI_DATA_CYCLE2_0 */
       
   807         s->rfbi.data[1] = value & 0x0f1f0f1f;
       
   808         break;
       
   809     case 0x74:	/* RFBI_DATA_CYCLE3_0 */
       
   810         s->rfbi.data[2] = value & 0x0f1f0f1f;
       
   811         break;
       
   812     case 0x78:	/* RFBI_CONFIG1 */
       
   813         s->rfbi.config[1] = value & 0x003f1fff;
       
   814         break;
       
   815 
       
   816     case 0x7c:	/* RFBI_ONOFF_TIME1 */
       
   817         s->rfbi.time[2] = value & 0x3fffffff;
       
   818         break;
       
   819     case 0x80:	/* RFBI_CYCLE_TIME1 */
       
   820         s->rfbi.time[3] = value & 0x0fffffff;
       
   821         break;
       
   822     case 0x84:	/* RFBI_DATA_CYCLE1_1 */
       
   823         s->rfbi.data[3] = value & 0x0f1f0f1f;
       
   824         break;
       
   825     case 0x88:	/* RFBI_DATA_CYCLE2_1 */
       
   826         s->rfbi.data[4] = value & 0x0f1f0f1f;
       
   827         break;
       
   828     case 0x8c:	/* RFBI_DATA_CYCLE3_1 */
       
   829         s->rfbi.data[5] = value & 0x0f1f0f1f;
       
   830         break;
       
   831 
       
   832     case 0x90:	/* RFBI_VSYNC_WIDTH */
       
   833         s->rfbi.vsync = value & 0xffff;
       
   834         break;
       
   835     case 0x94:	/* RFBI_HSYNC_WIDTH */
       
   836         s->rfbi.hsync = value & 0xffff;
       
   837         break;
       
   838 
       
   839     default:
       
   840         OMAP_BAD_REG(addr);
       
   841     }
       
   842 }
       
   843 
       
   844 static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
       
   845     omap_badwidth_read32,
       
   846     omap_badwidth_read32,
       
   847     omap_rfbi_read,
       
   848 };
       
   849 
       
   850 static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
       
   851     omap_badwidth_write32,
       
   852     omap_badwidth_write32,
       
   853     omap_rfbi_write,
       
   854 };
       
   855 
       
   856 static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
       
   857 {
       
   858     switch (addr) {
       
   859     case 0x00:	/* REV_ID */
       
   860     case 0x04:	/* STATUS */
       
   861     case 0x08:	/* F_CONTROL */
       
   862     case 0x10:	/* VIDOUT_CTRL */
       
   863     case 0x14:	/* SYNC_CTRL */
       
   864     case 0x1c:	/* LLEN */
       
   865     case 0x20:	/* FLENS */
       
   866     case 0x24:	/* HFLTR_CTRL */
       
   867     case 0x28:	/* CC_CARR_WSS_CARR */
       
   868     case 0x2c:	/* C_PHASE */
       
   869     case 0x30:	/* GAIN_U */
       
   870     case 0x34:	/* GAIN_V */
       
   871     case 0x38:	/* GAIN_Y */
       
   872     case 0x3c:	/* BLACK_LEVEL */
       
   873     case 0x40:	/* BLANK_LEVEL */
       
   874     case 0x44:	/* X_COLOR */
       
   875     case 0x48:	/* M_CONTROL */
       
   876     case 0x4c:	/* BSTAMP_WSS_DATA */
       
   877     case 0x50:	/* S_CARR */
       
   878     case 0x54:	/* LINE21 */
       
   879     case 0x58:	/* LN_SEL */
       
   880     case 0x5c:	/* L21__WC_CTL */
       
   881     case 0x60:	/* HTRIGGER_VTRIGGER */
       
   882     case 0x64:	/* SAVID__EAVID */
       
   883     case 0x68:	/* FLEN__FAL */
       
   884     case 0x6c:	/* LAL__PHASE_RESET */
       
   885     case 0x70:	/* HS_INT_START_STOP_X */
       
   886     case 0x74:	/* HS_EXT_START_STOP_X */
       
   887     case 0x78:	/* VS_INT_START_X */
       
   888     case 0x7c:	/* VS_INT_STOP_X__VS_INT_START_Y */
       
   889     case 0x80:	/* VS_INT_STOP_Y__VS_INT_START_X */
       
   890     case 0x84:	/* VS_EXT_STOP_X__VS_EXT_START_Y */
       
   891     case 0x88:	/* VS_EXT_STOP_Y */
       
   892     case 0x90:	/* AVID_START_STOP_X */
       
   893     case 0x94:	/* AVID_START_STOP_Y */
       
   894     case 0xa0:	/* FID_INT_START_X__FID_INT_START_Y */
       
   895     case 0xa4:	/* FID_INT_OFFSET_Y__FID_EXT_START_X */
       
   896     case 0xa8:	/* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
       
   897     case 0xb0:	/* TVDETGP_INT_START_STOP_X */
       
   898     case 0xb4:	/* TVDETGP_INT_START_STOP_Y */
       
   899     case 0xb8:	/* GEN_CTRL */
       
   900     case 0xc4:	/* DAC_TST__DAC_A */
       
   901     case 0xc8:	/* DAC_B__DAC_C */
       
   902         return 0;
       
   903 
       
   904     default:
       
   905         break;
       
   906     }
       
   907     OMAP_BAD_REG(addr);
       
   908     return 0;
       
   909 }
       
   910 
       
   911 static void omap_venc_write(void *opaque, target_phys_addr_t addr,
       
   912                 uint32_t value)
       
   913 {
       
   914     switch (addr) {
       
   915     case 0x08:	/* F_CONTROL */
       
   916     case 0x10:	/* VIDOUT_CTRL */
       
   917     case 0x14:	/* SYNC_CTRL */
       
   918     case 0x1c:	/* LLEN */
       
   919     case 0x20:	/* FLENS */
       
   920     case 0x24:	/* HFLTR_CTRL */
       
   921     case 0x28:	/* CC_CARR_WSS_CARR */
       
   922     case 0x2c:	/* C_PHASE */
       
   923     case 0x30:	/* GAIN_U */
       
   924     case 0x34:	/* GAIN_V */
       
   925     case 0x38:	/* GAIN_Y */
       
   926     case 0x3c:	/* BLACK_LEVEL */
       
   927     case 0x40:	/* BLANK_LEVEL */
       
   928     case 0x44:	/* X_COLOR */
       
   929     case 0x48:	/* M_CONTROL */
       
   930     case 0x4c:	/* BSTAMP_WSS_DATA */
       
   931     case 0x50:	/* S_CARR */
       
   932     case 0x54:	/* LINE21 */
       
   933     case 0x58:	/* LN_SEL */
       
   934     case 0x5c:	/* L21__WC_CTL */
       
   935     case 0x60:	/* HTRIGGER_VTRIGGER */
       
   936     case 0x64:	/* SAVID__EAVID */
       
   937     case 0x68:	/* FLEN__FAL */
       
   938     case 0x6c:	/* LAL__PHASE_RESET */
       
   939     case 0x70:	/* HS_INT_START_STOP_X */
       
   940     case 0x74:	/* HS_EXT_START_STOP_X */
       
   941     case 0x78:	/* VS_INT_START_X */
       
   942     case 0x7c:	/* VS_INT_STOP_X__VS_INT_START_Y */
       
   943     case 0x80:	/* VS_INT_STOP_Y__VS_INT_START_X */
       
   944     case 0x84:	/* VS_EXT_STOP_X__VS_EXT_START_Y */
       
   945     case 0x88:	/* VS_EXT_STOP_Y */
       
   946     case 0x90:	/* AVID_START_STOP_X */
       
   947     case 0x94:	/* AVID_START_STOP_Y */
       
   948     case 0xa0:	/* FID_INT_START_X__FID_INT_START_Y */
       
   949     case 0xa4:	/* FID_INT_OFFSET_Y__FID_EXT_START_X */
       
   950     case 0xa8:	/* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
       
   951     case 0xb0:	/* TVDETGP_INT_START_STOP_X */
       
   952     case 0xb4:	/* TVDETGP_INT_START_STOP_Y */
       
   953     case 0xb8:	/* GEN_CTRL */
       
   954     case 0xc4:	/* DAC_TST__DAC_A */
       
   955     case 0xc8:	/* DAC_B__DAC_C */
       
   956         break;
       
   957 
       
   958     default:
       
   959         OMAP_BAD_REG(addr);
       
   960     }
       
   961 }
       
   962 
       
   963 static CPUReadMemoryFunc *omap_venc1_readfn[] = {
       
   964     omap_badwidth_read32,
       
   965     omap_badwidth_read32,
       
   966     omap_venc_read,
       
   967 };
       
   968 
       
   969 static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
       
   970     omap_badwidth_write32,
       
   971     omap_badwidth_write32,
       
   972     omap_venc_write,
       
   973 };
       
   974 
       
   975 static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
       
   976 {
       
   977     switch (addr) {
       
   978     case 0x0a8:	/* SBIMERRLOGA */
       
   979     case 0x0b0:	/* SBIMERRLOG */
       
   980     case 0x190:	/* SBIMSTATE */
       
   981     case 0x198:	/* SBTMSTATE_L */
       
   982     case 0x19c:	/* SBTMSTATE_H */
       
   983     case 0x1a8:	/* SBIMCONFIG_L */
       
   984     case 0x1ac:	/* SBIMCONFIG_H */
       
   985     case 0x1f8:	/* SBID_L */
       
   986     case 0x1fc:	/* SBID_H */
       
   987         return 0;
       
   988 
       
   989     default:
       
   990         break;
       
   991     }
       
   992     OMAP_BAD_REG(addr);
       
   993     return 0;
       
   994 }
       
   995 
       
   996 static void omap_im3_write(void *opaque, target_phys_addr_t addr,
       
   997                 uint32_t value)
       
   998 {
       
   999     switch (addr) {
       
  1000     case 0x0b0:	/* SBIMERRLOG */
       
  1001     case 0x190:	/* SBIMSTATE */
       
  1002     case 0x198:	/* SBTMSTATE_L */
       
  1003     case 0x19c:	/* SBTMSTATE_H */
       
  1004     case 0x1a8:	/* SBIMCONFIG_L */
       
  1005     case 0x1ac:	/* SBIMCONFIG_H */
       
  1006         break;
       
  1007 
       
  1008     default:
       
  1009         OMAP_BAD_REG(addr);
       
  1010     }
       
  1011 }
       
  1012 
       
  1013 static CPUReadMemoryFunc *omap_im3_readfn[] = {
       
  1014     omap_badwidth_read32,
       
  1015     omap_badwidth_read32,
       
  1016     omap_im3_read,
       
  1017 };
       
  1018 
       
  1019 static CPUWriteMemoryFunc *omap_im3_writefn[] = {
       
  1020     omap_badwidth_write32,
       
  1021     omap_badwidth_write32,
       
  1022     omap_im3_write,
       
  1023 };
       
  1024 
       
  1025 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
       
  1026                 target_phys_addr_t l3_base, DisplayState *ds,
       
  1027                 qemu_irq irq, qemu_irq drq,
       
  1028                 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
       
  1029                 omap_clk ick1, omap_clk ick2)
       
  1030 {
       
  1031     int iomemtype[5];
       
  1032     struct omap_dss_s *s = (struct omap_dss_s *)
       
  1033             qemu_mallocz(sizeof(struct omap_dss_s));
       
  1034 
       
  1035     s->irq = irq;
       
  1036     s->drq = drq;
       
  1037     s->state = ds;
       
  1038     omap_dss_reset(s);
       
  1039 
       
  1040     iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn,
       
  1041                     omap_diss1_writefn, s);
       
  1042     iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn,
       
  1043                     omap_disc1_writefn, s);
       
  1044     iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn,
       
  1045                     omap_rfbi1_writefn, s);
       
  1046     iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn,
       
  1047                     omap_venc1_writefn, s);
       
  1048     iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
       
  1049                     omap_im3_writefn, s);
       
  1050     omap_l4_attach(ta, 0, iomemtype[0]);
       
  1051     omap_l4_attach(ta, 1, iomemtype[1]);
       
  1052     omap_l4_attach(ta, 2, iomemtype[2]);
       
  1053     omap_l4_attach(ta, 3, iomemtype[3]);
       
  1054     cpu_register_physical_memory(l3_base, 0x1000, iomemtype[4]);
       
  1055 
       
  1056 #if 0
       
  1057     if (ds)
       
  1058         graphic_console_init(ds, omap_update_display,
       
  1059                         omap_invalidate_display, omap_screen_dump, s);
       
  1060 #endif
       
  1061 
       
  1062     return s;
       
  1063 }
       
  1064 
       
  1065 void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
       
  1066 {
       
  1067     if (cs < 0 || cs > 1)
       
  1068         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
       
  1069     s->rfbi.chip[cs] = chip;
       
  1070 }