summaryrefslogtreecommitdiff
path: root/drivers/media
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
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')
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/common.c26
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/common.h1
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/vi2.c92
3 files changed, 82 insertions, 37 deletions
diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.c b/drivers/media/platform/soc_camera/tegra_camera/common.c
index 370035f1e824..d8b4ff1d4d58 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/common.c
+++ b/drivers/media/platform/soc_camera/tegra_camera/common.c
@@ -179,7 +179,6 @@ static void tegra_camera_deactivate(struct tegra_camera_dev *cam)
{
struct tegra_camera_ops *cam_ops = cam->ops;
-
if (cam_ops->clks_disable)
cam_ops->clks_disable(cam);
@@ -227,8 +226,6 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *cam)
while (retry) {
err = cam->ops->capture_start(cam, buf);
- /* Capturing succeed, stop capturing */
- cam->ops->capture_stop(cam, port);
if (err) {
retry--;
@@ -533,27 +530,12 @@ static int tegra_camera_stop_streaming(struct vb2_queue *q)
vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct tegra_camera_dev *cam = ici->priv;
- struct list_head *buf_head, *tmp;
-
+ struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
+ struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
+ int port = pdata->port;
mutex_lock(&cam->work_mutex);
-
- spin_lock_irq(&cam->videobuf_queue_lock);
- list_for_each_safe(buf_head, tmp, &cam->capture) {
- struct tegra_camera_buffer *buf = container_of(buf_head,
- struct tegra_camera_buffer,
- queue);
- if (buf->icd == icd)
- list_del_init(buf_head);
- }
- spin_unlock_irq(&cam->videobuf_queue_lock);
-
- if (cam->active) {
- struct tegra_camera_buffer *buf = to_tegra_vb(cam->active);
- if (buf->icd == icd)
- cam->active = NULL;
- }
-
+ cam->ops->capture_stop(cam, port);
mutex_unlock(&cam->work_mutex);
return 0;
diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.h b/drivers/media/platform/soc_camera/tegra_camera/common.h
index d4ffe414d7d8..18da08cb6a86 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/common.h
+++ b/drivers/media/platform/soc_camera/tegra_camera/common.h
@@ -122,7 +122,6 @@ struct tegra_camera_dev {
int tpg_mode;
int sof;
-
int cal_done;
};
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 */