summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 */