Statistics
| Branch: | Revision:

root / hw / omap_dss.c @ 084a197a

History | View | Annotate | Download (32.1 kB)

1
/*
2
 * OMAP2 Display Subsystem.
3
 *
4
 * Copyright (C) 2008 Nokia Corporation
5
 * Written by Andrzej Zaborowski <andrew@openedhand.com>
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License as
9
 * published by the Free Software Foundation; either version 2 or
10
 * (at your option) version 3 of the License.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20
 * MA 02111-1307 USA
21
 */
22
#include "hw.h"
23
#include "console.h"
24
#include "omap.h"
25

    
26
struct omap_dss_s {
27
    target_phys_addr_t diss_base;
28
    target_phys_addr_t disc_base;
29
    target_phys_addr_t rfbi_base;
30
    target_phys_addr_t venc_base;
31
    target_phys_addr_t im3_base;
32
    qemu_irq irq;
33
    qemu_irq drq;
34
    DisplayState *state;
35

    
36
    int autoidle;
37
    int control;
38
    int enable;
39

    
40
    struct omap_dss_panel_s {
41
        int enable;
42
        int nx;
43
        int ny;
44

    
45
        int x;
46
        int y;
47
    } dig, lcd;
48

    
49
    struct {
50
        uint32_t idlemode;
51
        uint32_t irqst;
52
        uint32_t irqen;
53
        uint32_t control;
54
        uint32_t config;
55
        uint32_t capable;
56
        uint32_t timing[4];
57
        int line;
58
        uint32_t bg[2];
59
        uint32_t trans[2];
60

    
61
        struct omap_dss_plane_s {
62
            int enable;
63
            int bpp;
64
            int posx;
65
            int posy;
66
            int nx;
67
            int ny;
68

    
69
            target_phys_addr_t addr[3];
70

    
71
            uint32_t attr;
72
            uint32_t tresh;
73
            int rowinc;
74
            int colinc;
75
            int wininc;
76
        } l[3];
77

    
78
        int invalidate;
79
        uint16_t palette[256];
80
    } dispc;
81

    
82
    struct {
83
        int idlemode;
84
        uint32_t control;
85
        int enable;
86
        int pixels;
87
        int busy;
88
        int skiplines;
89
        uint16_t rxbuf;
90
        uint32_t config[2];
91
        uint32_t time[4];
92
        uint32_t data[6];
93
        uint16_t vsync;
94
        uint16_t hsync;
95
        struct rfbi_chip_s *chip[2];
96
    } rfbi;
97
};
98

    
99
static void omap_dispc_interrupt_update(struct omap_dss_s *s)
100
{
101
    qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen);
102
}
103

    
104
static void omap_rfbi_reset(struct omap_dss_s *s)
105
{
106
    s->rfbi.idlemode = 0;
107
    s->rfbi.control = 2;
108
    s->rfbi.enable = 0;
109
    s->rfbi.pixels = 0;
110
    s->rfbi.skiplines = 0;
111
    s->rfbi.busy = 0;
112
    s->rfbi.config[0] = 0x00310000;
113
    s->rfbi.config[1] = 0x00310000;
114
    s->rfbi.time[0] = 0;
115
    s->rfbi.time[1] = 0;
116
    s->rfbi.time[2] = 0;
117
    s->rfbi.time[3] = 0;
118
    s->rfbi.data[0] = 0;
119
    s->rfbi.data[1] = 0;
120
    s->rfbi.data[2] = 0;
121
    s->rfbi.data[3] = 0;
122
    s->rfbi.data[4] = 0;
123
    s->rfbi.data[5] = 0;
124
    s->rfbi.vsync = 0;
125
    s->rfbi.hsync = 0;
126
}
127

    
128
void omap_dss_reset(struct omap_dss_s *s)
129
{
130
    s->autoidle = 0;
131
    s->control = 0;
132
    s->enable = 0;
133

    
134
    s->dig.enable = 0;
135
    s->dig.nx = 1;
136
    s->dig.ny = 1;
137

    
138
    s->lcd.enable = 0;
139
    s->lcd.nx = 1;
140
    s->lcd.ny = 1;
141

    
142
    s->dispc.idlemode = 0;
143
    s->dispc.irqst = 0;
144
    s->dispc.irqen = 0;
145
    s->dispc.control = 0;
146
    s->dispc.config = 0;
147
    s->dispc.capable = 0x161;
148
    s->dispc.timing[0] = 0;
149
    s->dispc.timing[1] = 0;
150
    s->dispc.timing[2] = 0;
151
    s->dispc.timing[3] = 0;
152
    s->dispc.line = 0;
153
    s->dispc.bg[0] = 0;
154
    s->dispc.bg[1] = 0;
155
    s->dispc.trans[0] = 0;
156
    s->dispc.trans[1] = 0;
157

    
158
    s->dispc.l[0].enable = 0;
159
    s->dispc.l[0].bpp = 0;
160
    s->dispc.l[0].addr[0] = 0;
161
    s->dispc.l[0].addr[1] = 0;
162
    s->dispc.l[0].addr[2] = 0;
163
    s->dispc.l[0].posx = 0;
164
    s->dispc.l[0].posy = 0;
165
    s->dispc.l[0].nx = 1;
166
    s->dispc.l[0].ny = 1;
167
    s->dispc.l[0].attr = 0;
168
    s->dispc.l[0].tresh = 0;
169
    s->dispc.l[0].rowinc = 1;
170
    s->dispc.l[0].colinc = 1;
171
    s->dispc.l[0].wininc = 0;
172

    
173
    omap_rfbi_reset(s);
174
    omap_dispc_interrupt_update(s);
175
}
176

    
177
static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
178
{
179
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
180
    int offset = addr - s->diss_base;
181

    
182
    switch (offset) {
183
    case 0x00:        /* DSS_REVISIONNUMBER */
184
        return 0x20;
185

    
186
    case 0x10:        /* DSS_SYSCONFIG */
187
        return s->autoidle;
188

    
189
    case 0x14:        /* DSS_SYSSTATUS */
190
        return 1;                                                /* RESETDONE */
191

    
192
    case 0x40:        /* DSS_CONTROL */
193
        return s->control;
194

    
195
    case 0x50:        /* DSS_PSA_LCD_REG_1 */
196
    case 0x54:        /* DSS_PSA_LCD_REG_2 */
197
    case 0x58:        /* DSS_PSA_VIDEO_REG */
198
        /* TODO: fake some values when appropriate s->control bits are set */
199
        return 0;
200

    
201
    case 0x5c:        /* DSS_STATUS */
202
        return 1 + (s->control & 1);
203

    
204
    default:
205
        break;
206
    }
207
    OMAP_BAD_REG(addr);
208
    return 0;
209
}
210

    
211
static void omap_diss_write(void *opaque, target_phys_addr_t addr,
212
                uint32_t value)
