aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2011-05-24 10:04:02 +0800
committerEric Miao <eric.miao@linaro.org>2011-08-16 12:37:03 +0800
commit747dbf24704a6fb6f6f83d73c55aebdaedd49af8 (patch)
tree326183902dd20c43a1ee6cf56f3a93ecfe3c3571
parent9eee9dc4ec42c338c0f7c166be59423bbea7d5d9 (diff)
ENGR00142551-2 ipuv3fb: Support HW triple buffer
This patch supports HW triple buffer for IPUv3 framebuffer. 1) Remove buf ready check in EOF irq handler, as we think the swap logic will not fail for HW triple buffer case. 2) When V4L2 output/overlay are used, switch to double buffer mode. 3) Changes IPU interface for IPUv1 framebuffer to pass building. Signed-off-by: Liu Ying <Ying.Liu@freescale.com> Signed-off-by: Jason Chen <b02280@freescale.com> (cherry picked from commit 4ada3031e13207902f8c90b33c082759889cb22a) Signed-off-by: Richard Zhao <richard.zhao@freescale.com> Signed-off-by: Eric Miao <eric.miao@linaro.org>
-rw-r--r--drivers/video/mxc/mxc_ipuv3_fb.c63
-rw-r--r--drivers/video/mxc/mxcfb.c1
-rw-r--r--include/linux/mxcfb.h2
3 files changed, 31 insertions, 35 deletions
diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c
index b3bf655f6f04..efdb664a1d7b 100644
--- a/drivers/video/mxc/mxc_ipuv3_fb.c
+++ b/drivers/video/mxc/mxc_ipuv3_fb.c
@@ -83,7 +83,6 @@ struct mxcfb_info {
u32 pseudo_palette[16];
bool wait4vsync;
- uint32_t waitcnt;
struct semaphore flip_sem;
struct semaphore alpha_flip_sem;
struct completion vsync_complete;
@@ -305,7 +304,7 @@ static int _setup_disp_channel2(struct fb_info *fbi)
fb_stride = fbi->fix.line_length;
}
- mxc_fbi->cur_ipu_buf = 1;
+ mxc_fbi->cur_ipu_buf = 2;
sema_init(&mxc_fbi->flip_sem, 1);
if (mxc_fbi->alpha_chan_en) {
mxc_fbi->cur_ipu_alpha_buf = 1;
@@ -324,6 +323,8 @@ static int _setup_disp_channel2(struct fb_info *fbi)
IPU_ROTATE_NONE,
base,
base,
+ (fbi->var.accel_flags ==
+ FB_ACCEL_TRIPLE_FLAG) ? base : 0,
0, 0);
if (retval) {
dev_err(fbi->device,
@@ -339,6 +340,7 @@ static int _setup_disp_channel2(struct fb_info *fbi)
IPU_ROTATE_NONE,
mxc_fbi->alpha_phy_addr1,
mxc_fbi->alpha_phy_addr0,
+ 0,
0, 0);
if (retval) {
dev_err(fbi->device,
@@ -1300,12 +1302,13 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
loc_alpha_en = true;
mxc_graphic_fbi = (struct mxcfb_info *)
(registered_fb[i]->par);
- active_alpha_phy_addr = mxc_fbi->cur_ipu_buf ?
+ active_alpha_phy_addr =
+ mxc_fbi->cur_ipu_alpha_buf ?
mxc_graphic_fbi->alpha_phy_addr1 :
mxc_graphic_fbi->alpha_phy_addr0;
- dev_dbg(info->device, "Updating SDC graphic "
+ dev_dbg(info->device, "Updating SDC alpha "
"buf %d address=0x%08lX\n",
- mxc_fbi->cur_ipu_buf,
+ !mxc_fbi->cur_ipu_alpha_buf,
active_alpha_phy_addr);
break;
}
@@ -1314,7 +1317,8 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
down(&mxc_fbi->flip_sem);
- mxc_fbi->cur_ipu_buf = !mxc_fbi->cur_ipu_buf;
+ mxc_fbi->cur_ipu_buf = (++mxc_fbi->cur_ipu_buf) % 3;
+ mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
dev_dbg(info->device, "Updating SDC %s buf %d address=0x%08lX\n",
info->fix.id, mxc_fbi->cur_ipu_buf, base);
@@ -1325,11 +1329,11 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
if (loc_alpha_en && mxc_graphic_fbi == mxc_fbi &&
ipu_update_channel_buffer(mxc_graphic_fbi->ipu_ch,
IPU_ALPHA_IN_BUFFER,
- mxc_fbi->cur_ipu_buf,
+ mxc_fbi->cur_ipu_alpha_buf,
active_alpha_phy_addr) == 0) {
ipu_select_buffer(mxc_graphic_fbi->ipu_ch,
IPU_ALPHA_IN_BUFFER,
- mxc_fbi->cur_ipu_buf);
+ mxc_fbi->cur_ipu_alpha_buf);
}
ipu_select_buffer(mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
@@ -1338,9 +1342,20 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
ipu_enable_irq(mxc_fbi->ipu_ch_irq);
} else {
dev_err(info->device,
- "Error updating SDC buf %d to address=0x%08lX\n",
- mxc_fbi->cur_ipu_buf, base);
- mxc_fbi->cur_ipu_buf = !mxc_fbi->cur_ipu_buf;
+ "Error updating SDC buf %d to address=0x%08lX, "
+ "current buf %d, buf0 ready %d, buf1 ready %d, "
+ "buf2 ready %d\n", mxc_fbi->cur_ipu_buf, base,
+ ipu_get_cur_buffer_idx(mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER),
+ ipu_check_buffer_ready(mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 0),
+ ipu_check_buffer_ready(mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 1),
+ ipu_check_buffer_ready(mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER, 2));
+ mxc_fbi->cur_ipu_buf = (++mxc_fbi->cur_ipu_buf) % 3;
+ mxc_fbi->cur_ipu_buf = (++mxc_fbi->cur_ipu_buf) % 3;
+ mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
ipu_clear_irq(mxc_fbi->ipu_ch_irq);
ipu_enable_irq(mxc_fbi->ipu_ch_irq);
return -EBUSY;
@@ -1436,30 +1451,8 @@ static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id)
ipu_disable_irq(irq);
mxc_fbi->wait4vsync = 0;
} else {
- if (!ipu_check_buffer_ready(mxc_fbi->ipu_ch,
- IPU_INPUT_BUFFER, mxc_fbi->cur_ipu_buf)
- || (mxc_fbi->waitcnt > 1)) {
- /*
- * This code wait for EOF irq to make sure current
- * buffer showed.
- *
- * Buffer ready will be clear after this buffer
- * begin to show. If it keep 1, it represents this
- * irq come from previous buffer. If so, wait for
- * EOF irq again.
- *
- * Normally, waitcnt will not > 1, if so, something
- * is wrong, then clear it manually.
- */
- if (mxc_fbi->waitcnt > 1)
- ipu_clear_buffer_ready(mxc_fbi->ipu_ch,
- IPU_INPUT_BUFFER,
- mxc_fbi->cur_ipu_buf);
- up(&mxc_fbi->flip_sem);
- ipu_disable_irq(irq);
- mxc_fbi->waitcnt = 0;
- } else
- mxc_fbi->waitcnt++;
+ up(&mxc_fbi->flip_sem);
+ ipu_disable_irq(irq);
}
return IRQ_HANDLED;
}
diff --git a/drivers/video/mxc/mxcfb.c b/drivers/video/mxc/mxcfb.c
index 52694e49e69d..4dffee5dbde3 100644
--- a/drivers/video/mxc/mxcfb.c
+++ b/drivers/video/mxc/mxcfb.c
@@ -241,6 +241,7 @@ static int mxcfb_set_par(struct fb_info *fbi)
fbi->fix.smem_start +
(fbi->fix.line_length * fbi->var.yres),
fbi->fix.smem_start,
+ 0,
0, 0);
if (retval) {
dev_err(fbi->device,
diff --git a/include/linux/mxcfb.h b/include/linux/mxcfb.h
index 58158eee72dc..a92494c3f11a 100644
--- a/include/linux/mxcfb.h
+++ b/include/linux/mxcfb.h
@@ -29,6 +29,8 @@
#define FB_SYNC_CLK_IDLE_EN 0x10000000
#define FB_SYNC_SHARP_MODE 0x08000000
#define FB_SYNC_SWAP_RGB 0x04000000
+#define FB_ACCEL_TRIPLE_FLAG 0x00000000
+#define FB_ACCEL_DOUBLE_FLAG 0x00000001
struct mxcfb_gbl_alpha {
int enable;