xref: /linux/drivers/media/platform/rockchip/rkcif/rkcif-interface.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip Camera Interface (CIF) Driver
4  *
5  * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
6  * Copyright (C) 2025 Collabora, Ltd.
7  */
8 
9 #include <media/v4l2-common.h>
10 #include <media/v4l2-fwnode.h>
11 #include <media/v4l2-mc.h>
12 #include <media/v4l2-subdev.h>
13 
14 #include "rkcif-common.h"
15 #include "rkcif-interface.h"
16 
17 static inline struct rkcif_interface *to_rkcif_interface(struct v4l2_subdev *sd)
18 {
19 	return container_of(sd, struct rkcif_interface, sd);
20 }
21 
22 static const struct media_entity_operations rkcif_interface_media_ops = {
23 	.link_validate = v4l2_subdev_link_validate,
24 	.has_pad_interdep = v4l2_subdev_has_pad_interdep,
25 };
26 
27 static int rkcif_interface_set_fmt(struct v4l2_subdev *sd,
28 				   struct v4l2_subdev_state *state,
29 				   struct v4l2_subdev_format *format)
30 {
31 	struct rkcif_interface *interface = to_rkcif_interface(sd);
32 	const struct rkcif_input_fmt *input;
33 	struct v4l2_mbus_framefmt *sink, *src;
34 	struct v4l2_rect *crop;
35 	u32 other_pad, other_stream;
36 	int ret;
37 
38 	/* the format on the source pad always matches the sink pad */
39 	if (format->pad == RKCIF_IF_PAD_SRC)
40 		return v4l2_subdev_get_fmt(sd, state, format);
41 
42 	input = rkcif_interface_find_input_fmt(interface, true,
43 					       format->format.code);
44 	format->format.code = input->mbus_code;
45 
46 	sink = v4l2_subdev_state_get_format(state, format->pad, format->stream);
47 	if (!sink)
48 		return -EINVAL;
49 
50 	*sink = format->format;
51 
52 	/* propagate the format to the source pad */
53 	src = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
54 							   format->stream);
55 	if (!src)
56 		return -EINVAL;
57 
58 	*src = *sink;
59 
60 	ret = v4l2_subdev_routing_find_opposite_end(&state->routing,
61 						    format->pad, format->stream,
62 						    &other_pad, &other_stream);
63 	if (ret)
64 		return -EINVAL;
65 
66 	crop = v4l2_subdev_state_get_crop(state, other_pad, other_stream);
67 	if (!crop)
68 		return -EINVAL;
69 
70 	/* reset crop */
71 	crop->left = 0;
72 	crop->top = 0;
73 	crop->width = sink->width;
74 	crop->height = sink->height;
75 
76 	return 0;
77 }
78 
79 static int rkcif_interface_get_sel(struct v4l2_subdev *sd,
80 				   struct v4l2_subdev_state *state,
81 				   struct v4l2_subdev_selection *sel)
82 {
83 	struct v4l2_mbus_framefmt *sink;
84 	struct v4l2_rect *crop;
85 	int ret = 0;
86 
87 	if (sel->pad != RKCIF_IF_PAD_SRC)
88 		return -EINVAL;
89 
90 	sink = v4l2_subdev_state_get_opposite_stream_format(state, sel->pad,
91 							    sel->stream);
92 	if (!sink)
93 		return -EINVAL;
94 
95 	crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream);
96 	if (!crop)
97 		return -EINVAL;
98 
99 	switch (sel->target) {
100 	case V4L2_SEL_TGT_CROP_DEFAULT:
101 	case V4L2_SEL_TGT_CROP_BOUNDS:
102 		sel->r.left = 0;
103 		sel->r.top = 0;
104 		sel->r.width = sink->width;
105 		sel->r.height = sink->height;
106 		break;
107 	case V4L2_SEL_TGT_CROP:
108 		sel->r = *crop;
109 		break;
110 	default:
111 		ret = -EINVAL;
112 	}
113 
114 	return ret;
115 }
116 
117 static int rkcif_interface_set_sel(struct v4l2_subdev *sd,
118 				   struct v4l2_subdev_state *state,
119 				   struct v4l2_subdev_selection *sel)
120 {
121 	struct v4l2_mbus_framefmt *sink, *src;
122 	struct v4l2_rect *crop;
123 
124 	if (sel->pad != RKCIF_IF_PAD_SRC || sel->target != V4L2_SEL_TGT_CROP)
125 		return -EINVAL;
126 
127 	sink = v4l2_subdev_state_get_opposite_stream_format(state, sel->pad,
128 							    sel->stream);
129 	if (!sink)
130 		return -EINVAL;
131 
132 	src = v4l2_subdev_state_get_format(state, sel->pad, sel->stream);
133 	if (!src)
134 		return -EINVAL;
135 
136 	crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream);
137 	if (!crop)
138 		return -EINVAL;
139 
140 	*crop = sel->r;
141 
142 	src->height = sel->r.height;
143 	src->width = sel->r.width;
144 
145 	return 0;
146 }
147 
148 static int rkcif_interface_set_routing(struct v4l2_subdev *sd,
149 				       struct v4l2_subdev_state *state,
150 				       enum v4l2_subdev_format_whence which,
151 				       struct v4l2_subdev_krouting *routing)
152 {
153 	int ret;
154 
155 	ret = v4l2_subdev_routing_validate(sd, routing,
156 					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
157 	if (ret)
158 		return ret;
159 
160 	for (unsigned int i = 0; i < routing->num_routes; i++) {
161 		const struct v4l2_subdev_route *route = &routing->routes[i];
162 
163 		if (route->source_stream >= RKCIF_ID_MAX)
164 			return -EINVAL;
165 	}
166 
167 	ret = v4l2_subdev_set_routing(sd, state, routing);
168 
169 	return ret;
170 }
171 
172 static int rkcif_interface_apply_crop(struct rkcif_stream *stream,
173 				      struct v4l2_subdev_state *state)
174 {
175 	struct rkcif_interface *interface = stream->interface;
176 	struct v4l2_rect *crop;
177 
178 	crop = v4l2_subdev_state_get_crop(state, RKCIF_IF_PAD_SRC, stream->id);
179 	if (!crop)
180 		return -EINVAL;
181 
182 	if (interface->set_crop)
183 		interface->set_crop(stream, crop->left, crop->top);
184 
185 	return 0;
186 }
187 
188 static int rkcif_interface_enable_streams(struct v4l2_subdev *sd,
189 					  struct v4l2_subdev_state *state,
190 					  u32 pad, u64 streams_mask)
191 {
192 	struct rkcif_interface *interface = to_rkcif_interface(sd);
193 	struct rkcif_stream *stream;
194 	struct v4l2_subdev_route *route;
195 	struct v4l2_subdev *remote_sd;
196 	struct media_pad *remote_pad;
197 	u64 mask;
198 
199 	remote_pad =
200 		media_pad_remote_pad_first(&sd->entity.pads[RKCIF_IF_PAD_SINK]);
201 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
202 
203 	/* DVP has one crop setting for all IDs */
204 	if (interface->type == RKCIF_IF_DVP) {
205 		stream = &interface->streams[RKCIF_ID0];
206 		rkcif_interface_apply_crop(stream, state);
207 	} else {
208 		for_each_active_route(&state->routing, route) {
209 			stream = &interface->streams[route->sink_stream];
210 			rkcif_interface_apply_crop(stream, state);
211 		}
212 	}
213 
214 	mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK,
215 					       RKCIF_IF_PAD_SRC, &streams_mask);
216 
217 	return v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask);
218 }
219 
220 static int rkcif_interface_disable_streams(struct v4l2_subdev *sd,
221 					   struct v4l2_subdev_state *state,
222 					   u32 pad, u64 streams_mask)
223 {
224 	struct v4l2_subdev *remote_sd;
225 	struct media_pad *remote_pad;
226 	u64 mask;
227 
228 	remote_pad =
229 		media_pad_remote_pad_first(&sd->entity.pads[RKCIF_IF_PAD_SINK]);
230 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
231 
232 	mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK,
233 					       RKCIF_IF_PAD_SRC, &streams_mask);
234 
235 	return v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
236 }
237 
238 static const struct v4l2_subdev_pad_ops rkcif_interface_pad_ops = {
239 	.get_fmt = v4l2_subdev_get_fmt,
240 	.set_fmt = rkcif_interface_set_fmt,
241 	.get_selection = rkcif_interface_get_sel,
242 	.set_selection = rkcif_interface_set_sel,
243 	.set_routing = rkcif_interface_set_routing,
244 	.enable_streams = rkcif_interface_enable_streams,
245 	.disable_streams = rkcif_interface_disable_streams,
246 };
247 
248 static const struct v4l2_subdev_ops rkcif_interface_ops = {
249 	.pad = &rkcif_interface_pad_ops,
250 };
251 
252 static int rkcif_interface_init_state(struct v4l2_subdev *sd,
253 				      struct v4l2_subdev_state *state)
254 {
255 	struct rkcif_interface *interface = to_rkcif_interface(sd);
256 	struct v4l2_subdev_route routes[] = {
257 		{
258 			.sink_pad = RKCIF_IF_PAD_SINK,
259 			.sink_stream = 0,
260 			.source_pad = RKCIF_IF_PAD_SRC,
261 			.source_stream = 0,
262 			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
263 		},
264 	};
265 	struct v4l2_subdev_krouting routing = {
266 		.len_routes = ARRAY_SIZE(routes),
267 		.num_routes = ARRAY_SIZE(routes),
268 		.routes = routes,
269 	};
270 	const struct v4l2_mbus_framefmt dvp_default_format = {
271 		.width = 3840,
272 		.height = 2160,
273 		.code = MEDIA_BUS_FMT_YUYV8_1X16,
274 		.field = V4L2_FIELD_NONE,
275 		.colorspace = V4L2_COLORSPACE_REC709,
276 		.ycbcr_enc = V4L2_YCBCR_ENC_709,
277 		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
278 		.xfer_func = V4L2_XFER_FUNC_NONE,
279 	};
280 	const struct v4l2_mbus_framefmt mipi_default_format = {
281 		.width = 3840,
282 		.height = 2160,
283 		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
284 		.field = V4L2_FIELD_NONE,
285 		.colorspace = V4L2_COLORSPACE_RAW,
286 		.ycbcr_enc = V4L2_YCBCR_ENC_601,
287 		.quantization = V4L2_QUANTIZATION_FULL_RANGE,
288 		.xfer_func = V4L2_XFER_FUNC_NONE,
289 	};
290 	const struct v4l2_mbus_framefmt *default_format;
291 	int ret;
292 
293 	default_format = (interface->type == RKCIF_IF_DVP) ?
294 				 &dvp_default_format :
295 				 &mipi_default_format;
296 
297 	ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
298 					       default_format);
299 
300 	return ret;
301 }
302 
303 static const struct v4l2_subdev_internal_ops rkcif_interface_internal_ops = {
304 	.init_state = rkcif_interface_init_state,
305 };
306 
307 static int rkcif_interface_add(struct rkcif_interface *interface)
308 {
309 	struct rkcif_device *rkcif = interface->rkcif;
310 	struct rkcif_remote *remote;
311 	struct v4l2_async_notifier *ntf = &rkcif->notifier;
312 	struct v4l2_fwnode_endpoint *vep = &interface->vep;
313 	struct device *dev = rkcif->dev;
314 	struct fwnode_handle *ep;
315 	u32 dvp_clk_delay = 0;
316 	int ret;
317 
318 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), interface->index,
319 					     0, 0);
320 	if (!ep)
321 		return -ENODEV;
322 
323 	vep->bus_type = V4L2_MBUS_UNKNOWN;
324 	ret = v4l2_fwnode_endpoint_parse(ep, vep);
325 	if (ret)
326 		goto complete;
327 
328 	if (interface->type == RKCIF_IF_DVP) {
329 		if (vep->bus_type != V4L2_MBUS_BT656 &&
330 		    vep->bus_type != V4L2_MBUS_PARALLEL) {
331 			ret = dev_err_probe(dev, -EINVAL,
332 					    "unsupported bus type\n");
333 			goto complete;
334 		}
335 
336 		fwnode_property_read_u32(ep, "rockchip,dvp-clk-delay",
337 					 &dvp_clk_delay);
338 		interface->dvp.dvp_clk_delay = dvp_clk_delay;
339 	}
340 
341 	remote = v4l2_async_nf_add_fwnode_remote(ntf, ep, struct rkcif_remote);
342 	if (IS_ERR(remote)) {
343 		ret = PTR_ERR(remote);
344 		goto complete;
345 	}
346 
347 	remote->interface = interface;
348 	interface->remote = remote;
349 	interface->status = RKCIF_IF_ACTIVE;
350 	ret = 0;
351 
352 complete:
353 	fwnode_handle_put(ep);
354 
355 	return ret;
356 }
357 
358 int rkcif_interface_register(struct rkcif_device *rkcif,
359 			     struct rkcif_interface *interface)
360 {
361 	struct media_pad *pads = interface->pads;
362 	struct v4l2_subdev *sd = &interface->sd;
363 	int ret;
364 
365 	interface->rkcif = rkcif;
366 
367 	v4l2_subdev_init(sd, &rkcif_interface_ops);
368 	sd->dev = rkcif->dev;
369 	sd->entity.ops = &rkcif_interface_media_ops;
370 	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
371 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
372 	sd->internal_ops = &rkcif_interface_internal_ops;
373 	sd->owner = THIS_MODULE;
374 
375 	if (interface->type == RKCIF_IF_DVP)
376 		snprintf(sd->name, sizeof(sd->name), "rkcif-dvp0");
377 	else if (interface->type == RKCIF_IF_MIPI)
378 		snprintf(sd->name, sizeof(sd->name), "rkcif-mipi%d",
379 			 interface->index - RKCIF_MIPI_BASE);
380 
381 	pads[RKCIF_IF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
382 	pads[RKCIF_IF_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
383 	ret = media_entity_pads_init(&sd->entity, RKCIF_IF_PAD_MAX, pads);
384 	if (ret)
385 		goto err;
386 
387 	ret = v4l2_subdev_init_finalize(sd);
388 	if (ret)
389 		goto err_entity_cleanup;
390 
391 	ret = v4l2_device_register_subdev(&rkcif->v4l2_dev, sd);
392 	if (ret) {
393 		dev_err(sd->dev, "failed to register subdev\n");
394 		goto err_subdev_cleanup;
395 	}
396 
397 	ret = rkcif_interface_add(interface);
398 	if (ret)
399 		goto err_subdev_unregister;
400 
401 	return 0;
402 
403 err_subdev_unregister:
404 	v4l2_device_unregister_subdev(sd);
405 err_subdev_cleanup:
406 	v4l2_subdev_cleanup(sd);
407 err_entity_cleanup:
408 	media_entity_cleanup(&sd->entity);
409 err:
410 	return ret;
411 }
412 
413 void rkcif_interface_unregister(struct rkcif_interface *interface)
414 {
415 	struct v4l2_subdev *sd = &interface->sd;
416 
417 	if (interface->status != RKCIF_IF_ACTIVE)
418 		return;
419 
420 	v4l2_device_unregister_subdev(sd);
421 	v4l2_subdev_cleanup(sd);
422 	media_entity_cleanup(&sd->entity);
423 }
424 
425 const struct rkcif_input_fmt *
426 rkcif_interface_find_input_fmt(struct rkcif_interface *interface, bool ret_def,
427 			       u32 mbus_code)
428 {
429 	const struct rkcif_input_fmt *fmt;
430 
431 	WARN_ON(interface->in_fmts_num == 0);
432 
433 	for (unsigned int i = 0; i < interface->in_fmts_num; i++) {
434 		fmt = &interface->in_fmts[i];
435 		if (fmt->mbus_code == mbus_code)
436 			return fmt;
437 	}
438 	if (ret_def)
439 		return &interface->in_fmts[0];
440 	else
441 		return NULL;
442 }
443