edff74cecf353181113e78fb5488b87313b2d84f
[openwrt/staging/neocturne.git] /
1 From 99e2a119c5dc323c698f8b7f699c20599c05e23e Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Tue, 5 Mar 2019 15:43:27 +0000
4 Subject: [PATCH 396/703] media: bcm2835-unicam: Add support for enum
5 framesizes and frameintervals
6
7 vidioc_enum_framesizes and vidioc_enum_frameintervals weren't implemented,
8 therefore clients couldn't enumerate the supported resolutions.
9
10 Implement them by forwarding on to the sensor driver.
11
12 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
13 ---
14 .../media/platform/bcm2835/bcm2835-unicam.c | 94 +++++++++++++++++++
15 1 file changed, 94 insertions(+)
16
17 --- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
18 +++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
19 @@ -1406,6 +1406,84 @@ static int unicam_g_edid(struct file *fi
20 return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
21 }
22
23 +static int unicam_enum_framesizes(struct file *file, void *priv,
24 + struct v4l2_frmsizeenum *fsize)
25 +{
26 + struct unicam_device *dev = video_drvdata(file);
27 + const struct unicam_fmt *fmt;
28 + struct v4l2_subdev_frame_size_enum fse;
29 + int ret;
30 +
31 + /* check for valid format */
32 + fmt = find_format_by_pix(dev, fsize->pixel_format);
33 + if (!fmt) {
34 + unicam_dbg(3, dev, "Invalid pixel code: %x\n",
35 + fsize->pixel_format);
36 + return -EINVAL;
37 + }
38 +
39 + fse.index = fsize->index;
40 + fse.pad = 0;
41 + fse.code = fmt->code;
42 +
43 + ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse);
44 + if (ret)
45 + return ret;
46 +
47 + unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
48 + __func__, fse.index, fse.code, fse.min_width, fse.max_width,
49 + fse.min_height, fse.max_height);
50 +
51 + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
52 + fsize->discrete.width = fse.max_width;
53 + fsize->discrete.height = fse.max_height;
54 +
55 + return 0;
56 +}
57 +
58 +static int unicam_enum_frameintervals(struct file *file, void *priv,
59 + struct v4l2_frmivalenum *fival)
60 +{
61 + struct unicam_device *dev = video_drvdata(file);
62 + const struct unicam_fmt *fmt;
63 + struct v4l2_subdev_frame_interval_enum fie = {
64 + .index = fival->index,
65 + .width = fival->width,
66 + .height = fival->height,
67 + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
68 + };
69 + int ret;
70 +
71 + fmt = find_format_by_pix(dev, fival->pixel_format);
72 + if (!fmt)
73 + return -EINVAL;
74 +
75 + fie.code = fmt->code;
76 + ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval,
77 + NULL, &fie);
78 + if (ret)
79 + return ret;
80 +
81 + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
82 + fival->discrete = fie.interval;
83 +
84 + return 0;
85 +}
86 +
87 +static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
88 +{
89 + struct unicam_device *dev = video_drvdata(file);
90 +
91 + return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a);
92 +}
93 +
94 +static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
95 +{
96 + struct unicam_device *dev = video_drvdata(file);
97 +
98 + return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a);
99 +}
100 +
101 static int unicam_g_dv_timings(struct file *file, void *priv,
102 struct v4l2_dv_timings *timings)
103 {
104 @@ -1613,6 +1691,12 @@ static const struct v4l2_ioctl_ops unica
105 .vidioc_g_edid = unicam_g_edid,
106 .vidioc_s_edid = unicam_s_edid,
107
108 + .vidioc_enum_framesizes = unicam_enum_framesizes,
109 + .vidioc_enum_frameintervals = unicam_enum_frameintervals,
110 +
111 + .vidioc_g_parm = unicam_g_parm,
112 + .vidioc_s_parm = unicam_s_parm,
113 +
114 .vidioc_s_dv_timings = unicam_s_dv_timings,
115 .vidioc_g_dv_timings = unicam_g_dv_timings,
116 .vidioc_query_dv_timings = unicam_query_dv_timings,
117 @@ -1850,6 +1934,16 @@ static int unicam_probe_complete(struct
118 v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_DV_TIMINGS);
119 v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_QUERY_DV_TIMINGS);
120 }
121 + if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
122 + v4l2_disable_ioctl(&unicam->video_dev,
123 + VIDIOC_ENUM_FRAMEINTERVALS);
124 + if (!v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
125 + v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_G_PARM);
126 + if (!v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
127 + v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_S_PARM);
128 +
129 + if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
130 + v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_FRAMESIZES);
131
132 ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev);
133 if (ret) {