summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Feinman <alex@1066labs.com>2014-05-16 15:55:05 +0100
committerWinnie Hsu <whsu@nvidia.com>2014-06-04 18:08:00 -0700
commit141076cd925f093adff5971ae8970ae339007ae4 (patch)
treef300afad4e27dddf42b4a4184d78315679f58f76
parentc682f8ce0abb3fccc8a86f478aeb1479938e91c6 (diff)
Added continuous mode capture support
Signed-off-by: Bryan Wu <pengw@nvidia.com> Change-Id: I67c50ff86b53a6c1001d2b688251dc55bd2eff55 Reviewed-on: http://git-master/r/419070 Reviewed-by: Winnie Hsu <whsu@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sensors.c13
-rw-r--r--drivers/media/video/tegra_v4l2_camera.c63
-rw-r--r--include/media/tegra_v4l2_camera.h4
3 files changed, 67 insertions, 13 deletions
diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c
index af66e1f571c6..3c259ebcdba1 100644
--- a/arch/arm/mach-tegra/board-cardhu-sensors.c
+++ b/arch/arm/mach-tegra/board-cardhu-sensors.c
@@ -115,6 +115,8 @@ static struct tegra_camera_platform_data cardhu_ov5640_camera_platform_data = {
.port = TEGRA_CAMERA_PORT_CSI_B,
.lanes = 2,
.continuous_clk = 0,
+ .continuous_capture = 1,
+ .vi_freq = 24000000,
};
static struct soc_camera_link ov5640_iclink = {
@@ -667,7 +669,7 @@ static const struct i2c_board_info cardhu_i2c3_board_info[] = {
},
};
-
+#if !defined(CONFIG_SOC_CAMERA)
static struct nvc_gpio_pdata sh532u_gpio_pdata[] = {
{ SH532U_GPIO_RESET, TEGRA_GPIO_PBB0, false, 0, },
};
@@ -862,6 +864,7 @@ static struct i2c_board_info cardhu_i2c8_board_info[] = {
},
#endif
};
+#endif
static int nct_get_temp(void *_data, long *temp)
{
@@ -1190,14 +1193,15 @@ int __init cardhu_sensors_init(void)
cardhu_camera_init();
cam_tca6416_init();
+ i2c_register_board_info(2, cardhu_i2c3_board_info,
+ ARRAY_SIZE(cardhu_i2c3_board_info));
+
+#if !defined(CONFIG_SOC_CAMERA)
if (board_info.board_id != BOARD_PM315) {
- i2c_register_board_info(2, cardhu_i2c3_board_info,
- ARRAY_SIZE(cardhu_i2c3_board_info));
i2c_register_board_info(2, cardhu_i2c_board_info_tps61050,
ARRAY_SIZE(cardhu_i2c_board_info_tps61050));
}
-
#ifdef CONFIG_VIDEO_OV14810
/* This is disabled by default; To enable this change Kconfig;
* there should be some way to detect dynamically which board
@@ -1230,6 +1234,7 @@ int __init cardhu_sensors_init(void)
ARRAY_SIZE(cardhu_i2c8_board_info));
#endif
+#endif
pmu_tca6416_init();
if (board_info.board_id == BOARD_E1291)
diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c
index 8f71d1702537..237441f9ee31 100644
--- a/drivers/media/video/tegra_v4l2_camera.c
+++ b/drivers/media/video/tegra_v4l2_camera.c
@@ -297,9 +297,12 @@ struct tegra_camera_dev {
struct work_struct work;
struct mutex work_mutex;
+ struct soc_camera_device *icd;
+
u32 syncpt_vi;
u32 syncpt_csi_a;
u32 syncpt_csi_b;
+ int capturing;
/* Debug */
int num_frames;
@@ -724,6 +727,9 @@ static int tegra_camera_capture_setup(struct tegra_camera_dev *pcdev)
enum v4l2_mbus_pixelcode input_code = current_fmt->code;
u32 hdr, input_control = 0x0;
+ if ( !pcdev->icd )
+ pcdev->icd = icd;
+
switch (input_code) {
case V4L2_MBUS_FMT_UYVY8_2X8:
input_control |= 0x2 << 8;
@@ -765,8 +771,11 @@ static int tegra_camera_capture_setup(struct tegra_camera_dev *pcdev)
/* Set up raise-on-edge, so we get an interrupt on end of frame. */
TC_VI_REG_WT(pcdev, TEGRA_VI_VI_RAISE, 0x00000001);
- /* Cleanup registers */
- tegra_camera_capture_clean(pcdev);
+ if ( !pdata->continuous_capture || !pcdev->capturing ) {
+
+ /* Cleanup registers */
+ tegra_camera_capture_clean(pcdev);
+ }
/* Setup registers for CSI-A, CSI-B and VIP inputs */
if (port == TEGRA_CAMERA_PORT_CSI_A)
@@ -850,7 +859,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev,
if (port == TEGRA_CAMERA_PORT_CSI_A) {
pcdev->syncpt_csi_a++;
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
- 0x0000f005);
+ pdata->continuous_capture?0x0000f001 :0x0000f005);
+
err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev,
TEGRA_VI_SYNCPT_CSI_A,
pcdev->syncpt_csi_a,
@@ -859,7 +869,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev,
} else if (port == TEGRA_CAMERA_PORT_CSI_B) {
pcdev->syncpt_csi_b++;
TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
- 0x0000f005);
+ pdata->continuous_capture? 0x0000f001: 0x0000f005);
+
err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev,
TEGRA_VI_SYNCPT_CSI_B,
pcdev->syncpt_csi_b,
@@ -876,6 +887,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev,
NULL);
}
+ pcdev->capturing = 1;
+
if (!err)
return 0;
@@ -1005,6 +1018,20 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev)
static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev)
{
+ struct soc_camera_device *icd = pcdev->icd;
+ if ( icd ) {
+ struct tegra_camera_platform_data *pdata = icd->link->priv;
+
+ if ( pdata->continuous_capture ) {
+ pcdev->capturing = 0;
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
+ 0x0000f003);
+ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
+ 0x0000f003);
+ usleep_range(20000, 21000);
+ }
+ }
+
/* Turn off relevant clocks. */
clk_disable(pcdev->clk_vi);
clk_disable(pcdev->clk_vi_sensor);
@@ -1192,6 +1219,8 @@ static void tegra_camera_work(struct work_struct *work)
struct tegra_camera_dev *pcdev =
container_of(work, struct tegra_camera_dev, work);
struct tegra_buffer *buf;
+ struct soc_camera_device *icd;
+ struct tegra_camera_platform_data *pdata;
while (1) {
mutex_lock(&pcdev->work_mutex);
@@ -1209,10 +1238,15 @@ static void tegra_camera_work(struct work_struct *work)
pcdev->active = &buf->vb;
spin_unlock_irq(&pcdev->videobuf_queue_lock);
- tegra_camera_capture_setup(pcdev);
- if (!pcdev->cal_done) {
- tegra_camera_csi_pad_calibration(pcdev);
- pcdev->cal_done = 1;
+ icd = buf->icd;
+ pdata = icd->link->priv;
+
+ if ( !pdata->continuous_capture || !pcdev->capturing ) {
+ tegra_camera_capture_setup(pcdev);
+ if (!pcdev->cal_done) {
+ tegra_camera_csi_pad_calibration(pcdev);
+ pcdev->cal_done = 1;
+ }
}
tegra_camera_capture_frame(pcdev);
@@ -1670,6 +1704,18 @@ static int tegra_camera_set_fmt(struct soc_camera_device *icd,
return ret;
}
+static int tegra_camera_enum_fsizes(struct soc_camera_device *icd, struct v4l2_frmsizeenum * fsize) {
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ int ret;
+
+ //printk("%s (%d)\n", __func__, fsize->index);
+ ret = v4l2_subdev_call(sd, video, enum_framesizes, fsize);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ return 0;
+}
+
static int tegra_camera_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
@@ -1770,6 +1816,7 @@ static struct soc_camera_host_ops tegra_soc_camera_host_ops = {
.reqbufs = tegra_camera_reqbufs,
.poll = tegra_camera_poll,
.querycap = tegra_camera_querycap,
+ .enum_fsizes = tegra_camera_enum_fsizes,
};
static int __devinit tegra_camera_probe(struct nvhost_device *ndev,
diff --git a/include/media/tegra_v4l2_camera.h b/include/media/tegra_v4l2_camera.h
index f6390b6e5609..aab1cde96d24 100644
--- a/include/media/tegra_v4l2_camera.h
+++ b/include/media/tegra_v4l2_camera.h
@@ -33,8 +33,10 @@ struct tegra_camera_platform_data {
bool flip_h;
bool flip_v;
enum tegra_camera_port port;
- int lanes; /* For CSI port only */
+ int lanes; /* For CSI port only */
bool continuous_clk; /* For CSI port only */
+ bool continuous_capture; /* CSI only */
+ int vi_freq;
};
#endif /* _TEGRA_CAMERA_H_ */