213
{
214
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
215
    int offset = addr - s->diss_base;
216

    
217
    switch (offset) {
218
    case 0x00:        /* DSS_REVISIONNUMBER */
219
    case 0x14:        /* DSS_SYSSTATUS */
220
    case 0x50:        /* DSS_PSA_LCD_REG_1 */
221
    case 0x54:        /* DSS_PSA_LCD_REG_2 */
222
    case 0x58:        /* DSS_PSA_VIDEO_REG */
223
    case 0x5c:        /* DSS_STATUS */
224
        OMAP_RO_REG(addr);
225
        break;
226

    
227
    case 0x10:        /* DSS_SYSCONFIG */
228
        if (value & 2)                                                /* SOFTRESET */
229
            omap_dss_reset(s);
230
        s->autoidle = value & 1;
231
        break;
232

    
233
    case 0x40:        /* DSS_CONTROL */
234
        s->control = value & 0x3dd;
235
        break;
236

    
237
    default:
238
        OMAP_BAD_REG(addr);
239
    }
240
}
241

    
242
static CPUReadMemoryFunc *omap_diss1_readfn[] = {
243
    omap_badwidth_read32,
244
    omap_badwidth_read32,
245
    omap_diss_read,
246
};
247

    
248
static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
249
    omap_badwidth_write32,
250
    omap_badwidth_write32,
251
    omap_diss_write,
