diff options
author | Liu Ying <Ying.Liu@freescale.com> | 2015-09-11 16:03:06 +0800 |
---|---|---|
committer | Liu Ying <Ying.Liu@freescale.com> | 2015-09-18 18:04:01 +0800 |
commit | bd9c14e24aaf67926dfd31bd819ab0c87129fe4b (patch) | |
tree | 200836495a1beb5c5cfcaab1c92c44e425559021 /drivers/mxc | |
parent | cf7df46e3b1d2142ff354498982194247bf07fea (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.c | 34 |
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; |