aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-4.19/950-0336-media-bcm2835-unicam-Add-support-for-enum-framesizes.patch
blob: c1686f55cd68f6581961909f58a1a0a2b6fc8a21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
From 7c876909bc0a6d23124689d5fca89657a4fcb5a5 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Tue, 5 Mar 2019 15:43:27 +0000
Subject: [PATCH] media: bcm2835-unicam: Add support for enum
 framesizes and frameintervals

vidioc_enum_framesizes and vidioc_enum_frameintervals weren't implemented,
therefore clients couldn't enumerate the supported resolutions.

Implement them by forwarding on to the sensor driver.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
---
 .../media/platform/bcm2835/bcm2835-unicam.c   | 94 +++++++++++++++++++
 1 file changed, 94 insertions(+)

--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
@@ -1406,6 +1406,84 @@ static int unicam_g_edid(struct file *fi
 	return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
 }
 
+static int unicam_enum_framesizes(struct file *file, void *priv,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	struct unicam_device *dev = video_drvdata(file);
+	const struct unicam_fmt *fmt;
+	struct v4l2_subdev_frame_size_enum fse;
+	int ret;
+
+	/* check for valid format */
+	fmt = find_format_by_pix(dev, fsize->pixel_format);
+	if (!fmt) {
+		unicam_dbg(3, dev, "Invalid pixel code: %x\n",
+			   fsize->pixel_format);
+		return -EINVAL;
+	}
+
+	fse.index = fsize->index;
+	fse.pad = 0;
+	fse.code = fmt->code;
+
+	ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse);
+	if (ret)
+		return ret;
+
+	unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
+		   __func__, fse.index, fse.code, fse.min_width, fse.max_width,
+		   fse.min_height, fse.max_height);
+
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete.width = fse.max_width;
+	fsize->discrete.height = fse.max_height;
+
+	return 0;
+}
+
+static int unicam_enum_frameintervals(struct file *file, void *priv,
+				      struct v4l2_frmivalenum *fival)
+{
+	struct unicam_device *dev = video_drvdata(file);
+	const struct unicam_fmt *fmt;
+	struct v4l2_subdev_frame_interval_enum fie = {
+		.index = fival->index,
+		.width = fival->width,
+		.height = fival->height,
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	int ret;
+
+	fmt = find_format_by_pix(dev, fival->pixel_format);
+	if (!fmt)
+		return -EINVAL;
+
+	fie.code = fmt->code;
+	ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval,
+			       NULL, &fie);
+	if (ret)
+		return ret;
+
+	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+	fival->discrete = fie.interval;
+
+	return 0;
+}
+
+static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct unicam_device *dev = video_drvdata(file);
+
+	return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a);
+}
+
+static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct unicam_device *dev = video_drvdata(file);
+
+	return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a);
+}
+
 static int unicam_g_dv_timings(struct file *file, void *priv,
 			       struct v4l2_dv_timings *timings)
 {
@@ -1613,6 +1691,12 @@ static const struct v4l2_ioctl_ops unica
 	.vidioc_g_edid			= unicam_g_edid,
 	.vidioc_s_edid			= unicam_s_edid,
 
+	.vidioc_enum_framesizes		= unicam_enum_framesizes,
+	.vidioc_enum_frameintervals	= unicam_enum_frameintervals,
+
+	.vidioc_g_parm			= unicam_g_parm,
+	.vidioc_s_parm			= unicam_s_parm,
+
 	.vidioc_s_dv_timings		= unicam_s_dv_timings,
 	.vidioc_g_dv_timings		= unicam_g_dv_timings,
 	.vidioc_query_dv_timings	= unicam_query_dv_timings,
@@ -1850,6 +1934,16 @@ static int unicam_probe_complete(struct
 		v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_DV_TIMINGS);
 		v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_QUERY_DV_TIMINGS);
 	}
+	if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
+		v4l2_disable_ioctl(&unicam->video_dev,
+				   VIDIOC_ENUM_FRAMEINTERVALS);
+	if (!v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
+		v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_G_PARM);
+	if (!v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
+		v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_S_PARM);
+
+	if (!v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
+		v4l2_disable_ioctl(&unicam->video_dev, VIDIOC_ENUM_FRAMESIZES);
 
 	ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev);
 	if (ret) {