1
2
3
4
5
6
7
8
9#include <linux/clk.h>
10#include <linux/delay.h>
11#include <linux/gcd.h>
12#include <linux/interrupt.h>
13#include <linux/mfd/syscon.h>
14#include <linux/module.h>
15#include <linux/of_graph.h>
16#include <linux/pinctrl/consumer.h>
17#include <linux/platform_device.h>
18#include <linux/regmap.h>
19#include <linux/types.h>
20
21#include <media/v4l2-ctrls.h>
22#include <media/v4l2-device.h>
23#include <media/v4l2-event.h>
24#include <media/v4l2-fwnode.h>
25#include <media/v4l2-mc.h>
26#include <media/v4l2-subdev.h>
27#include <media/videobuf2-dma-contig.h>
28
29#include <media/imx.h>
30#include "imx-media.h"
31
32#define IMX7_CSI_PAD_SINK 0
33#define IMX7_CSI_PAD_SRC 1
34#define IMX7_CSI_PADS_NUM 2
35
36
37#define CSICR1_RESET_VAL 0x40000800
38#define CSICR2_RESET_VAL 0x0
39#define CSICR3_RESET_VAL 0x0
40
41
42#define BIT_SWAP16_EN BIT(31)
43#define BIT_EXT_VSYNC BIT(30)
44#define BIT_EOF_INT_EN BIT(29)
45#define BIT_PRP_IF_EN BIT(28)
46#define BIT_CCIR_MODE BIT(27)
47#define BIT_COF_INT_EN BIT(26)
48#define BIT_SF_OR_INTEN BIT(25)
49#define BIT_RF_OR_INTEN BIT(24)
50#define BIT_SFF_DMA_DONE_INTEN BIT(22)
51#define BIT_STATFF_INTEN BIT(21)
52#define BIT_FB2_DMA_DONE_INTEN BIT(20)
53#define BIT_FB1_DMA_DONE_INTEN BIT(19)
54#define BIT_RXFF_INTEN BIT(18)
55#define BIT_SOF_POL BIT(17)
56#define BIT_SOF_INTEN BIT(16)
57#define BIT_MCLKDIV (0xF << 12)
58#define BIT_HSYNC_POL BIT(11)
59#define BIT_CCIR_EN BIT(10)
60#define BIT_MCLKEN BIT(9)
61#define BIT_FCC BIT(8)
62#define BIT_PACK_DIR BIT(7)
63#define BIT_CLR_STATFIFO BIT(6)
64#define BIT_CLR_RXFIFO BIT(5)
65#define BIT_GCLK_MODE BIT(4)
66#define BIT_INV_DATA BIT(3)
67#define BIT_INV_PCLK BIT(2)
68#define BIT_REDGE BIT(1)
69#define BIT_PIXEL_BIT BIT(0)
70
71#define SHIFT_MCLKDIV 12
72
73
74#define BIT_FRMCNT (0xFFFF << 16)
75#define BIT_FRMCNT_RST BIT(15)
76#define BIT_DMA_REFLASH_RFF BIT(14)
77#define BIT_DMA_REFLASH_SFF BIT(13)
78#define BIT_DMA_REQ_EN_RFF BIT(12)
79#define BIT_DMA_REQ_EN_SFF BIT(11)
80#define BIT_STATFF_LEVEL (0x7 << 8)
81#define BIT_HRESP_ERR_EN BIT(7)
82#define BIT_RXFF_LEVEL (0x7 << 4)
83#define BIT_TWO_8BIT_SENSOR BIT(3)
84#define BIT_ZERO_PACK_EN BIT(2)
85#define BIT_ECC_INT_EN BIT(1)
86#define BIT_ECC_AUTO_EN BIT(0)
87
88#define SHIFT_FRMCNT 16
89#define SHIFT_RXFIFO_LEVEL 4
90
91
92#define BIT_ADDR_CH_ERR_INT BIT(28)
93#define BIT_FIELD0_INT BIT(27)
94#define BIT_FIELD1_INT BIT(26)
95#define BIT_SFF_OR_INT BIT(25)
96#define BIT_RFF_OR_INT BIT(24)
97#define BIT_DMA_TSF_DONE_SFF BIT(22)
98#define BIT_STATFF_INT BIT(21)
99#define BIT_DMA_TSF_DONE_FB2 BIT(20)
100#define BIT_DMA_TSF_DONE_FB1 BIT(19)
101#define BIT_RXFF_INT BIT(18)
102#define BIT_EOF_INT BIT(17)
103#define BIT_SOF_INT BIT(16)
104#define BIT_F2_INT BIT(15)
105#define BIT_F1_INT BIT(14)
106#define BIT_COF_INT BIT(13)
107#define BIT_HRESP_ERR_INT BIT(7)
108#define BIT_ECC_INT BIT(1)
109#define BIT_DRDY BIT(0)
110
111
112#define BIT_CSI_HW_ENABLE BIT(31)
113#define BIT_MIPI_DATA_FORMAT_RAW8 (0x2a << 25)
114#define BIT_MIPI_DATA_FORMAT_RAW10 (0x2b << 25)
115#define BIT_MIPI_DATA_FORMAT_RAW12 (0x2c << 25)
116#define BIT_MIPI_DATA_FORMAT_RAW14 (0x2d << 25)
117#define BIT_MIPI_DATA_FORMAT_YUV422_8B (0x1e << 25)
118#define BIT_MIPI_DATA_FORMAT_MASK (0x3F << 25)
119#define BIT_MIPI_DATA_FORMAT_OFFSET 25
120#define BIT_DATA_FROM_MIPI BIT(22)
121#define BIT_MIPI_YU_SWAP BIT(21)
122#define BIT_MIPI_DOUBLE_CMPNT BIT(20)
123#define BIT_BASEADDR_CHG_ERR_EN BIT(9)
124#define BIT_BASEADDR_SWITCH_SEL BIT(5)
125#define BIT_BASEADDR_SWITCH_EN BIT(4)
126#define BIT_PARALLEL24_EN BIT(3)
127#define BIT_DEINTERLACE_EN BIT(2)
128#define BIT_TVDECODER_IN_EN BIT(1)
129#define BIT_NTSC_EN BIT(0)
130
131#define CSI_MCLK_VF 1
132#define CSI_MCLK_ENC 2
133#define CSI_MCLK_RAW 4
134#define CSI_MCLK_I2C 8
135
136#define CSI_CSICR1 0x0
137#define CSI_CSICR2 0x4
138#define CSI_CSICR3 0x8
139#define CSI_STATFIFO 0xC
140#define CSI_CSIRXFIFO 0x10
141#define CSI_CSIRXCNT 0x14
142#define CSI_CSISR 0x18
143
144#define CSI_CSIDBG 0x1C
145#define CSI_CSIDMASA_STATFIFO 0x20
146#define CSI_CSIDMATS_STATFIFO 0x24
147#define CSI_CSIDMASA_FB1 0x28
148#define CSI_CSIDMASA_FB2 0x2C
149#define CSI_CSIFBUF_PARA 0x30
150#define CSI_CSIIMAG_PARA 0x34
151
152#define CSI_CSICR18 0x48
153#define CSI_CSICR19 0x4c
154
155struct imx7_csi {
156 struct device *dev;
157 struct v4l2_subdev sd;
158 struct imx_media_video_dev *vdev;
159 struct imx_media_dev *imxmd;
160 struct media_pad pad[IMX7_CSI_PADS_NUM];
161
162
163 struct mutex lock;
164
165 spinlock_t irqlock;
166
167 struct v4l2_subdev *src_sd;
168
169 struct media_entity *sink;
170
171 struct v4l2_fwnode_endpoint upstream_ep;
172
173 struct v4l2_mbus_framefmt format_mbus[IMX7_CSI_PADS_NUM];
174 const struct imx_media_pixfmt *cc[IMX7_CSI_PADS_NUM];
175 struct v4l2_fract frame_interval[IMX7_CSI_PADS_NUM];
176
177 struct v4l2_ctrl_handler ctrl_hdlr;
178
179 void __iomem *regbase;
180 int irq;
181 struct clk *mclk;
182
183
184 struct imx_media_buffer *active_vb2_buf[2];
185 struct imx_media_dma_buf underrun_buf;
186
187 int buf_num;
188 u32 frame_sequence;
189
190 bool last_eof;
191 bool is_init;
192 bool is_streaming;
193 bool is_csi2;
194
195 struct completion last_eof_completion;
196};
197
198static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset)
199{
200 return readl(csi->regbase + offset);
201}
202
203static void imx7_csi_reg_write(struct imx7_csi *csi, unsigned int value,
204 unsigned int offset)
205{
206 writel(value, csi->regbase + offset);
207}
208
209static void imx7_csi_hw_reset(struct imx7_csi *csi)
210{
211 imx7_csi_reg_write(csi,
212 imx7_csi_reg_read(csi, CSI_CSICR3) | BIT_FRMCNT_RST,
213 CSI_CSICR3);
214
215 imx7_csi_reg_write(csi, CSICR1_RESET_VAL, CSI_CSICR1);
216 imx7_csi_reg_write(csi, CSICR2_RESET_VAL, CSI_CSICR2);
217 imx7_csi_reg_write(csi, CSICR3_RESET_VAL, CSI_CSICR3);
218}
219
220static u32 imx7_csi_irq_clear(struct imx7_csi *csi)
221{
222 u32 isr;
223
224 isr = imx7_csi_reg_read(csi, CSI_CSISR);
225 imx7_csi_reg_write(csi, isr, CSI_CSISR);
226
227 return isr;
228}
229
230static void imx7_csi_init_interface(struct imx7_csi *csi)
231{
232 unsigned int val = 0;
233 unsigned int imag_para;
234
235 val = BIT_SOF_POL | BIT_REDGE | BIT_GCLK_MODE | BIT_HSYNC_POL |
236 BIT_FCC | 1 << SHIFT_MCLKDIV | BIT_MCLKEN;
237 imx7_csi_reg_write(csi, val, CSI_CSICR1);
238
239 imag_para = (800 << 16) | 600;
240 imx7_csi_reg_write(csi, imag_para, CSI_CSIIMAG_PARA);
241
242 val = BIT_DMA_REFLASH_RFF;
243 imx7_csi_reg_write(csi, val, CSI_CSICR3);
244}
245
246static void imx7_csi_hw_enable_irq(struct imx7_csi *csi)
247{
248 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
249
250 cr1 |= BIT_SOF_INTEN;
251 cr1 |= BIT_RFF_OR_INT;
252
253
254 cr1 |= BIT_FB1_DMA_DONE_INTEN;
255 cr1 |= BIT_FB2_DMA_DONE_INTEN;
256
257 cr1 |= BIT_EOF_INT_EN;
258
259 imx7_csi_reg_write(csi, cr1, CSI_CSICR1);
260}
261
262static void imx7_csi_hw_disable_irq(struct imx7_csi *csi)
263{
264 u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
265
266 cr1 &= ~BIT_SOF_INTEN;
267 cr1 &= ~BIT_RFF_OR_INT;
268 cr1 &= ~BIT_FB1_DMA_DONE_INTEN;
269 cr1 &= ~BIT_FB2_DMA_DONE_INTEN;
270 cr1 &= ~BIT_EOF_INT_EN;
271
272 imx7_csi_reg_write(csi, cr1, CSI_CSICR1);
273}
274
275static void imx7_csi_hw_enable(struct imx7_csi *csi)
276{
277 u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18);
278
279 cr |= BIT_CSI_HW_ENABLE;
280
281 imx7_csi_reg_write(csi, cr, CSI_CSICR18);
282}
283
284static void imx7_csi_hw_disable(struct imx7_csi *csi)
285{
286 u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18);
287
288 cr &= ~BIT_CSI_HW_ENABLE;
289
290 imx7_csi_reg_write(csi, cr, CSI_CSICR18);
291}
292
293static void imx7_csi_dma_reflash(struct imx7_csi *csi)
294{
295 u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR18);
296
297 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
298 cr3 |= BIT_DMA_REFLASH_RFF;
299 imx7_csi_reg_write(csi, cr3, CSI_CSICR3);
300}
301
302static void imx7_csi_rx_fifo_clear(struct imx7_csi *csi)
303{
304 u32 cr1;
305
306 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
307 imx7_csi_reg_write(csi, cr1 & ~BIT_FCC, CSI_CSICR1);
308 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
309 imx7_csi_reg_write(csi, cr1 | BIT_CLR_RXFIFO, CSI_CSICR1);
310
311 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
312 imx7_csi_reg_write(csi, cr1 | BIT_FCC, CSI_CSICR1);
313}
314
315static void imx7_csi_buf_stride_set(struct imx7_csi *csi, u32 stride)
316{
317 imx7_csi_reg_write(csi, stride, CSI_CSIFBUF_PARA);
318}
319
320static void imx7_csi_deinterlace_enable(struct imx7_csi *csi, bool enable)
321{
322 u32 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18);
323
324 if (enable)
325 cr18 |= BIT_DEINTERLACE_EN;
326 else
327 cr18 &= ~BIT_DEINTERLACE_EN;
328
329 imx7_csi_reg_write(csi, cr18, CSI_CSICR18);
330}
331
332static void imx7_csi_dmareq_rff_enable(struct imx7_csi *csi)
333{
334 u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
335 u32 cr2 = imx7_csi_reg_read(csi, CSI_CSICR2);
336
337
338 cr2 |= 0xC0000000;
339
340 cr3 |= BIT_DMA_REQ_EN_RFF;
341 cr3 |= BIT_HRESP_ERR_EN;
342 cr3 &= ~BIT_RXFF_LEVEL;
343 cr3 |= 0x2 << 4;
344
345 imx7_csi_reg_write(csi, cr3, CSI_CSICR3);
346 imx7_csi_reg_write(csi, cr2, CSI_CSICR2);
347}
348
349static void imx7_csi_dmareq_rff_disable(struct imx7_csi *csi)
350{
351 u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
352
353 cr3 &= ~BIT_DMA_REQ_EN_RFF;
354 cr3 &= ~BIT_HRESP_ERR_EN;
355 imx7_csi_reg_write(csi, cr3, CSI_CSICR3);
356}
357
358static void imx7_csi_set_imagpara(struct imx7_csi *csi, int width, int height)
359{
360 int imag_para;
361 int rx_count;
362
363 rx_count = (width * height) >> 2;
364 imx7_csi_reg_write(csi, rx_count, CSI_CSIRXCNT);
365
366 imag_para = (width << 16) | height;
367 imx7_csi_reg_write(csi, imag_para, CSI_CSIIMAG_PARA);
368
369
370 imx7_csi_dma_reflash(csi);
371}
372
373static void imx7_csi_sw_reset(struct imx7_csi *csi)
374{
375 imx7_csi_hw_disable(csi);
376
377 imx7_csi_rx_fifo_clear(csi);
378
379 imx7_csi_dma_reflash(csi);
380
381 usleep_range(2000, 3000);
382
383 imx7_csi_irq_clear(csi);
384
385 imx7_csi_hw_enable(csi);
386}
387
388static void imx7_csi_error_recovery(struct imx7_csi *csi)
389{
390 imx7_csi_hw_disable(csi);
391
392 imx7_csi_rx_fifo_clear(csi);
393
394 imx7_csi_dma_reflash(csi);
395
396 imx7_csi_hw_enable(csi);
397}
398
399static int imx7_csi_init(struct imx7_csi *csi)
400{
401 int ret;
402
403 if (csi->is_init)
404 return 0;
405
406 ret = clk_prepare_enable(csi->mclk);
407 if (ret < 0)
408 return ret;
409 imx7_csi_hw_reset(csi);
410 imx7_csi_init_interface(csi);
411 imx7_csi_dmareq_rff_enable(csi);
412
413 csi->is_init = true;
414
415 return 0;
416}
417
418static void imx7_csi_deinit(struct imx7_csi *csi)
419{
420 if (!csi->is_init)
421 return;
422
423 imx7_csi_hw_reset(csi);
424 imx7_csi_init_interface(csi);
425 imx7_csi_dmareq_rff_disable(csi);
426 clk_disable_unprepare(csi->mclk);
427
428 csi->is_init = false;
429}
430
431static int imx7_csi_get_upstream_endpoint(struct imx7_csi *csi,
432 struct v4l2_fwnode_endpoint *ep,
433 bool skip_mux)
434{
435 struct device_node *endpoint, *port;
436 struct media_entity *src;
437 struct v4l2_subdev *sd;
438 struct media_pad *pad;
439
440 if (!csi->src_sd)
441 return -EPIPE;
442
443 src = &csi->src_sd->entity;
444
445
446
447
448
449 if (src->function != MEDIA_ENT_F_VID_IF_BRIDGE &&
450 src->function != MEDIA_ENT_F_VID_MUX)
451 src = &csi->sd.entity;
452
453skip_video_mux:
454
455 pad = imx_media_pipeline_pad(src, 0, 0, true);
456 if (!pad)
457 return -ENODEV;
458
459 sd = media_entity_to_v4l2_subdev(pad->entity);
460
461
462 if (skip_mux && src->function == MEDIA_ENT_F_VID_MUX) {
463 src = &sd->entity;
464 goto skip_video_mux;
465 }
466
467
468
469
470
471 port = of_graph_get_port_by_id(sd->dev->of_node, pad->index);
472 if (!port)
473 return -ENODEV;
474
475 endpoint = of_get_next_child(port, NULL);
476 of_node_put(port);
477 if (!endpoint)
478 return -ENODEV;
479
480 v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), ep);
481 of_node_put(endpoint);
482
483 return 0;
484}
485
486static int imx7_csi_link_setup(struct media_entity *entity,
487 const struct media_pad *local,
488 const struct media_pad *remote, u32 flags)
489{
490 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
491 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
492 struct v4l2_subdev *remote_sd;
493 int ret = 0;
494
495 dev_dbg(csi->dev, "link setup %s -> %s\n", remote->entity->name,
496 local->entity->name);
497
498 mutex_lock(&csi->lock);
499
500 if (local->flags & MEDIA_PAD_FL_SINK) {
501 if (!is_media_entity_v4l2_subdev(remote->entity)) {
502 ret = -EINVAL;
503 goto unlock;
504 }
505
506 remote_sd = media_entity_to_v4l2_subdev(remote->entity);
507
508 if (flags & MEDIA_LNK_FL_ENABLED) {
509 if (csi->src_sd) {
510 ret = -EBUSY;
511 goto unlock;
512 }
513 csi->src_sd = remote_sd;
514 } else {
515 csi->src_sd = NULL;
516 }
517
518 goto init;
519 }
520
521
522 if (flags & MEDIA_LNK_FL_ENABLED) {
523 if (csi->sink) {
524 ret = -EBUSY;
525 goto unlock;
526 }
527 csi->sink = remote->entity;
528 } else {
529 v4l2_ctrl_handler_free(&csi->ctrl_hdlr);
530 v4l2_ctrl_handler_init(&csi->ctrl_hdlr, 0);
531 csi->sink = NULL;
532 }
533
534init:
535 if (csi->sink || csi->src_sd)
536 ret = imx7_csi_init(csi);
537 else
538 imx7_csi_deinit(csi);
539
540unlock:
541 mutex_unlock(&csi->lock);
542
543 return ret;
544}
545
546static int imx7_csi_pad_link_validate(struct v4l2_subdev *sd,
547 struct media_link *link,
548 struct v4l2_subdev_format *source_fmt,
549 struct v4l2_subdev_format *sink_fmt)
550{
551 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
552 struct v4l2_fwnode_endpoint upstream_ep = {};
553 int ret;
554
555 ret = v4l2_subdev_link_validate_default(sd, link, source_fmt, sink_fmt);
556 if (ret)
557 return ret;
558
559 ret = imx7_csi_get_upstream_endpoint(csi, &upstream_ep, true);
560 if (ret) {
561 v4l2_err(&csi->sd, "failed to find upstream endpoint\n");
562 return ret;
563 }
564
565 mutex_lock(&csi->lock);
566
567 csi->upstream_ep = upstream_ep;
568 csi->is_csi2 = (upstream_ep.bus_type == V4L2_MBUS_CSI2_DPHY);
569
570 mutex_unlock(&csi->lock);
571
572 return 0;
573}
574
575static void imx7_csi_update_buf(struct imx7_csi *csi, dma_addr_t phys,
576 int buf_num)
577{
578 if (buf_num == 1)
579 imx7_csi_reg_write(csi, phys, CSI_CSIDMASA_FB2);
580 else
581 imx7_csi_reg_write(csi, phys, CSI_CSIDMASA_FB1);
582}
583
584static void imx7_csi_setup_vb2_buf(struct imx7_csi *csi)
585{
586 struct imx_media_video_dev *vdev = csi->vdev;
587 struct imx_media_buffer *buf;
588 struct vb2_buffer *vb2_buf;
589 dma_addr_t phys[2];
590 int i;
591
592 for (i = 0; i < 2; i++) {
593 buf = imx_media_capture_device_next_buf(vdev);
594 if (buf) {
595 csi->active_vb2_buf[i] = buf;
596 vb2_buf = &buf->vbuf.vb2_buf;
597 phys[i] = vb2_dma_contig_plane_dma_addr(vb2_buf, 0);
598 } else {
599 csi->active_vb2_buf[i] = NULL;
600 phys[i] = csi->underrun_buf.phys;
601 }
602
603 imx7_csi_update_buf(csi, phys[i], i);
604 }
605}
606
607static void imx7_csi_dma_unsetup_vb2_buf(struct imx7_csi *csi,
608 enum vb2_buffer_state return_status)
609{
610 struct imx_media_buffer *buf;
611 int i;
612
613
614 for (i = 0; i < 2; i++) {
615 buf = csi->active_vb2_buf[i];
616 if (buf) {
617 struct vb2_buffer *vb = &buf->vbuf.vb2_buf;
618
619 vb->timestamp = ktime_get_ns();
620 vb2_buffer_done(vb, return_status);
621 }
622 }
623}
624
625static void imx7_csi_vb2_buf_done(struct imx7_csi *csi)
626{
627 struct imx_media_video_dev *vdev = csi->vdev;
628 struct imx_media_buffer *done, *next;
629 struct vb2_buffer *vb;
630 dma_addr_t phys;
631
632 done = csi->active_vb2_buf[csi->buf_num];
633 if (done) {
634 done->vbuf.field = vdev->fmt.fmt.pix.field;
635 done->vbuf.sequence = csi->frame_sequence;
636 vb = &done->vbuf.vb2_buf;
637 vb->timestamp = ktime_get_ns();
638 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
639 }
640 csi->frame_sequence++;
641
642
643 next = imx_media_capture_device_next_buf(vdev);
644 if (next) {
645 phys = vb2_dma_contig_plane_dma_addr(&next->vbuf.vb2_buf, 0);
646 csi->active_vb2_buf[csi->buf_num] = next;
647 } else {
648 phys = csi->underrun_buf.phys;
649 csi->active_vb2_buf[csi->buf_num] = NULL;
650 }
651
652 imx7_csi_update_buf(csi, phys, csi->buf_num);
653}
654
655static irqreturn_t imx7_csi_irq_handler(int irq, void *data)
656{
657 struct imx7_csi *csi = data;
658 u32 status;
659
660 spin_lock(&csi->irqlock);
661
662 status = imx7_csi_irq_clear(csi);
663
664 if (status & BIT_RFF_OR_INT) {
665 dev_warn(csi->dev, "Rx fifo overflow\n");
666 imx7_csi_error_recovery(csi);
667 }
668
669 if (status & BIT_HRESP_ERR_INT) {
670 dev_warn(csi->dev, "Hresponse error detected\n");
671 imx7_csi_error_recovery(csi);
672 }
673
674 if (status & BIT_ADDR_CH_ERR_INT) {
675 imx7_csi_hw_disable(csi);
676
677 imx7_csi_dma_reflash(csi);
678
679 imx7_csi_hw_enable(csi);
680 }
681
682 if ((status & BIT_DMA_TSF_DONE_FB1) &&
683 (status & BIT_DMA_TSF_DONE_FB2)) {
684
685
686
687
688
689
690
691
692 } else if (status & BIT_DMA_TSF_DONE_FB1) {
693 csi->buf_num = 0;
694 } else if (status & BIT_DMA_TSF_DONE_FB2) {
695 csi->buf_num = 1;
696 }
697
698 if ((status & BIT_DMA_TSF_DONE_FB1) ||
699 (status & BIT_DMA_TSF_DONE_FB2)) {
700 imx7_csi_vb2_buf_done(csi);
701
702 if (csi->last_eof) {
703 complete(&csi->last_eof_completion);
704 csi->last_eof = false;
705 }
706 }
707
708 spin_unlock(&csi->irqlock);
709
710 return IRQ_HANDLED;
711}
712
713static int imx7_csi_dma_start(struct imx7_csi *csi)
714{
715 struct imx_media_video_dev *vdev = csi->vdev;
716 struct v4l2_pix_format *out_pix = &vdev->fmt.fmt.pix;
717 int ret;
718
719 ret = imx_media_alloc_dma_buf(csi->dev, &csi->underrun_buf,
720 out_pix->sizeimage);
721 if (ret < 0) {
722 v4l2_warn(&csi->sd, "consider increasing the CMA area\n");
723 return ret;
724 }
725
726 csi->frame_sequence = 0;
727 csi->last_eof = false;
728 init_completion(&csi->last_eof_completion);
729
730 imx7_csi_setup_vb2_buf(csi);
731
732 return 0;
733}
734
735static void imx7_csi_dma_stop(struct imx7_csi *csi)
736{
737 unsigned long timeout_jiffies;
738 unsigned long flags;
739 int ret;
740
741
742 spin_lock_irqsave(&csi->irqlock, flags);
743 csi->last_eof = true;
744 spin_unlock_irqrestore(&csi->irqlock, flags);
745
746
747
748
749 timeout_jiffies = msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT);
750 ret = wait_for_completion_timeout(&csi->last_eof_completion,
751 timeout_jiffies);
752 if (ret == 0)
753 v4l2_warn(&csi->sd, "wait last EOF timeout\n");
754
755 imx7_csi_hw_disable_irq(csi);
756
757 imx7_csi_dma_unsetup_vb2_buf(csi, VB2_BUF_STATE_ERROR);
758
759 imx_media_free_dma_buf(csi->dev, &csi->underrun_buf);
760}
761
762static int imx7_csi_configure(struct imx7_csi *csi)
763{
764 struct imx_media_video_dev *vdev = csi->vdev;
765 struct v4l2_pix_format *out_pix = &vdev->fmt.fmt.pix;
766 __u32 in_code = csi->format_mbus[IMX7_CSI_PAD_SINK].code;
767 u32 cr1, cr18;
768
769 if (out_pix->field == V4L2_FIELD_INTERLACED) {
770 imx7_csi_deinterlace_enable(csi, true);
771 imx7_csi_buf_stride_set(csi, out_pix->width);
772 } else {
773 imx7_csi_deinterlace_enable(csi, false);
774 imx7_csi_buf_stride_set(csi, 0);
775 }
776
777 imx7_csi_set_imagpara(csi, out_pix->width, out_pix->height);
778
779 if (!csi->is_csi2)
780 return 0;
781
782 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
783 cr1 &= ~BIT_GCLK_MODE;
784
785 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18);
786 cr18 &= BIT_MIPI_DATA_FORMAT_MASK;
787 cr18 |= BIT_DATA_FROM_MIPI;
788
789 switch (out_pix->pixelformat) {
790 case V4L2_PIX_FMT_UYVY:
791 case V4L2_PIX_FMT_YUYV:
792 cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B;
793 break;
794 case V4L2_PIX_FMT_SBGGR8:
795 cr18 |= BIT_MIPI_DATA_FORMAT_RAW8;
796 break;
797 case V4L2_PIX_FMT_SBGGR16:
798 if (in_code == MEDIA_BUS_FMT_SBGGR10_1X10)
799 cr18 |= BIT_MIPI_DATA_FORMAT_RAW10;
800 else if (in_code == MEDIA_BUS_FMT_SBGGR12_1X12)
801 cr18 |= BIT_MIPI_DATA_FORMAT_RAW12;
802 else if (in_code == MEDIA_BUS_FMT_SBGGR14_1X14)
803 cr18 |= BIT_MIPI_DATA_FORMAT_RAW14;
804 cr1 |= BIT_PIXEL_BIT;
805 break;
806 default:
807 return -EINVAL;
808 }
809
810 imx7_csi_reg_write(csi, cr1, CSI_CSICR1);
811 imx7_csi_reg_write(csi, cr18, CSI_CSICR18);
812
813 return 0;
814}
815
816static void imx7_csi_enable(struct imx7_csi *csi)
817{
818 imx7_csi_sw_reset(csi);
819
820 if (csi->is_csi2) {
821 imx7_csi_dmareq_rff_enable(csi);
822 imx7_csi_hw_enable_irq(csi);
823 imx7_csi_hw_enable(csi);
824 }
825}
826
827static void imx7_csi_disable(struct imx7_csi *csi)
828{
829 imx7_csi_dmareq_rff_disable(csi);
830
831 imx7_csi_hw_disable_irq(csi);
832
833 imx7_csi_buf_stride_set(csi, 0);
834
835 imx7_csi_hw_disable(csi);
836}
837
838static int imx7_csi_streaming_start(struct imx7_csi *csi)
839{
840 int ret;
841
842 ret = imx7_csi_dma_start(csi);
843 if (ret < 0)
844 return ret;
845
846 ret = imx7_csi_configure(csi);
847 if (ret < 0)
848 goto dma_stop;
849
850 imx7_csi_enable(csi);
851
852 return 0;
853
854dma_stop:
855 imx7_csi_dma_stop(csi);
856
857 return ret;
858}
859
860static int imx7_csi_streaming_stop(struct imx7_csi *csi)
861{
862 imx7_csi_dma_stop(csi);
863
864 imx7_csi_disable(csi);
865
866 return 0;
867}
868
869static int imx7_csi_s_stream(struct v4l2_subdev *sd, int enable)
870{
871 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
872 int ret = 0;
873
874 mutex_lock(&csi->lock);
875
876 if (!csi->src_sd || !csi->sink) {
877 ret = -EPIPE;
878 goto out_unlock;
879 }
880
881 if (csi->is_streaming == !!enable)
882 goto out_unlock;
883
884 if (enable) {
885 ret = v4l2_subdev_call(csi->src_sd, video, s_stream, 1);
886 if (ret < 0)
887 goto out_unlock;
888
889 ret = imx7_csi_streaming_start(csi);
890 if (ret < 0) {
891 v4l2_subdev_call(csi->src_sd, video, s_stream, 0);
892 goto out_unlock;
893 }
894 } else {
895 imx7_csi_streaming_stop(csi);
896
897 v4l2_subdev_call(csi->src_sd, video, s_stream, 0);
898 }
899
900 csi->is_streaming = !!enable;
901
902out_unlock:
903 mutex_unlock(&csi->lock);
904
905 return ret;
906}
907
908static struct v4l2_mbus_framefmt *
909imx7_csi_get_format(struct imx7_csi *csi,
910 struct v4l2_subdev_pad_config *cfg,
911 unsigned int pad,
912 enum v4l2_subdev_format_whence which)
913{
914 if (which == V4L2_SUBDEV_FORMAT_TRY)
915 return v4l2_subdev_get_try_format(&csi->sd, cfg, pad);
916
917 return &csi->format_mbus[pad];
918}
919
920static int imx7_csi_enum_mbus_code(struct v4l2_subdev *sd,
921 struct v4l2_subdev_pad_config *cfg,
922 struct v4l2_subdev_mbus_code_enum *code)
923{
924 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
925 struct v4l2_mbus_framefmt *in_fmt;
926 int ret = 0;
927
928 mutex_lock(&csi->lock);
929
930 in_fmt = imx7_csi_get_format(csi, cfg, IMX7_CSI_PAD_SINK, code->which);
931
932 switch (code->pad) {
933 case IMX7_CSI_PAD_SINK:
934 ret = imx_media_enum_mbus_format(&code->code, code->index,
935 CS_SEL_ANY, true);
936 break;
937 case IMX7_CSI_PAD_SRC:
938 if (code->index != 0) {
939 ret = -EINVAL;
940 goto out_unlock;
941 }
942
943 code->code = in_fmt->code;
944 break;
945 default:
946 ret = -EINVAL;
947 }
948
949out_unlock:
950 mutex_unlock(&csi->lock);
951
952 return ret;
953}
954
955static int imx7_csi_get_fmt(struct v4l2_subdev *sd,
956 struct v4l2_subdev_pad_config *cfg,
957 struct v4l2_subdev_format *sdformat)
958{
959 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
960 struct v4l2_mbus_framefmt *fmt;
961 int ret = 0;
962
963 mutex_lock(&csi->lock);
964
965 fmt = imx7_csi_get_format(csi, cfg, sdformat->pad, sdformat->which);
966 if (!fmt) {
967 ret = -EINVAL;
968 goto out_unlock;
969 }
970
971 sdformat->format = *fmt;
972
973out_unlock:
974 mutex_unlock(&csi->lock);
975
976 return ret;
977}
978
979static int imx7_csi_try_fmt(struct imx7_csi *csi,
980 struct v4l2_subdev_pad_config *cfg,
981 struct v4l2_subdev_format *sdformat,
982 const struct imx_media_pixfmt **cc)
983{
984 const struct imx_media_pixfmt *in_cc;
985 struct v4l2_mbus_framefmt *in_fmt;
986 u32 code;
987
988 in_fmt = imx7_csi_get_format(csi, cfg, IMX7_CSI_PAD_SINK,
989 sdformat->which);
990 if (!in_fmt)
991 return -EINVAL;
992
993 switch (sdformat->pad) {
994 case IMX7_CSI_PAD_SRC:
995 in_cc = imx_media_find_mbus_format(in_fmt->code, CS_SEL_ANY,
996 true);
997
998 sdformat->format.width = in_fmt->width;
999 sdformat->format.height = in_fmt->height;
1000 sdformat->format.code = in_fmt->code;
1001 *cc = in_cc;
1002
1003 sdformat->format.colorspace = in_fmt->colorspace;
1004 sdformat->format.xfer_func = in_fmt->xfer_func;
1005 break;
1006 case IMX7_CSI_PAD_SINK:
1007 *cc = imx_media_find_mbus_format(sdformat->format.code,
1008 CS_SEL_ANY, true);
1009 if (!*cc) {
1010 imx_media_enum_mbus_format(&code, 0, CS_SEL_ANY, false);
1011 *cc = imx_media_find_mbus_format(code, CS_SEL_ANY,
1012 false);
1013 sdformat->format.code = (*cc)->codes[0];
1014 }
1015 break;
1016 default:
1017 return -EINVAL;
1018 }
1019
1020 imx_media_try_colorimetry(&sdformat->format, false);
1021
1022 return 0;
1023}
1024
1025static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
1026 struct v4l2_subdev_pad_config *cfg,
1027 struct v4l2_subdev_format *sdformat)
1028{
1029 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
1030 const struct imx_media_pixfmt *outcc;
1031 struct v4l2_mbus_framefmt *outfmt;
1032 const struct imx_media_pixfmt *cc;
1033 struct v4l2_mbus_framefmt *fmt;
1034 struct v4l2_subdev_format format;
1035 int ret = 0;
1036
1037 if (sdformat->pad >= IMX7_CSI_PADS_NUM)
1038 return -EINVAL;
1039
1040 mutex_lock(&csi->lock);
1041
1042 if (csi->is_streaming) {
1043 ret = -EBUSY;
1044 goto out_unlock;
1045 }
1046
1047 ret = imx7_csi_try_fmt(csi, cfg, sdformat, &cc);
1048 if (ret < 0)
1049 goto out_unlock;
1050
1051 fmt = imx7_csi_get_format(csi, cfg, sdformat->pad, sdformat->which);
1052 if (!fmt) {
1053 ret = -EINVAL;
1054 goto out_unlock;
1055 }
1056
1057 *fmt = sdformat->format;
1058
1059 if (sdformat->pad == IMX7_CSI_PAD_SINK) {
1060
1061 format.pad = IMX7_CSI_PAD_SRC;
1062 format.which = sdformat->which;
1063 format.format = sdformat->format;
1064 if (imx7_csi_try_fmt(csi, cfg, &format, &outcc)) {
1065 ret = -EINVAL;
1066 goto out_unlock;
1067 }
1068 outfmt = imx7_csi_get_format(csi, cfg, IMX7_CSI_PAD_SRC,
1069 sdformat->which);
1070 *outfmt = format.format;
1071
1072 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1073 csi->cc[IMX7_CSI_PAD_SRC] = outcc;
1074 }
1075
1076 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1077 csi->cc[sdformat->pad] = cc;
1078
1079out_unlock:
1080 mutex_unlock(&csi->lock);
1081
1082 return ret;
1083}
1084
1085static int imx7_csi_registered(struct v4l2_subdev *sd)
1086{
1087 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
1088 int ret;
1089 int i;
1090
1091 for (i = 0; i < IMX7_CSI_PADS_NUM; i++) {
1092 csi->pad[i].flags = (i == IMX7_CSI_PAD_SINK) ?
1093 MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
1094
1095
1096 ret = imx_media_init_mbus_fmt(&csi->format_mbus[i],
1097 800, 600, 0, V4L2_FIELD_NONE,
1098 &csi->cc[i]);
1099 if (ret < 0)
1100 return ret;
1101
1102
1103 csi->frame_interval[i].numerator = 1;
1104 csi->frame_interval[i].denominator = 30;
1105 }
1106
1107 ret = media_entity_pads_init(&sd->entity, IMX7_CSI_PADS_NUM, csi->pad);
1108 if (ret < 0)
1109 return ret;
1110
1111 return imx_media_capture_device_register(csi->vdev);
1112}
1113
1114static void imx7_csi_unregistered(struct v4l2_subdev *sd)
1115{
1116 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
1117
1118 imx_media_capture_device_unregister(csi->vdev);
1119}
1120
1121static int imx7_csi_init_cfg(struct v4l2_subdev *sd,
1122 struct v4l2_subdev_pad_config *cfg)
1123{
1124 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
1125 struct v4l2_mbus_framefmt *mf;
1126 int ret;
1127 int i;
1128
1129 for (i = 0; i < IMX7_CSI_PADS_NUM; i++) {
1130 mf = v4l2_subdev_get_try_format(sd, cfg, i);
1131
1132 ret = imx_media_init_mbus_fmt(mf, 800, 600, 0, V4L2_FIELD_NONE,
1133 &csi->cc[i]);
1134 if (ret < 0)
1135 return ret;
1136 }
1137
1138 return 0;
1139}
1140
1141static const struct media_entity_operations imx7_csi_entity_ops = {
1142 .link_setup = imx7_csi_link_setup,
1143 .link_validate = v4l2_subdev_link_validate,
1144};
1145
1146static const struct v4l2_subdev_video_ops imx7_csi_video_ops = {
1147 .s_stream = imx7_csi_s_stream,
1148};
1149
1150static const struct v4l2_subdev_pad_ops imx7_csi_pad_ops = {
1151 .init_cfg = imx7_csi_init_cfg,
1152 .enum_mbus_code = imx7_csi_enum_mbus_code,
1153 .get_fmt = imx7_csi_get_fmt,
1154 .set_fmt = imx7_csi_set_fmt,
1155 .link_validate = imx7_csi_pad_link_validate,
1156};
1157
1158static const struct v4l2_subdev_ops imx7_csi_subdev_ops = {
1159 .video = &imx7_csi_video_ops,
1160 .pad = &imx7_csi_pad_ops,
1161};
1162
1163static const struct v4l2_subdev_internal_ops imx7_csi_internal_ops = {
1164 .registered = imx7_csi_registered,
1165 .unregistered = imx7_csi_unregistered,
1166};
1167
1168static int imx7_csi_parse_endpoint(struct device *dev,
1169 struct v4l2_fwnode_endpoint *vep,
1170 struct v4l2_async_subdev *asd)
1171{
1172 return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
1173}
1174
1175static int imx7_csi_probe(struct platform_device *pdev)
1176{
1177 struct device *dev = &pdev->dev;
1178 struct device_node *node = dev->of_node;
1179 struct imx_media_dev *imxmd;
1180 struct imx7_csi *csi;
1181 int ret;
1182
1183 csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL);
1184 if (!csi)
1185 return -ENOMEM;
1186
1187 csi->dev = dev;
1188
1189 csi->mclk = devm_clk_get(&pdev->dev, "mclk");
1190 if (IS_ERR(csi->mclk)) {
1191 ret = PTR_ERR(csi->mclk);
1192 dev_err(dev, "Failed to get mclk: %d", ret);
1193 return ret;
1194 }
1195
1196 csi->irq = platform_get_irq(pdev, 0);
1197 if (csi->irq < 0) {
1198 dev_err(dev, "Missing platform resources data\n");
1199 return csi->irq;
1200 }
1201
1202 csi->regbase = devm_platform_ioremap_resource(pdev, 0);
1203 if (IS_ERR(csi->regbase))
1204 return PTR_ERR(csi->regbase);
1205
1206 spin_lock_init(&csi->irqlock);
1207 mutex_init(&csi->lock);
1208
1209
1210 ret = devm_request_irq(dev, csi->irq, imx7_csi_irq_handler, 0, "csi",
1211 (void *)csi);
1212 if (ret < 0) {
1213 dev_err(dev, "Request CSI IRQ failed.\n");
1214 goto destroy_mutex;
1215 }
1216
1217
1218 imxmd = imx_media_dev_init(dev, NULL);
1219 if (IS_ERR(imxmd)) {
1220 ret = PTR_ERR(imxmd);
1221 goto destroy_mutex;
1222 }
1223 platform_set_drvdata(pdev, &csi->sd);
1224
1225 ret = imx_media_of_add_csi(imxmd, node);
1226 if (ret < 0 && ret != -ENODEV && ret != -EEXIST)
1227 goto cleanup;
1228
1229 ret = imx_media_dev_notifier_register(imxmd, NULL);
1230 if (ret < 0)
1231 goto cleanup;
1232
1233 csi->imxmd = imxmd;
1234 v4l2_subdev_init(&csi->sd, &imx7_csi_subdev_ops);
1235 v4l2_set_subdevdata(&csi->sd, csi);
1236 csi->sd.internal_ops = &imx7_csi_internal_ops;
1237 csi->sd.entity.ops = &imx7_csi_entity_ops;
1238 csi->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
1239 csi->sd.dev = &pdev->dev;
1240 csi->sd.owner = THIS_MODULE;
1241 csi->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
1242 csi->sd.grp_id = IMX_MEDIA_GRP_ID_CSI;
1243 snprintf(csi->sd.name, sizeof(csi->sd.name), "csi");
1244
1245 csi->vdev = imx_media_capture_device_init(csi->sd.dev, &csi->sd,
1246 IMX7_CSI_PAD_SRC);
1247 if (IS_ERR(csi->vdev))
1248 return PTR_ERR(csi->vdev);
1249
1250 v4l2_ctrl_handler_init(&csi->ctrl_hdlr, 0);
1251 csi->sd.ctrl_handler = &csi->ctrl_hdlr;
1252
1253 ret = v4l2_async_register_fwnode_subdev(&csi->sd,
1254 sizeof(struct v4l2_async_subdev),
1255 NULL, 0,
1256 imx7_csi_parse_endpoint);
1257 if (ret)
1258 goto free;
1259
1260 return 0;
1261
1262free:
1263 imx_media_capture_device_unregister(csi->vdev);
1264 imx_media_capture_device_remove(csi->vdev);
1265 v4l2_ctrl_handler_free(&csi->ctrl_hdlr);
1266
1267cleanup:
1268 v4l2_async_notifier_cleanup(&imxmd->notifier);
1269 v4l2_device_unregister(&imxmd->v4l2_dev);
1270 media_device_unregister(&imxmd->md);
1271 media_device_cleanup(&imxmd->md);
1272
1273destroy_mutex:
1274 mutex_destroy(&csi->lock);
1275
1276 return ret;
1277}
1278
1279static int imx7_csi_remove(struct platform_device *pdev)
1280{
1281 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
1282 struct imx7_csi *csi = v4l2_get_subdevdata(sd);
1283 struct imx_media_dev *imxmd = csi->imxmd;
1284
1285 v4l2_async_notifier_unregister(&imxmd->notifier);
1286 v4l2_async_notifier_cleanup(&imxmd->notifier);
1287
1288 media_device_unregister(&imxmd->md);
1289 v4l2_device_unregister(&imxmd->v4l2_dev);
1290 media_device_cleanup(&imxmd->md);
1291
1292 imx_media_capture_device_unregister(csi->vdev);
1293 imx_media_capture_device_remove(csi->vdev);
1294
1295 v4l2_async_unregister_subdev(sd);
1296 v4l2_ctrl_handler_free(&csi->ctrl_hdlr);
1297
1298 mutex_destroy(&csi->lock);
1299
1300 return 0;
1301}
1302
1303static const struct of_device_id imx7_csi_of_match[] = {
1304 { .compatible = "fsl,imx7-csi" },
1305 { },
1306};
1307MODULE_DEVICE_TABLE(of, imx7_csi_of_match);
1308
1309static struct platform_driver imx7_csi_driver = {
1310 .probe = imx7_csi_probe,
1311 .remove = imx7_csi_remove,
1312 .driver = {
1313 .of_match_table = imx7_csi_of_match,
1314 .name = "imx7-csi",
1315 },
1316};
1317module_platform_driver(imx7_csi_driver);
1318
1319MODULE_DESCRIPTION("i.MX7 CSI subdev driver");
1320MODULE_AUTHOR("Rui Miguel Silva <rui.silva@linaro.org>");
1321MODULE_LICENSE("GPL v2");
1322MODULE_ALIAS("platform:imx7-csi");
1323