bcm27xx: add support for linux v5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.15 / 950-0542-media-bcm2835-unicam-Parse-pad-numbers-correctly.patch
1 From 38c605af2dce528db71bd349ad9ecd41389a52b1 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 23 Sep 2020 15:16:18 +0100
4 Subject: [PATCH] media/bcm2835-unicam: Parse pad numbers correctly
5
6 The driver was making big assumptions about the source device
7 using pad 0 and 1, which doesn't follow for more complex
8 devices where Unicam's source device may be a sink device for
9 something else.
10
11 Read the pad numbers through media controller, and reference
12 them appropriately.
13
14 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
15 ---
16 .../media/platform/bcm2835/bcm2835-unicam.c | 89 ++++++++++++-------
17 1 file changed, 58 insertions(+), 31 deletions(-)
18
19 --- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
20 +++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
21 @@ -383,6 +383,8 @@ struct unicam_node {
22 int open;
23 bool streaming;
24 unsigned int pad_id;
25 + /* Source pad id on the sensor for this node */
26 + unsigned int src_pad_id;
27 /* Pointer pointing to current v4l2_buffer */
28 struct unicam_buffer *cur_frm;
29 /* Pointer pointing to next v4l2_buffer */
30 @@ -591,7 +593,7 @@ static int __subdev_get_format(struct un
31 {
32 struct v4l2_subdev_format sd_fmt = {
33 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
34 - .pad = pad_id
35 + .pad = dev->node[pad_id].src_pad_id,
36 };
37 int ret;
38
39 @@ -613,7 +615,7 @@ static int __subdev_set_format(struct un
40 {
41 struct v4l2_subdev_format sd_fmt = {
42 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
43 - .pad = pad_id
44 + .pad = dev->node[pad_id].src_pad_id,
45 };
46 int ret;
47
48 @@ -1981,7 +1983,7 @@ static int unicam_enum_framesizes(struct
49
50 fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
51 fse.index = fsize->index;
52 - fse.pad = node->pad_id;
53 + fse.pad = node->src_pad_id;
54
55 ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse);
56 if (ret)
57 @@ -2006,6 +2008,7 @@ static int unicam_enum_frameintervals(st
58 const struct unicam_fmt *fmt;
59 struct v4l2_subdev_frame_interval_enum fie = {
60 .index = fival->index,
61 + .pad = node->src_pad_id,
62 .width = fival->width,
63 .height = fival->height,
64 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
65 @@ -2097,8 +2100,13 @@ static int unicam_enum_dv_timings(struct
66 {
67 struct unicam_node *node = video_drvdata(file);
68 struct unicam_device *dev = node->dev;
69 + int ret;
70 +
71 + timings->pad = node->src_pad_id;
72 + ret = v4l2_subdev_call(dev->sensor, pad, enum_dv_timings, timings);
73 + timings->pad = node->pad_id;
74
75 - return v4l2_subdev_call(dev->sensor, pad, enum_dv_timings, timings);
76 + return ret;
77 }
78
79 static int unicam_dv_timings_cap(struct file *file, void *priv,
80 @@ -2106,8 +2114,13 @@ static int unicam_dv_timings_cap(struct
81 {
82 struct unicam_node *node = video_drvdata(file);
83 struct unicam_device *dev = node->dev;
84 + int ret;
85 +
86 + cap->pad = node->src_pad_id;
87 + ret = v4l2_subdev_call(dev->sensor, pad, dv_timings_cap, cap);
88 + cap->pad = node->pad_id;
89
90 - return v4l2_subdev_call(dev->sensor, pad, dv_timings_cap, cap);
91 + return ret;
92 }
93
94 static int unicam_subscribe_event(struct v4l2_fh *fh,
95 @@ -2378,14 +2391,12 @@ static int register_node(struct unicam_d
96 */
97 fmt = get_first_supported_format(unicam);
98
99 - if (!fmt)
100 - /* No compatible formats */
101 - return -EINVAL;
102 -
103 - mbus_fmt.code = fmt->code;
104 - ret = __subdev_set_format(unicam, &mbus_fmt, pad_id);
105 - if (ret)
106 - return -EINVAL;
107 + if (fmt) {
108 + mbus_fmt.code = fmt->code;
109 + ret = __subdev_set_format(unicam, &mbus_fmt, pad_id);
110 + if (ret)
111 + return -EINVAL;
112 + }
113 }
114 if (mbus_fmt.field != V4L2_FIELD_NONE) {
115 /* Interlaced not supported - disable it now. */
116 @@ -2395,7 +2406,8 @@ static int register_node(struct unicam_d
117 return -EINVAL;
118 }
119
120 - node->v_fmt.fmt.pix.pixelformat = fmt->fourcc ? fmt->fourcc
121 + if (fmt)
122 + node->v_fmt.fmt.pix.pixelformat = fmt->fourcc ? fmt->fourcc
123 : fmt->repacked_fourcc;
124 } else {
125 /* Fix this node format as embedded data. */
126 @@ -2408,7 +2420,8 @@ static int register_node(struct unicam_d
127 node->fmt = fmt;
128
129 /* Read current subdev format */
130 - unicam_reset_format(node);
131 + if (fmt)
132 + unicam_reset_format(node);
133
134 if (v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
135 v4l2_std_id tvnorms;
136 @@ -2497,6 +2510,7 @@ static int register_node(struct unicam_d
137 unicam_err(unicam, "Unable to allocate dummy buffer.\n");
138 return -ENOMEM;
139 }
140 +
141 if (pad_id == METADATA_PAD ||
142 !v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
143 v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_STD);
144 @@ -2555,7 +2569,8 @@ static int register_node(struct unicam_d
145 node->registered = true;
146
147 if (pad_id != METADATA_PAD || unicam->sensor_embedded_data) {
148 - ret = media_create_pad_link(&unicam->sensor->entity, pad_id,
149 + ret = media_create_pad_link(&unicam->sensor->entity,
150 + node->src_pad_id,
151 &node->video_dev.entity, 0,
152 MEDIA_LNK_FL_ENABLED |
153 MEDIA_LNK_FL_IMMUTABLE);
154 @@ -2587,8 +2602,10 @@ static void unregister_nodes(struct unic
155 }
156 }
157
158 -static int unicam_probe_complete(struct unicam_device *unicam)
159 +static int unicam_async_complete(struct v4l2_async_notifier *notifier)
160 {
161 + struct unicam_device *unicam = to_unicam_device(notifier->v4l2_dev);
162 + unsigned int i, source_pads = 0;
163 int ret;
164
165 unicam->v4l2_dev.notify = unicam_notify;
166 @@ -2597,7 +2614,20 @@ static int unicam_probe_complete(struct
167 if (!unicam->sensor_state)
168 return -ENOMEM;
169
170 - unicam->sensor_embedded_data = (unicam->sensor->entity.num_pads >= 2);
171 + for (i = 0; i < unicam->sensor->entity.num_pads; i++) {
172 + if (unicam->sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) {
173 + if (source_pads < MAX_NODES) {
174 + unicam->node[source_pads].src_pad_id = i;
175 + unicam_err(unicam, "source pad %u is index %u\n",
176 + source_pads, i);
177 + }
178 + source_pads++;
179 + }
180 + }
181 + if (!source_pads) {
182 + unicam_err(unicam, "No source pads on sensor.\n");
183 + goto unregister;
184 + }
185
186 ret = register_node(unicam, &unicam->node[IMAGE_PAD],
187 V4L2_BUF_TYPE_VIDEO_CAPTURE, IMAGE_PAD);
188 @@ -2606,11 +2636,15 @@ static int unicam_probe_complete(struct
189 goto unregister;
190 }
191
192 - ret = register_node(unicam, &unicam->node[METADATA_PAD],
193 - V4L2_BUF_TYPE_META_CAPTURE, METADATA_PAD);
194 - if (ret) {
195 - unicam_err(unicam, "Unable to register metadata video device.\n");
196 - goto unregister;
197 + if (source_pads >= 2) {
198 + unicam->sensor_embedded_data = true;
199 +
200 + ret = register_node(unicam, &unicam->node[METADATA_PAD],
201 + V4L2_BUF_TYPE_META_CAPTURE, METADATA_PAD);
202 + if (ret) {
203 + unicam_err(unicam, "Unable to register metadata video device.\n");
204 + goto unregister;
205 + }
206 }
207
208 ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev);
209 @@ -2633,13 +2667,6 @@ unregister:
210 return ret;
211 }
212
213 -static int unicam_async_complete(struct v4l2_async_notifier *notifier)
214 -{
215 - struct unicam_device *unicam = to_unicam_device(notifier->v4l2_dev);
216 -
217 - return unicam_probe_complete(unicam);
218 -}
219 -
220 static const struct v4l2_async_notifier_operations unicam_async_ops = {
221 .bound = unicam_async_bound,
222 .complete = unicam_async_complete,
223 @@ -2748,7 +2775,7 @@ static int of_unicam_connect_subdevs(str
224 dev->notifier.ops = &unicam_async_ops;
225
226 dev->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
227 - dev->asd.match.fwnode = of_fwnode_handle(sensor_node);
228 + dev->asd.match.fwnode = fwnode_graph_get_remote_endpoint(of_fwnode_handle(ep_node));
229 ret = v4l2_async_notifier_add_subdev(&dev->notifier, &dev->asd);
230 if (ret) {
231 unicam_err(dev, "Error adding subdevice: %d\n", ret);