252
};
253

    
254
static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
255
{
256
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
257
    int offset = addr - s->disc_base;
258

    
259
    switch (offset) {
260
    case 0x000:        /* DISPC_REVISION */
261
        return 0x20;
262

    
263
    case 0x010:        /* DISPC_SYSCONFIG */
264
        return s->dispc.idlemode;
265

    
266
    case 0x014:        /* DISPC_SYSSTATUS */
267
        return 1;                                                /* RESETDONE */
268

    
269
    case 0x018:        /* DISPC_IRQSTATUS */
270
        return s->dispc.irqst;
271

    
272
    case 0x01c:        /* DISPC_IRQENABLE */
273
        return s->dispc.irqen;
274

    
275
    case 0x040:        /* DISPC_CONTROL */
276
        return s->dispc.control;
277

    
278
    case 0x044:        /* DISPC_CONFIG */
279
        return s->dispc.config;
280

    
281
    case 0x048:        /* DISPC_CAPABLE */
282
        return s->dispc.capable;
283

    
284
    case 0x04c:        /* DISPC_DEFAULT_COLOR0 */
285
        return s->dispc.bg[0];
286
    case 0x050:        /* DISPC_DEFAULT_COLOR1 */
287
        return s->dispc.bg[1];
288
    case 0x054:        /* DISPC_TRANS_COLOR0 */
289
        return s->dispc.trans[0];
290
    case 0x058:        /* DISPC_TRANS_COLOR1 */
291
        return s->dispc.trans[1];
292

    
293
    case 0x05c:        /* DISPC_LINE_STATUS */
294
        return 0x7ff;
295
    case 0x060:        /* DISPC_LINE_NUMBER */
296
        return s->dispc.line;
297

    
298
    case 0x064:        /* DISPC_TIMING_H */
299
        return s->dispc.timing[0];
300
    case 0x068:        /* DISPC_TIMING_V */
301
        return s->dispc.timing[1];
302
    case 0x06c:        /* DISPC_POL_FREQ */
303
        return s->dispc.timing[2];
304
    case 0x070:        /* DISPC_DIVISOR */
305
        return s->dispc.timing[3];
306

    
307
    case 0x078:        /* DISPC_SIZE_DIG */
308
        return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
309
    case 0x07c:        /* DISPC_SIZE_LCD */
310
        return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
311

    
312
    case 0x080:        /* DISPC_GFX_BA0 */
313
        return s->dispc.l[0].addr[0];
314
    case 0x084:        /* DISPC_GFX_BA1 */
315
        return s->dispc.l[0].addr[1];
316
    case 0x088:        /* DISPC_GFX_POSITION */
317
        return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx;
318
    case 0x08c:        /* DISPC_GFX_SIZE */
319
        return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1);
320
    case 0x0a0:        /* DISPC_GFX_ATTRIBUTES */
321
        return s->dispc.l[0].attr;
322
    case 0x0a4:        /* DISPC_GFX_FIFO_TRESHOLD */
323
        return s->dispc.l[0].tresh;
324
    case 0x0a8:        /* DISPC_GFX_FIFO_SIZE_STATUS */
325
        return 256;
326
    case 0x0ac:        /* DISPC_GFX_ROW_INC */
327
        return s->dispc.l[0].rowinc;
328
    case 0x0b0:        /* DISPC_GFX_PIXEL_INC */
329
        return s->dispc.l[0].colinc;
330
    case 0x0b4:        /* DISPC_GFX_WINDOW_SKIP */
331
        return s->dispc.l[0].wininc;
332
    case 0x0b8:        /* DISPC_GFX_TABLE_BA */
333
        return s->dispc.l[0].addr[2];
334

    
335
    case 0x0bc:        /* DISPC_VID1_BA0 */
336
    case 0x0c0:        /* DISPC_VID1_BA1 */
337
    case 0x0c4:        /* DISPC_VID1_POSITION */
338
    case 0x0c8:        /* DISPC_VID1_SIZE */
339
    case 0x0cc:        /* DISPC_VID1_ATTRIBUTES */
340
    case 0x0d0:        /* DISPC_VID1_FIFO_TRESHOLD */
341
    case 0x0d4:        /* DISPC_VID1_FIFO_SIZE_STATUS */
342
    case 0x0d8:        /* DISPC_VID1_ROW_INC */
343
    case 0x0dc:        /* DISPC_VID1_PIXEL_INC */
344
    case 0x0e0:        /* DISPC_VID1_FIR */
345
    case 0x0e4:        /* DISPC_VID1_PICTURE_SIZE */
346
    case 0x0e8:        /* DISPC_VID1_ACCU0 */
347
    case 0x0ec:        /* DISPC_VID1_ACCU1 */
348
    case 0x0f0 ... 0x140:        /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
349
    case 0x14c:        /* DISPC_VID2_BA0 */
350
    case 0x150:        /* DISPC_VID2_BA1 */
351
    case 0x154:        /* DISPC_VID2_POSITION */
352
    case 0x158:        /* DISPC_VID2_SIZE */
353
    case 0x15c:        /* DISPC_VID2_ATTRIBUTES */
354
    case 0x160:        /* DISPC_VID2_FIFO_TRESHOLD */
355
    case 0x164:        /* DISPC_VID2_FIFO_SIZE_STATUS */
356
    case 0x168:        /* DISPC_VID2_ROW_INC */
357
    case 0x16c:        /* DISPC_VID2_PIXEL_INC */
358
    case 0x170:        /* DISPC_VID2_FIR */
359
    case 0x174:        /* DISPC_VID2_PICTURE_SIZE */
360
    case 0x178:        /* DISPC_VID2_ACCU0 */
361
    case 0x17c:        /* DISPC_VID2_ACCU1 */
362
    case 0x180 ... 0x1d0:        /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
363
    case 0x1d4:        /* DISPC_DATA_CYCLE1 */
364
    case 0x1d8:        /* DISPC_DATA_CYCLE2 */
365
    case 0x1dc:        /* DISPC_DATA_CYCLE3 */
366
        return 0;
367

    
368
    default:
369
        break;
370
    }
371
    OMAP_BAD_REG(addr);
372
    return 0;
373
}
374

    
375
static void omap_disc_write(void *opaque, target_phys_addr_t addr,
376
                uint32_t value)
