packing update
[qemu] / hw / omap_dss.c
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 along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 #include "hw.h"
22 #include "console.h"
23 #include "omap.h"
24 #include "qemu-common.h"
25 #include "sysemu.h"
26 #include "devices.h"
27 #include "vga_int.h"
28 #include "pixel_ops.h"
29
30 #define OMAP_DSS_DEBUG
31 //#define OMAP_DSS_DEBUG_REG
32
33 #ifdef OMAP_DSS_DEBUG
34 #define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
35 #else
36 #define TRACE(...)
37 #endif
38
39 #ifdef OMAP_DSS_DEBUG_REG
40 #define TRACEREG(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
41 #define LAYERNAME(n) ((!(n)) ? "GFX" : ((n)==1) ? "VID1" : "VID2")
42 #else
43 #define TRACEREG(...)
44 #endif
45
46 struct omap3_lcd_panel_s {
47     struct omap_dss_s *dss;
48     DisplayState *state;
49     omap3_lcd_panel_fn_t *line_fn_tab[2];
50     omap3_lcd_panel_fn_t line_fn;
51     uint32_t invalidate;
52 };
53
54 struct omap_dss_s {
55     qemu_irq irq;
56     qemu_irq drq;
57     DisplayState *state;
58
59     int autoidle;
60     int control;
61     uint32_t sdi_control;
62     uint32_t pll_control;
63     int enable;
64
65     struct omap_dss_panel_s {
66         int enable;
67         int nx;
68         int ny;
69
70         int x;
71         int y;
72     } dig, lcd;
73     struct omap3_lcd_panel_s *omap_lcd_panel[2];
74
75     struct {
76         uint8_t rev;
77         uint32_t idlemode;
78         uint32_t irqst;
79         uint32_t irqen;
80         uint32_t control;
81         uint32_t config;
82         uint32_t capable;
83         uint32_t timing[4];
84         int line;
85         uint32_t bg[2];
86         uint32_t trans[2];
87         uint32_t global_alpha;
88         uint32_t cpr_coef_r;
89         uint32_t cpr_coef_g;
90         uint32_t cpr_coef_b;
91         
92         struct omap_dss_plane_s {
93             int enable;
94             int bpp;
95             int posx;
96             int posy;
97             int nx;
98             int ny;
99
100             int rotation_flag;
101             int gfx_format;
102             int gfx_channel;
103             
104             target_phys_addr_t addr[3];
105
106             uint32_t attr;
107             uint32_t tresh;
108             int rowinc;
109             int colinc;
110             int wininc;
111             
112             uint32_t preload;
113             
114             /* following for l1 & l2 only (VID1 and VID2) */
115             uint32_t fir;
116             uint32_t fir_coef_h[8];
117             uint32_t fir_coef_hv[8];
118             uint32_t fir_coef_v[8];
119             uint32_t conv_coef[5];
120             uint32_t picture_size;
121             uint32_t accu[2];
122         } l[3];
123         
124         int invalidate;
125         uint16_t palette[256];
126     } dispc;
127
128     struct {
129         int idlemode;
130         uint32_t control;
131         int enable;
132         int pixels;
133         int busy;
134         int skiplines;
135         uint16_t rxbuf;
136         uint32_t config[2];
137         uint32_t time[4];
138         uint32_t data[6];
139         uint16_t vsync;
140         uint16_t hsync;
141         struct rfbi_chip_s *chip[2];
142     } rfbi;
143     
144     struct {
145         uint32_t irqst;
146         uint32_t irqen;
147     } dsi;
148 };
149
150 static void omap_dss_interrupt_update(struct omap_dss_s *s)
151 {
152     qemu_set_irq(s->irq, 
153                  (s->dsi.irqst & s->dsi.irqen)
154                  | (s->dispc.irqst & s->dispc.irqen));
155 }
156
157 static void omap_rfbi_reset(struct omap_dss_s *s)
158 {
159     s->rfbi.idlemode = 0;
160     s->rfbi.control = 2;
161     s->rfbi.enable = 0;
162     s->rfbi.pixels = 0;
163     s->rfbi.skiplines = 0;
164     s->rfbi.busy = 0;
165     s->rfbi.config[0] = 0x00310000;
166     s->rfbi.config[1] = 0x00310000;
167     s->rfbi.time[0] = 0;
168     s->rfbi.time[1] = 0;
169     s->rfbi.time[2] = 0;
170     s->rfbi.time[3] = 0;
171     s->rfbi.data[0] = 0;
172     s->rfbi.data[1] = 0;
173     s->rfbi.data[2] = 0;
174     s->rfbi.data[3] = 0;
175     s->rfbi.data[4] = 0;
176     s->rfbi.data[5] = 0;
177     s->rfbi.vsync = 0;
178     s->rfbi.hsync = 0;
179 }
180
181 void omap_dss_reset(struct omap_dss_s *s)
182 {
183     int i, j;
184     
185     s->autoidle = 0x10; /* was 0 for OMAP2 but bit4 must be set for OMAP3 */
186     s->control = 0;
187     s->sdi_control = 0;
188     s->pll_control = 0;
189     s->enable = 0;
190
191     s->dig.enable = 0;
192     s->dig.nx = 1;
193     s->dig.ny = 1;
194
195     s->lcd.enable = 0;
196     s->lcd.nx = 1;
197     s->lcd.ny = 1;
198
199     s->dispc.idlemode = 0;
200     s->dispc.irqst = 0;
201     s->dispc.irqen = 0;
202     s->dispc.control = 0;
203     s->dispc.config = 0;
204     s->dispc.capable = 0x161;
205     s->dispc.timing[0] = 0;
206     s->dispc.timing[1] = 0;
207     s->dispc.timing[2] = 0;
208     s->dispc.timing[3] = 0x00010002;
209     s->dispc.line = 0;
210     s->dispc.bg[0] = 0;
211     s->dispc.bg[1] = 0;
212     s->dispc.trans[0] = 0;
213     s->dispc.trans[1] = 0;
214     s->dispc.global_alpha = 0;
215     s->dispc.cpr_coef_r = 0;
216     s->dispc.cpr_coef_g = 0;
217     s->dispc.cpr_coef_b = 0;
218
219     for (i = 0; i < 3; i++) {
220         s->dispc.l[i].enable = 0;
221         s->dispc.l[i].bpp = 0;
222         s->dispc.l[i].addr[0] = 0;
223         s->dispc.l[i].addr[1] = 0;
224         s->dispc.l[i].addr[2] = 0;
225         s->dispc.l[i].posx = 0;
226         s->dispc.l[i].posy = 0;
227         s->dispc.l[i].nx = 1;
228         s->dispc.l[i].ny = 1;
229         s->dispc.l[i].attr = 0;
230         s->dispc.l[i].tresh = (s->dispc.rev < 0x30) ? 0 : 0x03ff03c0;
231         s->dispc.l[i].rowinc = 1;
232         s->dispc.l[i].colinc = 1;
233         s->dispc.l[i].wininc = 0;
234         s->dispc.l[i].preload = 0x100;
235         s->dispc.l[i].fir = 0;
236         s->dispc.l[i].picture_size = 0;
237         s->dispc.l[i].accu[0] = 0;
238         s->dispc.l[i].accu[1] = 0;
239         for (j = 0; j < 5; j++)
240             s->dispc.l[i].conv_coef[j] = 0;
241         for (j = 0; j < 8; j++) {
242             s->dispc.l[i].fir_coef_h[j] = 0;
243             s->dispc.l[i].fir_coef_hv[j] = 0;
244             s->dispc.l[i].fir_coef_v[j] = 0;
245         }
246     }
247         
248     s->dsi.irqst = 0;
249     s->dsi.irqen = 0;
250     
251     omap_rfbi_reset(s);
252     omap_dss_interrupt_update(s);
253 }
254
255 static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
256 {
257     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
258
259
260     switch (addr) {
261     case 0x00:  /* DSS_REVISIONNUMBER */
262         TRACEREG("DSS_REVISIONNUMBER: 0x20");
263         return 0x20;
264
265     case 0x10:  /* DSS_SYSCONFIG */
266         TRACEREG("DSS_SYSCONFIG: 0x%08x", s->autoidle);
267         return s->autoidle;
268
269     case 0x14:  /* DSS_SYSSTATUS */
270         TRACEREG("DSS_SYSSTATUS: 0x1");
271         return 1;                                               /* RESETDONE */
272             
273     case 0x18:  /* DSS_IRQSTATUS */
274         TRACEREG("DSS_IRQSTATUS: 0x%08x",
275                  ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0) 
276                  | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0));
277         return ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0) 
278             | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0);
279             
280     case 0x40:  /* DSS_CONTROL */
281         TRACEREG("DSS_CONTROL: 0x%08x", s->control);
282         return s->control;
283
284     case 0x44:  /* DSS_SDI_CONTROL */
285         TRACEREG("DSS_SDI_CONTROL: 0x%08x", s->sdi_control);
286         return s->sdi_control;
287             
288     case 0x48: /* DSS_PLL_CONTROL */
289         TRACEREG("DSS_PLL_CONTROL: 0x%08x", s->pll_control);
290         return s->pll_control;
291
292     case 0x50:  /* DSS_PSA_LCD_REG_1 */
293     case 0x54:  /* DSS_PSA_LCD_REG_2 */
294     case 0x58:  /* DSS_PSA_VIDEO_REG */
295         TRACEREG("DSS_PSA_xxx: 0");
296         /* TODO: fake some values when appropriate s->control bits are set */
297         return 0;
298
299     case 0x5c:  /* DSS_SDI_STATUS */
300         /* TODO: check and implement missing OMAP3 bits */
301         TRACEREG("DSS_STATUS: 0x%08x", 1 + (s->control & 1));
302         return 1 + (s->control & 1);
303
304     default:
305         break;
306     }
307     OMAP_BAD_REG(addr);
308     return 0;
309 }
310
311 static void omap_diss_write(void *opaque, target_phys_addr_t addr,
312                 uint32_t value)
313 {
314     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
315
316     switch (addr) {
317     case 0x00:  /* DSS_REVISIONNUMBER */
318     case 0x14:  /* DSS_SYSSTATUS */
319     case 0x18:  /* DSS_IRQSTATUS */
320     case 0x50:  /* DSS_PSA_LCD_REG_1 */
321     case 0x54:  /* DSS_PSA_LCD_REG_2 */
322     case 0x58:  /* DSS_PSA_VIDEO_REG */
323     case 0x5c:  /* DSS_STATUS */
324         /* quietly ignore */
325         /*OMAP_RO_REGV(addr, value);*/
326         break;
327
328     case 0x10:  /* DSS_SYSCONFIG */
329         TRACEREG("DSS_SYSCONFIG = 0x%08x", value);
330         if (value & 2)                                          /* SOFTRESET */
331             omap_dss_reset(s);
332         s->autoidle = value & 0x19; /* was 0x01 for OMAP2 */
333         break;
334
335     case 0x40:  /* DSS_CONTROL */
336         TRACEREG("DSS_CONTROL = 0x%08x", value);
337         s->control = value & 0x3ff; /* was 0x3dd for OMAP2 */
338         break;
339
340     case 0x44: /* DSS_SDI_CONTROL */
341         TRACEREG("DSS_SDI_CONTROL = 0x%08x", value);
342         s->sdi_control = value & 0x000ff80f;
343         break;
344
345     case 0x48: /* DSS_PLL_CONTROL */
346         TRACEREG("DSS_PLL_CONTROL = 0x%08x", value);
347         s->pll_control = value;
348         break;
349             
350     default:
351         OMAP_BAD_REGV(addr, value);
352         break;
353     }
354 }
355
356 static CPUReadMemoryFunc *omap_diss1_readfn[] = {
357     omap_badwidth_read32,
358     omap_badwidth_read32,
359     omap_diss_read,
360 };
361
362 static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
363     omap_badwidth_write32,
364     omap_badwidth_write32,
365     omap_diss_write,
366 };
367
368 static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
369 {
370     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
371     int n = 0;
372
373     switch (addr) {
374     case 0x000: /* DISPC_REVISION */
375         TRACEREG("DISPC_REVISION: 0x%08x", s->dispc.rev);
376         return s->dispc.rev;
377     case 0x010: /* DISPC_SYSCONFIG */
378         TRACEREG("DISPC_SYSCONFIG: 0x%08x", s->dispc.idlemode);
379         return s->dispc.idlemode;
380     case 0x014: /* DISPC_SYSSTATUS */
381         TRACEREG("DISPC_SYSSTATUS: 1");
382         return 1;                                               /* RESETDONE */
383     case 0x018: /* DISPC_IRQSTATUS */
384         TRACEREG("DISPC_IRQSTATUS: 0x%08x", s->dispc.irqst);
385         return s->dispc.irqst;
386     case 0x01c: /* DISPC_IRQENABLE */
387         TRACEREG("DISPC_IRQENABLE: 0x%08x", s->dispc.irqen);
388         return s->dispc.irqen;
389     case 0x040: /* DISPC_CONTROL */
390         TRACEREG("DISPC_CONTROL: 0x%08x", s->dispc.control);
391         return s->dispc.control;
392     case 0x044: /* DISPC_CONFIG */
393         TRACEREG("DISPC_CONFIG: 0x%08x", s->dispc.config);
394         return s->dispc.config;
395     case 0x048: /* DISPC_CAPABLE */
396         TRACEREG("DISPC_CAPABLE: 0x%08x", s->dispc.capable);
397         return s->dispc.capable;
398     case 0x04c: /* DISPC_DEFAULT_COLOR0 */
399         TRACEREG("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[0]);
400         return s->dispc.bg[0];
401     case 0x050: /* DISPC_DEFAULT_COLOR1 */
402         TRACEREG("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[1]);
403         return s->dispc.bg[1];
404     case 0x054: /* DISPC_TRANS_COLOR0 */
405         TRACEREG("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[0]);
406         return s->dispc.trans[0];
407     case 0x058: /* DISPC_TRANS_COLOR1 */
408         TRACEREG("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[1]);
409         return s->dispc.trans[1];
410     case 0x05c: /* DISPC_LINE_STATUS */
411         TRACEREG("DISPC_LINE_STATUS: 0x7ff");
412         return 0x7ff;
413     case 0x060: /* DISPC_LINE_NUMBER */
414         TRACEREG("DISPC_LINE_NUMBER: 0x%08x", s->dispc.line);
415         return s->dispc.line;
416     case 0x064: /* DISPC_TIMING_H */
417         TRACEREG("DISPC_TIMING_H: 0x%08x", s->dispc.timing[0]);
418         return s->dispc.timing[0];
419     case 0x068: /* DISPC_TIMING_V */
420         TRACEREG("DISPC_TIMING_H: 0x%08x", s->dispc.timing[1]);
421         return s->dispc.timing[1];
422     case 0x06c: /* DISPC_POL_FREQ */
423         TRACEREG("DISPC_POL_FREQ: 0x%08x", s->dispc.timing[2]);
424         return s->dispc.timing[2];
425     case 0x070: /* DISPC_DIVISOR */
426         TRACEREG("DISPC_DIVISOR: 0x%08x", s->dispc.timing[3]);
427         return s->dispc.timing[3];
428     case 0x074: /* DISPC_GLOBAL_ALPHA */
429         TRACEREG("DISPC_GLOBAL_ALPHA: 0x%08x", s->dispc.global_alpha);
430         return s->dispc.global_alpha;
431     case 0x078: /* DISPC_SIZE_DIG */
432         TRACEREG("DISPC_SIZE_DIG: 0x%08x", ((s->dig.ny - 1) << 16) | (s->dig.nx - 1));
433         return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
434     case 0x07c: /* DISPC_SIZE_LCD */
435         TRACEREG("DISPC_SIZE_LCD: 0x%08x", ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1));
436         return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
437     case 0x14c: /* DISPC_VID2_BA0 */
438         n++;
439     case 0x0bc: /* DISPC_VID1_BA0 */
440         n++;
441     case 0x080: /* DISPC_GFX_BA0 */
442         TRACEREG("DISPC_%s_BA0: 0x%08x", LAYERNAME(n), s->dispc.l[n].addr[0]);
443         return s->dispc.l[n].addr[0];
444     case 0x150: /* DISPC_VID2_BA1 */
445         n++;
446     case 0x0c0: /* DISPC_VID1_BA1 */
447         n++;
448     case 0x084: /* DISPC_GFX_BA1 */
449         TRACEREG("DISPC_%s_BA1: 0x%08x", LAYERNAME(n), s->dispc.l[n].addr[1]);
450         return s->dispc.l[n].addr[1];
451     case 0x154: /* DISPC_VID2_POSITION */
452         n++;
453     case 0x0c4: /* DISPC_VID1_POSITION */
454         n++;
455     case 0x088: /* DISPC_GFX_POSITION */
456         TRACEREG("DISPC_%s_POSITION: 0x%08x", LAYERNAME(n),
457                  (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx);
458         return (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx;
459     case 0x158: /* DISPC_VID2_SIZE */
460         n++;
461     case 0x0c8: /* DISPC_VID1_SIZE */
462         n++;
463     case 0x08c: /* DISPC_GFX_SIZE */
464         TRACEREG("DISPC_%s_SIZE: 0x%08x", LAYERNAME(n),
465                  ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1));
466         return ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1);
467     case 0x15c: /* DISPC_VID2_ATTRIBUTES */
468         n++;
469     case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
470         n++;
471     case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
472         TRACEREG("DISPC_%s_ATTRIBUTES: 0x%08x", LAYERNAME(n),
473                  s->dispc.l[n].attr);
474         return s->dispc.l[n].attr;
475     case 0x160: /* DISPC_VID2_FIFO_THRESHOLD */
476         n++;
477     case 0x0d0: /* DISPC_VID1_FIFO_THRESHOLD */
478         n++;
479     case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
480         TRACEREG("DISPC_%s_THRESHOLD: 0x%08x", LAYERNAME(n),
481                  s->dispc.l[n].tresh);
482         return s->dispc.l[n].tresh;
483     case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */
484         n++;
485     case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */
486         n++;
487     case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
488         TRACEREG("DISPC_%s_FIFO_SIZE_STATUS: 0x%08x", LAYERNAME(n),
489                  s->dispc.rev < 0x30 ? 256 : 1024);
490         return s->dispc.rev < 0x30 ? 256 : 1024;
491     case 0x168: /* DISPC_VID2_ROW_INC */
492         n++;
493     case 0x0d8: /* DISPC_VID1_ROW_INC */
494         n++;
495     case 0x0ac: /* DISPC_GFX_ROW_INC */
496         TRACEREG("DISPC_%s_ROW_INC: 0x%08x", LAYERNAME(n),
497                  s->dispc.l[n].rowinc);
498         return s->dispc.l[n].rowinc;
499     case 0x16c: /* DISPC_VID2_PIXEL_INC */
500         n++;
501     case 0x0dc: /* DISPC_VID1_PIXEL_INC */
502         n++;
503     case 0x0b0: /* DISPC_GFX_PIXEL_INC */
504         TRACEREG("DISPC_%s_PIXEL_INC: 0x%08x", LAYERNAME(n),
505                  s->dispc.l[n].colinc);
506         return s->dispc.l[n].colinc;
507     case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
508         TRACEREG("DISPC_GFX_WINDOW_SKIP: 0x%08x", s->dispc.l[0].wininc);
509         return s->dispc.l[0].wininc;
510     case 0x0b8: /* DISPC_GFX_TABLE_BA */
511         TRACEREG("DISPC_GFX_TABLE_BA: 0x%08x", s->dispc.l[0].addr[2]);
512         return s->dispc.l[0].addr[2];
513     case 0x170: /* DISPC_VID2_FIR */
514         n++;
515     case 0x0e0: /* DISPC_VID1_FIR */
516         n++;
517         TRACEREG("DISPC_%s_FIR: 0x%08x", LAYERNAME(n),
518                  s->dispc.l[n].fir);
519         return s->dispc.l[n].fir;
520     case 0x174: /* DISPC_VID2_PICTURE_SIZE */
521         n++;
522     case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
523         n++;
524         TRACEREG("DISPC_%s_PICTURE_SIZE: 0x%08x", LAYERNAME(n),
525                  s->dispc.l[n].picture_size);
526         return s->dispc.l[n].picture_size;
527     case 0x178: /* DISPC_VID2_ACCU0 */
528     case 0x17c: /* DISPC_VID2_ACCU1 */
529         n++;
530     case 0x0e8: /* DISPC_VID1_ACCU0 */
531     case 0x0ec: /* DISPC_VID1_ACCU1 */
532         n++;
533         TRACEREG("DISPC_%s_ACCU%d: 0x%08x", LAYERNAME(n),
534                  (addr >> 1) & 1, s->dispc.l[n].accu[(addr >> 1 ) & 1]);
535         return s->dispc.l[n].accu[(addr >> 1) & 1];
536     case 0x180 ... 0x1bc:       /* DISPC_VID2_FIR_COEF */
537         n++;
538     case 0x0f0 ... 0x12c:       /* DISPC_VID1_FIR_COEF */
539         n++;
540         if (addr & 4) {
541             TRACEREG("DISPC_%s_FIR_COEF_HV%d: 0x%08x", LAYERNAME(n),
542                      (addr - ((n > 1) ? 0x180 : 0xf0)) / 8,
543                      s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
544             return s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
545         }
546         TRACEREG("DISPC_%s_FIR_COEF_H%d: 0x%08x", LAYERNAME(n),
547                  (addr - ((n > 1) ? 0x180 : 0xf0)) / 8,
548                  s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
549         return s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
550     case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
551         n++;
552     case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
553         n++;
554         TRACEREG("DISPC_%s_CONV_COEF%d: 0x%08x", LAYERNAME(n),
555                  (addr - ((n > 1) ? 0x1c0 : 0x130)) / 4,
556                  s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4]);
557         return s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4];
558     case 0x1d4: /* DISPC_DATA_CYCLE1 */
559     case 0x1d8: /* DISPC_DATA_CYCLE2 */
560     case 0x1dc: /* DISPC_DATA_CYCLE3 */
561         TRACEREG("DISPC_DATA_CYCLE%d: 0", (addr - 0x1d4) / 4);
562         return 0;
563     case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
564         n++;
565     case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
566         n++;
567         TRACEREG("DISPC_%s_FIR_COEF_V%d: 0x%08x", LAYERNAME(n),
568                  (addr & 0x01f) / 4,
569                  s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4]);
570         return s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4];
571     case 0x220: /* DISPC_CPR_COEF_R */
572         TRACEREG("DISPC_CPR_COEF_R: 0x%08x", s->dispc.cpr_coef_r);
573         return s->dispc.cpr_coef_r;
574     case 0x224: /* DISPC_CPR_COEF_G */
575         TRACEREG("DISPC_CPR_COEF_G: 0x%08x", s->dispc.cpr_coef_g);
576         return s->dispc.cpr_coef_g;
577     case 0x228: /* DISPC_CPR_COEF_B */
578         TRACEREG("DISPC_CPR_COEF_B: 0x%08x", s->dispc.cpr_coef_b);
579         return s->dispc.cpr_coef_b;
580     case 0x234: /* DISPC_VID2_PRELOAD */
581         n++;
582     case 0x230: /* DISPC_VID1_PRELOAD */
583         n++;
584     case 0x22c: /* DISPC_GFX_PRELOAD */
585         TRACEREG("DISPC_%s_PRELOAD: 0x%08x", LAYERNAME(n),
586                  s->dispc.l[n].preload);
587         return s->dispc.l[n].preload;
588     default:
589         break;
590     }
591     OMAP_BAD_REG(addr);
592     return 0;
593 }
594
595 static void omap_disc_write(void *opaque, target_phys_addr_t addr,
596                 uint32_t value)
597 {
598     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
599     int n = 0;
600
601     switch (addr) {
602     case 0x000: /* DISPC_REVISION */
603     case 0x014: /* DISPC_SYSSTATUS */
604     case 0x05c: /* DISPC_LINE_STATUS */
605     case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
606         /* quietly ignore */
607         /*OMAP_RO_REGV(addr, value);*/
608         break;
609     case 0x010: /* DISPC_SYSCONFIG */
610         TRACEREG("DISPC_SYSCONFIG = 0x%08x", value);
611         if (value & 2)                                          /* SOFTRESET */
612             omap_dss_reset(s);
613         s->dispc.idlemode = value & ((s->dispc.rev < 0x30) ? 0x301b : 0x331f);
614         break;
615     case 0x018: /* DISPC_IRQSTATUS */
616         TRACEREG("DISPC_IRQSTATUS = 0x%08x", value);
617         s->dispc.irqst &= ~value;
618         omap_dss_interrupt_update(s);
619         break;
620     case 0x01c: /* DISPC_IRQENABLE */
621         TRACEREG("DISPC_IRQENABLE = 0x%08x", value);
622         s->dispc.irqen = value & ((s->dispc.rev < 0x30) ? 0xffff : 0x1ffff);
623         omap_dss_interrupt_update(s);
624         break;
625     case 0x040: /* DISPC_CONTROL */
626         TRACEREG("DISPC_CONTROL = 0x%08x", value);
627         if (s->dispc.rev < 0x30)
628             s->dispc.control = value & 0x07ff9fff;
629         else
630             s->dispc.control = (value & 0xffff9bff) | (s->dispc.control & 0x6000);
631         s->dig.enable = (value >> 1) & 1;
632         s->lcd.enable = (value >> 0) & 1;
633         if (value & (1 << 12))                  /* OVERLAY_OPTIMIZATION */
634             if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
635                  fprintf(stderr, "%s: Overlay Optimization when no overlay "
636                                  "region effectively exists leads to "
637                                  "unpredictable behaviour!\n", __FUNCTION__);
638         if (value & (1 << 6)) {                         /* GODIGITAL */
639             /* XXX: Shadowed fields are:
640              * s->dispc.config
641              * s->dispc.capable
642              * s->dispc.bg[0]
643              * s->dispc.bg[1]
644              * s->dispc.trans[0]
645              * s->dispc.trans[1]
646              * s->dispc.line
647              * s->dispc.timing[0]
648              * s->dispc.timing[1]
649              * s->dispc.timing[2]
650              * s->dispc.timing[3]
651              * s->lcd.nx
652              * s->lcd.ny
653              * s->dig.nx
654              * s->dig.ny
655              * s->dispc.l[0].addr[0]
656              * s->dispc.l[0].addr[1]
657              * s->dispc.l[0].addr[2]
658              * s->dispc.l[0].posx
659              * s->dispc.l[0].posy
660              * s->dispc.l[0].nx
661              * s->dispc.l[0].ny
662              * s->dispc.l[0].tresh
663              * s->dispc.l[0].rowinc
664              * s->dispc.l[0].colinc
665              * s->dispc.l[0].wininc
666              * All they need to be loaded here from their shadow registers.
667              */
668             s->dispc.control &= ~(1 << 6); /* GODIGITAL finished */
669         }
670         if (value & (1 << 5)) {                         /* GOLCD */
671              /* XXX: Likewise for LCD here.  */
672             s->dispc.control &= ~(1 << 5); /* GOLCD finished */
673         }
674         s->dispc.invalidate = 1;
675         break;
676     case 0x044: /* DISPC_CONFIG */
677         TRACEREG("DISPC_CONFIG = 0x%08x", value);
678         s->dispc.config = value & 0x3fff;
679         /* XXX:
680          * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
681          * bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
682          */
683         s->dispc.invalidate = 1;
684         break;
685     case 0x048: /* DISPC_CAPABLE */
686         TRACEREG("DISPC_CAPABLE = 0x%08x", value);
687         s->dispc.capable = value & 0x3ff;
688         break;
689     case 0x04c: /* DISPC_DEFAULT_COLOR0 */
690         TRACEREG("DISPC_DEFAULT_COLOR0 = 0x%08x", value);
691         s->dispc.bg[0] = value & 0xffffff;
692         s->dispc.invalidate = 1;
693         break;
694     case 0x050: /* DISPC_DEFAULT_COLOR1 */
695         TRACEREG("DISPC_DEFAULT_COLOR1 = 0x%08x", value);
696         s->dispc.bg[1] = value & 0xffffff;
697         s->dispc.invalidate = 1;
698         break;
699     case 0x054: /* DISPC_TRANS_COLOR0 */
700         TRACEREG("DISPC_TRANS_COLOR0 = 0x%08x", value);
701         s->dispc.trans[0] = value & 0xffffff;
702         s->dispc.invalidate = 1;
703         break;
704     case 0x058: /* DISPC_TRANS_COLOR1 */
705         TRACEREG("DISPC_TRANS_COLOR1 = 0x%08x", value);
706         s->dispc.trans[1] = value & 0xffffff;
707         s->dispc.invalidate = 1;
708         break;
709     case 0x060: /* DISPC_LINE_NUMBER */
710         TRACEREG("DISPC_LINE_NUMBER = 0x%08x", value);
711         s->dispc.line = value & 0x7ff;
712         break;
713     case 0x064: /* DISPC_TIMING_H */
714         TRACEREG("DISPC_TIMING_H = 0x%08x", value);
715         s->dispc.timing[0] = value & 0x0ff0ff3f;
716         break;
717     case 0x068: /* DISPC_TIMING_V */
718         TRACEREG("DISPC_TIMING_V = 0x%08x", value);
719         s->dispc.timing[1] = value & 0x0ff0ff3f;
720         break;
721     case 0x06c: /* DISPC_POL_FREQ */
722         TRACEREG("DISPC_POL_FREQ = 0x%08x", value);
723         s->dispc.timing[2] = value & 0x0003ffff;
724         break;
725     case 0x070: /* DISPC_DIVISOR */
726         TRACEREG("DISPC_DIVISOR = 0x%08x", value);
727         s->dispc.timing[3] = value & 0x00ff00ff;
728         break;
729     case 0x074: /* DISPC_GLOBAL_ALPHA */
730         TRACEREG("DISPC_GLOBAL_ALPHA = 0x%08x", value);
731         s->dispc.global_alpha = value & 0x00ff00ff;
732         break;
733     case 0x078: /* DISPC_SIZE_DIG */
734         s->dig.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
735         s->dig.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
736         s->dispc.invalidate = 1;
737         TRACEREG("DISPC_SIZE_DIG = 0x%08x (%dx%d)", value, s->dig.nx, s->dig.ny);
738         break;
739     case 0x07c: /* DISPC_SIZE_LCD */
740         s->lcd.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
741         s->lcd.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
742         s->dispc.invalidate = 1;
743         TRACEREG("DISPC_SIZE_LCD = 0x%08x (%dx%d)", value, s->lcd.nx, s->lcd.ny);
744         break;
745     case 0x14c: /* DISPC_VID2_BA0 */
746         n++;
747     case 0x0bc: /* DISPC_VID1_BA0 */
748         n++;
749     case 0x080: /* DISPC_GFX_BA0 */
750         TRACEREG("DISPC_%s_BA0 = 0x%08x", LAYERNAME(n), value);
751         s->dispc.l[n].addr[0] = (target_phys_addr_t) value;
752         s->dispc.invalidate = 1;
753         break;
754     case 0x150: /* DISPC_VID2_BA1 */
755         n++;
756     case 0x0c0: /* DISPC_VID1_BA1 */
757         n++;
758     case 0x084: /* DISPC_GFX_BA1 */
759         TRACEREG("DISPC_%s_BA1 = 0x%08x", LAYERNAME(n), value);
760         s->dispc.l[n].addr[1] = (target_phys_addr_t) value;
761         s->dispc.invalidate = 1;
762         break;
763     case 0x154: /* DISPC_VID2_POSITION */
764         n++;
765     case 0x0c4: /* DISPC_VID1_POSITION */
766         n++;
767     case 0x088: /* DISPC_GFX_POSITION */
768         s->dispc.l[n].posx = ((value >>  0) & 0x7ff);           /* GFXPOSX */
769         s->dispc.l[n].posy = ((value >> 16) & 0x7ff);           /* GFXPOSY */
770         s->dispc.invalidate = 1;
771         TRACEREG("DISPC_%s_POSITION = 0x%08x (%d,%d)", LAYERNAME(n),
772                  value, s->dispc.l[n].posx, s->dispc.l[n].posy);
773         break;
774     case 0x158: /* DISPC_VID2_SIZE */
775         n++;
776     case 0x0c8: /* DISPC_VID1_SIZE */
777         n++;
778     case 0x08c: /* DISPC_GFX_SIZE */
779         s->dispc.l[n].nx = ((value >>  0) & 0x7ff) + 1;         /* GFXSIZEX */
780         s->dispc.l[n].ny = ((value >> 16) & 0x7ff) + 1;         /* GFXSIZEY */
781         TRACEREG("DISPC_%s_SIZE = 0x%08x (%dx%d)", LAYERNAME(n),
782                  value, s->dispc.l[n].nx, s->dispc.l[n].ny);
783         s->dispc.invalidate = 1;
784         break;
785         n++;
786     case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
787         TRACEREG("DISPC_GFX_ATTRIBUTES = 0x%08x", value);
788         s->dispc.l[0].attr = value & 0xffff;
789         if (value & (3 << 9))
790             fprintf(stderr, "%s: Big-endian pixel format not supported\n",
791                             __FUNCTION__);
792         s->dispc.l[0].enable = value & 1;
793         s->dispc.l[0].bpp = (value >> 1) & 0xf;
794         s->dispc.l[0].rotation_flag = (value >> 12) & 0x3;
795         s->dispc.l[0].gfx_format = (value >> 1) & 0xf;
796         s->dispc.l[0].gfx_channel = (value >> 8) & 0x1;
797         s->dispc.invalidate = 1;
798         break;
799     case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
800         n++;
801     case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
802         n++;
803     case 0x0a4: /* DISPC_GFX_FIFO_THRESHOLD */
804         TRACEREG("DISPC_%s_FIFO_THRESHOLD = 0x%08x", LAYERNAME(n), value);
805         s->dispc.l[n].tresh = value & ((s->dispc.rev < 0x30) 
806                                        ? 0x01ff01ff : 0x0fff0fff);
807         break;
808     case 0x168: /* DISPC_VID2_ROW_INC */
809         n++;
810     case 0x0d8: /* DISPC_VID1_ROW_INC */
811         n++;
812     case 0x0ac: /* DISPC_GFX_ROW_INC */
813         TRACEREG("DISPC_%s_ROW_INC = 0x%08x", LAYERNAME(n), value);
814         s->dispc.l[n].rowinc = value;
815         s->dispc.invalidate = 1;
816         break;
817     case 0x16c: /* DISPC_VID2_PIXEL_INC */
818         n++;
819     case 0x0dc: /* DISPC_VID1_PIXEL_INC */
820         n++;
821     case 0x0b0: /* DISPC_GFX_PIXEL_INC */
822         TRACEREG("DISPC_%s_PIXEL_INC = 0x%08x", LAYERNAME(n), value);
823         s->dispc.l[n].colinc = value;
824         s->dispc.invalidate = 1;
825         break;
826     case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
827         TRACEREG("DISPC_GFX_WINDOW_SKIP = 0x%08x", value);
828         s->dispc.l[0].wininc = value;
829         break;
830     case 0x0b8: /* DISPC_GFX_TABLE_BA */
831         TRACEREG("DISPC_GFX_TABLE_BA = 0x%08x", value);
832         s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
833         s->dispc.invalidate = 1;
834         break;
835     case 0x15c: /* DISPC_VID2_ATTRIBUTES */
836         n++;
837     case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
838         n++;
839         TRACEREG("DISPC_%s_ATTRIBUTES = 0x%08x", LAYERNAME(n), value);
840         s->dispc.l[n].attr = value & 0x1fffffff;
841         break;
842     case 0x170: /* DISPC_VID2_FIR */
843         n++;
844     case 0x0e0: /* DISPC_VID1_FIR */
845         n++;
846         TRACEREG("DISPC_%s_FIR = 0x%08x", LAYERNAME(n), value);
847         s->dispc.l[n].fir = value & 0x1fff1fff;
848         break;
849     case 0x174: /* DISPC_VID2_PICTURE_SIZE */
850         n++;
851     case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
852         n++;
853         TRACEREG("DISPC_%s_PICTURE_SIZE = 0x%08x", LAYERNAME(n), value);
854         s->dispc.l[n].picture_size = value & 0x07ff07ff;
855         break;
856     case 0x178: /* DISPC_VID2_ACCU0 */
857     case 0x17c: /* DISPC_VID2_ACCU1 */
858         n++;
859     case 0x0e8: /* DISPC_VID1_ACCU0 */
860     case 0x0ec: /* DISPC_VID1_ACCU1 */
861         n++;
862         TRACEREG("DISPC_%s_ACCU%d = 0x%08x", LAYERNAME(n),
863                  (addr >> 1) & 1, value);
864         s->dispc.l[n].accu[(addr >> 1) & 1] = value & 0x03ff03ff;
865         break;
866     case 0x180 ... 0x1bc:       /* DISPC_VID2_FIR_COEF */
867         n++;
868     case 0x0f0 ... 0x12c:       /* DISPC_VID1_FIR_COEF */
869         n++;
870         if (addr & 4) {
871             TRACEREG("DISPC_%s_FIR_COEF_HV%d = 0x%08x", LAYERNAME(n),
872                      (addr - ((n > 1) ? 0x180 : 0xf0)) / 8, value);
873             s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
874         } else {
875             TRACEREG("DISPC_%s_FIR_COEF_H%d = 0x%08x", LAYERNAME(n),
876                      (addr - ((n > 1) ? 0x180 : 0xf0)) / 8, value);
877             s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
878         }
879         break;
880     case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
881         n++;
882     case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
883         n++;
884         TRACEREG("DISPC_%s_CONV_COEF%d = 0x%08x", LAYERNAME(n),
885                  (addr - ((n > 1) ? 0x1c0 : 0x130)) / 4, value);
886         s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4] = value;
887         break;
888     case 0x1d4: /* DISPC_DATA_CYCLE1 */
889     case 0x1d8: /* DISPC_DATA_CYCLE2 */
890     case 0x1dc: /* DISPC_DATA_CYCLE3 */
891         TRACEREG("DISPC_DATA_CYCLE%d = 0x%08x (ignored)", (addr - 0x1d4) / 4, value);
892         break;
893     case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
894         n++;
895     case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
896         n++;
897         TRACEREG("DISPC_%s_FIR_COEF_V%d = 0x%08x", LAYERNAME(n),
898                  (addr & 0x01f) / 4, value);
899         s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4] = value & 0x0000ffff;
900         break;
901     case 0x220: /* DISPC_CPR_COEF_R */
902         TRACEREG("DISPC_CPR_COEF_R = 0x%08x", value);
903         s->dispc.cpr_coef_r = value & 0xffbffbff;
904         break;
905     case 0x224: /* DISPC_CPR_COEF_G */
906         TRACEREG("DISPC_CPR_COEF_G = 0x%08x", value);
907         s->dispc.cpr_coef_g = value & 0xffbffbff;
908         break;
909     case 0x228: /* DISPC_CPR_COEF_B */
910         TRACEREG("DISPC_CPR_COEF_B = 0x%08x", value);
911         s->dispc.cpr_coef_b = value & 0xffbffbff;
912         break;
913     case 0x234: /* DISPC_VID2_PRELOAD */
914         n++;
915     case 0x230: /* DISPC_VID1_PRELOAD */
916         n++;
917     case 0x22c: /* DISPC_GFX_PRELOAD */
918         TRACEREG("DISPC_%s_PRELOAD = 0x%08x", LAYERNAME(n), value);
919         s->dispc.l[n].preload = value & 0x0fff;
920         break;
921     default:
922         OMAP_BAD_REGV(addr, value);
923         break;
924     }
925 }
926
927 static CPUReadMemoryFunc *omap_disc1_readfn[] = {
928     omap_badwidth_read32,
929     omap_badwidth_read32,
930     omap_disc_read,
931 };
932
933 static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
934     omap_badwidth_write32,
935     omap_badwidth_write32,
936     omap_disc_write,
937 };
938
939 static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
940 {
941     target_phys_addr_t fb;
942     uint32_t pd;
943
944     /* TODO */
945     fb = s->dispc.l[0].addr[0];
946
947     pd = cpu_get_physical_page_desc(fb);
948     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
949         /* TODO */
950         cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
951                         __FUNCTION__);
952     else
953         return phys_ram_base +
954                 (pd & TARGET_PAGE_MASK) +
955                 (fb & ~TARGET_PAGE_MASK);
956 }
957
958 static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
959 {
960     if (!s->rfbi.busy)
961         return;
962
963     /* TODO: in non-Bypass mode we probably need to just deassert the DRQ.  */
964
965     s->rfbi.busy = 0;
966 }
967
968 static void omap_rfbi_transfer_start(struct omap_dss_s *s)
969 {
970     void *data;
971     size_t len;
972     int pitch;
973
974     if (!s->rfbi.enable || s->rfbi.busy)
975         return;
976
977     if (s->rfbi.control & (1 << 1)) {                           /* BYPASS */
978         /* TODO: in non-Bypass mode we probably need to just assert the
979          * DRQ and wait for DMA to write the pixels.  */
980         fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
981         return;
982     }
983
984     if (!(s->dispc.control & (1 << 11)))                        /* RFBIMODE */
985         return;
986     /* TODO: check that LCD output is enabled in DISPC.  */
987
988     s->rfbi.busy = 1;
989
990     data = omap_rfbi_get_buffer(s);
991
992     /* TODO bpp */
993     len = s->rfbi.pixels * 2;
994     s->rfbi.pixels = 0;
995
996     /* TODO: negative values */
997     pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
998
999     if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1000         s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
1001     if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1002         s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
1003
1004     omap_rfbi_transfer_stop(s);
1005
1006     /* TODO */
1007     s->dispc.irqst |= 1;                                        /* FRAMEDONE */
1008     omap_dss_interrupt_update(s);
1009 }
1010
1011 static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
1012 {
1013     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1014
1015     switch (addr) {
1016     case 0x00:  /* RFBI_REVISION */
1017         TRACEREG("RFBI_REVISION: 0x10");
1018         return 0x10;
1019
1020     case 0x10:  /* RFBI_SYSCONFIG */
1021         TRACEREG("RFBI_SYSCONFIG: 0x%08x", s->rfbi.idlemode);
1022         return s->rfbi.idlemode;
1023
1024     case 0x14:  /* RFBI_SYSSTATUS */
1025         TRACEREG("RFBI_SYSSTATUS: 0x%08x", 1 | (s->rfbi.busy << 8));
1026         return 1 | (s->rfbi.busy << 8);                         /* RESETDONE */
1027
1028     case 0x40:  /* RFBI_CONTROL */
1029         TRACEREG("RFBI_CONTROL: 0x%08x", s->rfbi.control);
1030         return s->rfbi.control;
1031
1032     case 0x44:  /* RFBI_PIXELCNT */
1033         TRACEREG("RFBI_PIXELCNT: 0x%08x", s->rfbi.pixels);
1034         return s->rfbi.pixels;
1035
1036     case 0x48:  /* RFBI_LINE_NUMBER */
1037         TRACEREG("RFBI_LINE_NUMBER: 0x%08x", s->rfbi.skiplines);
1038         return s->rfbi.skiplines;
1039
1040     case 0x58:  /* RFBI_READ */
1041     case 0x5c:  /* RFBI_STATUS */
1042         TRACEREG("RFBI_READ/STATUS: 0x%08x", s->rfbi.rxbuf);
1043         return s->rfbi.rxbuf;
1044
1045     case 0x60:  /* RFBI_CONFIG0 */
1046         TRACEREG("RFBI_CONFIG0: 0x%08x", s->rfbi.config[0]);
1047         return s->rfbi.config[0];
1048     case 0x64:  /* RFBI_ONOFF_TIME0 */
1049         TRACEREG("RFBI_ONOFF_TIME0: 0x%08x", s->rfbi.time[0]);
1050         return s->rfbi.time[0];
1051     case 0x68:  /* RFBI_CYCLE_TIME0 */
1052         TRACEREG("RFBI_CYCLE_TIME0: 0x%08x", s->rfbi.time[1]);
1053         return s->rfbi.time[1];
1054     case 0x6c:  /* RFBI_DATA_CYCLE1_0 */
1055         TRACEREG("RFBI_DATA_CYCLE1_0: 0x%08x", s->rfbi.data[0]);
1056         return s->rfbi.data[0];
1057     case 0x70:  /* RFBI_DATA_CYCLE2_0 */
1058         TRACEREG("RFBI_DATA_CYCLE2_0: 0x%08x", s->rfbi.data[1]);
1059         return s->rfbi.data[1];
1060     case 0x74:  /* RFBI_DATA_CYCLE3_0 */
1061         TRACEREG("RFBI_DATA_CYCLE3_0: 0x%08x", s->rfbi.data[2]);
1062         return s->rfbi.data[2];
1063
1064     case 0x78:  /* RFBI_CONFIG1 */
1065         TRACEREG("RFBI_CONFIG1: 0x%08x", s->rfbi.config[1]);
1066         return s->rfbi.config[1];
1067     case 0x7c:  /* RFBI_ONOFF_TIME1 */
1068         TRACEREG("RFBI_ONOFF_TIME1: 0x%08x", s->rfbi.time[2]);
1069         return s->rfbi.time[2];
1070     case 0x80:  /* RFBI_CYCLE_TIME1 */
1071         TRACEREG("RFBI_CYCLE_TIME1: 0x%08x", s->rfbi.time[3]);
1072         return s->rfbi.time[3];
1073     case 0x84:  /* RFBI_DATA_CYCLE1_1 */
1074         TRACEREG("RFBI_DATA_CYCLE1_1: 0x%08x", s->rfbi.data[3]);
1075         return s->rfbi.data[3];
1076     case 0x88:  /* RFBI_DATA_CYCLE2_1 */
1077         TRACEREG("RFBI_DATA_CYCLE2_1: 0x%08x", s->rfbi.data[4]);
1078         return s->rfbi.data[4];
1079     case 0x8c:  /* RFBI_DATA_CYCLE3_1 */
1080         TRACEREG("RFBI_DATA_CYCLE3_1: 0x%08x", s->rfbi.data[5]);
1081         return s->rfbi.data[5];
1082
1083     case 0x90:  /* RFBI_VSYNC_WIDTH */
1084         TRACEREG("RFBI_VSYNC_WIDTH: 0x%08x", s->rfbi.vsync);
1085         return s->rfbi.vsync;
1086     case 0x94:  /* RFBI_HSYNC_WIDTH */
1087         TRACEREG("RFBI_HSYNC_WIDTH: 0x%08x", s->rfbi.hsync);
1088         return s->rfbi.hsync;
1089     }
1090     OMAP_BAD_REG(addr);
1091     return 0;
1092 }
1093
1094 static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
1095                 uint32_t value)
1096 {
1097     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1098
1099     switch (addr) {
1100     case 0x10:  /* RFBI_SYSCONFIG */
1101         TRACEREG("RFBI_SYSCONFIG = 0x%08x", value);
1102         if (value & 2)                                          /* SOFTRESET */
1103             omap_rfbi_reset(s);
1104         s->rfbi.idlemode = value & 0x19;
1105         break;
1106
1107     case 0x40:  /* RFBI_CONTROL */
1108         TRACEREG("RFBI_CONTROL = 0x%08x", value);
1109         s->rfbi.control = value & 0xf;
1110         s->rfbi.enable = value & 1;
1111         if (value & (1 << 4) &&                                 /* ITE */
1112                         !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
1113             omap_rfbi_transfer_start(s);
1114         break;
1115
1116     case 0x44:  /* RFBI_PIXELCNT */
1117         TRACEREG("RFBI_PIXELCNT = 0x%08x", value);
1118         s->rfbi.pixels = value;
1119         break;
1120
1121     case 0x48:  /* RFBI_LINE_NUMBER */
1122         TRACEREG("RFBI_LINE_NUMBER = 0x%08x", value);
1123         s->rfbi.skiplines = value & 0x7ff;
1124         break;
1125
1126     case 0x4c:  /* RFBI_CMD */
1127         TRACEREG("RFBI_CMD = 0x%08x", value);
1128         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1129             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
1130         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1131             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
1132         break;
1133     case 0x50:  /* RFBI_PARAM */
1134         TRACEREG("RFBI_PARAM = 0x%08x", value);
1135         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1136             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1137         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1138             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1139         break;
1140     case 0x54:  /* RFBI_DATA */
1141         TRACEREG("RFBI_DATA = 0x%08x", value);
1142         /* TODO: take into account the format set up in s->rfbi.config[?] and
1143          * s->rfbi.data[?], but special-case the most usual scenario so that
1144          * speed doesn't suffer.  */
1145         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
1146             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1147             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
1148         }
1149         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
1150             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1151             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
1152         }
1153         if (!-- s->rfbi.pixels)
1154             omap_rfbi_transfer_stop(s);
1155         break;
1156     case 0x58:  /* RFBI_READ */
1157         TRACEREG("RFBI_READ = 0x%08x", value);
1158         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1159             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
1160         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1161             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
1162         if (!-- s->rfbi.pixels)
1163             omap_rfbi_transfer_stop(s);
1164         break;
1165
1166     case 0x5c:  /* RFBI_STATUS */
1167         TRACEREG("RFBI_STATUS = 0x%08x", value);
1168         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1169             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
1170         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1171             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
1172         if (!-- s->rfbi.pixels)
1173             omap_rfbi_transfer_stop(s);
1174         break;
1175
1176     case 0x60:  /* RFBI_CONFIG0 */
1177         TRACEREG("RFBI_CONFIG0 = 0x%08x", value);
1178         s->rfbi.config[0] = value & 0x003f1fff;
1179         break;
1180
1181     case 0x64:  /* RFBI_ONOFF_TIME0 */
1182         TRACEREG("RFBI_ONOFF_TIME0 = 0x%08x", value);
1183         s->rfbi.time[0] = value & 0x3fffffff;
1184         break;
1185     case 0x68:  /* RFBI_CYCLE_TIME0 */
1186         TRACEREG("RFBI_CYCLE_TIME0 = 0x%08x", value);
1187         s->rfbi.time[1] = value & 0x0fffffff;
1188         break;
1189     case 0x6c:  /* RFBI_DATA_CYCLE1_0 */
1190         TRACEREG("RFBI_DATA_CYCLE1_0 = 0x%08x", value);
1191         s->rfbi.data[0] = value & 0x0f1f0f1f;
1192         break;
1193     case 0x70:  /* RFBI_DATA_CYCLE2_0 */
1194         TRACEREG("RFBI_DATA_CYCLE2_0 = 0x%08x", value);
1195         s->rfbi.data[1] = value & 0x0f1f0f1f;
1196         break;
1197     case 0x74:  /* RFBI_DATA_CYCLE3_0 */
1198         TRACEREG("RFBI_DATA_CYCLE3_0 = 0x%08x", value);
1199         s->rfbi.data[2] = value & 0x0f1f0f1f;
1200         break;
1201     case 0x78:  /* RFBI_CONFIG1 */
1202         TRACEREG("RFBI_CONFIG1 = 0x%08x", value);
1203         s->rfbi.config[1] = value & 0x003f1fff;
1204         break;
1205
1206     case 0x7c:  /* RFBI_ONOFF_TIME1 */
1207         TRACEREG("RFBI_ONOFF_TIME1 = 0x%08x", value);
1208         s->rfbi.time[2] = value & 0x3fffffff;
1209         break;
1210     case 0x80:  /* RFBI_CYCLE_TIME1 */
1211         TRACEREG("RFBI_CYCLE_TIME1 = 0x%08x", value);
1212         s->rfbi.time[3] = value & 0x0fffffff;
1213         break;
1214     case 0x84:  /* RFBI_DATA_CYCLE1_1 */
1215         TRACEREG("RFBI_DATA_CYCLE1_1 = 0x%08x", value);
1216         s->rfbi.data[3] = value & 0x0f1f0f1f;
1217         break;
1218     case 0x88:  /* RFBI_DATA_CYCLE2_1 */
1219         TRACEREG("RFBI_DATA_CYCLE2_1 = 0x%08x", value);
1220         s->rfbi.data[4] = value & 0x0f1f0f1f;
1221         break;
1222     case 0x8c:  /* RFBI_DATA_CYCLE3_1 */
1223         TRACEREG("RFBI_DATA_CYCLE3_1 = 0x%08x", value);
1224         s->rfbi.data[5] = value & 0x0f1f0f1f;
1225         break;
1226
1227     case 0x90:  /* RFBI_VSYNC_WIDTH */
1228         TRACEREG("RFBI_VSYNC_WIDTH = 0x%08x", value);
1229         s->rfbi.vsync = value & 0xffff;
1230         break;
1231     case 0x94:  /* RFBI_HSYNC_WIDTH */
1232         TRACEREG("RFBI_HSYNC_WIDTH = 0x%08x", value);
1233         s->rfbi.hsync = value & 0xffff;
1234         break;
1235
1236     default:
1237         OMAP_BAD_REGV(addr, value);
1238         break;
1239     }
1240 }
1241
1242 static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
1243     omap_badwidth_read32,
1244     omap_badwidth_read32,
1245     omap_rfbi_read,
1246 };
1247
1248 static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
1249     omap_badwidth_write32,
1250     omap_badwidth_write32,
1251     omap_rfbi_write,
1252 };
1253
1254 static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
1255 {
1256     switch (addr) {
1257     case 0x00:  /* REV_ID */
1258     case 0x04:  /* STATUS */
1259     case 0x08:  /* F_CONTROL */
1260     case 0x10:  /* VIDOUT_CTRL */
1261     case 0x14:  /* SYNC_CTRL */
1262     case 0x1c:  /* LLEN */
1263     case 0x20:  /* FLENS */
1264     case 0x24:  /* HFLTR_CTRL */
1265     case 0x28:  /* CC_CARR_WSS_CARR */
1266     case 0x2c:  /* C_PHASE */
1267     case 0x30:  /* GAIN_U */
1268     case 0x34:  /* GAIN_V */
1269     case 0x38:  /* GAIN_Y */
1270     case 0x3c:  /* BLACK_LEVEL */
1271     case 0x40:  /* BLANK_LEVEL */
1272     case 0x44:  /* X_COLOR */
1273     case 0x48:  /* M_CONTROL */
1274     case 0x4c:  /* BSTAMP_WSS_DATA */
1275     case 0x50:  /* S_CARR */
1276     case 0x54:  /* LINE21 */
1277     case 0x58:  /* LN_SEL */
1278     case 0x5c:  /* L21__WC_CTL */
1279     case 0x60:  /* HTRIGGER_VTRIGGER */
1280     case 0x64:  /* SAVID__EAVID */
1281     case 0x68:  /* FLEN__FAL */
1282     case 0x6c:  /* LAL__PHASE_RESET */
1283     case 0x70:  /* HS_INT_START_STOP_X */
1284     case 0x74:  /* HS_EXT_START_STOP_X */
1285     case 0x78:  /* VS_INT_START_X */
1286     case 0x7c:  /* VS_INT_STOP_X__VS_INT_START_Y */
1287     case 0x80:  /* VS_INT_STOP_Y__VS_INT_START_X */
1288     case 0x84:  /* VS_EXT_STOP_X__VS_EXT_START_Y */
1289     case 0x88:  /* VS_EXT_STOP_Y */
1290     case 0x90:  /* AVID_START_STOP_X */
1291     case 0x94:  /* AVID_START_STOP_Y */
1292     case 0xa0:  /* FID_INT_START_X__FID_INT_START_Y */
1293     case 0xa4:  /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1294     case 0xa8:  /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1295     case 0xb0:  /* TVDETGP_INT_START_STOP_X */
1296     case 0xb4:  /* TVDETGP_INT_START_STOP_Y */
1297     case 0xb8:  /* GEN_CTRL */
1298     case 0xc4:  /* DAC_TST__DAC_A */
1299     case 0xc8:  /* DAC_B__DAC_C */
1300         return 0;
1301
1302     default:
1303         break;
1304     }
1305     OMAP_BAD_REG(addr);
1306     return 0;
1307 }
1308
1309 static void omap_venc_write(void *opaque, target_phys_addr_t addr,
1310                 uint32_t value)
1311 {
1312     switch (addr) {
1313     case 0x08:  /* F_CONTROL */
1314     case 0x10:  /* VIDOUT_CTRL */
1315     case 0x14:  /* SYNC_CTRL */
1316     case 0x1c:  /* LLEN */
1317     case 0x20:  /* FLENS */
1318     case 0x24:  /* HFLTR_CTRL */
1319     case 0x28:  /* CC_CARR_WSS_CARR */
1320     case 0x2c:  /* C_PHASE */
1321     case 0x30:  /* GAIN_U */
1322     case 0x34:  /* GAIN_V */
1323     case 0x38:  /* GAIN_Y */
1324     case 0x3c:  /* BLACK_LEVEL */
1325     case 0x40:  /* BLANK_LEVEL */
1326     case 0x44:  /* X_COLOR */
1327     case 0x48:  /* M_CONTROL */
1328     case 0x4c:  /* BSTAMP_WSS_DATA */
1329     case 0x50:  /* S_CARR */
1330     case 0x54:  /* LINE21 */
1331     case 0x58:  /* LN_SEL */
1332     case 0x5c:  /* L21__WC_CTL */
1333     case 0x60:  /* HTRIGGER_VTRIGGER */
1334     case 0x64:  /* SAVID__EAVID */
1335     case 0x68:  /* FLEN__FAL */
1336     case 0x6c:  /* LAL__PHASE_RESET */
1337     case 0x70:  /* HS_INT_START_STOP_X */
1338     case 0x74:  /* HS_EXT_START_STOP_X */
1339     case 0x78:  /* VS_INT_START_X */
1340     case 0x7c:  /* VS_INT_STOP_X__VS_INT_START_Y */
1341     case 0x80:  /* VS_INT_STOP_Y__VS_INT_START_X */
1342     case 0x84:  /* VS_EXT_STOP_X__VS_EXT_START_Y */
1343     case 0x88:  /* VS_EXT_STOP_Y */
1344     case 0x90:  /* AVID_START_STOP_X */
1345     case 0x94:  /* AVID_START_STOP_Y */
1346     case 0xa0:  /* FID_INT_START_X__FID_INT_START_Y */
1347     case 0xa4:  /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1348     case 0xa8:  /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1349     case 0xb0:  /* TVDETGP_INT_START_STOP_X */
1350     case 0xb4:  /* TVDETGP_INT_START_STOP_Y */
1351     case 0xb8:  /* GEN_CTRL */
1352     case 0xc4:  /* DAC_TST__DAC_A */
1353     case 0xc8:  /* DAC_B__DAC_C */
1354         break;
1355
1356     default:
1357         OMAP_BAD_REGV(addr, value);
1358         break;
1359     }
1360 }
1361
1362 static CPUReadMemoryFunc *omap_venc1_readfn[] = {
1363     omap_badwidth_read32,
1364     omap_badwidth_read32,
1365     omap_venc_read,
1366 };
1367
1368 static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
1369     omap_badwidth_write32,
1370     omap_badwidth_write32,
1371     omap_venc_write,
1372 };
1373
1374 static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
1375 {
1376     switch (addr) {
1377     case 0x0a8: /* SBIMERRLOGA */
1378     case 0x0b0: /* SBIMERRLOG */
1379     case 0x190: /* SBIMSTATE */
1380     case 0x198: /* SBTMSTATE_L */
1381     case 0x19c: /* SBTMSTATE_H */
1382     case 0x1a8: /* SBIMCONFIG_L */
1383     case 0x1ac: /* SBIMCONFIG_H */
1384     case 0x1f8: /* SBID_L */
1385     case 0x1fc: /* SBID_H */
1386         return 0;
1387
1388     default:
1389         break;
1390     }
1391     OMAP_BAD_REG(addr);
1392     return 0;
1393 }
1394
1395 static void omap_im3_write(void *opaque, target_phys_addr_t addr,
1396                 uint32_t value)
1397 {
1398     switch (addr) {
1399     case 0x0b0: /* SBIMERRLOG */
1400     case 0x190: /* SBIMSTATE */
1401     case 0x198: /* SBTMSTATE_L */
1402     case 0x19c: /* SBTMSTATE_H */
1403     case 0x1a8: /* SBIMCONFIG_L */
1404     case 0x1ac: /* SBIMCONFIG_H */
1405         break;
1406
1407     default:
1408         OMAP_BAD_REGV(addr, value);
1409         break;
1410     }
1411 }
1412
1413 static CPUReadMemoryFunc *omap_im3_readfn[] = {
1414     omap_badwidth_read32,
1415     omap_badwidth_read32,
1416     omap_im3_read,
1417 };
1418
1419 static CPUWriteMemoryFunc *omap_im3_writefn[] = {
1420     omap_badwidth_write32,
1421     omap_badwidth_write32,
1422     omap_im3_write,
1423 };
1424
1425 static uint32_t omap_dsi_read(void *opaque, target_phys_addr_t addr)
1426 {
1427     fprintf(stderr, "%s: DSI register " OMAP_FMT_plx " not implemented!\n",
1428             __FUNCTION__, addr);
1429     return 0;
1430 }
1431
1432 static void omap_dsi_write(void *opaque, target_phys_addr_t addr,
1433                            uint32_t value)
1434 {
1435     fprintf(stderr, "%s: DSI register " OMAP_FMT_plx " not implemented!\n",
1436             __FUNCTION__, addr);
1437 }
1438
1439 static CPUReadMemoryFunc *omap_dsi_readfn[] = {
1440     omap_badwidth_read32,
1441     omap_badwidth_read32,
1442     omap_dsi_read,
1443 };
1444
1445 static CPUWriteMemoryFunc *omap_dsi_writefn[] = {
1446     omap_badwidth_write32,
1447     omap_badwidth_write32,
1448     omap_dsi_write,
1449 };
1450
1451 struct omap_dss_s *omap_dss_init(struct omap_mpu_state_s *mpu,
1452                                  struct omap_target_agent_s *ta,
1453                                  qemu_irq irq, qemu_irq drq,
1454                                  omap_clk fck1, omap_clk fck2, omap_clk ck54m,
1455                                  omap_clk ick1, omap_clk ick2)
1456 {
1457     int iomemtype[5];
1458     int region_base = 0;
1459     struct omap_dss_s *s = (struct omap_dss_s *)
1460             qemu_mallocz(sizeof(struct omap_dss_s));
1461
1462     s->irq = irq;
1463     s->drq = drq;
1464
1465     iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn,
1466                                          omap_diss1_writefn, s);
1467     iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn,
1468                                          omap_disc1_writefn, s);
1469     iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn,
1470                                          omap_rfbi1_writefn, s);
1471     iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn,
1472                                          omap_venc1_writefn, s);
1473
1474     if (cpu_class_omap3(mpu)) {
1475         s->dispc.rev = 0x30;
1476         
1477         iomemtype[4] = l4_register_io_memory(0, omap_dsi_readfn,
1478                                              omap_dsi_writefn, s);
1479         omap_l4_attach(ta, 0, iomemtype[4]);
1480         region_base = 1;
1481     } else {
1482         s->dispc.rev = 0x20;
1483         
1484         iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
1485                                               omap_im3_writefn, s);
1486         cpu_register_physical_memory(0x68000800, 0x1000, iomemtype[4]);
1487     }
1488     
1489     omap_l4_attach(ta, region_base+0, iomemtype[0]); /* DISS */
1490     omap_l4_attach(ta, region_base+1, iomemtype[1]); /* DISC */
1491     omap_l4_attach(ta, region_base+2, iomemtype[2]); /* RFBI */
1492     omap_l4_attach(ta, region_base+3, iomemtype[3]); /* VENC */
1493
1494     omap_dss_reset(s);
1495
1496 #if 0
1497     s->state = graphic_console_init(omap_update_display,
1498                                     omap_invalidate_display, omap_screen_dump, s);
1499 #endif
1500
1501     return s;
1502 }
1503
1504 void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
1505 {
1506     if (cs < 0 || cs > 1)
1507         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1508     s->rfbi.chip[cs] = chip;
1509 }
1510
1511 void omap3_lcd_panel_attach(struct omap_dss_s *dss,
1512                             int cs,
1513                             struct omap3_lcd_panel_s *lcd_panel)
1514 {
1515     if (cs < 0 || cs > 1)
1516         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1517     dss->omap_lcd_panel[cs] = lcd_panel;
1518         lcd_panel->dss = dss;
1519 }
1520
1521 /*omap3 lcd panel stuff*/
1522
1523 /* Bytes(!) per pixel */
1524 static const int omap3_lcd_panel_bpp[0x10] = {
1525     0,  /* 0x0: BITMAP1 (CLUT) */
1526     0,  /* 0x1: BITMAP2 (CLUT) */
1527     0,  /* 0x2: BITMAP4 (CLUT) */
1528     0,  /* 0x3: BITMAP8 (CLUT) */
1529     2,  /* 0x4: RGB12 (unpacked 16-bit container)*/
1530     2,  /* 0x5: ARGB16 */
1531     2,  /* 0x6: RGB16 */
1532     0,  /* 0x7: reserved */
1533     4,  /* 0x8: RGB24 (unpacked in 32-bit container) */
1534     3,  /* 0x9: RGB24 (packed in 24-bit container) */
1535     0,  /* 0xa: reserved */
1536     0,  /* 0xb: reserved */
1537     4,  /* 0xc: ARGB32 */
1538     4,  /* 0xd: RGBA32 */
1539     4,  /* 0xe: RGBx32 (24-bit RGB aligned on MSB of the 32-bit container) */
1540     0,  /* 0xf: reserved */
1541 };
1542
1543 static inline void omap3_lcd_panel_invalidate_display(void *opaque) 
1544 {
1545     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1546     s->invalidate = 1;
1547 }
1548
1549 static void omap3_lcd_panel_update_display(void *opaque)
1550 {
1551     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1552     struct omap_dss_s *dss = s->dss;
1553     const uint32_t lcd_width = dss->lcd.nx;
1554     const uint32_t lcd_height = dss->lcd.ny;
1555     uint32_t graphic_width, graphic_height;
1556     uint32_t start_x, start_y;
1557     const uint32_t lcd_Bpp = omap3_lcd_panel_bpp[dss->dispc.l[0].gfx_format];
1558     uint32_t dss_Bpp;
1559     uint32_t linesize, y;
1560     uint32_t copy_width, copy_height;
1561     uint8_t *src, *dest;
1562
1563     if (!dss->lcd.enable
1564         || dss->dispc.l[0].gfx_channel /* 24bit digital out */
1565         || ((dss->dispc.control & (1 << 11))) /* RFBI */
1566         || !lcd_Bpp)
1567         return;
1568     
1569     /* check for setup changes since last visit only if flagged */
1570     if (dss->dispc.invalidate) {
1571         dss->dispc.invalidate = 0;
1572         if (!(dss->dispc.l[0].rotation_flag)) {   /* rotation*/
1573             s->line_fn = s->line_fn_tab[0][dss->dispc.l[0].gfx_format];
1574         } else {
1575             fprintf(stderr, "%s: rotation is not supported \n", __FUNCTION__);
1576             exit(1);
1577         }
1578         if (!s->line_fn) {
1579             fprintf(stderr, "%s:s->line_fn is NULL. Not supported gfx_format \n", __FUNCTION__);
1580             exit(1);
1581         }
1582         if (lcd_width != ds_get_width(s->state) 
1583             || lcd_height != ds_get_height(s->state)) {
1584             qemu_console_resize(s->state, lcd_width, lcd_height);
1585             s->invalidate = 1;
1586         }
1587     }
1588     
1589     /* Resolution */
1590     graphic_width = dss->dispc.l[0].nx;
1591     graphic_height = dss->dispc.l[0].ny;
1592     start_x = dss->dispc.l[0].posx;
1593     start_y = dss->dispc.l[0].posy;
1594
1595     /*use the rfbi function*/
1596     src = (uint8_t *)omap_rfbi_get_buffer(dss);
1597     dest = ds_get_data(s->state);
1598     linesize = ds_get_linesize(s->state);
1599
1600     dss_Bpp = linesize / ds_get_width(s->state);
1601
1602     dest += linesize * start_y;
1603     dest += start_x * dss_Bpp;
1604
1605     if ((start_x + graphic_width) > lcd_width)
1606         copy_width = lcd_width - start_x;
1607     else
1608         copy_width = graphic_width;
1609     copy_height = lcd_height>graphic_height ? graphic_height:lcd_height;
1610
1611     for (y = start_y; y < copy_height; y++) {
1612         s->line_fn(dest, src, copy_width * lcd_Bpp);
1613         src += graphic_width * lcd_Bpp;
1614         dest += linesize;
1615     }
1616
1617     dpy_update(s->state, start_x, start_y, graphic_width, graphic_height);
1618     s->invalidate = 0;
1619     
1620     dss->dispc.irqst |= 1; /* FRAMEDONE */
1621     omap_dss_interrupt_update(dss);
1622 }
1623
1624 /*omap lcd stuff*/
1625 #define DEPTH 8
1626 #include "omap3_lcd_panel_template.h"
1627 #define DEPTH 15
1628 #include "omap3_lcd_panel_template.h"
1629 #define DEPTH 16
1630 #include "omap3_lcd_panel_template.h"
1631 #define DEPTH 24
1632 #include "omap3_lcd_panel_template.h"
1633 #define DEPTH 32
1634 #include "omap3_lcd_panel_template.h"
1635
1636 void *omap3_lcd_panel_init()
1637 {
1638     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *) qemu_mallocz(sizeof(*s));
1639
1640     s->state = graphic_console_init(omap3_lcd_panel_update_display,
1641                                     omap3_lcd_panel_invalidate_display,
1642                                     NULL, NULL, s);
1643
1644     switch (ds_get_bits_per_pixel(s->state)) {
1645     case 0:
1646         s->line_fn_tab[0] = s->line_fn_tab[1] =
1647             qemu_mallocz(sizeof(omap3_lcd_panel_fn_t) * 0x10);
1648         break;
1649     case 8:
1650         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_8;
1651         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_8;
1652         break;
1653     case 15:
1654         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_15;
1655         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_15;
1656         break;
1657     case 16:
1658         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_16;
1659         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_16;
1660         break;
1661     case 24:
1662         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_24;
1663         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_24;
1664         break;
1665     case 32:
1666         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_32;
1667         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_32;
1668         break;
1669     default:
1670         fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
1671         exit(1);
1672     }
1673
1674     return s;
1675 }