Merge commit 'origin/upstream' into juha-devel
[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_dss_save_state(QEMUFile *f, void *opaque)
158 {
159     struct omap_dss_s *s = (struct omap_dss_s *)opaque;
160     int i, j;
161     
162     qemu_put_sbe32(f, s->autoidle);
163     qemu_put_sbe32(f, s->control);
164     qemu_put_be32(f, s->sdi_control);
165     qemu_put_be32(f, s->pll_control);
166     qemu_put_sbe32(f, s->enable);
167     qemu_put_sbe32(f, s->dig.enable);
168     qemu_put_sbe32(f, s->dig.nx);
169     qemu_put_sbe32(f, s->dig.ny);
170     qemu_put_sbe32(f, s->dig.x);
171     qemu_put_sbe32(f, s->dig.y);
172     qemu_put_sbe32(f, s->lcd.enable);
173     qemu_put_sbe32(f, s->lcd.nx);
174     qemu_put_sbe32(f, s->lcd.ny);
175     qemu_put_sbe32(f, s->lcd.x);
176     qemu_put_sbe32(f, s->lcd.y);
177     qemu_put_be32(f, s->dispc.idlemode);
178     qemu_put_be32(f, s->dispc.irqst);
179     qemu_put_be32(f, s->dispc.irqen);
180     qemu_put_be32(f, s->dispc.control);
181     qemu_put_be32(f, s->dispc.config);
182     qemu_put_be32(f, s->dispc.capable);
183     qemu_put_be32(f, s->dispc.timing[0]);
184     qemu_put_be32(f, s->dispc.timing[1]);
185     qemu_put_be32(f, s->dispc.timing[2]);
186     qemu_put_be32(f, s->dispc.timing[3]);
187     qemu_put_sbe32(f, s->dispc.line);
188     qemu_put_be32(f, s->dispc.bg[0]);
189     qemu_put_be32(f, s->dispc.bg[1]);
190     qemu_put_be32(f, s->dispc.trans[0]);
191     qemu_put_be32(f, s->dispc.trans[1]);
192     qemu_put_be32(f, s->dispc.global_alpha);
193     qemu_put_be32(f, s->dispc.cpr_coef_r);
194     qemu_put_be32(f, s->dispc.cpr_coef_g);
195     qemu_put_be32(f, s->dispc.cpr_coef_b);
196     for (i = 0; i < 3; i++) {
197         qemu_put_sbe32(f, s->dispc.l[i].enable);
198         qemu_put_sbe32(f, s->dispc.l[i].bpp);
199         qemu_put_sbe32(f, s->dispc.l[i].posx);
200         qemu_put_sbe32(f, s->dispc.l[i].posy);
201         qemu_put_sbe32(f, s->dispc.l[i].nx);
202         qemu_put_sbe32(f, s->dispc.l[i].ny);
203         qemu_put_sbe32(f, s->dispc.l[i].rotation_flag);
204         qemu_put_sbe32(f, s->dispc.l[i].gfx_format);
205         qemu_put_sbe32(f, s->dispc.l[i].gfx_channel);
206         for (j = 0; j < 3; j++) {
207 #if TARGET_PHYS_ADDR_BITS == 32
208             qemu_put_be32(f, s->dispc.l[i].addr[j]);
209 #elif TARGET_PHYS_ADDR_BITS == 64
210             qemu_put_be64(f, s->dispc.l[i].addr[j]);
211 #else
212 #error TARGET_PHYS_ADDR_BITS undefined
213 #endif
214         }
215         qemu_put_be32(f, s->dispc.l[i].attr);
216         qemu_put_be32(f, s->dispc.l[i].tresh);
217         qemu_put_sbe32(f, s->dispc.l[i].rowinc);
218         qemu_put_sbe32(f, s->dispc.l[i].colinc);
219         qemu_put_sbe32(f, s->dispc.l[i].wininc);
220         qemu_put_be32(f, s->dispc.l[i].preload);
221         qemu_put_be32(f, s->dispc.l[i].fir);
222         for (j = 0; j < 8; j++) {
223             qemu_put_be32(f, s->dispc.l[i].fir_coef_h[j]);
224             qemu_put_be32(f, s->dispc.l[i].fir_coef_hv[j]);
225             qemu_put_be32(f, s->dispc.l[i].fir_coef_v[j]);
226             if (j < 5)
227                 qemu_put_be32(f, s->dispc.l[i].conv_coef[j]);
228         }
229         qemu_put_be32(f, s->dispc.l[i].picture_size);
230         qemu_put_be32(f, s->dispc.l[i].accu[0]);
231         qemu_put_be32(f, s->dispc.l[i].accu[1]);
232     }
233     qemu_put_sbe32(f, s->dispc.invalidate);
234     for (i = 0; i < 256; i++)
235         qemu_put_be16(f, s->dispc.palette[i]);
236     qemu_put_sbe32(f, s->rfbi.idlemode);
237     qemu_put_be32(f, s->rfbi.control);
238     qemu_put_sbe32(f, s->rfbi.enable);
239     qemu_put_sbe32(f, s->rfbi.pixels);
240     qemu_put_sbe32(f, s->rfbi.busy);
241     qemu_put_sbe32(f, s->rfbi.skiplines);
242     qemu_put_be16(f, s->rfbi.rxbuf);
243     for (i = 0; i < 6; i++) {
244         if (i < 2)
245             qemu_put_be32(f, s->rfbi.config[i]);
246         if (i < 4)
247             qemu_put_be32(f, s->rfbi.time[i]);
248         qemu_put_be32(f, s->rfbi.data[i]);
249     }
250     qemu_put_be16(f, s->rfbi.vsync);
251     qemu_put_be16(f, s->rfbi.hsync);
252     qemu_put_be32(f, s->dsi.irqst);
253     qemu_put_be32(f, s->dsi.irqen);
254 }
255
256 static int omap_dss_load_state(QEMUFile *f, void *opaque, int version_id)
257 {
258     struct omap_dss_s *s = (struct omap_dss_s *)opaque;
259     int i, j;
260     
261     if (version_id)
262         return -EINVAL;
263     
264     s->autoidle = qemu_get_sbe32(f);
265     s->control = qemu_get_sbe32(f);
266     s->sdi_control = qemu_get_be32(f);
267     s->pll_control = qemu_get_be32(f);
268     s->enable = qemu_get_sbe32(f);
269     s->dig.enable = qemu_get_sbe32(f);
270     s->dig.nx = qemu_get_sbe32(f);
271     s->dig.ny = qemu_get_sbe32(f);
272     s->dig.x = qemu_get_sbe32(f);
273     s->dig.y = qemu_get_sbe32(f);
274     s->lcd.enable = qemu_get_sbe32(f);
275     s->lcd.nx = qemu_get_sbe32(f);
276     s->lcd.ny = qemu_get_sbe32(f);
277     s->lcd.x = qemu_get_sbe32(f);
278     s->lcd.y = qemu_get_sbe32(f);
279     s->dispc.idlemode = qemu_get_be32(f);
280     s->dispc.irqst = qemu_get_be32(f);
281     s->dispc.irqen = qemu_get_be32(f);
282     s->dispc.control = qemu_get_be32(f);
283     s->dispc.config = qemu_get_be32(f);
284     s->dispc.capable = qemu_get_be32(f);
285     s->dispc.timing[0] = qemu_get_be32(f);
286     s->dispc.timing[1] = qemu_get_be32(f);
287     s->dispc.timing[2] = qemu_get_be32(f);
288     s->dispc.timing[3] = qemu_get_be32(f);
289     s->dispc.line = qemu_get_sbe32(f);
290     s->dispc.bg[0] = qemu_get_be32(f);
291     s->dispc.bg[1] = qemu_get_be32(f);
292     s->dispc.trans[0] = qemu_get_be32(f);
293     s->dispc.trans[1] = qemu_get_be32(f);
294     s->dispc.global_alpha = qemu_get_be32(f);
295     s->dispc.cpr_coef_r = qemu_get_be32(f);
296     s->dispc.cpr_coef_g = qemu_get_be32(f);
297     s->dispc.cpr_coef_b = qemu_get_be32(f);
298     for (i = 0; i < 3; i++) {
299         s->dispc.l[i].enable = qemu_get_sbe32(f);
300         s->dispc.l[i].bpp = qemu_get_sbe32(f);
301         s->dispc.l[i].posx = qemu_get_sbe32(f);
302         s->dispc.l[i].posy = qemu_get_sbe32(f);
303         s->dispc.l[i].nx = qemu_get_sbe32(f);
304         s->dispc.l[i].ny = qemu_get_sbe32(f);
305         s->dispc.l[i].rotation_flag = qemu_get_sbe32(f);
306         s->dispc.l[i].gfx_format = qemu_get_sbe32(f);
307         s->dispc.l[i].gfx_channel = qemu_get_sbe32(f);
308         for (j = 0; j < 3; j++) {
309 #if TARGET_PHYS_ADDR_BITS == 32
310             s->dispc.l[i].addr[j] = qemu_get_be32(f);
311 #elif TARGET_PHYS_ADDR_BITS == 64
312             s->dispc.l[i].addr[j] = qemu_get_be64(f);
313 #else
314 #error TARGET_PHYS_ADDR_BITS undefined
315 #endif
316         }
317         s->dispc.l[i].attr = qemu_get_be32(f);
318         s->dispc.l[i].tresh = qemu_get_be32(f);
319         s->dispc.l[i].rowinc = qemu_get_sbe32(f);
320         s->dispc.l[i].colinc = qemu_get_sbe32(f);
321         s->dispc.l[i].wininc = qemu_get_sbe32(f);
322         s->dispc.l[i].preload = qemu_get_be32(f);
323         s->dispc.l[i].fir = qemu_get_be32(f);
324         for (j = 0; j < 8; j++) {
325             s->dispc.l[i].fir_coef_h[j] = qemu_get_be32(f);
326             s->dispc.l[i].fir_coef_hv[j] = qemu_get_be32(f);
327             s->dispc.l[i].fir_coef_v[j] = qemu_get_be32(f);
328             if (j < 5)
329                 s->dispc.l[i].conv_coef[j] = qemu_get_be32(f);
330         }
331         s->dispc.l[i].picture_size = qemu_get_be32(f);
332         s->dispc.l[i].accu[0] = qemu_get_be32(f);
333         s->dispc.l[i].accu[1] = qemu_get_be32(f);
334     }
335     s->dispc.invalidate = qemu_get_sbe32(f);
336     for (i = 0; i < 256; i++)
337         s->dispc.palette[i] = qemu_get_be16(f);
338     s->rfbi.idlemode = qemu_get_sbe32(f);
339     s->rfbi.control = qemu_get_be32(f);
340     s->rfbi.enable = qemu_get_sbe32(f);
341     s->rfbi.pixels = qemu_get_sbe32(f);
342     s->rfbi.busy = qemu_get_sbe32(f);
343     s->rfbi.skiplines = qemu_get_sbe32(f);
344     s->rfbi.rxbuf = qemu_get_be16(f);
345     for (i = 0; i < 6; i++) {
346         if (i < 2)
347             s->rfbi.config[i] = qemu_get_be32(f);
348         if (i < 4)
349             s->rfbi.time[i] = qemu_get_be32(f);
350         s->rfbi.data[i] = qemu_get_be32(f);
351     }
352     s->rfbi.vsync = qemu_get_be16(f);
353     s->rfbi.hsync = qemu_get_be16(f);
354     s->dsi.irqst = qemu_get_be32(f);
355     s->dsi.irqen = qemu_get_be32(f);
356     
357     s->dispc.invalidate = 1; /* force refresh of display parameters */
358     if (s->omap_lcd_panel[0])
359         s->omap_lcd_panel[0]->invalidate = 1;
360     if (s->omap_lcd_panel[1])
361         s->omap_lcd_panel[1]->invalidate = 1;
362     
363     omap_dss_interrupt_update(s);
364
365     return 0;
366 }
367
368 static void omap_rfbi_reset(struct omap_dss_s *s)
369 {
370     s->rfbi.idlemode = 0;
371     s->rfbi.control = 2;
372     s->rfbi.enable = 0;
373     s->rfbi.pixels = 0;
374     s->rfbi.skiplines = 0;
375     s->rfbi.busy = 0;
376     s->rfbi.config[0] = 0x00310000;
377     s->rfbi.config[1] = 0x00310000;
378     s->rfbi.time[0] = 0;
379     s->rfbi.time[1] = 0;
380     s->rfbi.time[2] = 0;
381     s->rfbi.time[3] = 0;
382     s->rfbi.data[0] = 0;
383     s->rfbi.data[1] = 0;
384     s->rfbi.data[2] = 0;
385     s->rfbi.data[3] = 0;
386     s->rfbi.data[4] = 0;
387     s->rfbi.data[5] = 0;
388     s->rfbi.vsync = 0;
389     s->rfbi.hsync = 0;
390 }
391
392 void omap_dss_reset(struct omap_dss_s *s)
393 {
394     int i, j;
395     
396     s->autoidle = 0x10; /* was 0 for OMAP2 but bit4 must be set for OMAP3 */
397     s->control = 0;
398     s->sdi_control = 0;
399     s->pll_control = 0;
400     s->enable = 0;
401
402     s->dig.enable = 0;
403     s->dig.nx = 1;
404     s->dig.ny = 1;
405
406     s->lcd.enable = 0;
407     s->lcd.nx = 1;
408     s->lcd.ny = 1;
409
410     s->dispc.idlemode = 0;
411     s->dispc.irqst = 0;
412     s->dispc.irqen = 0;
413     s->dispc.control = 0;
414     s->dispc.config = 0;
415     s->dispc.capable = 0x161;
416     s->dispc.timing[0] = 0;
417     s->dispc.timing[1] = 0;
418     s->dispc.timing[2] = 0;
419     s->dispc.timing[3] = 0x00010002;
420     s->dispc.line = 0;
421     s->dispc.bg[0] = 0;
422     s->dispc.bg[1] = 0;
423     s->dispc.trans[0] = 0;
424     s->dispc.trans[1] = 0;
425     s->dispc.global_alpha = 0;
426     s->dispc.cpr_coef_r = 0;
427     s->dispc.cpr_coef_g = 0;
428     s->dispc.cpr_coef_b = 0;
429
430     for (i = 0; i < 3; i++) {
431         s->dispc.l[i].enable = 0;
432         s->dispc.l[i].bpp = 0;
433         s->dispc.l[i].addr[0] = 0;
434         s->dispc.l[i].addr[1] = 0;
435         s->dispc.l[i].addr[2] = 0;
436         s->dispc.l[i].posx = 0;
437         s->dispc.l[i].posy = 0;
438         s->dispc.l[i].nx = 1;
439         s->dispc.l[i].ny = 1;
440         s->dispc.l[i].attr = 0;
441         s->dispc.l[i].tresh = (s->dispc.rev < 0x30) ? 0 : 0x03ff03c0;
442         s->dispc.l[i].rowinc = 1;
443         s->dispc.l[i].colinc = 1;
444         s->dispc.l[i].wininc = 0;
445         s->dispc.l[i].preload = 0x100;
446         s->dispc.l[i].fir = 0;
447         s->dispc.l[i].picture_size = 0;
448         s->dispc.l[i].accu[0] = 0;
449         s->dispc.l[i].accu[1] = 0;
450         for (j = 0; j < 5; j++)
451             s->dispc.l[i].conv_coef[j] = 0;
452         for (j = 0; j < 8; j++) {
453             s->dispc.l[i].fir_coef_h[j] = 0;
454             s->dispc.l[i].fir_coef_hv[j] = 0;
455             s->dispc.l[i].fir_coef_v[j] = 0;
456         }
457     }
458         
459     s->dsi.irqst = 0;
460     s->dsi.irqen = 0;
461     
462     omap_rfbi_reset(s);
463     omap_dss_interrupt_update(s);
464 }
465
466 static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
467 {
468     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
469
470
471     switch (addr) {
472     case 0x00:  /* DSS_REVISIONNUMBER */
473         TRACEREG("DSS_REVISIONNUMBER: 0x20");
474         return 0x20;
475
476     case 0x10:  /* DSS_SYSCONFIG */
477         TRACEREG("DSS_SYSCONFIG: 0x%08x", s->autoidle);
478         return s->autoidle;
479
480     case 0x14:  /* DSS_SYSSTATUS */
481         TRACEREG("DSS_SYSSTATUS: 0x1");
482         return 1;                                               /* RESETDONE */
483             
484     case 0x18:  /* DSS_IRQSTATUS */
485         TRACEREG("DSS_IRQSTATUS: 0x%08x",
486                  ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0) 
487                  | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0));
488         return ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0) 
489             | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0);
490             
491     case 0x40:  /* DSS_CONTROL */
492         TRACEREG("DSS_CONTROL: 0x%08x", s->control);
493         return s->control;
494
495     case 0x44:  /* DSS_SDI_CONTROL */
496         TRACEREG("DSS_SDI_CONTROL: 0x%08x", s->sdi_control);
497         return s->sdi_control;
498             
499     case 0x48: /* DSS_PLL_CONTROL */
500         TRACEREG("DSS_PLL_CONTROL: 0x%08x", s->pll_control);
501         return s->pll_control;
502
503     case 0x50:  /* DSS_PSA_LCD_REG_1 */
504     case 0x54:  /* DSS_PSA_LCD_REG_2 */
505     case 0x58:  /* DSS_PSA_VIDEO_REG */
506         TRACEREG("DSS_PSA_xxx: 0");
507         /* TODO: fake some values when appropriate s->control bits are set */
508         return 0;
509
510     case 0x5c:  /* DSS_SDI_STATUS */
511         /* TODO: check and implement missing OMAP3 bits */
512         TRACEREG("DSS_STATUS: 0x%08x", 1 + (s->control & 1));
513         return 1 + (s->control & 1);
514
515     default:
516         break;
517     }
518     OMAP_BAD_REG(addr);
519     return 0;
520 }
521
522 static void omap_diss_write(void *opaque, target_phys_addr_t addr,
523                 uint32_t value)
524 {
525     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
526
527     switch (addr) {
528     case 0x00:  /* DSS_REVISIONNUMBER */
529     case 0x14:  /* DSS_SYSSTATUS */
530     case 0x18:  /* DSS_IRQSTATUS */
531     case 0x50:  /* DSS_PSA_LCD_REG_1 */
532     case 0x54:  /* DSS_PSA_LCD_REG_2 */
533     case 0x58:  /* DSS_PSA_VIDEO_REG */
534     case 0x5c:  /* DSS_STATUS */
535         /* quietly ignore */
536         /*OMAP_RO_REGV(addr, value);*/
537         break;
538
539     case 0x10:  /* DSS_SYSCONFIG */
540         TRACEREG("DSS_SYSCONFIG = 0x%08x", value);
541         if (value & 2)                                          /* SOFTRESET */
542             omap_dss_reset(s);
543         s->autoidle = value & 0x19; /* was 0x01 for OMAP2 */
544         break;
545
546     case 0x40:  /* DSS_CONTROL */
547         TRACEREG("DSS_CONTROL = 0x%08x", value);
548         s->control = value & 0x3ff; /* was 0x3dd for OMAP2 */
549         break;
550
551     case 0x44: /* DSS_SDI_CONTROL */
552         TRACEREG("DSS_SDI_CONTROL = 0x%08x", value);
553         s->sdi_control = value & 0x000ff80f;
554         break;
555
556     case 0x48: /* DSS_PLL_CONTROL */
557         TRACEREG("DSS_PLL_CONTROL = 0x%08x", value);
558         s->pll_control = value;
559         break;
560             
561     default:
562         OMAP_BAD_REGV(addr, value);
563         break;
564     }
565 }
566
567 static CPUReadMemoryFunc *omap_diss1_readfn[] = {
568     omap_badwidth_read32,
569     omap_badwidth_read32,
570     omap_diss_read,
571 };
572
573 static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
574     omap_badwidth_write32,
575     omap_badwidth_write32,
576     omap_diss_write,
577 };
578
579 static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
580 {
581     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
582     int n = 0;
583
584     switch (addr) {
585     case 0x000: /* DISPC_REVISION */
586         TRACEREG("DISPC_REVISION: 0x%08x", s->dispc.rev);
587         return s->dispc.rev;
588     case 0x010: /* DISPC_SYSCONFIG */
589         TRACEREG("DISPC_SYSCONFIG: 0x%08x", s->dispc.idlemode);
590         return s->dispc.idlemode;
591     case 0x014: /* DISPC_SYSSTATUS */
592         TRACEREG("DISPC_SYSSTATUS: 1");
593         return 1;                                               /* RESETDONE */
594     case 0x018: /* DISPC_IRQSTATUS */
595         TRACEREG("DISPC_IRQSTATUS: 0x%08x", s->dispc.irqst);
596         return s->dispc.irqst;
597     case 0x01c: /* DISPC_IRQENABLE */
598         TRACEREG("DISPC_IRQENABLE: 0x%08x", s->dispc.irqen);
599         return s->dispc.irqen;
600     case 0x040: /* DISPC_CONTROL */
601         TRACEREG("DISPC_CONTROL: 0x%08x", s->dispc.control);
602         return s->dispc.control;
603     case 0x044: /* DISPC_CONFIG */
604         TRACEREG("DISPC_CONFIG: 0x%08x", s->dispc.config);
605         return s->dispc.config;
606     case 0x048: /* DISPC_CAPABLE */
607         TRACEREG("DISPC_CAPABLE: 0x%08x", s->dispc.capable);
608         return s->dispc.capable;
609     case 0x04c: /* DISPC_DEFAULT_COLOR0 */
610         TRACEREG("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[0]);
611         return s->dispc.bg[0];
612     case 0x050: /* DISPC_DEFAULT_COLOR1 */
613         TRACEREG("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[1]);
614         return s->dispc.bg[1];
615     case 0x054: /* DISPC_TRANS_COLOR0 */
616         TRACEREG("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[0]);
617         return s->dispc.trans[0];
618     case 0x058: /* DISPC_TRANS_COLOR1 */
619         TRACEREG("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[1]);
620         return s->dispc.trans[1];
621     case 0x05c: /* DISPC_LINE_STATUS */
622         TRACEREG("DISPC_LINE_STATUS: 0x7ff");
623         return 0x7ff;
624     case 0x060: /* DISPC_LINE_NUMBER */
625         TRACEREG("DISPC_LINE_NUMBER: 0x%08x", s->dispc.line);
626         return s->dispc.line;
627     case 0x064: /* DISPC_TIMING_H */
628         TRACEREG("DISPC_TIMING_H: 0x%08x", s->dispc.timing[0]);
629         return s->dispc.timing[0];
630     case 0x068: /* DISPC_TIMING_V */
631         TRACEREG("DISPC_TIMING_H: 0x%08x", s->dispc.timing[1]);
632         return s->dispc.timing[1];
633     case 0x06c: /* DISPC_POL_FREQ */
634         TRACEREG("DISPC_POL_FREQ: 0x%08x", s->dispc.timing[2]);
635         return s->dispc.timing[2];
636     case 0x070: /* DISPC_DIVISOR */
637         TRACEREG("DISPC_DIVISOR: 0x%08x", s->dispc.timing[3]);
638         return s->dispc.timing[3];
639     case 0x074: /* DISPC_GLOBAL_ALPHA */
640         TRACEREG("DISPC_GLOBAL_ALPHA: 0x%08x", s->dispc.global_alpha);
641         return s->dispc.global_alpha;
642     case 0x078: /* DISPC_SIZE_DIG */
643         TRACEREG("DISPC_SIZE_DIG: 0x%08x", ((s->dig.ny - 1) << 16) | (s->dig.nx - 1));
644         return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
645     case 0x07c: /* DISPC_SIZE_LCD */
646         TRACEREG("DISPC_SIZE_LCD: 0x%08x", ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1));
647         return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
648     case 0x14c: /* DISPC_VID2_BA0 */
649         n++;
650     case 0x0bc: /* DISPC_VID1_BA0 */
651         n++;
652     case 0x080: /* DISPC_GFX_BA0 */
653         TRACEREG("DISPC_%s_BA0: 0x%08x", LAYERNAME(n), s->dispc.l[n].addr[0]);
654         return s->dispc.l[n].addr[0];
655     case 0x150: /* DISPC_VID2_BA1 */
656         n++;
657     case 0x0c0: /* DISPC_VID1_BA1 */
658         n++;
659     case 0x084: /* DISPC_GFX_BA1 */
660         TRACEREG("DISPC_%s_BA1: 0x%08x", LAYERNAME(n), s->dispc.l[n].addr[1]);
661         return s->dispc.l[n].addr[1];
662     case 0x154: /* DISPC_VID2_POSITION */
663         n++;
664     case 0x0c4: /* DISPC_VID1_POSITION */
665         n++;
666     case 0x088: /* DISPC_GFX_POSITION */
667         TRACEREG("DISPC_%s_POSITION: 0x%08x", LAYERNAME(n),
668                  (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx);
669         return (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx;
670     case 0x158: /* DISPC_VID2_SIZE */
671         n++;
672     case 0x0c8: /* DISPC_VID1_SIZE */
673         n++;
674     case 0x08c: /* DISPC_GFX_SIZE */
675         TRACEREG("DISPC_%s_SIZE: 0x%08x", LAYERNAME(n),
676                  ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1));
677         return ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1);
678     case 0x15c: /* DISPC_VID2_ATTRIBUTES */
679         n++;
680     case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
681         n++;
682     case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
683         TRACEREG("DISPC_%s_ATTRIBUTES: 0x%08x", LAYERNAME(n),
684                  s->dispc.l[n].attr);
685         return s->dispc.l[n].attr;
686     case 0x160: /* DISPC_VID2_FIFO_THRESHOLD */
687         n++;
688     case 0x0d0: /* DISPC_VID1_FIFO_THRESHOLD */
689         n++;
690     case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
691         TRACEREG("DISPC_%s_THRESHOLD: 0x%08x", LAYERNAME(n),
692                  s->dispc.l[n].tresh);
693         return s->dispc.l[n].tresh;
694     case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */
695         n++;
696     case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */
697         n++;
698     case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
699         TRACEREG("DISPC_%s_FIFO_SIZE_STATUS: 0x%08x", LAYERNAME(n),
700                  s->dispc.rev < 0x30 ? 256 : 1024);
701         return s->dispc.rev < 0x30 ? 256 : 1024;
702     case 0x168: /* DISPC_VID2_ROW_INC */
703         n++;
704     case 0x0d8: /* DISPC_VID1_ROW_INC */
705         n++;
706     case 0x0ac: /* DISPC_GFX_ROW_INC */
707         TRACEREG("DISPC_%s_ROW_INC: 0x%08x", LAYERNAME(n),
708                  s->dispc.l[n].rowinc);
709         return s->dispc.l[n].rowinc;
710     case 0x16c: /* DISPC_VID2_PIXEL_INC */
711         n++;
712     case 0x0dc: /* DISPC_VID1_PIXEL_INC */
713         n++;
714     case 0x0b0: /* DISPC_GFX_PIXEL_INC */
715         TRACEREG("DISPC_%s_PIXEL_INC: 0x%08x", LAYERNAME(n),
716                  s->dispc.l[n].colinc);
717         return s->dispc.l[n].colinc;
718     case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
719         TRACEREG("DISPC_GFX_WINDOW_SKIP: 0x%08x", s->dispc.l[0].wininc);
720         return s->dispc.l[0].wininc;
721     case 0x0b8: /* DISPC_GFX_TABLE_BA */
722         TRACEREG("DISPC_GFX_TABLE_BA: 0x%08x", s->dispc.l[0].addr[2]);
723         return s->dispc.l[0].addr[2];
724     case 0x170: /* DISPC_VID2_FIR */
725         n++;
726     case 0x0e0: /* DISPC_VID1_FIR */
727         n++;
728         TRACEREG("DISPC_%s_FIR: 0x%08x", LAYERNAME(n),
729                  s->dispc.l[n].fir);
730         return s->dispc.l[n].fir;
731     case 0x174: /* DISPC_VID2_PICTURE_SIZE */
732         n++;
733     case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
734         n++;
735         TRACEREG("DISPC_%s_PICTURE_SIZE: 0x%08x", LAYERNAME(n),
736                  s->dispc.l[n].picture_size);
737         return s->dispc.l[n].picture_size;
738     case 0x178: /* DISPC_VID2_ACCU0 */
739     case 0x17c: /* DISPC_VID2_ACCU1 */
740         n++;
741     case 0x0e8: /* DISPC_VID1_ACCU0 */
742     case 0x0ec: /* DISPC_VID1_ACCU1 */
743         n++;
744         TRACEREG("DISPC_%s_ACCU%d: 0x%08x", LAYERNAME(n),
745                  (addr >> 1) & 1, s->dispc.l[n].accu[(addr >> 1 ) & 1]);
746         return s->dispc.l[n].accu[(addr >> 1) & 1];
747     case 0x180 ... 0x1bc:       /* DISPC_VID2_FIR_COEF */
748         n++;
749     case 0x0f0 ... 0x12c:       /* DISPC_VID1_FIR_COEF */
750         n++;
751         if (addr & 4) {
752             TRACEREG("DISPC_%s_FIR_COEF_HV%d: 0x%08x", LAYERNAME(n),
753                      (addr - ((n > 1) ? 0x180 : 0xf0)) / 8,
754                      s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
755             return s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
756         }
757         TRACEREG("DISPC_%s_FIR_COEF_H%d: 0x%08x", LAYERNAME(n),
758                  (addr - ((n > 1) ? 0x180 : 0xf0)) / 8,
759                  s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
760         return s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
761     case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
762         n++;
763     case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
764         n++;
765         TRACEREG("DISPC_%s_CONV_COEF%d: 0x%08x", LAYERNAME(n),
766                  (addr - ((n > 1) ? 0x1c0 : 0x130)) / 4,
767                  s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4]);
768         return s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4];
769     case 0x1d4: /* DISPC_DATA_CYCLE1 */
770     case 0x1d8: /* DISPC_DATA_CYCLE2 */
771     case 0x1dc: /* DISPC_DATA_CYCLE3 */
772         TRACEREG("DISPC_DATA_CYCLE%d: 0", (addr - 0x1d4) / 4);
773         return 0;
774     case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
775         n++;
776     case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
777         n++;
778         TRACEREG("DISPC_%s_FIR_COEF_V%d: 0x%08x", LAYERNAME(n),
779                  (addr & 0x01f) / 4,
780                  s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4]);
781         return s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4];
782     case 0x220: /* DISPC_CPR_COEF_R */
783         TRACEREG("DISPC_CPR_COEF_R: 0x%08x", s->dispc.cpr_coef_r);
784         return s->dispc.cpr_coef_r;
785     case 0x224: /* DISPC_CPR_COEF_G */
786         TRACEREG("DISPC_CPR_COEF_G: 0x%08x", s->dispc.cpr_coef_g);
787         return s->dispc.cpr_coef_g;
788     case 0x228: /* DISPC_CPR_COEF_B */
789         TRACEREG("DISPC_CPR_COEF_B: 0x%08x", s->dispc.cpr_coef_b);
790         return s->dispc.cpr_coef_b;
791     case 0x234: /* DISPC_VID2_PRELOAD */
792         n++;
793     case 0x230: /* DISPC_VID1_PRELOAD */
794         n++;
795     case 0x22c: /* DISPC_GFX_PRELOAD */
796         TRACEREG("DISPC_%s_PRELOAD: 0x%08x", LAYERNAME(n),
797                  s->dispc.l[n].preload);
798         return s->dispc.l[n].preload;
799     default:
800         break;
801     }
802     OMAP_BAD_REG(addr);
803     return 0;
804 }
805
806 static void omap_disc_write(void *opaque, target_phys_addr_t addr,
807                 uint32_t value)
808 {
809     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
810     int n = 0;
811
812     switch (addr) {
813     case 0x000: /* DISPC_REVISION */
814     case 0x014: /* DISPC_SYSSTATUS */
815     case 0x05c: /* DISPC_LINE_STATUS */
816     case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
817         /* quietly ignore */
818         /*OMAP_RO_REGV(addr, value);*/
819         break;
820     case 0x010: /* DISPC_SYSCONFIG */
821         TRACEREG("DISPC_SYSCONFIG = 0x%08x", value);
822         if (value & 2)                                          /* SOFTRESET */
823             omap_dss_reset(s);
824         s->dispc.idlemode = value & ((s->dispc.rev < 0x30) ? 0x301b : 0x331f);
825         break;
826     case 0x018: /* DISPC_IRQSTATUS */
827         TRACEREG("DISPC_IRQSTATUS = 0x%08x", value);
828         s->dispc.irqst &= ~value;
829         omap_dss_interrupt_update(s);
830         break;
831     case 0x01c: /* DISPC_IRQENABLE */
832         TRACEREG("DISPC_IRQENABLE = 0x%08x", value);
833         s->dispc.irqen = value & ((s->dispc.rev < 0x30) ? 0xffff : 0x1ffff);
834         omap_dss_interrupt_update(s);
835         break;
836     case 0x040: /* DISPC_CONTROL */
837         TRACEREG("DISPC_CONTROL = 0x%08x", value);
838         if (s->dispc.rev < 0x30)
839             s->dispc.control = value & 0x07ff9fff;
840         else
841             s->dispc.control = (value & 0xffff9bff) | (s->dispc.control & 0x6000);
842         s->dig.enable = (value >> 1) & 1;
843         s->lcd.enable = (value >> 0) & 1;
844         if (value & (1 << 12))                  /* OVERLAY_OPTIMIZATION */
845             if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
846                  fprintf(stderr, "%s: Overlay Optimization when no overlay "
847                                  "region effectively exists leads to "
848                                  "unpredictable behaviour!\n", __FUNCTION__);
849         if (value & (1 << 6)) {                         /* GODIGITAL */
850             /* XXX: Shadowed fields are:
851              * s->dispc.config
852              * s->dispc.capable
853              * s->dispc.bg[0]
854              * s->dispc.bg[1]
855              * s->dispc.trans[0]
856              * s->dispc.trans[1]
857              * s->dispc.line
858              * s->dispc.timing[0]
859              * s->dispc.timing[1]
860              * s->dispc.timing[2]
861              * s->dispc.timing[3]
862              * s->lcd.nx
863              * s->lcd.ny
864              * s->dig.nx
865              * s->dig.ny
866              * s->dispc.l[0].addr[0]
867              * s->dispc.l[0].addr[1]
868              * s->dispc.l[0].addr[2]
869              * s->dispc.l[0].posx
870              * s->dispc.l[0].posy
871              * s->dispc.l[0].nx
872              * s->dispc.l[0].ny
873              * s->dispc.l[0].tresh
874              * s->dispc.l[0].rowinc
875              * s->dispc.l[0].colinc
876              * s->dispc.l[0].wininc
877              * All they need to be loaded here from their shadow registers.
878              */
879             s->dispc.control &= ~(1 << 6); /* GODIGITAL finished */
880         }
881         if (value & (1 << 5)) {                         /* GOLCD */
882              /* XXX: Likewise for LCD here.  */
883             s->dispc.control &= ~(1 << 5); /* GOLCD finished */
884         }
885         s->dispc.invalidate = 1;
886         break;
887     case 0x044: /* DISPC_CONFIG */
888         TRACEREG("DISPC_CONFIG = 0x%08x", value);
889         s->dispc.config = value & 0x3fff;
890         /* XXX:
891          * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
892          * bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
893          */
894         s->dispc.invalidate = 1;
895         break;
896     case 0x048: /* DISPC_CAPABLE */
897         TRACEREG("DISPC_CAPABLE = 0x%08x", value);
898         s->dispc.capable = value & 0x3ff;
899         break;
900     case 0x04c: /* DISPC_DEFAULT_COLOR0 */
901         TRACEREG("DISPC_DEFAULT_COLOR0 = 0x%08x", value);
902         s->dispc.bg[0] = value & 0xffffff;
903         s->dispc.invalidate = 1;
904         break;
905     case 0x050: /* DISPC_DEFAULT_COLOR1 */
906         TRACEREG("DISPC_DEFAULT_COLOR1 = 0x%08x", value);
907         s->dispc.bg[1] = value & 0xffffff;
908         s->dispc.invalidate = 1;
909         break;
910     case 0x054: /* DISPC_TRANS_COLOR0 */
911         TRACEREG("DISPC_TRANS_COLOR0 = 0x%08x", value);
912         s->dispc.trans[0] = value & 0xffffff;
913         s->dispc.invalidate = 1;
914         break;
915     case 0x058: /* DISPC_TRANS_COLOR1 */
916         TRACEREG("DISPC_TRANS_COLOR1 = 0x%08x", value);
917         s->dispc.trans[1] = value & 0xffffff;
918         s->dispc.invalidate = 1;
919         break;
920     case 0x060: /* DISPC_LINE_NUMBER */
921         TRACEREG("DISPC_LINE_NUMBER = 0x%08x", value);
922         s->dispc.line = value & 0x7ff;
923         break;
924     case 0x064: /* DISPC_TIMING_H */
925         TRACEREG("DISPC_TIMING_H = 0x%08x", value);
926         s->dispc.timing[0] = value & 0x0ff0ff3f;
927         break;
928     case 0x068: /* DISPC_TIMING_V */
929         TRACEREG("DISPC_TIMING_V = 0x%08x", value);
930         s->dispc.timing[1] = value & 0x0ff0ff3f;
931         break;
932     case 0x06c: /* DISPC_POL_FREQ */
933         TRACEREG("DISPC_POL_FREQ = 0x%08x", value);
934         s->dispc.timing[2] = value & 0x0003ffff;
935         break;
936     case 0x070: /* DISPC_DIVISOR */
937         TRACEREG("DISPC_DIVISOR = 0x%08x", value);
938         s->dispc.timing[3] = value & 0x00ff00ff;
939         break;
940     case 0x074: /* DISPC_GLOBAL_ALPHA */
941         TRACEREG("DISPC_GLOBAL_ALPHA = 0x%08x", value);
942         s->dispc.global_alpha = value & 0x00ff00ff;
943         break;
944     case 0x078: /* DISPC_SIZE_DIG */
945         s->dig.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
946         s->dig.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
947         s->dispc.invalidate = 1;
948         TRACEREG("DISPC_SIZE_DIG = 0x%08x (%dx%d)", value, s->dig.nx, s->dig.ny);
949         break;
950     case 0x07c: /* DISPC_SIZE_LCD */
951         s->lcd.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
952         s->lcd.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
953         s->dispc.invalidate = 1;
954         TRACEREG("DISPC_SIZE_LCD = 0x%08x (%dx%d)", value, s->lcd.nx, s->lcd.ny);
955         break;
956     case 0x14c: /* DISPC_VID2_BA0 */
957         n++;
958     case 0x0bc: /* DISPC_VID1_BA0 */
959         n++;
960     case 0x080: /* DISPC_GFX_BA0 */
961         TRACEREG("DISPC_%s_BA0 = 0x%08x", LAYERNAME(n), value);
962         s->dispc.l[n].addr[0] = (target_phys_addr_t) value;
963         s->dispc.invalidate = 1;
964         break;
965     case 0x150: /* DISPC_VID2_BA1 */
966         n++;
967     case 0x0c0: /* DISPC_VID1_BA1 */
968         n++;
969     case 0x084: /* DISPC_GFX_BA1 */
970         TRACEREG("DISPC_%s_BA1 = 0x%08x", LAYERNAME(n), value);
971         s->dispc.l[n].addr[1] = (target_phys_addr_t) value;
972         s->dispc.invalidate = 1;
973         break;
974     case 0x154: /* DISPC_VID2_POSITION */
975         n++;
976     case 0x0c4: /* DISPC_VID1_POSITION */
977         n++;
978     case 0x088: /* DISPC_GFX_POSITION */
979         s->dispc.l[n].posx = ((value >>  0) & 0x7ff);           /* GFXPOSX */
980         s->dispc.l[n].posy = ((value >> 16) & 0x7ff);           /* GFXPOSY */
981         s->dispc.invalidate = 1;
982         TRACEREG("DISPC_%s_POSITION = 0x%08x (%d,%d)", LAYERNAME(n),
983                  value, s->dispc.l[n].posx, s->dispc.l[n].posy);
984         break;
985     case 0x158: /* DISPC_VID2_SIZE */
986         n++;
987     case 0x0c8: /* DISPC_VID1_SIZE */
988         n++;
989     case 0x08c: /* DISPC_GFX_SIZE */
990         s->dispc.l[n].nx = ((value >>  0) & 0x7ff) + 1;         /* GFXSIZEX */
991         s->dispc.l[n].ny = ((value >> 16) & 0x7ff) + 1;         /* GFXSIZEY */
992         TRACEREG("DISPC_%s_SIZE = 0x%08x (%dx%d)", LAYERNAME(n),
993                  value, s->dispc.l[n].nx, s->dispc.l[n].ny);
994         s->dispc.invalidate = 1;
995         break;
996         n++;
997     case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
998         TRACEREG("DISPC_GFX_ATTRIBUTES = 0x%08x", value);
999         s->dispc.l[0].attr = value & 0xffff;
1000         if (value & (3 << 9))
1001             fprintf(stderr, "%s: Big-endian pixel format not supported\n",
1002                             __FUNCTION__);
1003         s->dispc.l[0].enable = value & 1;
1004         s->dispc.l[0].bpp = (value >> 1) & 0xf;
1005         s->dispc.l[0].rotation_flag = (value >> 12) & 0x3;
1006         s->dispc.l[0].gfx_format = (value >> 1) & 0xf;
1007         s->dispc.l[0].gfx_channel = (value >> 8) & 0x1;
1008         s->dispc.invalidate = 1;
1009         break;
1010     case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
1011         n++;
1012     case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
1013         n++;
1014     case 0x0a4: /* DISPC_GFX_FIFO_THRESHOLD */
1015         TRACEREG("DISPC_%s_FIFO_THRESHOLD = 0x%08x", LAYERNAME(n), value);
1016         s->dispc.l[n].tresh = value & ((s->dispc.rev < 0x30) 
1017                                        ? 0x01ff01ff : 0x0fff0fff);
1018         break;
1019     case 0x168: /* DISPC_VID2_ROW_INC */
1020         n++;
1021     case 0x0d8: /* DISPC_VID1_ROW_INC */
1022         n++;
1023     case 0x0ac: /* DISPC_GFX_ROW_INC */
1024         TRACEREG("DISPC_%s_ROW_INC = 0x%08x", LAYERNAME(n), value);
1025         s->dispc.l[n].rowinc = value;
1026         s->dispc.invalidate = 1;
1027         break;
1028     case 0x16c: /* DISPC_VID2_PIXEL_INC */
1029         n++;
1030     case 0x0dc: /* DISPC_VID1_PIXEL_INC */
1031         n++;
1032     case 0x0b0: /* DISPC_GFX_PIXEL_INC */
1033         TRACEREG("DISPC_%s_PIXEL_INC = 0x%08x", LAYERNAME(n), value);
1034         s->dispc.l[n].colinc = value;
1035         s->dispc.invalidate = 1;
1036         break;
1037     case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
1038         TRACEREG("DISPC_GFX_WINDOW_SKIP = 0x%08x", value);
1039         s->dispc.l[0].wininc = value;
1040         break;
1041     case 0x0b8: /* DISPC_GFX_TABLE_BA */
1042         TRACEREG("DISPC_GFX_TABLE_BA = 0x%08x", value);
1043         s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
1044         s->dispc.invalidate = 1;
1045         break;
1046     case 0x15c: /* DISPC_VID2_ATTRIBUTES */
1047         n++;
1048     case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
1049         n++;
1050         TRACEREG("DISPC_%s_ATTRIBUTES = 0x%08x", LAYERNAME(n), value);
1051         s->dispc.l[n].attr = value & 0x1fffffff;
1052         break;
1053     case 0x170: /* DISPC_VID2_FIR */
1054         n++;
1055     case 0x0e0: /* DISPC_VID1_FIR */
1056         n++;
1057         TRACEREG("DISPC_%s_FIR = 0x%08x", LAYERNAME(n), value);
1058         s->dispc.l[n].fir = value & 0x1fff1fff;
1059         break;
1060     case 0x174: /* DISPC_VID2_PICTURE_SIZE */
1061         n++;
1062     case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
1063         n++;
1064         TRACEREG("DISPC_%s_PICTURE_SIZE = 0x%08x", LAYERNAME(n), value);
1065         s->dispc.l[n].picture_size = value & 0x07ff07ff;
1066         break;
1067     case 0x178: /* DISPC_VID2_ACCU0 */
1068     case 0x17c: /* DISPC_VID2_ACCU1 */
1069         n++;
1070     case 0x0e8: /* DISPC_VID1_ACCU0 */
1071     case 0x0ec: /* DISPC_VID1_ACCU1 */
1072         n++;
1073         TRACEREG("DISPC_%s_ACCU%d = 0x%08x", LAYERNAME(n),
1074                  (addr >> 1) & 1, value);
1075         s->dispc.l[n].accu[(addr >> 1) & 1] = value & 0x03ff03ff;
1076         break;
1077     case 0x180 ... 0x1bc:       /* DISPC_VID2_FIR_COEF */
1078         n++;
1079     case 0x0f0 ... 0x12c:       /* DISPC_VID1_FIR_COEF */
1080         n++;
1081         if (addr & 4) {
1082             TRACEREG("DISPC_%s_FIR_COEF_HV%d = 0x%08x", LAYERNAME(n),
1083                      (addr - ((n > 1) ? 0x180 : 0xf0)) / 8, value);
1084             s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
1085         } else {
1086             TRACEREG("DISPC_%s_FIR_COEF_H%d = 0x%08x", LAYERNAME(n),
1087                      (addr - ((n > 1) ? 0x180 : 0xf0)) / 8, value);
1088             s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
1089         }
1090         break;
1091     case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
1092         n++;
1093     case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
1094         n++;
1095         TRACEREG("DISPC_%s_CONV_COEF%d = 0x%08x", LAYERNAME(n),
1096                  (addr - ((n > 1) ? 0x1c0 : 0x130)) / 4, value);
1097         s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4] = value;
1098         break;
1099     case 0x1d4: /* DISPC_DATA_CYCLE1 */
1100     case 0x1d8: /* DISPC_DATA_CYCLE2 */
1101     case 0x1dc: /* DISPC_DATA_CYCLE3 */
1102         TRACEREG("DISPC_DATA_CYCLE%d = 0x%08x (ignored)", (addr - 0x1d4) / 4, value);
1103         break;
1104     case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
1105         n++;
1106     case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
1107         n++;
1108         TRACEREG("DISPC_%s_FIR_COEF_V%d = 0x%08x", LAYERNAME(n),
1109                  (addr & 0x01f) / 4, value);
1110         s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4] = value & 0x0000ffff;
1111         break;
1112     case 0x220: /* DISPC_CPR_COEF_R */
1113         TRACEREG("DISPC_CPR_COEF_R = 0x%08x", value);
1114         s->dispc.cpr_coef_r = value & 0xffbffbff;
1115         break;
1116     case 0x224: /* DISPC_CPR_COEF_G */
1117         TRACEREG("DISPC_CPR_COEF_G = 0x%08x", value);
1118         s->dispc.cpr_coef_g = value & 0xffbffbff;
1119         break;
1120     case 0x228: /* DISPC_CPR_COEF_B */
1121         TRACEREG("DISPC_CPR_COEF_B = 0x%08x", value);
1122         s->dispc.cpr_coef_b = value & 0xffbffbff;
1123         break;
1124     case 0x234: /* DISPC_VID2_PRELOAD */
1125         n++;
1126     case 0x230: /* DISPC_VID1_PRELOAD */
1127         n++;
1128     case 0x22c: /* DISPC_GFX_PRELOAD */
1129         TRACEREG("DISPC_%s_PRELOAD = 0x%08x", LAYERNAME(n), value);
1130         s->dispc.l[n].preload = value & 0x0fff;
1131         break;
1132     default:
1133         OMAP_BAD_REGV(addr, value);
1134         break;
1135     }
1136 }
1137
1138 static CPUReadMemoryFunc *omap_disc1_readfn[] = {
1139     omap_badwidth_read32,
1140     omap_badwidth_read32,
1141     omap_disc_read,
1142 };
1143
1144 static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
1145     omap_badwidth_write32,
1146     omap_badwidth_write32,
1147     omap_disc_write,
1148 };
1149
1150 static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
1151 {
1152     target_phys_addr_t fb;
1153     uint32_t pd;
1154
1155     /* TODO */
1156     fb = s->dispc.l[0].addr[0];
1157
1158     pd = cpu_get_physical_page_desc(fb);
1159     if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
1160         /* TODO */
1161         cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
1162                         __FUNCTION__);
1163     else
1164         return phys_ram_base +
1165                 (pd & TARGET_PAGE_MASK) +
1166                 (fb & ~TARGET_PAGE_MASK);
1167 }
1168
1169 static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
1170 {
1171     if (!s->rfbi.busy)
1172         return;
1173
1174     /* TODO: in non-Bypass mode we probably need to just deassert the DRQ.  */
1175
1176     s->rfbi.busy = 0;
1177 }
1178
1179 static void omap_rfbi_transfer_start(struct omap_dss_s *s)
1180 {
1181     void *data;
1182     size_t len;
1183     int pitch;
1184
1185     if (!s->rfbi.enable || s->rfbi.busy)
1186         return;
1187
1188     if (s->rfbi.control & (1 << 1)) {                           /* BYPASS */
1189         /* TODO: in non-Bypass mode we probably need to just assert the
1190          * DRQ and wait for DMA to write the pixels.  */
1191         fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
1192         return;
1193     }
1194
1195     if (!(s->dispc.control & (1 << 11)))                        /* RFBIMODE */
1196         return;
1197     /* TODO: check that LCD output is enabled in DISPC.  */
1198
1199     s->rfbi.busy = 1;
1200
1201     data = omap_rfbi_get_buffer(s);
1202
1203     /* TODO bpp */
1204     len = s->rfbi.pixels * 2;
1205     s->rfbi.pixels = 0;
1206
1207     /* TODO: negative values */
1208     pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
1209
1210     if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1211         s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
1212     if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1213         s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
1214
1215     omap_rfbi_transfer_stop(s);
1216
1217     /* TODO */
1218     s->dispc.irqst |= 1;                                        /* FRAMEDONE */
1219     omap_dss_interrupt_update(s);
1220 }
1221
1222 static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
1223 {
1224     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1225
1226     switch (addr) {
1227     case 0x00:  /* RFBI_REVISION */
1228         TRACEREG("RFBI_REVISION: 0x10");
1229         return 0x10;
1230
1231     case 0x10:  /* RFBI_SYSCONFIG */
1232         TRACEREG("RFBI_SYSCONFIG: 0x%08x", s->rfbi.idlemode);
1233         return s->rfbi.idlemode;
1234
1235     case 0x14:  /* RFBI_SYSSTATUS */
1236         TRACEREG("RFBI_SYSSTATUS: 0x%08x", 1 | (s->rfbi.busy << 8));
1237         return 1 | (s->rfbi.busy << 8);                         /* RESETDONE */
1238
1239     case 0x40:  /* RFBI_CONTROL */
1240         TRACEREG("RFBI_CONTROL: 0x%08x", s->rfbi.control);
1241         return s->rfbi.control;
1242
1243     case 0x44:  /* RFBI_PIXELCNT */
1244         TRACEREG("RFBI_PIXELCNT: 0x%08x", s->rfbi.pixels);
1245         return s->rfbi.pixels;
1246
1247     case 0x48:  /* RFBI_LINE_NUMBER */
1248         TRACEREG("RFBI_LINE_NUMBER: 0x%08x", s->rfbi.skiplines);
1249         return s->rfbi.skiplines;
1250
1251     case 0x58:  /* RFBI_READ */
1252     case 0x5c:  /* RFBI_STATUS */
1253         TRACEREG("RFBI_READ/STATUS: 0x%08x", s->rfbi.rxbuf);
1254         return s->rfbi.rxbuf;
1255
1256     case 0x60:  /* RFBI_CONFIG0 */
1257         TRACEREG("RFBI_CONFIG0: 0x%08x", s->rfbi.config[0]);
1258         return s->rfbi.config[0];
1259     case 0x64:  /* RFBI_ONOFF_TIME0 */
1260         TRACEREG("RFBI_ONOFF_TIME0: 0x%08x", s->rfbi.time[0]);
1261         return s->rfbi.time[0];
1262     case 0x68:  /* RFBI_CYCLE_TIME0 */
1263         TRACEREG("RFBI_CYCLE_TIME0: 0x%08x", s->rfbi.time[1]);
1264         return s->rfbi.time[1];
1265     case 0x6c:  /* RFBI_DATA_CYCLE1_0 */
1266         TRACEREG("RFBI_DATA_CYCLE1_0: 0x%08x", s->rfbi.data[0]);
1267         return s->rfbi.data[0];
1268     case 0x70:  /* RFBI_DATA_CYCLE2_0 */
1269         TRACEREG("RFBI_DATA_CYCLE2_0: 0x%08x", s->rfbi.data[1]);
1270         return s->rfbi.data[1];
1271     case 0x74:  /* RFBI_DATA_CYCLE3_0 */
1272         TRACEREG("RFBI_DATA_CYCLE3_0: 0x%08x", s->rfbi.data[2]);
1273         return s->rfbi.data[2];
1274
1275     case 0x78:  /* RFBI_CONFIG1 */
1276         TRACEREG("RFBI_CONFIG1: 0x%08x", s->rfbi.config[1]);
1277         return s->rfbi.config[1];
1278     case 0x7c:  /* RFBI_ONOFF_TIME1 */
1279         TRACEREG("RFBI_ONOFF_TIME1: 0x%08x", s->rfbi.time[2]);
1280         return s->rfbi.time[2];
1281     case 0x80:  /* RFBI_CYCLE_TIME1 */
1282         TRACEREG("RFBI_CYCLE_TIME1: 0x%08x", s->rfbi.time[3]);
1283         return s->rfbi.time[3];
1284     case 0x84:  /* RFBI_DATA_CYCLE1_1 */
1285         TRACEREG("RFBI_DATA_CYCLE1_1: 0x%08x", s->rfbi.data[3]);
1286         return s->rfbi.data[3];
1287     case 0x88:  /* RFBI_DATA_CYCLE2_1 */
1288         TRACEREG("RFBI_DATA_CYCLE2_1: 0x%08x", s->rfbi.data[4]);
1289         return s->rfbi.data[4];
1290     case 0x8c:  /* RFBI_DATA_CYCLE3_1 */
1291         TRACEREG("RFBI_DATA_CYCLE3_1: 0x%08x", s->rfbi.data[5]);
1292         return s->rfbi.data[5];
1293
1294     case 0x90:  /* RFBI_VSYNC_WIDTH */
1295         TRACEREG("RFBI_VSYNC_WIDTH: 0x%08x", s->rfbi.vsync);
1296         return s->rfbi.vsync;
1297     case 0x94:  /* RFBI_HSYNC_WIDTH */
1298         TRACEREG("RFBI_HSYNC_WIDTH: 0x%08x", s->rfbi.hsync);
1299         return s->rfbi.hsync;
1300     }
1301     OMAP_BAD_REG(addr);
1302     return 0;
1303 }
1304
1305 static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
1306                 uint32_t value)
1307 {
1308     struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1309
1310     switch (addr) {
1311     case 0x10:  /* RFBI_SYSCONFIG */
1312         TRACEREG("RFBI_SYSCONFIG = 0x%08x", value);
1313         if (value & 2)                                          /* SOFTRESET */
1314             omap_rfbi_reset(s);
1315         s->rfbi.idlemode = value & 0x19;
1316         break;
1317
1318     case 0x40:  /* RFBI_CONTROL */
1319         TRACEREG("RFBI_CONTROL = 0x%08x", value);
1320         s->rfbi.control = value & 0xf;
1321         s->rfbi.enable = value & 1;
1322         if (value & (1 << 4) &&                                 /* ITE */
1323                         !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
1324             omap_rfbi_transfer_start(s);
1325         break;
1326
1327     case 0x44:  /* RFBI_PIXELCNT */
1328         TRACEREG("RFBI_PIXELCNT = 0x%08x", value);
1329         s->rfbi.pixels = value;
1330         break;
1331
1332     case 0x48:  /* RFBI_LINE_NUMBER */
1333         TRACEREG("RFBI_LINE_NUMBER = 0x%08x", value);
1334         s->rfbi.skiplines = value & 0x7ff;
1335         break;
1336
1337     case 0x4c:  /* RFBI_CMD */
1338         TRACEREG("RFBI_CMD = 0x%08x", value);
1339         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1340             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
1341         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1342             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
1343         break;
1344     case 0x50:  /* RFBI_PARAM */
1345         TRACEREG("RFBI_PARAM = 0x%08x", value);
1346         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1347             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1348         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1349             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1350         break;
1351     case 0x54:  /* RFBI_DATA */
1352         TRACEREG("RFBI_DATA = 0x%08x", value);
1353         /* TODO: take into account the format set up in s->rfbi.config[?] and
1354          * s->rfbi.data[?], but special-case the most usual scenario so that
1355          * speed doesn't suffer.  */
1356         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
1357             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1358             s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
1359         }
1360         if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
1361             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1362             s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
1363         }
1364         if (!-- s->rfbi.pixels)
1365             omap_rfbi_transfer_stop(s);
1366         break;
1367     case 0x58:  /* RFBI_READ */
1368         TRACEREG("RFBI_READ = 0x%08x", value);
1369         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1370             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
1371         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1372             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
1373         if (!-- s->rfbi.pixels)
1374             omap_rfbi_transfer_stop(s);
1375         break;
1376
1377     case 0x5c:  /* RFBI_STATUS */
1378         TRACEREG("RFBI_STATUS = 0x%08x", value);
1379         if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1380             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
1381         else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1382             s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
1383         if (!-- s->rfbi.pixels)
1384             omap_rfbi_transfer_stop(s);
1385         break;
1386
1387     case 0x60:  /* RFBI_CONFIG0 */
1388         TRACEREG("RFBI_CONFIG0 = 0x%08x", value);
1389         s->rfbi.config[0] = value & 0x003f1fff;
1390         break;
1391
1392     case 0x64:  /* RFBI_ONOFF_TIME0 */
1393         TRACEREG("RFBI_ONOFF_TIME0 = 0x%08x", value);
1394         s->rfbi.time[0] = value & 0x3fffffff;
1395         break;
1396     case 0x68:  /* RFBI_CYCLE_TIME0 */
1397         TRACEREG("RFBI_CYCLE_TIME0 = 0x%08x", value);
1398         s->rfbi.time[1] = value & 0x0fffffff;
1399         break;
1400     case 0x6c:  /* RFBI_DATA_CYCLE1_0 */
1401         TRACEREG("RFBI_DATA_CYCLE1_0 = 0x%08x", value);
1402         s->rfbi.data[0] = value & 0x0f1f0f1f;
1403         break;
1404     case 0x70:  /* RFBI_DATA_CYCLE2_0 */
1405         TRACEREG("RFBI_DATA_CYCLE2_0 = 0x%08x", value);
1406         s->rfbi.data[1] = value & 0x0f1f0f1f;
1407         break;
1408     case 0x74:  /* RFBI_DATA_CYCLE3_0 */
1409         TRACEREG("RFBI_DATA_CYCLE3_0 = 0x%08x", value);
1410         s->rfbi.data[2] = value & 0x0f1f0f1f;
1411         break;
1412     case 0x78:  /* RFBI_CONFIG1 */
1413         TRACEREG("RFBI_CONFIG1 = 0x%08x", value);
1414         s->rfbi.config[1] = value & 0x003f1fff;
1415         break;
1416
1417     case 0x7c:  /* RFBI_ONOFF_TIME1 */
1418         TRACEREG("RFBI_ONOFF_TIME1 = 0x%08x", value);
1419         s->rfbi.time[2] = value & 0x3fffffff;
1420         break;
1421     case 0x80:  /* RFBI_CYCLE_TIME1 */
1422         TRACEREG("RFBI_CYCLE_TIME1 = 0x%08x", value);
1423         s->rfbi.time[3] = value & 0x0fffffff;
1424         break;
1425     case 0x84:  /* RFBI_DATA_CYCLE1_1 */
1426         TRACEREG("RFBI_DATA_CYCLE1_1 = 0x%08x", value);
1427         s->rfbi.data[3] = value & 0x0f1f0f1f;
1428         break;
1429     case 0x88:  /* RFBI_DATA_CYCLE2_1 */
1430         TRACEREG("RFBI_DATA_CYCLE2_1 = 0x%08x", value);
1431         s->rfbi.data[4] = value & 0x0f1f0f1f;
1432         break;
1433     case 0x8c:  /* RFBI_DATA_CYCLE3_1 */
1434         TRACEREG("RFBI_DATA_CYCLE3_1 = 0x%08x", value);
1435         s->rfbi.data[5] = value & 0x0f1f0f1f;
1436         break;
1437
1438     case 0x90:  /* RFBI_VSYNC_WIDTH */
1439         TRACEREG("RFBI_VSYNC_WIDTH = 0x%08x", value);
1440         s->rfbi.vsync = value & 0xffff;
1441         break;
1442     case 0x94:  /* RFBI_HSYNC_WIDTH */
1443         TRACEREG("RFBI_HSYNC_WIDTH = 0x%08x", value);
1444         s->rfbi.hsync = value & 0xffff;
1445         break;
1446
1447     default:
1448         OMAP_BAD_REGV(addr, value);
1449         break;
1450     }
1451 }
1452
1453 static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
1454     omap_badwidth_read32,
1455     omap_badwidth_read32,
1456     omap_rfbi_read,
1457 };
1458
1459 static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
1460     omap_badwidth_write32,
1461     omap_badwidth_write32,
1462     omap_rfbi_write,
1463 };
1464
1465 static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
1466 {
1467     switch (addr) {
1468         case 0x00:      /* REV_ID */
1469             return 0x2;
1470         case 0x04:      /* STATUS */
1471         case 0x08:      /* F_CONTROL */
1472         case 0x10:      /* VIDOUT_CTRL */
1473         case 0x14:      /* SYNC_CTRL */
1474         case 0x1c:      /* LLEN */
1475         case 0x20:      /* FLENS */
1476         case 0x24:      /* HFLTR_CTRL */
1477         case 0x28:      /* CC_CARR_WSS_CARR */
1478         case 0x2c:      /* C_PHASE */
1479         case 0x30:      /* GAIN_U */
1480         case 0x34:      /* GAIN_V */
1481         case 0x38:      /* GAIN_Y */
1482         case 0x3c:      /* BLACK_LEVEL */
1483         case 0x40:      /* BLANK_LEVEL */
1484         case 0x44:      /* X_COLOR */
1485         case 0x48:      /* M_CONTROL */
1486         case 0x4c:      /* BSTAMP_WSS_DATA */
1487         case 0x50:      /* S_CARR */
1488         case 0x54:      /* LINE21 */
1489         case 0x58:      /* LN_SEL */
1490         case 0x5c:      /* L21__WC_CTL */
1491         case 0x60:      /* HTRIGGER_VTRIGGER */
1492         case 0x64:      /* SAVID__EAVID */
1493         case 0x68:      /* FLEN__FAL */
1494         case 0x6c:      /* LAL__PHASE_RESET */
1495         case 0x70:      /* HS_INT_START_STOP_X */
1496         case 0x74:      /* HS_EXT_START_STOP_X */
1497         case 0x78:      /* VS_INT_START_X */
1498         case 0x7c:      /* VS_INT_STOP_X__VS_INT_START_Y */
1499         case 0x80:      /* VS_INT_STOP_Y__VS_INT_START_X */
1500         case 0x84:      /* VS_EXT_STOP_X__VS_EXT_START_Y */
1501         case 0x88:      /* VS_EXT_STOP_Y */
1502         case 0x90:      /* AVID_START_STOP_X */
1503         case 0x94:      /* AVID_START_STOP_Y */
1504         case 0xa0:      /* FID_INT_START_X__FID_INT_START_Y */
1505         case 0xa4:      /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1506         case 0xa8:      /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1507         case 0xb0:      /* TVDETGP_INT_START_STOP_X */
1508         case 0xb4:      /* TVDETGP_INT_START_STOP_Y */
1509         case 0xb8:      /* GEN_CTRL */
1510         case 0xc4:      /* DAC_TST__DAC_A */
1511         case 0xc8:      /* DAC_B__DAC_C */
1512             return 0;
1513             
1514         default:
1515             break;
1516     }
1517     OMAP_BAD_REG(addr);
1518     return 0;
1519 }
1520
1521 static void omap_venc_write(void *opaque, target_phys_addr_t addr,
1522                 uint32_t value)
1523 {
1524     switch (addr) {
1525         case 0x00: /* REV_ID */
1526         case 0x04: /* STATUS */
1527             /* read-only, ignore */
1528             break;
1529         case 0x08:      /* F_CONTROL */
1530         case 0x10:      /* VIDOUT_CTRL */
1531         case 0x14:      /* SYNC_CTRL */
1532         case 0x1c:      /* LLEN */
1533         case 0x20:      /* FLENS */
1534         case 0x24:      /* HFLTR_CTRL */
1535         case 0x28:      /* CC_CARR_WSS_CARR */
1536         case 0x2c:      /* C_PHASE */
1537         case 0x30:      /* GAIN_U */
1538         case 0x34:      /* GAIN_V */
1539         case 0x38:      /* GAIN_Y */
1540         case 0x3c:      /* BLACK_LEVEL */
1541         case 0x40:      /* BLANK_LEVEL */
1542         case 0x44:      /* X_COLOR */
1543         case 0x48:      /* M_CONTROL */
1544         case 0x4c:      /* BSTAMP_WSS_DATA */
1545         case 0x50:      /* S_CARR */
1546         case 0x54:      /* LINE21 */
1547         case 0x58:      /* LN_SEL */
1548         case 0x5c:      /* L21__WC_CTL */
1549         case 0x60:      /* HTRIGGER_VTRIGGER */
1550         case 0x64:      /* SAVID__EAVID */
1551         case 0x68:      /* FLEN__FAL */
1552         case 0x6c:      /* LAL__PHASE_RESET */
1553         case 0x70:      /* HS_INT_START_STOP_X */
1554         case 0x74:      /* HS_EXT_START_STOP_X */
1555         case 0x78:      /* VS_INT_START_X */
1556         case 0x7c:      /* VS_INT_STOP_X__VS_INT_START_Y */
1557         case 0x80:      /* VS_INT_STOP_Y__VS_INT_START_X */
1558         case 0x84:      /* VS_EXT_STOP_X__VS_EXT_START_Y */
1559         case 0x88:      /* VS_EXT_STOP_Y */
1560         case 0x90:      /* AVID_START_STOP_X */
1561         case 0x94:      /* AVID_START_STOP_Y */
1562         case 0xa0:      /* FID_INT_START_X__FID_INT_START_Y */
1563         case 0xa4:      /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1564         case 0xa8:      /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1565         case 0xb0:      /* TVDETGP_INT_START_STOP_X */
1566         case 0xb4:      /* TVDETGP_INT_START_STOP_Y */
1567         case 0xb8:      /* GEN_CTRL */
1568         case 0xc4:      /* DAC_TST__DAC_A */
1569         case 0xc8:      /* DAC_B__DAC_C */
1570             break;
1571             
1572         default:
1573             OMAP_BAD_REGV(addr, value);
1574             break;
1575     }
1576 }
1577
1578 static CPUReadMemoryFunc *omap_venc1_readfn[] = {
1579     omap_badwidth_read32,
1580     omap_badwidth_read32,
1581     omap_venc_read,
1582 };
1583
1584 static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
1585     omap_badwidth_write32,
1586     omap_badwidth_write32,
1587     omap_venc_write,
1588 };
1589
1590 static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
1591 {
1592     switch (addr) {
1593     case 0x0a8: /* SBIMERRLOGA */
1594     case 0x0b0: /* SBIMERRLOG */
1595     case 0x190: /* SBIMSTATE */
1596     case 0x198: /* SBTMSTATE_L */
1597     case 0x19c: /* SBTMSTATE_H */
1598     case 0x1a8: /* SBIMCONFIG_L */
1599     case 0x1ac: /* SBIMCONFIG_H */
1600     case 0x1f8: /* SBID_L */
1601     case 0x1fc: /* SBID_H */
1602         return 0;
1603
1604     default:
1605         break;
1606     }
1607     OMAP_BAD_REG(addr);
1608     return 0;
1609 }
1610
1611 static void omap_im3_write(void *opaque, target_phys_addr_t addr,
1612                 uint32_t value)
1613 {
1614     switch (addr) {
1615     case 0x0b0: /* SBIMERRLOG */
1616     case 0x190: /* SBIMSTATE */
1617     case 0x198: /* SBTMSTATE_L */
1618     case 0x19c: /* SBTMSTATE_H */
1619     case 0x1a8: /* SBIMCONFIG_L */
1620     case 0x1ac: /* SBIMCONFIG_H */
1621         break;
1622
1623     default:
1624         OMAP_BAD_REGV(addr, value);
1625         break;
1626     }
1627 }
1628
1629 static CPUReadMemoryFunc *omap_im3_readfn[] = {
1630     omap_badwidth_read32,
1631     omap_badwidth_read32,
1632     omap_im3_read,
1633 };
1634
1635 static CPUWriteMemoryFunc *omap_im3_writefn[] = {
1636     omap_badwidth_write32,
1637     omap_badwidth_write32,
1638     omap_im3_write,
1639 };
1640
1641 static uint32_t omap_dsi_read(void *opaque, target_phys_addr_t addr)
1642 {
1643     switch (addr) {
1644         case 0x000: /* DSI_REVISION */
1645             return 0x10;
1646         case 0x014: /* DSI_SYSSTATUS */
1647             return 1; /* RESET_DONE */
1648         case 0x010: /* DSI_SYSCONFIG */
1649         case 0x018: /* DSI_IRQSTATUS */
1650         case 0x01c: /* DSI_IRQENABLE */
1651         case 0x040: /* DSI_CTRL */
1652         case 0x048: /* DSI_COMPLEXIO_CFG_1 */
1653         case 0x04c: /* DSI_COMPLEXIO_IRQ_STATUS */
1654         case 0x050: /* DSI_COMPLEXIO_IRQ_ENABLE */
1655         case 0x054: /* DSI_CLK_CTRL */
1656         case 0x058: /* DSI_TIMING1 */
1657         case 0x05c: /* DSI_TIMING2 */
1658         case 0x060: /* DSI_VM_TIMING1 */
1659         case 0x064: /* DSI_VM_TIMING2 */
1660         case 0x068: /* DSI_VM_TIMING3 */
1661         case 0x06c: /* DSI_CLK_TIMING */
1662         case 0x070: /* DSI_TX_FIFO_VC_SIZE */
1663         case 0x074: /* DSI_RX_FIFO_VC_SIZE */
1664         case 0x078: /* DSI_COMPLEXIO_CFG_2 */
1665         case 0x07c: /* DSI_RX_FIFO_VC_FULLNESS */
1666         case 0x080: /* DSI_VM_TIMING4 */
1667         case 0x084: /* DSI_TX_FIFO_VC_EMPTINESS */
1668         case 0x088: /* DSI_VM_TIMING5 */
1669         case 0x08c: /* DSI_VM_TIMING6 */
1670         case 0x090: /* DSI_VM_TIMING7 */
1671         case 0x094: /* DSI_STOPCLK_TIMING */
1672         case 0x100: /* DSI_VC0_CTRL */
1673         case 0x104: /* DSI_VC0_TE */
1674         case 0x108: /* DSI_VC0_LONG_PACKET_HEADER */
1675         case 0x10c: /* DSI_VC0_LONG_PACKET_PAYLOAD */
1676         case 0x110: /* DSI_VC0_SHORT_PACKET_HEADER */
1677         case 0x118: /* DSI_VC0_IRQSTATUS */
1678         case 0x11c: /* DSI_VC0_IRQENABLE */
1679         case 0x120: /* DSI_VC1_CTRL */
1680         case 0x124: /* DSI_VC1_TE */
1681         case 0x128: /* DSI_VC1_LONG_PACKET_HEADER */
1682         case 0x12c: /* DSI_VC1_LONG_PACKET_PAYLOAD */
1683         case 0x130: /* DSI_VC1_SHORT_PACKET_HEADER */
1684         case 0x138: /* DSI_VC1_IRQSTATUS */
1685         case 0x13c: /* DSI_VC1_IRQENABLE */
1686         case 0x140: /* DSI_VC2_CTRL */
1687         case 0x144: /* DSI_VC2_TE */
1688         case 0x148: /* DSI_VC2_LONG_PACKET_HEADER */
1689         case 0x14c: /* DSI_VC2_LONG_PACKET_PAYLOAD */
1690         case 0x150: /* DSI_VC2_SHORT_PACKET_HEADER */
1691         case 0x158: /* DSI_VC2_IRQSTATUS */
1692         case 0x15c: /* DSI_VC2_IRQENABLE */
1693         case 0x160: /* DSI_VC3_CTRL */
1694         case 0x164: /* DSI_VC3_TE */
1695         case 0x168: /* DSI_VC3_LONG_PACKET_HEADER */
1696         case 0x16c: /* DSI_VC3_LONG_PACKET_PAYLOAD */
1697         case 0x170: /* DSI_VC3_SHORT_PACKET_HEADER */
1698         case 0x178: /* DSI_VC3_IRQSTATUS */
1699         case 0x17c: /* DSI_VC3_IRQENABLE */
1700         
1701         case 0x200: /* DSI_PHY_CFG0 */
1702         case 0x204: /* DSI_PHY_CFG1 */
1703         case 0x208: /* DSI_PHY_CFG2 */
1704         case 0x214: /* DSI_PHY_CFG5 */
1705             
1706         case 0x300: /* DSI_PLL_CONTROL */
1707         case 0x304: /* DSI_PLL_STATUS */
1708         case 0x308: /* DSI_PLL_GO */
1709         case 0x30c: /* DSI_PLL_CONFIGURATION1 */
1710         case 0x310: /* DSI_PLL_CONFIGURATION2 */
1711             
1712             fprintf(stderr,
1713                     "%s: DSI register " OMAP_FMT_plx " not implemented!\n",
1714                     __FUNCTION__, addr);
1715             return 0;
1716             
1717         default:
1718             break;
1719     }
1720     OMAP_BAD_REG(addr);
1721     return 0;
1722 }
1723
1724 static void omap_dsi_write(void *opaque, target_phys_addr_t addr,
1725                            uint32_t value)
1726 {
1727     switch (addr) {
1728         case 0x000: /* DSI_REVISION */
1729         case 0x014: /* DSI_SYSSTATUS */
1730         case 0x07c: /* DSI_RX_FIFO_VC_FULLNESS */
1731         case 0x084: /* DSI_RX_FIFO_VC_EMPTINESS */
1732         case 0x214: /* DSI_PHY_CFG5 */
1733         case 0x304: /* DSI_PLL_STATUS */
1734             /* read-only, ignore */
1735             break;
1736         case 0x010: /* DSI_SYSCONFIG */
1737         case 0x018: /* DSI_IRQSTATUS */
1738         case 0x01c: /* DSI_IRQENABLE */
1739         case 0x040: /* DSI_CTRL */
1740         case 0x048: /* DSI_COMPLEXIO_CFG_1 */
1741         case 0x04c: /* DSI_COMPLEXIO_IRQ_STATUS */
1742         case 0x050: /* DSI_COMPLEXIO_IRQ_ENABLE */
1743         case 0x054: /* DSI_CLK_CTRL */
1744         case 0x058: /* DSI_TIMING1 */
1745         case 0x05c: /* DSI_TIMING2 */
1746         case 0x060: /* DSI_VM_TIMING1 */
1747         case 0x064: /* DSI_VM_TIMING2 */
1748         case 0x068: /* DSI_VM_TIMING3 */
1749         case 0x06c: /* DSI_CLK_TIMING */
1750         case 0x070: /* DSI_TX_FIFO_VC_SIZE */
1751         case 0x074: /* DSI_RX_FIFO_VC_SIZE */
1752         case 0x078: /* DSI_COMPLEXIO_CFG_2 */
1753         case 0x080: /* DSI_VM_TIMING4 */
1754         case 0x088: /* DSI_VM_TIMING5 */
1755         case 0x08c: /* DSI_VM_TIMING6 */
1756         case 0x090: /* DSI_VM_TIMING7 */
1757         case 0x094: /* DSI_STOPCLK_TIMING */
1758         case 0x100: /* DSI_VC0_CTRL */
1759         case 0x104: /* DSI_VC0_TE */
1760         case 0x108: /* DSI_VC0_LONG_PACKET_HEADER */
1761         case 0x10c: /* DSI_VC0_LONG_PACKET_PAYLOAD */
1762         case 0x110: /* DSI_VC0_SHORT_PACKET_HEADER */
1763         case 0x118: /* DSI_VC0_IRQSTATUS */
1764         case 0x11c: /* DSI_VC0_IRQENABLE */
1765         case 0x120: /* DSI_VC1_CTRL */
1766         case 0x124: /* DSI_VC1_TE */
1767         case 0x128: /* DSI_VC1_LONG_PACKET_HEADER */
1768         case 0x12c: /* DSI_VC1_LONG_PACKET_PAYLOAD */
1769         case 0x130: /* DSI_VC1_SHORT_PACKET_HEADER */
1770         case 0x138: /* DSI_VC1_IRQSTATUS */
1771         case 0x13c: /* DSI_VC1_IRQENABLE */
1772         case 0x140: /* DSI_VC2_CTRL */
1773         case 0x144: /* DSI_VC2_TE */
1774         case 0x148: /* DSI_VC2_LONG_PACKET_HEADER */
1775         case 0x14c: /* DSI_VC2_LONG_PACKET_PAYLOAD */
1776         case 0x150: /* DSI_VC2_SHORT_PACKET_HEADER */
1777         case 0x158: /* DSI_VC2_IRQSTATUS */
1778         case 0x15c: /* DSI_VC2_IRQENABLE */
1779         case 0x160: /* DSI_VC3_CTRL */
1780         case 0x164: /* DSI_VC3_TE */
1781         case 0x168: /* DSI_VC3_LONG_PACKET_HEADER */
1782         case 0x16c: /* DSI_VC3_LONG_PACKET_PAYLOAD */
1783         case 0x170: /* DSI_VC3_SHORT_PACKET_HEADER */
1784         case 0x178: /* DSI_VC3_IRQSTATUS */
1785         case 0x17c: /* DSI_VC3_IRQENABLE */
1786             
1787         case 0x200: /* DSI_PHY_CFG0 */
1788         case 0x204: /* DSI_PHY_CFG1 */
1789         case 0x208: /* DSI_PHY_CFG2 */
1790             
1791         case 0x300: /* DSI_PLL_CONTROL */
1792         case 0x308: /* DSI_PLL_GO */
1793         case 0x30c: /* DSI_PLL_CONFIGURATION1 */
1794         case 0x310: /* DSI_PLL_CONFIGURATION2 */
1795             
1796             fprintf(stderr,
1797                     "%s: DSI register " OMAP_FMT_plx " not implemented!\n",
1798                     __FUNCTION__, addr);
1799             break;
1800             
1801         default:
1802             OMAP_BAD_REGV(addr, value);
1803             break;
1804     }
1805 }
1806
1807 static CPUReadMemoryFunc *omap_dsi_readfn[] = {
1808     omap_badwidth_read32,
1809     omap_badwidth_read32,
1810     omap_dsi_read,
1811 };
1812
1813 static CPUWriteMemoryFunc *omap_dsi_writefn[] = {
1814     omap_badwidth_write32,
1815     omap_badwidth_write32,
1816     omap_dsi_write,
1817 };
1818
1819 struct omap_dss_s *omap_dss_init(struct omap_mpu_state_s *mpu,
1820                                  struct omap_target_agent_s *ta,
1821                                  qemu_irq irq, qemu_irq drq,
1822                                  omap_clk fck1, omap_clk fck2, omap_clk ck54m,
1823                                  omap_clk ick1, omap_clk ick2)
1824 {
1825     int iomemtype[5];
1826     int region_base = 0;
1827     struct omap_dss_s *s = (struct omap_dss_s *)
1828             qemu_mallocz(sizeof(struct omap_dss_s));
1829
1830     s->irq = irq;
1831     s->drq = drq;
1832
1833     iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn,
1834                                          omap_diss1_writefn, s);
1835     iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn,
1836                                          omap_disc1_writefn, s);
1837     iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn,
1838                                          omap_rfbi1_writefn, s);
1839     iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn,
1840                                          omap_venc1_writefn, s);
1841
1842     if (cpu_class_omap3(mpu)) {
1843         s->dispc.rev = 0x30;
1844         
1845         iomemtype[4] = l4_register_io_memory(0, omap_dsi_readfn,
1846                                              omap_dsi_writefn, s);
1847         omap_l4_attach(ta, 0, iomemtype[4]);
1848         region_base = 1;
1849     } else {
1850         s->dispc.rev = 0x20;
1851         
1852         iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
1853                                               omap_im3_writefn, s);
1854         cpu_register_physical_memory(0x68000800, 0x1000, iomemtype[4]);
1855     }
1856     
1857     omap_l4_attach(ta, region_base+0, iomemtype[0]); /* DISS */
1858     omap_l4_attach(ta, region_base+1, iomemtype[1]); /* DISC */
1859     omap_l4_attach(ta, region_base+2, iomemtype[2]); /* RFBI */
1860     omap_l4_attach(ta, region_base+3, iomemtype[3]); /* VENC */
1861
1862     omap_dss_reset(s);
1863
1864 #if 0
1865     s->state = graphic_console_init(omap_update_display,
1866                                     omap_invalidate_display, omap_screen_dump, s);
1867 #endif
1868
1869     register_savevm("omap_dss", -1, 0,
1870                     omap_dss_save_state, omap_dss_load_state, s);
1871     
1872     return s;
1873 }
1874
1875 void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
1876 {
1877     if (cs < 0 || cs > 1)
1878         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1879     s->rfbi.chip[cs] = chip;
1880 }
1881
1882 void omap3_lcd_panel_attach(struct omap_dss_s *dss,
1883                             int cs,
1884                             struct omap3_lcd_panel_s *lcd_panel)
1885 {
1886     if (cs < 0 || cs > 1)
1887         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1888     dss->omap_lcd_panel[cs] = lcd_panel;
1889         lcd_panel->dss = dss;
1890 }
1891
1892 /*omap3 lcd panel stuff*/
1893
1894 /* Bytes(!) per pixel */
1895 static const int omap3_lcd_panel_bpp[0x10] = {
1896     0,  /* 0x0: BITMAP1 (CLUT) */
1897     0,  /* 0x1: BITMAP2 (CLUT) */
1898     0,  /* 0x2: BITMAP4 (CLUT) */
1899     0,  /* 0x3: BITMAP8 (CLUT) */
1900     2,  /* 0x4: RGB12 (unpacked 16-bit container)*/
1901     2,  /* 0x5: ARGB16 */
1902     2,  /* 0x6: RGB16 */
1903     0,  /* 0x7: reserved */
1904     4,  /* 0x8: RGB24 (unpacked in 32-bit container) */
1905     3,  /* 0x9: RGB24 (packed in 24-bit container) */
1906     2,  /* 0xa: YUV2 422 */
1907     2,  /* 0xb: UYVY 422 */
1908     4,  /* 0xc: ARGB32 */
1909     4,  /* 0xd: RGBA32 */
1910     4,  /* 0xe: RGBx32 (24-bit RGB aligned on MSB of the 32-bit container) */
1911     0,  /* 0xf: reserved */
1912 };
1913
1914 static inline void omap3_lcd_panel_invalidate_display(void *opaque) 
1915 {
1916     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1917     s->invalidate = 1;
1918 }
1919
1920 static void omap3_lcd_panel_update_display(void *opaque)
1921 {
1922     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1923     struct omap_dss_s *dss = s->dss;
1924     const uint32_t lcd_width = dss->lcd.nx;
1925     const uint32_t lcd_height = dss->lcd.ny;
1926     uint32_t graphic_width, graphic_height;
1927     uint32_t start_x, start_y;
1928     const uint32_t lcd_Bpp = omap3_lcd_panel_bpp[dss->dispc.l[0].gfx_format];
1929     uint32_t dss_Bpp;
1930     uint32_t linesize, y;
1931     uint32_t copy_width, copy_height;
1932     uint8_t *src, *dest;
1933
1934     if (!dss->lcd.enable
1935         || dss->dispc.l[0].gfx_channel /* 24bit digital out */
1936         || ((dss->dispc.control & (1 << 11))) /* RFBI */
1937         || !lcd_Bpp)
1938         return;
1939     
1940     /* check for setup changes since last visit only if flagged */
1941     if (dss->dispc.invalidate) {
1942         dss->dispc.invalidate = 0;
1943         if (!(dss->dispc.l[0].rotation_flag)) {   /* rotation*/
1944             s->line_fn = s->line_fn_tab[0][dss->dispc.l[0].gfx_format];
1945         } else {
1946             fprintf(stderr, "%s: rotation is not supported \n", __FUNCTION__);
1947             exit(1);
1948         }
1949         if (!s->line_fn) {
1950             fprintf(stderr,
1951                     "%s: line_fn is NULL - unsupported gfx_format (%d)\n",
1952                     __FUNCTION__, dss->dispc.l[0].gfx_format);
1953             exit(1);
1954         }
1955         if (lcd_width != ds_get_width(s->state) 
1956             || lcd_height != ds_get_height(s->state)) {
1957             qemu_console_resize(s->state, lcd_width, lcd_height);
1958             s->invalidate = 1;
1959         }
1960     }
1961     
1962     /* Resolution */
1963     graphic_width = dss->dispc.l[0].nx;
1964     graphic_height = dss->dispc.l[0].ny;
1965     start_x = dss->dispc.l[0].posx;
1966     start_y = dss->dispc.l[0].posy;
1967
1968     /*use the rfbi function*/
1969     src = (uint8_t *)omap_rfbi_get_buffer(dss);
1970     dest = ds_get_data(s->state);
1971     linesize = ds_get_linesize(s->state);
1972
1973     dss_Bpp = linesize / ds_get_width(s->state);
1974
1975     dest += linesize * start_y;
1976     dest += start_x * dss_Bpp;
1977
1978     if ((start_x + graphic_width) > lcd_width)
1979         copy_width = lcd_width - start_x;
1980     else
1981         copy_width = graphic_width;
1982     copy_height = lcd_height>graphic_height ? graphic_height:lcd_height;
1983
1984     for (y = start_y; y < copy_height; y++) {
1985         s->line_fn(dest, src, copy_width * lcd_Bpp);
1986         src += graphic_width * lcd_Bpp;
1987         dest += linesize;
1988     }
1989
1990     dpy_update(s->state, start_x, start_y, graphic_width, graphic_height);
1991     s->invalidate = 0;
1992     
1993     dss->dispc.irqst |= 1; /* FRAMEDONE */
1994     omap_dss_interrupt_update(dss);
1995 }
1996
1997 /*omap lcd stuff*/
1998 #define DEPTH 8
1999 #include "omap3_lcd_panel_template.h"
2000 #define DEPTH 15
2001 #include "omap3_lcd_panel_template.h"
2002 #define DEPTH 16
2003 #include "omap3_lcd_panel_template.h"
2004 #define DEPTH 24
2005 #include "omap3_lcd_panel_template.h"
2006 #define DEPTH 32
2007 #include "omap3_lcd_panel_template.h"
2008
2009 void *omap3_lcd_panel_init()
2010 {
2011     struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *) qemu_mallocz(sizeof(*s));
2012
2013     s->state = graphic_console_init(omap3_lcd_panel_update_display,
2014                                     omap3_lcd_panel_invalidate_display,
2015                                     NULL, NULL, s);
2016
2017     switch (ds_get_bits_per_pixel(s->state)) {
2018     case 0:
2019         s->line_fn_tab[0] = s->line_fn_tab[1] =
2020             qemu_mallocz(sizeof(omap3_lcd_panel_fn_t) * 0x10);
2021         break;
2022     case 8:
2023         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_8;
2024         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_8;
2025         break;
2026     case 15:
2027         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_15;
2028         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_15;
2029         break;
2030     case 16:
2031         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_16;
2032         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_16;
2033         break;
2034     case 24:
2035         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_24;
2036         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_24;
2037         break;
2038     case 32:
2039         s->line_fn_tab[0] =  omap3_lcd_panel_draw_fn_32;
2040         s->line_fn_tab[1] =  omap3_lcd_panel_draw_fn_r_32;
2041         break;
2042     default:
2043         fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
2044         exit(1);
2045     }
2046
2047     return s;
2048 }