58283e5fc3ca838141507a878a1156d14a9572e1
[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 struct omap_dss_s {
31     qemu_irq irq;
32     qemu_irq drq;
33     DisplayState *state;
34
35     int autoidle;
36     int control;
37     uint32_t sdi_control;
38     int enable;
39
40     struct omap_dss_panel_s {
41         int enable;
42         int active;
43         int nx;
44         int ny;
45
46         int x;
47         int y;
48     } dig, lcd;
49     struct omap3_lcd_panel_s *omap_lcd_panel[2];
50
51     struct {
52         uint32_t idlemode;
53         uint32_t irqst;
54         uint32_t irqen;
55         uint32_t control;
56         uint32_t config;
57         uint32_t capable;
58         uint32_t timing[4];
59         int line;
60         uint32_t bg[2];
61         uint32_t trans[2];
62
63         struct omap_dss_plane_s {
64             int enable;
65             int bpp;
66             int posx;
67             int posy;
68             int nx;
69             int ny;
70
71             int rotation_flag;
72             int gfx_format;
73             int gfx_channel;
74             
75             target_phys_addr_t addr[3];
76
77             uint32_t attr;
78             uint32_t tresh;
79             int rowinc;
80             int colinc;
81             int wininc;
82         } l[3];
83
84         int invalidate;
85         uint16_t palette[256];
86     } dispc;
87
88     struct {
89         int idlemode;
90         uint32_t control;
91         int enable;
92         int pixels;
93         int busy;
94         int skiplines;
95         uint16_t rxbuf;
96         uint32_t config[2];
97         uint32_t time[4];
98         uint32_t data[6];
99         uint16_t vsync;
100         uint16_t hsync;
101         struct rfbi_chip_s *chip[2];
102     } rfbi;
103     
104     struct {
105         uint32_t irqst;
106     } dsi;
107 };
108
109 static void omap_dispc_interrupt_update(struct omap_dss_s *s)
110 {
111     qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen);
112 }
113
114 static void omap_rfbi_reset(struct omap_dss_s *s)
115 {
116     s->rfbi.idlemode = 0;
117     s->rfbi.control = 2;
118     s->rfbi.enable = 0;
119     s->rfbi.pixels = 0;
120     s->rfbi.skiplines = 0;
121     s->rfbi.busy = 0;
122     s->rfbi.config[0] = 0x00310000;
123     s->rfbi.config[1] = 0x00310000;
124     s->rfbi.time[0] = 0;
125     s->rfbi.time[1] = 0;
126     s->rfbi.time[2] = 0;
127     s->rfbi.time[3] = 0;
128     s->rfbi.data[0] = 0;
129     s->rfbi.data[1] = 0;
130     s->rfbi.data[2] = 0;
131     s->rfbi.data[3] = 0;
132     s->rfbi.data[4] = 0;
133     s->rfbi.data[5] = 0;
134     s->rfbi.vsync = 0;
135     s->rfbi.hsync = 0;
136 }
137
138 void omap_dss_reset(struct omap_dss_s *s)
139 {
140     s->autoidle = 0;
141     s->control = 0;
142     s->sdi_control = 0;
143     s->enable = 0;
144
145     s->dig.enable = 0;
146     s->dig.nx = 1;
147     s->dig.ny = 1;
148
149     s->lcd.enable = 0;
150     s->lcd.nx = 1;
151     s->lcd.ny = 1;
152
153     s->dispc.idlemode = 0;
154     s->dispc.irqst = 0;
155     s->dispc.irqen = 0;
156     s->dispc.control = 0;
157     s->dispc.config = 0;
158     s->dispc.capable = 0x161;
159     s->dispc.timing[0] = 0;
160     s->dispc.timing[1] = 0;
161     s->dispc.timing[2] = 0;
162     s->dispc.timing[3] = 0;
163     s->dispc.line = 0;
164     s->dispc.bg[0] = 0;
165     s->dispc.bg[1] = 0;
166     s->dispc.trans[0] = 0;
167     s->dispc.trans[1] = 0;
168
169     s->dispc.l[0].enable = 0;
170     s->dispc.l[0].bpp = 0;
171     s->dispc.l[0].addr[0] = 0;
172     s->dispc.l[0].addr[1] = 0;
173     s->dispc.l[0].addr[2] = 0;
174     s->dispc.l[0].posx = 0;
175     s->dispc.l[0].posy = 0;
176     s->dispc.l[0].nx = 1;
177     s->dispc.l[0].ny = 1;
178     s->dispc.l[0].attr = 0;
179     s->dispc.l[0].tresh = 0;
180     s->dispc.l[0].rowinc = 1;
181     s->dispc.l[0].colinc = 1;
182     s->dispc.l[0].wininc = 0;
183
184     s->dsi.irqst = 0;
185     
186     omap_rfbi_reset(s);
187     omap_dispc_interrupt_update(s);
188 }
189
190 static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
191 {
192     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
193
194     switch (addr) {
195     case 0x00:  /* DSS_REVISIONNUMBER */
196         return 0x20;
197
198     case 0x10:  /* DSS_SYSCONFIG */
199         return s->autoidle;
200
201     case 0x14:  /* DSS_SYSSTATUS */
202         return 1;                                               /* RESETDONE */
203             
204     case 0x18:  /* DSS_IRQSTATUS */
205         return ((s->dispc.irqst & s->dispc.irqen) ? 0x1 : 0x0)
206             | ((s->dsi.irqst) ? 0x2 : 0x0);
207
208     case 0x40:  /* DSS_CONTROL */
209         return s->control;
210
211     case 0x44:  /* DSS_SDI_CONTROL */
212         return s->sdi_control;
213
214     case 0x50:  /* DSS_PSA_LCD_REG_1 */
215     case 0x54:  /* DSS_PSA_LCD_REG_2 */
216     case 0x58:  /* DSS_PSA_VIDEO_REG */
217         /* TODO: fake some values when appropriate s->control bits are set */
218         return 0;
219
220     case 0x5c:  /* DSS_STATUS */
221         return 1 + (s->control & 1);
222
223     default:
224         break;
225     }
226     OMAP_BAD_REG(addr);
227     return 0;
228 }
229
230 static void omap_diss_write(void *opaque, target_phys_addr_t addr,
231                 uint32_t value)
232 {
233     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
234
235     switch (addr) {
236     case 0x00:  /* DSS_REVISIONNUMBER */
237     case 0x14:  /* DSS_SYSSTATUS */
238     case 0x50:  /* DSS_PSA_LCD_REG_1 */
239     case 0x54:  /* DSS_PSA_LCD_REG_2 */
240     case 0x58:  /* DSS_PSA_VIDEO_REG */
241     case 0x5c:  /* DSS_STATUS */
242         OMAP_RO_REGV(addr, value);
243         break;
244
245     case 0x10:  /* DSS_SYSCONFIG */
246         if (value & 2)                                          /* SOFTRESET */
247             omap_dss_reset(s);
248         s->autoidle = value & 1;
249         break;
250
251     case 0x40:  /* DSS_CONTROL */
252         s->control = value & 0x3dd;
253         break;
254
255     case 0x44: /* DSS_SDI_CONTROL */
256         s->sdi_control = value & 0x000ff80f;
257         break;
258     
259     default:
260         OMAP_BAD_REGV(addr, value);
261         break;
262     }
263 }
264
265 static CPUReadMemoryFunc *omap_diss1_readfn[] = {
266     omap_badwidth_read32,
267     omap_badwidth_read32,
268     omap_diss_read,
269 };
270
271 static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
272     omap_badwidth_write32,
273     omap_badwidth_write32,
274     omap_diss_write,
275 };
276
277 static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
278 {
279     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
280
281     switch (addr) {
282     case 0x000: /* DISPC_REVISION */
283         return 0x20; // 0x30 in OMAP3
284
285     case 0x010: /* DISPC_SYSCONFIG */
286         return s->dispc.idlemode;
287
288     case 0x014: /* DISPC_SYSSTATUS */
289         return 1;                                               /* RESETDONE */
290
291     case 0x018: /* DISPC_IRQSTATUS */
292         return s->dispc.irqst;
293
294     case 0x01c: /* DISPC_IRQENABLE */
295         return s->dispc.irqen;
296
297     case 0x040: /* DISPC_CONTROL */
298         return s->dispc.control;
299
300     case 0x044: /* DISPC_CONFIG */
301         return s->dispc.config;
302
303     case 0x048: /* DISPC_CAPABLE */
304         return s->dispc.capable;
305
306     case 0x04c: /* DISPC_DEFAULT_COLOR0 */
307         return s->dispc.bg[0];
308     case 0x050: /* DISPC_DEFAULT_COLOR1 */
309         return s->dispc.bg[1];
310     case 0x054: /* DISPC_TRANS_COLOR0 */
311         return s->dispc.trans[0];
312     case 0x058: /* DISPC_TRANS_COLOR1 */
313         return s->dispc.trans[1];
314
315     case 0x05c: /* DISPC_LINE_STATUS */
316         return 0x7ff;
317     case 0x060: /* DISPC_LINE_NUMBER */
318         return s->dispc.line;
319
320     case 0x064: /* DISPC_TIMING_H */
321         return s->dispc.timing[0];
322     case 0x068: /* DISPC_TIMING_V */
323         return s->dispc.timing[1];
324     case 0x06c: /* DISPC_POL_FREQ */
325         return s->dispc.timing[2];
326     case 0x070: /* DISPC_DIVISOR */
327         return s->dispc.timing[3];
328
329     case 0x078: /* DISPC_SIZE_DIG */
330         return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
331     case 0x07c: /* DISPC_SIZE_LCD */
332         return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
333
334     case 0x080: /* DISPC_GFX_BA0 */
335         return s->dispc.l[0].addr[0];
336     case 0x084: /* DISPC_GFX_BA1 */
337         return s->dispc.l[0].addr[1];
338     case 0x088: /* DISPC_GFX_POSITION */
339         return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx;
340     case 0x08c: /* DISPC_GFX_SIZE */
341         return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1);
342     case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
343         return s->dispc.l[0].attr;
344     case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
345         return s->dispc.l[0].tresh;
346     case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
347         return 256;
348     case 0x0ac: /* DISPC_GFX_ROW_INC */
349         return s->dispc.l[0].rowinc;
350     case 0x0b0: /* DISPC_GFX_PIXEL_INC */
351         return s->dispc.l[0].colinc;
352     case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
353         return s->dispc.l[0].wininc;
354     case 0x0b8: /* DISPC_GFX_TABLE_BA */
355         return s->dispc.l[0].addr[2];
356
357     case 0x0bc: /* DISPC_VID1_BA0 */
358     case 0x0c0: /* DISPC_VID1_BA1 */
359     case 0x0c4: /* DISPC_VID1_POSITION */
360     case 0x0c8: /* DISPC_VID1_SIZE */
361     case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
362     case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
363     case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */
364     case 0x0d8: /* DISPC_VID1_ROW_INC */
365     case 0x0dc: /* DISPC_VID1_PIXEL_INC */
366     case 0x0e0: /* DISPC_VID1_FIR */
367     case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
368     case 0x0e8: /* DISPC_VID1_ACCU0 */
369     case 0x0ec: /* DISPC_VID1_ACCU1 */
370     case 0x0f0 ... 0x140:       /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
371     case 0x14c: /* DISPC_VID2_BA0 */
372     case 0x150: /* DISPC_VID2_BA1 */
373     case 0x154: /* DISPC_VID2_POSITION */
374     case 0x158: /* DISPC_VID2_SIZE */
375     case 0x15c: /* DISPC_VID2_ATTRIBUTES */
376     case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
377     case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */
378     case 0x168: /* DISPC_VID2_ROW_INC */
379     case 0x16c: /* DISPC_VID2_PIXEL_INC */
380     case 0x170: /* DISPC_VID2_FIR */
381     case 0x174: /* DISPC_VID2_PICTURE_SIZE */
382     case 0x178: /* DISPC_VID2_ACCU0 */
383     case 0x17c: /* DISPC_VID2_ACCU1 */
384     case 0x180 ... 0x1d0:       /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
385     case 0x1d4: /* DISPC_DATA_CYCLE1 */
386     case 0x1d8: /* DISPC_DATA_CYCLE2 */
387     case 0x1dc: /* DISPC_DATA_CYCLE3 */
388         return 0;
389
390     default:
391         break;
392     }
393     OMAP_BAD_REG(addr);
394     return 0;
395 }
396
397 static void omap_disc_write(void *opaque, target_phys_addr_t addr,
398                 uint32_t value)
399 {
400     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
401
402     switch (addr) {
403     case 0x000: /* DISPC_REVISION */
404     case 0x014: /* DISPC_SYSSTATUS */
405     case 0x05c: /* DISPC_LINE_STATUS */
406     case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
407         OMAP_RO_REGV(addr, value);
408         break;
409             
410     case 0x010: /* DISPC_SYSCONFIG */
411         if (value & 2)                                          /* SOFTRESET */
412             omap_dss_reset(s);
413         s->dispc.idlemode = value & 0x301b;
414         break;
415
416     case 0x018: /* DISPC_IRQSTATUS */
417         s->dispc.irqst &= ~value;
418         omap_dispc_interrupt_update(s);
419         break;
420
421     case 0x01c: /* DISPC_IRQENABLE */
422         s->dispc.irqen = value & 0xffff;
423         omap_dispc_interrupt_update(s);
424         break;
425
426     case 0x040: /* DISPC_CONTROL */
427         s->dispc.control = value & 0x07ff9fff;
428         s->dig.enable = (value >> 1) & 1;
429         s->lcd.enable = (value >> 0) & 1;
430         s->lcd.active = (value >> 5) & 1;
431         if (value & (1 << 12))                  /* OVERLAY_OPTIMIZATION */
432             if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
433                  fprintf(stderr, "%s: Overlay Optimization when no overlay "
434                                  "region effectively exists leads to "
435                                  "unpredictable behaviour!\n", __FUNCTION__);
436         if (value & (1 << 6)) {                         /* GODIGITAL */
437             /* XXX: Shadowed fields are:
438              * s->dispc.config
439              * s->dispc.capable
440              * s->dispc.bg[0]
441              * s->dispc.bg[1]
442              * s->dispc.trans[0]
443              * s->dispc.trans[1]
444              * s->dispc.line
445              * s->dispc.timing[0]
446              * s->dispc.timing[1]
447              * s->dispc.timing[2]
448              * s->dispc.timing[3]
449              * s->lcd.nx
450              * s->lcd.ny
451              * s->dig.nx
452              * s->dig.ny
453              * s->dispc.l[0].addr[0]
454              * s->dispc.l[0].addr[1]
455              * s->dispc.l[0].addr[2]
456              * s->dispc.l[0].posx
457              * s->dispc.l[0].posy
458              * s->dispc.l[0].nx
459              * s->dispc.l[0].ny
460              * s->dispc.l[0].tresh
461              * s->dispc.l[0].rowinc
462              * s->dispc.l[0].colinc
463              * s->dispc.l[0].wininc
464              * All they need to be loaded here from their shadow registers.
465              */
466         }
467         if (value & (1 << 5)) {                         /* GOLCD */
468              /* XXX: Likewise for LCD here.  */
469         }
470         s->dispc.invalidate = 1;
471         break;
472
473     case 0x044: /* DISPC_CONFIG */
474         s->dispc.config = value & 0x3fff;
475         /* XXX:
476          * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
477          * bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
478          */
479         s->dispc.invalidate = 1;
480         break;
481
482     case 0x048: /* DISPC_CAPABLE */
483         s->dispc.capable = value & 0x3ff;
484         break;
485
486     case 0x04c: /* DISPC_DEFAULT_COLOR0 */
487         s->dispc.bg[0] = value & 0xffffff;
488         s->dispc.invalidate = 1;
489         break;
490     case 0x050: /* DISPC_DEFAULT_COLOR1 */
491         s->dispc.bg[1] = value & 0xffffff;
492         s->dispc.invalidate = 1;
493         break;
494     case 0x054: /* DISPC_TRANS_COLOR0 */
495         s->dispc.trans[0] = value & 0xffffff;
496         s->dispc.invalidate = 1;
497         break;
498     case 0x058: /* DISPC_TRANS_COLOR1 */
499         s->dispc.trans[1] = value & 0xffffff;
500         s->dispc.invalidate = 1;
501         break;
502
503     case 0x060: /* DISPC_LINE_NUMBER */
504         s->dispc.line = value & 0x7ff;
505         break;
506
507     case 0x064: /* DISPC_TIMING_H */
508         s->dispc.timing[0] = value & 0x0ff0ff3f;
509         break;
510     case 0x068: /* DISPC_TIMING_V */
511         s->dispc.timing[1] = value & 0x0ff0ff3f;
512         break;
513     case 0x06c: /* DISPC_POL_FREQ */
514         s->dispc.timing[2] = value & 0x0003ffff;
515         break;
516     case 0x070: /* DISPC_DIVISOR */
517         s->dispc.timing[3] = value & 0x00ff00ff;
518         break;
519
520     case 0x078: /* DISPC_SIZE_DIG */
521         s->dig.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
522         s->dig.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
523         s->dispc.invalidate = 1;
524         break;
525     case 0x07c: /* DISPC_SIZE_LCD */
526         s->lcd.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
527         s->lcd.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
528         s->dispc.invalidate = 1;
529         break;
530     case 0x080: /* DISPC_GFX_BA0 */
531         s->dispc.l[0].addr[0] = (target_phys_addr_t) value;
532         s->dispc.invalidate = 1;
533         break;
534     case 0x084: /* DISPC_GFX_BA1 */
535         s->dispc.l[0].addr[1] = (target_phys_addr_t) value;
536         s->dispc.invalidate = 1;
537         break;
538     case 0x088: /* DISPC_GFX_POSITION */
539         s->dispc.l[0].posx = ((value >>  0) & 0x7ff);           /* GFXPOSX */
540         s->dispc.l[0].posy = ((value >> 16) & 0x7ff);           /* GFXPOSY */
541         s->dispc.invalidate = 1;
542         break;
543     case 0x08c: /* DISPC_GFX_SIZE */
544         s->dispc.l[0].nx = ((value >>  0) & 0x7ff) + 1;         /* GFXSIZEX */
545         s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1;         /* GFXSIZEY */
546         s->dispc.invalidate = 1;
547         break;
548     case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
549         s->dispc.l[0].attr = value & 0xffff;
550         if (value & (3 << 9))
551             fprintf(stderr, "%s: Big-endian pixel format not supported\n",
552                             __FUNCTION__);
553         s->dispc.l[0].enable = value & 1;
554         s->dispc.l[0].bpp = (value >> 1) & 0xf;
555         s->dispc.l[0].rotation_flag = (value >> 12) & 0x3;
556         s->dispc.l[0].gfx_format = (value >> 1) & 0xf;
557         s->dispc.l[0].gfx_channel = (value >> 8) & 0x1;
558         s->dispc.invalidate = 1;
559         break;
560     case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
561         s->dispc.l[0].tresh = value & 0x01ff01ff;
562         break;
563     case 0x0ac: /* DISPC_GFX_ROW_INC */
564         s->dispc.l[0].rowinc = value;
565         s->dispc.invalidate = 1;
566         break;
567     case 0x0b0: /* DISPC_GFX_PIXEL_INC */
568         s->dispc.l[0].colinc = value;
569         s->dispc.invalidate = 1;
570         break;
571     case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
572         s->dispc.l[0].wininc = value;
573         break;
574     case 0x0b8: /* DISPC_GFX_TABLE_BA */
575         s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
576         s->dispc.invalidate = 1;
577         break;
578
579     case 0x0bc: /* DISPC_VID1_BA0 */
580     case 0x0c0: /* DISPC_VID1_BA1 */
581     case 0x0c4: /* DISPC_VID1_POSITION */
582     case 0x0c8: /* DISPC_VID1_SIZE */
583     case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
584     case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
585     case 0x0d8: /* DISPC_VID1_ROW_INC */
586     case 0x0dc: /* DISPC_VID1_PIXEL_INC */
587     case 0x0e0: /* DISPC_VID1_FIR */
588     case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
589     case 0x0e8: /* DISPC_VID1_ACCU0 */
590     case 0x0ec: /* DISPC_VID1_ACCU1 */
591     case 0x0f0 ... 0x140:       /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
592     case 0x14c: /* DISPC_VID2_BA0 */
593     case 0x150: /* DISPC_VID2_BA1 */
594     case 0x154: /* DISPC_VID2_POSITION */
595     case 0x158: /* DISPC_VID2_SIZE */
596     case 0x15c: /* DISPC_VID2_ATTRIBUTES */
597     case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
598     case 0x168: /* DISPC_VID2_ROW_INC */
599     case 0x16c: /* DISPC_VID2_PIXEL_INC */
600     case 0x170: /* DISPC_VID2_FIR */
601     case 0x174: /* DISPC_VID2_PICTURE_SIZE */
602     case 0x178: /* DISPC_VID2_ACCU0 */
603     case 0x17c: /* DISPC_VID2_ACCU1 */
604     case 0x180 ... 0x1d0:       /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
605     case 0x1d4: /* DISPC_DATA_CYCLE1 */
606     case 0x1d8: /* DISPC_DATA_CYCLE2 */
607     case 0x1dc: /* DISPC_DATA_CYCLE3 */
608         break;
609
610     default:
611         OMAP_BAD_REGV(addr, value);
612         break;
613     }
614 }
615
616 static CPUReadMemoryFunc *omap_disc1_readfn[] = {
617     omap_badwidth_read32,
618     omap_badwidth_read32,
619     omap_disc_read,
620 };
621
622 static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
623     omap_badwidth_write32,
624     omap_badwidth_write32,
625     omap_disc_write,
626 };
627
628 static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
629 {
630     target_phys_addr_t fb;
631     uint32_t pd;
632
633     /* TODO */
634     fb = s->dispc.l[0].addr[0];
635
636     pd = cpu_get_physical_page_desc(fb);
637     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
638         /* TODO */
639         cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
640                         __FUNCTION__);
641     else
642         return phys_ram_base +
643                 (pd & TARGET_PAGE_MASK) +
644                 (fb & ~TARGET_PAGE_MASK);
645 }
646
647 static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
648 {
649     if (!s->rfbi.busy)
650         return;
651
652     /* TODO: in non-Bypass mode we probably need to just deassert the DRQ.  */
653
654     s->rfbi.busy = 0;
655 }
656
657 static void omap_rfbi_transfer_start(struct omap_dss_s *s)
658 {
659     void *data;
660     size_t len;
661     int pitch;
662
663     if (!s->rfbi.enable || s->rfbi.busy)
664         return;
665
666     if (s->rfbi.control & (1 << 1)) {                           /* BYPASS */
667         /* TODO: in non-Bypass mode we probably need to just assert the
668          * DRQ and wait for DMA to write the pixels.  */
669         fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
670         return;
671     }
672
673     if (!(s->dispc.control & (1 << 11)))                        /* RFBIMODE */
674         return;
675     /* TODO: check that LCD output is enabled in DISPC.  */
676
677     s->rfbi.busy = 1;
678
679     data = omap_rfbi_get_buffer(s);
680
681     /* TODO bpp */
682     len = s->rfbi.pixels * 2;
683     s->rfbi.pixels = 0;
684
685     /* TODO: negative values */
686     pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
687
688     if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
689         s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
690     if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
691         s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
692
693     omap_rfbi_transfer_stop(s);
694
695     /* TODO */
696     s->dispc.irqst |= 1;                                        /* FRAMEDONE */
697     omap_dispc_interrupt_update(s);
698 }
699
700 static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
701 {
702     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
703
704     switch (addr) {
705     case 0x00:  /* RFBI_REVISION */
706         return 0x10;
707
708     case 0x10:  /* RFBI_SYSCONFIG */
709         return s->rfbi.idlemode;
710
711     case 0x14:  /* RFBI_SYSSTATUS */
712         return 1 | (s->rfbi.busy << 8);                         /* RESETDONE */
713
714     case 0x40:  /* RFBI_CONTROL */
715         return s->rfbi.control;
716
717     case 0x44:  /* RFBI_PIXELCNT */
718         return s->rfbi.pixels;
719
720     case 0x48:  /* RFBI_LINE_NUMBER */
721         return s->rfbi.skiplines;
722
723     case 0x58:  /* RFBI_READ */
724     case 0x5c:  /* RFBI_STATUS */
725         return s->rfbi.rxbuf;
726
727     case 0x60:  /* RFBI_CONFIG0 */
728         return s->rfbi.config[0];
729     case 0x64:  /* RFBI_ONOFF_TIME0 */
730         return s->rfbi.time[0];
731     case 0x68:  /* RFBI_CYCLE_TIME0 */
732         return s->rfbi.time[1];
733     case 0x6c:  /* RFBI_DATA_CYCLE1_0 */
734         return s->rfbi.data[0];
735     case 0x70:  /* RFBI_DATA_CYCLE2_0 */
736         return s->rfbi.data[1];
737     case 0x74:  /* RFBI_DATA_CYCLE3_0 */
738         return s->rfbi.data[2];
739
740     case 0x78:  /* RFBI_CONFIG1 */
741         return s->rfbi.config[1];
742     case 0x7c:  /* RFBI_ONOFF_TIME1 */
743         return s->rfbi.time[2];
744     case 0x80:  /* RFBI_CYCLE_TIME1 */
745         return s->rfbi.time[3];
746     case 0x84:  /* RFBI_DATA_CYCLE1_1 */
747         return s->rfbi.data[3];
748     case 0x88:  /* RFBI_DATA_CYCLE2_1 */
749         return s->rfbi.data[4];
750     case 0x8c:  /* RFBI_DATA_CYCLE3_1 */
751         return s->rfbi.data[5];
752
753     case 0x90:  /* RFBI_VSYNC_WIDTH */
754         return s->rfbi.vsync;
755     case 0x94:  /* RFBI_HSYNC_WIDTH */
756         return s->rfbi.hsync;
757     }
758     OMAP_BAD_REG(addr);
759     return 0;
760 }
761
762 static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
763                 uint32_t value)
764 {
765     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
766
767     switch (addr) {
768     case 0x10:  /* RFBI_SYSCONFIG */
769         if (value & 2)                                          /* SOFTRESET */
770             omap_rfbi_reset(s);
771         s->rfbi.idlemode = value & 0x19;
772         break;
773
774     case 0x40:  /* RFBI_CONTROL */
775         s->rfbi.control = value & 0xf;
776         s->rfbi.enable = value & 1;
777         if (value & (1 << 4) &&                                 /* ITE */
778                         !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
779             omap_rfbi_transfer_start(s);
780         break;
781
782     case 0x44:  /* RFBI_PIXELCNT */
783         s->rfbi.pixels = value;
784         break;
785
786     case 0x48:  /* RFBI_LINE_NUMBER */
787         s->rfbi.skiplines = value & 0x7ff;
788         break;
789
790     case 0x4c:  /* RFBI_CMD */
791         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
792             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
793         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
794             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
795         break;
796     case 0x50:  /* RFBI_PARAM */
797         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
798             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
799         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
800             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
801         break;
802     case 0x54:  /* RFBI_DATA */
803         /* TODO: take into account the format set up in s->rfbi.config[?] and
804          * s->rfbi.data[?], but special-case the most usual scenario so that
805          * speed doesn't suffer.  */
806         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
807             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
808             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
809         }
810         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
811             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
812             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
813         }
814         if (!-- s->rfbi.pixels)
815             omap_rfbi_transfer_stop(s);
816         break;
817     case 0x58:  /* RFBI_READ */
818         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
819             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
820         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
821             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
822         if (!-- s->rfbi.pixels)
823             omap_rfbi_transfer_stop(s);
824         break;
825
826     case 0x5c:  /* RFBI_STATUS */
827         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
828             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
829         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
830             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
831         if (!-- s->rfbi.pixels)
832             omap_rfbi_transfer_stop(s);
833         break;
834
835     case 0x60:  /* RFBI_CONFIG0 */
836         s->rfbi.config[0] = value & 0x003f1fff;
837         break;
838
839     case 0x64:  /* RFBI_ONOFF_TIME0 */
840         s->rfbi.time[0] = value & 0x3fffffff;
841         break;
842     case 0x68:  /* RFBI_CYCLE_TIME0 */
843         s->rfbi.time[1] = value & 0x0fffffff;
844         break;
845     case 0x6c:  /* RFBI_DATA_CYCLE1_0 */
846         s->rfbi.data[0] = value & 0x0f1f0f1f;
847         break;
848     case 0x70:  /* RFBI_DATA_CYCLE2_0 */
849         s->rfbi.data[1] = value & 0x0f1f0f1f;
850         break;
851     case 0x74:  /* RFBI_DATA_CYCLE3_0 */
852         s->rfbi.data[2] = value & 0x0f1f0f1f;
853         break;
854     case 0x78:  /* RFBI_CONFIG1 */
855         s->rfbi.config[1] = value & 0x003f1fff;
856         break;
857
858     case 0x7c:  /* RFBI_ONOFF_TIME1 */
859         s->rfbi.time[2] = value & 0x3fffffff;
860         break;
861     case 0x80:  /* RFBI_CYCLE_TIME1 */
862         s->rfbi.time[3] = value & 0x0fffffff;
863         break;
864     case 0x84:  /* RFBI_DATA_CYCLE1_1 */
865         s->rfbi.data[3] = value & 0x0f1f0f1f;
866         break;
867     case 0x88:  /* RFBI_DATA_CYCLE2_1 */
868         s->rfbi.data[4] = value & 0x0f1f0f1f;
869         break;
870     case 0x8c:  /* RFBI_DATA_CYCLE3_1 */
871         s->rfbi.data[5] = value & 0x0f1f0f1f;
872         break;
873
874     case 0x90:  /* RFBI_VSYNC_WIDTH */
875         s->rfbi.vsync = value & 0xffff;
876         break;
877     case 0x94:  /* RFBI_HSYNC_WIDTH */
878         s->rfbi.hsync = value & 0xffff;
879         break;
880
881     default:
882         OMAP_BAD_REGV(addr, value);
883         break;
884     }
885 }
886
887 static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
888     omap_badwidth_read32,
889     omap_badwidth_read32,
890     omap_rfbi_read,
891 };
892
893 static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
894     omap_badwidth_write32,
895     omap_badwidth_write32,
896     omap_rfbi_write,
897 };
898
899 static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
900 {
901     switch (addr) {
902     case 0x00:  /* REV_ID */
903     case 0x04:  /* STATUS */
904     case 0x08:  /* F_CONTROL */
905     case 0x10:  /* VIDOUT_CTRL */
906     case 0x14:  /* SYNC_CTRL */
907     case 0x1c:  /* LLEN */
908     case 0x20:  /* FLENS */
909     case 0x24:  /* HFLTR_CTRL */
910     case 0x28:  /* CC_CARR_WSS_CARR */
911     case 0x2c:  /* C_PHASE */
912     case 0x30:  /* GAIN_U */
913     case 0x34:  /* GAIN_V */
914     case 0x38:  /* GAIN_Y */
915     case 0x3c:  /* BLACK_LEVEL */
916     case 0x40:  /* BLANK_LEVEL */
917     case 0x44:  /* X_COLOR */
918     case 0x48:  /* M_CONTROL */
919     case 0x4c:  /* BSTAMP_WSS_DATA */
920     case 0x50:  /* S_CARR */
921     case 0x54:  /* LINE21 */
922     case 0x58:  /* LN_SEL */
923     case 0x5c:  /* L21__WC_CTL */
924     case 0x60:  /* HTRIGGER_VTRIGGER */
925     case 0x64:  /* SAVID__EAVID */
926     case 0x68:  /* FLEN__FAL */
927     case 0x6c:  /* LAL__PHASE_RESET */
928     case 0x70:  /* HS_INT_START_STOP_X */
929     case 0x74:  /* HS_EXT_START_STOP_X */
930     case 0x78:  /* VS_INT_START_X */
931     case 0x7c:  /* VS_INT_STOP_X__VS_INT_START_Y */
932     case 0x80:  /* VS_INT_STOP_Y__VS_INT_START_X */
933     case 0x84:  /* VS_EXT_STOP_X__VS_EXT_START_Y */
934     case 0x88:  /* VS_EXT_STOP_Y */
935     case 0x90:  /* AVID_START_STOP_X */
936     case 0x94:  /* AVID_START_STOP_Y */
937     case 0xa0:  /* FID_INT_START_X__FID_INT_START_Y */
938     case 0xa4:  /* FID_INT_OFFSET_Y__FID_EXT_START_X */
939     case 0xa8:  /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
940     case 0xb0:  /* TVDETGP_INT_START_STOP_X */
941     case 0xb4:  /* TVDETGP_INT_START_STOP_Y */
942     case 0xb8:  /* GEN_CTRL */
943     case 0xc4:  /* DAC_TST__DAC_A */
944     case 0xc8:  /* DAC_B__DAC_C */
945         return 0;
946
947     default:
948         break;
949     }
950     OMAP_BAD_REG(addr);
951     return 0;
952 }
953
954 static void omap_venc_write(void *opaque, target_phys_addr_t addr,
955                 uint32_t value)
956 {
957     switch (addr) {
958     case 0x08:  /* F_CONTROL */
959     case 0x10:  /* VIDOUT_CTRL */
960     case 0x14:  /* SYNC_CTRL */
961     case 0x1c:  /* LLEN */
962     case 0x20:  /* FLENS */
963     case 0x24:  /* HFLTR_CTRL */
964     case 0x28:  /* CC_CARR_WSS_CARR */
965     case 0x2c:  /* C_PHASE */
966     case 0x30:  /* GAIN_U */
967     case 0x34:  /* GAIN_V */
968     case 0x38:  /* GAIN_Y */
969     case 0x3c:  /* BLACK_LEVEL */
970     case 0x40:  /* BLANK_LEVEL */
971     case 0x44:  /* X_COLOR */
972     case 0x48:  /* M_CONTROL */
973     case 0x4c:  /* BSTAMP_WSS_DATA */
974     case 0x50:  /* S_CARR */
975     case 0x54:  /* LINE21 */
976     case 0x58:  /* LN_SEL */
977     case 0x5c:  /* L21__WC_CTL */
978     case 0x60:  /* HTRIGGER_VTRIGGER */
979     case 0x64:  /* SAVID__EAVID */
980     case 0x68:  /* FLEN__FAL */
981     case 0x6c:  /* LAL__PHASE_RESET */
982     case 0x70:  /* HS_INT_START_STOP_X */
983     case 0x74:  /* HS_EXT_START_STOP_X */
984     case 0x78:  /* VS_INT_START_X */
985     case 0x7c:  /* VS_INT_STOP_X__VS_INT_START_Y */
986     case 0x80:  /* VS_INT_STOP_Y__VS_INT_START_X */
987     case 0x84:  /* VS_EXT_STOP_X__VS_EXT_START_Y */
988     case 0x88:  /* VS_EXT_STOP_Y */
989     case 0x90:  /* AVID_START_STOP_X */
990     case 0x94:  /* AVID_START_STOP_Y */
991     case 0xa0:  /* FID_INT_START_X__FID_INT_START_Y */
992     case 0xa4:  /* FID_INT_OFFSET_Y__FID_EXT_START_X */
993     case 0xa8:  /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
994     case 0xb0:  /* TVDETGP_INT_START_STOP_X */
995     case 0xb4:  /* TVDETGP_INT_START_STOP_Y */
996     case 0xb8:  /* GEN_CTRL */
997     case 0xc4:  /* DAC_TST__DAC_A */
998     case 0xc8:  /* DAC_B__DAC_C */
999         break;
1000
1001     default:
1002         OMAP_BAD_REGV(addr, value);
1003         break;
1004     }
1005 }
1006
1007 static CPUReadMemoryFunc *omap_venc1_readfn[] = {
1008     omap_badwidth_read32,
1009     omap_badwidth_read32,
1010     omap_venc_read,
1011 };
1012
1013 static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
1014     omap_badwidth_write32,
1015     omap_badwidth_write32,
1016     omap_venc_write,
1017 };
1018
1019 static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
1020 {
1021     switch (addr) {
1022     case 0x0a8: /* SBIMERRLOGA */
1023     case 0x0b0: /* SBIMERRLOG */
1024     case 0x190: /* SBIMSTATE */
1025     case 0x198: /* SBTMSTATE_L */
1026     case 0x19c: /* SBTMSTATE_H */
1027     case 0x1a8: /* SBIMCONFIG_L */
1028     case 0x1ac: /* SBIMCONFIG_H */
1029     case 0x1f8: /* SBID_L */
1030     case 0x1fc: /* SBID_H */
1031         return 0;
1032
1033     default:
1034         break;
1035     }
1036     OMAP_BAD_REG(addr);
1037     return 0;
1038 }
1039
1040 static void omap_im3_write(void *opaque, target_phys_addr_t addr,
1041                 uint32_t value)
1042 {
1043     switch (addr) {
1044     case 0x0b0: /* SBIMERRLOG */
1045     case 0x190: /* SBIMSTATE */
1046     case 0x198: /* SBTMSTATE_L */
1047     case 0x19c: /* SBTMSTATE_H */
1048     case 0x1a8: /* SBIMCONFIG_L */
1049     case 0x1ac: /* SBIMCONFIG_H */
1050         break;
1051
1052     default:
1053         OMAP_BAD_REGV(addr, value);
1054         break;
1055     }
1056 }
1057
1058 static CPUReadMemoryFunc *omap_im3_readfn[] = {
1059     omap_badwidth_read32,
1060     omap_badwidth_read32,
1061     omap_im3_read,
1062 };
1063
1064 static CPUWriteMemoryFunc *omap_im3_writefn[] = {
1065     omap_badwidth_write32,
1066     omap_badwidth_write32,
1067     omap_im3_write,
1068 };
1069
1070 struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
1071                                  target_phys_addr_t l3_base, DisplayState *ds,
1072                                  qemu_irq irq, qemu_irq drq,
1073                                  omap_clk fck1, omap_clk fck2, omap_clk ck54m,
1074                                  omap_clk ick1, omap_clk ick2)
1075 {
1076     int iomemtype[5];
1077     struct omap_dss_s *s = (struct omap_dss_s *)
1078             qemu_mallocz(sizeof(struct omap_dss_s));
1079
1080     s->irq = irq;
1081     s->drq = drq;
1082     s->state = ds;
1083     omap_dss_reset(s);
1084
1085         iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn,
1086                                              omap_diss1_writefn, s);
1087         iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn,
1088                                              omap_disc1_writefn, s);
1089         iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn,
1090                                              omap_rfbi1_writefn, s);
1091         iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn,
1092                                              omap_venc1_writefn, s);
1093         iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
1094                                               omap_im3_writefn, s);
1095         omap_l4_attach(ta, 0, iomemtype[0]);
1096         omap_l4_attach(ta, 1, iomemtype[1]);
1097         omap_l4_attach(ta, 2, iomemtype[2]);
1098         omap_l4_attach(ta, 3, iomemtype[3]);
1099         cpu_register_physical_memory(l3_base, 0x1000, iomemtype[4]);
1100 #if 0
1101     if (ds)
1102         graphic_console_init(ds, omap_update_display,
1103                         omap_invalidate_display, omap_screen_dump, s);
1104 #endif
1105
1106     return s;
1107 }
1108
1109 void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
1110 {
1111     if (cs < 0 || cs > 1)
1112         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1113     s->rfbi.chip[cs] = chip;
1114 }
1115
1116 void omap3_lcd_panel_attach(struct omap_dss_s *s, int cs, struct omap3_lcd_panel_s *lcd_panel)
1117 {
1118     if (cs < 0 || cs > 1)
1119         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1120     s->omap_lcd_panel[cs] = lcd_panel;
1121 }
1122
1123 /*omap3 lcd panel stuff*/
1124
1125 /* Bytes(!) per pixel */
1126 static const int omap3_lcd_panel_bpp[0x10] = {
1127     0,   /*0x0*/
1128     0,   /*0x1*/
1129     0,   /*0x2*/
1130     0,   /*0x3*/
1131     2,  /*0x4:RGB 12 */
1132     2,  /*0x5: ARGB16 */
1133     2,  /*0x6: RGB 16 */
1134     0,  /*0x7*/
1135     4,  /*0x8: RGB 24 (un-packed in 32-bit container) */
1136     3,  /*0x9: RGB 24 (packed in 24-bit container) */
1137     0,  /*0xa */
1138     0,  /*0xb */
1139     4,  /*0xc: ARGB32 */
1140     4,  /*0xd: RGBA32 */
1141     4,  /*0xe: RGBx 32 (24-bit RGB aligned on MSB of the 32-bit container) */
1142     0,  /*0xf */
1143 };
1144
1145 static inline void omap3_lcd_panel_invalidate_display(void *opaque) 
1146 {
1147     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1148     s->invalidate = 1;
1149 }
1150
1151 static void omap3_lcd_panel_update_display(void *opaque)
1152 {
1153     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1154     struct omap_dss_s *dss = s->dss;
1155     uint32_t lcd_width,lcd_height;
1156     uint32_t graphic_width,graphic_height;
1157     uint32_t start_x,start_y;
1158     uint32_t lcd_Bpp,dss_Bpp;
1159     uint32_t linesize,y;
1160     uint32_t copy_width,copy_height;
1161     uint8_t *src, *dest;
1162
1163     //printf("dss->lcd.active  %d dss->lcd.enable %d \n",dss->lcd.active,dss->lcd.enable);
1164     if (!dss->lcd.active)
1165         return;
1166
1167     /*check whether LCD is enabled*/
1168     if (!dss->lcd.enable)
1169         return;
1170
1171     if ((dss->dispc.control & (1 << 11)))                       /* RFBIMODE */
1172         return;
1173
1174     if (dss->dispc.l[0].gfx_channel)                    /* 24 bit digital out */
1175         return;
1176
1177     if (!(dss->dispc.l[0].rotation_flag)) {       /* rotation*/
1178         s->line_fn = s->line_fn_tab[0][dss->dispc.l[0].gfx_format];
1179     } else {
1180         fprintf(stderr, "%s: rotation is not supported \n", __FUNCTION__);
1181         exit(1);
1182     }
1183     if (!s->line_fn) {
1184         fprintf(stderr, "%s:s->line_fn is NULL. Not supported gfx_format \n", __FUNCTION__);
1185         exit(1);
1186     }
1187
1188     /* Resolution */
1189     lcd_width = dss->lcd.nx;
1190     lcd_height = dss->lcd.ny;
1191     graphic_width = dss->dispc.l[0].nx;
1192     graphic_height = dss->dispc.l[0].ny;
1193     start_x = dss->dispc.l[0].posx;
1194     start_y = dss->dispc.l[0].posy;
1195     //printf("lcd_width %d lcd_height %d \n",lcd_width,lcd_height);
1196     //printf("graphic_width %d graphic_height %d \n",graphic_width,graphic_height);
1197     //printf("start_x %d start_y %d \n",start_x,start_y);
1198
1199     if (lcd_width != ds_get_width(s->state) 
1200         || lcd_height != ds_get_height(s->state)) {
1201         qemu_console_resize(s->console, lcd_width, lcd_height);
1202         dss->dispc.invalidate = 1;
1203     }
1204
1205     /*if ((start_x+graphic_width)>lcd_width) {
1206         fprintf(stderr, "%s: graphic window width(0x%x) > lcd width(0x%x) \n",__FUNCTION__,start_x+graphic_width,lcd_width );
1207          exit(1);
1208     }
1209     if ((start_y+graphic_height)>lcd_height) {
1210         fprintf(stderr, "%s: graphic window height(0x%x) > lcd height(0x%x) \n",__FUNCTION__,start_y+graphic_height,lcd_height);
1211         exit(1);
1212     }*/
1213
1214     /*use the rfbi function*/
1215     src = (uint8_t *)omap_rfbi_get_buffer(dss);
1216     dest = ds_get_data(s->state);
1217     linesize = ds_get_linesize(s->state);
1218
1219     lcd_Bpp = omap3_lcd_panel_bpp[dss->dispc.l[0].gfx_format];
1220     dss_Bpp = linesize/ds_get_width(s->state);
1221
1222     //printf("LCD BPP %d dss_bpp %d \n",lcd_Bpp,dss_Bpp);
1223
1224     dest += linesize*start_y;
1225     dest += start_x*dss_Bpp;
1226
1227     if ((start_x+graphic_width)>lcd_width)
1228         copy_width = lcd_width - start_x;
1229     else
1230         copy_width = graphic_width;
1231     copy_height = lcd_height>graphic_height ? graphic_height:lcd_height;
1232
1233     for (y=start_y;y<copy_height;y++) {
1234         s->line_fn(dest,src,copy_width*lcd_Bpp);
1235         src += graphic_width*lcd_Bpp;
1236         dest += linesize;
1237     }
1238
1239     dpy_update(s->state, start_x, start_y, graphic_width, graphic_height);
1240 }
1241
1242 /*omap lcd stuff*/
1243 #define DEPTH 8
1244 #include "omap3_lcd_panel_template.h"
1245 #define DEPTH 15
1246 #include "omap3_lcd_panel_template.h"
1247 #define DEPTH 16
1248 #include "omap3_lcd_panel_template.h"
1249 #define DEPTH 24
1250 #include "omap3_lcd_panel_template.h"
1251 #define DEPTH 32
1252 #include "omap3_lcd_panel_template.h"
1253
1254 void *omap3_lcd_panel_init(DisplayState *ds)
1255 {
1256     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *) qemu_mallocz(sizeof(*s));
1257
1258     s->state = ds;
1259
1260     switch (ds_get_bits_per_pixel(s->state)) {
1261     case 0:
1262         s->line_fn_tab[0] = s->line_fn_tab[1] =
1263             qemu_mallocz(sizeof(omap3_lcd_panel_fn_t) * 0x10);
1264         break;
1265     case 8:
1266         s->line_fn_tab[0] = ds->bgr ? omap3_lcd_panel_draw_fn_bgr_8 : omap3_lcd_panel_draw_fn_8;
1267         s->line_fn_tab[1] = ds->bgr ? omap3_lcd_panel_draw_fn_r_bgr_8 : omap3_lcd_panel_draw_fn_r_8;
1268         break;
1269     case 15:
1270         s->line_fn_tab[0] = ds->bgr ? omap3_lcd_panel_draw_fn_bgr_15 : omap3_lcd_panel_draw_fn_15;
1271         s->line_fn_tab[1] = ds->bgr ? omap3_lcd_panel_draw_fn_r_bgr_15 : omap3_lcd_panel_draw_fn_r_15;
1272         break;
1273     case 16:
1274         s->line_fn_tab[0] = ds->bgr ? omap3_lcd_panel_draw_fn_bgr_16 : omap3_lcd_panel_draw_fn_16;
1275         s->line_fn_tab[1] = ds->bgr ? omap3_lcd_panel_draw_fn_r_bgr_16: omap3_lcd_panel_draw_fn_r_16;
1276         break;
1277     case 24:
1278         s->line_fn_tab[0] = ds->bgr ? omap3_lcd_panel_draw_fn_bgr_24 : omap3_lcd_panel_draw_fn_24;
1279         s->line_fn_tab[1] = ds->bgr ? omap3_lcd_panel_draw_fn_r_bgr_24 : omap3_lcd_panel_draw_fn_r_24;
1280         break;
1281     case 32:
1282         s->line_fn_tab[0] = ds->bgr ? omap3_lcd_panel_draw_fn_bgr_32 : omap3_lcd_panel_draw_fn_32;
1283         s->line_fn_tab[1] = ds->bgr ? omap3_lcd_panel_draw_fn_r_bgr_32 : omap3_lcd_panel_draw_fn_r_32;
1284         break;
1285     default:
1286         fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
1287         exit(1);
1288     }
1289
1290     s->console = graphic_console_init(s->state, omap3_lcd_panel_update_display,
1291                                       omap3_lcd_panel_invalidate_display,
1292                                       NULL, NULL, s);
1293     return s;
1294 }