]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00142551-2 IPUv3 FB:Support HW triple buffer
authorLiu Ying <Ying.Liu@freescale.com>
Tue, 24 May 2011 02:04:02 +0000 (10:04 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:09:07 +0000 (14:09 +0200)
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)

drivers/video/mxc/mxc_ipuv3_fb.c
drivers/video/mxc/mxcfb.c
include/linux/mxcfb.h

index b3bf655f6f04fdfa1b399a6452e9fb2d176a9fed..efdb664a1d7b60136e9803ad1197550eb253d90f 100644 (file)
@@ -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;
 }
index 52694e49e69d59e2fb9807b1e0d9fdb71e0a4fa5..4dffee5dbde33186d71e25520ed080b8bb0dc45e 100644 (file)
@@ -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,
index c097eef9f6e25d5bf36bb897bb1de15ecd9754c4..c7c555b69de146f01776e1c036dde3e56563b131 100644 (file)
@@ -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;