Merge tag 'block-6.1-2022-11-11' of git://git.kernel.dk/linux
[linux-block.git] / drivers / media / platform / sunxi / sun6i-mipi-csi2 / sun6i_mipi_csi2.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2020-2022 Bootlin
4  * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
5  */
6
7 #include <linux/clk.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/of_device.h>
11 #include <linux/phy/phy.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/regmap.h>
15 #include <linux/reset.h>
16 #include <media/mipi-csi2.h>
17 #include <media/v4l2-ctrls.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-fwnode.h>
20
21 #include "sun6i_mipi_csi2.h"
22 #include "sun6i_mipi_csi2_reg.h"
23
24 /* Format */
25
26 static const struct sun6i_mipi_csi2_format sun6i_mipi_csi2_formats[] = {
27         {
28                 .mbus_code      = MEDIA_BUS_FMT_SBGGR8_1X8,
29                 .data_type      = MIPI_CSI2_DT_RAW8,
30                 .bpp            = 8,
31         },
32         {
33                 .mbus_code      = MEDIA_BUS_FMT_SGBRG8_1X8,
34                 .data_type      = MIPI_CSI2_DT_RAW8,
35                 .bpp            = 8,
36         },
37         {
38                 .mbus_code      = MEDIA_BUS_FMT_SGRBG8_1X8,
39                 .data_type      = MIPI_CSI2_DT_RAW8,
40                 .bpp            = 8,
41         },
42         {
43                 .mbus_code      = MEDIA_BUS_FMT_SRGGB8_1X8,
44                 .data_type      = MIPI_CSI2_DT_RAW8,
45                 .bpp            = 8,
46         },
47         {
48                 .mbus_code      = MEDIA_BUS_FMT_SBGGR10_1X10,
49                 .data_type      = MIPI_CSI2_DT_RAW10,
50                 .bpp            = 10,
51         },
52         {
53                 .mbus_code      = MEDIA_BUS_FMT_SGBRG10_1X10,
54                 .data_type      = MIPI_CSI2_DT_RAW10,
55                 .bpp            = 10,
56         },
57         {
58                 .mbus_code      = MEDIA_BUS_FMT_SGRBG10_1X10,
59                 .data_type      = MIPI_CSI2_DT_RAW10,
60                 .bpp            = 10,
61         },
62         {
63                 .mbus_code      = MEDIA_BUS_FMT_SRGGB10_1X10,
64                 .data_type      = MIPI_CSI2_DT_RAW10,
65                 .bpp            = 10,
66         },
67 };
68
69 static const struct sun6i_mipi_csi2_format *
70 sun6i_mipi_csi2_format_find(u32 mbus_code)
71 {
72         unsigned int i;
73
74         for (i = 0; i < ARRAY_SIZE(sun6i_mipi_csi2_formats); i++)
75                 if (sun6i_mipi_csi2_formats[i].mbus_code == mbus_code)
76                         return &sun6i_mipi_csi2_formats[i];
77
78         return NULL;
79 }
80
81 /* Controller */
82
83 static void sun6i_mipi_csi2_enable(struct sun6i_mipi_csi2_device *csi2_dev)
84 {
85         struct regmap *regmap = csi2_dev->regmap;
86
87         regmap_update_bits(regmap, SUN6I_MIPI_CSI2_CTL_REG,
88                            SUN6I_MIPI_CSI2_CTL_EN, SUN6I_MIPI_CSI2_CTL_EN);
89 }
90
91 static void sun6i_mipi_csi2_disable(struct sun6i_mipi_csi2_device *csi2_dev)
92 {
93         struct regmap *regmap = csi2_dev->regmap;
94
95         regmap_update_bits(regmap, SUN6I_MIPI_CSI2_CTL_REG,
96                            SUN6I_MIPI_CSI2_CTL_EN, 0);
97 }
98
99 static void sun6i_mipi_csi2_configure(struct sun6i_mipi_csi2_device *csi2_dev)
100 {
101         struct regmap *regmap = csi2_dev->regmap;
102         unsigned int lanes_count =
103                 csi2_dev->bridge.endpoint.bus.mipi_csi2.num_data_lanes;
104         struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
105         const struct sun6i_mipi_csi2_format *format;
106         struct device *dev = csi2_dev->dev;
107         u32 version = 0;
108
109         format = sun6i_mipi_csi2_format_find(mbus_format->code);
110         if (WARN_ON(!format))
111                 return;
112
113         /*
114          * The enable flow in the Allwinner BSP is a bit different: the enable
115          * and reset bits are set together before starting the CSI controller.
116          *
117          * In mainline we enable the CSI controller first (due to subdev logic).
118          * One reliable way to make this work is to deassert reset, configure
119          * registers and enable the controller when everything's ready.
120          *
121          * However, setting the version enable bit and removing it afterwards
122          * appears necessary for capture to work reliably, while replacing it
123          * with a delay doesn't do the trick.
124          */
125         regmap_write(regmap, SUN6I_MIPI_CSI2_CTL_REG,
126                      SUN6I_MIPI_CSI2_CTL_RESET_N |
127                      SUN6I_MIPI_CSI2_CTL_VERSION_EN |
128                      SUN6I_MIPI_CSI2_CTL_UNPK_EN);
129
130         regmap_read(regmap, SUN6I_MIPI_CSI2_VERSION_REG, &version);
131
132         regmap_update_bits(regmap, SUN6I_MIPI_CSI2_CTL_REG,
133                            SUN6I_MIPI_CSI2_CTL_VERSION_EN, 0);
134
135         dev_dbg(dev, "A31 MIPI CSI-2 version: %04x\n", version);
136
137         regmap_write(regmap, SUN6I_MIPI_CSI2_CFG_REG,
138                      SUN6I_MIPI_CSI2_CFG_CHANNEL_MODE(1) |
139                      SUN6I_MIPI_CSI2_CFG_LANE_COUNT(lanes_count));
140
141         /*
142          * Only a single virtual channel (index 0) is currently supported.
143          * While the registers do mention multiple physical channels being
144          * available (which can be configured to match a specific virtual
145          * channel or data type), it's unclear whether channels > 0 are actually
146          * connected and available and the reference source code only makes use
147          * of channel 0.
148          *
149          * Using extra channels would also require matching channels to be
150          * available on the CSI (and ISP) side, which is also unsure although
151          * some CSI implementations are said to support multiple channels for
152          * BT656 time-sharing.
153          *
154          * We still configure virtual channel numbers to ensure that virtual
155          * channel 0 only goes to channel 0.
156          */
157
158         regmap_write(regmap, SUN6I_MIPI_CSI2_VCDT_RX_REG,
159                      SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(3, 3) |
160                      SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(2, 2) |
161                      SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(1, 1) |
162                      SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(0, 0) |
163                      SUN6I_MIPI_CSI2_VCDT_RX_CH_DT(0, format->data_type));
164
165         regmap_write(regmap, SUN6I_MIPI_CSI2_CH_INT_PD_REG,
166                      SUN6I_MIPI_CSI2_CH_INT_PD_CLEAR);
167 }
168
169 /* V4L2 Subdev */
170
171 static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
172 {
173         struct sun6i_mipi_csi2_device *csi2_dev = v4l2_get_subdevdata(subdev);
174         struct v4l2_subdev *source_subdev = csi2_dev->bridge.source_subdev;
175         union phy_configure_opts dphy_opts = { 0 };
176         struct phy_configure_opts_mipi_dphy *dphy_cfg = &dphy_opts.mipi_dphy;
177         struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
178         const struct sun6i_mipi_csi2_format *format;
179         struct phy *dphy = csi2_dev->dphy;
180         struct device *dev = csi2_dev->dev;
181         struct v4l2_ctrl *ctrl;
182         unsigned int lanes_count =
183                 csi2_dev->bridge.endpoint.bus.mipi_csi2.num_data_lanes;
184         unsigned long pixel_rate;
185         int ret;
186
187         if (!source_subdev)
188                 return -ENODEV;
189
190         if (!on) {
191                 ret = v4l2_subdev_call(source_subdev, video, s_stream, 0);
192                 goto disable;
193         }
194
195         /* Runtime PM */
196
197         ret = pm_runtime_resume_and_get(dev);
198         if (ret < 0)
199                 return ret;
200
201         /* Sensor Pixel Rate */
202
203         ctrl = v4l2_ctrl_find(source_subdev->ctrl_handler, V4L2_CID_PIXEL_RATE);
204         if (!ctrl) {
205                 dev_err(dev, "missing sensor pixel rate\n");
206                 ret = -ENODEV;
207                 goto error_pm;
208         }
209
210         pixel_rate = (unsigned long)v4l2_ctrl_g_ctrl_int64(ctrl);
211         if (!pixel_rate) {
212                 dev_err(dev, "missing (zero) sensor pixel rate\n");
213                 ret = -ENODEV;
214                 goto error_pm;
215         }
216
217         /* D-PHY */
218
219         if (!lanes_count) {
220                 dev_err(dev, "missing (zero) MIPI CSI-2 lanes count\n");
221                 ret = -ENODEV;
222                 goto error_pm;
223         }
224
225         format = sun6i_mipi_csi2_format_find(mbus_format->code);
226         if (WARN_ON(!format)) {
227                 ret = -ENODEV;
228                 goto error_pm;
229         }
230
231         phy_mipi_dphy_get_default_config(pixel_rate, format->bpp, lanes_count,
232                                          dphy_cfg);
233
234         /*
235          * Note that our hardware is using DDR, which is not taken in account by
236          * phy_mipi_dphy_get_default_config when calculating hs_clk_rate from
237          * the pixel rate, lanes count and bpp.
238          *
239          * The resulting clock rate is basically the symbol rate over the whole
240          * link. The actual clock rate is calculated with division by two since
241          * DDR samples both on rising and falling edges.
242          */
243
244         dev_dbg(dev, "A31 MIPI CSI-2 config:\n");
245         dev_dbg(dev, "%ld pixels/s, %u bits/pixel, %u lanes, %lu Hz clock\n",
246                 pixel_rate, format->bpp, lanes_count,
247                 dphy_cfg->hs_clk_rate / 2);
248
249         ret = phy_reset(dphy);
250         if (ret) {
251                 dev_err(dev, "failed to reset MIPI D-PHY\n");
252                 goto error_pm;
253         }
254
255         ret = phy_configure(dphy, &dphy_opts);
256         if (ret) {
257                 dev_err(dev, "failed to configure MIPI D-PHY\n");
258                 goto error_pm;
259         }
260
261         /* Controller */
262
263         sun6i_mipi_csi2_configure(csi2_dev);
264         sun6i_mipi_csi2_enable(csi2_dev);
265
266         /* D-PHY */
267
268         ret = phy_power_on(dphy);
269         if (ret) {
270                 dev_err(dev, "failed to power on MIPI D-PHY\n");
271                 goto error_pm;
272         }
273
274         /* Source */
275
276         ret = v4l2_subdev_call(source_subdev, video, s_stream, 1);
277         if (ret && ret != -ENOIOCTLCMD)
278                 goto disable;
279
280         return 0;
281
282 disable:
283         if (!on)
284                 ret = 0;
285         phy_power_off(dphy);
286         sun6i_mipi_csi2_disable(csi2_dev);
287
288 error_pm:
289         pm_runtime_put(dev);
290
291         return ret;
292 }
293
294 static const struct v4l2_subdev_video_ops sun6i_mipi_csi2_video_ops = {
295         .s_stream       = sun6i_mipi_csi2_s_stream,
296 };
297
298 static void
299 sun6i_mipi_csi2_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
300 {
301         if (!sun6i_mipi_csi2_format_find(mbus_format->code))
302                 mbus_format->code = sun6i_mipi_csi2_formats[0].mbus_code;
303
304         mbus_format->field = V4L2_FIELD_NONE;
305         mbus_format->colorspace = V4L2_COLORSPACE_RAW;
306         mbus_format->quantization = V4L2_QUANTIZATION_DEFAULT;
307         mbus_format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
308 }
309
310 static int sun6i_mipi_csi2_init_cfg(struct v4l2_subdev *subdev,
311                                     struct v4l2_subdev_state *state)
312 {
313         struct sun6i_mipi_csi2_device *csi2_dev = v4l2_get_subdevdata(subdev);
314         unsigned int pad = SUN6I_MIPI_CSI2_PAD_SINK;
315         struct v4l2_mbus_framefmt *mbus_format =
316                 v4l2_subdev_get_try_format(subdev, state, pad);
317         struct mutex *lock = &csi2_dev->bridge.lock;
318
319         mutex_lock(lock);
320
321         mbus_format->code = sun6i_mipi_csi2_formats[0].mbus_code;
322         mbus_format->width = 640;
323         mbus_format->height = 480;
324
325         sun6i_mipi_csi2_mbus_format_prepare(mbus_format);
326
327         mutex_unlock(lock);
328
329         return 0;
330 }
331
332 static int
333 sun6i_mipi_csi2_enum_mbus_code(struct v4l2_subdev *subdev,
334                                struct v4l2_subdev_state *state,
335                                struct v4l2_subdev_mbus_code_enum *code_enum)
336 {
337         if (code_enum->index >= ARRAY_SIZE(sun6i_mipi_csi2_formats))
338                 return -EINVAL;
339
340         code_enum->code = sun6i_mipi_csi2_formats[code_enum->index].mbus_code;
341
342         return 0;
343 }
344
345 static int sun6i_mipi_csi2_get_fmt(struct v4l2_subdev *subdev,
346                                    struct v4l2_subdev_state *state,
347                                    struct v4l2_subdev_format *format)
348 {
349         struct sun6i_mipi_csi2_device *csi2_dev = v4l2_get_subdevdata(subdev);
350         struct v4l2_mbus_framefmt *mbus_format = &format->format;
351         struct mutex *lock = &csi2_dev->bridge.lock;
352
353         mutex_lock(lock);
354
355         if (format->which == V4L2_SUBDEV_FORMAT_TRY)
356                 *mbus_format = *v4l2_subdev_get_try_format(subdev, state,
357                                                            format->pad);
358         else
359                 *mbus_format = csi2_dev->bridge.mbus_format;
360
361         mutex_unlock(lock);
362
363         return 0;
364 }
365
366 static int sun6i_mipi_csi2_set_fmt(struct v4l2_subdev *subdev,
367                                    struct v4l2_subdev_state *state,
368                                    struct v4l2_subdev_format *format)
369 {
370         struct sun6i_mipi_csi2_device *csi2_dev = v4l2_get_subdevdata(subdev);
371         struct v4l2_mbus_framefmt *mbus_format = &format->format;
372         struct mutex *lock = &csi2_dev->bridge.lock;
373
374         mutex_lock(lock);
375
376         sun6i_mipi_csi2_mbus_format_prepare(mbus_format);
377
378         if (format->which == V4L2_SUBDEV_FORMAT_TRY)
379                 *v4l2_subdev_get_try_format(subdev, state, format->pad) =
380                         *mbus_format;
381         else
382                 csi2_dev->bridge.mbus_format = *mbus_format;
383
384         mutex_unlock(lock);
385
386         return 0;
387 }
388
389 static const struct v4l2_subdev_pad_ops sun6i_mipi_csi2_pad_ops = {
390         .init_cfg       = sun6i_mipi_csi2_init_cfg,
391         .enum_mbus_code = sun6i_mipi_csi2_enum_mbus_code,
392         .get_fmt        = sun6i_mipi_csi2_get_fmt,
393         .set_fmt        = sun6i_mipi_csi2_set_fmt,
394 };
395
396 static const struct v4l2_subdev_ops sun6i_mipi_csi2_subdev_ops = {
397         .video  = &sun6i_mipi_csi2_video_ops,
398         .pad    = &sun6i_mipi_csi2_pad_ops,
399 };
400
401 /* Media Entity */
402
403 static const struct media_entity_operations sun6i_mipi_csi2_entity_ops = {
404         .link_validate  = v4l2_subdev_link_validate,
405 };
406
407 /* V4L2 Async */
408
409 static int
410 sun6i_mipi_csi2_notifier_bound(struct v4l2_async_notifier *notifier,
411                                struct v4l2_subdev *remote_subdev,
412                                struct v4l2_async_subdev *async_subdev)
413 {
414         struct v4l2_subdev *subdev = notifier->sd;
415         struct sun6i_mipi_csi2_device *csi2_dev =
416                 container_of(notifier, struct sun6i_mipi_csi2_device,
417                              bridge.notifier);
418         struct media_entity *sink_entity = &subdev->entity;
419         struct media_entity *source_entity = &remote_subdev->entity;
420         struct device *dev = csi2_dev->dev;
421         int sink_pad_index = 0;
422         int source_pad_index;
423         int ret;
424
425         ret = media_entity_get_fwnode_pad(source_entity, remote_subdev->fwnode,
426                                           MEDIA_PAD_FL_SOURCE);
427         if (ret < 0) {
428                 dev_err(dev, "missing source pad in external entity %s\n",
429                         source_entity->name);
430                 return -EINVAL;
431         }
432
433         source_pad_index = ret;
434
435         dev_dbg(dev, "creating %s:%u -> %s:%u link\n", source_entity->name,
436                 source_pad_index, sink_entity->name, sink_pad_index);
437
438         ret = media_create_pad_link(source_entity, source_pad_index,
439                                     sink_entity, sink_pad_index,
440                                     MEDIA_LNK_FL_ENABLED |
441                                     MEDIA_LNK_FL_IMMUTABLE);
442         if (ret) {
443                 dev_err(dev, "failed to create %s:%u -> %s:%u link\n",
444                         source_entity->name, source_pad_index,
445                         sink_entity->name, sink_pad_index);
446                 return ret;
447         }
448
449         csi2_dev->bridge.source_subdev = remote_subdev;
450
451         return 0;
452 }
453
454 static const struct v4l2_async_notifier_operations
455 sun6i_mipi_csi2_notifier_ops = {
456         .bound  = sun6i_mipi_csi2_notifier_bound,
457 };
458
459 /* Bridge */
460
461 static int
462 sun6i_mipi_csi2_bridge_source_setup(struct sun6i_mipi_csi2_device *csi2_dev)
463 {
464         struct v4l2_async_notifier *notifier = &csi2_dev->bridge.notifier;
465         struct v4l2_fwnode_endpoint *endpoint = &csi2_dev->bridge.endpoint;
466         struct v4l2_async_subdev *subdev_async;
467         struct fwnode_handle *handle;
468         struct device *dev = csi2_dev->dev;
469         int ret;
470
471         handle = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0,
472                                                  FWNODE_GRAPH_ENDPOINT_NEXT);
473         if (!handle)
474                 return -ENODEV;
475
476         endpoint->bus_type = V4L2_MBUS_CSI2_DPHY;
477
478         ret = v4l2_fwnode_endpoint_parse(handle, endpoint);
479         if (ret)
480                 goto complete;
481
482         subdev_async =
483                 v4l2_async_nf_add_fwnode_remote(notifier, handle,
484                                                 struct v4l2_async_subdev);
485         if (IS_ERR(subdev_async))
486                 ret = PTR_ERR(subdev_async);
487
488 complete:
489         fwnode_handle_put(handle);
490
491         return ret;
492 }
493
494 static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
495 {
496         struct sun6i_mipi_csi2_bridge *bridge = &csi2_dev->bridge;
497         struct v4l2_subdev *subdev = &bridge->subdev;
498         struct v4l2_async_notifier *notifier = &bridge->notifier;
499         struct media_pad *pads = bridge->pads;
500         struct device *dev = csi2_dev->dev;
501         int ret;
502
503         mutex_init(&bridge->lock);
504
505         /* V4L2 Subdev */
506
507         v4l2_subdev_init(subdev, &sun6i_mipi_csi2_subdev_ops);
508         strscpy(subdev->name, SUN6I_MIPI_CSI2_NAME, sizeof(subdev->name));
509         subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
510         subdev->owner = THIS_MODULE;
511         subdev->dev = dev;
512
513         v4l2_set_subdevdata(subdev, csi2_dev);
514
515         /* Media Entity */
516
517         subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
518         subdev->entity.ops = &sun6i_mipi_csi2_entity_ops;
519
520         /* Media Pads */
521
522         pads[SUN6I_MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
523         pads[SUN6I_MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
524
525         ret = media_entity_pads_init(&subdev->entity, SUN6I_MIPI_CSI2_PAD_COUNT,
526                                      pads);
527         if (ret)
528                 return ret;
529
530         /* V4L2 Async */
531
532         v4l2_async_nf_init(notifier);
533         notifier->ops = &sun6i_mipi_csi2_notifier_ops;
534
535         ret = sun6i_mipi_csi2_bridge_source_setup(csi2_dev);
536         if (ret)
537                 goto error_v4l2_notifier_cleanup;
538
539         ret = v4l2_async_subdev_nf_register(subdev, notifier);
540         if (ret < 0)
541                 goto error_v4l2_notifier_cleanup;
542
543         /* V4L2 Subdev */
544
545         ret = v4l2_async_register_subdev(subdev);
546         if (ret < 0)
547                 goto error_v4l2_notifier_unregister;
548
549         return 0;
550
551 error_v4l2_notifier_unregister:
552         v4l2_async_nf_unregister(notifier);
553
554 error_v4l2_notifier_cleanup:
555         v4l2_async_nf_cleanup(notifier);
556
557         media_entity_cleanup(&subdev->entity);
558
559         return ret;
560 }
561
562 static void
563 sun6i_mipi_csi2_bridge_cleanup(struct sun6i_mipi_csi2_device *csi2_dev)
564 {
565         struct v4l2_subdev *subdev = &csi2_dev->bridge.subdev;
566         struct v4l2_async_notifier *notifier = &csi2_dev->bridge.notifier;
567
568         v4l2_async_unregister_subdev(subdev);
569         v4l2_async_nf_unregister(notifier);
570         v4l2_async_nf_cleanup(notifier);
571         media_entity_cleanup(&subdev->entity);
572 }
573
574 /* Platform */
575
576 static int sun6i_mipi_csi2_suspend(struct device *dev)
577 {
578         struct sun6i_mipi_csi2_device *csi2_dev = dev_get_drvdata(dev);
579
580         clk_disable_unprepare(csi2_dev->clock_mod);
581         reset_control_assert(csi2_dev->reset);
582
583         return 0;
584 }
585
586 static int sun6i_mipi_csi2_resume(struct device *dev)
587 {
588         struct sun6i_mipi_csi2_device *csi2_dev = dev_get_drvdata(dev);
589         int ret;
590
591         ret = reset_control_deassert(csi2_dev->reset);
592         if (ret) {
593                 dev_err(dev, "failed to deassert reset\n");
594                 return ret;
595         }
596
597         ret = clk_prepare_enable(csi2_dev->clock_mod);
598         if (ret) {
599                 dev_err(dev, "failed to enable module clock\n");
600                 goto error_reset;
601         }
602
603         return 0;
604
605 error_reset:
606         reset_control_assert(csi2_dev->reset);
607
608         return ret;
609 }
610
611 static const struct dev_pm_ops sun6i_mipi_csi2_pm_ops = {
612         .runtime_suspend        = sun6i_mipi_csi2_suspend,
613         .runtime_resume         = sun6i_mipi_csi2_resume,
614 };
615
616 static const struct regmap_config sun6i_mipi_csi2_regmap_config = {
617         .reg_bits       = 32,
618         .reg_stride     = 4,
619         .val_bits       = 32,
620         .max_register   = 0x400,
621 };
622
623 static int
624 sun6i_mipi_csi2_resources_setup(struct sun6i_mipi_csi2_device *csi2_dev,
625                                 struct platform_device *platform_dev)
626 {
627         struct device *dev = csi2_dev->dev;
628         void __iomem *io_base;
629         int ret;
630
631         /* Registers */
632
633         io_base = devm_platform_ioremap_resource(platform_dev, 0);
634         if (IS_ERR(io_base))
635                 return PTR_ERR(io_base);
636
637         csi2_dev->regmap =
638                 devm_regmap_init_mmio_clk(dev, "bus", io_base,
639                                           &sun6i_mipi_csi2_regmap_config);
640         if (IS_ERR(csi2_dev->regmap)) {
641                 dev_err(dev, "failed to init register map\n");
642                 return PTR_ERR(csi2_dev->regmap);
643         }
644
645         /* Clock */
646
647         csi2_dev->clock_mod = devm_clk_get(dev, "mod");
648         if (IS_ERR(csi2_dev->clock_mod)) {
649                 dev_err(dev, "failed to acquire mod clock\n");
650                 return PTR_ERR(csi2_dev->clock_mod);
651         }
652
653         ret = clk_set_rate_exclusive(csi2_dev->clock_mod, 297000000);
654         if (ret) {
655                 dev_err(dev, "failed to set mod clock rate\n");
656                 return ret;
657         }
658
659         /* Reset */
660
661         csi2_dev->reset = devm_reset_control_get_shared(dev, NULL);
662         if (IS_ERR(csi2_dev->reset)) {
663                 dev_err(dev, "failed to get reset controller\n");
664                 ret = PTR_ERR(csi2_dev->reset);
665                 goto error_clock_rate_exclusive;
666         }
667
668         /* D-PHY */
669
670         csi2_dev->dphy = devm_phy_get(dev, "dphy");
671         if (IS_ERR(csi2_dev->dphy)) {
672                 dev_err(dev, "failed to get MIPI D-PHY\n");
673                 ret = PTR_ERR(csi2_dev->dphy);
674                 goto error_clock_rate_exclusive;
675         }
676
677         ret = phy_init(csi2_dev->dphy);
678         if (ret) {
679                 dev_err(dev, "failed to initialize MIPI D-PHY\n");
680                 goto error_clock_rate_exclusive;
681         }
682
683         /* Runtime PM */
684
685         pm_runtime_enable(dev);
686
687         return 0;
688
689 error_clock_rate_exclusive:
690         clk_rate_exclusive_put(csi2_dev->clock_mod);
691
692         return ret;
693 }
694
695 static void
696 sun6i_mipi_csi2_resources_cleanup(struct sun6i_mipi_csi2_device *csi2_dev)
697 {
698         pm_runtime_disable(csi2_dev->dev);
699         phy_exit(csi2_dev->dphy);
700         clk_rate_exclusive_put(csi2_dev->clock_mod);
701 }
702
703 static int sun6i_mipi_csi2_probe(struct platform_device *platform_dev)
704 {
705         struct sun6i_mipi_csi2_device *csi2_dev;
706         struct device *dev = &platform_dev->dev;
707         int ret;
708
709         csi2_dev = devm_kzalloc(dev, sizeof(*csi2_dev), GFP_KERNEL);
710         if (!csi2_dev)
711                 return -ENOMEM;
712
713         csi2_dev->dev = dev;
714         platform_set_drvdata(platform_dev, csi2_dev);
715
716         ret = sun6i_mipi_csi2_resources_setup(csi2_dev, platform_dev);
717         if (ret)
718                 return ret;
719
720         ret = sun6i_mipi_csi2_bridge_setup(csi2_dev);
721         if (ret)
722                 goto error_resources;
723
724         return 0;
725
726 error_resources:
727         sun6i_mipi_csi2_resources_cleanup(csi2_dev);
728
729         return ret;
730 }
731
732 static int sun6i_mipi_csi2_remove(struct platform_device *platform_dev)
733 {
734         struct sun6i_mipi_csi2_device *csi2_dev =
735                 platform_get_drvdata(platform_dev);
736
737         sun6i_mipi_csi2_bridge_cleanup(csi2_dev);
738         sun6i_mipi_csi2_resources_cleanup(csi2_dev);
739
740         return 0;
741 }
742
743 static const struct of_device_id sun6i_mipi_csi2_of_match[] = {
744         { .compatible   = "allwinner,sun6i-a31-mipi-csi2" },
745         {},
746 };
747 MODULE_DEVICE_TABLE(of, sun6i_mipi_csi2_of_match);
748
749 static struct platform_driver sun6i_mipi_csi2_platform_driver = {
750         .probe  = sun6i_mipi_csi2_probe,
751         .remove = sun6i_mipi_csi2_remove,
752         .driver = {
753                 .name           = SUN6I_MIPI_CSI2_NAME,
754                 .of_match_table = of_match_ptr(sun6i_mipi_csi2_of_match),
755                 .pm             = &sun6i_mipi_csi2_pm_ops,
756         },
757 };
758 module_platform_driver(sun6i_mipi_csi2_platform_driver);
759
760 MODULE_DESCRIPTION("Allwinner A31 MIPI CSI-2 Controller Driver");
761 MODULE_AUTHOR("Paul Kocialkowski <paul.kocialkowski@bootlin.com>");
762 MODULE_LICENSE("GPL");