diff options
Diffstat (limited to 'board/st/u8500/mcde_hw.c')
-rw-r--r-- | board/st/u8500/mcde_hw.c | 155 |
1 files changed, 111 insertions, 44 deletions
diff --git a/board/st/u8500/mcde_hw.c b/board/st/u8500/mcde_hw.c index 67a36f5e9..a858e67aa 100644 --- a/board/st/u8500/mcde_hw.c +++ b/board/st/u8500/mcde_hw.c @@ -27,13 +27,13 @@ u8 *mcdeio; u8 **dsiio; -static inline u32 dsi_rreg(int __i, u32 __reg) +static inline u32 dsi_rreg(int i, u32 reg) { - return readl(dsiio[__i] + __reg); + return readl(dsiio[i] + reg); } -static inline void dsi_wreg(int __i, u32 __reg, u32 __val) +static inline void dsi_wreg(int i, u32 reg, u32 val) { - writel(__val, dsiio[__i] + __reg); + writel(val, dsiio[i] + reg); } #define dsi_rfld(__i, __reg, __fld) \ ((dsi_rreg(__i, __reg) & __reg##_##__fld##_MASK) >> \ @@ -43,13 +43,13 @@ static inline void dsi_wreg(int __i, u32 __reg, u32 __val) ~__reg##_##__fld##_MASK) | (((__val) << __reg##_##__fld##_SHIFT) & \ __reg##_##__fld##_MASK)) -static inline u32 mcde_rreg(u32 __reg) +static inline u32 mcde_rreg(u32 reg) { - return readl(mcdeio + __reg); + return readl(mcdeio + reg); } -static inline void mcde_wreg(u32 __reg, u32 __val) +static inline void mcde_wreg(u32 reg, u32 val) { - writel(__val, mcdeio + __reg); + writel(val, mcdeio + reg); } #define mcde_rfld(__reg, __fld) \ ((mcde_rreg(__reg) & __reg##_##__fld##_MASK) >> \ @@ -127,10 +127,10 @@ struct chnl_regs { struct mcde_chnl_state { t_bool inuse; enum mcde_chnl id; + enum mcde_fifo fifo; struct mcde_port port; struct mcde_ovly_state *ovly0; struct mcde_ovly_state *ovly1; - const struct chnl_config *cfg; u32 transactionid; u32 transactionid_regs; @@ -154,7 +154,6 @@ static struct mcde_chnl_state channels[] = { }, }; - /* MCDE internal helpers */ static u8 portfmt2dsipacking(enum mcde_port_pix_fmt pix_fmt) { @@ -175,21 +174,98 @@ static u8 portfmt2bpp(enum mcde_port_pix_fmt pix_fmt) } } +static u8 get_dsi_formid(const struct mcde_port *port) +{ + if (port->ifc == DSI_VIDEO_MODE && port->link == 0) + return MCDE_CTRLA_FORMID_DSI0VID; + else if (port->ifc == DSI_VIDEO_MODE && port->link == 1) + return MCDE_CTRLA_FORMID_DSI1VID; + else if (port->ifc == DSI_VIDEO_MODE && port->link == 2) + return MCDE_CTRLA_FORMID_DSI2VID; + else if (port->ifc == DSI_CMD_MODE && port->link == 0) + return MCDE_CTRLA_FORMID_DSI0CMD; + else if (port->ifc == DSI_CMD_MODE && port->link == 1) + return MCDE_CTRLA_FORMID_DSI1CMD; + else if (port->ifc == DSI_CMD_MODE && port->link == 2) + return MCDE_CTRLA_FORMID_DSI2CMD; + return 0; +} + #define DSI_UNIT_INTERVAL_0 0x9 -void update_channel_static_registers(struct mcde_chnl_state *chnl) +static int update_channel_static_registers(struct mcde_chnl_state *chnl) { const struct mcde_port *port = &chnl->port; int i = 0; u8 idx = 2 * port->link + port->ifc; u8 lnk = port->link; - /* Fifo & muxing */ - mcde_wfld(MCDE_CONF0, SWAP_A_C0, TRUE); - mcde_wfld(MCDE_CR, FABMUX, FALSE); + + if (!cpu_is_u8500v2()) { + /* Fifo & muxing */ + mcde_wfld(MCDE_CONF0, SWAP_A_C0_V1, TRUE); + mcde_wfld(MCDE_CR, FABMUX_V1, FALSE); + + if (port->ifc == DSI_VIDEO_MODE && port->link == 0) + mcde_wfld(MCDE_CR, DSIVID0_EN_V1, TRUE); + else if (port->ifc == DSI_VIDEO_MODE && port->link == 1) + mcde_wfld(MCDE_CR, DSIVID1_EN_V1, TRUE); + else if (port->ifc == DSI_VIDEO_MODE && port->link == 2) + mcde_wfld(MCDE_CR, DSIVID2_EN_V1, TRUE); + else if (port->ifc == DSI_CMD_MODE && port->link == 0) + mcde_wfld(MCDE_CR, DSICMD0_EN_V1, TRUE); + else if (port->ifc == DSI_CMD_MODE && port->link == 1) + mcde_wfld(MCDE_CR, DSICMD1_EN_V1, TRUE); + else if (port->ifc == DSI_CMD_MODE && port->link == 2) + mcde_wfld(MCDE_CR, DSICMD2_EN_V1, TRUE); + + mcde_wreg(MCDE_CTRLC0, MCDE_CTRLC0_FIFOWTRMRK(0xa0)); + } else { + switch (chnl->fifo) { + case MCDE_FIFO_A: + mcde_wreg(MCDE_CHNL0MUXING_V2 + chnl->id * + MCDE_CHNL0MUXING_V2_GROUPOFFSET, + MCDE_CHNL0MUXING_V2_FIFO_ID_ENUM(FIFO_A)); + mcde_wfld(MCDE_CTRLA, FORMTYPE, + MCDE_CTRLA_FORMTYPE_DSI); + mcde_wfld(MCDE_CTRLA, FORMID, + get_dsi_formid(port)); + mcde_wfld(MCDE_CTRLA, FIFOWTRMRK, 0x280); + break; + case MCDE_FIFO_B: + mcde_wreg(MCDE_CHNL0MUXING_V2 + chnl->id * + MCDE_CHNL0MUXING_V2_GROUPOFFSET, + MCDE_CHNL0MUXING_V2_FIFO_ID_ENUM(FIFO_B)); + mcde_wfld(MCDE_CTRLB, FORMTYPE, + MCDE_CTRLB_FORMTYPE_DSI); + mcde_wfld(MCDE_CTRLB, FORMID, + get_dsi_formid(port)); + mcde_wfld(MCDE_CTRLB, FIFOWTRMRK, 0x280); + break; + case MCDE_FIFO_C0: + mcde_wreg(MCDE_CHNL0MUXING_V2 + chnl->id * + MCDE_CHNL0MUXING_V2_GROUPOFFSET, + MCDE_CHNL0MUXING_V2_FIFO_ID_ENUM(FIFO_C0)); + mcde_wfld(MCDE_CTRLC0, FORMTYPE, + MCDE_CTRLC0_FORMTYPE_DSI); + mcde_wfld(MCDE_CTRLC0, FORMID, get_dsi_formid(port)); + mcde_wfld(MCDE_CTRLC0, FIFOWTRMRK, 0xa0); + break; + case MCDE_FIFO_C1: + mcde_wreg(MCDE_CHNL0MUXING_V2 + chnl->id * + MCDE_CHNL0MUXING_V2_GROUPOFFSET, + MCDE_CHNL0MUXING_V2_FIFO_ID_ENUM(FIFO_C1)); + mcde_wfld(MCDE_CTRLC1, FORMTYPE, + MCDE_CTRLC1_FORMTYPE_DSI); + mcde_wfld(MCDE_CTRLC1, FORMID, get_dsi_formid(port)); + mcde_wfld(MCDE_CTRLC1, FIFOWTRMRK, 0xa0); + break; + default: + return -EINVAL; + } + } /* Formatter */ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, LINK_EN, TRUE); - dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, BTA_EN, TRUE); dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, READ_EN, TRUE); dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, REG_TE_EN, TRUE); @@ -209,7 +285,7 @@ void update_channel_static_registers(struct mcde_chnl_state *chnl) DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME(1) | DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME(1)); dsi_wfld(lnk, DSI_CMD_MODE_CTL, ARB_MODE, FALSE); - dsi_wfld(lnk, DSI_CMD_MODE_CTL, ARB_PRI, port->ifc == 1); + dsi_wfld(lnk, DSI_CMD_MODE_CTL, ARB_PRI, port->ifc == DSI_CMD_MODE); dsi_wfld(lnk, DSI_CMD_MODE_CTL, TE_TIMEOUT, 0x3ff); dsi_wreg(lnk, DSI_MCTL_MAIN_EN, DSI_MCTL_MAIN_EN_PLL_START(TRUE) | @@ -217,29 +293,18 @@ void update_channel_static_registers(struct mcde_chnl_state *chnl) DSI_MCTL_MAIN_EN_DAT1_EN(TRUE) | DSI_MCTL_MAIN_EN_DAT2_EN(port->phy.dsi.num_data_lanes == 2) | - DSI_MCTL_MAIN_EN_IF1_EN(port->ifc == 0) | - DSI_MCTL_MAIN_EN_IF2_EN(port->ifc == 1)); + DSI_MCTL_MAIN_EN_IF1_EN(port->ifc == DSI_VIDEO_MODE) | + DSI_MCTL_MAIN_EN_IF2_EN(port->ifc == DSI_CMD_MODE)); while (dsi_rfld(lnk, DSI_MCTL_MAIN_STS, CLKLANE_READY) == 0 || dsi_rfld(lnk, DSI_MCTL_MAIN_STS, DAT1_READY) == 0 || dsi_rfld(lnk, DSI_MCTL_MAIN_STS, DAT2_READY) == 0) { mdelay(1); - if (i++ == 10) + if (i++ == 10) { printf("DSI lane not ready (link=%d)!\n", lnk); + return -EINVAL; + } } - - if (port->ifc == 0 && port->link == 0) - mcde_wfld(MCDE_CR, DSIVID0_EN, TRUE); - else if (port->ifc == 0 && port->link == 1) - mcde_wfld(MCDE_CR, DSIVID1_EN, TRUE); - else if (port->ifc == 0 && port->link == 2) - mcde_wfld(MCDE_CR, DSIVID2_EN, TRUE); - else if (port->ifc == 1 && port->link == 0) - mcde_wfld(MCDE_CR, DSICMD0_EN, TRUE); - else if (port->ifc == 1 && port->link == 1) - mcde_wfld(MCDE_CR, DSICMD1_EN, TRUE); - else if (port->ifc == 1 && port->link == 2) - mcde_wfld(MCDE_CR, DSICMD2_EN, TRUE); mcde_wreg(MCDE_DSIVID0CONF0 + idx * MCDE_DSIVID0CONF0_GROUPOFFSET, MCDE_DSIVID0CONF0_BLANKING(0) | @@ -249,10 +314,10 @@ void update_channel_static_registers(struct mcde_chnl_state *chnl) MCDE_DSIVID0CONF0_BYTE_SWAP(FALSE) | MCDE_DSIVID0CONF0_DCSVID_NOTGEN(TRUE)); - if (port->ifc == 0) + if (port->ifc == DSI_VIDEO_MODE) dsi_wfld(port->link, DSI_CMD_MODE_CTL, IF1_ID, port->phy.dsi.virt_id); - else if (port->ifc == 1) + else if (port->ifc == DSI_CMD_MODE) dsi_wfld(port->link, DSI_CMD_MODE_CTL, IF2_ID, port->phy.dsi.virt_id); @@ -260,10 +325,11 @@ void update_channel_static_registers(struct mcde_chnl_state *chnl) mcde_wreg(MCDE_VSCRC0, MCDE_VSCRC0_VSPMIN(1) | MCDE_VSCRC0_VSPMAX(0xff)); - mcde_wreg(MCDE_CTRLC0, MCDE_CTRLC0_FIFOWTRMRK(0xa0)); mcde_wfld(MCDE_CR, MCDEEN, TRUE); dbg_printk("Static registers setup, chnl=%d\n", chnl->id); + + return 0; } static void update_overlay_registers(u8 idx, struct ovly_regs *regs, @@ -310,9 +376,9 @@ static void update_overlay_registers(u8 idx, struct ovly_regs *regs, MCDE_OVL0CR_OVLB(FALSE) | MCDE_OVL0CR_FETCH_ROPC(0) | MCDE_OVL0CR_STBPRIO(0) | - MCDE_OVL0CR_BURSTSIZE(11) | /* TODO: _HW_8W */ - MCDE_OVL0CR_MAXOUTSTANDING(2) | /* TODO: get from ovly */ - MCDE_OVL0CR_ROTBURSTSIZE(2)); /* TODO: _4W, calculate? */ + MCDE_OVL0CR_BURSTSIZE_ENUM(HW_8W) | + MCDE_OVL0CR_MAXOUTSTANDING_ENUM(4_REQ) | + MCDE_OVL0CR_ROTBURSTSIZE_ENUM(HW_8W)); mcde_wreg(MCDE_OVL0CONF + idx * MCDE_OVL0CONF_GROUPOFFSET, MCDE_OVL0CONF_PPL(ppl) | MCDE_OVL0CONF_EXTSRC_ID(idx) | @@ -360,8 +426,6 @@ void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs, MCDE_CHNL0BCKGNDCOL_B(255) | /* TODO: Temp */ MCDE_CHNL0BCKGNDCOL_G(255) | MCDE_CHNL0BCKGNDCOL_R(255)); - mcde_wreg(MCDE_CHNL0PRIO + idx * MCDE_CHNL0PRIO_GROUPOFFSET, - MCDE_CHNL0PRIO_CHNLPRIO(0)); mcde_wfld(MCDE_CRC, POWEREN, TRUE); mcde_wfld(MCDE_CRC, FLOEN, TRUE); @@ -424,16 +488,19 @@ struct mcde_chnl_state *mcde_chnl_get(enum mcde_chnl chnl_id, } chnl->port = *port; + chnl->fifo = fifo; + + if (update_channel_static_registers(chnl) < 0) + return ERR_PTR(-EINVAL); + chnl->synchronized_update = FALSE; chnl->update_x = 0; chnl->update_y = 0; chnl->update_w = 0; chnl->update_h = 0; mcde_chnl_apply(chnl); - - update_channel_static_registers(chnl); - chnl->inuse = TRUE; + return chnl; } @@ -607,7 +674,7 @@ void mcde_ovly_apply(struct mcde_ovly_state *ovly) case MCDE_OVLYPIXFMT_RGB888: ovly->regs.bits_per_pixel = 24; ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_RGB888; - ovly->regs.bgr = TRUE; + ovly->regs.bgr = FALSE; ovly->regs.bebo = FALSE; ovly->regs.opq = TRUE; break; |