From 141076cd925f093adff5971ae8970ae339007ae4 Mon Sep 17 00:00:00 2001 From: Alex Feinman Date: Fri, 16 May 2014 15:55:05 +0100 Subject: Added continuous mode capture support Signed-off-by: Bryan Wu Change-Id: I67c50ff86b53a6c1001d2b688251dc55bd2eff55 Reviewed-on: http://git-master/r/419070 Reviewed-by: Winnie Hsu --- arch/arm/mach-tegra/board-cardhu-sensors.c | 13 ++++-- drivers/media/video/tegra_v4l2_camera.c | 63 ++++++++++++++++++++++++++---- include/media/tegra_v4l2_camera.h | 4 +- 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 @@ -1229,6 +1233,7 @@ int __init cardhu_sensors_init(void) i2c_register_board_info(PCA954x_I2C_BUS2, cardhu_i2c8_board_info, ARRAY_SIZE(cardhu_i2c8_board_info)); +#endif #endif pmu_tca6416_init(); 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_ */ -- cgit v1.2.3