377
{
378
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
379
    int offset = addr - s->disc_base;
380

    
381
    switch (offset) {
382
    case 0x010:        /* DISPC_SYSCONFIG */
383
        if (value & 2)                                                /* SOFTRESET */
384
            omap_dss_reset(s);
385
        s->dispc.idlemode = value & 0x301b;
386
        break;
387

    
388
    case 0x018:        /* DISPC_IRQSTATUS */
389
        s->dispc.irqst &= ~value;
390
        omap_dispc_interrupt_update(s);
391
        break;
392

    
393
    case 0x01c:        /* DISPC_IRQENABLE */
394
        s->dispc.irqen = value & 0xffff;
395
        omap_dispc_interrupt_update(s);
396
        break;
397

    
398
    case 0x040:        /* DISPC_CONTROL */
399
        s->dispc.control = value & 0x07ff9fff;
400
        s->dig.enable = (value >> 1) & 1;
401
        s->lcd.enable = (value >> 0) & 1;
402
        if (value & (1 << 12))                        /* OVERLAY_OPTIMIZATION */
403
            if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
404
                 fprintf(stderr, "%s: Overlay Optimization when no overlay "
405
                                 "region effectively exists leads to "
406
                                 "unpredictable behaviour!\n", __FUNCTION__);
407
        if (value & (1 << 6)) {                                /* GODIGITAL */
408
            /* XXX: Shadowed fields are:
409
             * s->dispc.config
410
             * s->dispc.capable
411
             * s->dispc.bg[0]
412
             * s->dispc.bg[1]
413
             * s->dispc.trans[0]
414
             * s->dispc.trans[1]
415
             * s->dispc.line
416
             * s->dispc.timing[0]
417
             * s->dispc.timing[1]
418
             * s->dispc.timing[2]
419
             * s->dispc.timing[3]
420
             * s->lcd.nx
421
             * s->lcd.ny
422
             * s->dig.nx
423
             * s->dig.ny
424
             * s->dispc.l[0].addr[0]
425
             * s->dispc.l[0].addr[1]
426
             * s->dispc.l[0].addr[2]
427
             * s->dispc.l[0].posx
428
             * s->dispc.l[0].posy
429
             * s->dispc.l[0].nx
430
             * s->dispc.l[0].ny
431
             * s->dispc.l[0].tresh
432
             * s->dispc.l[0].rowinc
433
             * s->dispc.l[0].colinc
434
             * s->dispc.l[0].wininc
435
             * All they need to be loaded here from their shadow registers.
436
             */
437
        }
438
        if (value & (1 << 5)) {                                /* GOLCD */
439
             /* XXX: Likewise for LCD here.  */
440
        }
441
        s->dispc.invalidate = 1;
442
        break;
443

    
444
    case 0x044:        /* DISPC_CONFIG */
445
        s->dispc.config = value & 0x3fff;
446
        /* XXX:
447
         * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
448
         * bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
449
         */
450
        s->dispc.invalidate = 1;
451
        break;
452

    
453
    case 0x048:        /* DISPC_CAPABLE */
454
        s->dispc.capable = value & 0x3ff;
455
        break;
456

    
457
    case 0x04c:        /* DISPC_DEFAULT_COLOR0 */
458
        s->dispc.bg[0] = value & 0xffffff;
459
        s->dispc.invalidate = 1;
460
        break;
461
    case 0x050:        /* DISPC_DEFAULT_COLOR1 */
462
        s->dispc.bg[1] = value & 0xffffff;
463
        s->dispc.invalidate = 1;
464
        break;
465
    case 0x054:        /* DISPC_TRANS_COLOR0 */
466
        s->dispc.trans[0] = value & 0xffffff;
467
        s->dispc.invalidate = 1;
468
        break;
469
    case 0x058:        /* DISPC_TRANS_COLOR1 */
470
        s->dispc.trans[1] = value & 0xffffff;
471
        s->dispc.invalidate = 1;
472
        break;
473

    
474
    case 0x060:        /* DISPC_LINE_NUMBER */
475
        s->dispc.line = value & 0x7ff;
476
        break;
477

    
478
    case 0x064:        /* DISPC_TIMING_H */
479
        s->dispc.timing[0] = value & 0x0ff0ff3f;
480
        break;
481
    case 0x068:        /* DISPC_TIMING_V */
482
        s->dispc.timing[1] = value & 0x0ff0ff3f;
483
        break;
484
    case 0x06c:        /* DISPC_POL_FREQ */
485
        s->dispc.timing[2] = value & 0x0003ffff;
486
        break;
487
    case 0x070:        /* DISPC_DIVISOR */
488
        s->dispc.timing[3] = value & 0x00ff00ff;
489
        break;
490

    
491
    case 0x078:        /* DISPC_SIZE_DIG */
492
        s->dig.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
493
        s->dig.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
494
        s->dispc.invalidate = 1;
495
        break;
496
    case 0x07c:        /* DISPC_SIZE_LCD */
497
        s->lcd.nx = ((value >>  0) & 0x7ff) + 1;                /* PPL */
498
        s->lcd.ny = ((value >> 16) & 0x7ff) + 1;                /* LPP */
499
        s->dispc.invalidate = 1;
500
        break;
501
    case 0x080:        /* DISPC_GFX_BA0 */
502
        s->dispc.l[0].addr[0] = (target_phys_addr_t) value;
503
        s->dispc.invalidate = 1;
504
        break;
505
    case 0x084:        /* DISPC_GFX_BA1 */
506
        s->dispc.l[0].addr[1] = (target_phys_addr_t) value;
507
        s->dispc.invalidate = 1;
508
        break;
509
    case 0x088:        /* DISPC_GFX_POSITION */
510
        s->dispc.l[0].posx = ((value >>  0) & 0x7ff);                /* GFXPOSX */
511
        s->dispc.l[0].posy = ((value >> 16) & 0x7ff);                /* GFXPOSY */
512
        s->dispc.invalidate = 1;
513
        break;
514
    case 0x08c:        /* DISPC_GFX_SIZE */
515
        s->dispc.l[0].nx = ((value >>  0) & 0x7ff) + 1;                /* GFXSIZEX */
516
        s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1;                /* GFXSIZEY */
517
        s->dispc.invalidate = 1;
518
        break;
519
    case 0x0a0:        /* DISPC_GFX_ATTRIBUTES */
520
        s->dispc.l[0].attr = value & 0x7ff;
521
        if (value & (3 << 9))
522
            fprintf(stderr, "%s: Big-endian pixel format not supported\n",
523
                            __FUNCTION__);
524
        s->dispc.l[0].enable = value & 1;
525
        s->dispc.l[0].bpp = (value >> 1) & 0xf;
526
        s->dispc.invalidate = 1;
527
        break;
528
    case 0x0a4:        /* DISPC_GFX_FIFO_TRESHOLD */
529
        s->dispc.l[0].tresh = value & 0x01ff01ff;
530
        break;
531
    case 0x0ac:        /* DISPC_GFX_ROW_INC */
532
        s->dispc.l[0].rowinc = value;
533
        s->dispc.invalidate = 1;
534
        break;
535
    case 0x0b0:        /* DISPC_GFX_PIXEL_INC */
536
        s->dispc.l[0].colinc = value;
537
        s->dispc.invalidate = 1;
538
        break;
539
    case 0x0b4:        /* DISPC_GFX_WINDOW_SKIP */
540
        s->dispc.l[0].wininc = value;
541
        break;
542
    case 0x0b8:        /* DISPC_GFX_TABLE_BA */
543
        s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
544
        s->dispc.invalidate = 1;
545
        break;
546

    
547
    case 0x0bc:        /* DISPC_VID1_BA0 */
548
    case 0x0c0:        /* DISPC_VID1_BA1 */
549
    case 0x0c4:        /* DISPC_VID1_POSITION */
550
    case 0x0c8:        /* DISPC_VID1_SIZE */
551
    case 0x0cc:        /* DISPC_VID1_ATTRIBUTES */
552
    case 0x0d0:        /* DISPC_VID1_FIFO_TRESHOLD */
553
    case 0x0d8:        /* DISPC_VID1_ROW_INC */
554
    case 0x0dc:        /* DISPC_VID1_PIXEL_INC */
555
    case 0x0e0:        /* DISPC_VID1_FIR */
556
    case 0x0e4:        /* DISPC_VID1_PICTURE_SIZE */
557
    case 0x0e8:        /* DISPC_VID1_ACCU0 */
558
    case 0x0ec:        /* DISPC_VID1_ACCU1 */
559
    case 0x0f0 ... 0x140:        /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
560
    case 0x14c:        /* DISPC_VID2_BA0 */
561
    case 0x150:        /* DISPC_VID2_BA1 */
562
    case 0x154:        /* DISPC_VID2_POSITION */
563
    case 0x158:        /* DISPC_VID2_SIZE */
564
    case 0x15c:        /* DISPC_VID2_ATTRIBUTES */
565
    case 0x160:        /* DISPC_VID2_FIFO_TRESHOLD */
566
    case 0x168:        /* DISPC_VID2_ROW_INC */
567
    case 0x16c:        /* DISPC_VID2_PIXEL_INC */
568
    case 0x170:        /* DISPC_VID2_FIR */
569
    case 0x174:        /* DISPC_VID2_PICTURE_SIZE */
570
    case 0x178:        /* DISPC_VID2_ACCU0 */
571
    case 0x17c:        /* DISPC_VID2_ACCU1 */
572
    case 0x180 ... 0x1d0:        /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
573
    case 0x1d4:        /* DISPC_DATA_CYCLE1 */
574
    case 0x1d8:        /* DISPC_DATA_CYCLE2 */
575
    case 0x1dc:        /* DISPC_DATA_CYCLE3 */
576
        break;
577

    
578
    default:
579
        OMAP_BAD_REG(addr);
580
    }
581
}
582

    
583
static CPUReadMemoryFunc *omap_disc1_readfn[] = {
584
    omap_badwidth_read32,
585
    omap_badwidth_read32,
586
    omap_disc_read,
587
};
588

    
589
static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
590
    omap_badwidth_write32,
