2
* OMAP2/3 Display Subsystem.
4
* Copyright (C) 2008,2009 Nokia Corporation
5
* Original OMAP2 support written by Andrzej Zaborowski <andrew@openedhand.com>
6
* Enhancements and OMAP3 support written by Juha Riihimäki
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 or
11
* (at your option) any later version of the License.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License along
19
* with this program; if not, see <http://www.gnu.org/licenses/>.
22
#include "hw/arm/omap.h"
23
#include "hw/sysbus.h"
24
#include "ui/console.h"
27
//#define OMAP_DSS_DEBUG
28
#define OMAP_DSS_DEBUG_DISPC
29
#define OMAP_DSS_DEBUG_DISS
30
#define OMAP_DSS_DEBUG_DSI
31
#define OMAP_DSS_DEBUG_RFBI
32
//#define OMAP_DSS_DEBUG_VENC
35
#define TRACE(fmt,...) fprintf(stderr, "%s@%d: " fmt "\n", __FUNCTION__, \
36
__LINE__, ##__VA_ARGS__)
37
#define LAYERNAME(n) ((!(n)) ? "GFX" : ((n)==1) ? "VID1" : "VID2")
38
#ifdef OMAP_DSS_DEBUG_DISPC
39
#define TRACEDISPC(fmt,...) TRACE(fmt, ##__VA_ARGS__)
41
#define TRACEDISPC(...)
43
#ifdef OMAP_DSS_DEBUG_DISS
44
#define TRACEDISS(fmt,...) TRACE(fmt, ##__VA_ARGS__)
46
#define TRACEDISS(...)
48
#ifdef OMAP_DSS_DEBUG_DSI
49
#define TRACEDSI(fmt,...) TRACE(fmt, ##__VA_ARGS__)
53
#ifdef OMAP_DSS_DEBUG_RFBI
54
#define TRACERFBI(fmt,...) TRACE(fmt, ##__VA_ARGS__)
56
#define TRACERFBI(...)
58
#ifdef OMAP_DSS_DEBUG_VENC
59
#define TRACEVENC(fmt,...) TRACE(fmt, ##__VA_ARGS__)
61
#define TRACEVENC(...)
65
#define TRACEDISPC(...)
66
#define TRACEDISS(...)
68
#define TRACERFBI(...)
69
#define TRACEVENC(...)
74
#define OMAP_RO_REG(...)
75
#define OMAP_RO_REGV(...)
76
#define OMAP_BAD_REG(...)
77
#define OMAP_BAD_REGV(...)
80
#define OMAP_DSI_RX_FIFO_SIZE 32
82
struct omap_dss_plane_s {
94
hwaddr addr[3]; /* BA0, BA1, TABLE_BA */
104
/* following used for planes 1 and 2 only (VID1 and VID2) */
106
uint32_t fir_coef_h[8];
107
uint32_t fir_coef_hv[8];
108
uint32_t fir_coef_v[8];
109
uint32_t conv_coef[5];
110
uint32_t picture_size;
114
struct omap_dss_panel_s {
122
struct omap_dss_plane_s gfx;
123
struct omap_dss_plane_s vid1;
124
struct omap_dss_plane_s vid2;
125
uint32_t *gfx_palette;
126
uint32_t gfx_palette_size;
132
MemoryRegion iomem_diss1, iomem_disc1, iomem_rfbi1, iomem_venc1, iomem_im3;
133
MemoryRegion iomem_dsi;
140
uint32_t sdi_control;
141
uint32_t pll_control;
144
struct omap_dss_panel_s dig, lcd;
147
QEMUTimer *lcdframer;
162
uint32_t global_alpha;
167
struct omap_dss_plane_s plane[3]; /* GFX, VID1, VID2 */
183
const struct rfbi_chip_s *chip[2];
188
QEMUTimer *xfer_timer;
190
/* protocol engine registers */
195
uint32_t complexio_cfg1;
196
uint32_t complexio_cfg2;
197
uint32_t complexio_irqst;
198
uint32_t complexio_irqen;
210
uint32_t stopclk_timing;
211
uint32_t tx_fifo_vc_size;
212
uint32_t rx_fifo_vc_size;
222
uint32_t rx_fifo[OMAP_DSI_RX_FIFO_SIZE];
230
/* pll controller registers */
231
uint32_t pll_control;
233
uint32_t pll_config1;
234
uint32_t pll_config2;
238
#include "ui/pixel_ops.h"
239
#include "framebuffer.h"
241
#include "omap_dss_drawfn.h"
243
#include "omap_dss_drawfn.h"
245
#include "omap_dss_drawfn.h"
247
#include "omap_dss_drawfn.h"
249
#include "omap_dss_drawfn.h"
252
static drawfn omap_dss_linefn(const DeviceState *dev, int format, int bpp)
255
case 8: return omap_dss_drawfn_8[format];
256
case 15: return omap_dss_drawfn_15[format];
257
case 16: return omap_dss_drawfn_16[format];
258
case 24: return omap_dss_drawfn_24[format];
259
case 32: return omap_dss_drawfn_32[format];
261
hw_error("%s: unsupported host display color depth: %d\n",
268
/* Bytes(!) per pixel */
269
static const int omap_lcd_Bpp[0x10] = {
270
0, /* 0x0: BITMAP1 (CLUT) */
271
0, /* 0x1: BITMAP2 (CLUT) */
272
0, /* 0x2: BITMAP4 (CLUT) */
273
1, /* 0x3: BITMAP8 (CLUT) */
274
2, /* 0x4: RGB12 (unpacked 16-bit container)*/
277
0, /* 0x7: reserved */
278
4, /* 0x8: RGB24 (unpacked in 32-bit container) */
279
3, /* 0x9: RGB24 (packed in 24-bit container) */
280
2, /* 0xa: YUV2 422 */
281
2, /* 0xb: UYVY 422 */
284
4, /* 0xe: RGBx32 (24-bit RGB aligned on MSB of the 32-bit container) */
285
0, /* 0xf: reserved */
288
static void omap_dss_interrupt_update(struct omap_dss_s *s)
291
(s->dsi.irqst & s->dsi.irqen)
292
| (s->dsi.complexio_irqst & s->dsi.complexio_irqen)
293
| (s->dsi.vc[0].irqst & s->dsi.vc[0].irqen)
294
| (s->dsi.vc[1].irqst & s->dsi.vc[1].irqen)
295
| (s->dsi.vc[2].irqst & s->dsi.vc[2].irqen)
296
| (s->dsi.vc[3].irqst & s->dsi.vc[3].irqen)
297
| (s->dispc.irqst & s->dispc.irqen));
300
static void omap_dss_framedone(void *opaque)
302
struct omap_dss_s *s = (struct omap_dss_s *)opaque;
303
if (s->dispc.control & 3) { /* DIGITALENABLE | LCDENABLE */
304
if ((s->dispc.control & (1 << 11))) { /* STALLMODE */
305
s->dispc.control &= ~1; /* LCDENABLE */
306
if ((s->rfbi.control & 1)) { /* ENABLE */
310
if (s->dispc.lcdframer) {
311
qemu_del_timer(s->dispc.lcdframer);
314
if (s->dispc.lcdframer) {
315
qemu_mod_timer(s->dispc.lcdframer,
316
qemu_get_clock_ns(vm_clock)
317
+ get_ticks_per_sec() / 10);
320
s->dispc.irqst |= 1 | 2; /* FRAMEDONE | VSYNC */
321
omap_dss_interrupt_update(s);
325
static void omap_dsi_te_trigger(DeviceState *dev, int vc)
327
struct omap_dss_s *s = FROM_SYSBUS(struct omap_dss_s,
328
SYS_BUS_DEVICE(dev));
329
if ((s->dsi.ctrl & 1) && /* IF_EN */
330
(s->dsi.vc[vc].ctrl & 1)) { /* VC_EN */
331
s->dsi.irqst |= 1 << 16; /* TE_TRIGGER_IRQ */
332
omap_dss_interrupt_update(s);
336
static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
341
/* TODO: in non-Bypass mode we probably need to just deassert the DRQ. */
344
s->rfbi.control &= ~0x10; /* ITE */
347
static void omap_rfbi_transfer_start(struct omap_dss_s *s)
353
static void *bounce_buffer;
354
static hwaddr bounce_len;
356
if (!s->rfbi.enable || s->rfbi.busy)
359
if (s->rfbi.control & (1 << 1)) { /* BYPASS */
360
/* TODO: in non-Bypass mode we probably need to just assert the
361
* DRQ and wait for DMA to write the pixels. */
362
hw_error("%s: Bypass mode unimplemented", __FUNCTION__);
365
if (!(s->dispc.control & (1 << 11))) /* STALLMODE */
370
len = s->rfbi.pixels * 2;
372
data_addr = s->dispc.plane[0].addr[0];
373
data = cpu_physical_memory_map(data_addr, &len, 0);
374
if (data && len != s->rfbi.pixels * 2) {
375
cpu_physical_memory_unmap(data, len, 0, 0);
377
len = s->rfbi.pixels * 2;
380
if (len > bounce_len) {
381
bounce_buffer = g_realloc(bounce_buffer, len);
383
data = bounce_buffer;
384
cpu_physical_memory_read(data_addr, data, len);
387
/* TODO: negative values */
388
pitch = s->dispc.plane[0].nx + (s->dispc.plane[0].rowinc - 1) / 2;
390
if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
391
s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
392
if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
393
s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
395
if (data != bounce_buffer) {
396
cpu_physical_memory_unmap(data, len, 0, len);
399
omap_rfbi_transfer_stop(s);
401
omap_dss_framedone(s);
404
static void omap_dsi_transfer_stop(void *opaque)
406
struct omap_dss_s *s = opaque;
408
qemu_del_timer(s->dsi.xfer_timer);
409
for (i = 0; i < 4; i++) {
410
if ((s->dsi.vc[i].ctrl & 1) && /* VC_EN */
411
((s->dsi.vc[i].te >> 30) & 3)) { /* TE_START | TE_EN */
412
TRACEDSI("TE data transfer ready, signaling framedone");
413
s->dsi.vc[i].te = 0; /* transfer complete */
414
omap_dss_framedone(s);
415
dsi_bltdone(s->dsi.host, i);
420
static void omap_dsi_transfer_start(struct omap_dss_s *s, int ch)
422
if (((s->dispc.control >> 11) & 1) && /* STALLMODE */
423
(s->dsi.ctrl & 1) && /* IF_EN */
424
(s->dsi.vc[ch].ctrl & 1) && /* VC_EN */
425
((s->dsi.vc[ch].te >> 30) & 3)) { /* TE_START | TE_EN */
426
TRACEDSI("start TE data transfer on channel %d for %d bytes",
427
ch, s->dsi.vc[ch].te & 0xffffff);
428
TRACEDSI("vc%d irqenable=0x%08x", ch, s->dsi.vc[ch].irqen);
429
TRACEDSI("dsi irqenable=0x%08x", s->dsi.irqen);
430
TRACEDSI("dispc irqenable=0x%08x", s->dispc.irqen);
431
int tx_dma = (s->dsi.vc[ch].ctrl >> 21) & 7; /* DMA_TX_REQ_NB */
433
qemu_irq_raise(s->dsi.drq[tx_dma]);
435
const int format = (s->dispc.plane[0].attr >> 1) & 0xf;
436
const int col_pitch = omap_lcd_Bpp[format] +
437
(s->dispc.plane[0].colinc - 1);
438
const int row_pitch = (s->dispc.plane[0].nx * col_pitch) +
439
(s->dispc.plane[0].rowinc - 1);
440
hwaddr len = row_pitch * s->dispc.plane[0].ny;
441
void *data = cpu_physical_memory_map(s->dispc.plane[0].addr[0],
443
if (!data || len != row_pitch * s->dispc.plane[0].ny) {
444
fprintf(stderr, "%s: unable to map contiguous frame buffer\n",
447
dsi_blt(s->dsi.host, ch, data, s->dispc.plane[0].nx,
448
s->dispc.plane[0].ny, col_pitch, row_pitch, format);
451
cpu_physical_memory_unmap(data, len, 0, 0);
453
/* We cannot signal transfer complete immediately since some
454
* display drivers assume transfer takes some time. Instead,
455
* setup a small delay and report transfer complete a bit
457
s->dsi.vc[ch].ctrl &= ~(0x11 << 16); /* TX/RX fifo not full */
458
qemu_mod_timer(s->dsi.xfer_timer,
459
qemu_get_clock_ns(vm_clock)
460
+ get_ticks_per_sec() / 1000);
465
static void omap_dss_panel_layer_update(DisplaySurface *surface,
467
uint32_t panel_width,
468
uint32_t panel_height,
470
int *posy, int *endy,
471
uint32_t width, uint32_t height,
477
if (!(attrib & 1)) { /* layer disabled? */
480
uint32_t format = (attrib >> 1) & 0xf;
481
if ((attrib & 0x600)) { /* GFXENDIANNESS | GFXNIBBLEMODE */
482
hw_error("%s: unsupported layer attributes (0x%08x)\n",
483
__FUNCTION__, attrib);
485
drawfn line_fn = omap_dss_linefn(NULL, format,
486
surface_bits_per_pixel(surface));
488
hw_error("%s: unsupported omap dss color format: %d\n",
489
__FUNCTION__, format);
492
fprintf(stderr, "%s@%d: non-zero layer x-coordinate (%d), "
493
"not currently supported -> using zero\n", __FUNCTION__,
498
uint32_t copy_width = (posx + width) > panel_width
499
? (panel_width - posx) : width;
500
uint32_t copy_height = ((*posy) + height) > panel_height
501
? (panel_height - (*posy)) : height;
502
uint32_t linesize = surface_stride(surface);
503
framebuffer_update_display(surface, mr, addr, copy_width, copy_height,
505
? (width >> (3 - format))
506
: (width * omap_lcd_Bpp[format]),
507
linesize, linesize / surface_width(surface),
508
full_update, line_fn, palette,
512
static void omap_dss_panel_update_display(struct omap_dss_panel_s *s,
513
MemoryRegion *mr, int lcd)
515
DisplaySurface *surface = qemu_console_surface(s->con);
517
if (s->shadow.width != surface_width(surface)
518
|| s->shadow.height != surface_height(surface)) {
519
qemu_console_resize(s->con, s->shadow.width, s->shadow.height);
520
surface = qemu_console_surface(s->con);
522
if ((s->shadow.gfx.attr >> 12) & 0x3) { /* GFXROTATION */
523
hw_error("%s: GFX rotation is not supported", __FUNCTION__);
527
/* TODO: draw background color */
530
if ((lcd && !(s->shadow.gfx.attr & 0x100)) ||
531
(!lcd && (s->shadow.gfx.attr & 0x100))) {
532
if (s->shadow.gfx_palette && s->shadow.gfx_palette_size) {
533
cpu_physical_memory_read(s->shadow.gfx.addr[2],
534
(uint8_t *)s->shadow.gfx_palette,
535
s->shadow.gfx_palette_size
538
first_row = s->shadow.gfx.posy;
539
omap_dss_panel_layer_update(surface, mr,
540
s->shadow.width, s->shadow.height,
541
s->shadow.gfx.posx, &first_row, &last_row,
542
s->shadow.gfx.nx, s->shadow.gfx.ny,
543
s->shadow.gfx.attr, s->shadow.gfx.addr[0],
544
s->shadow.gfx_palette, s->invalidate);
546
/* TODO: draw VID1 & VID2 layers */
549
if (first_row >= 0) {
550
dpy_gfx_update(s->con, 0, first_row, s->shadow.width,
551
last_row - first_row + 1);
555
static void omap_lcd_panel_update_display(void *opaque)
557
struct omap_dss_s *s = opaque;
559
|| !(s->lcd.shadow.control & 1) /* LCDENABLE */
560
|| (s->lcd.shadow.control & (1 << 11))) { /* STALLMODE */
563
omap_dss_panel_update_display(&s->lcd, sysbus_address_space(&s->busdev), 1);
564
omap_dss_framedone(s);
567
static void omap_lcd_panel_invalidate_display(void *opaque)
569
struct omap_dss_s *s = opaque;
570
s->lcd.invalidate = 1;
573
static void omap_dig_panel_update_display(void *opaque)
575
struct omap_dss_s *s = opaque;
576
if (!s->dig.con || !(s->dig.shadow.control & 2)) { /* DIGITALENABLE */
579
omap_dss_panel_update_display(&s->dig, sysbus_address_space(&s->busdev), 0);
580
omap_dss_framedone(s);
583
static void omap_dig_panel_invalidate_display(void *opaque)
585
struct omap_dss_s *s = opaque;
586
s->dig.invalidate = 1;
589
static void omap_dss_panel_go(struct omap_dss_s *s,
590
struct omap_dss_panel_s *p,
595
p->shadow.control = s->dispc.control;
596
p->shadow.width = (size & 0x7ff) + 1;
597
p->shadow.height = ((size >> 16) & 0x7ff) + 1;
598
p->shadow.gfx = s->dispc.plane[0];
599
p->shadow.vid1 = s->dispc.plane[1];
600
p->shadow.vid2 = s->dispc.plane[2];
602
switch ((p->shadow.gfx.attr >> 1) & 0x0f) {
603
case 0: new_size = 2; break;
604
case 1: new_size = 4; break;
605
case 2: new_size = 16; break;
606
case 3: new_size = 256; break;
609
if (new_size != p->shadow.gfx_palette_size) {
610
if (p->shadow.gfx_palette) {
611
g_free(p->shadow.gfx_palette);
612
p->shadow.gfx_palette = NULL;
615
p->shadow.gfx_palette = g_malloc(new_size * sizeof(uint32_t));
617
p->shadow.gfx_palette_size = new_size;
622
static void omap_dss_panel_reset(void *opaque)
624
struct omap_dss_panel_s *s = opaque;
626
s->shadow.control = 0;
627
memset(&s->shadow.gfx, 0, sizeof(s->shadow.gfx));
628
memset(&s->shadow.vid1, 0, sizeof(s->shadow.vid1));
629
memset(&s->shadow.vid2, 0, sizeof(s->shadow.vid2));
630
if (s->shadow.gfx_palette) {
631
g_free(s->shadow.gfx_palette);
632
s->shadow.gfx_palette = NULL;
633
s->shadow.gfx_palette_size = 0;
638
static void omap_dsi_reset(struct omap_dss_s *s)
642
s->dsi.sysconfig = 0x11;
646
s->dsi.complexio_cfg1 = 0x20000000;
647
s->dsi.complexio_cfg2 = 0;
648
s->dsi.complexio_irqst = 0;
649
s->dsi.complexio_irqen = 0;
651
s->dsi.timing1 = 0x7fff7fff;
652
s->dsi.timing2 = 0x7fff7fff;
653
s->dsi.vm_timing1 = 0;
654
s->dsi.vm_timing2 = 0;
655
s->dsi.vm_timing3 = 0;
656
s->dsi.vm_timing4 = 0;
657
s->dsi.vm_timing5 = 0;
658
s->dsi.vm_timing6 = 0;
659
s->dsi.vm_timing7 = 0;
660
s->dsi.clk_timing = 0x0101;
661
s->dsi.stopclk_timing = 0x80;
662
s->dsi.tx_fifo_vc_size = 0;
663
s->dsi.rx_fifo_vc_size = 0;
664
for (i = 0; i < 4; i++) {
665
s->dsi.vc[i].ctrl = 0;
667
s->dsi.vc[i].lp_header = 0;
668
s->dsi.vc[i].lp_payload = 0;
669
s->dsi.vc[i].lp_counter = 0;
670
s->dsi.vc[i].sp_header = 0;
671
s->dsi.vc[i].irqst = 0;
672
s->dsi.vc[i].irqen = 0;
673
s->dsi.vc[i].rx_fifo_pos = 0;
674
s->dsi.vc[i].rx_fifo_len = 0;
676
if (s->mpu_model < omap3630) {
677
s->dsi.phy_cfg0 = 0x1a3c1a28;
678
s->dsi.phy_cfg1 = 0x420a1875;
679
s->dsi.phy_cfg2 = 0xb800001b;
681
s->dsi.phy_cfg0 = 0x1e481d3a;
682
s->dsi.phy_cfg1 = 0x420a1a6a;
683
s->dsi.phy_cfg2 = 0xb800001a;
685
s->dsi.pll_control = 0;
687
s->dsi.pll_config1 = 0;
688
s->dsi.pll_config2 = 0;
689
omap_dss_interrupt_update(s);
692
static void omap_rfbi_reset(struct omap_dss_s *s)
694
s->rfbi.idlemode = 0;
698
s->rfbi.skiplines = 0;
700
s->rfbi.config[0] = 0x00310000;
701
s->rfbi.config[1] = 0x00310000;
716
static void omap_dss_reset(DeviceState *dev)
720
struct omap_dss_s *s = FROM_SYSBUS(struct omap_dss_s,
721
SYS_BUS_DEVICE(dev));
722
s->autoidle = 0x10; /* was 0 for OMAP2 but bit4 must be set for OMAP3 */
724
if (s->mpu_model == omap3430) {
727
s->dss_status = 0x81; /* bit 7 is not present prior to OMAP3 */
728
} else { /* omap2, omap3630 */
729
s->dss_status = 0x01;
732
s->dispc.idlemode = 0;
735
s->dispc.control = 0;
737
s->dispc.capable = 0x161;
738
s->dispc.timing[0] = 0;
739
s->dispc.timing[1] = 0;
740
s->dispc.timing[2] = 0;
741
s->dispc.timing[3] = 0x00010002;
745
s->dispc.trans[0] = 0;
746
s->dispc.trans[1] = 0;
747
s->dispc.size_dig = 0;
748
s->dispc.size_lcd = 0;
749
s->dispc.global_alpha = 0;
750
s->dispc.cpr_coef_r = 0;
751
s->dispc.cpr_coef_g = 0;
752
s->dispc.cpr_coef_b = 0;
754
for (i = 0; i < 3; i++) {
755
s->dispc.plane[i].enable = 0;
756
s->dispc.plane[i].bpp = 0;
757
s->dispc.plane[i].addr[0] = 0;
758
s->dispc.plane[i].addr[1] = 0;
759
s->dispc.plane[i].addr[2] = 0;
760
s->dispc.plane[i].posx = 0;
761
s->dispc.plane[i].posy = 0;
762
s->dispc.plane[i].nx = 1;
763
s->dispc.plane[i].ny = 1;
764
s->dispc.plane[i].attr = 0;
765
s->dispc.plane[i].tresh = (s->dispc.rev < 0x30) ? 0 : 0x03ff03c0;
766
s->dispc.plane[i].rowinc = 1;
767
s->dispc.plane[i].colinc = 1;
768
s->dispc.plane[i].wininc = 0;
769
s->dispc.plane[i].preload = 0x100;
770
s->dispc.plane[i].fir = 0;
771
s->dispc.plane[i].picture_size = 0;
772
s->dispc.plane[i].accu[0] = 0;
773
s->dispc.plane[i].accu[1] = 0;
774
for (j = 0; j < 5; j++)
775
s->dispc.plane[i].conv_coef[j] = 0;
776
for (j = 0; j < 8; j++) {
777
s->dispc.plane[i].fir_coef_h[j] = 0;
778
s->dispc.plane[i].fir_coef_hv[j] = 0;
779
s->dispc.plane[i].fir_coef_v[j] = 0;
785
omap_dss_panel_reset(&s->lcd);
786
omap_dss_panel_reset(&s->dig);
787
omap_dss_interrupt_update(s);
790
static uint64_t omap_diss_read(void *opaque, hwaddr addr,
793
struct omap_dss_s *s = (struct omap_dss_s *) opaque;
797
return omap_badwidth_read32(opaque, addr);
801
case 0x00: /* DSS_REVISIONNUMBER */
802
TRACEDISS("DSS_REVISIONNUMBER: 0x20");
805
case 0x10: /* DSS_SYSCONFIG */
806
TRACEDISS("DSS_SYSCONFIG: 0x%08x", s->autoidle);
809
case 0x14: /* DSS_SYSSTATUS */
810
TRACEDISS("DSS_SYSSTATUS: 0x1");
811
return 1; /* RESETDONE */
813
case 0x18: /* DSS_IRQSTATUS */
814
x = (s->dispc.irqst & s->dispc.irqen) ? 1 : 0;
815
if ((s->dsi.irqst & s->dsi.irqen)
816
| (s->dsi.complexio_irqst & s->dsi.complexio_irqen)
817
| (s->dsi.vc[0].irqst & s->dsi.vc[0].irqen)
818
| (s->dsi.vc[1].irqst & s->dsi.vc[1].irqen)
819
| (s->dsi.vc[2].irqst & s->dsi.vc[2].irqen)
820
| (s->dsi.vc[3].irqst & s->dsi.vc[3].irqen))
822
TRACEDISS("DSS_IRQSTATUS: 0x%08x", x);
825
case 0x40: /* DSS_CONTROL */
826
TRACEDISS("DSS_CONTROL: 0x%08x", s->control);
829
case 0x44: /* DSS_SDI_CONTROL */
830
if (s->mpu_model == omap3430) {
831
TRACEDISS("DSS_SDI_CONTROL: 0x%08x", s->sdi_control);
832
return s->sdi_control;
836
case 0x48: /* DSS_PLL_CONTROL */
837
if (s->mpu_model == omap3430) {
838
TRACEDISS("DSS_PLL_CONTROL: 0x%08x", s->pll_control);
839
return s->pll_control;
843
case 0x50: /* DSS_PSA_LCD_REG_1 */
844
case 0x54: /* DSS_PSA_LCD_REG_2 */
845
case 0x58: /* DSS_PSA_VIDEO_REG */
846
if (s->mpu_model < omap3430) {
847
TRACEDISS("DSS_PSA_xxx: 0");
848
/* TODO: fake some values according to s->control bits */
855
if (s->mpu_model < omap3430) {
856
TRACEDISS("DSS_STATUS: 0x%08x", x);
858
if (s->mpu_model == omap3430) {
859
s->dss_status &= ~(1 << 6); /* SDI_PLL_BUSYFLAG */
860
TRACEDISS("DSS_SDI_STATUS: 0x%08x", x);
861
} else { /* omap3630 */
862
TRACEDISS("DSS_CLK_STATUS: 0x%08x", x);
873
static void omap_diss_write(void *opaque, hwaddr addr,
874
uint64_t value, unsigned size)
876
struct omap_dss_s *s = (struct omap_dss_s *) opaque;
879
return omap_badwidth_write32(opaque, addr, value);
883
case 0x00: /* DSS_REVISIONNUMBER */
884
case 0x14: /* DSS_SYSSTATUS */
885
case 0x18: /* DSS_IRQSTATUS */
886
case 0x50: /* DSS_PSA_LCD_REG_1 */
887
case 0x54: /* DSS_PSA_LCD_REG_2 */
888
case 0x58: /* DSS_PSA_VIDEO_REG */
889
case 0x5c: /* DSS_STATUS */
891
/*OMAP_RO_REGV(addr, value);*/
894
case 0x10: /* DSS_SYSCONFIG */
895
TRACEDISS("DSS_SYSCONFIG = 0x%08x", value);
896
if (value & 2) { /* SOFTRESET */
897
omap_dss_reset(&s->busdev.qdev);
899
if (s->mpu_model < omap3430) {
907
case 0x40: /* DSS_CONTROL */
908
TRACEDISS("DSS_CONTROL = 0x%08x", value);
909
if (s->mpu_model < omap3430) {
915
s->dss_status &= ~0x3;
916
s->dss_status |= 1 + (s->control & 1);
919
case 0x44: /* DSS_SDI_CONTROL */
920
if (s->mpu_model == omap3430) {
921
TRACEDISS("DSS_SDI_CONTROL = 0x%08x", value);
922
s->sdi_control = value & 0x000ff80f;
924
OMAP_BAD_REGV(addr, value);
928
case 0x48: /* DSS_PLL_CONTROL */
929
if (s->mpu_model == omap3430) {
930
TRACEDISS("DSS_PLL_CONTROL = 0x%08x", value);
931
if (value & (1 << 18)) { /* SDI_PLL_SYSRESET */
932
s->dss_status |= 1 << 2; /* SDI_PLL_RESETDONE */
934
s->dss_status &= ~(1 << 2); /* SDI_PLL_RESETDONE */
936
if (value & (1 << 28)) { /* SDI_PLL_GOBIT */
937
s->dss_status |= 1 << 6; /* SDI_PLL_BUSYFLAG */
938
s->dss_status &= ~(1 << 5); /* SDI_PLL_LOCK */
940
if (s->pll_control & (1 << 28)) { /* SDI_PLL_GOBIT */
941
s->dss_status &= ~(1 << 6); /* SDI_PLL_BUSYFLAG */
942
s->dss_status |= 1 << 5; /* SDI_PLL_LOCK */
945
s->pll_control = value;
947
OMAP_BAD_REGV(addr, value);
952
OMAP_BAD_REGV(addr, value);
957
static const MemoryRegionOps omap_diss_ops = {
958
.read = omap_diss_read,
959
.write = omap_diss_write,
960
.endianness = DEVICE_NATIVE_ENDIAN,
963
static uint64_t omap_disc_read(void *opaque, hwaddr addr,
966
struct omap_dss_s *s = (struct omap_dss_s *) opaque;
970
return omap_badwidth_read32(opaque, addr);
974
case 0x000: /* DISPC_REVISION */
975
TRACEDISPC("DISPC_REVISION: 0x%08x", s->dispc.rev);
977
case 0x010: /* DISPC_SYSCONFIG */
978
TRACEDISPC("DISPC_SYSCONFIG: 0x%08x", s->dispc.idlemode);
979
return s->dispc.idlemode;
980
case 0x014: /* DISPC_SYSSTATUS */
981
TRACEDISPC("DISPC_SYSSTATUS: 1");
982
return 1; /* RESETDONE */
983
case 0x018: /* DISPC_IRQSTATUS */
984
TRACEDISPC("DISPC_IRQSTATUS: 0x%08x", s->dispc.irqst);
985
return s->dispc.irqst;
986
case 0x01c: /* DISPC_IRQENABLE */
987
TRACEDISPC("DISPC_IRQENABLE: 0x%08x", s->dispc.irqen);
988
return s->dispc.irqen;
989
case 0x040: /* DISPC_CONTROL */
990
TRACEDISPC("DISPC_CONTROL: 0x%08x", s->dispc.control);
991
return s->dispc.control;
992
case 0x044: /* DISPC_CONFIG */
993
TRACEDISPC("DISPC_CONFIG: 0x%08x", s->dispc.config);
994
return s->dispc.config;
995
case 0x048: /* DISPC_CAPABLE */
996
TRACEDISPC("DISPC_CAPABLE: 0x%08x", s->dispc.capable);
997
return s->dispc.capable;
998
case 0x04c: /* DISPC_DEFAULT_COLOR0 */
999
TRACEDISPC("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[0]);
1000
return s->dispc.bg[0];
1001
case 0x050: /* DISPC_DEFAULT_COLOR1 */
1002
TRACEDISPC("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[1]);
1003
return s->dispc.bg[1];
1004
case 0x054: /* DISPC_TRANS_COLOR0 */
1005
TRACEDISPC("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[0]);
1006
return s->dispc.trans[0];
1007
case 0x058: /* DISPC_TRANS_COLOR1 */
1008
TRACEDISPC("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[1]);
1009
return s->dispc.trans[1];
1010
case 0x05c: /* DISPC_LINE_STATUS */
1011
TRACEDISPC("DISPC_LINE_STATUS: 0x7ff");
1013
case 0x060: /* DISPC_LINE_NUMBER */
1014
TRACEDISPC("DISPC_LINE_NUMBER: 0x%08x", s->dispc.line);
1015
return s->dispc.line;
1016
case 0x064: /* DISPC_TIMING_H */
1017
TRACEDISPC("DISPC_TIMING_H: 0x%08x", s->dispc.timing[0]);
1018
return s->dispc.timing[0];
1019
case 0x068: /* DISPC_TIMING_V */
1020
TRACEDISPC("DISPC_TIMING_H: 0x%08x", s->dispc.timing[1]);
1021
return s->dispc.timing[1];
1022
case 0x06c: /* DISPC_POL_FREQ */
1023
TRACEDISPC("DISPC_POL_FREQ: 0x%08x", s->dispc.timing[2]);
1024
return s->dispc.timing[2];
1025
case 0x070: /* DISPC_DIVISOR */
1026
TRACEDISPC("DISPC_DIVISOR: 0x%08x", s->dispc.timing[3]);
1027
return s->dispc.timing[3];
1028
case 0x074: /* DISPC_GLOBAL_ALPHA */
1029
TRACEDISPC("DISPC_GLOBAL_ALPHA: 0x%08x", s->dispc.global_alpha);
1030
return s->dispc.global_alpha;
1031
case 0x078: /* DISPC_SIZE_DIG */
1032
TRACEDISPC("DISPC_SIZE_DIG: 0x%08x", s->dispc.size_dig);
1033
return s->dispc.size_dig;
1034
case 0x07c: /* DISPC_SIZE_LCD */
1035
TRACEDISPC("DISPC_SIZE_LCD: 0x%08x", s->dispc.size_lcd);
1036
return s->dispc.size_lcd;
1037
case 0x14c: /* DISPC_VID2_BA0 */
1039
case 0x0bc: /* DISPC_VID1_BA0 */
1041
case 0x080: /* DISPC_GFX_BA0 */
1042
TRACEDISPC("DISPC_%s_BA0: " OMAP_FMT_plx, LAYERNAME(n),
1043
s->dispc.plane[n].addr[0]);
1044
return s->dispc.plane[n].addr[0];
1045
case 0x150: /* DISPC_VID2_BA1 */
1047
case 0x0c0: /* DISPC_VID1_BA1 */
1049
case 0x084: /* DISPC_GFX_BA1 */
1050
TRACEDISPC("DISPC_%s_BA1: " OMAP_FMT_plx, LAYERNAME(n),
1051
s->dispc.plane[n].addr[1]);
1052
return s->dispc.plane[n].addr[1];
1053
case 0x154: /* DISPC_VID2_POSITION */
1055
case 0x0c4: /* DISPC_VID1_POSITION */
1057
case 0x088: /* DISPC_GFX_POSITION */
1058
TRACEDISPC("DISPC_%s_POSITION: 0x%08x", LAYERNAME(n),
1059
(s->dispc.plane[n].posy << 16) | s->dispc.plane[n].posx);
1060
return (s->dispc.plane[n].posy << 16) | s->dispc.plane[n].posx;
1061
case 0x158: /* DISPC_VID2_SIZE */
1063
case 0x0c8: /* DISPC_VID1_SIZE */
1065
case 0x08c: /* DISPC_GFX_SIZE */
1066
TRACEDISPC("DISPC_%s_SIZE: 0x%08x", LAYERNAME(n),
1067
((s->dispc.plane[n].ny - 1) << 16)
1068
| (s->dispc.plane[n].nx - 1));
1069
return ((s->dispc.plane[n].ny - 1) << 16) | (s->dispc.plane[n].nx - 1);
1070
case 0x15c: /* DISPC_VID2_ATTRIBUTES */
1072
case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
1074
case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
1075
TRACEDISPC("DISPC_%s_ATTRIBUTES: 0x%08x", LAYERNAME(n),
1076
s->dispc.plane[n].attr);
1077
return s->dispc.plane[n].attr;
1078
case 0x160: /* DISPC_VID2_FIFO_THRESHOLD */
1080
case 0x0d0: /* DISPC_VID1_FIFO_THRESHOLD */
1082
case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
1083
TRACEDISPC("DISPC_%s_THRESHOLD: 0x%08x", LAYERNAME(n),
1084
s->dispc.plane[n].tresh);
1085
return s->dispc.plane[n].tresh;
1086
case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */
1088
case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */
1090
case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
1091
TRACEDISPC("DISPC_%s_FIFO_SIZE_STATUS: 0x%08x", LAYERNAME(n),
1092
s->dispc.rev < 0x30 ? 256 : 1024);
1093
return s->dispc.rev < 0x30 ? 256 : 1024;
1094
case 0x168: /* DISPC_VID2_ROW_INC */
1096
case 0x0d8: /* DISPC_VID1_ROW_INC */
1098
case 0x0ac: /* DISPC_GFX_ROW_INC */
1099
TRACEDISPC("DISPC_%s_ROW_INC: 0x%08x", LAYERNAME(n),
1100
s->dispc.plane[n].rowinc);
1101
return s->dispc.plane[n].rowinc;
1102
case 0x16c: /* DISPC_VID2_PIXEL_INC */
1104
case 0x0dc: /* DISPC_VID1_PIXEL_INC */
1106
case 0x0b0: /* DISPC_GFX_PIXEL_INC */
1107
TRACEDISPC("DISPC_%s_PIXEL_INC: 0x%08x", LAYERNAME(n),
1108
s->dispc.plane[n].colinc);
1109
return s->dispc.plane[n].colinc;
1110
case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
1111
TRACEDISPC("DISPC_GFX_WINDOW_SKIP: 0x%08x", s->dispc.plane[0].wininc);
1112
return s->dispc.plane[0].wininc;
1113
case 0x0b8: /* DISPC_GFX_TABLE_BA */
1114
TRACEDISPC("DISPC_GFX_TABLE_BA: " OMAP_FMT_plx,
1115
s->dispc.plane[0].addr[2]);
1116
return s->dispc.plane[0].addr[2];
1117
case 0x170: /* DISPC_VID2_FIR */
1119
case 0x0e0: /* DISPC_VID1_FIR */
1121
TRACEDISPC("DISPC_%s_FIR: 0x%08x", LAYERNAME(n),
1122
s->dispc.plane[n].fir);
1123
return s->dispc.plane[n].fir;
1124
case 0x174: /* DISPC_VID2_PICTURE_SIZE */
1126
case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
1128
TRACEDISPC("DISPC_%s_PICTURE_SIZE: 0x%08x", LAYERNAME(n),
1129
s->dispc.plane[n].picture_size);
1130
return s->dispc.plane[n].picture_size;
1131
case 0x178: /* DISPC_VID2_ACCU0 */
1132
case 0x17c: /* DISPC_VID2_ACCU1 */
1134
case 0x0e8: /* DISPC_VID1_ACCU0 */
1135
case 0x0ec: /* DISPC_VID1_ACCU1 */
1137
TRACEDISPC("DISPC_%s_ACCU%d: 0x%08x", LAYERNAME(n),
1138
(int)((addr >> 1) & 1),
1139
s->dispc.plane[n].accu[(addr >> 1 ) & 1]);
1140
return s->dispc.plane[n].accu[(addr >> 1) & 1];
1141
case 0x180 ... 0x1bc: /* DISPC_VID2_FIR_COEF */
1143
case 0x0f0 ... 0x12c: /* DISPC_VID1_FIR_COEF */
1146
TRACEDISPC("DISPC_%s_FIR_COEF_HV%d: 0x%08x", LAYERNAME(n),
1147
(int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8),
1148
s->dispc.plane[n].fir_coef_hv[
1149
(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
1150
return s->dispc.plane[n].fir_coef_hv[
1151
(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
1153
TRACEDISPC("DISPC_%s_FIR_COEF_H%d: 0x%08x", LAYERNAME(n),
1154
(int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8),
1155
s->dispc.plane[n].fir_coef_h[
1156
(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
1157
return s->dispc.plane[n].fir_coef_h[
1158
(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
1159
case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
1161
case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
1163
TRACEDISPC("DISPC_%s_CONV_COEF%d: 0x%08x", LAYERNAME(n),
1164
(int)((addr - ((n > 1) ? 0x1c0 : 0x130)) / 4),
1165
s->dispc.plane[n].conv_coef[
1166
(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4]);
1167
return s->dispc.plane[n].conv_coef[
1168
(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4];
1169
case 0x1d4: /* DISPC_DATA_CYCLE1 */
1170
case 0x1d8: /* DISPC_DATA_CYCLE2 */
1171
case 0x1dc: /* DISPC_DATA_CYCLE3 */
1172
TRACEDISPC("DISPC_DATA_CYCLE%d: 0", (int)((addr - 0x1d4) / 4));
1174
case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
1176
case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
1178
TRACEDISPC("DISPC_%s_FIR_COEF_V%d: 0x%08x", LAYERNAME(n),
1179
(int)((addr & 0x01f) / 4),
1180
s->dispc.plane[n].fir_coef_v[(addr & 0x01f) / 4]);
1181
return s->dispc.plane[n].fir_coef_v[(addr & 0x01f) / 4];
1182
case 0x220: /* DISPC_CPR_COEF_R */
1183
TRACEDISPC("DISPC_CPR_COEF_R: 0x%08x", s->dispc.cpr_coef_r);
1184
return s->dispc.cpr_coef_r;
1185
case 0x224: /* DISPC_CPR_COEF_G */
1186
TRACEDISPC("DISPC_CPR_COEF_G: 0x%08x", s->dispc.cpr_coef_g);
1187
return s->dispc.cpr_coef_g;
1188
case 0x228: /* DISPC_CPR_COEF_B */
1189
TRACEDISPC("DISPC_CPR_COEF_B: 0x%08x", s->dispc.cpr_coef_b);
1190
return s->dispc.cpr_coef_b;
1191
case 0x234: /* DISPC_VID2_PRELOAD */
1193
case 0x230: /* DISPC_VID1_PRELOAD */
1195
case 0x22c: /* DISPC_GFX_PRELOAD */
1196
TRACEDISPC("DISPC_%s_PRELOAD: 0x%08x", LAYERNAME(n),
1197
s->dispc.plane[n].preload);
1198
return s->dispc.plane[n].preload;
1206
static void omap_disc_write(void *opaque, hwaddr addr,
1207
uint64_t value, unsigned size)
1209
struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1213
return omap_badwidth_write32(opaque, addr, value);
1217
case 0x000: /* DISPC_REVISION */
1218
case 0x014: /* DISPC_SYSSTATUS */
1219
case 0x05c: /* DISPC_LINE_STATUS */
1220
case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
1221
/* quietly ignore */
1222
/*OMAP_RO_REGV(addr, value);*/
1224
case 0x010: /* DISPC_SYSCONFIG */
1225
TRACEDISPC("DISPC_SYSCONFIG = 0x%08x", value);
1226
if (value & 2) { /* SOFTRESET */
1227
omap_dss_reset(&s->busdev.qdev);
1229
s->dispc.idlemode = value & ((s->dispc.rev < 0x30) ? 0x301b : 0x331f);
1231
case 0x018: /* DISPC_IRQSTATUS */
1232
TRACEDISPC("DISPC_IRQSTATUS = 0x%08x", value);
1233
s->dispc.irqst &= ~value;
1234
omap_dss_interrupt_update(s);
1236
case 0x01c: /* DISPC_IRQENABLE */
1237
TRACEDISPC("DISPC_IRQENABLE = 0x%08x", value);
1238
s->dispc.irqen = value & ((s->dispc.rev < 0x30) ? 0xffff : 0x1ffff);
1239
omap_dss_interrupt_update(s);
1241
case 0x040: /* DISPC_CONTROL */
1242
TRACEDISPC("DISPC_CONTROL = 0x%08x", value);
1243
n = s->dispc.control; /* cache old value */
1244
/* always clear GODIGITAL and GOLCD to signal completed shadowing */
1245
if (s->dispc.rev < 0x30) {
1246
s->dispc.control = value & 0x07ff9f9f;
1248
s->dispc.control = (value & 0xffff9b9f)
1249
| (s->dispc.control & 0x6000);
1251
if (value & (1 << 12)) /* OVERLAY_OPTIMIZATION */
1252
if (!((s->dispc.plane[1].attr | s->dispc.plane[2].attr) & 1)) {
1253
TRACEDISPC("Overlay Optimization when no overlay "
1254
"region effectively exists leads to "
1255
"unpredictable behaviour!");
1257
if ((value & 0x21)) { /* GOLCD | LCDENABLE */
1258
omap_dss_panel_go(s, &s->lcd, s->dispc.size_lcd);
1260
if ((value & 0x42)) { /* GODIGITAL | DIGITALENABLE */
1261
omap_dss_panel_go(s, &s->dig, s->dispc.size_dig);
1263
if (value & 1) { /* LCDENABLE */
1264
if ((value & (1 << 11))) { /* STALLMODE */
1265
if ((s->rfbi.control & 0x11) && /* ITE | ENABLE */
1266
!(s->rfbi.config[0] & s->rfbi.config[1] & 0xc)) { /* TRIGGERMODE */
1267
omap_rfbi_transfer_start(s);
1269
if (s->dsi.ctrl & 1) { /* IF_EN */
1271
for (ch = 0; ch < 4; ch++) {
1272
if ((s->dsi.vc[ch].ctrl & 1) && /* VC_EN */
1273
(s->dsi.vc[ch].te >> 30) & 3) { /* TE_START | TE_EN */
1274
omap_dsi_transfer_start(s, ch);
1278
} else if (s->dispc.lcdframer) {
1279
qemu_mod_timer(s->dispc.lcdframer,
1280
qemu_get_clock_ns(vm_clock)
1281
+ get_ticks_per_sec() / 10);
1283
} else if (n & 1) { /* enable -> disable, signal wip frame done */
1284
s->dispc.control |= 1;
1285
omap_dss_framedone(s);
1286
s->dispc.control &= ~1;
1289
case 0x044: /* DISPC_CONFIG */
1290
TRACEDISPC("DISPC_CONFIG = 0x%08x", value);
1291
s->dispc.config = value & 0x3fff;
1293
* bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
1294
* bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
1297
case 0x048: /* DISPC_CAPABLE */
1298
TRACEDISPC("DISPC_CAPABLE = 0x%08x", value);
1299
s->dispc.capable = value & 0x3ff;
1301
case 0x04c: /* DISPC_DEFAULT_COLOR0 */
1302
TRACEDISPC("DISPC_DEFAULT_COLOR0 = 0x%08x", value);
1303
s->dispc.bg[0] = value & 0xffffff;
1305
case 0x050: /* DISPC_DEFAULT_COLOR1 */
1306
TRACEDISPC("DISPC_DEFAULT_COLOR1 = 0x%08x", value);
1307
s->dispc.bg[1] = value & 0xffffff;
1309
case 0x054: /* DISPC_TRANS_COLOR0 */
1310
TRACEDISPC("DISPC_TRANS_COLOR0 = 0x%08x", value);
1311
s->dispc.trans[0] = value & 0xffffff;
1313
case 0x058: /* DISPC_TRANS_COLOR1 */
1314
TRACEDISPC("DISPC_TRANS_COLOR1 = 0x%08x", value);
1315
s->dispc.trans[1] = value & 0xffffff;
1317
case 0x060: /* DISPC_LINE_NUMBER */
1318
TRACEDISPC("DISPC_LINE_NUMBER = 0x%08x", value);
1319
s->dispc.line = value & 0x7ff;
1321
case 0x064: /* DISPC_TIMING_H */
1322
TRACEDISPC("DISPC_TIMING_H = 0x%08x", value);
1323
s->dispc.timing[0] = value & 0x0ff0ff3f;
1325
case 0x068: /* DISPC_TIMING_V */
1326
TRACEDISPC("DISPC_TIMING_V = 0x%08x", value);
1327
s->dispc.timing[1] = value & 0x0ff0ff3f;
1329
case 0x06c: /* DISPC_POL_FREQ */
1330
TRACEDISPC("DISPC_POL_FREQ = 0x%08x", value);
1331
s->dispc.timing[2] = value & 0x0003ffff;
1333
case 0x070: /* DISPC_DIVISOR */
1334
TRACEDISPC("DISPC_DIVISOR = 0x%08x", value);
1335
s->dispc.timing[3] = value & 0x00ff00ff;
1337
case 0x074: /* DISPC_GLOBAL_ALPHA */
1338
TRACEDISPC("DISPC_GLOBAL_ALPHA = 0x%08x", value);
1339
s->dispc.global_alpha = value & 0x00ff00ff;
1341
case 0x078: /* DISPC_SIZE_DIG */
1342
TRACEDISPC("DISPC_SIZE_DIG = 0x%08x (%dx%d)",
1343
value, (value & 0x7ff) + 1, ((value >> 16) & 0x7ff) + 1);
1344
s->dispc.size_dig = value;
1346
case 0x07c: /* DISPC_SIZE_LCD */
1347
TRACEDISPC("DISPC_SIZE_LCD = 0x%08x (%dx%d)",
1348
value, (value & 0x7ff) + 1, ((value >> 16) & 0x7ff) + 1);
1349
s->dispc.size_lcd = value;
1351
case 0x14c: /* DISPC_VID2_BA0 */
1353
case 0x0bc: /* DISPC_VID1_BA0 */
1355
case 0x080: /* DISPC_GFX_BA0 */
1356
TRACEDISPC("DISPC_%s_BA0 = 0x%08x", LAYERNAME(n), value);
1357
s->dispc.plane[n].addr[0] = (hwaddr) value;
1359
case 0x150: /* DISPC_VID2_BA1 */
1361
case 0x0c0: /* DISPC_VID1_BA1 */
1363
case 0x084: /* DISPC_GFX_BA1 */
1364
TRACEDISPC("DISPC_%s_BA1 = 0x%08x", LAYERNAME(n), value);
1365
s->dispc.plane[n].addr[1] = (hwaddr) value;
1367
case 0x154: /* DISPC_VID2_POSITION */
1369
case 0x0c4: /* DISPC_VID1_POSITION */
1371
case 0x088: /* DISPC_GFX_POSITION */
1372
s->dispc.plane[n].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */
1373
s->dispc.plane[n].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */
1374
TRACEDISPC("DISPC_%s_POSITION = 0x%08x (%d,%d)", LAYERNAME(n),
1375
value, s->dispc.plane[n].posx, s->dispc.plane[n].posy);
1377
case 0x158: /* DISPC_VID2_SIZE */
1379
case 0x0c8: /* DISPC_VID1_SIZE */
1381
case 0x08c: /* DISPC_GFX_SIZE */
1382
s->dispc.plane[n].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */
1383
s->dispc.plane[n].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */
1384
TRACEDISPC("DISPC_%s_SIZE = 0x%08x (%dx%d)", LAYERNAME(n),
1385
value, s->dispc.plane[n].nx, s->dispc.plane[n].ny);
1387
case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
1388
TRACEDISPC("DISPC_GFX_ATTRIBUTES = 0x%08x", value);
1389
if (s->mpu_model < omap3630) {
1392
value &= 0x1000ffff;
1394
s->dispc.plane[0].attr = value;
1395
if (value & (3 << 9)) {
1396
hw_error("%s: Big-endian pixel format not supported",
1399
s->dispc.plane[0].enable = value & 1;
1400
s->dispc.plane[0].bpp = (value >> 1) & 0xf;
1401
s->dispc.plane[0].rotation_flag = (value >> 12) & 0x3;
1402
s->dispc.plane[0].gfx_format = (value >> 1) & 0xf;
1403
s->dispc.plane[0].gfx_channel = (value >> 8) & 0x1;
1405
case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
1407
case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
1409
case 0x0a4: /* DISPC_GFX_FIFO_THRESHOLD */
1410
TRACEDISPC("DISPC_%s_FIFO_THRESHOLD = 0x%08x", LAYERNAME(n), value);
1411
s->dispc.plane[n].tresh = value & ((s->dispc.rev < 0x30)
1412
? 0x01ff01ff : 0x0fff0fff);
1414
case 0x168: /* DISPC_VID2_ROW_INC */
1416
case 0x0d8: /* DISPC_VID1_ROW_INC */
1418
case 0x0ac: /* DISPC_GFX_ROW_INC */
1419
TRACEDISPC("DISPC_%s_ROW_INC = 0x%08x", LAYERNAME(n), value);
1420
s->dispc.plane[n].rowinc = value;
1422
case 0x16c: /* DISPC_VID2_PIXEL_INC */
1424
case 0x0dc: /* DISPC_VID1_PIXEL_INC */
1426
case 0x0b0: /* DISPC_GFX_PIXEL_INC */
1427
TRACEDISPC("DISPC_%s_PIXEL_INC = 0x%08x", LAYERNAME(n), value);
1428
s->dispc.plane[n].colinc = value;
1430
case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
1431
TRACEDISPC("DISPC_GFX_WINDOW_SKIP = 0x%08x", value);
1432
s->dispc.plane[0].wininc = value;
1434
case 0x0b8: /* DISPC_GFX_TABLE_BA */
1435
TRACEDISPC("DISPC_GFX_TABLE_BA = 0x%08x", value);
1436
s->dispc.plane[0].addr[2] = (hwaddr) value;
1438
case 0x15c: /* DISPC_VID2_ATTRIBUTES */
1440
case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
1442
TRACEDISPC("DISPC_%s_ATTRIBUTES = 0x%08x", LAYERNAME(n), value);
1443
if (s->mpu_model < omap3630) {
1444
value &= 0x01ffffff;
1446
value &= 0x11ffffff;
1448
s->dispc.plane[n].attr = value;
1450
case 0x170: /* DISPC_VID2_FIR */
1452
case 0x0e0: /* DISPC_VID1_FIR */
1454
TRACEDISPC("DISPC_%s_FIR = 0x%08x", LAYERNAME(n), value);
1455
s->dispc.plane[n].fir = value & 0x1fff1fff;
1457
case 0x174: /* DISPC_VID2_PICTURE_SIZE */
1459
case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
1461
TRACEDISPC("DISPC_%s_PICTURE_SIZE = 0x%08x", LAYERNAME(n), value);
1462
s->dispc.plane[n].picture_size = value & 0x07ff07ff;
1464
case 0x178: /* DISPC_VID2_ACCU0 */
1465
case 0x17c: /* DISPC_VID2_ACCU1 */
1467
case 0x0e8: /* DISPC_VID1_ACCU0 */
1468
case 0x0ec: /* DISPC_VID1_ACCU1 */
1470
TRACEDISPC("DISPC_%s_ACCU%d = 0x%08x", LAYERNAME(n),
1471
(int)((addr >> 1) & 1), value);
1472
s->dispc.plane[n].accu[(addr >> 1) & 1] = value & 0x03ff03ff;
1474
case 0x180 ... 0x1bc: /* DISPC_VID2_FIR_COEF */
1476
case 0x0f0 ... 0x12c: /* DISPC_VID1_FIR_COEF */
1479
TRACEDISPC("DISPC_%s_FIR_COEF_HV%d = 0x%08x", LAYERNAME(n),
1480
(int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8), value);
1481
s->dispc.plane[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
1483
TRACEDISPC("DISPC_%s_FIR_COEF_H%d = 0x%08x", LAYERNAME(n),
1484
(int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8), value);
1485
s->dispc.plane[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
1488
case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
1490
case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
1492
TRACEDISPC("DISPC_%s_CONV_COEF%d = 0x%08x", LAYERNAME(n),
1493
(int)((addr - ((n > 1) ? 0x1c0 : 0x130)) / 4), value);
1494
s->dispc.plane[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4] = value;
1496
case 0x1d4: /* DISPC_DATA_CYCLE1 */
1497
case 0x1d8: /* DISPC_DATA_CYCLE2 */
1498
case 0x1dc: /* DISPC_DATA_CYCLE3 */
1499
TRACEDISPC("DISPC_DATA_CYCLE%d = 0x%08x (ignored)",
1500
(int)((addr - 0x1d4) / 4), value);
1502
case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
1504
case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
1506
TRACEDISPC("DISPC_%s_FIR_COEF_V%d = 0x%08x", LAYERNAME(n),
1507
(int)((addr & 0x01f) / 4), value);
1508
s->dispc.plane[n].fir_coef_v[(addr & 0x01f) / 4] = value & 0x0000ffff;
1510
case 0x220: /* DISPC_CPR_COEF_R */
1511
TRACEDISPC("DISPC_CPR_COEF_R = 0x%08x", value);
1512
s->dispc.cpr_coef_r = value & 0xffbffbff;
1514
case 0x224: /* DISPC_CPR_COEF_G */
1515
TRACEDISPC("DISPC_CPR_COEF_G = 0x%08x", value);
1516
s->dispc.cpr_coef_g = value & 0xffbffbff;
1518
case 0x228: /* DISPC_CPR_COEF_B */
1519
TRACEDISPC("DISPC_CPR_COEF_B = 0x%08x", value);
1520
s->dispc.cpr_coef_b = value & 0xffbffbff;
1522
case 0x234: /* DISPC_VID2_PRELOAD */
1524
case 0x230: /* DISPC_VID1_PRELOAD */
1526
case 0x22c: /* DISPC_GFX_PRELOAD */
1527
TRACEDISPC("DISPC_%s_PRELOAD = 0x%08x", LAYERNAME(n), value);
1528
s->dispc.plane[n].preload = value & 0x0fff;
1531
OMAP_BAD_REGV(addr, value);
1536
static const MemoryRegionOps omap_disc_ops = {
1537
.read = omap_disc_read,
1538
.write = omap_disc_write,
1539
.endianness = DEVICE_NATIVE_ENDIAN,
1542
static uint64_t omap_rfbi_read(void *opaque, hwaddr addr,
1545
struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1548
return omap_badwidth_read32(opaque, addr);
1552
case 0x00: /* RFBI_REVISION */
1553
TRACERFBI("RFBI_REVISION: 0x10");
1556
case 0x10: /* RFBI_SYSCONFIG */
1557
TRACERFBI("RFBI_SYSCONFIG: 0x%08x", s->rfbi.idlemode);
1558
return s->rfbi.idlemode;
1560
case 0x14: /* RFBI_SYSSTATUS */
1561
TRACERFBI("RFBI_SYSSTATUS: 0x%08x", 1 | (s->rfbi.busy << 8));
1562
return 1 | (s->rfbi.busy << 8); /* RESETDONE */
1564
case 0x40: /* RFBI_CONTROL */
1565
TRACERFBI("RFBI_CONTROL: 0x%08x", s->rfbi.control);
1566
return s->rfbi.control;
1568
case 0x44: /* RFBI_PIXELCNT */
1569
TRACERFBI("RFBI_PIXELCNT: 0x%08x", s->rfbi.pixels);
1570
return s->rfbi.pixels;
1572
case 0x48: /* RFBI_LINE_NUMBER */
1573
TRACERFBI("RFBI_LINE_NUMBER: 0x%08x", s->rfbi.skiplines);
1574
return s->rfbi.skiplines;
1576
case 0x58: /* RFBI_READ */
1577
case 0x5c: /* RFBI_STATUS */
1578
TRACERFBI("RFBI_READ/STATUS: 0x%08x", s->rfbi.rxbuf);
1579
return s->rfbi.rxbuf;
1581
case 0x60: /* RFBI_CONFIG0 */
1582
TRACERFBI("RFBI_CONFIG0: 0x%08x", s->rfbi.config[0]);
1583
return s->rfbi.config[0];
1584
case 0x64: /* RFBI_ONOFF_TIME0 */
1585
TRACERFBI("RFBI_ONOFF_TIME0: 0x%08x", s->rfbi.time[0]);
1586
return s->rfbi.time[0];
1587
case 0x68: /* RFBI_CYCLE_TIME0 */
1588
TRACERFBI("RFBI_CYCLE_TIME0: 0x%08x", s->rfbi.time[1]);
1589
return s->rfbi.time[1];
1590
case 0x6c: /* RFBI_DATA_CYCLE1_0 */
1591
TRACERFBI("RFBI_DATA_CYCLE1_0: 0x%08x", s->rfbi.data[0]);
1592
return s->rfbi.data[0];
1593
case 0x70: /* RFBI_DATA_CYCLE2_0 */
1594
TRACERFBI("RFBI_DATA_CYCLE2_0: 0x%08x", s->rfbi.data[1]);
1595
return s->rfbi.data[1];
1596
case 0x74: /* RFBI_DATA_CYCLE3_0 */
1597
TRACERFBI("RFBI_DATA_CYCLE3_0: 0x%08x", s->rfbi.data[2]);
1598
return s->rfbi.data[2];
1600
case 0x78: /* RFBI_CONFIG1 */
1601
TRACERFBI("RFBI_CONFIG1: 0x%08x", s->rfbi.config[1]);
1602
return s->rfbi.config[1];
1603
case 0x7c: /* RFBI_ONOFF_TIME1 */
1604
TRACERFBI("RFBI_ONOFF_TIME1: 0x%08x", s->rfbi.time[2]);
1605
return s->rfbi.time[2];
1606
case 0x80: /* RFBI_CYCLE_TIME1 */
1607
TRACERFBI("RFBI_CYCLE_TIME1: 0x%08x", s->rfbi.time[3]);
1608
return s->rfbi.time[3];
1609
case 0x84: /* RFBI_DATA_CYCLE1_1 */
1610
TRACERFBI("RFBI_DATA_CYCLE1_1: 0x%08x", s->rfbi.data[3]);
1611
return s->rfbi.data[3];
1612
case 0x88: /* RFBI_DATA_CYCLE2_1 */
1613
TRACERFBI("RFBI_DATA_CYCLE2_1: 0x%08x", s->rfbi.data[4]);
1614
return s->rfbi.data[4];
1615
case 0x8c: /* RFBI_DATA_CYCLE3_1 */
1616
TRACERFBI("RFBI_DATA_CYCLE3_1: 0x%08x", s->rfbi.data[5]);
1617
return s->rfbi.data[5];
1619
case 0x90: /* RFBI_VSYNC_WIDTH */
1620
TRACERFBI("RFBI_VSYNC_WIDTH: 0x%08x", s->rfbi.vsync);
1621
return s->rfbi.vsync;
1622
case 0x94: /* RFBI_HSYNC_WIDTH */
1623
TRACERFBI("RFBI_HSYNC_WIDTH: 0x%08x", s->rfbi.hsync);
1624
return s->rfbi.hsync;
1630
static void omap_rfbi_write(void *opaque, hwaddr addr,
1631
uint64_t value, unsigned size)
1633
struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1636
return omap_badwidth_write32(opaque, addr, value);
1640
case 0x10: /* RFBI_SYSCONFIG */
1641
TRACERFBI("RFBI_SYSCONFIG = 0x%08x", value);
1642
if (value & 2) /* SOFTRESET */
1644
s->rfbi.idlemode = value & 0x19;
1647
case 0x40: /* RFBI_CONTROL */
1648
TRACERFBI("RFBI_CONTROL = 0x%08x", value);
1649
if (s->dispc.rev < 0x30)
1650
s->rfbi.control = value & 0x1f;
1652
s->rfbi.control = value & 0x1ff;
1653
s->rfbi.enable = value & 1;
1654
if ((s->dispc.control & 1) && /* LCDENABLE */
1655
(value & 0x10) && /* ITE */
1656
!(s->rfbi.config[0] & s->rfbi.config[1] & 0xc)) /* TRIGGERMODE */
1657
omap_rfbi_transfer_start(s);
1660
case 0x44: /* RFBI_PIXELCNT */
1661
TRACERFBI("RFBI_PIXELCNT = 0x%08x", value);
1662
s->rfbi.pixels = value;
1665
case 0x48: /* RFBI_LINE_NUMBER */
1666
TRACERFBI("RFBI_LINE_NUMBER = 0x%08x", value);
1667
s->rfbi.skiplines = value & 0x7ff;
1670
case 0x4c: /* RFBI_CMD */
1671
TRACERFBI("RFBI_CMD = 0x%08x", value);
1672
if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1673
s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
1674
if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1675
s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
1677
case 0x50: /* RFBI_PARAM */
1678
TRACERFBI("RFBI_PARAM = 0x%08x", value);
1679
if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1680
s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1681
if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1682
s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1684
case 0x54: /* RFBI_DATA */
1685
TRACERFBI("RFBI_DATA = 0x%08x", value);
1686
/* TODO: take into account the format set up in s->rfbi.config[?] and
1687
* s->rfbi.data[?], but special-case the most usual scenario so that
1688
* speed doesn't suffer. */
1689
if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
1690
s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1691
s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
1693
if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
1694
s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1695
s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
1697
if (!-- s->rfbi.pixels)
1698
omap_rfbi_transfer_stop(s);
1700
case 0x58: /* RFBI_READ */
1701
TRACERFBI("RFBI_READ = 0x%08x", value);
1702
if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1703
s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
1704
else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1705
s->rfbi.rxbuf = s->rfbi.chip[1]->read(s->rfbi.chip[1]->opaque, 1);
1706
if (!-- s->rfbi.pixels)
1707
omap_rfbi_transfer_stop(s);
1710
case 0x5c: /* RFBI_STATUS */
1711
TRACERFBI("RFBI_STATUS = 0x%08x", value);
1712
if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1713
s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
1714
else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1715
s->rfbi.rxbuf = s->rfbi.chip[1]->read(s->rfbi.chip[1]->opaque, 0);
1716
if (!-- s->rfbi.pixels)
1717
omap_rfbi_transfer_stop(s);
1720
case 0x60: /* RFBI_CONFIG0 */
1721
TRACERFBI("RFBI_CONFIG0 = 0x%08x", value);
1722
s->rfbi.config[0] = value & 0x003f1fff;
1725
case 0x64: /* RFBI_ONOFF_TIME0 */
1726
TRACERFBI("RFBI_ONOFF_TIME0 = 0x%08x", value);
1727
s->rfbi.time[0] = value & 0x3fffffff;
1729
case 0x68: /* RFBI_CYCLE_TIME0 */
1730
TRACERFBI("RFBI_CYCLE_TIME0 = 0x%08x", value);
1731
s->rfbi.time[1] = value & 0x0fffffff;
1733
case 0x6c: /* RFBI_DATA_CYCLE1_0 */
1734
TRACERFBI("RFBI_DATA_CYCLE1_0 = 0x%08x", value);
1735
s->rfbi.data[0] = value & 0x0f1f0f1f;
1737
case 0x70: /* RFBI_DATA_CYCLE2_0 */
1738
TRACERFBI("RFBI_DATA_CYCLE2_0 = 0x%08x", value);
1739
s->rfbi.data[1] = value & 0x0f1f0f1f;
1741
case 0x74: /* RFBI_DATA_CYCLE3_0 */
1742
TRACERFBI("RFBI_DATA_CYCLE3_0 = 0x%08x", value);
1743
s->rfbi.data[2] = value & 0x0f1f0f1f;
1745
case 0x78: /* RFBI_CONFIG1 */
1746
TRACERFBI("RFBI_CONFIG1 = 0x%08x", value);
1747
s->rfbi.config[1] = value & 0x003f1fff;
1750
case 0x7c: /* RFBI_ONOFF_TIME1 */
1751
TRACERFBI("RFBI_ONOFF_TIME1 = 0x%08x", value);
1752
s->rfbi.time[2] = value & 0x3fffffff;
1754
case 0x80: /* RFBI_CYCLE_TIME1 */
1755
TRACERFBI("RFBI_CYCLE_TIME1 = 0x%08x", value);
1756
s->rfbi.time[3] = value & 0x0fffffff;
1758
case 0x84: /* RFBI_DATA_CYCLE1_1 */
1759
TRACERFBI("RFBI_DATA_CYCLE1_1 = 0x%08x", value);
1760
s->rfbi.data[3] = value & 0x0f1f0f1f;
1762
case 0x88: /* RFBI_DATA_CYCLE2_1 */
1763
TRACERFBI("RFBI_DATA_CYCLE2_1 = 0x%08x", value);
1764
s->rfbi.data[4] = value & 0x0f1f0f1f;
1766
case 0x8c: /* RFBI_DATA_CYCLE3_1 */
1767
TRACERFBI("RFBI_DATA_CYCLE3_1 = 0x%08x", value);
1768
s->rfbi.data[5] = value & 0x0f1f0f1f;
1771
case 0x90: /* RFBI_VSYNC_WIDTH */
1772
TRACERFBI("RFBI_VSYNC_WIDTH = 0x%08x", value);
1773
s->rfbi.vsync = value & 0xffff;
1775
case 0x94: /* RFBI_HSYNC_WIDTH */
1776
TRACERFBI("RFBI_HSYNC_WIDTH = 0x%08x", value);
1777
s->rfbi.hsync = value & 0xffff;
1781
OMAP_BAD_REGV(addr, value);
1786
static const MemoryRegionOps omap_rfbi_ops = {
1787
.read = omap_rfbi_read,
1788
.write = omap_rfbi_write,
1789
.endianness = DEVICE_NATIVE_ENDIAN,
1792
static uint64_t omap_venc_read(void *opaque, hwaddr addr,
1796
return omap_badwidth_read32(opaque, addr);
1800
case 0x00: /* REV_ID */
1802
case 0x04: /* STATUS */
1803
case 0x08: /* F_CONTROL */
1804
case 0x10: /* VIDOUT_CTRL */
1805
case 0x14: /* SYNC_CTRL */
1806
case 0x1c: /* LLEN */
1807
case 0x20: /* FLENS */
1808
case 0x24: /* HFLTR_CTRL */
1809
case 0x28: /* CC_CARR_WSS_CARR */
1810
case 0x2c: /* C_PHASE */
1811
case 0x30: /* GAIN_U */
1812
case 0x34: /* GAIN_V */
1813
case 0x38: /* GAIN_Y */
1814
case 0x3c: /* BLACK_LEVEL */
1815
case 0x40: /* BLANK_LEVEL */
1816
case 0x44: /* X_COLOR */
1817
case 0x48: /* M_CONTROL */
1818
case 0x4c: /* BSTAMP_WSS_DATA */
1819
case 0x50: /* S_CARR */
1820
case 0x54: /* LINE21 */
1821
case 0x58: /* LN_SEL */
1822
case 0x5c: /* L21__WC_CTL */
1823
case 0x60: /* HTRIGGER_VTRIGGER */
1824
case 0x64: /* SAVID__EAVID */
1825
case 0x68: /* FLEN__FAL */
1826
case 0x6c: /* LAL__PHASE_RESET */
1827
case 0x70: /* HS_INT_START_STOP_X */
1828
case 0x74: /* HS_EXT_START_STOP_X */
1829
case 0x78: /* VS_INT_START_X */
1830
case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */
1831
case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */
1832
case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */
1833
case 0x88: /* VS_EXT_STOP_Y */
1834
case 0x90: /* AVID_START_STOP_X */
1835
case 0x94: /* AVID_START_STOP_Y */
1836
case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */
1837
case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1838
case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1839
case 0xb0: /* TVDETGP_INT_START_STOP_X */
1840
case 0xb4: /* TVDETGP_INT_START_STOP_Y */
1841
case 0xb8: /* GEN_CTRL */
1842
case 0xc4: /* DAC_TST__DAC_A */
1843
case 0xc8: /* DAC_B__DAC_C */
1852
static void omap_venc_write(void *opaque, hwaddr addr,
1853
uint64_t value, unsigned size)
1856
return omap_badwidth_write32(opaque, addr, size);
1860
case 0x00: /* REV_ID */
1861
case 0x04: /* STATUS */
1862
/* read-only, ignore */
1864
case 0x08: /* F_CONTROL */
1865
case 0x10: /* VIDOUT_CTRL */
1866
case 0x14: /* SYNC_CTRL */
1867
case 0x1c: /* LLEN */
1868
case 0x20: /* FLENS */
1869
case 0x24: /* HFLTR_CTRL */
1870
case 0x28: /* CC_CARR_WSS_CARR */
1871
case 0x2c: /* C_PHASE */
1872
case 0x30: /* GAIN_U */
1873
case 0x34: /* GAIN_V */
1874
case 0x38: /* GAIN_Y */
1875
case 0x3c: /* BLACK_LEVEL */
1876
case 0x40: /* BLANK_LEVEL */
1877
case 0x44: /* X_COLOR */
1878
case 0x48: /* M_CONTROL */
1879
case 0x4c: /* BSTAMP_WSS_DATA */
1880
case 0x50: /* S_CARR */
1881
case 0x54: /* LINE21 */
1882
case 0x58: /* LN_SEL */
1883
case 0x5c: /* L21__WC_CTL */
1884
case 0x60: /* HTRIGGER_VTRIGGER */
1885
case 0x64: /* SAVID__EAVID */
1886
case 0x68: /* FLEN__FAL */
1887
case 0x6c: /* LAL__PHASE_RESET */
1888
case 0x70: /* HS_INT_START_STOP_X */
1889
case 0x74: /* HS_EXT_START_STOP_X */
1890
case 0x78: /* VS_INT_START_X */
1891
case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */
1892
case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */
1893
case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */
1894
case 0x88: /* VS_EXT_STOP_Y */
1895
case 0x90: /* AVID_START_STOP_X */
1896
case 0x94: /* AVID_START_STOP_Y */
1897
case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */
1898
case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1899
case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1900
case 0xb0: /* TVDETGP_INT_START_STOP_X */
1901
case 0xb4: /* TVDETGP_INT_START_STOP_Y */
1902
case 0xb8: /* GEN_CTRL */
1903
case 0xc4: /* DAC_TST__DAC_A */
1904
case 0xc8: /* DAC_B__DAC_C */
1907
OMAP_BAD_REGV(addr, value);
1912
static const MemoryRegionOps omap_venc_ops = {
1913
.read = omap_venc_read,
1914
.write = omap_venc_write,
1915
.endianness = DEVICE_NATIVE_ENDIAN,
1918
static uint64_t omap_im3_read(void *opaque, hwaddr addr,
1922
return omap_badwidth_read32(opaque, addr);
1926
case 0x0a8: /* SBIMERRLOGA */
1927
case 0x0b0: /* SBIMERRLOG */
1928
case 0x190: /* SBIMSTATE */
1929
case 0x198: /* SBTMSTATE_L */
1930
case 0x19c: /* SBTMSTATE_H */
1931
case 0x1a8: /* SBIMCONFIG_L */
1932
case 0x1ac: /* SBIMCONFIG_H */
1933
case 0x1f8: /* SBID_L */
1934
case 0x1fc: /* SBID_H */
1944
static void omap_im3_write(void *opaque, hwaddr addr,
1945
uint64_t value, unsigned size)
1948
return omap_badwidth_write32(opaque, addr, value);
1952
case 0x0b0: /* SBIMERRLOG */
1953
case 0x190: /* SBIMSTATE */
1954
case 0x198: /* SBTMSTATE_L */
1955
case 0x19c: /* SBTMSTATE_H */
1956
case 0x1a8: /* SBIMCONFIG_L */
1957
case 0x1ac: /* SBIMCONFIG_H */
1961
OMAP_BAD_REGV(addr, value);
1966
static const MemoryRegionOps omap_im3_ops = {
1967
.read = omap_im3_read,
1968
.write = omap_im3_write,
1969
.endianness = DEVICE_NATIVE_ENDIAN,
1972
static void omap_dsi_push_rx_fifo(struct omap_dss_s *s, int ch, uint32_t value)
1976
if (s->dsi.vc[ch].rx_fifo_len < OMAP_DSI_RX_FIFO_SIZE) {
1977
p = s->dsi.vc[ch].rx_fifo_pos + s->dsi.vc[ch].rx_fifo_len;
1978
if (p >= OMAP_DSI_RX_FIFO_SIZE)
1979
p -= OMAP_DSI_RX_FIFO_SIZE;
1980
s->dsi.vc[ch].rx_fifo[p] = value;
1981
s->dsi.vc[ch].rx_fifo_len++;
1983
TRACEDSI("vc%d rx fifo overflow!", ch);
1987
static uint32_t omap_dsi_pull_rx_fifo(struct omap_dss_s *s, int ch)
1991
if (!s->dsi.vc[ch].rx_fifo_len) {
1992
TRACEDSI("vc%d rx fifo underflow!", ch);
1994
v = s->dsi.vc[ch].rx_fifo[s->dsi.vc[ch].rx_fifo_pos++];
1995
s->dsi.vc[ch].rx_fifo_len--;
1996
if (s->dsi.vc[ch].rx_fifo_pos >= OMAP_DSI_RX_FIFO_SIZE)
1997
s->dsi.vc[ch].rx_fifo_pos = 0;
2003
static uint32_t omap_dsi_read(void *opaque, hwaddr addr)
2005
struct omap_dss_s *s = (struct omap_dss_s *)opaque;
2009
case 0x000: /* DSI_REVISION */
2010
TRACEDSI("DSI_REVISION = 0x10");
2012
case 0x010: /* DSI_SYSCONFIG */
2013
TRACEDSI("DSI_SYSCONFIG = 0x%04x", s->dsi.sysconfig);
2014
return s->dsi.sysconfig;
2015
case 0x014: /* DSI_SYSSTATUS */
2016
TRACEDSI("DSI_SYSSTATUS = 0x01");
2017
return 1; /* RESET_DONE */
2018
case 0x018: /* DSI_IRQSTATUS */
2019
TRACEDSI("DSI_IRQSTATUS = 0x%08x", s->dsi.irqst);
2020
return s->dsi.irqst;
2021
case 0x01c: /* DSI_IRQENABLE */
2022
TRACEDSI("DSI_IRQENABLE = 0x%08x", s->dsi.irqen);
2023
return s->dsi.irqen;
2024
case 0x040: /* DSI_CTRL */
2025
TRACEDSI("DSI_CTRL = 0x%08x", s->dsi.ctrl);
2027
case 0x048: /* DSI_COMPLEXIO_CFG1 */
2028
TRACEDSI("DSI_COMPLEXIO_CFG1 = 0x%08x", s->dsi.complexio_cfg1);
2029
return s->dsi.complexio_cfg1;
2030
case 0x04c: /* DSI_COMPLEXIO_IRQSTATUS */
2031
TRACEDSI("DSI_COMPLEXIO_IRQSTATUS = 0x%08x", s->dsi.complexio_irqst);
2032
return s->dsi.complexio_irqst;
2033
case 0x050: /* DSI_COMPLEXIO_IRQENABLE */
2034
TRACEDSI("DSI_COMPLEXIO_IRQENABLE = 0x%08x", s->dsi.complexio_irqen);
2035
return s->dsi.complexio_irqen;
2036
case 0x054: /* DSI_CLK_CTRL */
2037
TRACEDSI("DSI_CLK_CTRL = 0x%08x", s->dsi.clk_ctrl);
2038
return s->dsi.clk_ctrl;
2039
case 0x058: /* DSI_TIMING1 */
2040
TRACEDSI("DSI_TIMING1 = 0x%08x", s->dsi.timing1);
2041
return s->dsi.timing1;
2042
case 0x05c: /* DSI_TIMING2 */
2043
TRACEDSI("DSI_TIMING2 = 0x%08x", s->dsi.timing2);
2044
return s->dsi.timing2;
2045
case 0x060: /* DSI_VM_TIMING1 */
2046
TRACEDSI("DSI_VM_TIMING1 = 0x%08x", s->dsi.vm_timing1);
2047
return s->dsi.vm_timing1;
2048
case 0x064: /* DSI_VM_TIMING2 */
2049
TRACEDSI("DSI_VM_TIMING2 = 0x%08x", s->dsi.vm_timing2);
2050
return s->dsi.vm_timing2;
2051
case 0x068: /* DSI_VM_TIMING3 */
2052
TRACEDSI("DSI_VM_TIMING3 = 0x%08x", s->dsi.vm_timing3);
2053
return s->dsi.vm_timing3;
2054
case 0x06c: /* DSI_CLK_TIMING */
2055
TRACEDSI("DSI_CLK_TIMING = 0x%08x", s->dsi.clk_timing);
2056
return s->dsi.clk_timing;
2057
case 0x070: /* DSI_TX_FIFO_VC_SIZE */
2058
TRACEDSI("DSI_TX_FIFO_VC_SIZE = 0x%08x", s->dsi.tx_fifo_vc_size);
2059
return s->dsi.tx_fifo_vc_size;
2060
case 0x074: /* DSI_RX_FIFO_VC_SIZE */
2061
TRACEDSI("DSI_RX_FIFO_VC_SIZE = 0x%08x", s->dsi.rx_fifo_vc_size);
2062
return s->dsi.rx_fifo_vc_size;
2063
case 0x078: /* DSI_COMPLEXIO_CFG_2 */
2064
TRACEDSI("DSI_COMPLEXIO_CFG_2 = 0x%08x", s->dsi.complexio_cfg2);
2065
return s->dsi.complexio_cfg2;
2066
case 0x07c: /* DSI_RX_FIFO_VC_FULLNESS */
2067
TRACEDSI("DSI_RX_FIFO_VC_FULLNESS = 0x00");
2069
case 0x080: /* DSI_VM_TIMING4 */
2070
TRACEDSI("DSI_VM_TIMING4 = 0x%08x", s->dsi.vm_timing4);
2071
return s->dsi.vm_timing4;
2072
case 0x084: /* DSI_TX_FIFO_VC_EMPTINESS */
2073
TRACEDSI("DSI_TX_FIFO_VC_EMPTINESS = 0x7f7f7f7f");
2075
case 0x088: /* DSI_VM_TIMING5 */
2076
TRACEDSI("DSI_VM_TIMING5 = 0x%08x", s->dsi.vm_timing5);
2077
return s->dsi.vm_timing5;
2078
case 0x08c: /* DSI_VM_TIMING6 */
2079
TRACEDSI("DSI_VM_TIMING6 = 0x%08x", s->dsi.vm_timing6);
2080
return s->dsi.vm_timing6;
2081
case 0x090: /* DSI_VM_TIMING7 */
2082
TRACEDSI("DSI_VM_TIMING7 = 0x%08x", s->dsi.vm_timing7);
2083
return s->dsi.vm_timing7;
2084
case 0x094: /* DSI_STOPCLK_TIMING */
2085
TRACEDSI("DSI_STOPCLK_TIMING = 0x%08x", s->dsi.stopclk_timing);
2086
return s->dsi.stopclk_timing;
2087
case 0x100 ... 0x17c: /* DSI_VCx_xxx */
2088
x = (addr >> 5) & 3;
2089
switch (addr & 0x1f) {
2090
case 0x00: /* DSI_VCx_CTRL */
2091
TRACEDSI("DSI_VC%d_CTRL = 0x%08x", x, s->dsi.vc[x].ctrl);
2092
return s->dsi.vc[x].ctrl;
2093
case 0x04: /* DSI_VCx_TE */
2094
TRACEDSI("DSI_VC%d_TE = 0x%08x", x, s->dsi.vc[x].te);
2095
return s->dsi.vc[x].te;
2096
case 0x08: /* DSI_VCx_LONG_PACKET_HEADER */
2098
TRACEDSI("DSI_VC%d_LONG_PACKET_HEADER = 0", x);
2100
case 0x0c: /* DSI_VCx_LONG_PACKET_PAYLOAD */
2102
TRACEDSI("DSI_VC%d_LONG_PACKET_PAYLOAD = 0", x);
2104
case 0x10: /* DSI_VCx_SHORT_PACKET_HEADER */
2105
if (s->dsi.vc[x].ctrl & (1 << 20)) { /* RX_FIFO_NOT_EMPTY */
2106
y = omap_dsi_pull_rx_fifo(s, x);
2107
TRACEDSI("DSI_VC%d_SHORT_PACKET_HEADER = 0x%08x", x, y);
2108
if (!s->dsi.vc[x].rx_fifo_len)
2109
s->dsi.vc[x].ctrl &= ~(1 << 20); /* RX_FIFO_NOT_EMPTY */
2112
TRACEDSI("vc%d rx fifo underflow!", x);
2114
case 0x18: /* DSI_VCx_IRQSTATUS */
2115
TRACEDSI("DSI_VC%d_IRQSTATUS = 0x%08x", x, s->dsi.vc[x].irqst);
2116
return s->dsi.vc[x].irqst;
2117
case 0x1c: /* DSI_VCx_IRQENABLE */
2118
TRACEDSI("DSI_VC%d_IRQENABLE = 0x%08x", x, s->dsi.vc[x].irqen);
2119
return s->dsi.vc[x].irqen;
2124
case 0x200: /* DSI_PHY_CFG0 */
2125
TRACEDSI("DSI_PHY_CFG0 = 0x%08x", s->dsi.phy_cfg0);
2126
return s->dsi.phy_cfg0;
2127
case 0x204: /* DSI_PHY_CFG1 */
2128
TRACEDSI("DSI_PHY_CFG1 = 0x%08x", s->dsi.phy_cfg1);
2129
return s->dsi.phy_cfg1;
2130
case 0x208: /* DSI_PHY_CFG2 */
2131
TRACEDSI("DSI_PHY_CFG2 = 0x%08x", s->dsi.phy_cfg2);
2132
return s->dsi.phy_cfg2;
2133
case 0x214: /* DSI_PHY_CFG5 */
2134
TRACEDSI("DSI_PHY_CFG5 = 0xfc000000");
2135
return 0xfc000000; /* all resets done */
2136
case 0x300: /* DSI_PLL_CONTROL */
2137
TRACEDSI("DSI_PLL_CONTROL = 0x%08x", s->dsi.pll_control);
2138
return s->dsi.pll_control;
2139
case 0x304: /* DSI_PLL_STATUS */
2140
x = 1; /* DSI_PLLCTRL_RESET_DONE */
2141
if ((s->dsi.clk_ctrl >> 28) & 3) { /* DSI PLL control powered? */
2142
if (((s->dsi.pll_config1 >> 1) & 0x7f) && /* DSI_PLL_REGN */
2143
((s->dsi.pll_config1 >> 8) & 0x7ff)) { /* DSI_PLL_REGM */
2144
x |= 2; /* DSI_PLL_LOCK */
2147
if ((s->dsi.pll_config2 >> 20) & 1) /* DSI_HSDIVBYPASS */
2148
x |= (1 << 9); /* DSI_BYPASSACKZ */
2149
if ((s->dsi.pll_config2 >> 18) & 1) /* DSI_PROTO_CLOCK_EN */
2150
x |= (1 << 8); /* DSIPROTO_CLOCK_ACK */
2151
if ((s->dsi.pll_config2 >> 16) & 1) /* DSS_CLOCK_EN */
2152
x |= (1 << 7); /* DSS_CLOCK_ACK */
2153
if (!((s->dsi.pll_config2 >> 13) & 1)) /* DSI_PLL_REFEN */
2154
x |= (1 << 3); /* DSI_PLL_LOSSREF */
2155
TRACEDSI("DSI_PLL_STATUS = 0x%08x", x);
2157
case 0x308: /* DSI_PLL_GO */
2158
TRACEDSI("DSI_PLL_GO = 0x%08x", s->dsi.pll_go);
2159
return s->dsi.pll_go;
2160
case 0x30c: /* DSI_PLL_CONFIGURATION1 */
2161
TRACEDSI("DSI_PLL_CONFIGURATION1 = 0x%08x", s->dsi.pll_config1);
2162
return s->dsi.pll_config1;
2163
case 0x310: /* DSI_PLL_CONFIGURATION2 */
2164
TRACEDSI("DSI_PLL_CONFIGURATION2 = 0x%08x", s->dsi.pll_config2);
2165
return s->dsi.pll_config2;
2173
static void omap_dsi_txdone(struct omap_dss_s *s, int ch, int bta)
2176
s->dsi.vc[ch].irqst |= 0x20; /* BTA_IRQ */
2177
if (s->dsi.vc[ch].rx_fifo_len)
2178
s->dsi.vc[ch].ctrl |= 1 << 20; /* RX_FIFO_NOT_EMPTY */
2180
s->dsi.vc[ch].irqst |= 0x04; /* PACKET_SENT_IRQ */
2182
s->dsi.irqst |= 1 << ch; /* VIRTUAL_CHANNELx_IRQ */
2183
omap_dss_interrupt_update(s);
2186
static void omap_dsi_short_write(struct omap_dss_s *s, int ch)
2188
uint32_t data = s->dsi.vc[ch].sp_header;
2190
if (((data >> 6) & 0x03) != ch) {
2191
TRACEDSI("error - vc%d != %d", ch, (data >> 6) & 0x03);
2193
data = dsi_short_write(s->dsi.host, data);
2194
/* responses cannot be all-zero so it is safe to use that
2195
* as a no-reply value */
2197
omap_dsi_push_rx_fifo(s, ch, data);
2199
omap_dsi_txdone(s, ch, (s->dsi.vc[ch].ctrl & 0x04)); /* BTA_SHORT_EN */
2203
static void omap_dsi_long_write(struct omap_dss_s *s, int ch)
2205
uint32_t hdr = s->dsi.vc[ch].lp_header;
2207
/* TODO: implement packet footer sending (16bit checksum).
2208
* Currently none is sent and receiver is supposed to not expect one */
2209
if (((hdr >> 6) & 0x03) != ch) {
2210
TRACEDSI("error - vc%d != %d", ch, (hdr >> 6) & 0x03);
2212
dsi_long_write(s->dsi.host, hdr, s->dsi.vc[ch].lp_payload,
2213
s->dsi.vc[ch].lp_counter);
2214
if ((s->dsi.vc[ch].te >> 30) & 3) { /* TE_START | TE_EN */
2215
/* TODO: do we really need to implement something for this?
2216
* Should writes decrease the TE_SIZE counter, for example?
2217
* For now, the TE transfers are completed immediately */
2219
if (s->dsi.vc[ch].lp_counter > 0)
2220
s->dsi.vc[ch].lp_counter -= 4;
2221
if (s->dsi.vc[ch].lp_counter <= 0)
2222
omap_dsi_txdone(s, ch, (s->dsi.vc[ch].ctrl & 0x08)); /* BTA_LONG_EN */
2227
static void omap_dsi_write(void *opaque, hwaddr addr,
2230
struct omap_dss_s *s = (struct omap_dss_s *)opaque;
2234
case 0x000: /* DSI_REVISION */
2235
case 0x014: /* DSI_SYSSTATUS */
2236
case 0x07c: /* DSI_RX_FIFO_VC_FULLNESS */
2237
case 0x084: /* DSI_RX_FIFO_VC_EMPTINESS */
2238
case 0x214: /* DSI_PHY_CFG5 */
2239
case 0x304: /* DSI_PLL_STATUS */
2240
/* read-only, ignore */
2242
case 0x010: /* DSI_SYSCONFIG */
2243
TRACEDSI("DSI_SYSCONFIG = 0x%08x", value);
2244
if (value & 2) /* SOFT_RESET */
2247
s->dsi.sysconfig = value;
2249
case 0x018: /* DSI_IRQSTATUS */
2250
TRACEDSI("DSI_IRQSTATUS = 0x%08x", value);
2251
s->dsi.irqst &= ~(value & 0x1fc3b0);
2252
omap_dss_interrupt_update(s);
2254
case 0x01c: /* DSI_IRQENABLE */
2255
TRACEDSI("DSI_IRQENABLE = 0x%08x", value);
2256
s->dsi.irqen = value & 0x1fc3b0;
2257
omap_dss_interrupt_update(s);
2259
case 0x040: /* DSI_CTRL */
2260
TRACEDSI("DSI_CTRL = 0x%08x", value);
2261
s->dsi.ctrl = value & 0x7ffffff;
2263
case 0x048: /* DSI_COMPLEXIO_CFG_1 */
2264
TRACEDSI("DSI_COMPLEXIO_CFG1 = 0x%08x", value);
2265
value |= 1 << 29; /* RESET_DONE */
2266
value |= 1 << 21; /* LDO_POWER_GOOD_STATE */
2267
value &= ~(1 << 30); /* GOBIT */
2268
/* copy PWR_CMD directly to PWR_STATUS */
2269
value &= ~(3 << 25);
2270
value |= (value >> 2) & (3 << 25);
2271
/* TODO: notify screen refresh control about PWR_STATUS */
2272
s->dsi.complexio_cfg1 = value;
2274
case 0x04c: /* DSI_COMPLEXIO_IRQSTATUS */
2275
TRACEDSI("DSI_COMPLEXIO_IRQSTATUS = 0x%08x", value);
2276
s->dsi.complexio_irqst &= ~(value & 0xc3f39ce7);
2277
if (s->dsi.complexio_irqst & s->dsi.complexio_irqen)
2278
s->dsi.irqst |= (1 << 10); /* COMPLEXIO_ERR_IRQ */
2280
s->dsi.irqst &= ~(1 << 10); /* COMPLEXIO_ERR_IRQ */
2281
omap_dss_interrupt_update(s);
2283
case 0x050: /* DSI_COMPLEXIO_IRQENABLE */
2284
TRACEDSI("DSI_COMPLEXIO_IRQENABLE = 0x%08x", value);
2285
s->dsi.complexio_irqen = value & 0xc3f39ce7;
2286
omap_dss_interrupt_update(s);
2288
case 0x054: /* DSI_CLK_CTRL */
2289
TRACEDSI("DSI_CLK_CTRL = 0x%08x", value);
2290
value &= 0xc03fffff;
2291
/* copy PLL_PWR_CMD directly to PLL_PWR_STATUS */
2292
value |= (value >> 2) & (3 << 28);
2293
s->dsi.clk_ctrl = value;
2295
case 0x058: /* DSI_TIMING1 */
2296
TRACEDSI("DSI_TIMING1 = 0x%08x", value);
2297
value &= ~(1 << 15); /* deassert ForceTxStopMode signal */
2298
s->dsi.timing1 = value;
2300
case 0x05c: /* DSI_TIMING2 */
2301
TRACEDSI("DSI_TIMING2 = 0x%08x", value);
2302
s->dsi.timing2 = value;
2304
case 0x060: /* DSI_VM_TIMING1 */
2305
TRACEDSI("DSI_VM_TIMING1 = 0x%08x", value);
2306
s->dsi.vm_timing1 = value;
2308
case 0x064: /* DSI_VM_TIMING2 */
2309
TRACEDSI("DSI_VM_TIMING2 = 0x%08x", value);
2310
s->dsi.vm_timing2 = value & 0x0fffffff;
2312
case 0x068: /* DSI_VM_TIMING3 */
2313
TRACEDSI("DSI_VM_TIMING3 = 0x%08x", value);
2314
s->dsi.vm_timing3 = value;
2316
case 0x06c: /* DSI_CLK_TIMING */
2317
TRACEDSI("DSI_CLK_TIMING = 0x%08x", value);
2318
s->dsi.clk_timing = value & 0xffff;
2320
case 0x070: /* DSI_TX_FIFO_VC_SIZE */
2321
TRACEDSI("DSI_TX_FIFO_VC_SIZE = 0x%08x", value);
2322
s->dsi.tx_fifo_vc_size = value & 0xf7f7f7f7;
2324
case 0x074: /* DSI_RX_FIFO_VC_SIZE */
2325
TRACEDSI("DSI_RX_FIFO_VC_SIZE = 0x%08x", value);
2326
s->dsi.rx_fifo_vc_size = value & 0xf7f7f7f7;
2328
case 0x078: /* DSI_COMPLEXIO_CFG_2 */
2329
TRACEDSI("DSI_COMPLEXIO_CFG_2 = 0x%08x", value);
2330
s->dsi.complexio_cfg2 = (value & 0xfffcffff)
2331
| (s->dsi.complexio_cfg2 & (3 << 16));
2333
case 0x080: /* DSI_VM_TIMING4 */
2334
TRACEDSI("DSI_VM_TIMING4 = 0x%08x", value);
2335
s->dsi.vm_timing4 = value;
2337
case 0x088: /* DSI_VM_TIMING5 */
2338
TRACEDSI("DSI_VM_TIMING5 = 0x%08x", value);
2339
s->dsi.vm_timing5 = value;
2341
case 0x08c: /* DSI_VM_TIMING6 */
2342
TRACEDSI("DSI_VM_TIMING6 = 0x%08x", value);
2343
s->dsi.vm_timing6 = value;
2345
case 0x090: /* DSI_VM_TIMING7 */
2346
TRACEDSI("DSI_VM_TIMING7 = 0x%08x", value);
2347
s->dsi.vm_timing7 = value;
2349
case 0x094: /* DSI_STOPCLK_TIMING */
2350
TRACEDSI("DSI_STOPCLK_TIMING = 0x%08x", value);
2351
s->dsi.stopclk_timing = value & 0xff;
2353
case 0x100 ... 0x17c: /* DSI_VCx_xxx */
2354
x = (addr >> 5) & 3;
2355
switch (addr & 0x1f) {
2356
case 0x00: /* DSI_VCx_CTRL */
2357
TRACEDSI("DSI_VC%d_CTRL = 0x%08x", x, value);
2358
if (((value >> 27) & 7) != 4) /* DMA_RX_REQ_NB */
2359
hw_error("%s: RX DMA mode not implemented", __FUNCTION__);
2360
if (((value >> 21) & 7) != 4) /* DMA_TX_REQ_NB */
2361
hw_error("%s: TX DMA mode not implemented", __FUNCTION__);
2362
if (value & 1) { /* VC_EN */
2363
s->dsi.vc[x].ctrl &= ~0x40; /* BTA_EN */
2364
s->dsi.vc[x].ctrl |= 0x8001; /* VC_BUSY | VC_EN */
2366
/* clear VC_BUSY and VC_EN, assign writable bits */
2367
s->dsi.vc[x].ctrl = (s->dsi.vc[x].ctrl & 0x114020) |
2368
(value & 0x3fee039f);
2370
if (value & 0x40) /* BTA_EN */
2371
omap_dsi_txdone(s, x, 1);
2373
case 0x04: /* DSI_VCx_TE */
2374
TRACEDSI("DSI_VC%d_TE = 0x%08x", x, value);
2375
value &= 0xc0ffffff;
2376
/* according to the OMAP3 TRM the TE_EN bit in this
2377
* register is protected by VCx_CTRL VC_EN bit but
2378
* let's forget that */
2379
s->dsi.vc[x].te = value;
2380
if (s->dispc.control & 1) /* LCDENABLE */
2381
omap_dsi_transfer_start(s, x);
2383
case 0x08: /* DSI_VCx_LONG_PACKET_HEADER */
2384
TRACEDSI("DSI_VC%d_LONG_PACKET_HEADER id=0x%02x, len=0x%04x, ecc=0x%02x",
2385
x, value & 0xff, (value >> 8) & 0xffff, (value >> 24) & 0xff);
2386
s->dsi.vc[x].lp_header = value;
2387
s->dsi.vc[x].lp_counter = (value >> 8) & 0xffff;
2389
case 0x0c: /* DSI_VCx_LONG_PACKET_PAYLOAD */
2390
TRACEDSI("DSI_VC%d_LONG_PACKET_PAYLOAD = 0x%08x", x, value);
2391
s->dsi.vc[x].lp_payload = value;
2392
if ((s->dsi.vc[x].te >> 30) & 3) { /* TE_START | TE_EN */
2393
int tx_dma = (s->dsi.vc[x].ctrl >> 21) & 7; /* DMA_TX_REQ_NB */
2395
qemu_irq_lower(s->dsi.drq[tx_dma]);
2397
omap_dsi_long_write(s, x);
2399
case 0x10: /* DSI_VCx_SHORT_PACKET_HEADER */
2400
TRACEDSI("DSI_VC%d_SHORT_PACKET_HEADER = 0x%08x", x, value);
2401
s->dsi.vc[x].sp_header = value;
2402
omap_dsi_short_write(s, x);
2404
case 0x18: /* DSI_VCx_IRQSTATUS */
2405
TRACEDSI("DSI_VC%d_IRQSTATUS = 0x%08x", x, value);
2406
s->dsi.vc[x].irqst &= ~(value & 0x1ff);
2407
if (s->dsi.vc[x].irqst & s->dsi.vc[x].irqen)
2408
s->dsi.irqst |= 1 << x; /* VIRTUAL_CHANNELx_IRQ */
2410
s->dsi.irqst &= ~(1 << x); /* VIRTUAL_CHANNELx_IRQ */
2411
omap_dss_interrupt_update(s);
2413
case 0x1c: /* DSI_VCx_IRQENABLE */
2414
TRACEDSI("DSI_VC%d_IRQENABLE = 0x%08x", x, value);
2415
s->dsi.vc[x].irqen = value & 0x1ff;
2416
omap_dss_interrupt_update(s);
2419
OMAP_BAD_REGV(addr, value);
2423
case 0x200: /* DSI_PHY_CFG0 */
2424
TRACEDSI("DSI_PHY_CFG0 = 0x%08x", value);
2425
s->dsi.phy_cfg0 = value;
2427
case 0x204: /* DSI_PHY_CFG1 */
2428
TRACEDSI("DSI_PHY_CFG1 = 0x%08x", value);
2429
s->dsi.phy_cfg1 = value;
2431
case 0x208: /* DSI_PHY_CFG2 */
2432
TRACEDSI("DSI_PHY_CFG2 = 0x%08x", value);
2433
if (s->mpu_model >= omap3630) {
2434
value &= 0xff0000ff;
2436
s->dsi.phy_cfg2 = value;
2438
case 0x300: /* DSI_PLL_CONTROL */
2439
TRACEDSI("DSI_PLL_CONTROL = 0x%08x", value);
2440
s->dsi.pll_control = value & 0x1f;
2442
case 0x308: /* DSI_PLL_GO */
2443
TRACEDSI("DSI_PLL_GO = 0x%08x", value);
2444
/* TODO: check if we need to update something here */
2445
value &= ~1; /* mark it done */
2446
s->dsi.pll_go = value & 1;
2448
case 0x30c: /* DSI_PLL_CONFIGURATION1 */
2449
TRACEDSI("DSI_PLL_CONFIGURATION1 = 0x%08x", value);
2450
s->dsi.pll_config1 = value & 0x7ffffff;
2452
case 0x310: /* DSI_PLL_CONFIGURATION2 */
2453
TRACEDSI("DSI_PLL_CONFIGURATION2 = 0x%08x", value);
2454
if (s->mpu_model < omap3630) {
2459
s->dsi.pll_config2 = value;
2462
OMAP_BAD_REGV(addr, value);
2467
static const MemoryRegionOps omap_dsi_ops = {
2470
omap_badwidth_read32,
2471
omap_badwidth_read32,
2475
omap_badwidth_write32,
2476
omap_badwidth_write32,
2480
.endianness = DEVICE_NATIVE_ENDIAN,
2483
static int omap_dss_init(SysBusDevice *dev)
2485
struct omap_dss_s *s = FROM_SYSBUS(struct omap_dss_s, dev);
2486
sysbus_init_irq(dev, &s->irq);
2487
sysbus_init_irq(dev, &s->drq); /* linetrigger */
2489
memory_region_init_io(&s->iomem_diss1, &omap_diss_ops, s,
2490
"omap.diss1", 0x400);
2491
memory_region_init_io(&s->iomem_disc1, &omap_disc_ops, s,
2492
"omap.disc1", 0x400);
2493
memory_region_init_io(&s->iomem_rfbi1, &omap_rfbi_ops, s,
2494
"omap.rfbi1", 0x400);
2495
memory_region_init_io(&s->iomem_venc1, &omap_venc_ops, s,
2496
"omap.venc1", 0x400);
2497
sysbus_init_mmio(dev, &s->iomem_diss1);
2498
sysbus_init_mmio(dev, &s->iomem_disc1);
2499
sysbus_init_mmio(dev, &s->iomem_rfbi1);
2500
sysbus_init_mmio(dev, &s->iomem_venc1);
2502
if (s->mpu_model < omap2410) {
2503
hw_error("%s: unsupported cpu type\n", __FUNCTION__);
2504
} else if (s->mpu_model < omap3430) {
2505
s->dispc.rev = 0x20;
2506
memory_region_init_io(&s->iomem_im3, &omap_im3_ops, s,
2507
"omap.im3", 0x1000);
2508
sysbus_init_mmio(dev, &s->iomem_im3);
2510
s->dispc.rev = 0x30;
2511
s->dispc.lcdframer = qemu_new_timer_ns(vm_clock, omap_dss_framedone, s);
2512
s->dsi.host = dsi_init_host(&dev->qdev, "omap3_dsi",
2513
omap_dsi_te_trigger,
2515
s->dsi.xfer_timer = qemu_new_timer_ns(vm_clock, omap_dsi_transfer_stop,
2517
memory_region_init_io(&s->iomem_dsi, &omap_dsi_ops, s,
2519
sysbus_init_mmio(dev, &s->iomem_dsi);
2520
sysbus_init_irq(dev, &s->dsi.drq[0]);
2521
sysbus_init_irq(dev, &s->dsi.drq[1]);
2522
sysbus_init_irq(dev, &s->dsi.drq[2]);
2523
sysbus_init_irq(dev, &s->dsi.drq[3]);
2528
static Property omap_dss_properties[] = {
2529
DEFINE_PROP_INT32("mpu_model", struct omap_dss_s, mpu_model, 0),
2530
DEFINE_PROP_END_OF_LIST()
2533
static void omap_dss_class_init(ObjectClass *klass, void *data)
2535
DeviceClass *dc = DEVICE_CLASS(klass);
2536
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
2537
k->init = omap_dss_init;
2538
dc->reset = omap_dss_reset;
2539
dc->props = omap_dss_properties;
2542
static TypeInfo omap_dss_info = {
2544
.parent = TYPE_SYS_BUS_DEVICE,
2545
.instance_size = sizeof(struct omap_dss_s),
2546
.class_init = omap_dss_class_init,
2549
static void omap_dss_register_types(void)
2551
type_register_static(&omap_dss_info);
2554
void omap_rfbi_attach(DeviceState *dev, int cs,
2555
const struct rfbi_chip_s *chip)
2557
struct omap_dss_s *s = FROM_SYSBUS(struct omap_dss_s,
2558
SYS_BUS_DEVICE(dev));
2559
if (cs < 0 || cs > 1) {
2560
hw_error("%s: wrong CS %i\n", __FUNCTION__, cs);
2562
if (s->rfbi.chip[cs]) {
2563
TRACERFBI("warning - replacing previously attached "
2564
"RFBI chip on CS%d", cs);
2566
s->rfbi.chip[cs] = chip;
2569
DSIHost *omap_dsi_host(DeviceState *dev)
2571
return FROM_SYSBUS(struct omap_dss_s,
2572
SYS_BUS_DEVICE(dev))->dsi.host;
2575
static const GraphicHwOps omap_lcd_panel_ops = {
2576
.invalidate = omap_lcd_panel_invalidate_display,
2577
.gfx_update = omap_lcd_panel_update_display,
2580
static const GraphicHwOps omap_digital_panel_ops = {
2581
.invalidate = omap_dig_panel_invalidate_display,
2582
.gfx_update = omap_dig_panel_update_display,
2585
void omap_lcd_panel_attach(DeviceState *dev)
2587
struct omap_dss_s *s = FROM_SYSBUS(struct omap_dss_s,
2588
SYS_BUS_DEVICE(dev));
2589
if (!s->lcd.attached) {
2590
s->lcd.attached = 1;
2591
s->lcd.invalidate = 1;
2592
s->lcd.con = graphic_console_init(dev, &omap_lcd_panel_ops, s);
2596
void omap_digital_panel_attach(DeviceState *dev)
2598
struct omap_dss_s *s = FROM_SYSBUS(struct omap_dss_s,
2599
SYS_BUS_DEVICE(dev));
2600
if (!s->dig.attached) {
2601
s->dig.attached = 1;
2602
s->dig.invalidate = 1;
2603
s->dig.con = graphic_console_init(dev, &omap_digital_panel_ops, s);
2607
type_init(omap_dss_register_types)