1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "hw/hw.h"
22#include "ui/console.h"
23#include "hw/arm/omap.h"
24
25struct omap_dss_s {
26 qemu_irq irq;
27 qemu_irq drq;
28 DisplayState *state;
29 MemoryRegion iomem_diss1, iomem_disc1, iomem_rfbi1, iomem_venc1, iomem_im3;
30
31 int autoidle;
32 int control;
33 int enable;
34
35 struct omap_dss_panel_s {
36 int enable;
37 int nx;
38 int ny;
39
40 int x;
41 int y;
42 } dig, lcd;
43
44 struct {
45 uint32_t idlemode;
46 uint32_t irqst;
47 uint32_t irqen;
48 uint32_t control;
49 uint32_t config;
50 uint32_t capable;
51 uint32_t timing[4];
52 int line;
53 uint32_t bg[2];
54 uint32_t trans[2];
55
56 struct omap_dss_plane_s {
57 int enable;
58 int bpp;
59 int posx;
60 int posy;
61 int nx;
62 int ny;
63
64 hwaddr addr[3];
65
66 uint32_t attr;
67 uint32_t tresh;
68 int rowinc;
69 int colinc;
70 int wininc;
71 } l[3];
72
73 int invalidate;
74 uint16_t palette[256];
75 } dispc;
76
77 struct {
78 int idlemode;
79 uint32_t control;
80 int enable;
81 int pixels;
82 int busy;
83 int skiplines;
84 uint16_t rxbuf;
85 uint32_t config[2];
86 uint32_t time[4];
87 uint32_t data[6];
88 uint16_t vsync;
89 uint16_t hsync;
90 struct rfbi_chip_s *chip[2];
91 } rfbi;
92};
93
94static void omap_dispc_interrupt_update(struct omap_dss_s *s)
95{
96 qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen);
97}
98
99static void omap_rfbi_reset(struct omap_dss_s *s)
100{
101 s->rfbi.idlemode = 0;
102 s->rfbi.control = 2;
103 s->rfbi.enable = 0;
104 s->rfbi.pixels = 0;
105 s->rfbi.skiplines = 0;
106 s->rfbi.busy = 0;
107 s->rfbi.config[0] = 0x00310000;
108 s->rfbi.config[1] = 0x00310000;
109 s->rfbi.time[0] = 0;
110 s->rfbi.time[1] = 0;
111 s->rfbi.time[2] = 0;
112 s->rfbi.time[3] = 0;
113 s->rfbi.data[0] = 0;
114 s->rfbi.data[1] = 0;
115 s->rfbi.data[2] = 0;
116 s->rfbi.data[3] = 0;
117 s->rfbi.data[4] = 0;
118 s->rfbi.data[5] = 0;
119 s->rfbi.vsync = 0;
120 s->rfbi.hsync = 0;
121}
122
123void omap_dss_reset(struct omap_dss_s *s)
124{
125 s->autoidle = 0;
126 s->control = 0;
127 s->enable = 0;
128
129 s->dig.enable = 0;
130 s->dig.nx = 1;
131 s->dig.ny = 1;
132
133 s->lcd.enable = 0;
134 s->lcd.nx = 1;
135 s->lcd.ny = 1;
136
137 s->dispc.idlemode = 0;
138 s->dispc.irqst = 0;
139 s->dispc.irqen = 0;
140 s->dispc.control = 0;
141 s->dispc.config = 0;
142 s->dispc.capable = 0x161;
143 s->dispc.timing[0] = 0;
144 s->dispc.timing[1] = 0;
145 s->dispc.timing[2] = 0;
146 s->dispc.timing[3] = 0;
147 s->dispc.line = 0;
148 s->dispc.bg[0] = 0;
149 s->dispc.bg[1] = 0;
150 s->dispc.trans[0] = 0;
151 s->dispc.trans[1] = 0;
152
153 s->dispc.l[0].enable = 0;
154 s->dispc.l[0].bpp = 0;
155 s->dispc.l[0].addr[0] = 0;
156 s->dispc.l[0].addr[1] = 0;
157 s->dispc.l[0].addr[2] = 0;
158 s->dispc.l[0].posx = 0;
159 s->dispc.l[0].posy = 0;
160 s->dispc.l[0].nx = 1;
161 s->dispc.l[0].ny = 1;
162 s->dispc.l[0].attr = 0;
163 s->dispc.l[0].tresh = 0;
164 s->dispc.l[0].rowinc = 1;
165 s->dispc.l[0].colinc = 1;
166 s->dispc.l[0].wininc = 0;
167
168 omap_rfbi_reset(s);
169 omap_dispc_interrupt_update(s);
170}
171
172static uint64_t omap_diss_read(void *opaque, hwaddr addr,
173 unsigned size)
174{
175 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
176
177 if (size != 4) {
178 return omap_badwidth_read32(opaque, addr);
179 }
180
181 switch (addr) {
182 case 0x00:
183 return 0x20;
184
185 case 0x10:
186 return s->autoidle;
187
188 case 0x14:
189 return 1;
190
191 case 0x40:
192 return s->control;
193
194 case 0x50:
195 case 0x54:
196 case 0x58:
197
198 return 0;
199
200 case 0x5c:
201 return 1 + (s->control & 1);
202
203 default:
204 break;
205 }
206 OMAP_BAD_REG(addr);
207 return 0;
208}
209
210static void omap_diss_write(void *opaque, hwaddr addr,
211 uint64_t value, unsigned size)
212{
213 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
214
215 if (size != 4) {
216 omap_badwidth_write32(opaque, addr, value);
217 return;
218 }
219
220 switch (addr) {
221 case 0x00:
222 case 0x14:
223 case 0x50:
224 case 0x54:
225 case 0x58:
226 case 0x5c:
227 OMAP_RO_REG(addr);
228 break;
229
230 case 0x10:
231 if (value & 2)
232 omap_dss_reset(s);
233 s->autoidle = value & 1;
234 break;
235
236 case 0x40:
237 s->control = value & 0x3dd;
238 break;
239
240 default:
241 OMAP_BAD_REG(addr);
242 }
243}
244
245static const MemoryRegionOps omap_diss_ops = {
246 .read = omap_diss_read,
247 .write = omap_diss_write,
248 .endianness = DEVICE_NATIVE_ENDIAN,
249};
250
251static uint64_t omap_disc_read(void *opaque, hwaddr addr,
252 unsigned size)
253{
254 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
255
256 if (size != 4) {
257 return omap_badwidth_read32(opaque, addr);
258 }
259
260 switch (addr) {
261 case 0x000:
262 return 0x20;
263
264 case 0x010:
265 return s->dispc.idlemode;
266
267 case 0x014:
268 return 1;
269
270 case 0x018:
271 return s->dispc.irqst;
272
273 case 0x01c:
274 return s->dispc.irqen;
275
276 case 0x040:
277 return s->dispc.control;
278
279 case 0x044:
280 return s->dispc.config;
281
282 case 0x048:
283 return s->dispc.capable;
284
285 case 0x04c:
286 return s->dispc.bg[0];
287 case 0x050:
288 return s->dispc.bg[1];
289 case 0x054:
290 return s->dispc.trans[0];
291 case 0x058:
292 return s->dispc.trans[1];
293
294 case 0x05c:
295 return 0x7ff;
296 case 0x060:
297 return s->dispc.line;
298
299 case 0x064:
300 return s->dispc.timing[0];
301 case 0x068:
302 return s->dispc.timing[1];
303 case 0x06c:
304 return s->dispc.timing[2];
305 case 0x070:
306 return s->dispc.timing[3];
307
308 case 0x078:
309 return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
310 case 0x07c:
311 return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
312
313 case 0x080:
314 return s->dispc.l[0].addr[0];
315 case 0x084:
316 return s->dispc.l[0].addr[1];
317 case 0x088:
318 return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx;
319 case 0x08c:
320 return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1);
321 case 0x0a0:
322 return s->dispc.l[0].attr;
323 case 0x0a4:
324 return s->dispc.l[0].tresh;
325 case 0x0a8:
326 return 256;
327 case 0x0ac:
328 return s->dispc.l[0].rowinc;
329 case 0x0b0:
330 return s->dispc.l[0].colinc;
331 case 0x0b4:
332 return s->dispc.l[0].wininc;
333 case 0x0b8:
334 return s->dispc.l[0].addr[2];
335
336 case 0x0bc:
337 case 0x0c0:
338 case 0x0c4:
339 case 0x0c8:
340 case 0x0cc:
341 case 0x0d0:
342 case 0x0d4:
343 case 0x0d8:
344 case 0x0dc:
345 case 0x0e0:
346 case 0x0e4:
347 case 0x0e8:
348 case 0x0ec:
349 case 0x0f0 ... 0x140:
350 case 0x14c:
351 case 0x150:
352 case 0x154:
353 case 0x158:
354 case 0x15c:
355 case 0x160:
356 case 0x164:
357 case 0x168:
358 case 0x16c:
359 case 0x170:
360 case 0x174:
361 case 0x178:
362 case 0x17c:
363 case 0x180 ... 0x1d0:
364 case 0x1d4:
365 case 0x1d8:
366 case 0x1dc:
367 return 0;
368
369 default:
370 break;
371 }
372 OMAP_BAD_REG(addr);
373 return 0;
374}
375
376static void omap_disc_write(void *opaque, hwaddr addr,
377 uint64_t value, unsigned size)
378{
379 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
380
381 if (size != 4) {
382 omap_badwidth_write32(opaque, addr, value);
383 return;
384 }
385
386 switch (addr) {
387 case 0x010:
388 if (value & 2)
389 omap_dss_reset(s);
390 s->dispc.idlemode = value & 0x301b;
391 break;
392
393 case 0x018:
394 s->dispc.irqst &= ~value;
395 omap_dispc_interrupt_update(s);
396 break;
397
398 case 0x01c:
399 s->dispc.irqen = value & 0xffff;
400 omap_dispc_interrupt_update(s);
401 break;
402
403 case 0x040:
404 s->dispc.control = value & 0x07ff9fff;
405 s->dig.enable = (value >> 1) & 1;
406 s->lcd.enable = (value >> 0) & 1;
407 if (value & (1 << 12))
408 if (!((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1)) {
409 fprintf(stderr, "%s: Overlay Optimization when no overlay "
410 "region effectively exists leads to "
411 "unpredictable behaviour!\n", __func__);
412 }
413 if (value & (1 << 6)) {
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443 }
444 if (value & (1 << 5)) {
445
446 }
447 s->dispc.invalidate = 1;
448 break;
449
450 case 0x044:
451 s->dispc.config = value & 0x3fff;
452
453
454
455
456 s->dispc.invalidate = 1;
457 break;
458
459 case 0x048:
460 s->dispc.capable = value & 0x3ff;
461 break;
462
463 case 0x04c:
464 s->dispc.bg[0] = value & 0xffffff;
465 s->dispc.invalidate = 1;
466 break;
467 case 0x050:
468 s->dispc.bg[1] = value & 0xffffff;
469 s->dispc.invalidate = 1;
470 break;
471 case 0x054:
472 s->dispc.trans[0] = value & 0xffffff;
473 s->dispc.invalidate = 1;
474 break;
475 case 0x058:
476 s->dispc.trans[1] = value & 0xffffff;
477 s->dispc.invalidate = 1;
478 break;
479
480 case 0x060:
481 s->dispc.line = value & 0x7ff;
482 break;
483
484 case 0x064:
485 s->dispc.timing[0] = value & 0x0ff0ff3f;
486 break;
487 case 0x068:
488 s->dispc.timing[1] = value & 0x0ff0ff3f;
489 break;
490 case 0x06c:
491 s->dispc.timing[2] = value & 0x0003ffff;
492 break;
493 case 0x070:
494 s->dispc.timing[3] = value & 0x00ff00ff;
495 break;
496
497 case 0x078:
498 s->dig.nx = ((value >> 0) & 0x7ff) + 1;
499 s->dig.ny = ((value >> 16) & 0x7ff) + 1;
500 s->dispc.invalidate = 1;
501 break;
502 case 0x07c:
503 s->lcd.nx = ((value >> 0) & 0x7ff) + 1;
504 s->lcd.ny = ((value >> 16) & 0x7ff) + 1;
505 s->dispc.invalidate = 1;
506 break;
507 case 0x080:
508 s->dispc.l[0].addr[0] = (hwaddr) value;
509 s->dispc.invalidate = 1;
510 break;
511 case 0x084:
512 s->dispc.l[0].addr[1] = (hwaddr) value;
513 s->dispc.invalidate = 1;
514 break;
515 case 0x088:
516 s->dispc.l[0].posx = ((value >> 0) & 0x7ff);
517 s->dispc.l[0].posy = ((value >> 16) & 0x7ff);
518 s->dispc.invalidate = 1;
519 break;
520 case 0x08c:
521 s->dispc.l[0].nx = ((value >> 0) & 0x7ff) + 1;
522 s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1;
523 s->dispc.invalidate = 1;
524 break;
525 case 0x0a0:
526 s->dispc.l[0].attr = value & 0x7ff;
527 if (value & (3 << 9))
528 fprintf(stderr, "%s: Big-endian pixel format not supported\n",
529 __FUNCTION__);
530 s->dispc.l[0].enable = value & 1;
531 s->dispc.l[0].bpp = (value >> 1) & 0xf;
532 s->dispc.invalidate = 1;
533 break;
534 case 0x0a4:
535 s->dispc.l[0].tresh = value & 0x01ff01ff;
536 break;
537 case 0x0ac:
538 s->dispc.l[0].rowinc = value;
539 s->dispc.invalidate = 1;
540 break;
541 case 0x0b0:
542 s->dispc.l[0].colinc = value;
543 s->dispc.invalidate = 1;
544 break;
545 case 0x0b4:
546 s->dispc.l[0].wininc = value;
547 break;
548 case 0x0b8:
549 s->dispc.l[0].addr[2] = (hwaddr) value;
550 s->dispc.invalidate = 1;
551 break;
552
553 case 0x0bc:
554 case 0x0c0:
555 case 0x0c4:
556 case 0x0c8:
557 case 0x0cc:
558 case 0x0d0:
559 case 0x0d8:
560 case 0x0dc:
561 case 0x0e0:
562 case 0x0e4:
563 case 0x0e8:
564 case 0x0ec:
565 case 0x0f0 ... 0x140:
566 case 0x14c:
567 case 0x150:
568 case 0x154:
569 case 0x158:
570 case 0x15c:
571 case 0x160:
572 case 0x168:
573 case 0x16c:
574 case 0x170:
575 case 0x174:
576 case 0x178:
577 case 0x17c:
578 case 0x180 ... 0x1d0:
579 case 0x1d4:
580 case 0x1d8:
581 case 0x1dc:
582 break;
583
584 default:
585 OMAP_BAD_REG(addr);
586 }
587}
588
589static const MemoryRegionOps omap_disc_ops = {
590 .read = omap_disc_read,
591 .write = omap_disc_write,
592 .endianness = DEVICE_NATIVE_ENDIAN,
593};
594
595static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
596{
597 if (!s->rfbi.busy)
598 return;
599
600
601
602 s->rfbi.busy = 0;
603}
604
605static void omap_rfbi_transfer_start(struct omap_dss_s *s)
606{
607 void *data;
608 hwaddr len;
609 hwaddr data_addr;
610 int pitch;
611 static void *bounce_buffer;
612 static hwaddr bounce_len;
613
614 if (!s->rfbi.enable || s->rfbi.busy)
615 return;
616
617 if (s->rfbi.control & (1 << 1)) {
618
619
620 fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
621 return;
622 }
623
624 if (!(s->dispc.control & (1 << 11)))
625 return;
626
627
628 s->rfbi.busy = 1;
629
630 len = s->rfbi.pixels * 2;
631
632 data_addr = s->dispc.l[0].addr[0];
633 data = cpu_physical_memory_map(data_addr, &len, 0);
634 if (data && len != s->rfbi.pixels * 2) {
635 cpu_physical_memory_unmap(data, len, 0, 0);
636 data = NULL;
637 len = s->rfbi.pixels * 2;
638 }
639 if (!data) {
640 if (len > bounce_len) {
641 bounce_buffer = g_realloc(bounce_buffer, len);
642 }
643 data = bounce_buffer;
644 cpu_physical_memory_read(data_addr, data, len);
645 }
646
647
648 s->rfbi.pixels = 0;
649
650
651 pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
652
653 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
654 s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
655 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
656 s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
657
658 if (data != bounce_buffer) {
659 cpu_physical_memory_unmap(data, len, 0, len);
660 }
661
662 omap_rfbi_transfer_stop(s);
663
664
665 s->dispc.irqst |= 1;
666 omap_dispc_interrupt_update(s);
667}
668
669static uint64_t omap_rfbi_read(void *opaque, hwaddr addr,
670 unsigned size)
671{
672 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
673
674 if (size != 4) {
675 return omap_badwidth_read32(opaque, addr);
676 }
677
678 switch (addr) {
679 case 0x00:
680 return 0x10;
681
682 case 0x10:
683 return s->rfbi.idlemode;
684
685 case 0x14:
686 return 1 | (s->rfbi.busy << 8);
687
688 case 0x40:
689 return s->rfbi.control;
690
691 case 0x44:
692 return s->rfbi.pixels;
693
694 case 0x48:
695 return s->rfbi.skiplines;
696
697 case 0x58:
698 case 0x5c:
699 return s->rfbi.rxbuf;
700
701 case 0x60:
702 return s->rfbi.config[0];
703 case 0x64:
704 return s->rfbi.time[0];
705 case 0x68:
706 return s->rfbi.time[1];
707 case 0x6c:
708 return s->rfbi.data[0];
709 case 0x70:
710 return s->rfbi.data[1];
711 case 0x74:
712 return s->rfbi.data[2];
713
714 case 0x78:
715 return s->rfbi.config[1];
716 case 0x7c:
717 return s->rfbi.time[2];
718 case 0x80:
719 return s->rfbi.time[3];
720 case 0x84:
721 return s->rfbi.data[3];
722 case 0x88:
723 return s->rfbi.data[4];
724 case 0x8c:
725 return s->rfbi.data[5];
726
727 case 0x90:
728 return s->rfbi.vsync;
729 case 0x94:
730 return s->rfbi.hsync;
731 }
732 OMAP_BAD_REG(addr);
733 return 0;
734}
735
736static void omap_rfbi_write(void *opaque, hwaddr addr,
737 uint64_t value, unsigned size)
738{
739 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
740
741 if (size != 4) {
742 omap_badwidth_write32(opaque, addr, value);
743 return;
744 }
745
746 switch (addr) {
747 case 0x10:
748 if (value & 2)
749 omap_rfbi_reset(s);
750 s->rfbi.idlemode = value & 0x19;
751 break;
752
753 case 0x40:
754 s->rfbi.control = value & 0xf;
755 s->rfbi.enable = value & 1;
756 if (value & (1 << 4) &&
757 !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
758 omap_rfbi_transfer_start(s);
759 break;
760
761 case 0x44:
762 s->rfbi.pixels = value;
763 break;
764
765 case 0x48:
766 s->rfbi.skiplines = value & 0x7ff;
767 break;
768
769 case 0x4c:
770 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
771 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
772 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
773 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
774 break;
775 case 0x50:
776 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
777 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
778 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
779 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
780 break;
781 case 0x54:
782
783
784
785 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
786 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
787 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
788 }
789 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
790 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
791 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
792 }
793 if (!-- s->rfbi.pixels)
794 omap_rfbi_transfer_stop(s);
795 break;
796 case 0x58:
797 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
798 s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
799 else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
800 s->rfbi.rxbuf = s->rfbi.chip[1]->read(s->rfbi.chip[1]->opaque, 1);
801 if (!-- s->rfbi.pixels)
802 omap_rfbi_transfer_stop(s);
803 break;
804
805 case 0x5c:
806 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
807 s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
808 else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
809 s->rfbi.rxbuf = s->rfbi.chip[1]->read(s->rfbi.chip[1]->opaque, 0);
810 if (!-- s->rfbi.pixels)
811 omap_rfbi_transfer_stop(s);
812 break;
813
814 case 0x60:
815 s->rfbi.config[0] = value & 0x003f1fff;
816 break;
817
818 case 0x64:
819 s->rfbi.time[0] = value & 0x3fffffff;
820 break;
821 case 0x68:
822 s->rfbi.time[1] = value & 0x0fffffff;
823 break;
824 case 0x6c:
825 s->rfbi.data[0] = value & 0x0f1f0f1f;
826 break;
827 case 0x70:
828 s->rfbi.data[1] = value & 0x0f1f0f1f;
829 break;
830 case 0x74:
831 s->rfbi.data[2] = value & 0x0f1f0f1f;
832 break;
833 case 0x78:
834 s->rfbi.config[1] = value & 0x003f1fff;
835 break;
836
837 case 0x7c:
838 s->rfbi.time[2] = value & 0x3fffffff;
839 break;
840 case 0x80:
841 s->rfbi.time[3] = value & 0x0fffffff;
842 break;
843 case 0x84:
844 s->rfbi.data[3] = value & 0x0f1f0f1f;
845 break;
846 case 0x88:
847 s->rfbi.data[4] = value & 0x0f1f0f1f;
848 break;
849 case 0x8c:
850 s->rfbi.data[5] = value & 0x0f1f0f1f;
851 break;
852
853 case 0x90:
854 s->rfbi.vsync = value & 0xffff;
855 break;
856 case 0x94:
857 s->rfbi.hsync = value & 0xffff;
858 break;
859
860 default:
861 OMAP_BAD_REG(addr);
862 }
863}
864
865static const MemoryRegionOps omap_rfbi_ops = {
866 .read = omap_rfbi_read,
867 .write = omap_rfbi_write,
868 .endianness = DEVICE_NATIVE_ENDIAN,
869};
870
871static uint64_t omap_venc_read(void *opaque, hwaddr addr,
872 unsigned size)
873{
874 if (size != 4) {
875 return omap_badwidth_read32(opaque, addr);
876 }
877
878 switch (addr) {
879 case 0x00:
880 case 0x04:
881 case 0x08:
882 case 0x10:
883 case 0x14:
884 case 0x1c:
885 case 0x20:
886 case 0x24:
887 case 0x28:
888 case 0x2c:
889 case 0x30:
890 case 0x34:
891 case 0x38:
892 case 0x3c:
893 case 0x40:
894 case 0x44:
895 case 0x48:
896 case 0x4c:
897 case 0x50:
898 case 0x54:
899 case 0x58:
900 case 0x5c:
901 case 0x60:
902 case 0x64:
903 case 0x68:
904 case 0x6c:
905 case 0x70:
906 case 0x74:
907 case 0x78:
908 case 0x7c:
909 case 0x80:
910 case 0x84:
911 case 0x88:
912 case 0x90:
913 case 0x94:
914 case 0xa0:
915 case 0xa4:
916 case 0xa8:
917 case 0xb0:
918 case 0xb4:
919 case 0xb8:
920 case 0xc4:
921 case 0xc8:
922 return 0;
923
924 default:
925 break;
926 }
927 OMAP_BAD_REG(addr);
928 return 0;
929}
930
931static void omap_venc_write(void *opaque, hwaddr addr,
932 uint64_t value, unsigned size)
933{
934 if (size != 4) {
935 omap_badwidth_write32(opaque, addr, size);
936 return;
937 }
938
939 switch (addr) {
940 case 0x08:
941 case 0x10:
942 case 0x14:
943 case 0x1c:
944 case 0x20:
945 case 0x24:
946 case 0x28:
947 case 0x2c:
948 case 0x30:
949 case 0x34:
950 case 0x38:
951 case 0x3c:
952 case 0x40:
953 case 0x44:
954 case 0x48:
955 case 0x4c:
956 case 0x50:
957 case 0x54:
958 case 0x58:
959 case 0x5c:
960 case 0x60:
961 case 0x64:
962 case 0x68:
963 case 0x6c:
964 case 0x70:
965 case 0x74:
966 case 0x78:
967 case 0x7c:
968 case 0x80:
969 case 0x84:
970 case 0x88:
971 case 0x90:
972 case 0x94:
973 case 0xa0:
974 case 0xa4:
975 case 0xa8:
976 case 0xb0:
977 case 0xb4:
978 case 0xb8:
979 case 0xc4:
980 case 0xc8:
981 break;
982
983 default:
984 OMAP_BAD_REG(addr);
985 }
986}
987
988static const MemoryRegionOps omap_venc_ops = {
989 .read = omap_venc_read,
990 .write = omap_venc_write,
991 .endianness = DEVICE_NATIVE_ENDIAN,
992};
993
994static uint64_t omap_im3_read(void *opaque, hwaddr addr,
995 unsigned size)
996{
997 if (size != 4) {
998 return omap_badwidth_read32(opaque, addr);
999 }
1000
1001 switch (addr) {
1002 case 0x0a8:
1003 case 0x0b0:
1004 case 0x190:
1005 case 0x198:
1006 case 0x19c:
1007 case 0x1a8:
1008 case 0x1ac:
1009 case 0x1f8:
1010 case 0x1fc:
1011 return 0;
1012
1013 default:
1014 break;
1015 }
1016 OMAP_BAD_REG(addr);
1017 return 0;
1018}
1019
1020static void omap_im3_write(void *opaque, hwaddr addr,
1021 uint64_t value, unsigned size)
1022{
1023 if (size != 4) {
1024 omap_badwidth_write32(opaque, addr, value);
1025 return;
1026 }
1027
1028 switch (addr) {
1029 case 0x0b0:
1030 case 0x190:
1031 case 0x198:
1032 case 0x19c:
1033 case 0x1a8:
1034 case 0x1ac:
1035 break;
1036
1037 default:
1038 OMAP_BAD_REG(addr);
1039 }
1040}
1041
1042static const MemoryRegionOps omap_im3_ops = {
1043 .read = omap_im3_read,
1044 .write = omap_im3_write,
1045 .endianness = DEVICE_NATIVE_ENDIAN,
1046};
1047
1048struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
1049 MemoryRegion *sysmem,
1050 hwaddr l3_base,
1051 qemu_irq irq, qemu_irq drq,
1052 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
1053 omap_clk ick1, omap_clk ick2)
1054{
1055 struct omap_dss_s *s = g_new0(struct omap_dss_s, 1);
1056
1057 s->irq = irq;
1058 s->drq = drq;
1059 omap_dss_reset(s);
1060
1061 memory_region_init_io(&s->iomem_diss1, NULL, &omap_diss_ops, s, "omap.diss1",
1062 omap_l4_region_size(ta, 0));
1063 memory_region_init_io(&s->iomem_disc1, NULL, &omap_disc_ops, s, "omap.disc1",
1064 omap_l4_region_size(ta, 1));
1065 memory_region_init_io(&s->iomem_rfbi1, NULL, &omap_rfbi_ops, s, "omap.rfbi1",
1066 omap_l4_region_size(ta, 2));
1067 memory_region_init_io(&s->iomem_venc1, NULL, &omap_venc_ops, s, "omap.venc1",
1068 omap_l4_region_size(ta, 3));
1069 memory_region_init_io(&s->iomem_im3, NULL, &omap_im3_ops, s,
1070 "omap.im3", 0x1000);
1071
1072 omap_l4_attach(ta, 0, &s->iomem_diss1);
1073 omap_l4_attach(ta, 1, &s->iomem_disc1);
1074 omap_l4_attach(ta, 2, &s->iomem_rfbi1);
1075 omap_l4_attach(ta, 3, &s->iomem_venc1);
1076 memory_region_add_subregion(sysmem, l3_base, &s->iomem_im3);
1077
1078#if 0
1079 s->state = graphic_console_init(omap_update_display,
1080 omap_invalidate_display, omap_screen_dump, s);
1081#endif
1082
1083 return s;
1084}
1085
1086void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
1087{
1088 if (cs < 0 || cs > 1)
1089 hw_error("%s: wrong CS %i\n", __FUNCTION__, cs);
1090 s->rfbi.chip[cs] = chip;
1091}
1092