591
    omap_badwidth_write32,
592
    omap_disc_write,
593
};
594

    
595
static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
596
{
597
    target_phys_addr_t fb;
598
    uint32_t pd;
599

    
600
    /* TODO */
601
    fb = s->dispc.l[0].addr[0];
602

    
603
    pd = cpu_get_physical_page_desc(fb);
604
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
605
        /* TODO */
606
        cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
607
                        __FUNCTION__);
608
    else
609
        return phys_ram_base +
610
                (pd & TARGET_PAGE_MASK) +
611
                (fb & ~TARGET_PAGE_MASK);
612
}
613

    
614
static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
615
{
616
    if (!s->rfbi.busy)
617
        return;
618

    
619
    /* TODO: in non-Bypass mode we probably need to just deassert the DRQ.  */
620

    
621
    s->rfbi.busy = 0;
622
}
623

    
624
static void omap_rfbi_transfer_start(struct omap_dss_s *s)
625
{
626
    void *data;
627
    size_t len;
628
    int pitch;
629

    
630
    if (!s->rfbi.enable || s->rfbi.busy)
631
        return;
632

    
633
    if (s->rfbi.control & (1 << 1)) {                                /* BYPASS */
634
        /* TODO: in non-Bypass mode we probably need to just assert the
635
         * DRQ and wait for DMA to write the pixels.  */
636
        fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
637
        return;
638
    }
639

    
640
    if (!(s->dispc.control & (1 << 11)))                        /* RFBIMODE */
641
        return;
642
    /* TODO: check that LCD output is enabled in DISPC.  */
643

    
644
    s->rfbi.busy = 1;
645

    
646
    data = omap_rfbi_get_buffer(s);
647

    
648
    /* TODO bpp */
649
    len = s->rfbi.pixels * 2;
650
    s->rfbi.pixels = 0;
651

    
652
    /* TODO: negative values */
653
    pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
654

    
655
    if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
656
        s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
657
    if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
658
        s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
659

    
660
    omap_rfbi_transfer_stop(s);
661

    
662
    /* TODO */
663
    s->dispc.irqst |= 1;                                        /* FRAMEDONE */
664
    omap_dispc_interrupt_update(s);
665
}
666

    
667
static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
668
{
669
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
670
    int offset = addr - s->rfbi_base;
671

    
672
    switch (offset) {
673
    case 0x00:        /* RFBI_REVISION */
674
        return 0x10;
675

    
676
    case 0x10:        /* RFBI_SYSCONFIG */
677
        return s->rfbi.idlemode;
678

    
679
    case 0x14:        /* RFBI_SYSSTATUS */
680
        return 1 | (s->rfbi.busy << 8);                                /* RESETDONE */
681

    
682
    case 0x40:        /* RFBI_CONTROL */
683
        return s->rfbi.control;
684

    
685
    case 0x44:        /* RFBI_PIXELCNT */
686
        return s->rfbi.pixels;
687

    
688
    case 0x48:        /* RFBI_LINE_NUMBER */
689
        return s->rfbi.skiplines;
690

    
691
    case 0x58:        /* RFBI_READ */
692
    case 0x5c:        /* RFBI_STATUS */
693
        return s->rfbi.rxbuf;
694

    
695
    case 0x60:        /* RFBI_CONFIG0 */
696
        return s->rfbi.config[0];
697
    case 0x64:        /* RFBI_ONOFF_TIME0 */
698
        return s->rfbi.time[0];
699
    case 0x68:        /* RFBI_CYCLE_TIME0 */
700
        return s->rfbi.time[1];
701
    case 0x6c:        /* RFBI_DATA_CYCLE1_0 */
702
        return s->rfbi.data[0];
703
    case 0x70:        /* RFBI_DATA_CYCLE2_0 */
704
        return s->rfbi.data[1];
705
    case 0x74:        /* RFBI_DATA_CYCLE3_0 */
706
        return s->rfbi.data[2];
707

    
708
    case 0x78:        /* RFBI_CONFIG1 */
709
        return s->rfbi.config[1];
710
    case 0x7c:        /* RFBI_ONOFF_TIME1 */
711
        return s->rfbi.time[2];
712
    case 0x80:        /* RFBI_CYCLE_TIME1 */
713
        return s->rfbi.time[3];
714
    case 0x84:        /* RFBI_DATA_CYCLE1_1 */
715
        return s->rfbi.data[3];
716
    case 0x88:        /* RFBI_DATA_CYCLE2_1 */
717
        return s->rfbi.data[4];
718
    case 0x8c:        /* RFBI_DATA_CYCLE3_1 */
719
        return s->rfbi.data[5];
720

    
721
    case 0x90:        /* RFBI_VSYNC_WIDTH */
722
        return s->rfbi.vsync;
723
    case 0x94:        /* RFBI_HSYNC_WIDTH */
724
        return s->rfbi.hsync;
725
    }
726
    OMAP_BAD_REG(addr);
727
    return 0;
728
}
729

    
730
static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
731
                uint32_t value)
