summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorTroy Kisky <troy.kisky@boundarydevices.com>2013-10-22 12:44:51 -0700
committerMax Krummenacher <max.krummenacher@toradex.com>2015-12-26 13:46:19 +0100
commit7a0e6c99a098a8c3b4ca41631814c5d6675530e7 (patch)
tree6955df0762ebc4f90949417ea119ed8f8aafd332 /drivers/media
parent90a9dfc61fcd7dd4ce4c1aa4cbcaf22addc7c0d5 (diff)
fix camera power down
Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.c41
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.h2
2 files changed, 38 insertions, 5 deletions
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
index ed2d82245407..57f1ad9e28cb 100644
--- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
@@ -1564,6 +1564,37 @@ static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
return retval;
}
+static void power_down_callback(struct work_struct *work)
+{
+ cam_data *cam = container_of(work, struct _cam_data, power_down_work.work);
+
+ down(&cam->busy_lock);
+ if (!cam->open_count) {
+ vidioc_int_s_power(cam->sensor, 0);
+ cam->power_on = 0;
+ }
+ up(&cam->busy_lock);
+}
+
+/* cam->busy_lock is held */
+void power_up_camera(cam_data *cam)
+{
+ if (cam->power_on) {
+ cancel_delayed_work(&cam->power_down_work);
+ return;
+ }
+ vidioc_int_s_power(cam->sensor, 1);
+ vidioc_int_init(cam->sensor);
+ vidioc_int_dev_init(cam->sensor);
+ cam->power_on = 1;
+}
+
+
+void power_off_camera(cam_data *cam)
+{
+ schedule_delayed_work(&cam->power_down_work, (HZ * 2));
+}
+
/*!
* V4L interface - open function
*
@@ -1707,9 +1738,7 @@ static int mxc_v4l_open(struct file *file)
cam_fmt.fmt.pix.pixelformat,
csi_param);
clk_prepare_enable(sensor->sensor_clk);
- vidioc_int_s_power(cam->sensor, 1);
- vidioc_int_init(cam->sensor);
- vidioc_int_dev_init(cam->sensor);
+ power_up_camera(cam);
}
file->private_data = dev;
@@ -1766,7 +1795,6 @@ static int mxc_v4l_close(struct file *file)
}
if (--cam->open_count == 0) {
- vidioc_int_s_power(cam->sensor, 0);
clk_disable_unprepare(sensor->sensor_clk);
wait_event_interruptible(cam->power_queue,
cam->low_power == false);
@@ -1791,6 +1819,7 @@ static int mxc_v4l_close(struct file *file)
wake_up_interruptible(&cam->enc_queue);
mxc_free_frames(cam);
cam->enc_counter++;
+ power_off_camera(cam);
}
up(&cam->busy_lock);
@@ -2672,6 +2701,7 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev)
init_MUTEX(&cam->param_lock);
init_MUTEX(&cam->busy_lock);
+ INIT_DELAYED_WORK(&cam->power_down_work, power_down_callback);
cam->video_dev = video_device_alloc();
if (cam->video_dev == NULL)
@@ -2959,7 +2989,8 @@ static int mxc_v4l2_resume(struct platform_device *pdev)
wake_up_interruptible(&cam->power_queue);
if (cam->sensor && cam->open_count) {
- vidioc_int_s_power(cam->sensor, 1);
+ if ((cam->overlay_on == true) || (cam->capture_on == true))
+ vidioc_int_s_power(cam->sensor, 1);
if (!cam->mclk_on[cam->mclk_source]) {
ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C,
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
index f6717752d4b9..d16b40574c63 100644
--- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
@@ -114,6 +114,8 @@ typedef struct _cam_data {
struct semaphore busy_lock;
int open_count;
+ struct delayed_work power_down_work;
+ int power_on;
/* params lock for this camera */
struct semaphore param_lock;