Added continuous mode capture support
Alex Feinman [Fri, 16 May 2014 14:55:05 +0000 (15:55 +0100)]
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>

arch/arm/mach-tegra/board-cardhu-sensors.c
drivers/media/video/tegra_v4l2_camera.c
include/media/tegra_v4l2_camera.h

index af66e1f..3c259eb 100644 (file)
@@ -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)
index 8f71d17..237441f 100644 (file)
@@ -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,
index f6390b6..aab1cde 100644 (file)
@@ -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_ */