diff options
-rw-r--r-- | drivers/media/platform/soc_camera/tegra_camera/common.c | 26 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/tegra_camera/common.h | 1 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/tegra_camera/vi2.c | 92 |
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 */ |