summaryrefslogtreecommitdiff
path: root/drivers/media/video/tegra_v4l2_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/tegra_v4l2_camera.c')
-rw-r--r--drivers/media/video/tegra_v4l2_camera.c63
1 files changed, 55 insertions, 8 deletions
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,