X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hw%2Fomap_dss.c;fp=hw%2Fomap_dss.c;h=3a92d0a860dba59d9c4fe08f3a21a19b9704e6ab;hb=759b334a9739814df2883aa4c41b1c0f5670e90a;hp=d8c2977b6b1466515e082694dcee40fd4d71cd03;hpb=168ccc11c323af885de353d9e045c0c1f78f6f2f;p=qemu diff --git a/hw/omap_dss.c b/hw/omap_dss.c index d8c2977..3a92d0a 100644 --- a/hw/omap_dss.c +++ b/hw/omap_dss.c @@ -1,8 +1,8 @@ /* - * OMAP2 Display Subsystem. + * OMAP2/3 Display Subsystem. * - * Copyright (C) 2008 Nokia Corporation - * Written by Andrzej Zaborowski + * Copyright (C) 2008,2009 Nokia Corporation + * OMAP2 support written by Andrzej Zaborowski * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -21,14 +21,71 @@ #include "hw.h" #include "console.h" #include "omap.h" +#include "qemu-common.h" +#include "sysemu.h" +#include "devices.h" +#include "vga_int.h" +#include "pixel_ops.h" + +//#define OMAP_DSS_DEBUG +//#define OMAP_DSS_DEBUG_DISPC +//#define OMAP_DSS_DEBUG_DISS +//#define OMAP_DSS_DEBUG_DSI +//#define OMAP_DSS_DEBUG_RFBI +//#define OMAP_DSS_DEBUG_VENC + +#ifdef OMAP_DSS_DEBUG +#define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__) +#define LAYERNAME(n) ((!(n)) ? "GFX" : ((n)==1) ? "VID1" : "VID2") +#ifdef OMAP_DSS_DEBUG_DISPC +#define TRACEDISPC(fmt,...) TRACE(fmt, ##__VA_ARGS__) +#else +#define TRACEDISPC(...) +#endif +#ifdef OMAP_DSS_DEBUG_DISS +#define TRACEDISS(fmt,...) TRACE(fmt, ##__VA_ARGS__) +#else +#define TRACEDISS(...) +#endif +#ifdef OMAP_DSS_DEBUG_DSI +#define TRACEDSI(fmt,...) TRACE(fmt, ##__VA_ARGS__) +#else +#define TRACEDSI(...) +#endif +#ifdef OMAP_DSS_DEBUG_RFBI +#define TRACERFBI(fmt,...) TRACE(fmt, ##__VA_ARGS__) +#else +#define TRACERFBI(...) +#endif +#ifdef OMAP_DSS_DEBUG_VENC +#define TRACEVENC(fmt,...) TRACE(fmt, ##__VA_ARGS__) +#else +#define TRACEVENC(...) +#endif +#else +#define TRACE(...) +#define TRACEDISPC(...) +#define TRACEDISS(...) +#define TRACEDSI(...) +#define TRACERFBI(...) +#define TRACEVENC(...) +#endif + +struct omap3_lcd_panel_s { + struct omap_dss_s *dss; + DisplayState *state; + omap3_lcd_panel_fn_t line_fn; + uint32_t invalidate; +}; struct omap_dss_s { qemu_irq irq; qemu_irq drq; - DisplayState *state; int autoidle; int control; + uint32_t sdi_control; + uint32_t pll_control; int enable; struct omap_dss_panel_s { @@ -39,8 +96,10 @@ struct omap_dss_s { int x; int y; } dig, lcd; + struct omap3_lcd_panel_s *omap_lcd_panel[2]; struct { + uint8_t rev; uint32_t idlemode; uint32_t irqst; uint32_t irqen; @@ -51,7 +110,11 @@ struct omap_dss_s { int line; uint32_t bg[2]; uint32_t trans[2]; - + uint32_t global_alpha; + uint32_t cpr_coef_r; + uint32_t cpr_coef_g; + uint32_t cpr_coef_b; + struct omap_dss_plane_s { int enable; int bpp; @@ -60,6 +123,10 @@ struct omap_dss_s { int nx; int ny; + int rotation_flag; + int gfx_format; + int gfx_channel; + target_phys_addr_t addr[3]; uint32_t attr; @@ -67,8 +134,19 @@ struct omap_dss_s { int rowinc; int colinc; int wininc; + + uint32_t preload; + + /* following for l1 & l2 only (VID1 and VID2) */ + uint32_t fir; + uint32_t fir_coef_h[8]; + uint32_t fir_coef_hv[8]; + uint32_t fir_coef_v[8]; + uint32_t conv_coef[5]; + uint32_t picture_size; + uint32_t accu[2]; } l[3]; - + int invalidate; uint16_t palette[256]; } dispc; @@ -88,11 +166,341 @@ struct omap_dss_s { uint16_t hsync; struct rfbi_chip_s *chip[2]; } rfbi; + + struct { + /* protocol engine registers */ + uint32_t sysconfig; + uint32_t irqst; + uint32_t irqen; + uint32_t ctrl; + uint32_t complexio_cfg1; + uint32_t complexio_irqst; + uint32_t complexio_irqen; + uint32_t clk_ctrl; + uint32_t timing1; + uint32_t timing2; + uint32_t vm_timing1; + uint32_t vm_timing2; + uint32_t vm_timing3; + uint32_t clk_timing; + uint32_t tx_fifo_vc_size; + uint32_t rx_fifo_vc_size; + struct { + uint32_t ctrl; + uint32_t te; + uint32_t lp_header; + uint32_t lp_payload; + uint32_t sp_header; + uint32_t irqst; + uint32_t irqen; + } vc[4]; + /* phy registers */ + uint32_t phy_cfg0; + uint32_t phy_cfg1; + uint32_t phy_cfg2; + /* pll controller registers */ + uint32_t pll_control; + uint32_t pll_go; + uint32_t pll_config1; + uint32_t pll_config2; + } dsi; }; -static void omap_dispc_interrupt_update(struct omap_dss_s *s) +static void omap_dss_interrupt_update(struct omap_dss_s *s) +{ + qemu_set_irq(s->irq, + (s->dsi.irqst & s->dsi.irqen) + | (s->dsi.complexio_irqst & s->dsi.complexio_irqen) + | (s->dsi.vc[0].irqst & s->dsi.vc[0].irqen) + | (s->dsi.vc[1].irqst & s->dsi.vc[1].irqen) + | (s->dsi.vc[2].irqst & s->dsi.vc[2].irqen) + | (s->dsi.vc[3].irqst & s->dsi.vc[3].irqen) + | (s->dispc.irqst & s->dispc.irqen)); +} + +static void omap_dss_save_state(QEMUFile *f, void *opaque) +{ + struct omap_dss_s *s = (struct omap_dss_s *)opaque; + int i, j; + + qemu_put_sbe32(f, s->autoidle); + qemu_put_sbe32(f, s->control); + qemu_put_be32(f, s->sdi_control); + qemu_put_be32(f, s->pll_control); + qemu_put_sbe32(f, s->enable); + qemu_put_sbe32(f, s->dig.enable); + qemu_put_sbe32(f, s->dig.nx); + qemu_put_sbe32(f, s->dig.ny); + qemu_put_sbe32(f, s->dig.x); + qemu_put_sbe32(f, s->dig.y); + qemu_put_sbe32(f, s->lcd.enable); + qemu_put_sbe32(f, s->lcd.nx); + qemu_put_sbe32(f, s->lcd.ny); + qemu_put_sbe32(f, s->lcd.x); + qemu_put_sbe32(f, s->lcd.y); + qemu_put_be32(f, s->dispc.idlemode); + qemu_put_be32(f, s->dispc.irqst); + qemu_put_be32(f, s->dispc.irqen); + qemu_put_be32(f, s->dispc.control); + qemu_put_be32(f, s->dispc.config); + qemu_put_be32(f, s->dispc.capable); + qemu_put_be32(f, s->dispc.timing[0]); + qemu_put_be32(f, s->dispc.timing[1]); + qemu_put_be32(f, s->dispc.timing[2]); + qemu_put_be32(f, s->dispc.timing[3]); + qemu_put_sbe32(f, s->dispc.line); + qemu_put_be32(f, s->dispc.bg[0]); + qemu_put_be32(f, s->dispc.bg[1]); + qemu_put_be32(f, s->dispc.trans[0]); + qemu_put_be32(f, s->dispc.trans[1]); + qemu_put_be32(f, s->dispc.global_alpha); + qemu_put_be32(f, s->dispc.cpr_coef_r); + qemu_put_be32(f, s->dispc.cpr_coef_g); + qemu_put_be32(f, s->dispc.cpr_coef_b); + for (i = 0; i < 3; i++) { + qemu_put_sbe32(f, s->dispc.l[i].enable); + qemu_put_sbe32(f, s->dispc.l[i].bpp); + qemu_put_sbe32(f, s->dispc.l[i].posx); + qemu_put_sbe32(f, s->dispc.l[i].posy); + qemu_put_sbe32(f, s->dispc.l[i].nx); + qemu_put_sbe32(f, s->dispc.l[i].ny); + qemu_put_sbe32(f, s->dispc.l[i].rotation_flag); + qemu_put_sbe32(f, s->dispc.l[i].gfx_format); + qemu_put_sbe32(f, s->dispc.l[i].gfx_channel); + for (j = 0; j < 3; j++) { +#if TARGET_PHYS_ADDR_BITS == 32 + qemu_put_be32(f, s->dispc.l[i].addr[j]); +#elif TARGET_PHYS_ADDR_BITS == 64 + qemu_put_be64(f, s->dispc.l[i].addr[j]); +#else +#error TARGET_PHYS_ADDR_BITS undefined +#endif + } + qemu_put_be32(f, s->dispc.l[i].attr); + qemu_put_be32(f, s->dispc.l[i].tresh); + qemu_put_sbe32(f, s->dispc.l[i].rowinc); + qemu_put_sbe32(f, s->dispc.l[i].colinc); + qemu_put_sbe32(f, s->dispc.l[i].wininc); + qemu_put_be32(f, s->dispc.l[i].preload); + qemu_put_be32(f, s->dispc.l[i].fir); + for (j = 0; j < 8; j++) { + qemu_put_be32(f, s->dispc.l[i].fir_coef_h[j]); + qemu_put_be32(f, s->dispc.l[i].fir_coef_hv[j]); + qemu_put_be32(f, s->dispc.l[i].fir_coef_v[j]); + if (j < 5) + qemu_put_be32(f, s->dispc.l[i].conv_coef[j]); + } + qemu_put_be32(f, s->dispc.l[i].picture_size); + qemu_put_be32(f, s->dispc.l[i].accu[0]); + qemu_put_be32(f, s->dispc.l[i].accu[1]); + } + qemu_put_sbe32(f, s->dispc.invalidate); + for (i = 0; i < 256; i++) + qemu_put_be16(f, s->dispc.palette[i]); + qemu_put_sbe32(f, s->rfbi.idlemode); + qemu_put_be32(f, s->rfbi.control); + qemu_put_sbe32(f, s->rfbi.enable); + qemu_put_sbe32(f, s->rfbi.pixels); + qemu_put_sbe32(f, s->rfbi.busy); + qemu_put_sbe32(f, s->rfbi.skiplines); + qemu_put_be16(f, s->rfbi.rxbuf); + for (i = 0; i < 6; i++) { + if (i < 2) + qemu_put_be32(f, s->rfbi.config[i]); + if (i < 4) + qemu_put_be32(f, s->rfbi.time[i]); + qemu_put_be32(f, s->rfbi.data[i]); + } + qemu_put_be16(f, s->rfbi.vsync); + qemu_put_be16(f, s->rfbi.hsync); + qemu_put_be32(f, s->dsi.sysconfig); + qemu_put_be32(f, s->dsi.irqst); + qemu_put_be32(f, s->dsi.irqen); + qemu_put_be32(f, s->dsi.ctrl); + qemu_put_be32(f, s->dsi.complexio_cfg1); + qemu_put_be32(f, s->dsi.complexio_irqst); + qemu_put_be32(f, s->dsi.complexio_irqen); + qemu_put_be32(f, s->dsi.clk_ctrl); + qemu_put_be32(f, s->dsi.timing1); + qemu_put_be32(f, s->dsi.timing2); + qemu_put_be32(f, s->dsi.vm_timing1); + qemu_put_be32(f, s->dsi.vm_timing2); + qemu_put_be32(f, s->dsi.vm_timing3); + qemu_put_be32(f, s->dsi.clk_timing); + qemu_put_be32(f, s->dsi.tx_fifo_vc_size); + qemu_put_be32(f, s->dsi.rx_fifo_vc_size); + for (i = 0; i < 4; i++) { + qemu_put_be32(f, s->dsi.vc[i].ctrl); + qemu_put_be32(f, s->dsi.vc[i].te); + qemu_put_be32(f, s->dsi.vc[i].lp_header); + qemu_put_be32(f, s->dsi.vc[i].lp_payload); + qemu_put_be32(f, s->dsi.vc[i].sp_header); + qemu_put_be32(f, s->dsi.vc[i].irqst); + qemu_put_be32(f, s->dsi.vc[i].irqen); + } + qemu_put_be32(f, s->dsi.phy_cfg0); + qemu_put_be32(f, s->dsi.phy_cfg1); + qemu_put_be32(f, s->dsi.phy_cfg2); + qemu_put_be32(f, s->dsi.pll_control); + qemu_put_be32(f, s->dsi.pll_go); + qemu_put_be32(f, s->dsi.pll_config1); + qemu_put_be32(f, s->dsi.pll_config2); +} + +static int omap_dss_load_state(QEMUFile *f, void *opaque, int version_id) +{ + struct omap_dss_s *s = (struct omap_dss_s *)opaque; + int i, j; + + if (version_id) + return -EINVAL; + + s->autoidle = qemu_get_sbe32(f); + s->control = qemu_get_sbe32(f); + s->sdi_control = qemu_get_be32(f); + s->pll_control = qemu_get_be32(f); + s->enable = qemu_get_sbe32(f); + s->dig.enable = qemu_get_sbe32(f); + s->dig.nx = qemu_get_sbe32(f); + s->dig.ny = qemu_get_sbe32(f); + s->dig.x = qemu_get_sbe32(f); + s->dig.y = qemu_get_sbe32(f); + s->lcd.enable = qemu_get_sbe32(f); + s->lcd.nx = qemu_get_sbe32(f); + s->lcd.ny = qemu_get_sbe32(f); + s->lcd.x = qemu_get_sbe32(f); + s->lcd.y = qemu_get_sbe32(f); + s->dispc.idlemode = qemu_get_be32(f); + s->dispc.irqst = qemu_get_be32(f); + s->dispc.irqen = qemu_get_be32(f); + s->dispc.control = qemu_get_be32(f); + s->dispc.config = qemu_get_be32(f); + s->dispc.capable = qemu_get_be32(f); + s->dispc.timing[0] = qemu_get_be32(f); + s->dispc.timing[1] = qemu_get_be32(f); + s->dispc.timing[2] = qemu_get_be32(f); + s->dispc.timing[3] = qemu_get_be32(f); + s->dispc.line = qemu_get_sbe32(f); + s->dispc.bg[0] = qemu_get_be32(f); + s->dispc.bg[1] = qemu_get_be32(f); + s->dispc.trans[0] = qemu_get_be32(f); + s->dispc.trans[1] = qemu_get_be32(f); + s->dispc.global_alpha = qemu_get_be32(f); + s->dispc.cpr_coef_r = qemu_get_be32(f); + s->dispc.cpr_coef_g = qemu_get_be32(f); + s->dispc.cpr_coef_b = qemu_get_be32(f); + for (i = 0; i < 3; i++) { + s->dispc.l[i].enable = qemu_get_sbe32(f); + s->dispc.l[i].bpp = qemu_get_sbe32(f); + s->dispc.l[i].posx = qemu_get_sbe32(f); + s->dispc.l[i].posy = qemu_get_sbe32(f); + s->dispc.l[i].nx = qemu_get_sbe32(f); + s->dispc.l[i].ny = qemu_get_sbe32(f); + s->dispc.l[i].rotation_flag = qemu_get_sbe32(f); + s->dispc.l[i].gfx_format = qemu_get_sbe32(f); + s->dispc.l[i].gfx_channel = qemu_get_sbe32(f); + for (j = 0; j < 3; j++) { +#if TARGET_PHYS_ADDR_BITS == 32 + s->dispc.l[i].addr[j] = qemu_get_be32(f); +#elif TARGET_PHYS_ADDR_BITS == 64 + s->dispc.l[i].addr[j] = qemu_get_be64(f); +#else +#error TARGET_PHYS_ADDR_BITS undefined +#endif + } + s->dispc.l[i].attr = qemu_get_be32(f); + s->dispc.l[i].tresh = qemu_get_be32(f); + s->dispc.l[i].rowinc = qemu_get_sbe32(f); + s->dispc.l[i].colinc = qemu_get_sbe32(f); + s->dispc.l[i].wininc = qemu_get_sbe32(f); + s->dispc.l[i].preload = qemu_get_be32(f); + s->dispc.l[i].fir = qemu_get_be32(f); + for (j = 0; j < 8; j++) { + s->dispc.l[i].fir_coef_h[j] = qemu_get_be32(f); + s->dispc.l[i].fir_coef_hv[j] = qemu_get_be32(f); + s->dispc.l[i].fir_coef_v[j] = qemu_get_be32(f); + if (j < 5) + s->dispc.l[i].conv_coef[j] = qemu_get_be32(f); + } + s->dispc.l[i].picture_size = qemu_get_be32(f); + s->dispc.l[i].accu[0] = qemu_get_be32(f); + s->dispc.l[i].accu[1] = qemu_get_be32(f); + } + s->dispc.invalidate = qemu_get_sbe32(f); + for (i = 0; i < 256; i++) + s->dispc.palette[i] = qemu_get_be16(f); + s->rfbi.idlemode = qemu_get_sbe32(f); + s->rfbi.control = qemu_get_be32(f); + s->rfbi.enable = qemu_get_sbe32(f); + s->rfbi.pixels = qemu_get_sbe32(f); + s->rfbi.busy = qemu_get_sbe32(f); + s->rfbi.skiplines = qemu_get_sbe32(f); + s->rfbi.rxbuf = qemu_get_be16(f); + for (i = 0; i < 6; i++) { + if (i < 2) + s->rfbi.config[i] = qemu_get_be32(f); + if (i < 4) + s->rfbi.time[i] = qemu_get_be32(f); + s->rfbi.data[i] = qemu_get_be32(f); + } + s->rfbi.vsync = qemu_get_be16(f); + s->rfbi.hsync = qemu_get_be16(f); + s->dsi.sysconfig = qemu_get_be32(f); + s->dsi.irqst = qemu_get_be32(f); + s->dsi.irqen = qemu_get_be32(f); + s->dsi.ctrl = qemu_get_be32(f); + s->dsi.complexio_cfg1 = qemu_get_be32(f); + s->dsi.complexio_irqst = qemu_get_be32(f); + s->dsi.complexio_irqen = qemu_get_be32(f); + s->dsi.clk_ctrl = qemu_get_be32(f); + s->dsi.timing1 = qemu_get_be32(f); + s->dsi.timing2 = qemu_get_be32(f); + s->dsi.vm_timing1 = qemu_get_be32(f); + s->dsi.vm_timing2 = qemu_get_be32(f); + s->dsi.vm_timing3 = qemu_get_be32(f); + s->dsi.clk_timing = qemu_get_be32(f); + s->dsi.tx_fifo_vc_size = qemu_get_be32(f); + s->dsi.rx_fifo_vc_size = qemu_get_be32(f); + for (i = 0; i < 4; i++) { + s->dsi.vc[i].ctrl = qemu_get_be32(f); + s->dsi.vc[i].te = qemu_get_be32(f); + s->dsi.vc[i].lp_header = qemu_get_be32(f); + s->dsi.vc[i].lp_payload = qemu_get_be32(f); + s->dsi.vc[i].sp_header = qemu_get_be32(f); + s->dsi.vc[i].irqst = qemu_get_be32(f); + s->dsi.vc[i].irqen = qemu_get_be32(f); + } + s->dsi.phy_cfg0 = qemu_get_be32(f); + s->dsi.phy_cfg1 = qemu_get_be32(f); + s->dsi.phy_cfg2 = qemu_get_be32(f); + s->dsi.pll_control = qemu_get_be32(f); + s->dsi.pll_go = qemu_get_be32(f); + s->dsi.pll_config1 = qemu_get_be32(f); + s->dsi.pll_config2 = qemu_get_be32(f); + + s->dispc.invalidate = 1; /* force refresh of display parameters */ + if (s->omap_lcd_panel[0]) + s->omap_lcd_panel[0]->invalidate = 1; + if (s->omap_lcd_panel[1]) + s->omap_lcd_panel[1]->invalidate = 1; + + omap_dss_interrupt_update(s); + + return 0; +} + +static void omap_dsi_reset(struct omap_dss_s *s) { - qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen); + memset(&s->dsi, 0, sizeof(s->dsi)); + s->dsi.sysconfig = 0x11; + s->dsi.ctrl = 0x100; + s->dsi.complexio_cfg1 = 0x20000000; + s->dsi.timing1 = 0x7fff7fff; + s->dsi.timing2 = 0x7fff7fff; + s->dsi.clk_timing = 0x0101; + s->dsi.phy_cfg0 = 0x1a3c1a28; + s->dsi.phy_cfg1 = 0x420a1875; + s->dsi.phy_cfg2 = 0xb800001b; } static void omap_rfbi_reset(struct omap_dss_s *s) @@ -121,8 +529,12 @@ static void omap_rfbi_reset(struct omap_dss_s *s) void omap_dss_reset(struct omap_dss_s *s) { - s->autoidle = 0; + int i, j; + + s->autoidle = 0x10; /* was 0 for OMAP2 but bit4 must be set for OMAP3 */ s->control = 0; + s->sdi_control = 0; + s->pll_control = 0; s->enable = 0; s->dig.enable = 0; @@ -142,56 +554,98 @@ void omap_dss_reset(struct omap_dss_s *s) s->dispc.timing[0] = 0; s->dispc.timing[1] = 0; s->dispc.timing[2] = 0; - s->dispc.timing[3] = 0; + s->dispc.timing[3] = 0x00010002; s->dispc.line = 0; s->dispc.bg[0] = 0; s->dispc.bg[1] = 0; s->dispc.trans[0] = 0; s->dispc.trans[1] = 0; - - s->dispc.l[0].enable = 0; - s->dispc.l[0].bpp = 0; - s->dispc.l[0].addr[0] = 0; - s->dispc.l[0].addr[1] = 0; - s->dispc.l[0].addr[2] = 0; - s->dispc.l[0].posx = 0; - s->dispc.l[0].posy = 0; - s->dispc.l[0].nx = 1; - s->dispc.l[0].ny = 1; - s->dispc.l[0].attr = 0; - s->dispc.l[0].tresh = 0; - s->dispc.l[0].rowinc = 1; - s->dispc.l[0].colinc = 1; - s->dispc.l[0].wininc = 0; - + s->dispc.global_alpha = 0; + s->dispc.cpr_coef_r = 0; + s->dispc.cpr_coef_g = 0; + s->dispc.cpr_coef_b = 0; + + for (i = 0; i < 3; i++) { + s->dispc.l[i].enable = 0; + s->dispc.l[i].bpp = 0; + s->dispc.l[i].addr[0] = 0; + s->dispc.l[i].addr[1] = 0; + s->dispc.l[i].addr[2] = 0; + s->dispc.l[i].posx = 0; + s->dispc.l[i].posy = 0; + s->dispc.l[i].nx = 1; + s->dispc.l[i].ny = 1; + s->dispc.l[i].attr = 0; + s->dispc.l[i].tresh = (s->dispc.rev < 0x30) ? 0 : 0x03ff03c0; + s->dispc.l[i].rowinc = 1; + s->dispc.l[i].colinc = 1; + s->dispc.l[i].wininc = 0; + s->dispc.l[i].preload = 0x100; + s->dispc.l[i].fir = 0; + s->dispc.l[i].picture_size = 0; + s->dispc.l[i].accu[0] = 0; + s->dispc.l[i].accu[1] = 0; + for (j = 0; j < 5; j++) + s->dispc.l[i].conv_coef[j] = 0; + for (j = 0; j < 8; j++) { + s->dispc.l[i].fir_coef_h[j] = 0; + s->dispc.l[i].fir_coef_hv[j] = 0; + s->dispc.l[i].fir_coef_v[j] = 0; + } + } + + omap_dsi_reset(s); omap_rfbi_reset(s); - omap_dispc_interrupt_update(s); + omap_dss_interrupt_update(s); } static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; + switch (addr) { case 0x00: /* DSS_REVISIONNUMBER */ + TRACEDISS("DSS_REVISIONNUMBER: 0x20"); return 0x20; case 0x10: /* DSS_SYSCONFIG */ + TRACEDISS("DSS_SYSCONFIG: 0x%08x", s->autoidle); return s->autoidle; case 0x14: /* DSS_SYSSTATUS */ + TRACEDISS("DSS_SYSSTATUS: 0x1"); return 1; /* RESETDONE */ - + + case 0x18: /* DSS_IRQSTATUS */ + TRACEDISS("DSS_IRQSTATUS: 0x%08x", + ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0) + | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0)); + return ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0) + | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0); + case 0x40: /* DSS_CONTROL */ + TRACEDISS("DSS_CONTROL: 0x%08x", s->control); return s->control; + case 0x44: /* DSS_SDI_CONTROL */ + TRACEDISS("DSS_SDI_CONTROL: 0x%08x", s->sdi_control); + return s->sdi_control; + + case 0x48: /* DSS_PLL_CONTROL */ + TRACEDISS("DSS_PLL_CONTROL: 0x%08x", s->pll_control); + return s->pll_control; + case 0x50: /* DSS_PSA_LCD_REG_1 */ case 0x54: /* DSS_PSA_LCD_REG_2 */ case 0x58: /* DSS_PSA_VIDEO_REG */ + TRACEDISS("DSS_PSA_xxx: 0"); /* TODO: fake some values when appropriate s->control bits are set */ return 0; - case 0x5c: /* DSS_STATUS */ + case 0x5c: /* DSS_SDI_STATUS */ + /* TODO: check and implement missing OMAP3 bits */ + TRACEDISS("DSS_STATUS: 0x%08x", 1 + (s->control & 1)); return 1 + (s->control & 1); default: @@ -209,25 +663,40 @@ static void omap_diss_write(void *opaque, target_phys_addr_t addr, switch (addr) { case 0x00: /* DSS_REVISIONNUMBER */ case 0x14: /* DSS_SYSSTATUS */ + case 0x18: /* DSS_IRQSTATUS */ case 0x50: /* DSS_PSA_LCD_REG_1 */ case 0x54: /* DSS_PSA_LCD_REG_2 */ case 0x58: /* DSS_PSA_VIDEO_REG */ case 0x5c: /* DSS_STATUS */ - OMAP_RO_REG(addr); + /* quietly ignore */ + /*OMAP_RO_REGV(addr, value);*/ break; case 0x10: /* DSS_SYSCONFIG */ + TRACEDISS("DSS_SYSCONFIG = 0x%08x", value); if (value & 2) /* SOFTRESET */ omap_dss_reset(s); - s->autoidle = value & 1; + s->autoidle = value & 0x19; /* was 0x01 for OMAP2 */ break; case 0x40: /* DSS_CONTROL */ - s->control = value & 0x3dd; + TRACEDISS("DSS_CONTROL = 0x%08x", value); + s->control = value & 0x3ff; /* was 0x3dd for OMAP2 */ + break; + + case 0x44: /* DSS_SDI_CONTROL */ + TRACEDISS("DSS_SDI_CONTROL = 0x%08x", value); + s->sdi_control = value & 0x000ff80f; break; + case 0x48: /* DSS_PLL_CONTROL */ + TRACEDISS("DSS_PLL_CONTROL = 0x%08x", value); + s->pll_control = value; + break; + default: - OMAP_BAD_REG(addr); + OMAP_BAD_REGV(addr, value); + break; } } @@ -246,116 +715,223 @@ static CPUWriteMemoryFunc *omap_diss1_writefn[] = { static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; + int n = 0; switch (addr) { case 0x000: /* DISPC_REVISION */ - return 0x20; - + TRACEDISPC("DISPC_REVISION: 0x%08x", s->dispc.rev); + return s->dispc.rev; case 0x010: /* DISPC_SYSCONFIG */ + TRACEDISPC("DISPC_SYSCONFIG: 0x%08x", s->dispc.idlemode); return s->dispc.idlemode; - case 0x014: /* DISPC_SYSSTATUS */ + TRACEDISPC("DISPC_SYSSTATUS: 1"); return 1; /* RESETDONE */ - case 0x018: /* DISPC_IRQSTATUS */ + TRACEDISPC("DISPC_IRQSTATUS: 0x%08x", s->dispc.irqst); return s->dispc.irqst; - case 0x01c: /* DISPC_IRQENABLE */ + TRACEDISPC("DISPC_IRQENABLE: 0x%08x", s->dispc.irqen); return s->dispc.irqen; - case 0x040: /* DISPC_CONTROL */ + TRACEDISPC("DISPC_CONTROL: 0x%08x", s->dispc.control); return s->dispc.control; - case 0x044: /* DISPC_CONFIG */ + TRACEDISPC("DISPC_CONFIG: 0x%08x", s->dispc.config); return s->dispc.config; - case 0x048: /* DISPC_CAPABLE */ + TRACEDISPC("DISPC_CAPABLE: 0x%08x", s->dispc.capable); return s->dispc.capable; - case 0x04c: /* DISPC_DEFAULT_COLOR0 */ + TRACEDISPC("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[0]); return s->dispc.bg[0]; case 0x050: /* DISPC_DEFAULT_COLOR1 */ + TRACEDISPC("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[1]); return s->dispc.bg[1]; case 0x054: /* DISPC_TRANS_COLOR0 */ + TRACEDISPC("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[0]); return s->dispc.trans[0]; case 0x058: /* DISPC_TRANS_COLOR1 */ + TRACEDISPC("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[1]); return s->dispc.trans[1]; - case 0x05c: /* DISPC_LINE_STATUS */ + TRACEDISPC("DISPC_LINE_STATUS: 0x7ff"); return 0x7ff; case 0x060: /* DISPC_LINE_NUMBER */ + TRACEDISPC("DISPC_LINE_NUMBER: 0x%08x", s->dispc.line); return s->dispc.line; - case 0x064: /* DISPC_TIMING_H */ + TRACEDISPC("DISPC_TIMING_H: 0x%08x", s->dispc.timing[0]); return s->dispc.timing[0]; case 0x068: /* DISPC_TIMING_V */ + TRACEDISPC("DISPC_TIMING_H: 0x%08x", s->dispc.timing[1]); return s->dispc.timing[1]; case 0x06c: /* DISPC_POL_FREQ */ + TRACEDISPC("DISPC_POL_FREQ: 0x%08x", s->dispc.timing[2]); return s->dispc.timing[2]; case 0x070: /* DISPC_DIVISOR */ + TRACEDISPC("DISPC_DIVISOR: 0x%08x", s->dispc.timing[3]); return s->dispc.timing[3]; - + case 0x074: /* DISPC_GLOBAL_ALPHA */ + TRACEDISPC("DISPC_GLOBAL_ALPHA: 0x%08x", s->dispc.global_alpha); + return s->dispc.global_alpha; case 0x078: /* DISPC_SIZE_DIG */ + TRACEDISPC("DISPC_SIZE_DIG: 0x%08x", ((s->dig.ny - 1) << 16) | (s->dig.nx - 1)); return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1); case 0x07c: /* DISPC_SIZE_LCD */ + TRACEDISPC("DISPC_SIZE_LCD: 0x%08x", ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1)); return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1); - + case 0x14c: /* DISPC_VID2_BA0 */ + n++; + case 0x0bc: /* DISPC_VID1_BA0 */ + n++; case 0x080: /* DISPC_GFX_BA0 */ - return s->dispc.l[0].addr[0]; + TRACEDISPC("DISPC_%s_BA0: " OMAP_FMT_plx, LAYERNAME(n), s->dispc.l[n].addr[0]); + return s->dispc.l[n].addr[0]; + case 0x150: /* DISPC_VID2_BA1 */ + n++; + case 0x0c0: /* DISPC_VID1_BA1 */ + n++; case 0x084: /* DISPC_GFX_BA1 */ - return s->dispc.l[0].addr[1]; + TRACEDISPC("DISPC_%s_BA1: " OMAP_FMT_plx, LAYERNAME(n), s->dispc.l[n].addr[1]); + return s->dispc.l[n].addr[1]; + case 0x154: /* DISPC_VID2_POSITION */ + n++; + case 0x0c4: /* DISPC_VID1_POSITION */ + n++; case 0x088: /* DISPC_GFX_POSITION */ - return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx; + TRACEDISPC("DISPC_%s_POSITION: 0x%08x", LAYERNAME(n), + (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx); + return (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx; + case 0x158: /* DISPC_VID2_SIZE */ + n++; + case 0x0c8: /* DISPC_VID1_SIZE */ + n++; case 0x08c: /* DISPC_GFX_SIZE */ - return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1); + TRACEDISPC("DISPC_%s_SIZE: 0x%08x", LAYERNAME(n), + ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1)); + return ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1); + case 0x15c: /* DISPC_VID2_ATTRIBUTES */ + n++; + case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ + n++; case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ - return s->dispc.l[0].attr; + TRACEDISPC("DISPC_%s_ATTRIBUTES: 0x%08x", LAYERNAME(n), + s->dispc.l[n].attr); + return s->dispc.l[n].attr; + case 0x160: /* DISPC_VID2_FIFO_THRESHOLD */ + n++; + case 0x0d0: /* DISPC_VID1_FIFO_THRESHOLD */ + n++; case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ - return s->dispc.l[0].tresh; + TRACEDISPC("DISPC_%s_THRESHOLD: 0x%08x", LAYERNAME(n), + s->dispc.l[n].tresh); + return s->dispc.l[n].tresh; + case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */ + n++; + case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */ + n++; case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */ - return 256; + TRACEDISPC("DISPC_%s_FIFO_SIZE_STATUS: 0x%08x", LAYERNAME(n), + s->dispc.rev < 0x30 ? 256 : 1024); + return s->dispc.rev < 0x30 ? 256 : 1024; + case 0x168: /* DISPC_VID2_ROW_INC */ + n++; + case 0x0d8: /* DISPC_VID1_ROW_INC */ + n++; case 0x0ac: /* DISPC_GFX_ROW_INC */ - return s->dispc.l[0].rowinc; + TRACEDISPC("DISPC_%s_ROW_INC: 0x%08x", LAYERNAME(n), + s->dispc.l[n].rowinc); + return s->dispc.l[n].rowinc; + case 0x16c: /* DISPC_VID2_PIXEL_INC */ + n++; + case 0x0dc: /* DISPC_VID1_PIXEL_INC */ + n++; case 0x0b0: /* DISPC_GFX_PIXEL_INC */ - return s->dispc.l[0].colinc; + TRACEDISPC("DISPC_%s_PIXEL_INC: 0x%08x", LAYERNAME(n), + s->dispc.l[n].colinc); + return s->dispc.l[n].colinc; case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ + TRACEDISPC("DISPC_GFX_WINDOW_SKIP: 0x%08x", s->dispc.l[0].wininc); return s->dispc.l[0].wininc; case 0x0b8: /* DISPC_GFX_TABLE_BA */ + TRACEDISPC("DISPC_GFX_TABLE_BA: " OMAP_FMT_plx, s->dispc.l[0].addr[2]); return s->dispc.l[0].addr[2]; - - case 0x0bc: /* DISPC_VID1_BA0 */ - case 0x0c0: /* DISPC_VID1_BA1 */ - case 0x0c4: /* DISPC_VID1_POSITION */ - case 0x0c8: /* DISPC_VID1_SIZE */ - case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ - case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ - case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */ - case 0x0d8: /* DISPC_VID1_ROW_INC */ - case 0x0dc: /* DISPC_VID1_PIXEL_INC */ - case 0x0e0: /* DISPC_VID1_FIR */ - case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ - case 0x0e8: /* DISPC_VID1_ACCU0 */ - case 0x0ec: /* DISPC_VID1_ACCU1 */ - case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ - case 0x14c: /* DISPC_VID2_BA0 */ - case 0x150: /* DISPC_VID2_BA1 */ - case 0x154: /* DISPC_VID2_POSITION */ - case 0x158: /* DISPC_VID2_SIZE */ - case 0x15c: /* DISPC_VID2_ATTRIBUTES */ - case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ - case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */ - case 0x168: /* DISPC_VID2_ROW_INC */ - case 0x16c: /* DISPC_VID2_PIXEL_INC */ case 0x170: /* DISPC_VID2_FIR */ + n++; + case 0x0e0: /* DISPC_VID1_FIR */ + n++; + TRACEDISPC("DISPC_%s_FIR: 0x%08x", LAYERNAME(n), + s->dispc.l[n].fir); + return s->dispc.l[n].fir; case 0x174: /* DISPC_VID2_PICTURE_SIZE */ + n++; + case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ + n++; + TRACEDISPC("DISPC_%s_PICTURE_SIZE: 0x%08x", LAYERNAME(n), + s->dispc.l[n].picture_size); + return s->dispc.l[n].picture_size; case 0x178: /* DISPC_VID2_ACCU0 */ case 0x17c: /* DISPC_VID2_ACCU1 */ - case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ + n++; + case 0x0e8: /* DISPC_VID1_ACCU0 */ + case 0x0ec: /* DISPC_VID1_ACCU1 */ + n++; + TRACEDISPC("DISPC_%s_ACCU%d: 0x%08x", LAYERNAME(n), + (int)((addr >> 1) & 1), s->dispc.l[n].accu[(addr >> 1 ) & 1]); + return s->dispc.l[n].accu[(addr >> 1) & 1]; + case 0x180 ... 0x1bc: /* DISPC_VID2_FIR_COEF */ + n++; + case 0x0f0 ... 0x12c: /* DISPC_VID1_FIR_COEF */ + n++; + if (addr & 4) { + TRACEDISPC("DISPC_%s_FIR_COEF_HV%d: 0x%08x", LAYERNAME(n), + (int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8), + s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]); + return s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]; + } + TRACEDISPC("DISPC_%s_FIR_COEF_H%d: 0x%08x", LAYERNAME(n), + (int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8), + s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]); + return s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]; + case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */ + n++; + case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */ + n++; + TRACEDISPC("DISPC_%s_CONV_COEF%d: 0x%08x", LAYERNAME(n), + (int)((addr - ((n > 1) ? 0x1c0 : 0x130)) / 4), + s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4]); + return s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4]; case 0x1d4: /* DISPC_DATA_CYCLE1 */ case 0x1d8: /* DISPC_DATA_CYCLE2 */ case 0x1dc: /* DISPC_DATA_CYCLE3 */ + TRACEDISPC("DISPC_DATA_CYCLE%d: 0", (int)((addr - 0x1d4) / 4)); return 0; - + case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */ + n++; + case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */ + n++; + TRACEDISPC("DISPC_%s_FIR_COEF_V%d: 0x%08x", LAYERNAME(n), + (int)((addr & 0x01f) / 4), + s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4]); + return s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4]; + case 0x220: /* DISPC_CPR_COEF_R */ + TRACEDISPC("DISPC_CPR_COEF_R: 0x%08x", s->dispc.cpr_coef_r); + return s->dispc.cpr_coef_r; + case 0x224: /* DISPC_CPR_COEF_G */ + TRACEDISPC("DISPC_CPR_COEF_G: 0x%08x", s->dispc.cpr_coef_g); + return s->dispc.cpr_coef_g; + case 0x228: /* DISPC_CPR_COEF_B */ + TRACEDISPC("DISPC_CPR_COEF_B: 0x%08x", s->dispc.cpr_coef_b); + return s->dispc.cpr_coef_b; + case 0x234: /* DISPC_VID2_PRELOAD */ + n++; + case 0x230: /* DISPC_VID1_PRELOAD */ + n++; + case 0x22c: /* DISPC_GFX_PRELOAD */ + TRACEDISPC("DISPC_%s_PRELOAD: 0x%08x", LAYERNAME(n), + s->dispc.l[n].preload); + return s->dispc.l[n].preload; default: break; } @@ -367,26 +943,38 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr, uint32_t value) { struct omap_dss_s *s = (struct omap_dss_s *) opaque; + int n = 0; switch (addr) { + case 0x000: /* DISPC_REVISION */ + case 0x014: /* DISPC_SYSSTATUS */ + case 0x05c: /* DISPC_LINE_STATUS */ + case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */ + /* quietly ignore */ + /*OMAP_RO_REGV(addr, value);*/ + break; case 0x010: /* DISPC_SYSCONFIG */ + TRACEDISPC("DISPC_SYSCONFIG = 0x%08x", value); if (value & 2) /* SOFTRESET */ omap_dss_reset(s); - s->dispc.idlemode = value & 0x301b; + s->dispc.idlemode = value & ((s->dispc.rev < 0x30) ? 0x301b : 0x331f); break; - case 0x018: /* DISPC_IRQSTATUS */ + TRACEDISPC("DISPC_IRQSTATUS = 0x%08x", value); s->dispc.irqst &= ~value; - omap_dispc_interrupt_update(s); + omap_dss_interrupt_update(s); break; - case 0x01c: /* DISPC_IRQENABLE */ - s->dispc.irqen = value & 0xffff; - omap_dispc_interrupt_update(s); + TRACEDISPC("DISPC_IRQENABLE = 0x%08x", value); + s->dispc.irqen = value & ((s->dispc.rev < 0x30) ? 0xffff : 0x1ffff); + omap_dss_interrupt_update(s); break; - case 0x040: /* DISPC_CONTROL */ - s->dispc.control = value & 0x07ff9fff; + TRACEDISPC("DISPC_CONTROL = 0x%08x", value); + if (s->dispc.rev < 0x30) + s->dispc.control = value & 0x07ff9fff; + else + s->dispc.control = (value & 0xffff9bff) | (s->dispc.control & 0x6000); s->dig.enable = (value >> 1) & 1; s->lcd.enable = (value >> 0) & 1; if (value & (1 << 12)) /* OVERLAY_OPTIMIZATION */ @@ -424,14 +1012,16 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr, * s->dispc.l[0].wininc * All they need to be loaded here from their shadow registers. */ + s->dispc.control &= ~(1 << 6); /* GODIGITAL finished */ } if (value & (1 << 5)) { /* GOLCD */ /* XXX: Likewise for LCD here. */ + s->dispc.control &= ~(1 << 5); /* GOLCD finished */ } s->dispc.invalidate = 1; break; - case 0x044: /* DISPC_CONFIG */ + TRACEDISPC("DISPC_CONFIG = 0x%08x", value); s->dispc.config = value & 0x3fff; /* XXX: * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded @@ -439,134 +1029,246 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr, */ s->dispc.invalidate = 1; break; - case 0x048: /* DISPC_CAPABLE */ + TRACEDISPC("DISPC_CAPABLE = 0x%08x", value); s->dispc.capable = value & 0x3ff; break; - case 0x04c: /* DISPC_DEFAULT_COLOR0 */ + TRACEDISPC("DISPC_DEFAULT_COLOR0 = 0x%08x", value); s->dispc.bg[0] = value & 0xffffff; s->dispc.invalidate = 1; break; case 0x050: /* DISPC_DEFAULT_COLOR1 */ + TRACEDISPC("DISPC_DEFAULT_COLOR1 = 0x%08x", value); s->dispc.bg[1] = value & 0xffffff; s->dispc.invalidate = 1; break; case 0x054: /* DISPC_TRANS_COLOR0 */ + TRACEDISPC("DISPC_TRANS_COLOR0 = 0x%08x", value); s->dispc.trans[0] = value & 0xffffff; s->dispc.invalidate = 1; break; case 0x058: /* DISPC_TRANS_COLOR1 */ + TRACEDISPC("DISPC_TRANS_COLOR1 = 0x%08x", value); s->dispc.trans[1] = value & 0xffffff; s->dispc.invalidate = 1; break; - case 0x060: /* DISPC_LINE_NUMBER */ + TRACEDISPC("DISPC_LINE_NUMBER = 0x%08x", value); s->dispc.line = value & 0x7ff; break; - case 0x064: /* DISPC_TIMING_H */ + TRACEDISPC("DISPC_TIMING_H = 0x%08x", value); s->dispc.timing[0] = value & 0x0ff0ff3f; break; case 0x068: /* DISPC_TIMING_V */ + TRACEDISPC("DISPC_TIMING_V = 0x%08x", value); s->dispc.timing[1] = value & 0x0ff0ff3f; break; case 0x06c: /* DISPC_POL_FREQ */ + TRACEDISPC("DISPC_POL_FREQ = 0x%08x", value); s->dispc.timing[2] = value & 0x0003ffff; break; case 0x070: /* DISPC_DIVISOR */ + TRACEDISPC("DISPC_DIVISOR = 0x%08x", value); s->dispc.timing[3] = value & 0x00ff00ff; break; - + case 0x074: /* DISPC_GLOBAL_ALPHA */ + TRACEDISPC("DISPC_GLOBAL_ALPHA = 0x%08x", value); + s->dispc.global_alpha = value & 0x00ff00ff; + break; case 0x078: /* DISPC_SIZE_DIG */ s->dig.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ s->dig.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ s->dispc.invalidate = 1; + TRACEDISPC("DISPC_SIZE_DIG = 0x%08x (%dx%d)", value, s->dig.nx, s->dig.ny); break; case 0x07c: /* DISPC_SIZE_LCD */ s->lcd.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */ s->lcd.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */ s->dispc.invalidate = 1; + TRACEDISPC("DISPC_SIZE_LCD = 0x%08x (%dx%d)", value, s->lcd.nx, s->lcd.ny); break; + case 0x14c: /* DISPC_VID2_BA0 */ + n++; + case 0x0bc: /* DISPC_VID1_BA0 */ + n++; case 0x080: /* DISPC_GFX_BA0 */ - s->dispc.l[0].addr[0] = (target_phys_addr_t) value; + TRACEDISPC("DISPC_%s_BA0 = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].addr[0] = (target_phys_addr_t) value; s->dispc.invalidate = 1; break; + case 0x150: /* DISPC_VID2_BA1 */ + n++; + case 0x0c0: /* DISPC_VID1_BA1 */ + n++; case 0x084: /* DISPC_GFX_BA1 */ - s->dispc.l[0].addr[1] = (target_phys_addr_t) value; + TRACEDISPC("DISPC_%s_BA1 = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].addr[1] = (target_phys_addr_t) value; s->dispc.invalidate = 1; break; + case 0x154: /* DISPC_VID2_POSITION */ + n++; + case 0x0c4: /* DISPC_VID1_POSITION */ + n++; case 0x088: /* DISPC_GFX_POSITION */ - s->dispc.l[0].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */ - s->dispc.l[0].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */ + s->dispc.l[n].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */ + s->dispc.l[n].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */ s->dispc.invalidate = 1; + TRACEDISPC("DISPC_%s_POSITION = 0x%08x (%d,%d)", LAYERNAME(n), + value, s->dispc.l[n].posx, s->dispc.l[n].posy); break; + case 0x158: /* DISPC_VID2_SIZE */ + n++; + case 0x0c8: /* DISPC_VID1_SIZE */ + n++; case 0x08c: /* DISPC_GFX_SIZE */ - s->dispc.l[0].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */ - s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */ + s->dispc.l[n].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */ + s->dispc.l[n].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */ + TRACEDISPC("DISPC_%s_SIZE = 0x%08x (%dx%d)", LAYERNAME(n), + value, s->dispc.l[n].nx, s->dispc.l[n].ny); s->dispc.invalidate = 1; break; + n++; case 0x0a0: /* DISPC_GFX_ATTRIBUTES */ - s->dispc.l[0].attr = value & 0x7ff; + TRACEDISPC("DISPC_GFX_ATTRIBUTES = 0x%08x", value); + s->dispc.l[0].attr = value & 0xffff; if (value & (3 << 9)) fprintf(stderr, "%s: Big-endian pixel format not supported\n", __FUNCTION__); s->dispc.l[0].enable = value & 1; s->dispc.l[0].bpp = (value >> 1) & 0xf; + s->dispc.l[0].rotation_flag = (value >> 12) & 0x3; + s->dispc.l[0].gfx_format = (value >> 1) & 0xf; + s->dispc.l[0].gfx_channel = (value >> 8) & 0x1; s->dispc.invalidate = 1; break; - case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */ - s->dispc.l[0].tresh = value & 0x01ff01ff; + case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ + n++; + case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ + n++; + case 0x0a4: /* DISPC_GFX_FIFO_THRESHOLD */ + TRACEDISPC("DISPC_%s_FIFO_THRESHOLD = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].tresh = value & ((s->dispc.rev < 0x30) + ? 0x01ff01ff : 0x0fff0fff); break; + case 0x168: /* DISPC_VID2_ROW_INC */ + n++; + case 0x0d8: /* DISPC_VID1_ROW_INC */ + n++; case 0x0ac: /* DISPC_GFX_ROW_INC */ - s->dispc.l[0].rowinc = value; + TRACEDISPC("DISPC_%s_ROW_INC = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].rowinc = value; s->dispc.invalidate = 1; break; + case 0x16c: /* DISPC_VID2_PIXEL_INC */ + n++; + case 0x0dc: /* DISPC_VID1_PIXEL_INC */ + n++; case 0x0b0: /* DISPC_GFX_PIXEL_INC */ - s->dispc.l[0].colinc = value; + TRACEDISPC("DISPC_%s_PIXEL_INC = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].colinc = value; s->dispc.invalidate = 1; break; case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */ + TRACEDISPC("DISPC_GFX_WINDOW_SKIP = 0x%08x", value); s->dispc.l[0].wininc = value; break; case 0x0b8: /* DISPC_GFX_TABLE_BA */ + TRACEDISPC("DISPC_GFX_TABLE_BA = 0x%08x", value); s->dispc.l[0].addr[2] = (target_phys_addr_t) value; s->dispc.invalidate = 1; break; - - case 0x0bc: /* DISPC_VID1_BA0 */ - case 0x0c0: /* DISPC_VID1_BA1 */ - case 0x0c4: /* DISPC_VID1_POSITION */ - case 0x0c8: /* DISPC_VID1_SIZE */ - case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ - case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */ - case 0x0d8: /* DISPC_VID1_ROW_INC */ - case 0x0dc: /* DISPC_VID1_PIXEL_INC */ - case 0x0e0: /* DISPC_VID1_FIR */ - case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ - case 0x0e8: /* DISPC_VID1_ACCU0 */ - case 0x0ec: /* DISPC_VID1_ACCU1 */ - case 0x0f0 ... 0x140: /* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */ - case 0x14c: /* DISPC_VID2_BA0 */ - case 0x150: /* DISPC_VID2_BA1 */ - case 0x154: /* DISPC_VID2_POSITION */ - case 0x158: /* DISPC_VID2_SIZE */ case 0x15c: /* DISPC_VID2_ATTRIBUTES */ - case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */ - case 0x168: /* DISPC_VID2_ROW_INC */ - case 0x16c: /* DISPC_VID2_PIXEL_INC */ + n++; + case 0x0cc: /* DISPC_VID1_ATTRIBUTES */ + n++; + TRACEDISPC("DISPC_%s_ATTRIBUTES = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].attr = value & 0x1fffffff; + break; case 0x170: /* DISPC_VID2_FIR */ + n++; + case 0x0e0: /* DISPC_VID1_FIR */ + n++; + TRACEDISPC("DISPC_%s_FIR = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].fir = value & 0x1fff1fff; + break; case 0x174: /* DISPC_VID2_PICTURE_SIZE */ + n++; + case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */ + n++; + TRACEDISPC("DISPC_%s_PICTURE_SIZE = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].picture_size = value & 0x07ff07ff; + break; case 0x178: /* DISPC_VID2_ACCU0 */ case 0x17c: /* DISPC_VID2_ACCU1 */ - case 0x180 ... 0x1d0: /* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */ + n++; + case 0x0e8: /* DISPC_VID1_ACCU0 */ + case 0x0ec: /* DISPC_VID1_ACCU1 */ + n++; + TRACEDISPC("DISPC_%s_ACCU%d = 0x%08x", LAYERNAME(n), + (int)((addr >> 1) & 1), value); + s->dispc.l[n].accu[(addr >> 1) & 1] = value & 0x03ff03ff; + break; + case 0x180 ... 0x1bc: /* DISPC_VID2_FIR_COEF */ + n++; + case 0x0f0 ... 0x12c: /* DISPC_VID1_FIR_COEF */ + n++; + if (addr & 4) { + TRACEDISPC("DISPC_%s_FIR_COEF_HV%d = 0x%08x", LAYERNAME(n), + (int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8), value); + s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value; + } else { + TRACEDISPC("DISPC_%s_FIR_COEF_H%d = 0x%08x", LAYERNAME(n), + (int)((addr - ((n > 1) ? 0x180 : 0xf0)) / 8), value); + s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value; + } + break; + case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */ + n++; + case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */ + n++; + TRACEDISPC("DISPC_%s_CONV_COEF%d = 0x%08x", LAYERNAME(n), + (int)((addr - ((n > 1) ? 0x1c0 : 0x130)) / 4), value); + s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4] = value; + break; case 0x1d4: /* DISPC_DATA_CYCLE1 */ case 0x1d8: /* DISPC_DATA_CYCLE2 */ case 0x1dc: /* DISPC_DATA_CYCLE3 */ + TRACEDISPC("DISPC_DATA_CYCLE%d = 0x%08x (ignored)", + (int)((addr - 0x1d4) / 4), value); + break; + case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */ + n++; + case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */ + n++; + TRACEDISPC("DISPC_%s_FIR_COEF_V%d = 0x%08x", LAYERNAME(n), + (int)((addr & 0x01f) / 4), value); + s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4] = value & 0x0000ffff; + break; + case 0x220: /* DISPC_CPR_COEF_R */ + TRACEDISPC("DISPC_CPR_COEF_R = 0x%08x", value); + s->dispc.cpr_coef_r = value & 0xffbffbff; + break; + case 0x224: /* DISPC_CPR_COEF_G */ + TRACEDISPC("DISPC_CPR_COEF_G = 0x%08x", value); + s->dispc.cpr_coef_g = value & 0xffbffbff; + break; + case 0x228: /* DISPC_CPR_COEF_B */ + TRACEDISPC("DISPC_CPR_COEF_B = 0x%08x", value); + s->dispc.cpr_coef_b = value & 0xffbffbff; + break; + case 0x234: /* DISPC_VID2_PRELOAD */ + n++; + case 0x230: /* DISPC_VID1_PRELOAD */ + n++; + case 0x22c: /* DISPC_GFX_PRELOAD */ + TRACEDISPC("DISPC_%s_PRELOAD = 0x%08x", LAYERNAME(n), value); + s->dispc.l[n].preload = value & 0x0fff; break; - default: - OMAP_BAD_REG(addr); + OMAP_BAD_REGV(addr, value); + break; } } @@ -653,7 +1355,7 @@ static void omap_rfbi_transfer_start(struct omap_dss_s *s) /* TODO */ s->dispc.irqst |= 1; /* FRAMEDONE */ - omap_dispc_interrupt_update(s); + omap_dss_interrupt_update(s); } static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr) @@ -662,56 +1364,77 @@ static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr) switch (addr) { case 0x00: /* RFBI_REVISION */ + TRACERFBI("RFBI_REVISION: 0x10"); return 0x10; case 0x10: /* RFBI_SYSCONFIG */ + TRACERFBI("RFBI_SYSCONFIG: 0x%08x", s->rfbi.idlemode); return s->rfbi.idlemode; case 0x14: /* RFBI_SYSSTATUS */ + TRACERFBI("RFBI_SYSSTATUS: 0x%08x", 1 | (s->rfbi.busy << 8)); return 1 | (s->rfbi.busy << 8); /* RESETDONE */ case 0x40: /* RFBI_CONTROL */ + TRACERFBI("RFBI_CONTROL: 0x%08x", s->rfbi.control); return s->rfbi.control; case 0x44: /* RFBI_PIXELCNT */ + TRACERFBI("RFBI_PIXELCNT: 0x%08x", s->rfbi.pixels); return s->rfbi.pixels; case 0x48: /* RFBI_LINE_NUMBER */ + TRACERFBI("RFBI_LINE_NUMBER: 0x%08x", s->rfbi.skiplines); return s->rfbi.skiplines; case 0x58: /* RFBI_READ */ case 0x5c: /* RFBI_STATUS */ + TRACERFBI("RFBI_READ/STATUS: 0x%08x", s->rfbi.rxbuf); return s->rfbi.rxbuf; case 0x60: /* RFBI_CONFIG0 */ + TRACERFBI("RFBI_CONFIG0: 0x%08x", s->rfbi.config[0]); return s->rfbi.config[0]; case 0x64: /* RFBI_ONOFF_TIME0 */ + TRACERFBI("RFBI_ONOFF_TIME0: 0x%08x", s->rfbi.time[0]); return s->rfbi.time[0]; case 0x68: /* RFBI_CYCLE_TIME0 */ + TRACERFBI("RFBI_CYCLE_TIME0: 0x%08x", s->rfbi.time[1]); return s->rfbi.time[1]; case 0x6c: /* RFBI_DATA_CYCLE1_0 */ + TRACERFBI("RFBI_DATA_CYCLE1_0: 0x%08x", s->rfbi.data[0]); return s->rfbi.data[0]; case 0x70: /* RFBI_DATA_CYCLE2_0 */ + TRACERFBI("RFBI_DATA_CYCLE2_0: 0x%08x", s->rfbi.data[1]); return s->rfbi.data[1]; case 0x74: /* RFBI_DATA_CYCLE3_0 */ + TRACERFBI("RFBI_DATA_CYCLE3_0: 0x%08x", s->rfbi.data[2]); return s->rfbi.data[2]; case 0x78: /* RFBI_CONFIG1 */ + TRACERFBI("RFBI_CONFIG1: 0x%08x", s->rfbi.config[1]); return s->rfbi.config[1]; case 0x7c: /* RFBI_ONOFF_TIME1 */ + TRACERFBI("RFBI_ONOFF_TIME1: 0x%08x", s->rfbi.time[2]); return s->rfbi.time[2]; case 0x80: /* RFBI_CYCLE_TIME1 */ + TRACERFBI("RFBI_CYCLE_TIME1: 0x%08x", s->rfbi.time[3]); return s->rfbi.time[3]; case 0x84: /* RFBI_DATA_CYCLE1_1 */ + TRACERFBI("RFBI_DATA_CYCLE1_1: 0x%08x", s->rfbi.data[3]); return s->rfbi.data[3]; case 0x88: /* RFBI_DATA_CYCLE2_1 */ + TRACERFBI("RFBI_DATA_CYCLE2_1: 0x%08x", s->rfbi.data[4]); return s->rfbi.data[4]; case 0x8c: /* RFBI_DATA_CYCLE3_1 */ + TRACERFBI("RFBI_DATA_CYCLE3_1: 0x%08x", s->rfbi.data[5]); return s->rfbi.data[5]; case 0x90: /* RFBI_VSYNC_WIDTH */ + TRACERFBI("RFBI_VSYNC_WIDTH: 0x%08x", s->rfbi.vsync); return s->rfbi.vsync; case 0x94: /* RFBI_HSYNC_WIDTH */ + TRACERFBI("RFBI_HSYNC_WIDTH: 0x%08x", s->rfbi.hsync); return s->rfbi.hsync; } OMAP_BAD_REG(addr); @@ -725,12 +1448,14 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, switch (addr) { case 0x10: /* RFBI_SYSCONFIG */ + TRACERFBI("RFBI_SYSCONFIG = 0x%08x", value); if (value & 2) /* SOFTRESET */ omap_rfbi_reset(s); s->rfbi.idlemode = value & 0x19; break; case 0x40: /* RFBI_CONTROL */ + TRACERFBI("RFBI_CONTROL = 0x%08x", value); s->rfbi.control = value & 0xf; s->rfbi.enable = value & 1; if (value & (1 << 4) && /* ITE */ @@ -739,26 +1464,31 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, break; case 0x44: /* RFBI_PIXELCNT */ + TRACERFBI("RFBI_PIXELCNT = 0x%08x", value); s->rfbi.pixels = value; break; case 0x48: /* RFBI_LINE_NUMBER */ + TRACERFBI("RFBI_LINE_NUMBER = 0x%08x", value); s->rfbi.skiplines = value & 0x7ff; break; case 0x4c: /* RFBI_CMD */ + TRACERFBI("RFBI_CMD = 0x%08x", value); if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff); if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff); break; case 0x50: /* RFBI_PARAM */ + TRACERFBI("RFBI_PARAM = 0x%08x", value); if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff); if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff); break; case 0x54: /* RFBI_DATA */ + TRACERFBI("RFBI_DATA = 0x%08x", value); /* TODO: take into account the format set up in s->rfbi.config[?] and * s->rfbi.data[?], but special-case the most usual scenario so that * speed doesn't suffer. */ @@ -774,6 +1504,7 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, omap_rfbi_transfer_stop(s); break; case 0x58: /* RFBI_READ */ + TRACERFBI("RFBI_READ = 0x%08x", value); if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1); else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) @@ -783,6 +1514,7 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, break; case 0x5c: /* RFBI_STATUS */ + TRACERFBI("RFBI_STATUS = 0x%08x", value); if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0); else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) @@ -792,53 +1524,68 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, break; case 0x60: /* RFBI_CONFIG0 */ + TRACERFBI("RFBI_CONFIG0 = 0x%08x", value); s->rfbi.config[0] = value & 0x003f1fff; break; case 0x64: /* RFBI_ONOFF_TIME0 */ + TRACERFBI("RFBI_ONOFF_TIME0 = 0x%08x", value); s->rfbi.time[0] = value & 0x3fffffff; break; case 0x68: /* RFBI_CYCLE_TIME0 */ + TRACERFBI("RFBI_CYCLE_TIME0 = 0x%08x", value); s->rfbi.time[1] = value & 0x0fffffff; break; case 0x6c: /* RFBI_DATA_CYCLE1_0 */ + TRACERFBI("RFBI_DATA_CYCLE1_0 = 0x%08x", value); s->rfbi.data[0] = value & 0x0f1f0f1f; break; case 0x70: /* RFBI_DATA_CYCLE2_0 */ + TRACERFBI("RFBI_DATA_CYCLE2_0 = 0x%08x", value); s->rfbi.data[1] = value & 0x0f1f0f1f; break; case 0x74: /* RFBI_DATA_CYCLE3_0 */ + TRACERFBI("RFBI_DATA_CYCLE3_0 = 0x%08x", value); s->rfbi.data[2] = value & 0x0f1f0f1f; break; case 0x78: /* RFBI_CONFIG1 */ + TRACERFBI("RFBI_CONFIG1 = 0x%08x", value); s->rfbi.config[1] = value & 0x003f1fff; break; case 0x7c: /* RFBI_ONOFF_TIME1 */ + TRACERFBI("RFBI_ONOFF_TIME1 = 0x%08x", value); s->rfbi.time[2] = value & 0x3fffffff; break; case 0x80: /* RFBI_CYCLE_TIME1 */ + TRACERFBI("RFBI_CYCLE_TIME1 = 0x%08x", value); s->rfbi.time[3] = value & 0x0fffffff; break; case 0x84: /* RFBI_DATA_CYCLE1_1 */ + TRACERFBI("RFBI_DATA_CYCLE1_1 = 0x%08x", value); s->rfbi.data[3] = value & 0x0f1f0f1f; break; case 0x88: /* RFBI_DATA_CYCLE2_1 */ + TRACERFBI("RFBI_DATA_CYCLE2_1 = 0x%08x", value); s->rfbi.data[4] = value & 0x0f1f0f1f; break; case 0x8c: /* RFBI_DATA_CYCLE3_1 */ + TRACERFBI("RFBI_DATA_CYCLE3_1 = 0x%08x", value); s->rfbi.data[5] = value & 0x0f1f0f1f; break; case 0x90: /* RFBI_VSYNC_WIDTH */ + TRACERFBI("RFBI_VSYNC_WIDTH = 0x%08x", value); s->rfbi.vsync = value & 0xffff; break; case 0x94: /* RFBI_HSYNC_WIDTH */ + TRACERFBI("RFBI_HSYNC_WIDTH = 0x%08x", value); s->rfbi.hsync = value & 0xffff; break; default: - OMAP_BAD_REG(addr); + OMAP_BAD_REGV(addr, value); + break; } } @@ -857,53 +1604,54 @@ static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = { static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr) { switch (addr) { - case 0x00: /* REV_ID */ - case 0x04: /* STATUS */ - case 0x08: /* F_CONTROL */ - case 0x10: /* VIDOUT_CTRL */ - case 0x14: /* SYNC_CTRL */ - case 0x1c: /* LLEN */ - case 0x20: /* FLENS */ - case 0x24: /* HFLTR_CTRL */ - case 0x28: /* CC_CARR_WSS_CARR */ - case 0x2c: /* C_PHASE */ - case 0x30: /* GAIN_U */ - case 0x34: /* GAIN_V */ - case 0x38: /* GAIN_Y */ - case 0x3c: /* BLACK_LEVEL */ - case 0x40: /* BLANK_LEVEL */ - case 0x44: /* X_COLOR */ - case 0x48: /* M_CONTROL */ - case 0x4c: /* BSTAMP_WSS_DATA */ - case 0x50: /* S_CARR */ - case 0x54: /* LINE21 */ - case 0x58: /* LN_SEL */ - case 0x5c: /* L21__WC_CTL */ - case 0x60: /* HTRIGGER_VTRIGGER */ - case 0x64: /* SAVID__EAVID */ - case 0x68: /* FLEN__FAL */ - case 0x6c: /* LAL__PHASE_RESET */ - case 0x70: /* HS_INT_START_STOP_X */ - case 0x74: /* HS_EXT_START_STOP_X */ - case 0x78: /* VS_INT_START_X */ - case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ - case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ - case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ - case 0x88: /* VS_EXT_STOP_Y */ - case 0x90: /* AVID_START_STOP_X */ - case 0x94: /* AVID_START_STOP_Y */ - case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ - case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ - case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ - case 0xb0: /* TVDETGP_INT_START_STOP_X */ - case 0xb4: /* TVDETGP_INT_START_STOP_Y */ - case 0xb8: /* GEN_CTRL */ - case 0xc4: /* DAC_TST__DAC_A */ - case 0xc8: /* DAC_B__DAC_C */ - return 0; - - default: - break; + case 0x00: /* REV_ID */ + return 0x2; + case 0x04: /* STATUS */ + case 0x08: /* F_CONTROL */ + case 0x10: /* VIDOUT_CTRL */ + case 0x14: /* SYNC_CTRL */ + case 0x1c: /* LLEN */ + case 0x20: /* FLENS */ + case 0x24: /* HFLTR_CTRL */ + case 0x28: /* CC_CARR_WSS_CARR */ + case 0x2c: /* C_PHASE */ + case 0x30: /* GAIN_U */ + case 0x34: /* GAIN_V */ + case 0x38: /* GAIN_Y */ + case 0x3c: /* BLACK_LEVEL */ + case 0x40: /* BLANK_LEVEL */ + case 0x44: /* X_COLOR */ + case 0x48: /* M_CONTROL */ + case 0x4c: /* BSTAMP_WSS_DATA */ + case 0x50: /* S_CARR */ + case 0x54: /* LINE21 */ + case 0x58: /* LN_SEL */ + case 0x5c: /* L21__WC_CTL */ + case 0x60: /* HTRIGGER_VTRIGGER */ + case 0x64: /* SAVID__EAVID */ + case 0x68: /* FLEN__FAL */ + case 0x6c: /* LAL__PHASE_RESET */ + case 0x70: /* HS_INT_START_STOP_X */ + case 0x74: /* HS_EXT_START_STOP_X */ + case 0x78: /* VS_INT_START_X */ + case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ + case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ + case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ + case 0x88: /* VS_EXT_STOP_Y */ + case 0x90: /* AVID_START_STOP_X */ + case 0x94: /* AVID_START_STOP_Y */ + case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ + case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ + case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ + case 0xb0: /* TVDETGP_INT_START_STOP_X */ + case 0xb4: /* TVDETGP_INT_START_STOP_Y */ + case 0xb8: /* GEN_CTRL */ + case 0xc4: /* DAC_TST__DAC_A */ + case 0xc8: /* DAC_B__DAC_C */ + return 0; + + default: + break; } OMAP_BAD_REG(addr); return 0; @@ -913,51 +1661,56 @@ static void omap_venc_write(void *opaque, target_phys_addr_t addr, uint32_t value) { switch (addr) { - case 0x08: /* F_CONTROL */ - case 0x10: /* VIDOUT_CTRL */ - case 0x14: /* SYNC_CTRL */ - case 0x1c: /* LLEN */ - case 0x20: /* FLENS */ - case 0x24: /* HFLTR_CTRL */ - case 0x28: /* CC_CARR_WSS_CARR */ - case 0x2c: /* C_PHASE */ - case 0x30: /* GAIN_U */ - case 0x34: /* GAIN_V */ - case 0x38: /* GAIN_Y */ - case 0x3c: /* BLACK_LEVEL */ - case 0x40: /* BLANK_LEVEL */ - case 0x44: /* X_COLOR */ - case 0x48: /* M_CONTROL */ - case 0x4c: /* BSTAMP_WSS_DATA */ - case 0x50: /* S_CARR */ - case 0x54: /* LINE21 */ - case 0x58: /* LN_SEL */ - case 0x5c: /* L21__WC_CTL */ - case 0x60: /* HTRIGGER_VTRIGGER */ - case 0x64: /* SAVID__EAVID */ - case 0x68: /* FLEN__FAL */ - case 0x6c: /* LAL__PHASE_RESET */ - case 0x70: /* HS_INT_START_STOP_X */ - case 0x74: /* HS_EXT_START_STOP_X */ - case 0x78: /* VS_INT_START_X */ - case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ - case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ - case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ - case 0x88: /* VS_EXT_STOP_Y */ - case 0x90: /* AVID_START_STOP_X */ - case 0x94: /* AVID_START_STOP_Y */ - case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ - case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ - case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ - case 0xb0: /* TVDETGP_INT_START_STOP_X */ - case 0xb4: /* TVDETGP_INT_START_STOP_Y */ - case 0xb8: /* GEN_CTRL */ - case 0xc4: /* DAC_TST__DAC_A */ - case 0xc8: /* DAC_B__DAC_C */ - break; - - default: - OMAP_BAD_REG(addr); + case 0x00: /* REV_ID */ + case 0x04: /* STATUS */ + /* read-only, ignore */ + break; + case 0x08: /* F_CONTROL */ + case 0x10: /* VIDOUT_CTRL */ + case 0x14: /* SYNC_CTRL */ + case 0x1c: /* LLEN */ + case 0x20: /* FLENS */ + case 0x24: /* HFLTR_CTRL */ + case 0x28: /* CC_CARR_WSS_CARR */ + case 0x2c: /* C_PHASE */ + case 0x30: /* GAIN_U */ + case 0x34: /* GAIN_V */ + case 0x38: /* GAIN_Y */ + case 0x3c: /* BLACK_LEVEL */ + case 0x40: /* BLANK_LEVEL */ + case 0x44: /* X_COLOR */ + case 0x48: /* M_CONTROL */ + case 0x4c: /* BSTAMP_WSS_DATA */ + case 0x50: /* S_CARR */ + case 0x54: /* LINE21 */ + case 0x58: /* LN_SEL */ + case 0x5c: /* L21__WC_CTL */ + case 0x60: /* HTRIGGER_VTRIGGER */ + case 0x64: /* SAVID__EAVID */ + case 0x68: /* FLEN__FAL */ + case 0x6c: /* LAL__PHASE_RESET */ + case 0x70: /* HS_INT_START_STOP_X */ + case 0x74: /* HS_EXT_START_STOP_X */ + case 0x78: /* VS_INT_START_X */ + case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */ + case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */ + case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */ + case 0x88: /* VS_EXT_STOP_Y */ + case 0x90: /* AVID_START_STOP_X */ + case 0x94: /* AVID_START_STOP_Y */ + case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */ + case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */ + case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */ + case 0xb0: /* TVDETGP_INT_START_STOP_X */ + case 0xb4: /* TVDETGP_INT_START_STOP_Y */ + case 0xb8: /* GEN_CTRL */ + case 0xc4: /* DAC_TST__DAC_A */ + case 0xc8: /* DAC_B__DAC_C */ + break; + + default: + OMAP_BAD_REGV(addr, value); + break; } } @@ -1007,7 +1760,8 @@ static void omap_im3_write(void *opaque, target_phys_addr_t addr, break; default: - OMAP_BAD_REG(addr); + OMAP_BAD_REGV(addr, value); + break; } } @@ -1023,41 +1777,413 @@ static CPUWriteMemoryFunc *omap_im3_writefn[] = { omap_im3_write, }; -struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, - target_phys_addr_t l3_base, - qemu_irq irq, qemu_irq drq, - omap_clk fck1, omap_clk fck2, omap_clk ck54m, - omap_clk ick1, omap_clk ick2) +static uint32_t omap_dsi_read(void *opaque, target_phys_addr_t addr) +{ + struct omap_dss_s *s = (struct omap_dss_s *)opaque; + uint32_t x; + + switch (addr) { + case 0x000: /* DSI_REVISION */ + TRACEDSI("DSI_REVISION = 0x10"); + return 0x10; + case 0x010: /* DSI_SYSCONFIG */ + TRACEDSI("DSI_SYSCONFIG = 0x%04x", s->dsi.sysconfig); + return s->dsi.sysconfig; + case 0x014: /* DSI_SYSSTATUS */ + TRACEDSI("DSI_SYSSTATUS = 0x01"); + return 1; /* RESET_DONE */ + case 0x018: /* DSI_IRQSTATUS */ + TRACEDSI("DSI_IRQSTATUS = 0x%08x", s->dsi.irqst); + return s->dsi.irqst; + case 0x01c: /* DSI_IRQENABLE */ + TRACEDSI("DSI_IRQENABLE = 0x%08x", s->dsi.irqen); + return s->dsi.irqen; + case 0x040: /* DSI_CTRL */ + TRACEDSI("DSI_CTRL = 0x%08x", s->dsi.ctrl); + return s->dsi.ctrl; + case 0x048: /* DSI_COMPLEXIO_CFG1 */ + TRACEDSI("DSI_COMPLEXIO_CFG1 = 0x%08x", s->dsi.complexio_cfg1); + return s->dsi.complexio_cfg1; + case 0x04c: /* DSI_COMPLEXIO_IRQSTATUS */ + TRACEDSI("DSI_COMPLEXIO_IRQSTATUS = 0x%08x", s->dsi.complexio_irqst); + return s->dsi.complexio_irqst; + case 0x050: /* DSI_COMPLEXIO_IRQENABLE */ + TRACEDSI("DSI_COMPLEXIO_IRQENABLE = 0x%08x", s->dsi.complexio_irqen); + return s->dsi.complexio_irqen; + case 0x054: /* DSI_CLK_CTRL */ + TRACEDSI("DSI_CLK_CTRL = 0x%08x", s->dsi.clk_ctrl); + return s->dsi.clk_ctrl; + case 0x058: /* DSI_TIMING1 */ + TRACEDSI("DSI_TIMING1 = 0x%08x", s->dsi.timing1); + return s->dsi.timing1; + case 0x05c: /* DSI_TIMING2 */ + TRACEDSI("DSI_TIMING2 = 0x%08x", s->dsi.timing2); + return s->dsi.timing2; + case 0x060: /* DSI_VM_TIMING1 */ + TRACEDSI("DSI_VM_TIMING1 = 0x%08x", s->dsi.vm_timing1); + return s->dsi.vm_timing1; + case 0x064: /* DSI_VM_TIMING2 */ + TRACEDSI("DSI_VM_TIMING2 = 0x%08x", s->dsi.vm_timing2); + return s->dsi.vm_timing2; + case 0x068: /* DSI_VM_TIMING3 */ + TRACEDSI("DSI_VM_TIMING3 = 0x%08x", s->dsi.vm_timing3); + return s->dsi.vm_timing3; + case 0x06c: /* DSI_CLK_TIMING */ + TRACEDSI("DSI_CLK_TIMING = 0x%08x", s->dsi.clk_timing); + return s->dsi.clk_timing; + case 0x070: /* DSI_TX_FIFO_VC_SIZE */ + TRACEDSI("DSI_TX_FIFO_VC_SIZE = 0x%08x", s->dsi.tx_fifo_vc_size); + return s->dsi.tx_fifo_vc_size; + case 0x074: /* DSI_RX_FIFO_VC_SIZE */ + TRACEDSI("DSI_RX_FIFO_VC_SIZE = 0x%08x", s->dsi.rx_fifo_vc_size); + return s->dsi.rx_fifo_vc_size; + case 0x078: /* DSI_COMPLEXIO_CFG_2 */ + case 0x07c: /* DSI_RX_FIFO_VC_FULLNESS */ + case 0x080: /* DSI_VM_TIMING4 */ + case 0x084: /* DSI_TX_FIFO_VC_EMPTINESS */ + case 0x088: /* DSI_VM_TIMING5 */ + case 0x08c: /* DSI_VM_TIMING6 */ + case 0x090: /* DSI_VM_TIMING7 */ + case 0x094: /* DSI_STOPCLK_TIMING */ + OMAP_BAD_REG(addr); + break; + case 0x100 ... 0x17c: /* DSI_VCx_xxx */ + x = (addr >> 6) & 3; + switch (addr & 0x1f) { + case 0x00: /* DSI_VCx_CTRL */ + TRACEDSI("DSI_VC%d_CTRL = 0x%08x", x, s->dsi.vc[x].ctrl); + return s->dsi.vc[x].ctrl; + case 0x04: /* DSI_VCx_TE */ + TRACEDSI("DSI_VC%d_TE = 0x%08x", x, s->dsi.vc[x].te); + return s->dsi.vc[x].te; + case 0x08: /* DSI_VCx_LONG_PACKET_HEADER */ + /* write-only */ + TRACEDSI("DSI_VC%d_LONG_PACKET_HEADER = 0", x); + return 0; + case 0x0c: /* DSI_VCx_LONG_PACKET_PAYLOAD */ + /* write-only */ + TRACEDSI("DSI_VC%d_LONG_PACKET_PAYLOAD = 0", x); + return 0; + case 0x10: /* DSI_VCx_SHORT_PACKET_HEADER */ + /* TODO: this should return value from RX FIFO */ + TRACEDSI("DSI_VC%d_SHORT_PACKET_HEADER = 0", x); + return 0; + case 0x18: /* DSI_VCx_IRQSTATUS */ + TRACEDSI("DSI_VC%d_IRQSTATUS = 0x%08x", x, s->dsi.vc[x].irqst); + return s->dsi.vc[x].irqst; + case 0x1c: /* DSI_VCx_IRQENABLE */ + TRACEDSI("DSI_VC%d_IRQENABLE = 0x%08x", x, s->dsi.vc[x].irqen); + return s->dsi.vc[x].irqen; + default: + OMAP_BAD_REG(addr); + } + break; + + case 0x200: /* DSI_PHY_CFG0 */ + TRACEDSI("DSI_PHY_CFG0 = 0x%08x", s->dsi.phy_cfg0); + return s->dsi.phy_cfg0; + case 0x204: /* DSI_PHY_CFG1 */ + TRACEDSI("DSI_PHY_CFG1 = 0x%08x", s->dsi.phy_cfg1); + return s->dsi.phy_cfg1; + case 0x208: /* DSI_PHY_CFG2 */ + TRACEDSI("DSI_PHY_CFG2 = 0x%08x", s->dsi.phy_cfg2); + return s->dsi.phy_cfg2; + case 0x214: /* DSI_PHY_CFG5 */ + TRACEDSI("DSI_PHY_CFG5 = 0xfc000000"); + return 0xfc000000; /* all resets done */ + + case 0x300: /* DSI_PLL_CONTROL */ + TRACEDSI("DSI_PLL_CONTROL = 0x%08x", s->dsi.pll_control); + return s->dsi.pll_control; + case 0x304: /* DSI_PLL_STATUS */ + x = 1; /* DSI_PLLCTRL_RESET_DONE */ + if ((s->dsi.clk_ctrl >> 28) & 3) { /* DSI PLL control powered? */ + if (((s->dsi.pll_config1 >> 1) & 0x7f) && /* DSI_PLL_REGN */ + ((s->dsi.pll_config1 >> 8) & 0x7ff)) { /* DSI_PLL_REGM */ + x |= 2; /* DSI_PLL_LOCK */ + } + } + if ((s->dsi.pll_config2 >> 20) & 1) /* DSI_HSDIVBYPASS */ + x |= (1 << 9); /* DSI_BYPASSACKZ */ + if (!((s->dsi.pll_config2 >> 13) & 1)) /* DSI_PLL_REFEN */ + x |= (1 << 3); /* DSI_PLL_LOSSREF */ + TRACEDSI("DSI_PLL_STATUS = 0x%08x", x); + return x; + case 0x308: /* DSI_PLL_GO */ + TRACEDSI("DSI_PLL_GO = 0x%08x", s->dsi.pll_go); + return s->dsi.pll_go; + case 0x30c: /* DSI_PLL_CONFIGURATION1 */ + TRACEDSI("DSI_PLL_CONFIGURATION1 = 0x%08x", s->dsi.pll_config1); + return s->dsi.pll_config1; + case 0x310: /* DSI_PLL_CONFIGURATION2 */ + TRACEDSI("DSI_PLL_CONFIGURATION2 = 0x%08x", s->dsi.pll_config2); + return s->dsi.pll_config2; + + default: + break; + } + OMAP_BAD_REG(addr); + return 0; +} + +static void omap_dsi_write(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + struct omap_dss_s *s = (struct omap_dss_s *)opaque; + uint32_t x; + + switch (addr) { + case 0x000: /* DSI_REVISION */ + case 0x014: /* DSI_SYSSTATUS */ + case 0x07c: /* DSI_RX_FIFO_VC_FULLNESS */ + case 0x084: /* DSI_RX_FIFO_VC_EMPTINESS */ + case 0x214: /* DSI_PHY_CFG5 */ + case 0x304: /* DSI_PLL_STATUS */ + /* read-only, ignore */ + break; + case 0x010: /* DSI_SYSCONFIG */ + TRACEDSI("DSI_SYSCONFIG = 0x%08x", value); + if (value & 2) /* SOFT_RESET */ + omap_dsi_reset(s); + else + s->dsi.sysconfig = value; + break; + case 0x018: /* DSI_IRQSTATUS */ + TRACEDSI("DSI_IRQSTATUS = 0x%08x", value); + s->dsi.irqst &= ~(value & 0x1fc3b0); + break; + case 0x01c: /* DSI_IRQENABLE */ + TRACEDSI("DSI_IRQENABLE = 0x%08x", value); + s->dsi.irqen = value & 0x1fc3b0; + break; + case 0x040: /* DSI_CTRL */ + TRACEDSI("DSI_CTRL = 0x%08x", value); + s->dsi.ctrl = value & 0x7ffffff; + break; + case 0x048: /* DSI_COMPLEXIO_CFG_1 */ + TRACEDSI("DSI_COMPLEXIO_CFG1 = 0x%08x", value); + value |= 1 << 29; /* RESET_DONE */ + value |= 1 << 21; /* LDO_POWER_GOOD_STATE */ + /* copy PWR_CMD directly to PWR_STATUS */ + value &= ~(3 << 25); + value |= (value >> 2) & (3 << 25); + s->dsi.complexio_cfg1 = value; + break; + case 0x04c: /* DSI_COMPLEXIO_IRQSTATUS */ + TRACEDSI("DSI_COMPLEXIO_IRQSTATUS = 0x%08x", value); + s->dsi.complexio_irqst &= ~(value & 0xc3f39ce7); + if (s->dsi.complexio_irqst) + s->dsi.irqst |= (1 << 10); /* COMPLEXIO_ERR_IRQ */ + else + s->dsi.irqst &= ~(1 << 10); /* COMPLEXIO_ERR_IRQ */ + break; + case 0x050: /* DSI_COMPLEXIO_IRQENABLE */ + TRACEDSI("DSI_COMPLEXIO_IRQENABLE = 0x%08x", value); + s->dsi.complexio_irqen = value & 0xc3f39ce7; + break; + case 0x054: /* DSI_CLK_CTRL */ + TRACEDSI("DSI_CLK_CTRL = 0x%08x", value); + value &= 0xc03fffff; + /* copy PLL_PWR_CMD directly to PLL_PWR_STATUS */ + value |= (value >> 2) & (3 << 28); + s->dsi.clk_ctrl = value; + break; + case 0x058: /* DSI_TIMING1 */ + TRACEDSI("DSI_TIMING1 = 0x%08x", value); + value &= ~(1 << 15); /* deassert ForceTxStopMode signal */ + s->dsi.timing1 = value; + break; + case 0x05c: /* DSI_TIMING2 */ + TRACEDSI("DSI_TIMING2 = 0x%08x", value); + s->dsi.timing2 = value; + break; + case 0x060: /* DSI_VM_TIMING1 */ + TRACEDSI("DSI_VM_TIMING1 = 0x%08x", value); + s->dsi.vm_timing1 = value; + break; + case 0x064: /* DSI_VM_TIMING2 */ + TRACEDSI("DSI_VM_TIMING2 = 0x%08x", value); + s->dsi.vm_timing2 = value & 0x0fffffff; + break; + case 0x068: /* DSI_VM_TIMING3 */ + TRACEDSI("DSI_VM_TIMING3 = 0x%08x", value); + s->dsi.vm_timing3 = value; + break; + case 0x06c: /* DSI_CLK_TIMING */ + TRACEDSI("DSI_CLK_TIMING = 0x%08x", value); + s->dsi.clk_timing = value & 0xffff; + break; + case 0x070: /* DSI_TX_FIFO_VC_SIZE */ + TRACEDSI("DSI_TX_FIFO_VC_SIZE = 0x%08x", value); + s->dsi.tx_fifo_vc_size = value & 0xf7f7f7f7; + break; + case 0x074: /* DSI_RX_FIFO_VC_SIZE */ + TRACEDSI("DSI_RX_FIFO_VC_SIZE = 0x%08x", value); + s->dsi.rx_fifo_vc_size = value & 0xf7f7f7f7; + break; + case 0x078: /* DSI_COMPLEXIO_CFG_2 */ + case 0x080: /* DSI_VM_TIMING4 */ + case 0x088: /* DSI_VM_TIMING5 */ + case 0x08c: /* DSI_VM_TIMING6 */ + case 0x090: /* DSI_VM_TIMING7 */ + case 0x094: /* DSI_STOPCLK_TIMING */ + OMAP_BAD_REGV(addr, value); + break; + case 0x100 ... 0x17c: /* DSI_VCx_xxx */ + x = (addr >> 6) & 3; + switch (addr & 0x1f) { + case 0x00: /* DSI_VCx_CTRL */ + TRACEDSI("DSI_VC%d_CTRL = 0x%08x", x, value); + if (value & 1) { /* VC_EN */ + s->dsi.vc[x].ctrl &= ~0x40; /* BTA_EN */ + s->dsi.vc[x].ctrl |= 0x1; /* VC_EN */ + } else { + s->dsi.vc[x].ctrl = (s->dsi.vc[x].ctrl & 0x11c020) | + (value & 0x3fee039f); + } +// if (value & 0x40) { /* BTA_EN */ +// s->dsi.irqst |= 1 << x; /* VIRTUAL_CHANNELx_IRQ */ +// s->dsi.vc[x].irqst |= 0x20; /* BTA_IRQ */ +// omap_dss_interrupt_update(s); +// } + break; + case 0x04: /* DSI_VCx_TE */ + TRACEDSI("DSI_VC%d_TE = 0x%08x", x, value); + value &= 0xc0ffffff; + if (s->dsi.vc[x].ctrl & 1) { /* VC_EN */ + value &= ~(1 << 30); /* TE_EN */ + value |= s->dsi.vc[x].te & (1 << 30); + } + s->dsi.vc[x].te = value; + break; + case 0x08: /* DSI_VCx_LONG_PACKET_HEADER */ + TRACEDSI("DSI_VC%d_LONG_PACKET_HEADER = 0x%08x", x, value); + s->dsi.vc[x].lp_header = value; + break; + case 0x0c: /* DSI_VCx_LONG_PACKET_PAYLOAD */ + TRACEDSI("DSI_VC%d_LONG_PACKET_PAYLOAD = 0x%08x", x, value); + s->dsi.vc[x].lp_payload = value; + break; + case 0x10: /* DSI_VCx_SHORT_PACKET_HEADER */ + TRACEDSI("DSI_VC%d_SHORT_PACKET_HEADER = 0x%08x", x, value); + s->dsi.vc[x].sp_header = value; + break; + case 0x18: /* DSI_VCx_IRQSTATUS */ + TRACEDSI("DSI_VC%d_IRQSTATUS = 0x%08x", x, value); + s->dsi.vc[x].irqst &= ~(value & 0x1ff); + if (s->dsi.vc[x].irqst) + s->dsi.irqst |= 1 << x; /* VIRTUAL_CHANNELx_IRQ */ + else + s->dsi.irqst &= ~(1 << x); /* VIRTUAL_CHANNELx_IRQ */ + break; + case 0x1c: /* DSI_VCx_IRQENABLE */ + TRACEDSI("DSI_VC%d_IRQENABLE = 0x%08x", x, value); + s->dsi.vc[x].irqen = value & 0x1ff; + break; + default: + OMAP_BAD_REG(addr); + } + break; + + case 0x200: /* DSI_PHY_CFG0 */ + TRACEDSI("DSI_PHY_CFG0 = 0x%08x", value); + s->dsi.phy_cfg0 = value; + break; + case 0x204: /* DSI_PHY_CFG1 */ + TRACEDSI("DSI_PHY_CFG1 = 0x%08x", value); + s->dsi.phy_cfg1 = value; + break; + case 0x208: /* DSI_PHY_CFG2 */ + TRACEDSI("DSI_PHY_CFG2 = 0x%08x", value); + s->dsi.phy_cfg2 = value; + break; + + case 0x300: /* DSI_PLL_CONTROL */ + TRACEDSI("DSI_PLL_CONTROL = 0x%08x", value); + s->dsi.pll_control = value & 0x1f; + break; + case 0x308: /* DSI_PLL_GO */ + TRACEDSI("DSI_PLL_GO = 0x%08x", value); + /* TODO: check if we need to update something here */ + value &= ~1; /* mark it done */ + s->dsi.pll_go = value & 1; + break; + case 0x30c: /* DSI_PLL_CONFIGURATION1 */ + TRACEDSI("DSI_PLL_CONFIGURATION1 = 0x%08x", value); + s->dsi.pll_config1 = value & 0x7ffffff; + break; + case 0x310: /* DSI_PLL_CONFIGURATION2 */ + TRACEDSI("DSI_PLL_CONFIGURATION2 = 0x%08x", value); + s->dsi.pll_config2 = value & 0x1fffff; + break; + + default: + OMAP_BAD_REGV(addr, value); + break; + } +} + +static CPUReadMemoryFunc *omap_dsi_readfn[] = { + omap_badwidth_read32, + omap_badwidth_read32, + omap_dsi_read, +}; + +static CPUWriteMemoryFunc *omap_dsi_writefn[] = { + omap_badwidth_write32, + omap_badwidth_write32, + omap_dsi_write, +}; + +struct omap_dss_s *omap_dss_init(struct omap_mpu_state_s *mpu, + struct omap_target_agent_s *ta, + qemu_irq irq, qemu_irq drq, + omap_clk fck1, omap_clk fck2, omap_clk ck54m, + omap_clk ick1, omap_clk ick2) { int iomemtype[5]; + int region_base = 0; struct omap_dss_s *s = (struct omap_dss_s *) qemu_mallocz(sizeof(struct omap_dss_s)); s->irq = irq; s->drq = drq; - omap_dss_reset(s); iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn, - omap_diss1_writefn, s); + omap_diss1_writefn, s); iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn, - omap_disc1_writefn, s); + omap_disc1_writefn, s); iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn, - omap_rfbi1_writefn, s); + omap_rfbi1_writefn, s); iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn, - omap_venc1_writefn, s); - iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn, - omap_im3_writefn, s); - omap_l4_attach(ta, 0, iomemtype[0]); - omap_l4_attach(ta, 1, iomemtype[1]); - omap_l4_attach(ta, 2, iomemtype[2]); - omap_l4_attach(ta, 3, iomemtype[3]); - cpu_register_physical_memory(l3_base, 0x1000, iomemtype[4]); - -#if 0 - s->state = graphic_console_init(omap_update_display, - omap_invalidate_display, omap_screen_dump, s); -#endif + omap_venc1_writefn, s); + + if (cpu_class_omap3(mpu)) { + s->dispc.rev = 0x30; + omap_dsi_reset(s); + + iomemtype[4] = l4_register_io_memory(0, omap_dsi_readfn, + omap_dsi_writefn, s); + omap_l4_attach(ta, 0, iomemtype[4]); + region_base = 1; + } else { + s->dispc.rev = 0x20; + + iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn, + omap_im3_writefn, s); + cpu_register_physical_memory(0x68000800, 0x1000, iomemtype[4]); + } + + omap_l4_attach(ta, region_base+0, iomemtype[0]); /* DISS */ + omap_l4_attach(ta, region_base+1, iomemtype[1]); /* DISC */ + omap_l4_attach(ta, region_base+2, iomemtype[2]); /* RFBI */ + omap_l4_attach(ta, region_base+3, iomemtype[3]); /* VENC */ + + omap_dss_reset(s); + register_savevm("omap_dss", -1, 0, + omap_dss_save_state, omap_dss_load_state, s); + return s; } @@ -1067,3 +2193,160 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip) hw_error("%s: wrong CS %i\n", __FUNCTION__, cs); s->rfbi.chip[cs] = chip; } + +void omap3_lcd_panel_attach(struct omap_dss_s *dss, + int cs, + struct omap3_lcd_panel_s *lcd_panel) +{ + if (cs < 0 || cs > 1) + cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs); + dss->omap_lcd_panel[cs] = lcd_panel; + lcd_panel->dss = dss; +} + +/*omap3 lcd panel stuff*/ + +#define DEPTH 8 +#include "omap3_lcd_panel_template.h" +#define DEPTH 15 +#include "omap3_lcd_panel_template.h" +#define DEPTH 16 +#include "omap3_lcd_panel_template.h" +#define DEPTH 24 +#include "omap3_lcd_panel_template.h" +#define DEPTH 32 +#include "omap3_lcd_panel_template.h" + +/* Bytes(!) per pixel */ +static const int omap3_lcd_panel_bpp[0x10] = { + 0, /* 0x0: BITMAP1 (CLUT) */ + 0, /* 0x1: BITMAP2 (CLUT) */ + 0, /* 0x2: BITMAP4 (CLUT) */ + 0, /* 0x3: BITMAP8 (CLUT) */ + 2, /* 0x4: RGB12 (unpacked 16-bit container)*/ + 2, /* 0x5: ARGB16 */ + 2, /* 0x6: RGB16 */ + 0, /* 0x7: reserved */ + 4, /* 0x8: RGB24 (unpacked in 32-bit container) */ + 3, /* 0x9: RGB24 (packed in 24-bit container) */ + 2, /* 0xa: YUV2 422 */ + 2, /* 0xb: UYVY 422 */ + 4, /* 0xc: ARGB32 */ + 4, /* 0xd: RGBA32 */ + 4, /* 0xe: RGBx32 (24-bit RGB aligned on MSB of the 32-bit container) */ + 0, /* 0xf: reserved */ +}; + +static inline void omap3_lcd_panel_invalidate_display(void *opaque) +{ + struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque; + s->invalidate = 1; +} + +static void omap3_lcd_panel_update_display(void *opaque) +{ + struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque; + struct omap_dss_s *dss = s->dss; + const uint32_t lcd_width = dss->lcd.nx; + const uint32_t lcd_height = dss->lcd.ny; + uint32_t graphic_width, graphic_height; + uint32_t start_x, start_y; + const uint32_t lcd_Bpp = omap3_lcd_panel_bpp[dss->dispc.l[0].gfx_format]; + uint32_t dss_Bpp; + uint32_t linesize, y; + uint32_t copy_width, copy_height; + uint8_t *src, *dest; + target_phys_addr_t size; + + if (!dss->lcd.enable + || dss->dispc.l[0].gfx_channel /* 24bit digital out */ + || ((dss->dispc.control & (1 << 11))) /* RFBI */ + || !lcd_Bpp) + return; + + /* check for setup changes since last visit only if flagged */ + if (dss->dispc.invalidate) { + dss->dispc.invalidate = 0; + if (lcd_width != ds_get_width(s->state) + || lcd_height != ds_get_height(s->state)) { + qemu_console_resize(s->state, lcd_width, lcd_height); + s->invalidate = 1; + } + int gf = dss->dispc.l[0].gfx_format; + if (!(dss->dispc.l[0].rotation_flag)) { /* rotation*/ + switch (ds_get_bits_per_pixel(s->state)) { + case 8: s->line_fn = omap3_lcd_panel_draw_fn_8[gf]; break; + case 15: s->line_fn = omap3_lcd_panel_draw_fn_15[gf]; break; + case 16: s->line_fn = omap3_lcd_panel_draw_fn_16[gf]; break; + case 24: s->line_fn = omap3_lcd_panel_draw_fn_24[gf]; break; + case 32: s->line_fn = omap3_lcd_panel_draw_fn_32[gf]; break; + default: s->line_fn = 0; break; + } + } else { + switch (ds_get_bits_per_pixel(s->state)) { + case 8: s->line_fn = omap3_lcd_panel_draw_fn_r_8[gf]; break; + case 15: s->line_fn = omap3_lcd_panel_draw_fn_r_15[gf]; break; + case 16: s->line_fn = omap3_lcd_panel_draw_fn_r_16[gf]; break; + case 24: s->line_fn = omap3_lcd_panel_draw_fn_r_24[gf]; break; + case 32: s->line_fn = omap3_lcd_panel_draw_fn_r_32[gf]; break; + default: s->line_fn = 0; break; + } + } + } + if (!s->line_fn) { + fprintf(stderr, + "%s: line_fn is NULL - host bpp=%d, omap3 lcd gfx_format=%d\n", + __FUNCTION__, + ds_get_bits_per_pixel(s->state), + dss->dispc.l[0].gfx_format); + exit(1); + } + + /* Resolution */ + graphic_width = dss->dispc.l[0].nx; + graphic_height = dss->dispc.l[0].ny; + start_x = dss->dispc.l[0].posx; + start_y = dss->dispc.l[0].posy; + + dest = ds_get_data(s->state); + linesize = ds_get_linesize(s->state); + + dss_Bpp = linesize / ds_get_width(s->state); + + dest += linesize * start_y; + dest += start_x * dss_Bpp; + + if ((start_x + graphic_width) > lcd_width) + copy_width = lcd_width - start_x; + else + copy_width = graphic_width; + copy_height = lcd_height > graphic_height ? graphic_height : lcd_height; + + size = copy_height * copy_width * lcd_Bpp; + src = cpu_physical_memory_map(dss->dispc.l[0].addr[0], &size, 0); + if (src) { + if (size == copy_height * copy_width * lcd_Bpp) { + for (y = start_y; y < copy_height; y++) { + s->line_fn(dest, src, copy_width * lcd_Bpp); + src += graphic_width * lcd_Bpp; + dest += linesize; + } + dpy_update(s->state, start_x, start_y, graphic_width, graphic_height); + } + cpu_physical_memory_unmap(src, size, 0, size); + } + s->invalidate = 0; + + dss->dispc.irqst |= 1; /* FRAMEDONE */ + omap_dss_interrupt_update(dss); +} + +void *omap3_lcd_panel_init() +{ + struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *) qemu_mallocz(sizeof(*s)); + + s->state = graphic_console_init(omap3_lcd_panel_update_display, + omap3_lcd_panel_invalidate_display, + NULL, NULL, s); + return s; +}