bcm27xx: 6.1: add kernel patches
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-6.1 / 950-0344-media-bcm2835-unicam-Parse-pad-numbers-correctly.patch
1 From a335da8b55f0ade5c4488d5dddda9681f885fb45 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 @@ -382,6 +382,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 @@ -590,7 +592,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 @@ -612,7 +614,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 @@ -1980,7 +1982,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 @@ -2005,6 +2007,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 @@ -2096,8 +2099,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 @@ -2105,8 +2113,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 @@ -2377,14 +2390,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 @@ -2394,7 +2405,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 @@ -2407,7 +2419,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 @@ -2496,6 +2509,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 @@ -2554,7 +2568,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 @@ -2586,9 +2601,11 @@ 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 static struct lock_class_key key;
162 + struct unicam_device *unicam = to_unicam_device(notifier->v4l2_dev);
163 + unsigned int i, source_pads = 0;
164 int ret;
165
166 unicam->v4l2_dev.notify = unicam_notify;
167 @@ -2598,7 +2615,20 @@ static int unicam_probe_complete(struct
168 if (!unicam->sensor_state)
169 return -ENOMEM;
170
171 - unicam->sensor_embedded_data = (unicam->sensor->entity.num_pads >= 2);
172 + for (i = 0; i < unicam->sensor->entity.num_pads; i++) {
173 + if (unicam->sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) {
174 + if (source_pads < MAX_NODES) {
175 + unicam->node[source_pads].src_pad_id = i;
176 + unicam_err(unicam, "source pad %u is index %u\n",
177 + source_pads, i);
178 + }
179 + source_pads++;
180 + }
181 + }
182 + if (!source_pads) {
183 + unicam_err(unicam, "No source pads on sensor.\n");
184 + goto unregister;
185 + }
186
187 ret = register_node(unicam, &unicam->node[IMAGE_PAD],
188 V4L2_BUF_TYPE_VIDEO_CAPTURE, IMAGE_PAD);
189 @@ -2607,11 +2637,15 @@ static int unicam_probe_complete(struct
190 goto unregister;
191 }
192
193 - ret = register_node(unicam, &unicam->node[METADATA_PAD],
194 - V4L2_BUF_TYPE_META_CAPTURE, METADATA_PAD);
195 - if (ret) {
196 - unicam_err(unicam, "Unable to register metadata video device.\n");
197 - goto unregister;
198 + if (source_pads >= 2) {
199 + unicam->sensor_embedded_data = true;
200 +
201 + ret = register_node(unicam, &unicam->node[METADATA_PAD],
202 + V4L2_BUF_TYPE_META_CAPTURE, METADATA_PAD);
203 + if (ret) {
204 + unicam_err(unicam, "Unable to register metadata video device.\n");
205 + goto unregister;
206 + }
207 }
208
209 ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev);
210 @@ -2634,13 +2668,6 @@ unregister:
211 return ret;
212 }
213
214 -static int unicam_async_complete(struct v4l2_async_notifier *notifier)
215 -{
216 - struct unicam_device *unicam = to_unicam_device(notifier->v4l2_dev);
217 -
218 - return unicam_probe_complete(unicam);
219 -}
220 -
221 static const struct v4l2_async_notifier_operations unicam_async_ops = {
222 .bound = unicam_async_bound,
223 .complete = unicam_async_complete,
224 @@ -2749,7 +2776,7 @@ static int of_unicam_connect_subdevs(str
225 dev->notifier.ops = &unicam_async_ops;
226
227 dev->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
228 - dev->asd.match.fwnode = of_fwnode_handle(sensor_node);
229 + dev->asd.match.fwnode = fwnode_graph_get_remote_endpoint(of_fwnode_handle(ep_node));
230 ret = __v4l2_async_nf_add_subdev(&dev->notifier, &dev->asd);
231 if (ret) {
232 unicam_err(dev, "Error adding subdevice: %d\n", ret);