xref: /linux/drivers/media/platform/synopsys/dw-mipi-csi2rx.c (revision b7ef56a07672e0d7ebe71c9d9b45f959f0c2f8e8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Synopsys DesignWare MIPI CSI-2 Receiver Driver
4  *
5  * Copyright (C) 2019 Rockchip Electronics Co., Ltd.
6  * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
7  * Copyright (C) 2026 Collabora, Ltd.
8  */
9 
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/io.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/phy/phy.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/property.h>
19 #include <linux/reset.h>
20 
21 #include <media/mipi-csi2.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-fwnode.h>
24 #include <media/v4l2-mc.h>
25 #include <media/v4l2-subdev.h>
26 
27 #define DW_MIPI_CSI2RX_N_LANES		0x04
28 #define DW_MIPI_CSI2RX_RESETN		0x10
29 #define DW_MIPI_CSI2RX_PHY_STATE	0x14
30 #define DW_MIPI_CSI2RX_ERR1		0x20
31 #define DW_MIPI_CSI2RX_ERR2		0x24
32 #define DW_MIPI_CSI2RX_MSK1		0x28
33 #define DW_MIPI_CSI2RX_MSK2		0x2c
34 #define DW_MIPI_CSI2RX_CONTROL		0x40
35 
36 #define SW_CPHY_EN(x)		((x) << 0)
37 #define SW_DSI_EN(x)		((x) << 4)
38 #define SW_DATATYPE_FS(x)	((x) << 8)
39 #define SW_DATATYPE_FE(x)	((x) << 14)
40 #define SW_DATATYPE_LS(x)	((x) << 20)
41 #define SW_DATATYPE_LE(x)	((x) << 26)
42 
43 #define DW_MIPI_CSI2RX_CLKS_MAX	1
44 
45 enum {
46 	DW_MIPI_CSI2RX_PAD_SINK,
47 	DW_MIPI_CSI2RX_PAD_SRC,
48 	DW_MIPI_CSI2RX_PAD_MAX,
49 };
50 
51 struct dw_mipi_csi2rx_format {
52 	u32 code;
53 	u8 depth;
54 	u8 csi_dt;
55 };
56 
57 struct dw_mipi_csi2rx_device {
58 	struct device *dev;
59 
60 	void __iomem *base_addr;
61 	struct clk_bulk_data *clks;
62 	unsigned int clks_num;
63 	struct phy *phy;
64 	struct reset_control *reset;
65 
66 	const struct dw_mipi_csi2rx_format *formats;
67 	unsigned int formats_num;
68 
69 	struct media_pad pads[DW_MIPI_CSI2RX_PAD_MAX];
70 	struct v4l2_async_notifier notifier;
71 	struct v4l2_subdev sd;
72 
73 	enum v4l2_mbus_type bus_type;
74 	u32 lanes_num;
75 };
76 
77 static const struct v4l2_mbus_framefmt default_format = {
78 	.width = 3840,
79 	.height = 2160,
80 	.code = MEDIA_BUS_FMT_SRGGB10_1X10,
81 	.field = V4L2_FIELD_NONE,
82 	.colorspace = V4L2_COLORSPACE_RAW,
83 	.ycbcr_enc = V4L2_YCBCR_ENC_601,
84 	.quantization = V4L2_QUANTIZATION_FULL_RANGE,
85 	.xfer_func = V4L2_XFER_FUNC_NONE,
86 };
87 
88 static const struct dw_mipi_csi2rx_format formats[] = {
89 	/* YUV formats */
90 	{
91 		.code = MEDIA_BUS_FMT_YUYV8_1X16,
92 		.depth = 16,
93 		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
94 	},
95 	{
96 		.code = MEDIA_BUS_FMT_UYVY8_1X16,
97 		.depth = 16,
98 		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
99 	},
100 	{
101 		.code = MEDIA_BUS_FMT_YVYU8_1X16,
102 		.depth = 16,
103 		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
104 	},
105 	{
106 		.code = MEDIA_BUS_FMT_VYUY8_1X16,
107 		.depth = 16,
108 		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
109 	},
110 	/* RGB formats */
111 	{
112 		.code = MEDIA_BUS_FMT_RGB888_1X24,
113 		.depth = 24,
114 		.csi_dt = MIPI_CSI2_DT_RGB888,
115 	},
116 	{
117 		.code = MEDIA_BUS_FMT_BGR888_1X24,
118 		.depth = 24,
119 		.csi_dt = MIPI_CSI2_DT_RGB888,
120 	},
121 	/* Bayer formats */
122 	{
123 		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
124 		.depth = 8,
125 		.csi_dt = MIPI_CSI2_DT_RAW8,
126 	},
127 	{
128 		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
129 		.depth = 8,
130 		.csi_dt = MIPI_CSI2_DT_RAW8,
131 	},
132 	{
133 		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
134 		.depth = 8,
135 		.csi_dt = MIPI_CSI2_DT_RAW8,
136 	},
137 	{
138 		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
139 		.depth = 8,
140 		.csi_dt = MIPI_CSI2_DT_RAW8,
141 	},
142 	{
143 		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
144 		.depth = 10,
145 		.csi_dt = MIPI_CSI2_DT_RAW10,
146 	},
147 	{
148 		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
149 		.depth = 10,
150 		.csi_dt = MIPI_CSI2_DT_RAW10,
151 	},
152 	{
153 		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
154 		.depth = 10,
155 		.csi_dt = MIPI_CSI2_DT_RAW10,
156 	},
157 	{
158 		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
159 		.depth = 10,
160 		.csi_dt = MIPI_CSI2_DT_RAW10,
161 	},
162 	{
163 		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
164 		.depth = 12,
165 		.csi_dt = MIPI_CSI2_DT_RAW12,
166 	},
167 	{
168 		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
169 		.depth = 12,
170 		.csi_dt = MIPI_CSI2_DT_RAW12,
171 	},
172 	{
173 		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
174 		.depth = 12,
175 		.csi_dt = MIPI_CSI2_DT_RAW12,
176 	},
177 	{
178 		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
179 		.depth = 12,
180 		.csi_dt = MIPI_CSI2_DT_RAW12,
181 	},
182 };
183 
184 static inline struct dw_mipi_csi2rx_device *to_csi2(struct v4l2_subdev *sd)
185 {
186 	return container_of(sd, struct dw_mipi_csi2rx_device, sd);
187 }
188 
189 static inline void dw_mipi_csi2rx_write(struct dw_mipi_csi2rx_device *csi2,
190 					unsigned int addr, u32 val)
191 {
192 	writel(val, csi2->base_addr + addr);
193 }
194 
195 static inline u32 dw_mipi_csi2rx_read(struct dw_mipi_csi2rx_device *csi2,
196 				      unsigned int addr)
197 {
198 	return readl(csi2->base_addr + addr);
199 }
200 
201 static const struct dw_mipi_csi2rx_format *
202 dw_mipi_csi2rx_find_format(struct dw_mipi_csi2rx_device *csi2, u32 mbus_code)
203 {
204 	WARN_ON(csi2->formats_num == 0);
205 
206 	for (unsigned int i = 0; i < csi2->formats_num; i++) {
207 		const struct dw_mipi_csi2rx_format *format = &csi2->formats[i];
208 
209 		if (format->code == mbus_code)
210 			return format;
211 	}
212 
213 	return NULL;
214 }
215 
216 static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
217 {
218 	struct media_pad *source_pad;
219 	union phy_configure_opts opts;
220 	u32 lanes = csi2->lanes_num;
221 	u32 control = 0;
222 	s64 link_freq;
223 	int ret;
224 
225 	if (lanes < 1 || lanes > 4)
226 		return -EINVAL;
227 
228 	source_pad = media_pad_remote_pad_unique(
229 		&csi2->pads[DW_MIPI_CSI2RX_PAD_SINK]);
230 	if (IS_ERR(source_pad))
231 		return PTR_ERR(source_pad);
232 
233 	/* set mult and div to 0, thus completely rely on V4L2_CID_LINK_FREQ */
234 	link_freq = v4l2_get_link_freq(source_pad, 0, 0);
235 	if (link_freq < 0)
236 		return link_freq;
237 
238 	switch (csi2->bus_type) {
239 	case V4L2_MBUS_CSI2_DPHY:
240 		ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq * 2,
241 								 lanes, &opts.mipi_dphy);
242 		if (ret)
243 			return ret;
244 
245 		ret = phy_set_mode(csi2->phy, PHY_MODE_MIPI_DPHY);
246 		if (ret)
247 			return ret;
248 
249 		ret = phy_configure(csi2->phy, &opts);
250 		if (ret)
251 			return ret;
252 
253 		control |= SW_CPHY_EN(0);
254 		break;
255 
256 	case V4L2_MBUS_CSI2_CPHY:
257 		/* TODO: implement CPHY configuration */
258 		return -EOPNOTSUPP;
259 	default:
260 		return -EINVAL;
261 	}
262 
263 	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
264 		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
265 
266 	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_N_LANES, lanes - 1);
267 	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_CONTROL, control);
268 	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 1);
269 
270 	return phy_power_on(csi2->phy);
271 }
272 
273 static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
274 {
275 	phy_power_off(csi2->phy);
276 
277 	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 0);
278 	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
279 	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK2, ~0);
280 }
281 
282 static const struct media_entity_operations dw_mipi_csi2rx_media_ops = {
283 	.link_validate = v4l2_subdev_link_validate,
284 };
285 
286 static int
287 dw_mipi_csi2rx_enum_mbus_code(struct v4l2_subdev *sd,
288 			      struct v4l2_subdev_state *sd_state,
289 			      struct v4l2_subdev_mbus_code_enum *code)
290 {
291 	struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
292 
293 	switch (code->pad) {
294 	case DW_MIPI_CSI2RX_PAD_SRC:
295 		if (code->index)
296 			return -EINVAL;
297 
298 		code->code =
299 			v4l2_subdev_state_get_format(sd_state,
300 						     DW_MIPI_CSI2RX_PAD_SINK)->code;
301 
302 		return 0;
303 	case DW_MIPI_CSI2RX_PAD_SINK:
304 		if (code->index > csi2->formats_num)
305 			return -EINVAL;
306 
307 		code->code = csi2->formats[code->index].code;
308 		return 0;
309 	default:
310 		return -EINVAL;
311 	}
312 }
313 
314 static int dw_mipi_csi2rx_set_fmt(struct v4l2_subdev *sd,
315 				  struct v4l2_subdev_state *state,
316 				  struct v4l2_subdev_format *format)
317 {
318 	struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
319 	const struct dw_mipi_csi2rx_format *fmt;
320 	struct v4l2_mbus_framefmt *sink, *src;
321 
322 	/* the format on the source pad always matches the sink pad */
323 	if (format->pad == DW_MIPI_CSI2RX_PAD_SRC)
324 		return v4l2_subdev_get_fmt(sd, state, format);
325 
326 	sink = v4l2_subdev_state_get_format(state, format->pad, format->stream);
327 	if (!sink)
328 		return -EINVAL;
329 
330 	fmt = dw_mipi_csi2rx_find_format(csi2, format->format.code);
331 	if (!fmt)
332 		format->format = default_format;
333 
334 	*sink = format->format;
335 
336 	/* propagate the format to the source pad */
337 	src = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
338 							   format->stream);
339 	if (!src)
340 		return -EINVAL;
341 
342 	*src = *sink;
343 
344 	return 0;
345 }
346 
347 static int dw_mipi_csi2rx_set_routing(struct v4l2_subdev *sd,
348 				      struct v4l2_subdev_state *state,
349 				      enum v4l2_subdev_format_whence which,
350 				      struct v4l2_subdev_krouting *routing)
351 {
352 	int ret;
353 
354 	ret = v4l2_subdev_routing_validate(sd, routing,
355 					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
356 	if (ret)
357 		return ret;
358 
359 	return v4l2_subdev_set_routing_with_fmt(sd, state, routing,
360 						&default_format);
361 }
362 
363 static int dw_mipi_csi2rx_enable_streams(struct v4l2_subdev *sd,
364 					 struct v4l2_subdev_state *state,
365 					 u32 pad, u64 streams_mask)
366 {
367 	struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
368 	struct v4l2_subdev *remote_sd;
369 	struct media_pad *sink_pad, *remote_pad;
370 	struct device *dev = csi2->dev;
371 	u64 mask;
372 	int ret;
373 
374 	sink_pad = &sd->entity.pads[DW_MIPI_CSI2RX_PAD_SINK];
375 	remote_pad = media_pad_remote_pad_first(sink_pad);
376 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
377 
378 	mask = v4l2_subdev_state_xlate_streams(state, DW_MIPI_CSI2RX_PAD_SINK,
379 					       DW_MIPI_CSI2RX_PAD_SRC,
380 					       &streams_mask);
381 
382 	ret = pm_runtime_resume_and_get(dev);
383 	if (ret)
384 		goto err;
385 
386 	ret = dw_mipi_csi2rx_start(csi2);
387 	if (ret) {
388 		dev_err(dev, "failed to enable CSI hardware\n");
389 		goto err_pm_runtime_put;
390 	}
391 
392 	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask);
393 	if (ret)
394 		goto err_csi_stop;
395 
396 	return 0;
397 
398 err_csi_stop:
399 	dw_mipi_csi2rx_stop(csi2);
400 err_pm_runtime_put:
401 	pm_runtime_put(dev);
402 err:
403 	return ret;
404 }
405 
406 static int dw_mipi_csi2rx_disable_streams(struct v4l2_subdev *sd,
407 					  struct v4l2_subdev_state *state,
408 					  u32 pad, u64 streams_mask)
409 {
410 	struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
411 	struct v4l2_subdev *remote_sd;
412 	struct media_pad *sink_pad, *remote_pad;
413 	struct device *dev = csi2->dev;
414 	u64 mask;
415 	int ret;
416 
417 	sink_pad = &sd->entity.pads[DW_MIPI_CSI2RX_PAD_SINK];
418 	remote_pad = media_pad_remote_pad_first(sink_pad);
419 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
420 
421 	mask = v4l2_subdev_state_xlate_streams(state, DW_MIPI_CSI2RX_PAD_SINK,
422 					       DW_MIPI_CSI2RX_PAD_SRC,
423 					       &streams_mask);
424 
425 	ret = v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
426 
427 	dw_mipi_csi2rx_stop(csi2);
428 
429 	pm_runtime_put(dev);
430 
431 	return ret;
432 }
433 
434 static const struct v4l2_subdev_pad_ops dw_mipi_csi2rx_pad_ops = {
435 	.enum_mbus_code = dw_mipi_csi2rx_enum_mbus_code,
436 	.get_fmt = v4l2_subdev_get_fmt,
437 	.set_fmt = dw_mipi_csi2rx_set_fmt,
438 	.set_routing = dw_mipi_csi2rx_set_routing,
439 	.enable_streams = dw_mipi_csi2rx_enable_streams,
440 	.disable_streams = dw_mipi_csi2rx_disable_streams,
441 };
442 
443 static const struct v4l2_subdev_ops dw_mipi_csi2rx_ops = {
444 	.pad = &dw_mipi_csi2rx_pad_ops,
445 };
446 
447 static int dw_mipi_csi2rx_init_state(struct v4l2_subdev *sd,
448 				     struct v4l2_subdev_state *state)
449 {
450 	struct v4l2_subdev_route routes[] = {
451 		{
452 			.sink_pad = DW_MIPI_CSI2RX_PAD_SINK,
453 			.sink_stream = 0,
454 			.source_pad = DW_MIPI_CSI2RX_PAD_SRC,
455 			.source_stream = 0,
456 			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
457 		},
458 	};
459 	struct v4l2_subdev_krouting routing = {
460 		.len_routes = ARRAY_SIZE(routes),
461 		.num_routes = ARRAY_SIZE(routes),
462 		.routes = routes,
463 	};
464 
465 	return v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
466 						&default_format);
467 }
468 
469 static const struct v4l2_subdev_internal_ops dw_mipi_csi2rx_internal_ops = {
470 	.init_state = dw_mipi_csi2rx_init_state,
471 };
472 
473 static int dw_mipi_csi2rx_notifier_bound(struct v4l2_async_notifier *notifier,
474 					 struct v4l2_subdev *sd,
475 					 struct v4l2_async_connection *asd)
476 {
477 	struct dw_mipi_csi2rx_device *csi2 =
478 		container_of(notifier, struct dw_mipi_csi2rx_device, notifier);
479 	struct media_pad *sink_pad = &csi2->pads[DW_MIPI_CSI2RX_PAD_SINK];
480 	int ret;
481 
482 	ret = v4l2_create_fwnode_links_to_pad(sd, sink_pad,
483 					      MEDIA_LNK_FL_ENABLED);
484 	if (ret) {
485 		dev_err(csi2->dev, "failed to link source pad of %s\n",
486 			sd->name);
487 		return ret;
488 	}
489 
490 	return 0;
491 }
492 
493 static const struct v4l2_async_notifier_operations dw_mipi_csi2rx_notifier_ops = {
494 	.bound = dw_mipi_csi2rx_notifier_bound,
495 };
496 
497 static int dw_mipi_csi2rx_register_notifier(struct dw_mipi_csi2rx_device *csi2)
498 {
499 	struct v4l2_async_connection *asd;
500 	struct v4l2_async_notifier *ntf = &csi2->notifier;
501 	struct v4l2_fwnode_endpoint vep;
502 	struct v4l2_subdev *sd = &csi2->sd;
503 	struct device *dev = csi2->dev;
504 	int ret;
505 
506 	struct fwnode_handle *ep __free(fwnode_handle) =
507 		fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
508 	if (!ep)
509 		return dev_err_probe(dev, -ENODEV, "failed to get endpoint\n");
510 
511 	vep.bus_type = V4L2_MBUS_UNKNOWN;
512 	ret = v4l2_fwnode_endpoint_parse(ep, &vep);
513 	if (ret)
514 		return dev_err_probe(dev, ret, "failed to parse endpoint\n");
515 
516 	if (vep.bus_type != V4L2_MBUS_CSI2_DPHY &&
517 	    vep.bus_type != V4L2_MBUS_CSI2_CPHY)
518 		return dev_err_probe(dev, -EINVAL,
519 				     "invalid bus type of endpoint\n");
520 
521 	csi2->bus_type = vep.bus_type;
522 	csi2->lanes_num = vep.bus.mipi_csi2.num_data_lanes;
523 
524 	v4l2_async_subdev_nf_init(ntf, sd);
525 	ntf->ops = &dw_mipi_csi2rx_notifier_ops;
526 
527 	asd = v4l2_async_nf_add_fwnode_remote(ntf, ep,
528 					      struct v4l2_async_connection);
529 	if (IS_ERR(asd)) {
530 		ret = PTR_ERR(asd);
531 		goto err_nf_cleanup;
532 	}
533 
534 	ret = v4l2_async_nf_register(ntf);
535 	if (ret) {
536 		ret = dev_err_probe(dev, ret, "failed to register notifier\n");
537 		goto err_nf_cleanup;
538 	}
539 
540 	return 0;
541 
542 err_nf_cleanup:
543 	v4l2_async_nf_cleanup(ntf);
544 
545 	return ret;
546 }
547 
548 static int dw_mipi_csi2rx_register(struct dw_mipi_csi2rx_device *csi2)
549 {
550 	struct media_pad *pads = csi2->pads;
551 	struct v4l2_subdev *sd = &csi2->sd;
552 	int ret;
553 
554 	ret = dw_mipi_csi2rx_register_notifier(csi2);
555 	if (ret)
556 		goto err;
557 
558 	v4l2_subdev_init(sd, &dw_mipi_csi2rx_ops);
559 	sd->dev = csi2->dev;
560 	sd->entity.ops = &dw_mipi_csi2rx_media_ops;
561 	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
562 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
563 	sd->internal_ops = &dw_mipi_csi2rx_internal_ops;
564 	snprintf(sd->name, sizeof(sd->name), "dw-mipi-csi2rx %s",
565 		 dev_name(csi2->dev));
566 
567 	pads[DW_MIPI_CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
568 					      MEDIA_PAD_FL_MUST_CONNECT;
569 	pads[DW_MIPI_CSI2RX_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
570 	ret = media_entity_pads_init(&sd->entity, DW_MIPI_CSI2RX_PAD_MAX, pads);
571 	if (ret)
572 		goto err_notifier_unregister;
573 
574 	ret = v4l2_subdev_init_finalize(sd);
575 	if (ret)
576 		goto err_entity_cleanup;
577 
578 	ret = v4l2_async_register_subdev(sd);
579 	if (ret) {
580 		dev_err(sd->dev, "failed to register CSI-2 subdev\n");
581 		goto err_subdev_cleanup;
582 	}
583 
584 	return 0;
585 
586 err_subdev_cleanup:
587 	v4l2_subdev_cleanup(sd);
588 err_entity_cleanup:
589 	media_entity_cleanup(&sd->entity);
590 err_notifier_unregister:
591 	v4l2_async_nf_unregister(&csi2->notifier);
592 	v4l2_async_nf_cleanup(&csi2->notifier);
593 err:
594 	return ret;
595 }
596 
597 static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
598 {
599 	struct v4l2_subdev *sd = &csi2->sd;
600 
601 	v4l2_async_unregister_subdev(sd);
602 	v4l2_subdev_cleanup(sd);
603 	media_entity_cleanup(&sd->entity);
604 	v4l2_async_nf_unregister(&csi2->notifier);
605 	v4l2_async_nf_cleanup(&csi2->notifier);
606 }
607 
608 static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
609 	{
610 		.compatible = "rockchip,rk3568-mipi-csi2",
611 	},
612 	{}
613 };
614 MODULE_DEVICE_TABLE(of, dw_mipi_csi2rx_of_match);
615 
616 static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
617 {
618 	struct device *dev = &pdev->dev;
619 	struct dw_mipi_csi2rx_device *csi2;
620 	int ret;
621 
622 	csi2 = devm_kzalloc(dev, sizeof(*csi2), GFP_KERNEL);
623 	if (!csi2)
624 		return -ENOMEM;
625 	csi2->dev = dev;
626 	dev_set_drvdata(dev, csi2);
627 
628 	csi2->base_addr = devm_platform_ioremap_resource(pdev, 0);
629 	if (IS_ERR(csi2->base_addr))
630 		return PTR_ERR(csi2->base_addr);
631 
632 	ret = devm_clk_bulk_get_all(dev, &csi2->clks);
633 	if (ret != DW_MIPI_CSI2RX_CLKS_MAX)
634 		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
635 	csi2->clks_num = ret;
636 
637 	csi2->phy = devm_phy_get(dev, NULL);
638 	if (IS_ERR(csi2->phy))
639 		return dev_err_probe(dev, PTR_ERR(csi2->phy),
640 				     "failed to get MIPI CSI-2 PHY\n");
641 
642 	csi2->reset = devm_reset_control_get_exclusive(dev, NULL);
643 	if (IS_ERR(csi2->reset))
644 		return dev_err_probe(dev, PTR_ERR(csi2->reset),
645 				     "failed to get reset\n");
646 
647 	csi2->formats = formats;
648 	csi2->formats_num = ARRAY_SIZE(formats);
649 
650 	ret = devm_pm_runtime_enable(dev);
651 	if (ret)
652 		return dev_err_probe(dev, ret, "failed to enable pm runtime\n");
653 
654 	ret = phy_init(csi2->phy);
655 	if (ret)
656 		return dev_err_probe(dev, ret,
657 				     "failed to initialize MIPI CSI-2 PHY\n");
658 
659 	ret = dw_mipi_csi2rx_register(csi2);
660 	if (ret)
661 		goto err_phy_exit;
662 
663 	return 0;
664 
665 err_phy_exit:
666 	phy_exit(csi2->phy);
667 
668 	return ret;
669 }
670 
671 static void dw_mipi_csi2rx_remove(struct platform_device *pdev)
672 {
673 	struct dw_mipi_csi2rx_device *csi2 = platform_get_drvdata(pdev);
674 
675 	dw_mipi_csi2rx_unregister(csi2);
676 	phy_exit(csi2->phy);
677 }
678 
679 static int dw_mipi_csi2rx_runtime_suspend(struct device *dev)
680 {
681 	struct dw_mipi_csi2rx_device *csi2 = dev_get_drvdata(dev);
682 
683 	clk_bulk_disable_unprepare(csi2->clks_num, csi2->clks);
684 
685 	return 0;
686 }
687 
688 static int dw_mipi_csi2rx_runtime_resume(struct device *dev)
689 {
690 	struct dw_mipi_csi2rx_device *csi2 = dev_get_drvdata(dev);
691 	int ret;
692 
693 	reset_control_assert(csi2->reset);
694 	udelay(5);
695 	reset_control_deassert(csi2->reset);
696 
697 	ret = clk_bulk_prepare_enable(csi2->clks_num, csi2->clks);
698 	if (ret) {
699 		dev_err(dev, "failed to enable clocks\n");
700 		return ret;
701 	}
702 
703 	return 0;
704 }
705 
706 static DEFINE_RUNTIME_DEV_PM_OPS(dw_mipi_csi2rx_pm_ops,
707 				 dw_mipi_csi2rx_runtime_suspend,
708 				 dw_mipi_csi2rx_runtime_resume, NULL);
709 
710 static struct platform_driver dw_mipi_csi2rx_drv = {
711 	.driver = {
712 		.name = "dw-mipi-csi2rx",
713 		.of_match_table = dw_mipi_csi2rx_of_match,
714 		.pm = pm_ptr(&dw_mipi_csi2rx_pm_ops),
715 	},
716 	.probe = dw_mipi_csi2rx_probe,
717 	.remove = dw_mipi_csi2rx_remove,
718 };
719 module_platform_driver(dw_mipi_csi2rx_drv);
720 
721 MODULE_DESCRIPTION("Synopsys DesignWare MIPI CSI-2 Receiver platform driver");
722 MODULE_LICENSE("GPL");
723