summaryrefslogtreecommitdiff
path: root/drivers/mxc
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2015-09-11 16:03:06 +0800
committerLiu Ying <Ying.Liu@freescale.com>2015-09-18 18:04:01 +0800
commitbd9c14e24aaf67926dfd31bd819ab0c87129fe4b (patch)
tree200836495a1beb5c5cfcaab1c92c44e425559021 /drivers/mxc
parentcf7df46e3b1d2142ff354498982194247bf07fea (diff)
MLK-11316-3 video: mxc ipuv3 fb: Change pan display mechanism for PRE workaround
In order to workaround the PRE SoC bug recorded by errata ERR009624, the software cannot write the PRE_CTRL register when the PRE writes the PRE_CTRL register automatically to set the ENABLE bit(bit0) to 1 in the PRE repeat mode. The software mechanism to set the PRE_CTRL register is different for PRE Y resolution higher than 9 lines and lower than or equal to 9 lines. For cases in which Y resolution is higher than 9 lines, before we update PRE shadow, we just need to wait until the PRE store engine status runs out of the problematic PRE automatic writing window. While for cases in which Y resolutin is lower than or equal to 9 lines, we have to update PRE shadow in the buffer flip interrupt handler. Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
Diffstat (limited to 'drivers/mxc')
-rw-r--r--drivers/mxc/ipu3/pre.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/mxc/ipu3/pre.c b/drivers/mxc/ipu3/pre.c
index 87214b390922..6fb61c47606b 100644
--- a/drivers/mxc/ipu3/pre.c
+++ b/drivers/mxc/ipu3/pre.c
@@ -831,14 +831,18 @@ void ipu_pre_disable(int id)
}
EXPORT_SYMBOL(ipu_pre_disable);
-int ipu_pre_set_fb_buffer(int id, unsigned long fb_paddr,
+int ipu_pre_set_fb_buffer(int id, bool resolve,
+ unsigned long fb_paddr,
+ unsigned int y_res,
unsigned int x_crop,
unsigned int y_crop,
unsigned int sec_buf_off,
unsigned int trd_buf_off)
{
struct ipu_pre_data *pre = get_pre(id);
+ unsigned int store_stat, store_block_y;
unsigned long lock_flags;
+ bool update = true;
if (!pre)
return -EINVAL;
@@ -850,7 +854,33 @@ int ipu_pre_set_fb_buffer(int id, unsigned long fb_paddr,
pre_write(pre, BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X(x_crop) |
BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y(y_crop),
HW_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC);
- pre_write(pre, BF_PRE_CTRL_SDW_UPDATE(1), HW_PRE_CTRL_SET);
+
+ /*
+ * Update shadow only when store engine runs out of the problematic
+ * window to workaround the SoC design bug recorded by errata ERR009624.
+ */
+ if (y_res > IPU_PRE_SMALL_LINE) {
+ unsigned long timeout = jiffies + msecs_to_jiffies(20);
+
+ do {
+ if (time_after(jiffies, timeout)) {
+ update = false;
+ dev_warn(pre->dev, "timeout waiting for PRE "
+ "to run out of problematic window for "
+ "shadow update\n");
+ break;
+ }
+
+ store_stat = pre_read(pre, HW_PRE_STORE_ENGINE_STATUS);
+ store_block_y = (store_stat &
+ BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y) >>
+ BP_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y;
+ } while (store_block_y >=
+ (y_res / (resolve ? 4 : 1) - 2) || store_block_y == 0);
+ }
+
+ if (update)
+ pre_write(pre, BF_PRE_CTRL_SDW_UPDATE(1), HW_PRE_CTRL_SET);
spin_unlock_irqrestore(&pre->lock, lock_flags);
return 0;