732
{
733
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
734
    int offset = addr - s->rfbi_base;
735

    
736
    switch (offset) {
737
    case 0x10:        /* RFBI_SYSCONFIG */
738
        if (value & 2)                                                /* SOFTRESET */
739
            omap_rfbi_reset(s);
740
        s->rfbi.idlemode = value & 0x19;
741
        break;
742

    
743
    case 0x40:        /* RFBI_CONTROL */
744
        s->rfbi.control = value & 0xf;
745
        s->rfbi.enable = value & 1;
746
        if (value & (1 << 4) &&                                        /* ITE */
747
                        !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
748
            omap_rfbi_transfer_start(s);
749
        break;
750

    
751
    case 0x44:        /* RFBI_PIXELCNT */
752
        s->rfbi.pixels = value;
753
        break;
754

    
755
    case 0x48:        /* RFBI_LINE_NUMBER */
756
        s->rfbi.skiplines = value & 0x7ff;
757
        break;
758

    
759
    case 0x4c:        /* RFBI_CMD */
760
        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
761
            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
762
        if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
763
            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
764
        break;
765
    case 0x50:        /* RFBI_PARAM */
766
        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
767
            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
768
        if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
769
            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
770
        break;
771
    case 0x54:        /* RFBI_DATA */
772
        /* TODO: take into account the format set up in s->rfbi.config[?] and
773
         * s->rfbi.data[?], but special-case the most usual scenario so that
774
         * speed doesn't suffer.  */
775
        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
776
            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
777
            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
778
        }
779
        if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
780
            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
781
            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
782
        }
783
        if (!-- s->rfbi.pixels)
784
            omap_rfbi_transfer_stop(s);
785
        break;
786
    case 0x58:        /* RFBI_READ */
787
        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
788
            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
789
        else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
790
            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
791
        if (!-- s->rfbi.pixels)
792
            omap_rfbi_transfer_stop(s);
793
        break;
794

    
795
    case 0x5c:        /* RFBI_STATUS */
796
        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
797
            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
798
        else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
799
            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
800
        if (!-- s->rfbi.pixels)
801
            omap_rfbi_transfer_stop(s);
802
        break;
803

    
804
    case 0x60:        /* RFBI_CONFIG0 */
805
        s->rfbi.config[0] = value & 0x003f1fff;
806
        break;
807

    
808
    case 0x64:        /* RFBI_ONOFF_TIME0 */
809
        s->rfbi.time[0] = value & 0x3fffffff;
810
        break;
811
    case 0x68:        /* RFBI_CYCLE_TIME0 */
812
        s->rfbi.time[1] = value & 0x0fffffff;
813
        break;
814
    case 0x6c:        /* RFBI_DATA_CYCLE1_0 */
815
        s->rfbi.data[0] = value & 0x0f1f0f1f;
816
        break;
817
    case 0x70:        /* RFBI_DATA_CYCLE2_0 */
818
        s->rfbi.data[1] = value & 0x0f1f0f1f;
819
        break;
820
    case 0x74:        /* RFBI_DATA_CYCLE3_0 */
821
        s->rfbi.data[2] = value & 0x0f1f0f1f;
822
        break;
823
    case 0x78:        /* RFBI_CONFIG1 */
824
        s->rfbi.config[1] = value & 0x003f1fff;
825
        break;
826

    
827
    case 0x7c:        /* RFBI_ONOFF_TIME1 */
828
        s->rfbi.time[2] = value & 0x3fffffff;
829
        break;
830
    case 0x80:        /* RFBI_CYCLE_TIME1 */
831
        s->rfbi.time[3] = value & 0x0fffffff;
832
        break;
833
    case 0x84:        /* RFBI_DATA_CYCLE1_1 */
834
        s->rfbi.data[3] = value & 0x0f1f0f1f;
835
        break;
836
    case 0x88:        /* RFBI_DATA_CYCLE2_1 */
837
        s->rfbi.data[4] = value & 0x0f1f0f1f;
838
        break;
839
    case 0x8c:        /* RFBI_DATA_CYCLE3_1 */
840
        s->rfbi.data[5] = value & 0x0f1f0f1f;
841
        break;
842

    
843
    case 0x90:        /* RFBI_VSYNC_WIDTH */
844
        s->rfbi.vsync = value & 0xffff;
845
        break;
846
    case 0x94:        /* RFBI_HSYNC_WIDTH */
847
        s->rfbi.hsync = value & 0xffff;
848
        break;
849

    
850
    default:
851
        OMAP_BAD_REG(addr);
852
    }
