Merge branch 'core-objtool-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / staging / media / imx / imx-media-csi.c
CommitLineData
ffe00b0a 1// SPDX-License-Identifier: GPL-2.0+
4a34ec8e
SL
2/*
3 * V4L2 Capture CSI Subdev for Freescale i.MX5/6 SOC
4 *
5 * Copyright (c) 2014-2017 Mentor Graphics Inc.
fb30ee79 6 * Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
4a34ec8e
SL
7 */
8#include <linux/delay.h>
fb30ee79 9#include <linux/gcd.h>
4a34ec8e
SL
10#include <linux/interrupt.h>
11#include <linux/module.h>
bf3cfaa7 12#include <linux/of_graph.h>
4a34ec8e
SL
13#include <linux/pinctrl/consumer.h>
14#include <linux/platform_device.h>
15#include <media/v4l2-ctrls.h>
16#include <media/v4l2-device.h>
17#include <media/v4l2-event.h>
18#include <media/v4l2-fwnode.h>
19#include <media/v4l2-mc.h>
20#include <media/v4l2-subdev.h>
21#include <media/videobuf2-dma-contig.h>
22#include <video/imx-ipu-v3.h>
23#include <media/imx.h>
24#include "imx-media.h"
25
26/*
27 * Min/Max supported width and heights.
28 *
29 * We allow planar output, so we have to align width by 16 pixels
30 * to meet IDMAC alignment requirements.
31 *
32 * TODO: move this into pad format negotiation, if capture device
33 * has not requested planar formats, we should allow 8 pixel
34 * alignment.
35 */
36#define MIN_W 176
37#define MIN_H 144
38#define MAX_W 4096
39#define MAX_H 4096
451a7b78 40#define W_ALIGN 1 /* multiple of 2 pixels */
4a34ec8e
SL
41#define H_ALIGN 1 /* multiple of 2 lines */
42#define S_ALIGN 1 /* multiple of 2 */
43
fb30ee79
PZ
44/*
45 * struct csi_skip_desc - CSI frame skipping descriptor
46 * @keep - number of frames kept per max_ratio frames
47 * @max_ratio - width of skip_smfc, written to MAX_RATIO bitfield
48 * @skip_smfc - skip pattern written to the SKIP_SMFC bitfield
49 */
50struct csi_skip_desc {
51 u8 keep;
52 u8 max_ratio;
53 u8 skip_smfc;
54};
55
4a34ec8e
SL
56struct csi_priv {
57 struct device *dev;
58 struct ipu_soc *ipu;
4a34ec8e
SL
59 struct v4l2_subdev sd;
60 struct media_pad pad[CSI_NUM_PADS];
61 /* the video device at IDMAC output pad */
62 struct imx_media_video_dev *vdev;
63 struct imx_media_fim *fim;
64 int csi_id;
65 int smfc_id;
66
67 /* lock to protect all members below */
68 struct mutex lock;
69
70 int active_output_pad;
71
72 struct ipuv3_channel *idmac_ch;
73 struct ipu_smfc *smfc;
74 struct ipu_csi *csi;
75
76 struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS];
77 const struct imx_media_pixfmt *cc[CSI_NUM_PADS];
fb30ee79 78 struct v4l2_fract frame_interval[CSI_NUM_PADS];
4a34ec8e 79 struct v4l2_rect crop;
69e78611 80 struct v4l2_rect compose;
fb30ee79 81 const struct csi_skip_desc *skip;
4a34ec8e
SL
82
83 /* active vb2 buffers to send to video dev sink */
84 struct imx_media_buffer *active_vb2_buf[2];
85 struct imx_media_dma_buf underrun_buf;
86
87 int ipu_buf_num; /* ipu double buffer index: 0-1 */
88
89 /* the sink for the captured frames */
90 struct media_entity *sink;
91 enum ipu_csi_dest dest;
92 /* the source subdev */
93 struct v4l2_subdev *src_sd;
94
95 /* the mipi virtual channel number at link validate */
96 int vc_num;
97
bf3cfaa7
SL
98 /* the upstream endpoint CSI is receiving from */
99 struct v4l2_fwnode_endpoint upstream_ep;
4a34ec8e
SL
100
101 spinlock_t irqlock; /* protect eof_irq handler */
102 struct timer_list eof_timeout_timer;
103 int eof_irq;
104 int nfb4eof_irq;
105
106 struct v4l2_ctrl_handler ctrl_hdlr;
107
108 int stream_count; /* streaming counter */
56e5faf2 109 u32 frame_sequence; /* frame sequence counter */
4a34ec8e
SL
110 bool last_eof; /* waiting for last EOF at stream off */
111 bool nfb4eof; /* NFB4EOF encountered during streaming */
3c6640a6 112 bool interweave_swap; /* swap top/bottom lines when interweaving */
4a34ec8e
SL
113 struct completion last_eof_comp;
114};
115
116static inline struct csi_priv *sd_to_dev(struct v4l2_subdev *sdev)
117{
118 return container_of(sdev, struct csi_priv, sd);
119}
120
779680e2
JL
121static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep)
122{
2d95e7ed 123 return ep->bus_type != V4L2_MBUS_CSI2_DPHY;
779680e2
JL
124}
125
bf3cfaa7
SL
126static inline bool is_parallel_16bit_bus(struct v4l2_fwnode_endpoint *ep)
127{
779680e2
JL
128 return is_parallel_bus(ep) && ep->bus.parallel.bus_width >= 16;
129}
130
131/*
132 * Check for conditions that require the IPU to handle the
133 * data internally as generic data, aka passthrough mode:
134 * - raw bayer media bus formats, or
135 * - the CSI is receiving from a 16-bit parallel bus, or
136 * - the CSI is receiving from an 8-bit parallel bus and the incoming
137 * media bus format is other than UYVY8_2X8/YUYV8_2X8.
138 */
139static inline bool requires_passthrough(struct v4l2_fwnode_endpoint *ep,
140 struct v4l2_mbus_framefmt *infmt,
141 const struct imx_media_pixfmt *incc)
142{
143 return incc->bayer || is_parallel_16bit_bus(ep) ||
144 (is_parallel_bus(ep) &&
145 infmt->code != MEDIA_BUS_FMT_UYVY8_2X8 &&
146 infmt->code != MEDIA_BUS_FMT_YUYV8_2X8);
bf3cfaa7
SL
147}
148
149/*
150 * Parses the fwnode endpoint from the source pad of the entity
151 * connected to this CSI. This will either be the entity directly
904371f9
SL
152 * upstream from the CSI-2 receiver, directly upstream from the
153 * video mux, or directly upstream from the CSI itself. The endpoint
154 * is needed to determine the bus type and bus config coming into
155 * the CSI.
bf3cfaa7
SL
156 */
157static int csi_get_upstream_endpoint(struct csi_priv *priv,
158 struct v4l2_fwnode_endpoint *ep)
159{
160 struct device_node *endpoint, *port;
bf3cfaa7
SL
161 struct media_entity *src;
162 struct v4l2_subdev *sd;
163 struct media_pad *pad;
164
8d1a4817
AB
165 if (!IS_ENABLED(CONFIG_OF))
166 return -ENXIO;
167
bf3cfaa7
SL
168 if (!priv->src_sd)
169 return -EPIPE;
170
904371f9
SL
171 sd = priv->src_sd;
172 src = &sd->entity;
bf3cfaa7
SL
173
174 if (src->function == MEDIA_ENT_F_VID_MUX) {
175 /*
176 * CSI is connected directly to video mux, skip up to
177 * CSI-2 receiver if it is in the path, otherwise stay
178 * with video mux.
179 */
3ef46bc9
SL
180 sd = imx_media_pipeline_subdev(src, IMX_MEDIA_GRP_ID_CSI2,
181 true);
9f6a0c59
SL
182 if (!IS_ERR(sd))
183 src = &sd->entity;
bf3cfaa7
SL
184 }
185
904371f9
SL
186 /*
187 * If the source is neither the video mux nor the CSI-2 receiver,
188 * get the source pad directly upstream from CSI itself.
189 */
190 if (src->function != MEDIA_ENT_F_VID_MUX &&
191 sd->grp_id != IMX_MEDIA_GRP_ID_CSI2)
192 src = &priv->sd.entity;
193
bf3cfaa7 194 /* get source pad of entity directly upstream from src */
3ef46bc9 195 pad = imx_media_pipeline_pad(src, 0, 0, true);
c89b4134
DC
196 if (!pad)
197 return -ENODEV;
bf3cfaa7
SL
198
199 sd = media_entity_to_v4l2_subdev(pad->entity);
200
201 /*
202 * NOTE: this assumes an OF-graph port id is the same as a
203 * media pad index.
204 */
205 port = of_graph_get_port_by_id(sd->dev->of_node, pad->index);
206 if (!port)
207 return -ENODEV;
208
209 endpoint = of_get_next_child(port, NULL);
210 of_node_put(port);
211 if (!endpoint)
212 return -ENODEV;
213
214 v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), ep);
215 of_node_put(endpoint);
216
217 return 0;
218}
219
4a34ec8e
SL
220static void csi_idmac_put_ipu_resources(struct csi_priv *priv)
221{
0b2e9e79 222 if (priv->idmac_ch)
4a34ec8e
SL
223 ipu_idmac_put(priv->idmac_ch);
224 priv->idmac_ch = NULL;
225
0b2e9e79 226 if (priv->smfc)
4a34ec8e
SL
227 ipu_smfc_put(priv->smfc);
228 priv->smfc = NULL;
229}
230
231static int csi_idmac_get_ipu_resources(struct csi_priv *priv)
232{
233 int ch_num, ret;
0b2e9e79
AB
234 struct ipu_smfc *smfc;
235 struct ipuv3_channel *idmac_ch;
4a34ec8e
SL
236
237 ch_num = IPUV3_CHANNEL_CSI0 + priv->smfc_id;
238
0b2e9e79
AB
239 smfc = ipu_smfc_get(priv->ipu, ch_num);
240 if (IS_ERR(smfc)) {
4a34ec8e 241 v4l2_err(&priv->sd, "failed to get SMFC\n");
0b2e9e79 242 ret = PTR_ERR(smfc);
4a34ec8e
SL
243 goto out;
244 }
0b2e9e79 245 priv->smfc = smfc;
4a34ec8e 246
0b2e9e79
AB
247 idmac_ch = ipu_idmac_get(priv->ipu, ch_num);
248 if (IS_ERR(idmac_ch)) {
4a34ec8e
SL
249 v4l2_err(&priv->sd, "could not get IDMAC channel %u\n",
250 ch_num);
0b2e9e79 251 ret = PTR_ERR(idmac_ch);
4a34ec8e
SL
252 goto out;
253 }
0b2e9e79 254 priv->idmac_ch = idmac_ch;
4a34ec8e
SL
255
256 return 0;
257out:
258 csi_idmac_put_ipu_resources(priv);
259 return ret;
260}
261
262static void csi_vb2_buf_done(struct csi_priv *priv)
263{
264 struct imx_media_video_dev *vdev = priv->vdev;
265 struct imx_media_buffer *done, *next;
266 struct vb2_buffer *vb;
267 dma_addr_t phys;
268
269 done = priv->active_vb2_buf[priv->ipu_buf_num];
270 if (done) {
a38d4b71 271 done->vbuf.field = vdev->fmt.fmt.pix.field;
56e5faf2 272 done->vbuf.sequence = priv->frame_sequence;
4a34ec8e
SL
273 vb = &done->vbuf.vb2_buf;
274 vb->timestamp = ktime_get_ns();
275 vb2_buffer_done(vb, priv->nfb4eof ?
276 VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
277 }
278
56e5faf2 279 priv->frame_sequence++;
4a34ec8e
SL
280 priv->nfb4eof = false;
281
282 /* get next queued buffer */
283 next = imx_media_capture_device_next_buf(vdev);
284 if (next) {
285 phys = vb2_dma_contig_plane_dma_addr(&next->vbuf.vb2_buf, 0);
286 priv->active_vb2_buf[priv->ipu_buf_num] = next;
287 } else {
288 phys = priv->underrun_buf.phys;
289 priv->active_vb2_buf[priv->ipu_buf_num] = NULL;
290 }
291
292 if (ipu_idmac_buffer_is_ready(priv->idmac_ch, priv->ipu_buf_num))
293 ipu_idmac_clear_buffer(priv->idmac_ch, priv->ipu_buf_num);
294
3c6640a6
SL
295 if (priv->interweave_swap)
296 phys += vdev->fmt.fmt.pix.bytesperline;
297
4a34ec8e
SL
298 ipu_cpmem_set_buffer(priv->idmac_ch, priv->ipu_buf_num, phys);
299}
300
301static irqreturn_t csi_idmac_eof_interrupt(int irq, void *dev_id)
302{
303 struct csi_priv *priv = dev_id;
304
305 spin_lock(&priv->irqlock);
306
307 if (priv->last_eof) {
308 complete(&priv->last_eof_comp);
309 priv->last_eof = false;
310 goto unlock;
311 }
312
1d88f4bc 313 if (priv->fim)
4a34ec8e 314 /* call frame interval monitor */
1d88f4bc 315 imx_media_fim_eof_monitor(priv->fim, ktime_get());
4a34ec8e
SL
316
317 csi_vb2_buf_done(priv);
318
319 /* select new IPU buf */
320 ipu_idmac_select_buffer(priv->idmac_ch, priv->ipu_buf_num);
321 /* toggle IPU double-buffer index */
322 priv->ipu_buf_num ^= 1;
323
324 /* bump the EOF timeout timer */
325 mod_timer(&priv->eof_timeout_timer,
326 jiffies + msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
327
328unlock:
329 spin_unlock(&priv->irqlock);
330 return IRQ_HANDLED;
331}
332
333static irqreturn_t csi_idmac_nfb4eof_interrupt(int irq, void *dev_id)
334{
335 struct csi_priv *priv = dev_id;
336
337 spin_lock(&priv->irqlock);
338
339 /*
340 * this is not an unrecoverable error, just mark
341 * the next captured frame with vb2 error flag.
342 */
343 priv->nfb4eof = true;
344
345 v4l2_err(&priv->sd, "NFB4EOF\n");
346
347 spin_unlock(&priv->irqlock);
348
349 return IRQ_HANDLED;
350}
351
352/*
353 * EOF timeout timer function. This is an unrecoverable condition
354 * without a stream restart.
355 */
e99e88a9 356static void csi_idmac_eof_timeout(struct timer_list *t)
4a34ec8e 357{
e99e88a9 358 struct csi_priv *priv = from_timer(priv, t, eof_timeout_timer);
4a34ec8e
SL
359 struct imx_media_video_dev *vdev = priv->vdev;
360
361 v4l2_err(&priv->sd, "EOF timeout\n");
362
363 /* signal a fatal error to capture device */
364 imx_media_capture_device_error(vdev);
365}
366
367static void csi_idmac_setup_vb2_buf(struct csi_priv *priv, dma_addr_t *phys)
368{
369 struct imx_media_video_dev *vdev = priv->vdev;
370 struct imx_media_buffer *buf;
371 int i;
372
373 for (i = 0; i < 2; i++) {
374 buf = imx_media_capture_device_next_buf(vdev);
375 if (buf) {
376 priv->active_vb2_buf[i] = buf;
377 phys[i] = vb2_dma_contig_plane_dma_addr(
378 &buf->vbuf.vb2_buf, 0);
379 } else {
380 priv->active_vb2_buf[i] = NULL;
381 phys[i] = priv->underrun_buf.phys;
382 }
383 }
384}
385
386static void csi_idmac_unsetup_vb2_buf(struct csi_priv *priv,
387 enum vb2_buffer_state return_status)
388{
389 struct imx_media_buffer *buf;
390 int i;
391
392 /* return any remaining active frames with return_status */
393 for (i = 0; i < 2; i++) {
394 buf = priv->active_vb2_buf[i];
395 if (buf) {
396 struct vb2_buffer *vb = &buf->vbuf.vb2_buf;
397
398 vb->timestamp = ktime_get_ns();
399 vb2_buffer_done(vb, return_status);
400 }
401 }
402}
403
404/* init the SMFC IDMAC channel */
405static int csi_idmac_setup_channel(struct csi_priv *priv)
406{
407 struct imx_media_video_dev *vdev = priv->vdev;
779680e2 408 const struct imx_media_pixfmt *incc;
4a34ec8e 409 struct v4l2_mbus_framefmt *infmt;
d969291d
SL
410 struct v4l2_mbus_framefmt *outfmt;
411 bool passthrough, interweave;
4a34ec8e 412 struct ipu_image image;
c8da8c03 413 u32 passthrough_bits;
779680e2 414 u32 passthrough_cycles;
4a34ec8e 415 dma_addr_t phys[2];
c8da8c03 416 u32 burst_size;
4a34ec8e
SL
417 int ret;
418
419 infmt = &priv->format_mbus[CSI_SINK_PAD];
779680e2 420 incc = priv->cc[CSI_SINK_PAD];
d969291d 421 outfmt = &priv->format_mbus[CSI_SRC_PAD_IDMAC];
4a34ec8e
SL
422
423 ipu_cpmem_zero(priv->idmac_ch);
424
425 memset(&image, 0, sizeof(image));
426 image.pix = vdev->fmt.fmt.pix;
439d8186 427 image.rect = vdev->compose;
4a34ec8e
SL
428
429 csi_idmac_setup_vb2_buf(priv, phys);
430
431 image.phys0 = phys[0];
432 image.phys1 = phys[1];
433
779680e2
JL
434 passthrough = requires_passthrough(&priv->upstream_ep, infmt, incc);
435 passthrough_cycles = 1;
436
d969291d
SL
437 /*
438 * If the field type at capture interface is interlaced, and
439 * the output IDMAC pad is sequential, enable interweave at
440 * the IDMAC output channel.
441 */
442 interweave = V4L2_FIELD_IS_INTERLACED(image.pix.field) &&
443 V4L2_FIELD_IS_SEQUENTIAL(outfmt->field);
3c6640a6
SL
444 priv->interweave_swap = interweave &&
445 image.pix.field == V4L2_FIELD_INTERLACED_BT;
d969291d 446
c8da8c03
RK
447 switch (image.pix.pixelformat) {
448 case V4L2_PIX_FMT_SBGGR8:
449 case V4L2_PIX_FMT_SGBRG8:
450 case V4L2_PIX_FMT_SGRBG8:
451 case V4L2_PIX_FMT_SRGGB8:
b1e064c2 452 case V4L2_PIX_FMT_GREY:
37ea9830 453 burst_size = 16;
c8da8c03
RK
454 passthrough_bits = 8;
455 break;
456 case V4L2_PIX_FMT_SBGGR16:
457 case V4L2_PIX_FMT_SGBRG16:
458 case V4L2_PIX_FMT_SGRBG16:
459 case V4L2_PIX_FMT_SRGGB16:
8f197302
LP
460 case V4L2_PIX_FMT_Y10:
461 case V4L2_PIX_FMT_Y12:
5b817555 462 burst_size = 8;
c8da8c03
RK
463 passthrough_bits = 16;
464 break;
6f303592 465 case V4L2_PIX_FMT_YUV420:
792f061b 466 case V4L2_PIX_FMT_YVU420:
6f303592
PZ
467 case V4L2_PIX_FMT_NV12:
468 burst_size = (image.pix.width & 0x3f) ?
469 ((image.pix.width & 0x1f) ?
470 ((image.pix.width & 0xf) ? 8 : 16) : 32) : 64;
6f303592 471 passthrough_bits = 16;
bc11dd66
SL
472 /*
473 * Skip writing U and V components to odd rows (but not
474 * when enabling IDMAC interweaving, they are incompatible).
475 */
476 if (!interweave)
477 ipu_cpmem_skip_odd_chroma_rows(priv->idmac_ch);
6f303592
PZ
478 break;
479 case V4L2_PIX_FMT_YUYV:
480 case V4L2_PIX_FMT_UYVY:
481 burst_size = (image.pix.width & 0x1f) ?
482 ((image.pix.width & 0xf) ? 8 : 16) : 32;
6f303592
PZ
483 passthrough_bits = 16;
484 break;
779680e2
JL
485 case V4L2_PIX_FMT_RGB565:
486 if (passthrough) {
487 burst_size = 16;
488 passthrough_bits = 8;
489 passthrough_cycles = incc->cycles;
490 break;
491 }
40e43111 492 /* fallthrough - non-passthrough RGB565 (CSI-2 bus) */
c8da8c03
RK
493 default:
494 burst_size = (image.pix.width & 0xf) ? 8 : 16;
c8da8c03
RK
495 passthrough_bits = 16;
496 break;
497 }
4a34ec8e 498
c8da8c03 499 if (passthrough) {
3c6640a6
SL
500 if (priv->interweave_swap) {
501 /* start interweave scan at 1st top line (2nd line) */
502 image.phys0 += image.pix.bytesperline;
503 image.phys1 += image.pix.bytesperline;
504 }
505
779680e2
JL
506 ipu_cpmem_set_resolution(priv->idmac_ch,
507 image.rect.width * passthrough_cycles,
c8da8c03
RK
508 image.rect.height);
509 ipu_cpmem_set_stride(priv->idmac_ch, image.pix.bytesperline);
510 ipu_cpmem_set_buffer(priv->idmac_ch, 0, image.phys0);
511 ipu_cpmem_set_buffer(priv->idmac_ch, 1, image.phys1);
512 ipu_cpmem_set_format_passthrough(priv->idmac_ch,
513 passthrough_bits);
514 } else {
3c6640a6
SL
515 if (priv->interweave_swap) {
516 /* start interweave scan at 1st top line (2nd line) */
517 image.rect.top = 1;
518 }
519
c8da8c03
RK
520 ret = ipu_cpmem_set_image(priv->idmac_ch, &image);
521 if (ret)
522 goto unsetup_vb2;
523 }
524
525 ipu_cpmem_set_burstsize(priv->idmac_ch, burst_size);
4a34ec8e
SL
526
527 /*
528 * Set the channel for the direct CSI-->memory via SMFC
529 * use-case to very high priority, by enabling the watermark
530 * signal in the SMFC, enabling WM in the channel, and setting
531 * the channel priority to high.
532 *
533 * Refer to the i.mx6 rev. D TRM Table 36-8: Calculated priority
534 * value.
535 *
536 * The WM's are set very low by intention here to ensure that
537 * the SMFC FIFOs do not overflow.
538 */
539 ipu_smfc_set_watermark(priv->smfc, 0x02, 0x01);
540 ipu_cpmem_set_high_priority(priv->idmac_ch);
541 ipu_idmac_enable_watermark(priv->idmac_ch, true);
542 ipu_cpmem_set_axi_id(priv->idmac_ch, 0);
543
544 burst_size = passthrough ?
545 (burst_size >> 3) - 1 : (burst_size >> 2) - 1;
546
547 ipu_smfc_set_burstsize(priv->smfc, burst_size);
548
d969291d 549 if (interweave)
4a34ec8e 550 ipu_cpmem_interlaced_scan(priv->idmac_ch,
3c6640a6
SL
551 priv->interweave_swap ?
552 -image.pix.bytesperline :
9b5c8d5f
SL
553 image.pix.bytesperline,
554 image.pix.pixelformat);
4a34ec8e
SL
555
556 ipu_idmac_set_double_buffer(priv->idmac_ch, true);
557
558 return 0;
559
560unsetup_vb2:
561 csi_idmac_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
562 return ret;
563}
564
565static void csi_idmac_unsetup(struct csi_priv *priv,
566 enum vb2_buffer_state state)
567{
568 ipu_idmac_disable_channel(priv->idmac_ch);
569 ipu_smfc_disable(priv->smfc);
570
571 csi_idmac_unsetup_vb2_buf(priv, state);
572}
573
574static int csi_idmac_setup(struct csi_priv *priv)
575{
576 int ret;
577
578 ret = csi_idmac_setup_channel(priv);
579 if (ret)
580 return ret;
581
582 ipu_cpmem_dump(priv->idmac_ch);
583 ipu_dump(priv->ipu);
584
585 ipu_smfc_enable(priv->smfc);
586
587 /* set buffers ready */
588 ipu_idmac_select_buffer(priv->idmac_ch, 0);
589 ipu_idmac_select_buffer(priv->idmac_ch, 1);
590
591 /* enable the channels */
592 ipu_idmac_enable_channel(priv->idmac_ch);
593
594 return 0;
595}
596
597static int csi_idmac_start(struct csi_priv *priv)
598{
599 struct imx_media_video_dev *vdev = priv->vdev;
600 struct v4l2_pix_format *outfmt;
601 int ret;
602
603 ret = csi_idmac_get_ipu_resources(priv);
604 if (ret)
605 return ret;
606
607 ipu_smfc_map_channel(priv->smfc, priv->csi_id, priv->vc_num);
608
609 outfmt = &vdev->fmt.fmt.pix;
610
34ff3874 611 ret = imx_media_alloc_dma_buf(priv->dev, &priv->underrun_buf,
4a34ec8e
SL
612 outfmt->sizeimage);
613 if (ret)
614 goto out_put_ipu;
615
616 priv->ipu_buf_num = 0;
617
618 /* init EOF completion waitq */
619 init_completion(&priv->last_eof_comp);
56e5faf2 620 priv->frame_sequence = 0;
4a34ec8e
SL
621 priv->last_eof = false;
622 priv->nfb4eof = false;
623
624 ret = csi_idmac_setup(priv);
625 if (ret) {
626 v4l2_err(&priv->sd, "csi_idmac_setup failed: %d\n", ret);
627 goto out_free_dma_buf;
628 }
629
630 priv->nfb4eof_irq = ipu_idmac_channel_irq(priv->ipu,
1d96e53f
AG
631 priv->idmac_ch,
632 IPU_IRQ_NFB4EOF);
4a34ec8e
SL
633 ret = devm_request_irq(priv->dev, priv->nfb4eof_irq,
634 csi_idmac_nfb4eof_interrupt, 0,
635 "imx-smfc-nfb4eof", priv);
636 if (ret) {
637 v4l2_err(&priv->sd,
638 "Error registering NFB4EOF irq: %d\n", ret);
639 goto out_unsetup;
640 }
641
642 priv->eof_irq = ipu_idmac_channel_irq(priv->ipu, priv->idmac_ch,
643 IPU_IRQ_EOF);
644
645 ret = devm_request_irq(priv->dev, priv->eof_irq,
646 csi_idmac_eof_interrupt, 0,
647 "imx-smfc-eof", priv);
648 if (ret) {
649 v4l2_err(&priv->sd,
650 "Error registering eof irq: %d\n", ret);
651 goto out_free_nfb4eof_irq;
652 }
653
654 /* start the EOF timeout timer */
655 mod_timer(&priv->eof_timeout_timer,
656 jiffies + msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
657
658 return 0;
659
660out_free_nfb4eof_irq:
661 devm_free_irq(priv->dev, priv->nfb4eof_irq, priv);
662out_unsetup:
663 csi_idmac_unsetup(priv, VB2_BUF_STATE_QUEUED);
664out_free_dma_buf:
34ff3874 665 imx_media_free_dma_buf(priv->dev, &priv->underrun_buf);
4a34ec8e
SL
666out_put_ipu:
667 csi_idmac_put_ipu_resources(priv);
668 return ret;
669}
670
2e0fe66e 671static void csi_idmac_wait_last_eof(struct csi_priv *priv)
4a34ec8e
SL
672{
673 unsigned long flags;
674 int ret;
675
676 /* mark next EOF interrupt as the last before stream off */
677 spin_lock_irqsave(&priv->irqlock, flags);
678 priv->last_eof = true;
679 spin_unlock_irqrestore(&priv->irqlock, flags);
680
681 /*
682 * and then wait for interrupt handler to mark completion.
683 */
684 ret = wait_for_completion_timeout(
685 &priv->last_eof_comp, msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
686 if (ret == 0)
687 v4l2_warn(&priv->sd, "wait last EOF timeout\n");
2e0fe66e 688}
4a34ec8e 689
2e0fe66e
SL
690static void csi_idmac_stop(struct csi_priv *priv)
691{
4a34ec8e
SL
692 devm_free_irq(priv->dev, priv->eof_irq, priv);
693 devm_free_irq(priv->dev, priv->nfb4eof_irq, priv);
694
695 csi_idmac_unsetup(priv, VB2_BUF_STATE_ERROR);
696
34ff3874 697 imx_media_free_dma_buf(priv->dev, &priv->underrun_buf);
4a34ec8e
SL
698
699 /* cancel the EOF timeout timer */
700 del_timer_sync(&priv->eof_timeout_timer);
701
702 csi_idmac_put_ipu_resources(priv);
703}
704
705/* Update the CSI whole sensor and active windows */
706static int csi_setup(struct csi_priv *priv)
707{
708 struct v4l2_mbus_framefmt *infmt, *outfmt;
779680e2 709 const struct imx_media_pixfmt *incc;
bf3cfaa7 710 struct v4l2_mbus_config mbus_cfg;
4a34ec8e 711 struct v4l2_mbus_framefmt if_fmt;
779680e2 712 struct v4l2_rect crop;
4a34ec8e
SL
713
714 infmt = &priv->format_mbus[CSI_SINK_PAD];
779680e2 715 incc = priv->cc[CSI_SINK_PAD];
4a34ec8e 716 outfmt = &priv->format_mbus[priv->active_output_pad];
4a34ec8e 717
bf3cfaa7
SL
718 /* compose mbus_config from the upstream endpoint */
719 mbus_cfg.type = priv->upstream_ep.bus_type;
779680e2
JL
720 mbus_cfg.flags = is_parallel_bus(&priv->upstream_ep) ?
721 priv->upstream_ep.bus.parallel.flags :
722 priv->upstream_ep.bus.mipi_csi2.flags;
4a34ec8e 723
4a34ec8e 724 if_fmt = *infmt;
779680e2 725 crop = priv->crop;
4a34ec8e 726
779680e2
JL
727 /*
728 * if cycles is set, we need to handle this over multiple cycles as
729 * generic/bayer data
730 */
731 if (is_parallel_bus(&priv->upstream_ep) && incc->cycles) {
732 if_fmt.width *= incc->cycles;
733 crop.width *= incc->cycles;
734 }
735
736 ipu_csi_set_window(priv->csi, &crop);
4a34ec8e
SL
737
738 ipu_csi_set_downsize(priv->csi,
69e78611
PZ
739 priv->crop.width == 2 * priv->compose.width,
740 priv->crop.height == 2 * priv->compose.height);
4a34ec8e 741
fc8c7238 742 ipu_csi_init_interface(priv->csi, &mbus_cfg, &if_fmt, outfmt);
4a34ec8e
SL
743
744 ipu_csi_set_dest(priv->csi, priv->dest);
745
fb30ee79
PZ
746 if (priv->dest == IPU_CSI_DEST_IDMAC)
747 ipu_csi_set_skip_smfc(priv->csi, priv->skip->skip_smfc,
748 priv->skip->max_ratio - 1, 0);
749
4a34ec8e
SL
750 ipu_csi_dump(priv->csi);
751
752 return 0;
753}
754
755static int csi_start(struct csi_priv *priv)
756{
52e17089 757 struct v4l2_fract *output_fi;
4a34ec8e
SL
758 int ret;
759
fb30ee79 760 output_fi = &priv->frame_interval[priv->active_output_pad];
fb30ee79 761
4bc1ab41
SL
762 /* start upstream */
763 ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 1);
764 ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
765 if (ret)
766 return ret;
767
4a34ec8e
SL
768 if (priv->dest == IPU_CSI_DEST_IDMAC) {
769 ret = csi_idmac_start(priv);
770 if (ret)
4bc1ab41 771 goto stop_upstream;
4a34ec8e
SL
772 }
773
774 ret = csi_setup(priv);
775 if (ret)
776 goto idmac_stop;
777
778 /* start the frame interval monitor */
779 if (priv->fim && priv->dest == IPU_CSI_DEST_IDMAC) {
fb30ee79 780 ret = imx_media_fim_set_stream(priv->fim, output_fi, true);
4a34ec8e
SL
781 if (ret)
782 goto idmac_stop;
783 }
784
785 ret = ipu_csi_enable(priv->csi);
786 if (ret) {
787 v4l2_err(&priv->sd, "CSI enable error: %d\n", ret);
788 goto fim_off;
789 }
790
791 return 0;
792
793fim_off:
794 if (priv->fim && priv->dest == IPU_CSI_DEST_IDMAC)
fb30ee79 795 imx_media_fim_set_stream(priv->fim, NULL, false);
4a34ec8e
SL
796idmac_stop:
797 if (priv->dest == IPU_CSI_DEST_IDMAC)
798 csi_idmac_stop(priv);
4bc1ab41
SL
799stop_upstream:
800 v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
4a34ec8e
SL
801 return ret;
802}
803
804static void csi_stop(struct csi_priv *priv)
805{
2e0fe66e
SL
806 if (priv->dest == IPU_CSI_DEST_IDMAC)
807 csi_idmac_wait_last_eof(priv);
808
809 /*
810 * Disable the CSI asap, after syncing with the last EOF.
811 * Doing so after the IDMA channel is disabled has shown to
812 * create hard system-wide hangs.
813 */
814 ipu_csi_disable(priv->csi);
815
4bc1ab41
SL
816 /* stop upstream */
817 v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
818
4a34ec8e
SL
819 if (priv->dest == IPU_CSI_DEST_IDMAC) {
820 csi_idmac_stop(priv);
821
822 /* stop the frame interval monitor */
823 if (priv->fim)
fb30ee79 824 imx_media_fim_set_stream(priv->fim, NULL, false);
4a34ec8e 825 }
4a34ec8e
SL
826}
827
fb30ee79
PZ
828static const struct csi_skip_desc csi_skip[12] = {
829 { 1, 1, 0x00 }, /* Keep all frames */
830 { 5, 6, 0x10 }, /* Skip every sixth frame */
831 { 4, 5, 0x08 }, /* Skip every fifth frame */
832 { 3, 4, 0x04 }, /* Skip every fourth frame */
833 { 2, 3, 0x02 }, /* Skip every third frame */
834 { 3, 5, 0x0a }, /* Skip frames 1 and 3 of every 5 */
835 { 1, 2, 0x01 }, /* Skip every second frame */
836 { 2, 5, 0x0b }, /* Keep frames 1 and 4 of every 5 */
837 { 1, 3, 0x03 }, /* Keep one in three frames */
838 { 1, 4, 0x07 }, /* Keep one in four frames */
839 { 1, 5, 0x0f }, /* Keep one in five frames */
840 { 1, 6, 0x1f }, /* Keep one in six frames */
841};
842
843static void csi_apply_skip_interval(const struct csi_skip_desc *skip,
844 struct v4l2_fract *interval)
845{
846 unsigned int div;
847
848 interval->numerator *= skip->max_ratio;
849 interval->denominator *= skip->keep;
850
851 /* Reduce fraction to lowest terms */
852 div = gcd(interval->numerator, interval->denominator);
853 if (div > 1) {
854 interval->numerator /= div;
855 interval->denominator /= div;
856 }
857}
858
859/*
860 * Find the skip pattern to produce the output frame interval closest to the
861 * requested one, for the given input frame interval. Updates the output frame
862 * interval to the exact value.
863 */
864static const struct csi_skip_desc *csi_find_best_skip(struct v4l2_fract *in,
865 struct v4l2_fract *out)
866{
867 const struct csi_skip_desc *skip = &csi_skip[0], *best_skip = skip;
868 u32 min_err = UINT_MAX;
869 u64 want_us;
870 int i;
871
872 /* Default to 1:1 ratio */
873 if (out->numerator == 0 || out->denominator == 0 ||
874 in->numerator == 0 || in->denominator == 0) {
875 *out = *in;
876 return best_skip;
877 }
878
879 want_us = div_u64((u64)USEC_PER_SEC * out->numerator, out->denominator);
880
881 /* Find the reduction closest to the requested time per frame */
882 for (i = 0; i < ARRAY_SIZE(csi_skip); i++, skip++) {
883 u64 tmp, err;
884
885 tmp = div_u64((u64)USEC_PER_SEC * in->numerator *
886 skip->max_ratio, in->denominator * skip->keep);
887
888 err = abs((s64)tmp - want_us);
889 if (err < min_err) {
890 min_err = err;
891 best_skip = skip;
892 }
893 }
894
895 *out = *in;
896 csi_apply_skip_interval(best_skip, out);
897
898 return best_skip;
899}
900
4a34ec8e
SL
901/*
902 * V4L2 subdev operations.
903 */
904
905static int csi_g_frame_interval(struct v4l2_subdev *sd,
906 struct v4l2_subdev_frame_interval *fi)
907{
908 struct csi_priv *priv = v4l2_get_subdevdata(sd);
909
fb30ee79
PZ
910 if (fi->pad >= CSI_NUM_PADS)
911 return -EINVAL;
912
4a34ec8e 913 mutex_lock(&priv->lock);
fb30ee79
PZ
914
915 fi->interval = priv->frame_interval[fi->pad];
916
4a34ec8e
SL
917 mutex_unlock(&priv->lock);
918
919 return 0;
920}
921
922static int csi_s_frame_interval(struct v4l2_subdev *sd,
923 struct v4l2_subdev_frame_interval *fi)
924{
925 struct csi_priv *priv = v4l2_get_subdevdata(sd);
fb30ee79
PZ
926 struct v4l2_fract *input_fi;
927 int ret = 0;
4a34ec8e
SL
928
929 mutex_lock(&priv->lock);
930
fb30ee79 931 input_fi = &priv->frame_interval[CSI_SINK_PAD];
4a34ec8e 932
fb30ee79
PZ
933 switch (fi->pad) {
934 case CSI_SINK_PAD:
9bcb830b
SL
935 /* No limits on valid input frame intervals */
936 if (fi->interval.numerator == 0 ||
937 fi->interval.denominator == 0)
938 fi->interval = *input_fi;
fb30ee79
PZ
939 /* Reset output intervals and frame skipping ratio to 1:1 */
940 priv->frame_interval[CSI_SRC_PAD_IDMAC] = fi->interval;
941 priv->frame_interval[CSI_SRC_PAD_DIRECT] = fi->interval;
942 priv->skip = &csi_skip[0];
943 break;
944 case CSI_SRC_PAD_IDMAC:
945 /*
946 * frame interval at IDMAC output pad depends on input
947 * interval, modified by frame skipping.
948 */
949 priv->skip = csi_find_best_skip(input_fi, &fi->interval);
950 break;
951 case CSI_SRC_PAD_DIRECT:
952 /*
953 * frame interval at DIRECT output pad is same as input
954 * interval.
955 */
956 fi->interval = *input_fi;
957 break;
958 default:
959 ret = -EINVAL;
960 goto out;
961 }
4a34ec8e 962
fb30ee79
PZ
963 priv->frame_interval[fi->pad] = fi->interval;
964out:
4a34ec8e 965 mutex_unlock(&priv->lock);
fb30ee79 966 return ret;
4a34ec8e
SL
967}
968
969static int csi_s_stream(struct v4l2_subdev *sd, int enable)
970{
971 struct csi_priv *priv = v4l2_get_subdevdata(sd);
972 int ret = 0;
973
974 mutex_lock(&priv->lock);
975
976 if (!priv->src_sd || !priv->sink) {
977 ret = -EPIPE;
978 goto out;
979 }
980
981 /*
982 * enable/disable streaming only if stream_count is
983 * going from 0 to 1 / 1 to 0.
984 */
985 if (priv->stream_count != !enable)
986 goto update_count;
987
988 if (enable) {
4a34ec8e
SL
989 dev_dbg(priv->dev, "stream ON\n");
990 ret = csi_start(priv);
4bc1ab41 991 if (ret)
4a34ec8e 992 goto out;
4a34ec8e
SL
993 } else {
994 dev_dbg(priv->dev, "stream OFF\n");
4a34ec8e 995 csi_stop(priv);
4a34ec8e
SL
996 }
997
998update_count:
999 priv->stream_count += enable ? 1 : -1;
de2e0456
MV
1000 if (priv->stream_count < 0)
1001 priv->stream_count = 0;
4a34ec8e
SL
1002out:
1003 mutex_unlock(&priv->lock);
1004 return ret;
1005}
1006
1007static int csi_link_setup(struct media_entity *entity,
1008 const struct media_pad *local,
1009 const struct media_pad *remote, u32 flags)
1010{
1011 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1012 struct csi_priv *priv = v4l2_get_subdevdata(sd);
1013 struct v4l2_subdev *remote_sd;
1014 int ret = 0;
1015
1016 dev_dbg(priv->dev, "link setup %s -> %s\n", remote->entity->name,
1017 local->entity->name);
1018
1019 mutex_lock(&priv->lock);
1020
1021 if (local->flags & MEDIA_PAD_FL_SINK) {
1022 if (!is_media_entity_v4l2_subdev(remote->entity)) {
1023 ret = -EINVAL;
1024 goto out;
1025 }
1026
1027 remote_sd = media_entity_to_v4l2_subdev(remote->entity);
1028
1029 if (flags & MEDIA_LNK_FL_ENABLED) {
1030 if (priv->src_sd) {
1031 ret = -EBUSY;
1032 goto out;
1033 }
1034 priv->src_sd = remote_sd;
1035 } else {
1036 priv->src_sd = NULL;
1037 }
1038
1039 goto out;
1040 }
1041
1042 /* this is a source pad */
1043
1044 if (flags & MEDIA_LNK_FL_ENABLED) {
1045 if (priv->sink) {
1046 ret = -EBUSY;
1047 goto out;
1048 }
1049 } else {
1050 v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
1051 v4l2_ctrl_handler_init(&priv->ctrl_hdlr, 0);
1052 priv->sink = NULL;
451a7b78
PZ
1053 /* do not apply IC burst alignment in csi_try_crop */
1054 priv->active_output_pad = CSI_SRC_PAD_IDMAC;
4a34ec8e
SL
1055 goto out;
1056 }
1057
1058 /* record which output pad is now active */
1059 priv->active_output_pad = local->index;
1060
1061 /* set CSI destination */
1062 if (local->index == CSI_SRC_PAD_IDMAC) {
1063 if (!is_media_entity_v4l2_video_device(remote->entity)) {
1064 ret = -EINVAL;
1065 goto out;
1066 }
1067
1068 if (priv->fim) {
1069 ret = imx_media_fim_add_controls(priv->fim);
1070 if (ret)
1071 goto out;
1072 }
1073
1074 priv->dest = IPU_CSI_DEST_IDMAC;
1075 } else {
1076 if (!is_media_entity_v4l2_subdev(remote->entity)) {
1077 ret = -EINVAL;
1078 goto out;
1079 }
1080
1081 remote_sd = media_entity_to_v4l2_subdev(remote->entity);
1082 switch (remote_sd->grp_id) {
67673ed5 1083 case IMX_MEDIA_GRP_ID_IPU_VDIC:
4a34ec8e
SL
1084 priv->dest = IPU_CSI_DEST_VDIC;
1085 break;
67673ed5 1086 case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
4a34ec8e
SL
1087 priv->dest = IPU_CSI_DEST_IC;
1088 break;
1089 default:
1090 ret = -EINVAL;
1091 goto out;
1092 }
1093 }
1094
1095 priv->sink = remote->entity;
1096out:
1097 mutex_unlock(&priv->lock);
1098 return ret;
1099}
1100
1101static int csi_link_validate(struct v4l2_subdev *sd,
1102 struct media_link *link,
1103 struct v4l2_subdev_format *source_fmt,
1104 struct v4l2_subdev_format *sink_fmt)
1105{
1106 struct csi_priv *priv = v4l2_get_subdevdata(sd);
60359a28 1107 struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
4a34ec8e
SL
1108 bool is_csi2;
1109 int ret;
1110
1111 ret = v4l2_subdev_link_validate_default(sd, link,
1112 source_fmt, sink_fmt);
1113 if (ret)
1114 return ret;
1115
bf3cfaa7
SL
1116 ret = csi_get_upstream_endpoint(priv, &upstream_ep);
1117 if (ret) {
1118 v4l2_err(&priv->sd, "failed to find upstream endpoint\n");
1119 return ret;
4a34ec8e
SL
1120 }
1121
1122 mutex_lock(&priv->lock);
1123
bf3cfaa7 1124 priv->upstream_ep = upstream_ep;
779680e2 1125 is_csi2 = !is_parallel_bus(&upstream_ep);
4a34ec8e
SL
1126 if (is_csi2) {
1127 int vc_num = 0;
1128 /*
1129 * NOTE! It seems the virtual channels from the mipi csi-2
1130 * receiver are used only for routing by the video mux's,
1131 * or for hard-wired routing to the CSI's. Once the stream
1132 * enters the CSI's however, they are treated internally
1133 * in the IPU as virtual channel 0.
1134 */
1135#if 0
1136 mutex_unlock(&priv->lock);
3ef46bc9 1137 vc_num = imx_media_find_mipi_csi2_channel(&priv->sd.entity);
4a34ec8e
SL
1138 if (vc_num < 0)
1139 return vc_num;
1140 mutex_lock(&priv->lock);
1141#endif
1142 ipu_csi_set_mipi_datatype(priv->csi, vc_num,
1143 &priv->format_mbus[CSI_SINK_PAD]);
1144 }
1145
1146 /* select either parallel or MIPI-CSI2 as input to CSI */
1147 ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2);
779680e2 1148
4a34ec8e
SL
1149 mutex_unlock(&priv->lock);
1150 return ret;
1151}
1152
1153static struct v4l2_mbus_framefmt *
1154__csi_get_fmt(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
1155 unsigned int pad, enum v4l2_subdev_format_whence which)
1156{
1157 if (which == V4L2_SUBDEV_FORMAT_TRY)
1158 return v4l2_subdev_get_try_format(&priv->sd, cfg, pad);
1159 else
1160 return &priv->format_mbus[pad];
1161}
1162
1163static struct v4l2_rect *
1164__csi_get_crop(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
1165 enum v4l2_subdev_format_whence which)
1166{
1167 if (which == V4L2_SUBDEV_FORMAT_TRY)
1168 return v4l2_subdev_get_try_crop(&priv->sd, cfg, CSI_SINK_PAD);
1169 else
1170 return &priv->crop;
1171}
1172
69e78611
PZ
1173static struct v4l2_rect *
1174__csi_get_compose(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
1175 enum v4l2_subdev_format_whence which)
1176{
1177 if (which == V4L2_SUBDEV_FORMAT_TRY)
1178 return v4l2_subdev_get_try_compose(&priv->sd, cfg,
1179 CSI_SINK_PAD);
1180 else
1181 return &priv->compose;
1182}
1183
4a34ec8e
SL
1184static void csi_try_crop(struct csi_priv *priv,
1185 struct v4l2_rect *crop,
1186 struct v4l2_subdev_pad_config *cfg,
1187 struct v4l2_mbus_framefmt *infmt,
bf3cfaa7 1188 struct v4l2_fwnode_endpoint *upstream_ep)
4a34ec8e 1189{
2a87c0c9
SL
1190 u32 in_height;
1191
4a34ec8e
SL
1192 crop->width = min_t(__u32, infmt->width, crop->width);
1193 if (crop->left + crop->width > infmt->width)
1194 crop->left = infmt->width - crop->width;
1195 /* adjust crop left/width to h/w alignment restrictions */
1196 crop->left &= ~0x3;
451a7b78
PZ
1197 if (priv->active_output_pad == CSI_SRC_PAD_DIRECT)
1198 crop->width &= ~0x7; /* multiple of 8 pixels (IC burst) */
1199 else
1200 crop->width &= ~0x1; /* multiple of 2 pixels */
4a34ec8e 1201
2a87c0c9
SL
1202 in_height = infmt->height;
1203 if (infmt->field == V4L2_FIELD_ALTERNATE)
1204 in_height *= 2;
1205
4a34ec8e
SL
1206 /*
1207 * FIXME: not sure why yet, but on interlaced bt.656,
1208 * changing the vertical cropping causes loss of vertical
1209 * sync, so fix it to NTSC/PAL active lines. NTSC contains
1210 * 2 extra lines of active video that need to be cropped.
1211 */
bf3cfaa7 1212 if (upstream_ep->bus_type == V4L2_MBUS_BT656 &&
4a34ec8e
SL
1213 (V4L2_FIELD_HAS_BOTH(infmt->field) ||
1214 infmt->field == V4L2_FIELD_ALTERNATE)) {
2a87c0c9
SL
1215 crop->height = in_height;
1216 crop->top = (in_height == 480) ? 2 : 0;
4a34ec8e 1217 } else {
2a87c0c9
SL
1218 crop->height = min_t(__u32, in_height, crop->height);
1219 if (crop->top + crop->height > in_height)
1220 crop->top = in_height - crop->height;
4a34ec8e
SL
1221 }
1222}
1223
1224static int csi_enum_mbus_code(struct v4l2_subdev *sd,
1225 struct v4l2_subdev_pad_config *cfg,
1226 struct v4l2_subdev_mbus_code_enum *code)
1227{
1228 struct csi_priv *priv = v4l2_get_subdevdata(sd);
60359a28 1229 struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
4a34ec8e
SL
1230 const struct imx_media_pixfmt *incc;
1231 struct v4l2_mbus_framefmt *infmt;
1232 int ret = 0;
1233
1234 mutex_lock(&priv->lock);
1235
1236 infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, code->which);
1237 incc = imx_media_find_mbus_format(infmt->code, CS_SEL_ANY, true);
1238
1239 switch (code->pad) {
1240 case CSI_SINK_PAD:
1241 ret = imx_media_enum_mbus_format(&code->code, code->index,
1242 CS_SEL_ANY, true);
1243 break;
1244 case CSI_SRC_PAD_DIRECT:
1245 case CSI_SRC_PAD_IDMAC:
779680e2
JL
1246 ret = csi_get_upstream_endpoint(priv, &upstream_ep);
1247 if (ret) {
1248 v4l2_err(&priv->sd, "failed to find upstream endpoint\n");
1249 goto out;
1250 }
1251
1252 if (requires_passthrough(&upstream_ep, infmt, incc)) {
4a34ec8e
SL
1253 if (code->index != 0) {
1254 ret = -EINVAL;
1255 goto out;
1256 }
1257 code->code = infmt->code;
1258 } else {
1259 u32 cs_sel = (incc->cs == IPUV3_COLORSPACE_YUV) ?
1260 CS_SEL_YUV : CS_SEL_RGB;
1261 ret = imx_media_enum_ipu_format(&code->code,
1262 code->index,
1263 cs_sel);
1264 }
1265 break;
1266 default:
1267 ret = -EINVAL;
1268 }
1269
1270out:
1271 mutex_unlock(&priv->lock);
1272 return ret;
1273}
1274
949ffdbf
RK
1275static int csi_enum_frame_size(struct v4l2_subdev *sd,
1276 struct v4l2_subdev_pad_config *cfg,
1277 struct v4l2_subdev_frame_size_enum *fse)
1278{
1279 struct csi_priv *priv = v4l2_get_subdevdata(sd);
1280 struct v4l2_rect *crop;
1281 int ret = 0;
1282
1283 if (fse->pad >= CSI_NUM_PADS ||
1284 fse->index > (fse->pad == CSI_SINK_PAD ? 0 : 3))
1285 return -EINVAL;
1286
1287 mutex_lock(&priv->lock);
1288
1289 if (fse->pad == CSI_SINK_PAD) {
1290 fse->min_width = MIN_W;
1291 fse->max_width = MAX_W;
1292 fse->min_height = MIN_H;
1293 fse->max_height = MAX_H;
1294 } else {
1295 crop = __csi_get_crop(priv, cfg, fse->which);
1296
5a0996af 1297 fse->min_width = fse->index & 1 ?
949ffdbf 1298 crop->width / 2 : crop->width;
5a0996af
JSB
1299 fse->max_width = fse->min_width;
1300 fse->min_height = fse->index & 2 ?
949ffdbf 1301 crop->height / 2 : crop->height;
5a0996af 1302 fse->max_height = fse->min_height;
949ffdbf
RK
1303 }
1304
1305 mutex_unlock(&priv->lock);
1306 return ret;
1307}
1308
1309static int csi_enum_frame_interval(struct v4l2_subdev *sd,
1310 struct v4l2_subdev_pad_config *cfg,
1311 struct v4l2_subdev_frame_interval_enum *fie)
1312{
1313 struct csi_priv *priv = v4l2_get_subdevdata(sd);
1314 struct v4l2_fract *input_fi;
1315 struct v4l2_rect *crop;
1316 int ret = 0;
1317
1318 if (fie->pad >= CSI_NUM_PADS ||
1319 fie->index >= (fie->pad != CSI_SRC_PAD_IDMAC ?
1320 1 : ARRAY_SIZE(csi_skip)))
1321 return -EINVAL;
1322
1323 mutex_lock(&priv->lock);
1324
1325 input_fi = &priv->frame_interval[CSI_SINK_PAD];
1326 crop = __csi_get_crop(priv, cfg, fie->which);
1327
1328 if ((fie->width != crop->width && fie->width != crop->width / 2) ||
1329 (fie->height != crop->height && fie->height != crop->height / 2)) {
1330 ret = -EINVAL;
1331 goto out;
1332 }
1333
1334 fie->interval = *input_fi;
1335
1336 if (fie->pad == CSI_SRC_PAD_IDMAC)
1337 csi_apply_skip_interval(&csi_skip[fie->index],
1338 &fie->interval);
1339
1340out:
1341 mutex_unlock(&priv->lock);
1342 return ret;
1343}
1344
4a34ec8e
SL
1345static int csi_get_fmt(struct v4l2_subdev *sd,
1346 struct v4l2_subdev_pad_config *cfg,
1347 struct v4l2_subdev_format *sdformat)
1348{
1349 struct csi_priv *priv = v4l2_get_subdevdata(sd);
1350 struct v4l2_mbus_framefmt *fmt;
1351 int ret = 0;
1352
1353 if (sdformat->pad >= CSI_NUM_PADS)
1354 return -EINVAL;
1355
1356 mutex_lock(&priv->lock);
1357
1358 fmt = __csi_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
1359 if (!fmt) {
1360 ret = -EINVAL;
1361 goto out;
1362 }
1363
1364 sdformat->format = *fmt;
1365out:
1366 mutex_unlock(&priv->lock);
1367 return ret;
1368}
1369
d969291d
SL
1370static void csi_try_field(struct csi_priv *priv,
1371 struct v4l2_subdev_pad_config *cfg,
1372 struct v4l2_subdev_format *sdformat)
1373{
1374 struct v4l2_mbus_framefmt *infmt =
1375 __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
1376
4791bd7d
SL
1377 /*
1378 * no restrictions on sink pad field type except must
1379 * be initialized.
1380 */
1381 if (sdformat->pad == CSI_SINK_PAD) {
1382 if (sdformat->format.field == V4L2_FIELD_ANY)
1383 sdformat->format.field = V4L2_FIELD_NONE;
d969291d 1384 return;
4791bd7d 1385 }
d969291d
SL
1386
1387 switch (infmt->field) {
1388 case V4L2_FIELD_SEQ_TB:
1389 case V4L2_FIELD_SEQ_BT:
3c6640a6
SL
1390 /*
1391 * If the user requests sequential at the source pad,
1392 * allow it (along with possibly inverting field order).
1393 * Otherwise passthrough the field type.
1394 */
1395 if (!V4L2_FIELD_IS_SEQUENTIAL(sdformat->format.field))
1396 sdformat->format.field = infmt->field;
1397 break;
d969291d
SL
1398 case V4L2_FIELD_ALTERNATE:
1399 /*
d969291d
SL
1400 * This driver does not support alternate field mode, and
1401 * the CSI captures a whole frame, so the CSI never presents
3c6640a6
SL
1402 * alternate mode at its source pads. If user has not
1403 * already requested sequential, translate ALTERNATE at
1404 * sink pad to SEQ_TB or SEQ_BT at the source pad depending
1405 * on input height (assume NTSC BT order if 480 total active
1406 * frame lines, otherwise PAL TB order).
d969291d 1407 */
3c6640a6
SL
1408 if (!V4L2_FIELD_IS_SEQUENTIAL(sdformat->format.field))
1409 sdformat->format.field = (infmt->height == 480 / 2) ?
1410 V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB;
d969291d
SL
1411 break;
1412 default:
1413 /* Passthrough for all other input field types */
1414 sdformat->format.field = infmt->field;
1415 break;
1416 }
1417}
1418
4a34ec8e 1419static void csi_try_fmt(struct csi_priv *priv,
bf3cfaa7 1420 struct v4l2_fwnode_endpoint *upstream_ep,
4a34ec8e
SL
1421 struct v4l2_subdev_pad_config *cfg,
1422 struct v4l2_subdev_format *sdformat,
1423 struct v4l2_rect *crop,
69e78611 1424 struct v4l2_rect *compose,
4a34ec8e
SL
1425 const struct imx_media_pixfmt **cc)
1426{
1427 const struct imx_media_pixfmt *incc;
1428 struct v4l2_mbus_framefmt *infmt;
1429 u32 code;
1430
21e54111
SL
1431 infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
1432
4a34ec8e
SL
1433 switch (sdformat->pad) {
1434 case CSI_SRC_PAD_DIRECT:
1435 case CSI_SRC_PAD_IDMAC:
4a34ec8e
SL
1436 incc = imx_media_find_mbus_format(infmt->code,
1437 CS_SEL_ANY, true);
1438
69e78611
PZ
1439 sdformat->format.width = compose->width;
1440 sdformat->format.height = compose->height;
4a34ec8e 1441
779680e2 1442 if (requires_passthrough(upstream_ep, infmt, incc)) {
4a34ec8e
SL
1443 sdformat->format.code = infmt->code;
1444 *cc = incc;
1445 } else {
1446 u32 cs_sel = (incc->cs == IPUV3_COLORSPACE_YUV) ?
1447 CS_SEL_YUV : CS_SEL_RGB;
1448
1449 *cc = imx_media_find_ipu_format(sdformat->format.code,
1450 cs_sel);
1451 if (!*cc) {
1452 imx_media_enum_ipu_format(&code, 0, cs_sel);
1453 *cc = imx_media_find_ipu_format(code, cs_sel);
1454 sdformat->format.code = (*cc)->codes[0];
1455 }
1456 }
1457
d969291d 1458 csi_try_field(priv, cfg, sdformat);
21e54111
SL
1459
1460 /* propagate colorimetry from sink */
1461 sdformat->format.colorspace = infmt->colorspace;
1462 sdformat->format.xfer_func = infmt->xfer_func;
e3004605
SL
1463 sdformat->format.quantization = infmt->quantization;
1464 sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
d969291d 1465
4a34ec8e
SL
1466 break;
1467 case CSI_SINK_PAD:
1468 v4l_bound_align_image(&sdformat->format.width, MIN_W, MAX_W,
1469 W_ALIGN, &sdformat->format.height,
1470 MIN_H, MAX_H, H_ALIGN, S_ALIGN);
69e78611 1471
4a34ec8e
SL
1472 *cc = imx_media_find_mbus_format(sdformat->format.code,
1473 CS_SEL_ANY, true);
1474 if (!*cc) {
1475 imx_media_enum_mbus_format(&code, 0,
1476 CS_SEL_ANY, false);
1477 *cc = imx_media_find_mbus_format(code,
1d96e53f 1478 CS_SEL_ANY, false);
4a34ec8e
SL
1479 sdformat->format.code = (*cc)->codes[0];
1480 }
21e54111 1481
d969291d
SL
1482 csi_try_field(priv, cfg, sdformat);
1483
ab2f05cd
SL
1484 /* Reset crop and compose rectangles */
1485 crop->left = 0;
1486 crop->top = 0;
1487 crop->width = sdformat->format.width;
1488 crop->height = sdformat->format.height;
1489 if (sdformat->format.field == V4L2_FIELD_ALTERNATE)
1490 crop->height *= 2;
1491 csi_try_crop(priv, crop, cfg, &sdformat->format, upstream_ep);
1492 compose->left = 0;
1493 compose->top = 0;
1494 compose->width = crop->width;
1495 compose->height = crop->height;
1496
4a34ec8e
SL
1497 break;
1498 }
4791bd7d
SL
1499
1500 imx_media_try_colorimetry(&sdformat->format,
1501 priv->active_output_pad == CSI_SRC_PAD_DIRECT);
4a34ec8e
SL
1502}
1503
1504static int csi_set_fmt(struct v4l2_subdev *sd,
1505 struct v4l2_subdev_pad_config *cfg,
1506 struct v4l2_subdev_format *sdformat)
1507{
1508 struct csi_priv *priv = v4l2_get_subdevdata(sd);
60359a28 1509 struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
4a34ec8e 1510 const struct imx_media_pixfmt *cc;
4a34ec8e 1511 struct v4l2_mbus_framefmt *fmt;
69e78611 1512 struct v4l2_rect *crop, *compose;
bf3cfaa7 1513 int ret;
4a34ec8e
SL
1514
1515 if (sdformat->pad >= CSI_NUM_PADS)
1516 return -EINVAL;
1517
bf3cfaa7
SL
1518 ret = csi_get_upstream_endpoint(priv, &upstream_ep);
1519 if (ret) {
1520 v4l2_err(&priv->sd, "failed to find upstream endpoint\n");
1521 return ret;
4a34ec8e
SL
1522 }
1523
1524 mutex_lock(&priv->lock);
1525
1526 if (priv->stream_count > 0) {
1527 ret = -EBUSY;
1528 goto out;
1529 }
1530
1531 crop = __csi_get_crop(priv, cfg, sdformat->which);
69e78611 1532 compose = __csi_get_compose(priv, cfg, sdformat->which);
4a34ec8e 1533
bf3cfaa7 1534 csi_try_fmt(priv, &upstream_ep, cfg, sdformat, crop, compose, &cc);
4a34ec8e
SL
1535
1536 fmt = __csi_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
1537 *fmt = sdformat->format;
1538
1539 if (sdformat->pad == CSI_SINK_PAD) {
1540 int pad;
1541
1542 /* propagate format to source pads */
1543 for (pad = CSI_SINK_PAD + 1; pad < CSI_NUM_PADS; pad++) {
1544 const struct imx_media_pixfmt *outcc;
1545 struct v4l2_mbus_framefmt *outfmt;
1546 struct v4l2_subdev_format format;
1547
1548 format.pad = pad;
1549 format.which = sdformat->which;
1550 format.format = sdformat->format;
bf3cfaa7
SL
1551 csi_try_fmt(priv, &upstream_ep, cfg, &format,
1552 NULL, compose, &outcc);
4a34ec8e
SL
1553
1554 outfmt = __csi_get_fmt(priv, cfg, pad, sdformat->which);
1555 *outfmt = format.format;
1556
1557 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1558 priv->cc[pad] = outcc;
1559 }
1560 }
1561
523759c7
SL
1562 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1563 priv->cc[sdformat->pad] = cc;
4a34ec8e 1564
4a34ec8e
SL
1565out:
1566 mutex_unlock(&priv->lock);
1567 return ret;
1568}
1569
1570static int csi_get_selection(struct v4l2_subdev *sd,
1571 struct v4l2_subdev_pad_config *cfg,
1572 struct v4l2_subdev_selection *sel)
1573{
1574 struct csi_priv *priv = v4l2_get_subdevdata(sd);
1575 struct v4l2_mbus_framefmt *infmt;
69e78611 1576 struct v4l2_rect *crop, *compose;
4a34ec8e
SL
1577 int ret = 0;
1578
69e78611 1579 if (sel->pad != CSI_SINK_PAD)
4a34ec8e
SL
1580 return -EINVAL;
1581
1582 mutex_lock(&priv->lock);
1583
1584 infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sel->which);
1585 crop = __csi_get_crop(priv, cfg, sel->which);
69e78611 1586 compose = __csi_get_compose(priv, cfg, sel->which);
4a34ec8e
SL
1587
1588 switch (sel->target) {
1589 case V4L2_SEL_TGT_CROP_BOUNDS:
1590 sel->r.left = 0;
1591 sel->r.top = 0;
1592 sel->r.width = infmt->width;
1593 sel->r.height = infmt->height;
2a87c0c9
SL
1594 if (infmt->field == V4L2_FIELD_ALTERNATE)
1595 sel->r.height *= 2;
4a34ec8e
SL
1596 break;
1597 case V4L2_SEL_TGT_CROP:
1598 sel->r = *crop;
1599 break;
69e78611
PZ
1600 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1601 sel->r.left = 0;
1602 sel->r.top = 0;
1603 sel->r.width = crop->width;
1604 sel->r.height = crop->height;
1605 break;
1606 case V4L2_SEL_TGT_COMPOSE:
1607 sel->r = *compose;
1608 break;
4a34ec8e
SL
1609 default:
1610 ret = -EINVAL;
1611 }
1612
1613 mutex_unlock(&priv->lock);
1614 return ret;
1615}
1616
69e78611
PZ
1617static int csi_set_scale(u32 *compose, u32 crop, u32 flags)
1618{
1619 if ((flags & (V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE)) ==
1620 (V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE) &&
1621 *compose != crop && *compose != crop / 2)
1622 return -ERANGE;
1623
1624 if (*compose <= crop / 2 ||
1625 (*compose < crop * 3 / 4 && !(flags & V4L2_SEL_FLAG_GE)) ||
1626 (*compose < crop && (flags & V4L2_SEL_FLAG_LE)))
1627 *compose = crop / 2;
1628 else
1629 *compose = crop;
1630
1631 return 0;
1632}
1633
4a34ec8e
SL
1634static int csi_set_selection(struct v4l2_subdev *sd,
1635 struct v4l2_subdev_pad_config *cfg,
1636 struct v4l2_subdev_selection *sel)
1637{
1638 struct csi_priv *priv = v4l2_get_subdevdata(sd);
60359a28 1639 struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 };
4a34ec8e 1640 struct v4l2_mbus_framefmt *infmt;
69e78611 1641 struct v4l2_rect *crop, *compose;
bf3cfaa7 1642 int pad, ret;
4a34ec8e 1643
69e78611 1644 if (sel->pad != CSI_SINK_PAD)
4a34ec8e
SL
1645 return -EINVAL;
1646
bf3cfaa7
SL
1647 ret = csi_get_upstream_endpoint(priv, &upstream_ep);
1648 if (ret) {
1649 v4l2_err(&priv->sd, "failed to find upstream endpoint\n");
1650 return ret;
4a34ec8e
SL
1651 }
1652
1653 mutex_lock(&priv->lock);
1654
1655 if (priv->stream_count > 0) {
1656 ret = -EBUSY;
1657 goto out;
1658 }
1659
1660 infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sel->which);
1661 crop = __csi_get_crop(priv, cfg, sel->which);
69e78611 1662 compose = __csi_get_compose(priv, cfg, sel->which);
4a34ec8e 1663
69e78611
PZ
1664 switch (sel->target) {
1665 case V4L2_SEL_TGT_CROP:
1666 /*
1667 * Modifying the crop rectangle always changes the format on
1668 * the source pads. If the KEEP_CONFIG flag is set, just return
1669 * the current crop rectangle.
1670 */
1671 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
1672 sel->r = priv->crop;
1673 if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
1674 *crop = sel->r;
1675 goto out;
1676 }
1677
bf3cfaa7 1678 csi_try_crop(priv, &sel->r, cfg, infmt, &upstream_ep);
69e78611
PZ
1679
1680 *crop = sel->r;
1681
1682 /* Reset scaling to 1:1 */
1683 compose->width = crop->width;
1684 compose->height = crop->height;
1685 break;
1686 case V4L2_SEL_TGT_COMPOSE:
1687 /*
1688 * Modifying the compose rectangle always changes the format on
1689 * the source pads. If the KEEP_CONFIG flag is set, just return
1690 * the current compose rectangle.
1691 */
1692 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
1693 sel->r = priv->compose;
1694 if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
1695 *compose = sel->r;
1696 goto out;
1697 }
4a34ec8e 1698
69e78611
PZ
1699 sel->r.left = 0;
1700 sel->r.top = 0;
1701 ret = csi_set_scale(&sel->r.width, crop->width, sel->flags);
1702 if (ret)
1703 goto out;
1704 ret = csi_set_scale(&sel->r.height, crop->height, sel->flags);
1705 if (ret)
1706 goto out;
4a34ec8e 1707
69e78611
PZ
1708 *compose = sel->r;
1709 break;
1710 default:
1711 ret = -EINVAL;
1712 goto out;
1713 }
4a34ec8e 1714
69e78611 1715 /* Reset source pads to sink compose rectangle */
4a34ec8e
SL
1716 for (pad = CSI_SINK_PAD + 1; pad < CSI_NUM_PADS; pad++) {
1717 struct v4l2_mbus_framefmt *outfmt;
1718
1719 outfmt = __csi_get_fmt(priv, cfg, pad, sel->which);
69e78611
PZ
1720 outfmt->width = compose->width;
1721 outfmt->height = compose->height;
4a34ec8e
SL
1722 }
1723
1724out:
1725 mutex_unlock(&priv->lock);
1726 return ret;
1727}
1728
1729static int csi_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1730 struct v4l2_event_subscription *sub)
1731{
1732 if (sub->type != V4L2_EVENT_IMX_FRAME_INTERVAL_ERROR)
1733 return -EINVAL;
1734 if (sub->id != 0)
1735 return -EINVAL;
1736
1737 return v4l2_event_subscribe(fh, sub, 0, NULL);
1738}
1739
1740static int csi_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1741 struct v4l2_event_subscription *sub)
1742{
1743 return v4l2_event_unsubscribe(fh, sub);
1744}
1745
4a34ec8e
SL
1746static int csi_registered(struct v4l2_subdev *sd)
1747{
1748 struct csi_priv *priv = v4l2_get_subdevdata(sd);
0b2e9e79 1749 struct ipu_csi *csi;
4a34ec8e
SL
1750 int i, ret;
1751 u32 code;
1752
4a34ec8e 1753 /* get handle to IPU CSI */
0b2e9e79
AB
1754 csi = ipu_csi_get(priv->ipu, priv->csi_id);
1755 if (IS_ERR(csi)) {
4a34ec8e 1756 v4l2_err(&priv->sd, "failed to get CSI%d\n", priv->csi_id);
0b2e9e79 1757 return PTR_ERR(csi);
4a34ec8e 1758 }
0b2e9e79 1759 priv->csi = csi;
4a34ec8e
SL
1760
1761 for (i = 0; i < CSI_NUM_PADS; i++) {
4a34ec8e
SL
1762 code = 0;
1763 if (i != CSI_SINK_PAD)
1764 imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
1765
1766 /* set a default mbus format */
1767 ret = imx_media_init_mbus_fmt(&priv->format_mbus[i],
1768 640, 480, code, V4L2_FIELD_NONE,
1769 &priv->cc[i]);
1770 if (ret)
1771 goto put_csi;
fb30ee79
PZ
1772
1773 /* init default frame interval */
1774 priv->frame_interval[i].numerator = 1;
1775 priv->frame_interval[i].denominator = 30;
4a34ec8e
SL
1776 }
1777
fb30ee79
PZ
1778 /* disable frame skipping */
1779 priv->skip = &csi_skip[0];
4a34ec8e 1780
69e78611
PZ
1781 /* init default crop and compose rectangle sizes */
1782 priv->crop.width = 640;
1783 priv->crop.height = 480;
1784 priv->compose.width = 640;
1785 priv->compose.height = 480;
1786
4a34ec8e
SL
1787 priv->fim = imx_media_fim_init(&priv->sd);
1788 if (IS_ERR(priv->fim)) {
1789 ret = PTR_ERR(priv->fim);
1790 goto put_csi;
1791 }
1792
1f464246
SL
1793 priv->vdev = imx_media_capture_device_init(priv->sd.dev,
1794 &priv->sd,
1795 CSI_SRC_PAD_IDMAC);
1796 if (IS_ERR(priv->vdev)) {
1797 ret = PTR_ERR(priv->vdev);
1798 goto free_fim;
1799 }
1800
411c5988 1801 ret = imx_media_capture_device_register(priv->vdev);
4a34ec8e 1802 if (ret)
1f464246 1803 goto remove_vdev;
4a34ec8e 1804
4a34ec8e 1805 return 0;
3e80d125 1806
1f464246
SL
1807remove_vdev:
1808 imx_media_capture_device_remove(priv->vdev);
4a34ec8e
SL
1809free_fim:
1810 if (priv->fim)
1811 imx_media_fim_free(priv->fim);
1812put_csi:
1813 ipu_csi_put(priv->csi);
1814 return ret;
1815}
1816
1817static void csi_unregistered(struct v4l2_subdev *sd)
1818{
1819 struct csi_priv *priv = v4l2_get_subdevdata(sd);
1820
1821 imx_media_capture_device_unregister(priv->vdev);
1f464246 1822 imx_media_capture_device_remove(priv->vdev);
4a34ec8e
SL
1823
1824 if (priv->fim)
1825 imx_media_fim_free(priv->fim);
1826
0b2e9e79 1827 if (priv->csi)
4a34ec8e
SL
1828 ipu_csi_put(priv->csi);
1829}
1830
1831static const struct media_entity_operations csi_entity_ops = {
1832 .link_setup = csi_link_setup,
1833 .link_validate = v4l2_subdev_link_validate,
1834};
1835
1836static const struct v4l2_subdev_core_ops csi_core_ops = {
1837 .subscribe_event = csi_subscribe_event,
1838 .unsubscribe_event = csi_unsubscribe_event,
1839};
1840
1841static const struct v4l2_subdev_video_ops csi_video_ops = {
1842 .g_frame_interval = csi_g_frame_interval,
1843 .s_frame_interval = csi_s_frame_interval,
1844 .s_stream = csi_s_stream,
1845};
1846
1847static const struct v4l2_subdev_pad_ops csi_pad_ops = {
46c121e0 1848 .init_cfg = imx_media_init_cfg,
4a34ec8e 1849 .enum_mbus_code = csi_enum_mbus_code,
949ffdbf
RK
1850 .enum_frame_size = csi_enum_frame_size,
1851 .enum_frame_interval = csi_enum_frame_interval,
4a34ec8e
SL
1852 .get_fmt = csi_get_fmt,
1853 .set_fmt = csi_set_fmt,
1854 .get_selection = csi_get_selection,
1855 .set_selection = csi_set_selection,
1856 .link_validate = csi_link_validate,
1857};
1858
1859static const struct v4l2_subdev_ops csi_subdev_ops = {
1860 .core = &csi_core_ops,
1861 .video = &csi_video_ops,
1862 .pad = &csi_pad_ops,
1863};
1864
1865static const struct v4l2_subdev_internal_ops csi_internal_ops = {
1866 .registered = csi_registered,
1867 .unregistered = csi_unregistered,
1868};
1869
c893500a
SL
1870static int imx_csi_parse_endpoint(struct device *dev,
1871 struct v4l2_fwnode_endpoint *vep,
1872 struct v4l2_async_subdev *asd)
1873{
337e90ed 1874 return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
c893500a
SL
1875}
1876
1877static int imx_csi_async_register(struct csi_priv *priv)
1878{
1879 struct v4l2_async_notifier *notifier;
1880 struct fwnode_handle *fwnode;
1881 unsigned int port;
1882 int ret;
1883
1884 notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
1885 if (!notifier)
1886 return -ENOMEM;
1887
1888 v4l2_async_notifier_init(notifier);
1889
1890 fwnode = dev_fwnode(priv->dev);
1891
1892 /* get this CSI's port id */
1893 ret = fwnode_property_read_u32(fwnode, "reg", &port);
1894 if (ret < 0)
1895 goto out_free;
1896
1897 ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
1898 priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev),
1899 port, imx_csi_parse_endpoint);
1900 if (ret < 0)
1901 goto out_cleanup;
1902
1903 ret = v4l2_async_subdev_notifier_register(&priv->sd, notifier);
1904 if (ret < 0)
1905 goto out_cleanup;
1906
1907 ret = v4l2_async_register_subdev(&priv->sd);
1908 if (ret < 0)
1909 goto out_unregister;
1910
1911 priv->sd.subdev_notifier = notifier;
1912
1913 return 0;
1914
1915out_unregister:
1916 v4l2_async_notifier_unregister(notifier);
1917out_cleanup:
1918 v4l2_async_notifier_cleanup(notifier);
1919out_free:
1920 kfree(notifier);
1921
1922 return ret;
1923}
1924
4a34ec8e
SL
1925static int imx_csi_probe(struct platform_device *pdev)
1926{
1927 struct ipu_client_platformdata *pdata;
1928 struct pinctrl *pinctrl;
1929 struct csi_priv *priv;
2a4558c6 1930 int i, ret;
4a34ec8e
SL
1931
1932 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1933 if (!priv)
1934 return -ENOMEM;
1935
1936 platform_set_drvdata(pdev, &priv->sd);
1937 priv->dev = &pdev->dev;
1938
1939 ret = dma_set_coherent_mask(priv->dev, DMA_BIT_MASK(32));
1940 if (ret)
1941 return ret;
1942
1943 /* get parent IPU */
1944 priv->ipu = dev_get_drvdata(priv->dev->parent);
1945
1946 /* get our CSI id */
1947 pdata = priv->dev->platform_data;
1948 priv->csi_id = pdata->csi;
1949 priv->smfc_id = (priv->csi_id == 0) ? 0 : 2;
1950
451a7b78
PZ
1951 priv->active_output_pad = CSI_SRC_PAD_IDMAC;
1952
e99e88a9 1953 timer_setup(&priv->eof_timeout_timer, csi_idmac_eof_timeout, 0);
4a34ec8e
SL
1954 spin_lock_init(&priv->irqlock);
1955
1956 v4l2_subdev_init(&priv->sd, &csi_subdev_ops);
1957 v4l2_set_subdevdata(&priv->sd, priv);
1958 priv->sd.internal_ops = &csi_internal_ops;
1959 priv->sd.entity.ops = &csi_entity_ops;
1960 priv->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
1961 priv->sd.dev = &pdev->dev;
1962 priv->sd.fwnode = of_fwnode_handle(pdata->of_node);
1963 priv->sd.owner = THIS_MODULE;
1964 priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
1965 priv->sd.grp_id = priv->csi_id ?
67673ed5 1966 IMX_MEDIA_GRP_ID_IPU_CSI1 : IMX_MEDIA_GRP_ID_IPU_CSI0;
4a34ec8e
SL
1967 imx_media_grp_id_to_sd_name(priv->sd.name, sizeof(priv->sd.name),
1968 priv->sd.grp_id, ipu_get_num(priv->ipu));
1969
2a4558c6
SL
1970 for (i = 0; i < CSI_NUM_PADS; i++)
1971 priv->pad[i].flags = (i == CSI_SINK_PAD) ?
1972 MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
1973
1974 ret = media_entity_pads_init(&priv->sd.entity, CSI_NUM_PADS,
1975 priv->pad);
1976 if (ret)
1977 return ret;
1978
4a34ec8e
SL
1979 mutex_init(&priv->lock);
1980
1981 v4l2_ctrl_handler_init(&priv->ctrl_hdlr, 0);
1982 priv->sd.ctrl_handler = &priv->ctrl_hdlr;
1983
1984 /*
1985 * The IPUv3 driver did not assign an of_node to this
1986 * device. As a result, pinctrl does not automatically
1987 * configure our pin groups, so we need to do that manually
1988 * here, after setting this device's of_node.
1989 */
1990 priv->dev->of_node = pdata->of_node;
1991 pinctrl = devm_pinctrl_get_select_default(priv->dev);
52e17089 1992 if (IS_ERR(pinctrl)) {
2b7db29b 1993 ret = PTR_ERR(pinctrl);
dd5747fb
FE
1994 dev_dbg(priv->dev,
1995 "devm_pinctrl_get_select_default() failed: %d\n", ret);
1996 if (ret != -ENODEV)
1997 goto free;
52e17089 1998 }
4a34ec8e 1999
c893500a 2000 ret = imx_csi_async_register(priv);
4a34ec8e
SL
2001 if (ret)
2002 goto free;
2003
2004 return 0;
2005free:
2006 v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
2007 mutex_destroy(&priv->lock);
4a34ec8e
SL
2008 return ret;
2009}
2010
2011static int imx_csi_remove(struct platform_device *pdev)
2012{
2013 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
2014 struct csi_priv *priv = sd_to_dev(sd);
2015
2016 v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
2017 mutex_destroy(&priv->lock);
4a34ec8e
SL
2018 v4l2_async_unregister_subdev(sd);
2019 media_entity_cleanup(&sd->entity);
2020
2021 return 0;
2022}
2023
2024static const struct platform_device_id imx_csi_ids[] = {
2025 { .name = "imx-ipuv3-csi" },
2026 { },
2027};
2028MODULE_DEVICE_TABLE(platform, imx_csi_ids);
2029
2030static struct platform_driver imx_csi_driver = {
2031 .probe = imx_csi_probe,
2032 .remove = imx_csi_remove,
2033 .id_table = imx_csi_ids,
2034 .driver = {
2035 .name = "imx-ipuv3-csi",
2036 },
2037};
2038module_platform_driver(imx_csi_driver);
2039
2040MODULE_DESCRIPTION("i.MX CSI subdev driver");
2041MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
2042MODULE_LICENSE("GPL");
2043MODULE_ALIAS("platform:imx-ipuv3-csi");