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