853
}
854

    
855
static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
856
    omap_badwidth_read32,
857
    omap_badwidth_read32,
858
    omap_rfbi_read,
859
};
860

    
861
static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
862
    omap_badwidth_write32,
863
    omap_badwidth_write32,
864
    omap_rfbi_write,
865
};
866

    
867
static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
868
{
869
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
870
    int offset = addr - s->venc_base;
871

    
872
    switch (offset) {
873
    case 0x00:        /* REV_ID */
874
    case 0x04:        /* STATUS */
875
    case 0x08:        /* F_CONTROL */
876
    case 0x10:        /* VIDOUT_CTRL */
877
    case 0x14:        /* SYNC_CTRL */
878
    case 0x1c:        /* LLEN */
879
    case 0x20:        /* FLENS */
880
    case 0x24:        /* HFLTR_CTRL */
881
    case 0x28:        /* CC_CARR_WSS_CARR */
882
    case 0x2c:        /* C_PHASE */
883
    case 0x30:        /* GAIN_U */
884
    case 0x34:        /* GAIN_V */
885
    case 0x38:        /* GAIN_Y */
886
    case 0x3c:        /* BLACK_LEVEL */
887
    case 0x40:        /* BLANK_LEVEL */
888
    case 0x44:        /* X_COLOR */
889
    case 0x48:        /* M_CONTROL */
890
    case 0x4c:        /* BSTAMP_WSS_DATA */
891
    case 0x50:        /* S_CARR */
892
    case 0x54:        /* LINE21 */
893
    case 0x58:        /* LN_SEL */
894
    case 0x5c:        /* L21__WC_CTL */
895
    case 0x60:        /* HTRIGGER_VTRIGGER */
896
    case 0x64:        /* SAVID__EAVID */
897
    case 0x68:        /* FLEN__FAL */
898
    case 0x6c:        /* LAL__PHASE_RESET */
899
    case 0x70:        /* HS_INT_START_STOP_X */
900
    case 0x74:        /* HS_EXT_START_STOP_X */
901
    case 0x78:        /* VS_INT_START_X */
902
    case 0x7c:        /* VS_INT_STOP_X__VS_INT_START_Y */
903
    case 0x80:        /* VS_INT_STOP_Y__VS_INT_START_X */
904
    case 0x84:        /* VS_EXT_STOP_X__VS_EXT_START_Y */
905
    case 0x88:        /* VS_EXT_STOP_Y */
906
    case 0x90:        /* AVID_START_STOP_X */
907
    case 0x94:        /* AVID_START_STOP_Y */
908
    case 0xa0:        /* FID_INT_START_X__FID_INT_START_Y */
909
    case 0xa4:        /* FID_INT_OFFSET_Y__FID_EXT_START_X */
910
    case 0xa8:        /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
911
    case 0xb0:        /* TVDETGP_INT_START_STOP_X */
912
    case 0xb4:        /* TVDETGP_INT_START_STOP_Y */
913
    case 0xb8:        /* GEN_CTRL */
914
    case 0xc4:        /* DAC_TST__DAC_A */
915
    case 0xc8:        /* DAC_B__DAC_C */
916
        return 0;
917

    
918
    default:
919
        break;
920
    }
921
    OMAP_BAD_REG(addr);
922
    return 0;
923
}
924

    
925
static void omap_venc_write(void *opaque, target_phys_addr_t addr,
926
                uint32_t value)
