summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Bauer <anders.bauer@stericsson.com>2011-12-01 16:41:53 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:04:26 +0200
commit4728b0c732f4d1c8c80702ba8e4bf48bd627d273 (patch)
tree7def874a07adfa61fa4edaa2ca083adc2e694ee0
parent51da222046dff73d3b221b9a8bc72dbe7eb77013 (diff)
video: mcde: use hw frame trig from mcde formatter
DSI BTA always rely on software frame trigger. This patch introduces hardware frame trigger from MCDE formatter and makes it selectable from LCD driver to use either software or hardware frame trigger on DSI BTA vertical synchronization. ST-Ericsson ID: 405619 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Idb7ed9b999760ecf3156895c9fd313a7613b39cb Signed-off-by: Anders Bauer <anders.bauer@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40866 Reviewed-by: Jimmy RUBIN <jimmy.rubin@stericsson.com> Tested-by: Jimmy RUBIN <jimmy.rubin@stericsson.com> Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Per PERSSON <per.xb.persson@stericsson.com>
-rw-r--r--drivers/video/mcde/display-samsung_s6d16d0.c3
-rw-r--r--drivers/video/mcde/display-sony_acx424akp_dsi.c3
-rw-r--r--drivers/video/mcde/mcde_hw.c162
-rw-r--r--include/video/mcde.h8
4 files changed, 117 insertions, 59 deletions
diff --git a/drivers/video/mcde/display-samsung_s6d16d0.c b/drivers/video/mcde/display-samsung_s6d16d0.c
index ac46a37130c..900c3f70aa6 100644
--- a/drivers/video/mcde/display-samsung_s6d16d0.c
+++ b/drivers/video/mcde/display-samsung_s6d16d0.c
@@ -170,7 +170,8 @@ static int __devinit samsung_s6d16d0_probe(struct mcde_display_device *ddev)
di->port.type = MCDE_PORTTYPE_DSI;
di->port.mode = MCDE_PORTMODE_CMD;
di->port.pixel_format = MCDE_PORTPIXFMT_DSI_24BPP;
- di->port.sync_src = MCDE_SYNCSRC_BTA;
+ di->port.sync_src = ddev->port->sync_src;
+ di->port.frame_trig = ddev->port->frame_trig;
di->port.phy.dsi.num_data_lanes = 2;
di->port.phy.dsi.host_eot_gen = true;
/* TODO: Move UI to mcde_hw.c when clk_get_rate(dsi) is done */
diff --git a/drivers/video/mcde/display-sony_acx424akp_dsi.c b/drivers/video/mcde/display-sony_acx424akp_dsi.c
index 78b1477c15c..a197f5cc1df 100644
--- a/drivers/video/mcde/display-sony_acx424akp_dsi.c
+++ b/drivers/video/mcde/display-sony_acx424akp_dsi.c
@@ -268,7 +268,8 @@ static int __devinit sony_acx424akp_probe(struct mcde_display_device *dev)
di->port.type = MCDE_PORTTYPE_DSI;
di->port.mode = MCDE_PORTMODE_CMD;
di->port.pixel_format = MCDE_PORTPIXFMT_DSI_24BPP;
- di->port.sync_src = MCDE_SYNCSRC_BTA;
+ di->port.sync_src = dev->port->sync_src;
+ di->port.frame_trig = dev->port->frame_trig;
di->port.phy.dsi.num_data_lanes = 2;
di->port.link = port->link;
di->port.phy.dsi.host_eot_gen = true;
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);
+ }
}
}
}
diff --git a/include/video/mcde.h b/include/video/mcde.h
index 94344812f33..b9f6a6b55fd 100644
--- a/include/video/mcde.h
+++ b/include/video/mcde.h
@@ -46,7 +46,12 @@ enum mcde_sync_src {
MCDE_SYNCSRC_TE1 = 2, /* MCDE ext TE1 */
MCDE_SYNCSRC_BTA = 3, /* DSI BTA */
MCDE_SYNCSRC_TE_POLLING = 4, /* DSI TE_POLLING */
- MCDE_SYNCSRC_FORMATTER = 5, /* Sync from formatter */
+};
+
+/* Frame trig method */
+enum mcde_trig_method {
+ MCDE_TRIG_HW = 0, /* frame trig from MCDE formatter */
+ MCDE_TRIG_SW = 1, /* frame trig from software */
};
/* Interface pixel formats (output) */
@@ -118,6 +123,7 @@ struct mcde_port {
u8 ifc;
u8 link;
enum mcde_sync_src sync_src;
+ enum mcde_trig_method frame_trig;
bool update_auto_trig;
enum mcde_hdmi_sdtv_switch hdmi_sdtv_switch;
union {