1 From bf1805e0c8c4fc05e2a13b0a03b510ff4e523418 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Tue, 29 Jan 2019 15:56:10 +0000
4 Subject: [PATCH] media:bcm2835-unicam: Power on subdev on
5 open/release, not streaming
7 The driver was powering on the source subdevice as part of STREAMON,
8 and powering it off in STREAMOFF. This isn't so great if there is a
9 significant amount of setup required for your device.
11 Copy the approach taken in the Atmel ISC driver where s_power(1) is called
12 on first file handle open, and s_power(0) is called on the last release.
14 See https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=232437
16 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
18 .../media/platform/bcm2835/bcm2835-unicam.c | 68 +++++++++++++++----
19 1 file changed, 54 insertions(+), 14 deletions(-)
21 --- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
22 +++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
23 @@ -1237,11 +1237,6 @@ static int unicam_start_streaming(struct
24 unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
27 - ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
28 - if (ret < 0 && ret != -ENOIOCTLCMD) {
29 - unicam_err(dev, "power on failed in subdev\n");
30 - goto err_clock_unprepare;
34 unicam_start_rx(dev, addr);
35 @@ -1256,8 +1251,6 @@ static int unicam_start_streaming(struct
39 - v4l2_subdev_call(dev->sensor, core, s_power, 0);
41 clk_disable_unprepare(dev->clock);
43 unicam_runtime_put(dev);
44 @@ -1306,11 +1299,6 @@ static void unicam_stop_streaming(struct
46 spin_unlock_irqrestore(&dev->dma_queue_lock, flags);
48 - if (v4l2_subdev_has_op(dev->sensor, core, s_power)) {
49 - if (v4l2_subdev_call(dev->sensor, core, s_power, 0) < 0)
50 - unicam_err(dev, "power off failed in subdev\n");
53 clk_disable_unprepare(dev->clock);
54 unicam_runtime_put(dev);
56 @@ -1543,11 +1531,63 @@ static const struct vb2_ops unicam_video
57 .stop_streaming = unicam_stop_streaming,
61 + * unicam_open : This function is based on the v4l2_fh_open helper function.
62 + * It has been augmented to handle sensor subdevice power management,
64 +static int unicam_open(struct file *file)
66 + struct unicam_device *dev = video_drvdata(file);
69 + mutex_lock(&dev->lock);
71 + ret = v4l2_fh_open(file);
73 + unicam_err(dev, "v4l2_fh_open failed\n");
77 + if (!v4l2_fh_is_singular_file(file))
80 + ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
81 + if (ret < 0 && ret != -ENOIOCTLCMD) {
82 + v4l2_fh_release(file);
87 + mutex_unlock(&dev->lock);
91 +static int unicam_release(struct file *file)
93 + struct unicam_device *dev = video_drvdata(file);
94 + struct v4l2_subdev *sd = dev->sensor;
98 + mutex_lock(&dev->lock);
100 + fh_singular = v4l2_fh_is_singular_file(file);
102 + ret = _vb2_fop_release(file, NULL);
105 + v4l2_subdev_call(sd, core, s_power, 0);
107 + mutex_unlock(&dev->lock);
112 /* unicam capture driver file operations */
113 static const struct v4l2_file_operations unicam_fops = {
114 .owner = THIS_MODULE,
115 - .open = v4l2_fh_open,
116 - .release = vb2_fop_release,
117 + .open = unicam_open,
118 + .release = unicam_release,
119 .read = vb2_fop_read,
120 .poll = vb2_fop_poll,
121 .unlocked_ioctl = video_ioctl2,