927
{
928
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
929
    int offset = addr - s->venc_base;
930

    
931
    switch (offset) {
932
    case 0x08:        /* F_CONTROL */
933
    case 0x10:        /* VIDOUT_CTRL */
934
    case 0x14:        /* SYNC_CTRL */
935
    case 0x1c:        /* LLEN */
936
    case 0x20:        /* FLENS */
937
    case 0x24:        /* HFLTR_CTRL */
938
    case 0x28:        /* CC_CARR_WSS_CARR */
939
    case 0x2c:        /* C_PHASE */
940
    case 0x30:        /* GAIN_U */
941
    case 0x34:        /* GAIN_V */
942
    case 0x38:        /* GAIN_Y */
943
    case 0x3c:        /* BLACK_LEVEL */
944
    case 0x40:        /* BLANK_LEVEL */
945
    case 0x44:        /* X_COLOR */
946
    case 0x48:        /* M_CONTROL */
947
    case 0x4c:        /* BSTAMP_WSS_DATA */
948
    case 0x50:        /* S_CARR */
949
    case 0x54:        /* LINE21 */
950
    case 0x58:        /* LN_SEL */
951
    case 0x5c:        /* L21__WC_CTL */
952
    case 0x60:        /* HTRIGGER_VTRIGGER */
953
    case 0x64:        /* SAVID__EAVID */
954
    case 0x68:        /* FLEN__FAL */
955
    case 0x6c:        /* LAL__PHASE_RESET */
956
    case 0x70:        /* HS_INT_START_STOP_X */
957
    case 0x74:        /* HS_EXT_START_STOP_X */
958
    case 0x78:        /* VS_INT_START_X */
959
    case 0x7c:        /* VS_INT_STOP_X__VS_INT_START_Y */
960
    case 0x80:        /* VS_INT_STOP_Y__VS_INT_START_X */
961
    case 0x84:        /* VS_EXT_STOP_X__VS_EXT_START_Y */
962
    case 0x88:        /* VS_EXT_STOP_Y */
963
    case 0x90:        /* AVID_START_STOP_X */
964
    case 0x94:        /* AVID_START_STOP_Y */
965
    case 0xa0:        /* FID_INT_START_X__FID_INT_START_Y */
966
    case 0xa4:        /* FID_INT_OFFSET_Y__FID_EXT_START_X */
967
    case 0xa8:        /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
968
    case 0xb0:        /* TVDETGP_INT_START_STOP_X */
969
    case 0xb4:        /* TVDETGP_INT_START_STOP_Y */
970
    case 0xb8:        /* GEN_CTRL */
971
    case 0xc4:        /* DAC_TST__DAC_A */
972
    case 0xc8:        /* DAC_B__DAC_C */
973
        break;
974

    
975
    default:
976
        OMAP_BAD_REG(addr);
977
    }
978
}
979

    
980
static CPUReadMemoryFunc *omap_venc1_readfn[] = {
981
    omap_badwidth_read32,
982
    omap_badwidth_read32,
983
    omap_venc_read,
984
};
985

    
986
static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
987
    omap_badwidth_write32,
988
    omap_badwidth_write32,
989
    omap_venc_write,
990
};
991

    
992
static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
993
{
994
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
995
    int offset = addr - s->im3_base;
996

    
997
    switch (offset) {
998
    case 0x0a8:        /* SBIMERRLOGA */
999
    case 0x0b0:        /* SBIMERRLOG */
1000
    case 0x190:        /* SBIMSTATE */
1001
    case 0x198:        /* SBTMSTATE_L */
1002
    case 0x19c:        /* SBTMSTATE_H */
1003
    case 0x1a8:        /* SBIMCONFIG_L */
1004
    case 0x1ac:        /* SBIMCONFIG_H */
1005
    case 0x1f8:        /* SBID_L */
1006
    case 0x1fc:        /* SBID_H */
1007
        return 0;
1008

    
1009
    default:
1010
        break;
1011
    }
1012
    OMAP_BAD_REG(addr);
1013
    return 0;
1014
}
1015

    
1016
static void omap_im3_write(void *opaque, target_phys_addr_t addr,
1017
                uint32_t value)
1018
{
1019
    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1020
    int offset = addr - s->im3_base;
1021

    
1022
    switch (offset) {
1023
    case 0x0b0:        /* SBIMERRLOG */
1024
    case 0x190:        /* SBIMSTATE */
1025
    case 0x198:        /* SBTMSTATE_L */
1026
    case 0x19c:        /* SBTMSTATE_H */
1027
    case 0x1a8:        /* SBIMCONFIG_L */
1028
    case 0x1ac:        /* SBIMCONFIG_H */
1029
        break;
1030

    
1031
    default:
1032
        OMAP_BAD_REG(addr);
1033
    }
1034
}
1035

    
1036
static CPUReadMemoryFunc *omap_im3_readfn[] = {
1037
    omap_badwidth_read32,
1038
    omap_badwidth_read32,
1039
    omap_im3_read,
1040
};
1041

    
1042
static CPUWriteMemoryFunc *omap_im3_writefn[] = {
1043
    omap_badwidth_write32,
1044
    omap_badwidth_write32,
1045
    omap_im3_write,
1046
};
1047

    
1048
struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
1049
                target_phys_addr_t l3_base, DisplayState *ds,
1050
                qemu_irq irq, qemu_irq drq,
1051
                omap_clk fck1, omap_clk fck2, omap_clk ck54m,
1052
                omap_clk ick1, omap_clk ick2)
1053
{
1054
    int iomemtype[5];
1055
    struct omap_dss_s *s = (struct omap_dss_s *)
1056
            qemu_mallocz(sizeof(struct omap_dss_s));
1057

    
1058
    s->irq = irq;
1059
    s->drq = drq;
1060
    s->state = ds;
1061
    omap_dss_reset(s);
1062

    
1063
    iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn,
1064
                    omap_diss1_writefn, s);
1065
    iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn,
1066
                    omap_disc1_writefn, s);
1067
    iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn,
1068
                    omap_rfbi1_writefn, s);
1069
    iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn,
1070
                    omap_venc1_writefn, s);
1071
    iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
1072
                    omap_im3_writefn, s);
1073
    s->diss_base = omap_l4_attach(ta, 0, iomemtype[0]);
1074
    s->disc_base = omap_l4_attach(ta, 1, iomemtype[1]);
1075
    s->rfbi_base = omap_l4_attach(ta, 2, iomemtype[2]);
1076
    s->venc_base = omap_l4_attach(ta, 3, iomemtype[3]);
1077
    s->im3_base = l3_base;
1078
    cpu_register_physical_memory(s->im3_base, 0x1000, iomemtype[4]);
1079

    
1080
#if 0
1081
    if (ds)
1082
        graphic_console_init(ds, omap_update_display,
1083
                        omap_invalidate_display, omap_screen_dump, s);
1084
#endif
1085

    
1086
    return s;
1087
}
1088

    
1089
void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
1090
{
1091
    if (cs < 0 || cs > 1)
1092
        cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1093
    s->rfbi.chip[cs] = chip;
1094
}