summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorMaciej Socha <maciej.socha@stericsson.com>2011-08-31 12:58:19 +0200
committerRobert Marklund <robert.marklund@stericsson.com>2011-10-05 12:56:35 +0200
commitc0c204a9dac7ae6c12051c9d77d0449db6f130cb (patch)
tree3551925e882227411cbd43df323e6487a3f8cb8b /drivers/video
parent096cee13e52ba31ef807c0eb6b290d3281a036bb (diff)
video: mcde: Match DSI pkt_size to display width
Data for each scanline is split into several equally sized DSI packets. The selected packet size is always less than or equal to the corresponding output FIFO size. Watermark level of output FIFO is set to match the display width whenever possible. Otherwise it is set to split each scanline into several equally sized data chunks. ST-Ericsson ID: 340442, 352852 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ife405bd43a63991f984e14a0615035a2a33c8cb3 Signed-off-by: Maciej Socha <maciej.socha@stericsson.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/mcde/mcde_hw.c97
1 files changed, 58 insertions, 39 deletions
diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c
index 9b009259af9..5db23a8dcf1 100644
--- a/drivers/video/mcde/mcde_hw.c
+++ b/drivers/video/mcde/mcde_hw.c
@@ -1129,21 +1129,6 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
else if (port->ifc == DSI_CMD_MODE && port->link == 2)
mcde_wfld(MCDE_CR, DSICMD2_EN_V1, true);
}
-
- if (chnl->fifo == MCDE_FIFO_C0)
- mcde_wreg(MCDE_CTRLC0, MCDE_CTRLC0_FIFOWTRMRK(
- get_output_fifo_size(MCDE_FIFO_C0)));
- else if (chnl->fifo == MCDE_FIFO_C1)
- mcde_wreg(MCDE_CTRLC1, MCDE_CTRLC1_FIFOWTRMRK(
- get_output_fifo_size(MCDE_FIFO_C1)));
- else if (port->update_auto_trig &&
- (port->sync_src == MCDE_SYNCSRC_TE0))
- mcde_wreg(MCDE_CTRLC0, MCDE_CTRLC0_FIFOWTRMRK(
- get_output_fifo_size(MCDE_FIFO_C0)));
- else if (port->update_auto_trig &&
- (port->sync_src == MCDE_SYNCSRC_TE1))
- mcde_wreg(MCDE_CTRLC1, MCDE_CTRLC1_FIFOWTRMRK(
- get_output_fifo_size(MCDE_FIFO_C1)));
} else if (hardware_version == MCDE_CHIP_VERSION_3_0_8 ||
hardware_version == MCDE_CHIP_VERSION_4_0_4) {
switch (chnl->fifo) {
@@ -1155,15 +1140,11 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
mcde_wfld(MCDE_CTRLA, FORMTYPE,
MCDE_CTRLA_FORMTYPE_DPITV);
mcde_wfld(MCDE_CTRLA, FORMID, port->link);
- mcde_wfld(MCDE_CTRLA, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_A));
} else if (port->type == MCDE_PORTTYPE_DSI) {
mcde_wfld(MCDE_CTRLA, FORMTYPE,
MCDE_CTRLA_FORMTYPE_DSI);
mcde_wfld(MCDE_CTRLA, FORMID,
get_dsi_formid(port));
- mcde_wfld(MCDE_CTRLA, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_A));
}
break;
case MCDE_FIFO_B:
@@ -1174,15 +1155,11 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
mcde_wfld(MCDE_CTRLB, FORMTYPE,
MCDE_CTRLB_FORMTYPE_DPITV);
mcde_wfld(MCDE_CTRLB, FORMID, port->link);
- mcde_wfld(MCDE_CTRLB, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_B));
} else if (port->type == MCDE_PORTTYPE_DSI) {
mcde_wfld(MCDE_CTRLB, FORMTYPE,
MCDE_CTRLB_FORMTYPE_DSI);
mcde_wfld(MCDE_CTRLB, FORMID,
get_dsi_formid(port));
- mcde_wfld(MCDE_CTRLB, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_B));
}
break;
@@ -1195,8 +1172,6 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
mcde_wfld(MCDE_CTRLC0, FORMTYPE,
MCDE_CTRLC0_FORMTYPE_DSI);
mcde_wfld(MCDE_CTRLC0, FORMID, get_dsi_formid(port));
- mcde_wfld(MCDE_CTRLC0, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_C0));
break;
case MCDE_FIFO_C1:
mcde_wreg(MCDE_CHNL0MUXING_V2 + chnl->id *
@@ -1207,8 +1182,6 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
mcde_wfld(MCDE_CTRLC1, FORMTYPE,
MCDE_CTRLC1_FORMTYPE_DSI);
mcde_wfld(MCDE_CTRLC1, FORMID, get_dsi_formid(port));
- mcde_wfld(MCDE_CTRLC1, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_C1));
break;
default:
return -EINVAL;
@@ -1230,8 +1203,6 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
} else if (port->type == MCDE_PORTTYPE_DPI) {
mcde_wfld(MCDE_CR, DPI_EN_V3, true);
}
- mcde_wfld(MCDE_CTRLA, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_A));
break;
case MCDE_FIFO_B:
if (port->type != MCDE_PORTTYPE_DSI)
@@ -1245,9 +1216,6 @@ static int update_channel_static_registers(struct mcde_chnl_state *chnl)
return -EINVAL;
mcde_wfld(MCDE_CR, DSI1_EN_V3, true);
- mcde_wfld(MCDE_CTRLB, FIFOWTRMRK,
- get_output_fifo_size(MCDE_FIFO_B));
-
break;
default:
return -EINVAL;
@@ -1901,6 +1869,35 @@ static void work_sleep_function(struct work_struct *ptr)
/* TODO get from register */
#define MCDE_CLK_FREQ_MHZ 160
+static u32 get_pkt_div(u32 disp_ppl,
+ struct mcde_port *port,
+ enum mcde_fifo fifo)
+{
+ /*
+ * The lines can be split in several packets only on DSI CMD mode.
+ * In DSI VIDEO mode, 1 line = 1 packet.
+ * DPI is like DSI VIDEO (watermark = 1 line).
+ * DPI waits for fifo ready only for the first line of the first frame.
+ * If line is wider than fifo size, one can set watermark
+ * at fifo size, or set it to line size as watermark will be
+ * saturated at fifo size inside MCDE.
+ */
+ switch (port->type) {
+ case MCDE_PORTTYPE_DSI:
+ if (port->ifc == DSI_CMD_MODE)
+ /* Equivalent of ceil(disp_ppl/fifo_size) */
+ return (disp_ppl - 1) / get_output_fifo_size(fifo) + 1;
+ else
+ return 1;
+ break;
+ case MCDE_PORTTYPE_DPI:
+ return 1;
+ break;
+ default:
+ break;
+ }
+ return 1;
+}
void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
struct mcde_port *port, enum mcde_fifo fifo,
@@ -1909,9 +1906,37 @@ void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
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__);
+ /*
+ * Select appropriate fifo watermark.
+ * Watermark will be saturated at fifo size inside MCDE.
+ */
+ fifo_wtrmrk = video_mode->xres /
+ get_pkt_div(video_mode->xres, port, fifo);
+
+ dev_vdbg(&mcde_dev->dev, "%s fifo_watermark=%d for chnl_id=%d\n",
+ __func__, fifo_wtrmrk, chnl_id);
+
+ switch (chnl_id) {
+ case MCDE_CHNL_A:
+ mcde_wfld(MCDE_CTRLA, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ case MCDE_CHNL_B:
+ mcde_wfld(MCDE_CTRLB, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ case MCDE_CHNL_C0:
+ mcde_wfld(MCDE_CTRLC0, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ case MCDE_CHNL_C1:
+ mcde_wfld(MCDE_CTRLC1, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ default:
+ break;
+ }
+
/* Channel */
if (port->update_auto_trig && port->type == MCDE_PORTTYPE_DSI) {
switch (port->sync_src) {
@@ -2011,13 +2036,7 @@ void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
screen_ppl = video_mode->xres;
screen_lpf = video_mode->yres;
- if (screen_ppl == SCREEN_PPL_HIGH) {
- pkt_div = (screen_ppl - 1) /
- get_output_fifo_size(fifo) + 1;
- } else {
- pkt_div = screen_ppl /
- (get_output_fifo_size(fifo) * 2) + 1;
- }
+ pkt_div = get_pkt_div(screen_ppl, port, fifo);
if (video_mode->interlaced)
screen_lpf /= 2;