]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
media: tegra_camera: optimize single shot mode
authorBryan Wu <pengw@nvidia.com>
Thu, 9 Jul 2015 23:22:59 +0000 (16:22 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Thu, 16 Jul 2015 03:17:47 +0000 (20:17 -0700)
Current single shot mode, pixel parser is disabled after capture one
frame and software waits for memory write ack done syncpoint, which
only gives us half the frame rate.

Optimized single shot mode:
 - during capture setup, set single shot mode
 - for each frame, wait for FRAME_START syncpoint
 - arm single shot bit to start capture
 - for the last frame, wait for MWA_DONE syncpoint to make sure capture
   finished.

With optimized single shot mode, frame rate is about 4208x3120 @ 24fps
for IMX135, 1920x1080 @ 30fps for AR0261 and 3280x2464 @ 21fps for
IMX219 (2 lanes).

Bug 1639982

Change-Id: I00a434254c9783358872095f05b8765fe391182e
Signed-off-by: Bryan Wu <pengw@nvidia.com>
Reviewed-on: http://git-master/r/768664
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
Reviewed-by: David Wang (SW-TEGRA) <davidw@nvidia.com>
drivers/media/platform/soc_camera/tegra_camera/vi2.c

index 7bec559a4f90145dcdf3b633e44ba1867759f8b5..fa8e5e9437b8c1e7227239b1251ac34c129a4b2c 100644 (file)
@@ -53,6 +53,19 @@ module_param(tpg_mode, int, 0644);
 
 /* VI registers */
 #define TEGRA_VI_CFG_VI_INCR_SYNCPT                    0x000
+#if (IS_ENABLED(CONFIG_ARCH_TEGRA_12x_SOC) || \
+       IS_ENABLED(CONFIG_ARCH_TEGRA_13x_SOC))
+#define        VI_MW_REQ_DONE                          4
+#define        VI_MW_ACK_DONE                          6
+#define        VI_FRAME_START                          9
+#define        VI_LINE_START                           11
+#else
+#define        VI_LINE_START                           4
+#define        VI_FRAME_START                          5
+#define        VI_MW_REQ_DONE                          6
+#define        VI_MW_ACK_DONE                          7
+#endif
+
 #define TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL              0x004
 #define TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR              0x008
 #define TEGRA_VI_CFG_CTXSW                             0x020
@@ -478,6 +491,15 @@ static void vi2_free_syncpts(struct vi2_channel *chan)
        nvhost_free_syncpt(chan->syncpt_id);
 }
 
+static u32 vi2_syncpt_cond(u32 cond, int port)
+{
+       if (IS_ENABLED(CONFIG_ARCH_TEGRA_12x_SOC) ||
+           IS_ENABLED(CONFIG_ARCH_TEGRA_13x_SOC))
+               return (cond + port * 1) << 8;
+       else
+               return (cond + port * 4) << 8;
+}
+
 static int vi2_clock_start(struct vi2_camera *vi2_cam,
                           struct vi2_camera_clk *clks, int num_clks)
 {
@@ -945,21 +967,38 @@ static int vi2_stop_streaming(struct tegra_camera *cam,
        struct vi2_camera *vi2_cam = (struct vi2_camera *)cam;
        int port = icd_to_port(icd);
        struct vi2_channel *chan = &vi2_cam->channels[port];
-       struct list_head *buf_head, *tmp;
 
-       mutex_lock(&chan->work_mutex);
+       u32 val;
+       int err = 0;
 
-       spin_lock_irq(&chan->videobuf_queue_lock);
-       list_for_each_safe(buf_head, tmp, &chan->capture)
-               list_del_init(buf_head);
-       spin_unlock_irq(&chan->videobuf_queue_lock);
+       mutex_lock(&chan->work_mutex);
+       if (!nvhost_syncpt_read_ext_check(cam->pdev, chan->syncpt_id, &val))
+               chan->syncpt_thresh = nvhost_syncpt_incr_max_ext(cam->pdev,
+                                       chan->syncpt_id, 1);
 
-       if (chan->active)
-               chan->active = NULL;
+       /*
+        * Make sure recieve VI_MW_ACK_DONE of the last frame before
+        * stop and dequeue buffer, otherwise MC error will shows up
+        * for the last frame.
+        */
+       TC_VI_REG_WT(vi2_cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
+                    vi2_syncpt_cond(VI_MW_ACK_DONE,  chan->port) |
+                    chan->syncpt_id);
 
+       /*
+        * Ignore error here and just stop pixel parser after waiting,
+        * even if it's timeout
+        */
+       err = nvhost_syncpt_wait_timeout_ext(cam->pdev,
+                       chan->syncpt_id, chan->syncpt_thresh,
+                       TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
+                       NULL,
+                       NULL);
+       csi_pp_regs_write(vi2_cam, chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
+                         0xf002);
        mutex_unlock(&chan->work_mutex);
 
-       return 0;
+       return err;
 }
 
 #define TEGRA_CSI_CILA_PAD_CONFIG0     0x92c
@@ -1187,6 +1226,10 @@ static int vi2_capture_setup(struct vi2_channel *chan)
        csi_regs_write(vi2_cam, chan, TEGRA_VI_CSI_IMAGE_SIZE,
                        (height << 16) | width);
 
+       /* Start pixel parser in single shot mode at beginning */
+       csi_pp_regs_write(vi2_cam, chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
+                         0xf005);
+
        return 0;
 }
 
@@ -1272,15 +1315,9 @@ static int vi2_capture_start(struct vi2_channel *chan)
        if (err < 0)
                return err;
 
-       if (IS_ENABLED(CONFIG_ARCH_TEGRA_12x_SOC) ||
-           IS_ENABLED(CONFIG_ARCH_TEGRA_13x_SOC))
-               TC_VI_REG_WT(vi2_cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
-                       ((6 + chan->port * 1) << 8) | chan->syncpt_id);
-       else
-               TC_VI_REG_WT(vi2_cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
-                       ((7 + chan->port * 4) << 8) | chan->syncpt_id);
-       csi_pp_regs_write(vi2_cam, chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
-                         0xf005);
+       TC_VI_REG_WT(vi2_cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
+                    vi2_syncpt_cond(VI_FRAME_START,  chan->port) |
+                    chan->syncpt_id);
        csi_regs_write(vi2_cam, chan, TEGRA_VI_CSI_SINGLE_SHOT, 0x1);
 
        if (!nvhost_syncpt_read_ext_check(cam->pdev, chan->syncpt_id, &val))
@@ -1316,10 +1353,6 @@ static int vi2_capture_frame(struct vi2_channel *chan)
 
        while (retry) {
                err = vi2_capture_start(chan);
-               /* Capturing succeed, stop capturing */
-               csi_pp_regs_write(vi2_cam, chan,
-                                 TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
-                                 0xf002);
                if (err) {
                        retry--;
                        continue;