1// SPDX-License-Identifier: GPL-2.0
2/*
3 * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver
4 *
5 * Copyright (C) 2021 Purism SPC
6 */
7
8#include <linux/clk.h>
9#include <linux/clk-provider.h>
10#include <linux/delay.h>
11#include <linux/errno.h>
12#include <linux/interconnect.h>
13#include <linux/interrupt.h>
14#include <linux/io.h>
15#include <linux/kernel.h>
16#include <linux/mfd/syscon.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/of.h>
20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
22#include <linux/regmap.h>
23#include <linux/regulator/consumer.h>
24#include <linux/reset.h>
25#include <linux/spinlock.h>
26
27#include <media/v4l2-common.h>
28#include <media/v4l2-device.h>
29#include <media/v4l2-fwnode.h>
30#include <media/v4l2-mc.h>
31#include <media/v4l2-subdev.h>
32
33#define MIPI_CSI2_DRIVER_NAME "imx8mq-mipi-csi2"
34#define MIPI_CSI2_SUBDEV_NAME MIPI_CSI2_DRIVER_NAME
35
36#define MIPI_CSI2_PAD_SINK 0
37#define MIPI_CSI2_PAD_SOURCE 1
38#define MIPI_CSI2_PADS_NUM 2
39
40#define MIPI_CSI2_DEF_PIX_WIDTH 640
41#define MIPI_CSI2_DEF_PIX_HEIGHT 480
42
43/* Register map definition */
44
45/* i.MX8MQ CSI-2 controller CSR */
46#define CSI2RX_CFG_NUM_LANES 0x100
47#define CSI2RX_CFG_DISABLE_DATA_LANES 0x104
48#define CSI2RX_BIT_ERR 0x108
49#define CSI2RX_IRQ_STATUS 0x10c
50#define CSI2RX_IRQ_MASK 0x110
51#define CSI2RX_IRQ_MASK_ALL 0x1ff
52#define CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE 0x8
53#define CSI2RX_ULPS_STATUS 0x114
54#define CSI2RX_PPI_ERRSOT_HS 0x118
55#define CSI2RX_PPI_ERRSOTSYNC_HS 0x11c
56#define CSI2RX_PPI_ERRESC 0x120
57#define CSI2RX_PPI_ERRSYNCESC 0x124
58#define CSI2RX_PPI_ERRCONTROL 0x128
59#define CSI2RX_CFG_DISABLE_PAYLOAD_0 0x12c
60#define CSI2RX_CFG_VID_VC_IGNORE 0x180
61#define CSI2RX_CFG_VID_VC 0x184
62#define CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL 0x188
63#define CSI2RX_CFG_DISABLE_PAYLOAD_1 0x130
64
65enum {
66 ST_POWERED = 1,
67 ST_STREAMING = 2,
68 ST_SUSPENDED = 4,
69};
70
71enum imx8mq_mipi_csi_clk {
72 CSI2_CLK_CORE,
73 CSI2_CLK_ESC,
74 CSI2_CLK_UI,
75 CSI2_NUM_CLKS,
76};
77
78static const char * const imx8mq_mipi_csi_clk_id[CSI2_NUM_CLKS] = {
79 [CSI2_CLK_CORE] = "core",
80 [CSI2_CLK_ESC] = "esc",
81 [CSI2_CLK_UI] = "ui",
82};
83
84#define CSI2_NUM_CLKS ARRAY_SIZE(imx8mq_mipi_csi_clk_id)
85
86#define GPR_CSI2_1_RX_ENABLE BIT(13)
87#define GPR_CSI2_1_VID_INTFC_ENB BIT(12)
88#define GPR_CSI2_1_HSEL BIT(10)
89#define GPR_CSI2_1_CONT_CLK_MODE BIT(8)
90#define GPR_CSI2_1_S_PRG_RXHS_SETTLE(x) (((x) & 0x3f) << 2)
91
92/*
93 * The send level configures the number of entries that must accumulate in
94 * the Pixel FIFO before the data will be transferred to the video output.
95 * The exact value needed for this configuration is dependent on the rate at
96 * which the sensor transfers data to the CSI-2 Controller and the user
97 * video clock.
98 *
99 * The calculation is the classical rate-in rate-out type of problem: If the
100 * video bandwidth is 10% faster than the incoming mipi data and the video
101 * line length is 500 pixels, then the fifo should be allowed to fill
102 * 10% of the line length or 50 pixels. If the gap data is ok, then the level
103 * can be set to 16 and ignored.
104 */
105#define CSI2RX_SEND_LEVEL 64
106
107struct csi_state {
108 struct device *dev;
109 void __iomem *regs;
110 struct clk_bulk_data clks[CSI2_NUM_CLKS];
111 struct reset_control *rst;
112 struct regulator *mipi_phy_regulator;
113
114 struct v4l2_subdev sd;
115 struct media_pad pads[MIPI_CSI2_PADS_NUM];
116 struct v4l2_async_notifier notifier;
117 struct v4l2_subdev *src_sd;
118
119 struct v4l2_mbus_config_mipi_csi2 bus;
120
121 struct mutex lock; /* Protect state */
122 u32 state;
123
124 struct regmap *phy_gpr;
125 u8 phy_gpr_reg;
126
127 struct icc_path *icc_path;
128 s32 icc_path_bw;
129};
130
131/* -----------------------------------------------------------------------------
132 * Format helpers
133 */
134
135struct csi2_pix_format {
136 u32 code;
137 u8 width;
138};
139
140static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = {
141 /* RAW (Bayer and greyscale) formats. */
142 {
143 .code = MEDIA_BUS_FMT_SBGGR8_1X8,
144 .width = 8,
145 }, {
146 .code = MEDIA_BUS_FMT_SGBRG8_1X8,
147 .width = 8,
148 }, {
149 .code = MEDIA_BUS_FMT_SGRBG8_1X8,
150 .width = 8,
151 }, {
152 .code = MEDIA_BUS_FMT_SRGGB8_1X8,
153 .width = 8,
154 }, {
155 .code = MEDIA_BUS_FMT_Y8_1X8,
156 .width = 8,
157 }, {
158 .code = MEDIA_BUS_FMT_SBGGR10_1X10,
159 .width = 10,
160 }, {
161 .code = MEDIA_BUS_FMT_SGBRG10_1X10,
162 .width = 10,
163 }, {
164 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
165 .width = 10,
166 }, {
167 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
168 .width = 10,
169 }, {
170 .code = MEDIA_BUS_FMT_Y10_1X10,
171 .width = 10,
172 }, {
173 .code = MEDIA_BUS_FMT_SBGGR12_1X12,
174 .width = 12,
175 }, {
176 .code = MEDIA_BUS_FMT_SGBRG12_1X12,
177 .width = 12,
178 }, {
179 .code = MEDIA_BUS_FMT_SGRBG12_1X12,
180 .width = 12,
181 }, {
182 .code = MEDIA_BUS_FMT_SRGGB12_1X12,
183 .width = 12,
184 }, {
185 .code = MEDIA_BUS_FMT_Y12_1X12,
186 .width = 12,
187 }, {
188 .code = MEDIA_BUS_FMT_SBGGR14_1X14,
189 .width = 14,
190 }, {
191 .code = MEDIA_BUS_FMT_SGBRG14_1X14,
192 .width = 14,
193 }, {
194 .code = MEDIA_BUS_FMT_SGRBG14_1X14,
195 .width = 14,
196 }, {
197 .code = MEDIA_BUS_FMT_SRGGB14_1X14,
198 .width = 14,
199 },
200 /* YUV formats */
201 {
202 .code = MEDIA_BUS_FMT_YUYV8_1X16,
203 .width = 16,
204 }, {
205 .code = MEDIA_BUS_FMT_UYVY8_1X16,
206 .width = 16,
207 }
208};
209
210static const struct csi2_pix_format *find_csi2_format(u32 code)
211{
212 unsigned int i;
213
214 for (i = 0; i < ARRAY_SIZE(imx8mq_mipi_csi_formats); i++)
215 if (code == imx8mq_mipi_csi_formats[i].code)
216 return &imx8mq_mipi_csi_formats[i];
217 return NULL;
218}
219
220/* -----------------------------------------------------------------------------
221 * Hardware configuration
222 */
223
224static inline void imx8mq_mipi_csi_write(struct csi_state *state, u32 reg, u32 val)
225{
226 writel(val, addr: state->regs + reg);
227}
228
229static int imx8mq_mipi_csi_sw_reset(struct csi_state *state)
230{
231 int ret;
232
233 /*
234 * these are most likely self-clearing reset bits. to make it
235 * more clear, the reset-imx7 driver should implement the
236 * .reset() operation.
237 */
238 ret = reset_control_assert(rstc: state->rst);
239 if (ret < 0) {
240 dev_err(state->dev, "Failed to assert resets: %d\n", ret);
241 return ret;
242 }
243
244 return 0;
245}
246
247static void imx8mq_mipi_csi_set_params(struct csi_state *state)
248{
249 int lanes = state->bus.num_data_lanes;
250
251 imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, val: lanes - 1);
252 imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES,
253 val: (0xf << lanes) & 0xf);
254 imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, CSI2RX_IRQ_MASK_ALL);
255 /*
256 * 0x180 bit 0 controls the Virtual Channel behaviour: when set the
257 * interface ignores the Virtual Channel (VC) field in received packets;
258 * when cleared it causes the interface to only accept packets whose VC
259 * matches the value to which VC is set at offset 0x184.
260 */
261 imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_VC_IGNORE, val: 1);
262 imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL,
263 CSI2RX_SEND_LEVEL);
264}
265
266static int imx8mq_mipi_csi_clk_enable(struct csi_state *state)
267{
268 return clk_bulk_prepare_enable(CSI2_NUM_CLKS, clks: state->clks);
269}
270
271static void imx8mq_mipi_csi_clk_disable(struct csi_state *state)
272{
273 clk_bulk_disable_unprepare(CSI2_NUM_CLKS, clks: state->clks);
274}
275
276static int imx8mq_mipi_csi_clk_get(struct csi_state *state)
277{
278 unsigned int i;
279
280 for (i = 0; i < CSI2_NUM_CLKS; i++)
281 state->clks[i].id = imx8mq_mipi_csi_clk_id[i];
282
283 return devm_clk_bulk_get(dev: state->dev, CSI2_NUM_CLKS, clks: state->clks);
284}
285
286static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state,
287 struct v4l2_subdev_state *sd_state,
288 u32 *hs_settle)
289{
290 s64 link_freq;
291 u32 lane_rate;
292 unsigned long esc_clk_rate;
293 u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns;
294 const struct v4l2_mbus_framefmt *fmt;
295 const struct csi2_pix_format *csi2_fmt;
296
297 /* Calculate the line rate from the pixel rate. */
298
299 fmt = v4l2_subdev_state_get_format(sd_state, MIPI_CSI2_PAD_SINK);
300 csi2_fmt = find_csi2_format(code: fmt->code);
301
302 link_freq = v4l2_get_link_freq(handler: state->src_sd->ctrl_handler,
303 mul: csi2_fmt->width,
304 div: state->bus.num_data_lanes * 2);
305 if (link_freq < 0) {
306 dev_err(state->dev, "Unable to obtain link frequency: %d\n",
307 (int)link_freq);
308 return link_freq;
309 }
310
311 lane_rate = link_freq * 2;
312 if (lane_rate < 80000000 || lane_rate > 1500000000) {
313 dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
314 return -EINVAL;
315 }
316
317 /*
318 * The D-PHY specification requires Ths-settle to be in the range
319 * 85ns + 6*UI to 140ns + 10*UI, with the unit interval UI being half
320 * the clock period.
321 *
322 * The Ths-settle value is expressed in the hardware as a multiple of
323 * the Esc clock period:
324 *
325 * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc
326 *
327 * Due to the one cycle inaccuracy introduced by rounding, the
328 * documentation recommends picking a value away from the boundaries.
329 * Let's pick the average.
330 */
331 esc_clk_rate = clk_get_rate(clk: state->clks[CSI2_CLK_ESC].clk);
332 if (!esc_clk_rate) {
333 dev_err(state->dev, "Could not get esc clock rate.\n");
334 return -EINVAL;
335 }
336
337 dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate);
338 esc_clk_period_ns = 1000000000 / esc_clk_rate;
339
340 min_ths_settle = 85 + 6 * 1000000 / (lane_rate / 1000);
341 max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000);
342 ths_settle_ns = (min_ths_settle + max_ths_settle) / 2;
343
344 *hs_settle = ths_settle_ns / esc_clk_period_ns - 1;
345
346 dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n",
347 lane_rate, ths_settle_ns, *hs_settle);
348
349 return 0;
350}
351
352static int imx8mq_mipi_csi_start_stream(struct csi_state *state,
353 struct v4l2_subdev_state *sd_state)
354{
355 int ret;
356 u32 hs_settle = 0;
357
358 ret = imx8mq_mipi_csi_sw_reset(state);
359 if (ret)
360 return ret;
361
362 imx8mq_mipi_csi_set_params(state);
363 ret = imx8mq_mipi_csi_calc_hs_settle(state, sd_state, hs_settle: &hs_settle);
364 if (ret)
365 return ret;
366
367 regmap_update_bits(map: state->phy_gpr,
368 reg: state->phy_gpr_reg,
369 mask: 0x3fff,
370 GPR_CSI2_1_RX_ENABLE |
371 GPR_CSI2_1_VID_INTFC_ENB |
372 GPR_CSI2_1_HSEL |
373 GPR_CSI2_1_CONT_CLK_MODE |
374 GPR_CSI2_1_S_PRG_RXHS_SETTLE(hs_settle));
375
376 return 0;
377}
378
379static void imx8mq_mipi_csi_stop_stream(struct csi_state *state)
380{
381 imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, val: 0xf);
382}
383
384/* -----------------------------------------------------------------------------
385 * V4L2 subdev operations
386 */
387
388static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev)
389{
390 return container_of(sdev, struct csi_state, sd);
391}
392
393static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
394{
395 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
396 struct v4l2_subdev_state *sd_state;
397 int ret = 0;
398
399 if (enable) {
400 ret = pm_runtime_resume_and_get(dev: state->dev);
401 if (ret < 0)
402 return ret;
403 }
404
405 mutex_lock(&state->lock);
406
407 if (enable) {
408 if (state->state & ST_SUSPENDED) {
409 ret = -EBUSY;
410 goto unlock;
411 }
412
413 sd_state = v4l2_subdev_lock_and_get_active_state(sd);
414 ret = imx8mq_mipi_csi_start_stream(state, sd_state);
415 v4l2_subdev_unlock_state(state: sd_state);
416
417 if (ret < 0)
418 goto unlock;
419
420 ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
421 if (ret < 0)
422 goto unlock;
423
424 state->state |= ST_STREAMING;
425 } else {
426 v4l2_subdev_call(state->src_sd, video, s_stream, 0);
427 imx8mq_mipi_csi_stop_stream(state);
428 state->state &= ~ST_STREAMING;
429 }
430
431unlock:
432 mutex_unlock(lock: &state->lock);
433
434 if (!enable || ret < 0)
435 pm_runtime_put(dev: state->dev);
436
437 return ret;
438}
439
440static int imx8mq_mipi_csi_init_state(struct v4l2_subdev *sd,
441 struct v4l2_subdev_state *sd_state)
442{
443 struct v4l2_mbus_framefmt *fmt_sink;
444 struct v4l2_mbus_framefmt *fmt_source;
445
446 fmt_sink = v4l2_subdev_state_get_format(sd_state, MIPI_CSI2_PAD_SINK);
447 fmt_source = v4l2_subdev_state_get_format(sd_state,
448 MIPI_CSI2_PAD_SOURCE);
449
450 fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10;
451 fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH;
452 fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT;
453 fmt_sink->field = V4L2_FIELD_NONE;
454
455 fmt_sink->colorspace = V4L2_COLORSPACE_RAW;
456 fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
457 fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
458 fmt_sink->quantization =
459 V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
460 fmt_sink->ycbcr_enc);
461
462 *fmt_source = *fmt_sink;
463
464 return 0;
465}
466
467static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd,
468 struct v4l2_subdev_state *sd_state,
469 struct v4l2_subdev_mbus_code_enum *code)
470{
471 /*
472 * We can't transcode in any way, the source format is identical
473 * to the sink format.
474 */
475 if (code->pad == MIPI_CSI2_PAD_SOURCE) {
476 struct v4l2_mbus_framefmt *fmt;
477
478 if (code->index > 0)
479 return -EINVAL;
480
481 fmt = v4l2_subdev_state_get_format(sd_state, code->pad);
482 code->code = fmt->code;
483 return 0;
484 }
485
486 if (code->pad != MIPI_CSI2_PAD_SINK)
487 return -EINVAL;
488
489 if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats))
490 return -EINVAL;
491
492 code->code = imx8mq_mipi_csi_formats[code->index].code;
493
494 return 0;
495}
496
497static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
498 struct v4l2_subdev_state *sd_state,
499 struct v4l2_subdev_format *sdformat)
500{
501 const struct csi2_pix_format *csi2_fmt;
502 struct v4l2_mbus_framefmt *fmt;
503
504 /*
505 * The device can't transcode in any way, the source format can't be
506 * modified.
507 */
508 if (sdformat->pad == MIPI_CSI2_PAD_SOURCE)
509 return v4l2_subdev_get_fmt(sd, state: sd_state, format: sdformat);
510
511 if (sdformat->pad != MIPI_CSI2_PAD_SINK)
512 return -EINVAL;
513
514 csi2_fmt = find_csi2_format(code: sdformat->format.code);
515 if (!csi2_fmt)
516 csi2_fmt = &imx8mq_mipi_csi_formats[0];
517
518 fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
519
520 fmt->code = csi2_fmt->code;
521 fmt->width = sdformat->format.width;
522 fmt->height = sdformat->format.height;
523
524 sdformat->format = *fmt;
525
526 /* Propagate the format from sink to source. */
527 fmt = v4l2_subdev_state_get_format(sd_state, MIPI_CSI2_PAD_SOURCE);
528 *fmt = sdformat->format;
529
530 return 0;
531}
532
533static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = {
534 .s_stream = imx8mq_mipi_csi_s_stream,
535};
536
537static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = {
538 .enum_mbus_code = imx8mq_mipi_csi_enum_mbus_code,
539 .get_fmt = v4l2_subdev_get_fmt,
540 .set_fmt = imx8mq_mipi_csi_set_fmt,
541};
542
543static const struct v4l2_subdev_ops imx8mq_mipi_csi_subdev_ops = {
544 .video = &imx8mq_mipi_csi_video_ops,
545 .pad = &imx8mq_mipi_csi_pad_ops,
546};
547
548static const struct v4l2_subdev_internal_ops imx8mq_mipi_csi_internal_ops = {
549 .init_state = imx8mq_mipi_csi_init_state,
550};
551
552/* -----------------------------------------------------------------------------
553 * Media entity operations
554 */
555
556static const struct media_entity_operations imx8mq_mipi_csi_entity_ops = {
557 .link_validate = v4l2_subdev_link_validate,
558 .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
559};
560
561/* -----------------------------------------------------------------------------
562 * Async subdev notifier
563 */
564
565static struct csi_state *
566mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n)
567{
568 return container_of(n, struct csi_state, notifier);
569}
570
571static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier,
572 struct v4l2_subdev *sd,
573 struct v4l2_async_connection *asd)
574{
575 struct csi_state *state = mipi_notifier_to_csi2_state(n: notifier);
576 struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK];
577
578 state->src_sd = sd;
579
580 return v4l2_create_fwnode_links_to_pad(src_sd: sd, sink, MEDIA_LNK_FL_ENABLED |
581 MEDIA_LNK_FL_IMMUTABLE);
582}
583
584static const struct v4l2_async_notifier_operations imx8mq_mipi_csi_notify_ops = {
585 .bound = imx8mq_mipi_csi_notify_bound,
586};
587
588static int imx8mq_mipi_csi_async_register(struct csi_state *state)
589{
590 struct v4l2_fwnode_endpoint vep = {
591 .bus_type = V4L2_MBUS_CSI2_DPHY,
592 };
593 struct v4l2_async_connection *asd;
594 struct fwnode_handle *ep;
595 unsigned int i;
596 int ret;
597
598 v4l2_async_subdev_nf_init(notifier: &state->notifier, sd: &state->sd);
599
600 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), port: 0, endpoint: 0,
601 FWNODE_GRAPH_ENDPOINT_NEXT);
602 if (!ep)
603 return -ENOTCONN;
604
605 ret = v4l2_fwnode_endpoint_parse(fwnode: ep, vep: &vep);
606 if (ret)
607 goto err_parse;
608
609 for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
610 if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
611 dev_err(state->dev,
612 "data lanes reordering is not supported");
613 ret = -EINVAL;
614 goto err_parse;
615 }
616 }
617
618 state->bus = vep.bus.mipi_csi2;
619
620 dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n",
621 state->bus.num_data_lanes,
622 state->bus.flags);
623
624 asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
625 struct v4l2_async_connection);
626 if (IS_ERR(ptr: asd)) {
627 ret = PTR_ERR(ptr: asd);
628 goto err_parse;
629 }
630
631 fwnode_handle_put(fwnode: ep);
632
633 state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
634
635 ret = v4l2_async_nf_register(notifier: &state->notifier);
636 if (ret)
637 return ret;
638
639 return v4l2_async_register_subdev(sd: &state->sd);
640
641err_parse:
642 fwnode_handle_put(fwnode: ep);
643
644 return ret;
645}
646
647/* -----------------------------------------------------------------------------
648 * Suspend/resume
649 */
650
651static void imx8mq_mipi_csi_pm_suspend(struct device *dev)
652{
653 struct v4l2_subdev *sd = dev_get_drvdata(dev);
654 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
655
656 mutex_lock(&state->lock);
657
658 if (state->state & ST_POWERED) {
659 imx8mq_mipi_csi_stop_stream(state);
660 imx8mq_mipi_csi_clk_disable(state);
661 state->state &= ~ST_POWERED;
662 }
663
664 mutex_unlock(lock: &state->lock);
665}
666
667static int imx8mq_mipi_csi_pm_resume(struct device *dev)
668{
669 struct v4l2_subdev *sd = dev_get_drvdata(dev);
670 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
671 struct v4l2_subdev_state *sd_state;
672 int ret = 0;
673
674 mutex_lock(&state->lock);
675
676 if (!(state->state & ST_POWERED)) {
677 state->state |= ST_POWERED;
678 ret = imx8mq_mipi_csi_clk_enable(state);
679 }
680 if (state->state & ST_STREAMING) {
681 sd_state = v4l2_subdev_lock_and_get_active_state(sd);
682 ret = imx8mq_mipi_csi_start_stream(state, sd_state);
683 v4l2_subdev_unlock_state(state: sd_state);
684 if (ret)
685 goto unlock;
686 }
687
688 state->state &= ~ST_SUSPENDED;
689
690unlock:
691 mutex_unlock(lock: &state->lock);
692
693 return ret ? -EAGAIN : 0;
694}
695
696static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev)
697{
698 struct v4l2_subdev *sd = dev_get_drvdata(dev);
699 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
700
701 imx8mq_mipi_csi_pm_suspend(dev);
702
703 state->state |= ST_SUSPENDED;
704
705 return 0;
706}
707
708static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev)
709{
710 struct v4l2_subdev *sd = dev_get_drvdata(dev);
711 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
712
713 if (!(state->state & ST_SUSPENDED))
714 return 0;
715
716 return imx8mq_mipi_csi_pm_resume(dev);
717}
718
719static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev)
720{
721 struct v4l2_subdev *sd = dev_get_drvdata(dev);
722 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
723 int ret;
724
725 imx8mq_mipi_csi_pm_suspend(dev);
726
727 ret = icc_set_bw(path: state->icc_path, avg_bw: 0, peak_bw: 0);
728 if (ret)
729 dev_err(dev, "icc_set_bw failed with %d\n", ret);
730
731 return ret;
732}
733
734static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev)
735{
736 struct v4l2_subdev *sd = dev_get_drvdata(dev);
737 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
738 int ret;
739
740 ret = icc_set_bw(path: state->icc_path, avg_bw: 0, peak_bw: state->icc_path_bw);
741 if (ret) {
742 dev_err(dev, "icc_set_bw failed with %d\n", ret);
743 return ret;
744 }
745
746 return imx8mq_mipi_csi_pm_resume(dev);
747}
748
749static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = {
750 SET_RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend,
751 imx8mq_mipi_csi_runtime_resume,
752 NULL)
753 SET_SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume)
754};
755
756/* -----------------------------------------------------------------------------
757 * Probe/remove & platform driver
758 */
759
760static int imx8mq_mipi_csi_subdev_init(struct csi_state *state)
761{
762 struct v4l2_subdev *sd = &state->sd;
763 int ret;
764
765 v4l2_subdev_init(sd, ops: &imx8mq_mipi_csi_subdev_ops);
766 sd->internal_ops = &imx8mq_mipi_csi_internal_ops;
767 sd->owner = THIS_MODULE;
768 snprintf(buf: sd->name, size: sizeof(sd->name), fmt: "%s %s",
769 MIPI_CSI2_SUBDEV_NAME, dev_name(dev: state->dev));
770
771 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
772
773 sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
774 sd->entity.ops = &imx8mq_mipi_csi_entity_ops;
775
776 sd->dev = state->dev;
777
778 state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
779 | MEDIA_PAD_FL_MUST_CONNECT;
780 state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
781 | MEDIA_PAD_FL_MUST_CONNECT;
782 ret = media_entity_pads_init(entity: &sd->entity, MIPI_CSI2_PADS_NUM,
783 pads: state->pads);
784 if (ret)
785 return ret;
786
787 ret = v4l2_subdev_init_finalize(sd);
788 if (ret) {
789 media_entity_cleanup(entity: &sd->entity);
790 return ret;
791 }
792
793 return 0;
794}
795
796static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev)
797{
798 struct v4l2_subdev *sd = dev_get_drvdata(dev: &pdev->dev);
799 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
800
801 icc_put(path: state->icc_path);
802}
803
804static int imx8mq_mipi_csi_init_icc(struct platform_device *pdev)
805{
806 struct v4l2_subdev *sd = dev_get_drvdata(dev: &pdev->dev);
807 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
808
809 /* Optional interconnect request */
810 state->icc_path = of_icc_get(dev: &pdev->dev, name: "dram");
811 if (IS_ERR_OR_NULL(ptr: state->icc_path))
812 return PTR_ERR_OR_ZERO(ptr: state->icc_path);
813
814 state->icc_path_bw = MBps_to_icc(700);
815
816 return 0;
817}
818
819static int imx8mq_mipi_csi_parse_dt(struct csi_state *state)
820{
821 struct device *dev = state->dev;
822 struct device_node *np = state->dev->of_node;
823 struct device_node *node;
824 phandle ph;
825 u32 out_val[2];
826 int ret = 0;
827
828 state->rst = devm_reset_control_array_get_exclusive(dev);
829 if (IS_ERR(ptr: state->rst)) {
830 dev_err(dev, "Failed to get reset: %pe\n", state->rst);
831 return PTR_ERR(ptr: state->rst);
832 }
833
834 ret = of_property_read_u32_array(np, propname: "fsl,mipi-phy-gpr", out_values: out_val,
835 ARRAY_SIZE(out_val));
836 if (ret) {
837 dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret);
838 return ret;
839 }
840
841 ph = *out_val;
842
843 node = of_find_node_by_phandle(handle: ph);
844 if (!node) {
845 dev_err(dev, "Error finding node by phandle\n");
846 return -ENODEV;
847 }
848 state->phy_gpr = syscon_node_to_regmap(np: node);
849 of_node_put(node);
850 if (IS_ERR(ptr: state->phy_gpr)) {
851 dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr);
852 return PTR_ERR(ptr: state->phy_gpr);
853 }
854
855 state->phy_gpr_reg = out_val[1];
856 dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg);
857
858 return ret;
859}
860
861static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
862{
863 struct device *dev = &pdev->dev;
864 struct csi_state *state;
865 int ret;
866
867 state = devm_kzalloc(dev, size: sizeof(*state), GFP_KERNEL);
868 if (!state)
869 return -ENOMEM;
870
871 state->dev = dev;
872
873 ret = imx8mq_mipi_csi_parse_dt(state);
874 if (ret < 0) {
875 dev_err(dev, "Failed to parse device tree: %d\n", ret);
876 return ret;
877 }
878
879 /* Acquire resources. */
880 state->regs = devm_platform_ioremap_resource(pdev, index: 0);
881 if (IS_ERR(ptr: state->regs))
882 return PTR_ERR(ptr: state->regs);
883
884 ret = imx8mq_mipi_csi_clk_get(state);
885 if (ret < 0)
886 return ret;
887
888 platform_set_drvdata(pdev, data: &state->sd);
889
890 mutex_init(&state->lock);
891
892 ret = imx8mq_mipi_csi_subdev_init(state);
893 if (ret < 0)
894 goto mutex;
895
896 ret = imx8mq_mipi_csi_init_icc(pdev);
897 if (ret)
898 goto mutex;
899
900 /* Enable runtime PM. */
901 pm_runtime_enable(dev);
902 if (!pm_runtime_enabled(dev)) {
903 ret = imx8mq_mipi_csi_runtime_resume(dev);
904 if (ret < 0)
905 goto icc;
906 }
907
908 ret = imx8mq_mipi_csi_async_register(state);
909 if (ret < 0)
910 goto cleanup;
911
912 return 0;
913
914cleanup:
915 pm_runtime_disable(dev: &pdev->dev);
916 imx8mq_mipi_csi_runtime_suspend(dev: &pdev->dev);
917
918 media_entity_cleanup(entity: &state->sd.entity);
919 v4l2_subdev_cleanup(sd: &state->sd);
920 v4l2_async_nf_unregister(notifier: &state->notifier);
921 v4l2_async_nf_cleanup(notifier: &state->notifier);
922 v4l2_async_unregister_subdev(sd: &state->sd);
923icc:
924 imx8mq_mipi_csi_release_icc(pdev);
925mutex:
926 mutex_destroy(lock: &state->lock);
927
928 return ret;
929}
930
931static void imx8mq_mipi_csi_remove(struct platform_device *pdev)
932{
933 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
934 struct csi_state *state = mipi_sd_to_csi2_state(sdev: sd);
935
936 v4l2_async_nf_unregister(notifier: &state->notifier);
937 v4l2_async_nf_cleanup(notifier: &state->notifier);
938 v4l2_async_unregister_subdev(sd: &state->sd);
939
940 pm_runtime_disable(dev: &pdev->dev);
941 imx8mq_mipi_csi_runtime_suspend(dev: &pdev->dev);
942 media_entity_cleanup(entity: &state->sd.entity);
943 v4l2_subdev_cleanup(sd: &state->sd);
944 mutex_destroy(lock: &state->lock);
945 pm_runtime_set_suspended(dev: &pdev->dev);
946 imx8mq_mipi_csi_release_icc(pdev);
947}
948
949static const struct of_device_id imx8mq_mipi_csi_of_match[] = {
950 { .compatible = "fsl,imx8mq-mipi-csi2", },
951 { /* sentinel */ },
952};
953MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match);
954
955static struct platform_driver imx8mq_mipi_csi_driver = {
956 .probe = imx8mq_mipi_csi_probe,
957 .remove_new = imx8mq_mipi_csi_remove,
958 .driver = {
959 .of_match_table = imx8mq_mipi_csi_of_match,
960 .name = MIPI_CSI2_DRIVER_NAME,
961 .pm = &imx8mq_mipi_csi_pm_ops,
962 },
963};
964
965module_platform_driver(imx8mq_mipi_csi_driver);
966
967MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver");
968MODULE_AUTHOR("Martin Kepplinger <martin.kepplinger@puri.sm>");
969MODULE_LICENSE("GPL v2");
970MODULE_ALIAS("platform:imx8mq-mipi-csi2");
971

source code of linux/drivers/media/platform/nxp/imx8mq-mipi-csi2.c