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
to_csi2(struct v4l2_subdev * sd)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
dw_mipi_csi2rx_write(struct dw_mipi_csi2rx_device * csi2,unsigned int addr,u32 val)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
dw_mipi_csi2rx_read(struct dw_mipi_csi2rx_device * csi2,unsigned int addr)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 *
dw_mipi_csi2rx_find_format(struct dw_mipi_csi2rx_device * csi2,u32 mbus_code)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
dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device * csi2)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
dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device * csi2)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
dw_mipi_csi2rx_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)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
dw_mipi_csi2rx_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_format * format)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
dw_mipi_csi2rx_set_routing(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,enum v4l2_subdev_format_whence which,struct v4l2_subdev_krouting * routing)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
dw_mipi_csi2rx_enable_streams(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,u32 pad,u64 streams_mask)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
dw_mipi_csi2rx_disable_streams(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,u32 pad,u64 streams_mask)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
dw_mipi_csi2rx_init_state(struct v4l2_subdev * sd,struct v4l2_subdev_state * state)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
dw_mipi_csi2rx_notifier_bound(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_connection * asd)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
dw_mipi_csi2rx_register_notifier(struct dw_mipi_csi2rx_device * csi2)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
dw_mipi_csi2rx_register(struct dw_mipi_csi2rx_device * csi2)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
dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device * csi2)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
dw_mipi_csi2rx_probe(struct platform_device * pdev)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
dw_mipi_csi2rx_remove(struct platform_device * pdev)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
dw_mipi_csi2rx_runtime_suspend(struct device * dev)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
dw_mipi_csi2rx_runtime_resume(struct device * dev)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