1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2013--2024 Intel Corporation
4  */
5 
6 #include <linux/atomic.h>
7 #include <linux/bitfield.h>
8 #include <linux/bits.h>
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/minmax.h>
14 #include <linux/sprintf.h>
15 
16 #include <media/media-entity.h>
17 #include <media/v4l2-ctrls.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-event.h>
20 #include <media/v4l2-subdev.h>
21 
22 #include "ipu6-bus.h"
23 #include "ipu6-isys.h"
24 #include "ipu6-isys-csi2.h"
25 #include "ipu6-isys-subdev.h"
26 #include "ipu6-platform-isys-csi2-reg.h"
27 
28 static const u32 csi2_supported_codes[] = {
29 	MEDIA_BUS_FMT_RGB565_1X16,
30 	MEDIA_BUS_FMT_RGB888_1X24,
31 	MEDIA_BUS_FMT_UYVY8_1X16,
32 	MEDIA_BUS_FMT_YUYV8_1X16,
33 	MEDIA_BUS_FMT_SBGGR10_1X10,
34 	MEDIA_BUS_FMT_SGBRG10_1X10,
35 	MEDIA_BUS_FMT_SGRBG10_1X10,
36 	MEDIA_BUS_FMT_SRGGB10_1X10,
37 	MEDIA_BUS_FMT_SBGGR12_1X12,
38 	MEDIA_BUS_FMT_SGBRG12_1X12,
39 	MEDIA_BUS_FMT_SGRBG12_1X12,
40 	MEDIA_BUS_FMT_SRGGB12_1X12,
41 	MEDIA_BUS_FMT_SBGGR8_1X8,
42 	MEDIA_BUS_FMT_SGBRG8_1X8,
43 	MEDIA_BUS_FMT_SGRBG8_1X8,
44 	MEDIA_BUS_FMT_SRGGB8_1X8,
45 	MEDIA_BUS_FMT_META_8,
46 	MEDIA_BUS_FMT_META_10,
47 	MEDIA_BUS_FMT_META_12,
48 	MEDIA_BUS_FMT_META_16,
49 	MEDIA_BUS_FMT_META_24,
50 	0
51 };
52 
53 /*
54  * Strings corresponding to CSI-2 receiver errors are here.
55  * Corresponding macros are defined in the header file.
56  */
57 static const struct ipu6_csi2_error dphy_rx_errors[] = {
58 	{ "Single packet header error corrected", true },
59 	{ "Multiple packet header errors detected", true },
60 	{ "Payload checksum (CRC) error", true },
61 	{ "Transfer FIFO overflow", false },
62 	{ "Reserved short packet data type detected", true },
63 	{ "Reserved long packet data type detected", true },
64 	{ "Incomplete long packet detected", false },
65 	{ "Frame sync error", false },
66 	{ "Line sync error", false },
67 	{ "DPHY recoverable synchronization error", true },
68 	{ "DPHY fatal error", false },
69 	{ "DPHY elastic FIFO overflow", false },
70 	{ "Inter-frame short packet discarded", true },
71 	{ "Inter-frame long packet discarded", true },
72 	{ "MIPI pktgen overflow", false },
73 	{ "MIPI pktgen data loss", false },
74 	{ "FIFO overflow", false },
75 	{ "Lane deskew", false },
76 	{ "SOT sync error", false },
77 	{ "HSIDLE detected", false }
78 };
79 
ipu6_isys_csi2_get_link_freq(struct ipu6_isys_csi2 * csi2)80 s64 ipu6_isys_csi2_get_link_freq(struct ipu6_isys_csi2 *csi2)
81 {
82 	struct media_pad *src_pad;
83 
84 	if (!csi2)
85 		return -EINVAL;
86 
87 	src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity);
88 	if (IS_ERR(src_pad)) {
89 		dev_err(&csi2->isys->adev->auxdev.dev,
90 			"can't get source pad of %s (%ld)\n",
91 			csi2->asd.sd.name, PTR_ERR(src_pad));
92 		return PTR_ERR(src_pad);
93 	}
94 
95 	return v4l2_get_link_freq(src_pad, 0, 0);
96 }
97 
csi2_subscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)98 static int csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
99 				struct v4l2_event_subscription *sub)
100 {
101 	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
102 	struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);
103 	struct device *dev = &csi2->isys->adev->auxdev.dev;
104 
105 	dev_dbg(dev, "csi2 subscribe event(type %u id %u)\n",
106 		sub->type, sub->id);
107 
108 	switch (sub->type) {
109 	case V4L2_EVENT_FRAME_SYNC:
110 		return v4l2_event_subscribe(fh, sub, 10, NULL);
111 	case V4L2_EVENT_CTRL:
112 		return v4l2_ctrl_subscribe_event(fh, sub);
113 	default:
114 		return -EINVAL;
115 	}
116 }
117 
118 static const struct v4l2_subdev_core_ops csi2_sd_core_ops = {
119 	.subscribe_event = csi2_subscribe_event,
120 	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
121 };
122 
123 /*
124  * The input system CSI2+ receiver has several
125  * parameters affecting the receiver timings. These depend
126  * on the MIPI bus frequency F in Hz (sensor transmitter rate)
127  * as follows:
128  *	register value = (A/1e9 + B * UI) / COUNT_ACC
129  * where
130  *	UI = 1 / (2 * F) in seconds
131  *	COUNT_ACC = counter accuracy in seconds
132  *	COUNT_ACC = 0.125 ns = 1 / 8 ns, ACCINV = 8.
133  *
134  * A and B are coefficients from the table below,
135  * depending whether the register minimum or maximum value is
136  * calculated.
137  *				       Minimum     Maximum
138  * Clock lane			       A     B     A     B
139  * reg_rx_csi_dly_cnt_termen_clane     0     0    38     0
140  * reg_rx_csi_dly_cnt_settle_clane    95    -8   300   -16
141  * Data lanes
142  * reg_rx_csi_dly_cnt_termen_dlane0    0     0    35     4
143  * reg_rx_csi_dly_cnt_settle_dlane0   85    -2   145    -6
144  * reg_rx_csi_dly_cnt_termen_dlane1    0     0    35     4
145  * reg_rx_csi_dly_cnt_settle_dlane1   85    -2   145    -6
146  * reg_rx_csi_dly_cnt_termen_dlane2    0     0    35     4
147  * reg_rx_csi_dly_cnt_settle_dlane2   85    -2   145    -6
148  * reg_rx_csi_dly_cnt_termen_dlane3    0     0    35     4
149  * reg_rx_csi_dly_cnt_settle_dlane3   85    -2   145    -6
150  *
151  * We use the minimum values of both A and B.
152  */
153 
154 #define DIV_SHIFT	8
155 #define CSI2_ACCINV	8
156 
calc_timing(s32 a,s32 b,s64 link_freq,s32 accinv)157 static u32 calc_timing(s32 a, s32 b, s64 link_freq, s32 accinv)
158 {
159 	return accinv * a + (accinv * b * (500000000 >> DIV_SHIFT)
160 			     / (s32)(link_freq >> DIV_SHIFT));
161 }
162 
163 static int
ipu6_isys_csi2_calc_timing(struct ipu6_isys_csi2 * csi2,struct ipu6_isys_csi2_timing * timing,s32 accinv)164 ipu6_isys_csi2_calc_timing(struct ipu6_isys_csi2 *csi2,
165 			   struct ipu6_isys_csi2_timing *timing, s32 accinv)
166 {
167 	struct device *dev = &csi2->isys->adev->auxdev.dev;
168 	s64 link_freq;
169 
170 	link_freq = ipu6_isys_csi2_get_link_freq(csi2);
171 	if (link_freq < 0)
172 		return link_freq;
173 
174 	timing->ctermen = calc_timing(CSI2_CSI_RX_DLY_CNT_TERMEN_CLANE_A,
175 				      CSI2_CSI_RX_DLY_CNT_TERMEN_CLANE_B,
176 				      link_freq, accinv);
177 	timing->csettle = calc_timing(CSI2_CSI_RX_DLY_CNT_SETTLE_CLANE_A,
178 				      CSI2_CSI_RX_DLY_CNT_SETTLE_CLANE_B,
179 				      link_freq, accinv);
180 	timing->dtermen = calc_timing(CSI2_CSI_RX_DLY_CNT_TERMEN_DLANE_A,
181 				      CSI2_CSI_RX_DLY_CNT_TERMEN_DLANE_B,
182 				      link_freq, accinv);
183 	timing->dsettle = calc_timing(CSI2_CSI_RX_DLY_CNT_SETTLE_DLANE_A,
184 				      CSI2_CSI_RX_DLY_CNT_SETTLE_DLANE_B,
185 				      link_freq, accinv);
186 
187 	dev_dbg(dev, "ctermen %u csettle %u dtermen %u dsettle %u\n",
188 		timing->ctermen, timing->csettle,
189 		timing->dtermen, timing->dsettle);
190 
191 	return 0;
192 }
193 
ipu6_isys_register_errors(struct ipu6_isys_csi2 * csi2)194 void ipu6_isys_register_errors(struct ipu6_isys_csi2 *csi2)
195 {
196 	u32 irq = readl(csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
197 			CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET);
198 	struct ipu6_isys *isys = csi2->isys;
199 	u32 mask;
200 
201 	mask = isys->pdata->ipdata->csi2.irq_mask;
202 	writel(irq & mask, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
203 	       CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);
204 	csi2->receiver_errors |= irq & mask;
205 }
206 
ipu6_isys_csi2_error(struct ipu6_isys_csi2 * csi2)207 void ipu6_isys_csi2_error(struct ipu6_isys_csi2 *csi2)
208 {
209 	struct device *dev = &csi2->isys->adev->auxdev.dev;
210 	const struct ipu6_csi2_error *errors;
211 	u32 status;
212 	u32 i;
213 
214 	/* register errors once more in case of interrupts are disabled */
215 	ipu6_isys_register_errors(csi2);
216 	status = csi2->receiver_errors;
217 	csi2->receiver_errors = 0;
218 	errors = dphy_rx_errors;
219 
220 	for (i = 0; i < CSI_RX_NUM_ERRORS_IN_IRQ; i++) {
221 		if (status & BIT(i))
222 			dev_err_ratelimited(dev, "csi2-%i error: %s\n",
223 					    csi2->port, errors[i].error_string);
224 	}
225 }
226 
ipu6_isys_csi2_set_stream(struct v4l2_subdev * sd,const struct ipu6_isys_csi2_timing * timing,unsigned int nlanes,int enable)227 static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd,
228 				     const struct ipu6_isys_csi2_timing *timing,
229 				     unsigned int nlanes, int enable)
230 {
231 	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
232 	struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);
233 	struct ipu6_isys *isys = csi2->isys;
234 	struct device *dev = &isys->adev->auxdev.dev;
235 	struct ipu6_isys_csi2_config cfg;
236 	unsigned int nports;
237 	int ret = 0;
238 	u32 mask = 0;
239 	u32 i;
240 
241 	dev_dbg(dev, "stream %s CSI2-%u with %u lanes\n", enable ? "on" : "off",
242 		csi2->port, nlanes);
243 
244 	cfg.port = csi2->port;
245 	cfg.nlanes = nlanes;
246 
247 	mask = isys->pdata->ipdata->csi2.irq_mask;
248 	nports = isys->pdata->ipdata->csi2.nports;
249 
250 	if (!enable) {
251 		writel(0, csi2->base + CSI_REG_CSI_FE_ENABLE);
252 		writel(0, csi2->base + CSI_REG_PPI2CSI_ENABLE);
253 
254 		writel(0,
255 		       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
256 		       CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET);
257 		writel(mask,
258 		       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
259 		       CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);
260 		writel(0,
261 		       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
262 		       CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET);
263 		writel(0xffffffff,
264 		       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
265 		       CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);
266 
267 		isys->phy_set_power(isys, &cfg, timing, false);
268 
269 		writel(0, isys->pdata->base + CSI_REG_HUB_FW_ACCESS_PORT
270 		       (isys->pdata->ipdata->csi2.fw_access_port_ofs,
271 			csi2->port));
272 		writel(0, isys->pdata->base +
273 		       CSI_REG_HUB_DRV_ACCESS_PORT(csi2->port));
274 
275 		return ret;
276 	}
277 
278 	/* reset port reset */
279 	writel(0x1, csi2->base + CSI_REG_PORT_GPREG_SRST);
280 	usleep_range(100, 200);
281 	writel(0x0, csi2->base + CSI_REG_PORT_GPREG_SRST);
282 
283 	/* enable port clock */
284 	for (i = 0; i < nports; i++) {
285 		writel(1, isys->pdata->base + CSI_REG_HUB_DRV_ACCESS_PORT(i));
286 		writel(1, isys->pdata->base + CSI_REG_HUB_FW_ACCESS_PORT
287 		       (isys->pdata->ipdata->csi2.fw_access_port_ofs, i));
288 	}
289 
290 	/* enable all error related irq */
291 	writel(mask,
292 	       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
293 	       CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET);
294 	writel(mask,
295 	       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
296 	       CSI_PORT_REG_BASE_IRQ_MASK_OFFSET);
297 	writel(mask,
298 	       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
299 	       CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);
300 	writel(mask,
301 	       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
302 	       CSI_PORT_REG_BASE_IRQ_LEVEL_NOT_PULSE_OFFSET);
303 	writel(mask,
304 	       csi2->base + CSI_PORT_REG_BASE_IRQ_CSI +
305 	       CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET);
306 
307 	/*
308 	 * Using event from firmware instead of irq to handle CSI2 sync event
309 	 * which can reduce system wakeups. If CSI2 sync irq enabled, we need
310 	 * disable the firmware CSI2 sync event to avoid duplicate handling.
311 	 */
312 	writel(0xffffffff, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
313 	       CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET);
314 	writel(0, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
315 	       CSI_PORT_REG_BASE_IRQ_MASK_OFFSET);
316 	writel(0xffffffff, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
317 	       CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);
318 	writel(0, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
319 	       CSI_PORT_REG_BASE_IRQ_LEVEL_NOT_PULSE_OFFSET);
320 	writel(0xffffffff, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
321 	       CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET);
322 
323 	/* configure to enable FE and PPI2CSI */
324 	writel(0, csi2->base + CSI_REG_CSI_FE_MODE);
325 	writel(CSI_SENSOR_INPUT, csi2->base + CSI_REG_CSI_FE_MUX_CTRL);
326 	writel(CSI_CNTR_SENSOR_LINE_ID | CSI_CNTR_SENSOR_FRAME_ID,
327 	       csi2->base + CSI_REG_CSI_FE_SYNC_CNTR_SEL);
328 	writel(FIELD_PREP(PPI_INTF_CONFIG_NOF_ENABLED_DLANES_MASK, nlanes - 1),
329 	       csi2->base + CSI_REG_PPI2CSI_CONFIG_PPI_INTF);
330 
331 	writel(1, csi2->base + CSI_REG_PPI2CSI_ENABLE);
332 	writel(1, csi2->base + CSI_REG_CSI_FE_ENABLE);
333 
334 	ret = isys->phy_set_power(isys, &cfg, timing, true);
335 	if (ret)
336 		dev_err(dev, "csi-%d phy power up failed %d\n", csi2->port,
337 			ret);
338 
339 	return ret;
340 }
341 
ipu6_isys_csi2_enable_streams(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,u32 pad,u64 streams_mask)342 static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
343 					 struct v4l2_subdev_state *state,
344 					 u32 pad, u64 streams_mask)
345 {
346 	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
347 	struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);
348 	struct ipu6_isys_csi2_timing timing = { };
349 	struct v4l2_subdev *remote_sd;
350 	struct media_pad *remote_pad;
351 	u64 sink_streams;
352 	int ret;
353 
354 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
355 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
356 
357 	sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC,
358 						       CSI2_PAD_SINK,
359 						       &streams_mask);
360 
361 	ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);
362 	if (ret)
363 		return ret;
364 
365 	ret = ipu6_isys_csi2_set_stream(sd, &timing, csi2->nlanes, true);
366 	if (ret)
367 		return ret;
368 
369 	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index,
370 					 sink_streams);
371 	if (ret) {
372 		ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
373 		return ret;
374 	}
375 
376 	return 0;
377 }
378 
ipu6_isys_csi2_disable_streams(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,u32 pad,u64 streams_mask)379 static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
380 					  struct v4l2_subdev_state *state,
381 					  u32 pad, u64 streams_mask)
382 {
383 	struct v4l2_subdev *remote_sd;
384 	struct media_pad *remote_pad;
385 	u64 sink_streams;
386 
387 	sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC,
388 						       CSI2_PAD_SINK,
389 						       &streams_mask);
390 
391 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
392 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
393 
394 	ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
395 
396 	v4l2_subdev_disable_streams(remote_sd, remote_pad->index, sink_streams);
397 
398 	return 0;
399 }
400 
ipu6_isys_csi2_set_sel(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_selection * sel)401 static int ipu6_isys_csi2_set_sel(struct v4l2_subdev *sd,
402 				  struct v4l2_subdev_state *state,
403 				  struct v4l2_subdev_selection *sel)
404 {
405 	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
406 	struct device *dev = &asd->isys->adev->auxdev.dev;
407 	struct v4l2_mbus_framefmt *sink_ffmt;
408 	struct v4l2_mbus_framefmt *src_ffmt;
409 	struct v4l2_rect *crop;
410 
411 	if (sel->pad == CSI2_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP)
412 		return -EINVAL;
413 
414 	sink_ffmt = v4l2_subdev_state_get_opposite_stream_format(state,
415 								 sel->pad,
416 								 sel->stream);
417 	if (!sink_ffmt)
418 		return -EINVAL;
419 
420 	src_ffmt = v4l2_subdev_state_get_format(state, sel->pad, sel->stream);
421 	if (!src_ffmt)
422 		return -EINVAL;
423 
424 	crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream);
425 	if (!crop)
426 		return -EINVAL;
427 
428 	/* Only vertical cropping is supported */
429 	sel->r.left = 0;
430 	sel->r.width = sink_ffmt->width;
431 	/* Non-bayer formats can't be single line cropped */
432 	if (!ipu6_isys_is_bayer_format(sink_ffmt->code))
433 		sel->r.top &= ~1;
434 	sel->r.height = clamp(sel->r.height & ~1, IPU6_ISYS_MIN_HEIGHT,
435 			      sink_ffmt->height - sel->r.top);
436 	*crop = sel->r;
437 
438 	/* update source pad format */
439 	src_ffmt->width = sel->r.width;
440 	src_ffmt->height = sel->r.height;
441 	if (ipu6_isys_is_bayer_format(sink_ffmt->code))
442 		src_ffmt->code = ipu6_isys_convert_bayer_order(sink_ffmt->code,
443 							       sel->r.left,
444 							       sel->r.top);
445 	dev_dbg(dev, "set crop for %s sel: %d,%d,%d,%d code: 0x%x\n",
446 		sd->name, sel->r.left, sel->r.top, sel->r.width, sel->r.height,
447 		src_ffmt->code);
448 
449 	return 0;
450 }
451 
ipu6_isys_csi2_get_sel(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_selection * sel)452 static int ipu6_isys_csi2_get_sel(struct v4l2_subdev *sd,
453 				  struct v4l2_subdev_state *state,
454 				  struct v4l2_subdev_selection *sel)
455 {
456 	struct v4l2_mbus_framefmt *sink_ffmt;
457 	struct v4l2_rect *crop;
458 	int ret = 0;
459 
460 	if (sd->entity.pads[sel->pad].flags & MEDIA_PAD_FL_SINK)
461 		return -EINVAL;
462 
463 	sink_ffmt = v4l2_subdev_state_get_opposite_stream_format(state,
464 								 sel->pad,
465 								 sel->stream);
466 	if (!sink_ffmt)
467 		return -EINVAL;
468 
469 	crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream);
470 	if (!crop)
471 		return -EINVAL;
472 
473 	switch (sel->target) {
474 	case V4L2_SEL_TGT_CROP_DEFAULT:
475 	case V4L2_SEL_TGT_CROP_BOUNDS:
476 		sel->r.left = 0;
477 		sel->r.top = 0;
478 		sel->r.width = sink_ffmt->width;
479 		sel->r.height = sink_ffmt->height;
480 		break;
481 	case V4L2_SEL_TGT_CROP:
482 		sel->r = *crop;
483 		break;
484 	default:
485 		ret = -EINVAL;
486 	}
487 
488 	return ret;
489 }
490 
491 static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = {
492 	.get_fmt = v4l2_subdev_get_fmt,
493 	.set_fmt = ipu6_isys_subdev_set_fmt,
494 	.get_selection = ipu6_isys_csi2_get_sel,
495 	.set_selection = ipu6_isys_csi2_set_sel,
496 	.enum_mbus_code = ipu6_isys_subdev_enum_mbus_code,
497 	.set_routing = ipu6_isys_subdev_set_routing,
498 	.enable_streams = ipu6_isys_csi2_enable_streams,
499 	.disable_streams = ipu6_isys_csi2_disable_streams,
500 };
501 
502 static const struct v4l2_subdev_ops csi2_sd_ops = {
503 	.core = &csi2_sd_core_ops,
504 	.pad = &csi2_sd_pad_ops,
505 };
506 
507 static const struct media_entity_operations csi2_entity_ops = {
508 	.link_validate = v4l2_subdev_link_validate,
509 	.has_pad_interdep = v4l2_subdev_has_pad_interdep,
510 };
511 
ipu6_isys_csi2_cleanup(struct ipu6_isys_csi2 * csi2)512 void ipu6_isys_csi2_cleanup(struct ipu6_isys_csi2 *csi2)
513 {
514 	if (!csi2->isys)
515 		return;
516 
517 	v4l2_device_unregister_subdev(&csi2->asd.sd);
518 	v4l2_subdev_cleanup(&csi2->asd.sd);
519 	ipu6_isys_subdev_cleanup(&csi2->asd);
520 	csi2->isys = NULL;
521 }
522 
ipu6_isys_csi2_init(struct ipu6_isys_csi2 * csi2,struct ipu6_isys * isys,void __iomem * base,unsigned int index)523 int ipu6_isys_csi2_init(struct ipu6_isys_csi2 *csi2,
524 			struct ipu6_isys *isys,
525 			void __iomem *base, unsigned int index)
526 {
527 	struct device *dev = &isys->adev->auxdev.dev;
528 	int ret;
529 
530 	csi2->isys = isys;
531 	csi2->base = base;
532 	csi2->port = index;
533 
534 	csi2->asd.sd.entity.ops = &csi2_entity_ops;
535 	csi2->asd.isys = isys;
536 	ret = ipu6_isys_subdev_init(&csi2->asd, &csi2_sd_ops, 0,
537 				    NR_OF_CSI2_SINK_PADS, NR_OF_CSI2_SRC_PADS);
538 	if (ret)
539 		goto fail;
540 
541 	csi2->asd.source = IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT0 + index;
542 	csi2->asd.supported_codes = csi2_supported_codes;
543 	snprintf(csi2->asd.sd.name, sizeof(csi2->asd.sd.name),
544 		 IPU6_ISYS_ENTITY_PREFIX " CSI2 %u", index);
545 	v4l2_set_subdevdata(&csi2->asd.sd, &csi2->asd);
546 	ret = v4l2_subdev_init_finalize(&csi2->asd.sd);
547 	if (ret) {
548 		dev_err(dev, "failed to init v4l2 subdev\n");
549 		goto fail;
550 	}
551 
552 	ret = v4l2_device_register_subdev(&isys->v4l2_dev, &csi2->asd.sd);
553 	if (ret) {
554 		dev_err(dev, "failed to register v4l2 subdev\n");
555 		goto fail;
556 	}
557 
558 	return 0;
559 
560 fail:
561 	ipu6_isys_csi2_cleanup(csi2);
562 
563 	return ret;
564 }
565 
ipu6_isys_csi2_sof_event_by_stream(struct ipu6_isys_stream * stream)566 void ipu6_isys_csi2_sof_event_by_stream(struct ipu6_isys_stream *stream)
567 {
568 	struct video_device *vdev = stream->asd->sd.devnode;
569 	struct device *dev = &stream->isys->adev->auxdev.dev;
570 	struct ipu6_isys_csi2 *csi2 = ipu6_isys_subdev_to_csi2(stream->asd);
571 	struct v4l2_event ev = {
572 		.type = V4L2_EVENT_FRAME_SYNC,
573 	};
574 
575 	ev.u.frame_sync.frame_sequence = atomic_fetch_inc(&stream->sequence);
576 	v4l2_event_queue(vdev, &ev);
577 
578 	dev_dbg(dev, "sof_event::csi2-%i sequence: %i, vc: %d\n",
579 		csi2->port, ev.u.frame_sync.frame_sequence, stream->vc);
580 }
581 
ipu6_isys_csi2_eof_event_by_stream(struct ipu6_isys_stream * stream)582 void ipu6_isys_csi2_eof_event_by_stream(struct ipu6_isys_stream *stream)
583 {
584 	struct device *dev = &stream->isys->adev->auxdev.dev;
585 	struct ipu6_isys_csi2 *csi2 = ipu6_isys_subdev_to_csi2(stream->asd);
586 	u32 frame_sequence = atomic_read(&stream->sequence);
587 
588 	dev_dbg(dev, "eof_event::csi2-%i sequence: %i\n",
589 		csi2->port, frame_sequence);
590 }
591 
ipu6_isys_csi2_get_remote_desc(u32 source_stream,struct ipu6_isys_csi2 * csi2,struct media_entity * source_entity,struct v4l2_mbus_frame_desc_entry * entry)592 int ipu6_isys_csi2_get_remote_desc(u32 source_stream,
593 				   struct ipu6_isys_csi2 *csi2,
594 				   struct media_entity *source_entity,
595 				   struct v4l2_mbus_frame_desc_entry *entry)
596 {
597 	struct v4l2_mbus_frame_desc_entry *desc_entry = NULL;
598 	struct device *dev = &csi2->isys->adev->auxdev.dev;
599 	struct v4l2_mbus_frame_desc desc;
600 	struct v4l2_subdev *source;
601 	struct media_pad *pad;
602 	unsigned int i;
603 	int ret;
604 
605 	source = media_entity_to_v4l2_subdev(source_entity);
606 	if (!source)
607 		return -EPIPE;
608 
609 	pad = media_pad_remote_pad_first(&csi2->asd.pad[CSI2_PAD_SINK]);
610 	if (!pad)
611 		return -EPIPE;
612 
613 	ret = v4l2_subdev_call(source, pad, get_frame_desc, pad->index, &desc);
614 	if (ret)
615 		return ret;
616 
617 	if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
618 		dev_err(dev, "Unsupported frame descriptor type\n");
619 		return -EINVAL;
620 	}
621 
622 	for (i = 0; i < desc.num_entries; i++) {
623 		if (source_stream == desc.entry[i].stream) {
624 			desc_entry = &desc.entry[i];
625 			break;
626 		}
627 	}
628 
629 	if (!desc_entry) {
630 		dev_err(dev, "Failed to find stream %u from remote subdev\n",
631 			source_stream);
632 		return -EINVAL;
633 	}
634 
635 	if (desc_entry->bus.csi2.vc >= NR_OF_CSI2_VC) {
636 		dev_err(dev, "invalid vc %d\n", desc_entry->bus.csi2.vc);
637 		return -EINVAL;
638 	}
639 
640 	*entry = *desc_entry;
641 
642 	return 0;
643 }
644