diff options
-rw-r--r-- | drivers/video/mcde/display-samsung_s6d16d0.c | 3 | ||||
-rw-r--r-- | drivers/video/mcde/display-sony_acx424akp_dsi.c | 3 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_hw.c | 162 | ||||
-rw-r--r-- | include/video/mcde.h | 8 |
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 { |