f25dbaf44d7fda0d902839eb77b8d2b4bfa99f83
[oweals/openwrt.git] /
1 From 5aa550c39ac7d2b67c253ea51d42b79ecf251d46 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 324/782] media:bcm2835-unicam: Power on subdev on
5  open/release, not streaming
6
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.
10
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.
13
14 See https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=232437
15
16 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
17 ---
18  .../media/platform/bcm2835/bcm2835-unicam.c   | 68 +++++++++++++++----
19  1 file changed, 54 insertions(+), 14 deletions(-)
20
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);
25                 goto err_pm_put;
26         }
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;
31 -       }
32         dev->streaming = 1;
33  
34         unicam_start_rx(dev, addr);
35 @@ -1256,8 +1251,6 @@ static int unicam_start_streaming(struct
36  
37  err_disable_unicam:
38         unicam_disable(dev);
39 -       v4l2_subdev_call(dev->sensor, core, s_power, 0);
40 -err_clock_unprepare:
41         clk_disable_unprepare(dev->clock);
42  err_pm_put:
43         unicam_runtime_put(dev);
44 @@ -1306,11 +1299,6 @@ static void unicam_stop_streaming(struct
45         dev->next_frm = NULL;
46         spin_unlock_irqrestore(&dev->dma_queue_lock, flags);
47  
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");
51 -       }
52 -
53         clk_disable_unprepare(dev->clock);
54         unicam_runtime_put(dev);
55  }
56 @@ -1543,11 +1531,63 @@ static const struct vb2_ops unicam_video
57         .stop_streaming         = unicam_stop_streaming,
58  };
59  
60 +/*
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,
63 + */
64 +static int unicam_open(struct file *file)
65 +{
66 +       struct unicam_device *dev = video_drvdata(file);
67 +       int ret;
68 +
69 +       mutex_lock(&dev->lock);
70 +
71 +       ret = v4l2_fh_open(file);
72 +       if (ret) {
73 +               unicam_err(dev, "v4l2_fh_open failed\n");
74 +               goto unlock;
75 +       }
76 +
77 +       if (!v4l2_fh_is_singular_file(file))
78 +               goto unlock;
79 +
80 +       ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
81 +       if (ret < 0 && ret != -ENOIOCTLCMD) {
82 +               v4l2_fh_release(file);
83 +               goto unlock;
84 +       }
85 +
86 +unlock:
87 +       mutex_unlock(&dev->lock);
88 +       return ret;
89 +}
90 +
91 +static int unicam_release(struct file *file)
92 +{
93 +       struct unicam_device *dev = video_drvdata(file);
94 +       struct v4l2_subdev *sd = dev->sensor;
95 +       bool fh_singular;
96 +       int ret;
97 +
98 +       mutex_lock(&dev->lock);
99 +
100 +       fh_singular = v4l2_fh_is_singular_file(file);
101 +
102 +       ret = _vb2_fop_release(file, NULL);
103 +
104 +       if (fh_singular)
105 +               v4l2_subdev_call(sd, core, s_power, 0);
106 +
107 +       mutex_unlock(&dev->lock);
108 +
109 +       return ret;
110 +}
111 +
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,