summaryrefslogtreecommitdiff
path: root/drivers/media/platform/soc_camera/tegra_camera/vi2.c
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2015-05-27 17:09:45 -0700
committerWinnie Hsu <whsu@nvidia.com>2015-06-19 17:27:43 -0700
commit9a9279ad1acf717c69c00724b28ef39acc606eb7 (patch)
treed51baa92f496f09e55df583982145c0f297269aa /drivers/media/platform/soc_camera/tegra_camera/vi2.c
parent554875650a0dcf0f1c8d4e8d7a56bd03b3b9a812 (diff)
media: tegra_camera: optimize single shot mode
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 and 1920x1080 @ 30fps for AR0261. Bug 1639982 Change-Id: I0b15d02c2853647d03f5b2d38a7fe5c145174bd5 Signed-off-by: Bryan Wu <pengw@nvidia.com> Reviewed-on: http://git-master/r/754709 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: David Wang (SW-TEGRA) <davidw@nvidia.com> Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Diffstat (limited to 'drivers/media/platform/soc_camera/tegra_camera/vi2.c')
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/vi2.c92
1 files changed, 78 insertions, 14 deletions
diff --git a/drivers/media/platform/soc_camera/tegra_camera/vi2.c b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
index a6c31435dc0a..6a75e8e2e838 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/vi2.c
+++ b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
@@ -31,6 +31,16 @@
#define TEGRA_SYNCPT_CSI_WAIT_TIMEOUT 200
#define TEGRA_VI_CFG_VI_INCR_SYNCPT 0x000
+#define VI_MWA_REQ_DONE (4 << 8)
+#define VI_MWB_REQ_DONE (5 << 8)
+#define VI_MWA_ACK_DONE (6 << 8)
+#define VI_MWB_ACK_DONE (7 << 8)
+#define VI_ISPA_DONE (8 << 8)
+#define VI_CSI_PPA_FRAME_START (9 << 8)
+#define VI_CSI_PPB_FRAME_START (10 << 8)
+#define VI_CSI_PPA_LINE_START (11 << 8)
+#define VI_CSI_PPB_LINE_START (12 << 8)
+
#define TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL 0x004
#define TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR 0x008
#define TEGRA_VI_CFG_CTXSW 0x020
@@ -663,6 +673,9 @@ static int vi2_capture_setup_csi_0(struct tegra_camera_dev *cam,
TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE,
(icd->user_height << 16) | icd->user_width);
+ /* Start pixel parser in single shot mode at beginning */
+ TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0xf005);
+
return 0;
}
@@ -766,6 +779,9 @@ static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam,
TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_SIZE,
(icd->user_height << 16) | icd->user_width);
+ /* Start pixel parser in single shot mode at beginning */
+ TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0xf005);
+
return 0;
}
@@ -954,10 +970,9 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
cam->syncpt_id_csi_a, 1);
TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
- (6 << 8) | cam->syncpt_id_csi_a);
- TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
- 0x0000f005);
+ VI_CSI_PPA_FRAME_START | cam->syncpt_id_csi_a);
TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SINGLE_SHOT, 0x1);
+
err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
cam->syncpt_id_csi_a,
cam->syncpt_csi_a,
@@ -973,10 +988,9 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
cam->syncpt_id_csi_b, 1);
TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
- (7 << 8) | cam->syncpt_id_csi_b);
- TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
- 0x0000f005);
+ VI_CSI_PPB_FRAME_START | cam->syncpt_id_csi_b);
TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_SINGLE_SHOT, 0x1);
+
err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
cam->syncpt_id_csi_b,
cam->syncpt_csi_b,
@@ -1008,15 +1022,65 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
static int vi2_capture_stop(struct tegra_camera_dev *cam, int port)
{
- if (port == TEGRA_CAMERA_PORT_CSI_A)
- TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
- 0x0000f002);
- else if (port == TEGRA_CAMERA_PORT_CSI_B ||
- port == TEGRA_CAMERA_PORT_CSI_C)
- TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
- 0x0000f002);
+ u32 val;
+ int err = 0;
- return 0;
+ if (port == TEGRA_CAMERA_PORT_CSI_A) {
+ if (!nvhost_syncpt_read_ext_check(cam->ndev,
+ cam->syncpt_id_csi_a, &val))
+ cam->syncpt_csi_a = nvhost_syncpt_incr_max_ext(
+ cam->ndev,
+ cam->syncpt_id_csi_a, 1);
+
+ /*
+ * Make sure recieve VI_MWA_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(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
+ VI_MWA_ACK_DONE | cam->syncpt_id_csi_a);
+
+ /*
+ * Ignore error here and just stop pixel parser after waiting,
+ * even if it's timeout
+ */
+ err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
+ cam->syncpt_id_csi_a,
+ cam->syncpt_csi_a,
+ TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
+ NULL,
+ NULL);
+ TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0xf002);
+ } else if (port == TEGRA_CAMERA_PORT_CSI_B ||
+ port == TEGRA_CAMERA_PORT_CSI_C) {
+ if (!nvhost_syncpt_read_ext_check(cam->ndev,
+ cam->syncpt_id_csi_b, &val))
+ cam->syncpt_csi_b = nvhost_syncpt_incr_max_ext(
+ cam->ndev,
+ cam->syncpt_id_csi_b, 1);
+
+ /*
+ * Make sure recieve VI_MWB_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(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
+ VI_MWB_ACK_DONE | cam->syncpt_id_csi_b);
+
+ /*
+ * Ignore error here and just stop pixel parser after waiting,
+ * even if it's timeout
+ */
+ err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
+ cam->syncpt_id_csi_b,
+ cam->syncpt_csi_b,
+ TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
+ NULL,
+ NULL);
+ TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0xf002);
+ }
+
+ return err;
}
/* Reset VI2/CSI2 when activating, no sepecial ops for deactiving */