summaryrefslogtreecommitdiff
path: root/drivers/video/mcde/mcde_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/mcde/mcde_hw.c')
-rw-r--r--drivers/video/mcde/mcde_hw.c162
1 files changed, 106 insertions, 56 deletions
diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c
index 3b394106416..220b6dcb8e9 100644
--- a/drivers/video/mcde/mcde_hw.c
+++ b/drivers/video/mcde/mcde_hw.c
@@ -975,7 +975,8 @@ static void handle_dsi_irq(struct mcde_chnl_state *chnl, int i)
dsi_wreg(i, DSI_DIRECT_CMD_STS_CLR,
DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR(true));
dev_vdbg(&mcde_dev->dev, "BTA TE DSI%d\n", i);
- do_softwaretrig(chnl);
+ if (chnl->port.frame_trig == MCDE_TRIG_SW)
+ do_softwaretrig(chnl);
}
irq_status = dsi_rfld(i, DSI_CMD_MODE_STS_FLAG, ERR_NO_TE_FLAG);
@@ -1984,13 +1985,94 @@ static void update_vid_frame_parameters(struct mcde_port *port,
blkline_pck - 6);
}
+static void set_vsync_method(u8 idx, struct mcde_port *port)
+{
+ u32 out_synch_src;
+ u32 src_synch;
+
+ if (port->type == MCDE_PORTTYPE_DSI) {
+ switch (port->frame_trig) {
+ case MCDE_TRIG_HW:
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ break;
+ case MCDE_TRIG_SW:
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
+ break;
+ default:
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ break;
+ }
+
+ switch (port->sync_src) {
+ case MCDE_SYNCSRC_OFF:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ break;
+ case MCDE_SYNCSRC_TE0:
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE0;
+ if (src_synch ==
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) {
+ dev_dbg(&mcde_dev->dev, "%s: badly configured "
+ "frame sync, TE0 defaulting "
+ "to hw frame trig\n", __func__);
+ src_synch =
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ }
+ break;
+ case MCDE_SYNCSRC_TE1:
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE1;
+ if (src_synch ==
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) {
+ dev_dbg(&mcde_dev->dev, "%s: badly configured "
+ "frame sync, TE1 defaulting "
+ "to hw frame trig\n", __func__);
+ src_synch =
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ }
+ break;
+ case MCDE_SYNCSRC_BTA:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ break;
+ case MCDE_SYNCSRC_TE_POLLING:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ if (src_synch ==
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) {
+ dev_dbg(&mcde_dev->dev, "%s: badly configured "
+ "frame sync, TE_POLLING defaulting "
+ "to hw frame trig\n", __func__);
+ src_synch =
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ }
+ break;
+ default:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ dev_dbg(&mcde_dev->dev, "%s: no sync src selected, "
+ "defaulting to DSI BTA with "
+ "hw frame trig\n", __func__);
+ break;
+ }
+ } else if (port->type == MCDE_PORTTYPE_DPI) {
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ src_synch = port->update_auto_trig ?
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE :
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
+ }
+
+ mcde_wreg(MCDE_CHNL0SYNCHMOD +
+ idx * MCDE_CHNL0SYNCHMOD_GROUPOFFSET,
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH(src_synch) |
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC(out_synch_src));
+}
+
void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
struct mcde_port *port, enum mcde_fifo fifo,
struct mcde_video_mode *video_mode)
{
u8 idx = chnl_id;
- u32 out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
- u32 src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
u32 fifo_wtrmrk = 0;
dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
@@ -2022,51 +2104,7 @@ void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
break;
}
- /* Channel */
- if (port->type == MCDE_PORTTYPE_DSI) {
- if (port->update_auto_trig) {
- switch (port->sync_src) {
- case MCDE_SYNCSRC_TE0:
- out_synch_src =
- MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE0;
- src_synch =
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
- break;
- case MCDE_SYNCSRC_OFF:
- src_synch =
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
- break;
- case MCDE_SYNCSRC_TE1:
- default:
- out_synch_src =
- MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE1;
- src_synch =
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
- break;
- case MCDE_SYNCSRC_TE_POLLING:
- src_synch =
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
- break;
- case MCDE_SYNCSRC_FORMATTER:
- out_synch_src =
- MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
- src_synch =
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
- break;
- }
- } else {
- if (port->sync_src == MCDE_SYNCSRC_TE0) {
- out_synch_src =
- MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE0;
- src_synch =
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
- }
- }
- } else if (port->type == MCDE_PORTTYPE_DPI) {
- src_synch = port->update_auto_trig ?
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE :
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
- }
+ set_vsync_method(idx, port);
mcde_wreg(MCDE_CHNL0CONF + idx * MCDE_CHNL0CONF_GROUPOFFSET,
MCDE_CHNL0CONF_PPL(regs->ppl-1) |
@@ -2074,10 +2112,6 @@ void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
mcde_wreg(MCDE_CHNL0STAT + idx * MCDE_CHNL0STAT_GROUPOFFSET,
MCDE_CHNL0STAT_CHNLBLBCKGND_EN(false) |
MCDE_CHNL0STAT_CHNLRD(true));
- mcde_wreg(MCDE_CHNL0SYNCHMOD +
- idx * MCDE_CHNL0SYNCHMOD_GROUPOFFSET,
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH(src_synch) |
- MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC(out_synch_src));
mcde_wreg(MCDE_CHNL0BCKGNDCOL + idx * MCDE_CHNL0BCKGNDCOL_GROUPOFFSET,
MCDE_CHNL0BCKGNDCOL_B(0) |
MCDE_CHNL0BCKGNDCOL_G(0) |
@@ -2807,14 +2841,30 @@ static void chnl_update_non_continous(struct mcde_chnl_state *chnl)
if (chnl->port.type == MCDE_PORTTYPE_DSI) {
if (chnl->port.sync_src == MCDE_SYNCSRC_OFF) {
- do_softwaretrig(chnl);
+ if (chnl->port.frame_trig == MCDE_TRIG_SW) {
+ do_softwaretrig(chnl);
+ } else {
+ enable_flow(chnl);
+ disable_flow(chnl);
+ }
dev_vdbg(&mcde_dev->dev, "Channel update (no sync), "
"chnl=%d\n", chnl->id);
} else if (chnl->port.sync_src == MCDE_SYNCSRC_BTA) {
- if (chnl->power_mode == MCDE_DISPLAY_PM_ON)
+ if (chnl->power_mode == MCDE_DISPLAY_PM_ON) {
dsi_te_request(chnl);
- else
- do_softwaretrig(chnl);
+ } else {
+ if (chnl->port.frame_trig == MCDE_TRIG_SW)
+ do_softwaretrig(chnl);
+ }
+ if (chnl->port.frame_trig == MCDE_TRIG_HW) {
+ /*
+ * During BTA TE the MCDE block will be stalled,
+ * once the TE is received the DMA trig will
+ * happen
+ */
+ enable_flow(chnl);
+ disable_flow(chnl);
+ }
}
}
}