1
2
3
4
5
6
7
8
9
10
11#include <linux/delay.h>
12#include <linux/interrupt.h>
13#include <linux/module.h>
14#include <linux/sched.h>
15#include <linux/slab.h>
16#include <linux/spinlock.h>
17#include <linux/timer.h>
18#include <media/v4l2-ctrls.h>
19#include <media/v4l2-device.h>
20#include <media/v4l2-ioctl.h>
21#include <media/v4l2-mc.h>
22#include <media/v4l2-subdev.h>
23#include <media/imx.h>
24#include "imx-media.h"
25#include "imx-ic.h"
26
27
28
29
30
31
32
33
34
35
36
37
38#define MIN_W_SINK 32
39#define MIN_H_SINK 32
40#define MAX_W_SINK 4096
41#define MAX_H_SINK 4096
42#define W_ALIGN_SINK 3
43#define H_ALIGN_SINK 1
44
45#define MAX_W_SRC 1024
46#define MAX_H_SRC 1024
47#define W_ALIGN_SRC 1
48#define H_ALIGN_SRC 1
49
50#define S_ALIGN 1
51
52struct prp_priv {
53 struct imx_ic_priv *ic_priv;
54 struct media_pad pad[PRPENCVF_NUM_PADS];
55
56 struct imx_media_video_dev *vdev;
57
58
59 struct mutex lock;
60
61
62 struct ipu_ic *ic;
63 struct ipuv3_channel *out_ch;
64 struct ipuv3_channel *rot_in_ch;
65 struct ipuv3_channel *rot_out_ch;
66
67
68 struct imx_media_buffer *active_vb2_buf[2];
69 struct imx_media_dma_buf underrun_buf;
70
71 int ipu_buf_num;
72
73
74 struct media_entity *sink;
75
76 struct v4l2_subdev *src_sd;
77
78 struct v4l2_mbus_framefmt format_mbus[PRPENCVF_NUM_PADS];
79 const struct imx_media_pixfmt *cc[PRPENCVF_NUM_PADS];
80 struct v4l2_fract frame_interval;
81
82 struct imx_media_dma_buf rot_buf[2];
83
84
85 struct v4l2_ctrl_handler ctrl_hdlr;
86 int rotation;
87 bool hflip;
88 bool vflip;
89
90
91 enum ipu_rotate_mode rot_mode;
92
93 spinlock_t irqlock;
94
95 struct timer_list eof_timeout_timer;
96 int eof_irq;
97 int nfb4eof_irq;
98
99 int stream_count;
100 u32 frame_sequence;
101 bool last_eof;
102 bool nfb4eof;
103 bool interweave_swap;
104 struct completion last_eof_comp;
105};
106
107static const struct prp_channels {
108 u32 out_ch;
109 u32 rot_in_ch;
110 u32 rot_out_ch;
111} prp_channel[] = {
112 [IC_TASK_ENCODER] = {
113 .out_ch = IPUV3_CHANNEL_IC_PRP_ENC_MEM,
114 .rot_in_ch = IPUV3_CHANNEL_MEM_ROT_ENC,
115 .rot_out_ch = IPUV3_CHANNEL_ROT_ENC_MEM,
116 },
117 [IC_TASK_VIEWFINDER] = {
118 .out_ch = IPUV3_CHANNEL_IC_PRP_VF_MEM,
119 .rot_in_ch = IPUV3_CHANNEL_MEM_ROT_VF,
120 .rot_out_ch = IPUV3_CHANNEL_ROT_VF_MEM,
121 },
122};
123
124static inline struct prp_priv *sd_to_priv(struct v4l2_subdev *sd)
125{
126 struct imx_ic_priv *ic_priv = v4l2_get_subdevdata(sd);
127
128 return ic_priv->task_priv;
129}
130
131static void prp_put_ipu_resources(struct prp_priv *priv)
132{
133 if (priv->ic)
134 ipu_ic_put(priv->ic);
135 priv->ic = NULL;
136
137 if (priv->out_ch)
138 ipu_idmac_put(priv->out_ch);
139 priv->out_ch = NULL;
140
141 if (priv->rot_in_ch)
142 ipu_idmac_put(priv->rot_in_ch);
143 priv->rot_in_ch = NULL;
144
145 if (priv->rot_out_ch)
146 ipu_idmac_put(priv->rot_out_ch);
147 priv->rot_out_ch = NULL;
148}
149
150static int prp_get_ipu_resources(struct prp_priv *priv)
151{
152 struct imx_ic_priv *ic_priv = priv->ic_priv;
153 struct ipu_ic *ic;
154 struct ipuv3_channel *out_ch, *rot_in_ch, *rot_out_ch;
155 int ret, task = ic_priv->task_id;
156
157 ic = ipu_ic_get(ic_priv->ipu, task);
158 if (IS_ERR(ic)) {
159 v4l2_err(&ic_priv->sd, "failed to get IC\n");
160 ret = PTR_ERR(ic);
161 goto out;
162 }
163 priv->ic = ic;
164
165 out_ch = ipu_idmac_get(ic_priv->ipu, prp_channel[task].out_ch);
166 if (IS_ERR(out_ch)) {
167 v4l2_err(&ic_priv->sd, "could not get IDMAC channel %u\n",
168 prp_channel[task].out_ch);
169 ret = PTR_ERR(out_ch);
170 goto out;
171 }
172 priv->out_ch = out_ch;
173
174 rot_in_ch = ipu_idmac_get(ic_priv->ipu, prp_channel[task].rot_in_ch);
175 if (IS_ERR(rot_in_ch)) {
176 v4l2_err(&ic_priv->sd, "could not get IDMAC channel %u\n",
177 prp_channel[task].rot_in_ch);
178 ret = PTR_ERR(rot_in_ch);
179 goto out;
180 }
181 priv->rot_in_ch = rot_in_ch;
182
183 rot_out_ch = ipu_idmac_get(ic_priv->ipu, prp_channel[task].rot_out_ch);
184 if (IS_ERR(rot_out_ch)) {
185 v4l2_err(&ic_priv->sd, "could not get IDMAC channel %u\n",
186 prp_channel[task].rot_out_ch);
187 ret = PTR_ERR(rot_out_ch);
188 goto out;
189 }
190 priv->rot_out_ch = rot_out_ch;
191
192 return 0;
193out:
194 prp_put_ipu_resources(priv);
195 return ret;
196}
197
198static void prp_vb2_buf_done(struct prp_priv *priv, struct ipuv3_channel *ch)
199{
200 struct imx_media_video_dev *vdev = priv->vdev;
201 struct imx_media_buffer *done, *next;
202 struct vb2_buffer *vb;
203 dma_addr_t phys;
204
205 done = priv->active_vb2_buf[priv->ipu_buf_num];
206 if (done) {
207 done->vbuf.field = vdev->fmt.fmt.pix.field;
208 done->vbuf.sequence = priv->frame_sequence;
209 vb = &done->vbuf.vb2_buf;
210 vb->timestamp = ktime_get_ns();
211 vb2_buffer_done(vb, priv->nfb4eof ?
212 VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
213 }
214
215 priv->frame_sequence++;
216 priv->nfb4eof = false;
217
218
219 next = imx_media_capture_device_next_buf(vdev);
220 if (next) {
221 phys = vb2_dma_contig_plane_dma_addr(&next->vbuf.vb2_buf, 0);
222 priv->active_vb2_buf[priv->ipu_buf_num] = next;
223 } else {
224 phys = priv->underrun_buf.phys;
225 priv->active_vb2_buf[priv->ipu_buf_num] = NULL;
226 }
227
228 if (ipu_idmac_buffer_is_ready(ch, priv->ipu_buf_num))
229 ipu_idmac_clear_buffer(ch, priv->ipu_buf_num);
230
231 if (priv->interweave_swap && ch == priv->out_ch)
232 phys += vdev->fmt.fmt.pix.bytesperline;
233
234 ipu_cpmem_set_buffer(ch, priv->ipu_buf_num, phys);
235}
236
237static irqreturn_t prp_eof_interrupt(int irq, void *dev_id)
238{
239 struct prp_priv *priv = dev_id;
240 struct ipuv3_channel *channel;
241
242 spin_lock(&priv->irqlock);
243
244 if (priv->last_eof) {
245 complete(&priv->last_eof_comp);
246 priv->last_eof = false;
247 goto unlock;
248 }
249
250 channel = (ipu_rot_mode_is_irt(priv->rot_mode)) ?
251 priv->rot_out_ch : priv->out_ch;
252
253 prp_vb2_buf_done(priv, channel);
254
255
256 ipu_idmac_select_buffer(channel, priv->ipu_buf_num);
257
258 priv->ipu_buf_num ^= 1;
259
260
261 mod_timer(&priv->eof_timeout_timer,
262 jiffies + msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
263
264unlock:
265 spin_unlock(&priv->irqlock);
266 return IRQ_HANDLED;
267}
268
269static irqreturn_t prp_nfb4eof_interrupt(int irq, void *dev_id)
270{
271 struct prp_priv *priv = dev_id;
272 struct imx_ic_priv *ic_priv = priv->ic_priv;
273
274 spin_lock(&priv->irqlock);
275
276
277
278
279
280 priv->nfb4eof = true;
281
282 v4l2_err(&ic_priv->sd, "NFB4EOF\n");
283
284 spin_unlock(&priv->irqlock);
285
286 return IRQ_HANDLED;
287}
288
289
290
291
292
293
294
295
296static void prp_eof_timeout(struct timer_list *t)
297{
298 struct prp_priv *priv = from_timer(priv, t, eof_timeout_timer);
299 struct imx_media_video_dev *vdev = priv->vdev;
300 struct imx_ic_priv *ic_priv = priv->ic_priv;
301
302 v4l2_err(&ic_priv->sd, "EOF timeout\n");
303
304
305 imx_media_capture_device_error(vdev);
306}
307
308static void prp_setup_vb2_buf(struct prp_priv *priv, dma_addr_t *phys)
309{
310 struct imx_media_video_dev *vdev = priv->vdev;
311 struct imx_media_buffer *buf;
312 int i;
313
314 for (i = 0; i < 2; i++) {
315 buf = imx_media_capture_device_next_buf(vdev);
316 if (buf) {
317 priv->active_vb2_buf[i] = buf;
318 phys[i] = vb2_dma_contig_plane_dma_addr(
319 &buf->vbuf.vb2_buf, 0);
320 } else {
321 priv->active_vb2_buf[i] = NULL;
322 phys[i] = priv->underrun_buf.phys;
323 }
324 }
325}
326
327static void prp_unsetup_vb2_buf(struct prp_priv *priv,
328 enum vb2_buffer_state return_status)
329{
330 struct imx_media_buffer *buf;
331 int i;
332
333
334 for (i = 0; i < 2; i++) {
335 buf = priv->active_vb2_buf[i];
336 if (buf) {
337 struct vb2_buffer *vb = &buf->vbuf.vb2_buf;
338
339 vb->timestamp = ktime_get_ns();
340 vb2_buffer_done(vb, return_status);
341 }
342 }
343}
344
345static int prp_setup_channel(struct prp_priv *priv,
346 struct ipuv3_channel *channel,
347 enum ipu_rotate_mode rot_mode,
348 dma_addr_t addr0, dma_addr_t addr1,
349 bool rot_swap_width_height)
350{
351 struct imx_media_video_dev *vdev = priv->vdev;
352 const struct imx_media_pixfmt *outcc;
353 struct v4l2_mbus_framefmt *outfmt;
354 unsigned int burst_size;
355 struct ipu_image image;
356 bool interweave;
357 int ret;
358
359 outfmt = &priv->format_mbus[PRPENCVF_SRC_PAD];
360 outcc = vdev->cc;
361
362 ipu_cpmem_zero(channel);
363
364 memset(&image, 0, sizeof(image));
365 image.pix = vdev->fmt.fmt.pix;
366 image.rect = vdev->compose;
367
368
369
370
371
372
373 interweave = V4L2_FIELD_IS_INTERLACED(image.pix.field) &&
374 V4L2_FIELD_IS_SEQUENTIAL(outfmt->field);
375 priv->interweave_swap = interweave &&
376 image.pix.field == V4L2_FIELD_INTERLACED_BT;
377
378 if (rot_swap_width_height) {
379 swap(image.pix.width, image.pix.height);
380 swap(image.rect.width, image.rect.height);
381
382 image.pix.bytesperline = outcc->planar ?
383 image.pix.width :
384 (image.pix.width * outcc->bpp) >> 3;
385 }
386
387 if (priv->interweave_swap && channel == priv->out_ch) {
388
389 image.rect.top = 1;
390 }
391
392 image.phys0 = addr0;
393 image.phys1 = addr1;
394
395
396
397
398
399
400 if ((channel == priv->out_ch && !interweave) ||
401 channel == priv->rot_out_ch) {
402 switch (image.pix.pixelformat) {
403 case V4L2_PIX_FMT_YUV420:
404 case V4L2_PIX_FMT_YVU420:
405 case V4L2_PIX_FMT_NV12:
406 ipu_cpmem_skip_odd_chroma_rows(channel);
407 break;
408 }
409 }
410
411 ret = ipu_cpmem_set_image(channel, &image);
412 if (ret)
413 return ret;
414
415 if (channel == priv->rot_in_ch ||
416 channel == priv->rot_out_ch) {
417 burst_size = 8;
418 ipu_cpmem_set_block_mode(channel);
419 } else {
420 burst_size = (image.pix.width & 0xf) ? 8 : 16;
421 }
422
423 ipu_cpmem_set_burstsize(channel, burst_size);
424
425 if (rot_mode)
426 ipu_cpmem_set_rotation(channel, rot_mode);
427
428 if (interweave && channel == priv->out_ch)
429 ipu_cpmem_interlaced_scan(channel,
430 priv->interweave_swap ?
431 -image.pix.bytesperline :
432 image.pix.bytesperline,
433 image.pix.pixelformat);
434
435 ret = ipu_ic_task_idma_init(priv->ic, channel,
436 image.pix.width, image.pix.height,
437 burst_size, rot_mode);
438 if (ret)
439 return ret;
440
441 ipu_cpmem_set_axi_id(channel, 1);
442
443 ipu_idmac_set_double_buffer(channel, true);
444
445 return 0;
446}
447
448static int prp_setup_rotation(struct prp_priv *priv)
449{
450 struct imx_media_video_dev *vdev = priv->vdev;
451 struct imx_ic_priv *ic_priv = priv->ic_priv;
452 const struct imx_media_pixfmt *outcc, *incc;
453 struct v4l2_mbus_framefmt *infmt;
454 struct v4l2_pix_format *outfmt;
455 struct ipu_ic_csc csc;
456 dma_addr_t phys[2];
457 int ret;
458
459 infmt = &priv->format_mbus[PRPENCVF_SINK_PAD];
460 outfmt = &vdev->fmt.fmt.pix;
461 incc = priv->cc[PRPENCVF_SINK_PAD];
462 outcc = vdev->cc;
463
464 ret = ipu_ic_calc_csc(&csc,
465 infmt->ycbcr_enc, infmt->quantization,
466 incc->cs,
467 outfmt->ycbcr_enc, outfmt->quantization,
468 outcc->cs);
469 if (ret) {
470 v4l2_err(&ic_priv->sd, "ipu_ic_calc_csc failed, %d\n",
471 ret);
472 return ret;
473 }
474
475 ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0],
476 outfmt->sizeimage);
477 if (ret) {
478 v4l2_err(&ic_priv->sd, "failed to alloc rot_buf[0], %d\n", ret);
479 return ret;
480 }
481 ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1],
482 outfmt->sizeimage);
483 if (ret) {
484 v4l2_err(&ic_priv->sd, "failed to alloc rot_buf[1], %d\n", ret);
485 goto free_rot0;
486 }
487
488 ret = ipu_ic_task_init(priv->ic, &csc,
489 infmt->width, infmt->height,
490 outfmt->height, outfmt->width);
491 if (ret) {
492 v4l2_err(&ic_priv->sd, "ipu_ic_task_init failed, %d\n", ret);
493 goto free_rot1;
494 }
495
496
497 ret = prp_setup_channel(priv, priv->out_ch, IPU_ROTATE_NONE,
498 priv->rot_buf[0].phys, priv->rot_buf[1].phys,
499 true);
500 if (ret) {
501 v4l2_err(&ic_priv->sd,
502 "prp_setup_channel(out_ch) failed, %d\n", ret);
503 goto free_rot1;
504 }
505
506
507 ret = prp_setup_channel(priv, priv->rot_in_ch, priv->rot_mode,
508 priv->rot_buf[0].phys, priv->rot_buf[1].phys,
509 true);
510 if (ret) {
511 v4l2_err(&ic_priv->sd,
512 "prp_setup_channel(rot_in_ch) failed, %d\n", ret);
513 goto free_rot1;
514 }
515
516 prp_setup_vb2_buf(priv, phys);
517
518
519 ret = prp_setup_channel(priv, priv->rot_out_ch, IPU_ROTATE_NONE,
520 phys[0], phys[1],
521 false);
522 if (ret) {
523 v4l2_err(&ic_priv->sd,
524 "prp_setup_channel(rot_out_ch) failed, %d\n", ret);
525 goto unsetup_vb2;
526 }
527
528
529 ipu_idmac_link(priv->out_ch, priv->rot_in_ch);
530
531
532 ipu_ic_enable(priv->ic);
533
534
535 ipu_idmac_select_buffer(priv->out_ch, 0);
536 ipu_idmac_select_buffer(priv->out_ch, 1);
537 ipu_idmac_select_buffer(priv->rot_out_ch, 0);
538 ipu_idmac_select_buffer(priv->rot_out_ch, 1);
539
540
541 ipu_idmac_enable_channel(priv->out_ch);
542 ipu_idmac_enable_channel(priv->rot_in_ch);
543 ipu_idmac_enable_channel(priv->rot_out_ch);
544
545
546 ipu_ic_task_enable(priv->ic);
547
548 return 0;
549
550unsetup_vb2:
551 prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
552free_rot1:
553 imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1]);
554free_rot0:
555 imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0]);
556 return ret;
557}
558
559static void prp_unsetup_rotation(struct prp_priv *priv)
560{
561 struct imx_ic_priv *ic_priv = priv->ic_priv;
562
563 ipu_ic_task_disable(priv->ic);
564
565 ipu_idmac_disable_channel(priv->out_ch);
566 ipu_idmac_disable_channel(priv->rot_in_ch);
567 ipu_idmac_disable_channel(priv->rot_out_ch);
568
569 ipu_idmac_unlink(priv->out_ch, priv->rot_in_ch);
570
571 ipu_ic_disable(priv->ic);
572
573 imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0]);
574 imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1]);
575}
576
577static int prp_setup_norotation(struct prp_priv *priv)
578{
579 struct imx_media_video_dev *vdev = priv->vdev;
580 struct imx_ic_priv *ic_priv = priv->ic_priv;
581 const struct imx_media_pixfmt *outcc, *incc;
582 struct v4l2_mbus_framefmt *infmt;
583 struct v4l2_pix_format *outfmt;
584 struct ipu_ic_csc csc;
585 dma_addr_t phys[2];
586 int ret;
587
588 infmt = &priv->format_mbus[PRPENCVF_SINK_PAD];
589 outfmt = &vdev->fmt.fmt.pix;
590 incc = priv->cc[PRPENCVF_SINK_PAD];
591 outcc = vdev->cc;
592
593 ret = ipu_ic_calc_csc(&csc,
594 infmt->ycbcr_enc, infmt->quantization,
595 incc->cs,
596 outfmt->ycbcr_enc, outfmt->quantization,
597 outcc->cs);
598 if (ret) {
599 v4l2_err(&ic_priv->sd, "ipu_ic_calc_csc failed, %d\n",
600 ret);
601 return ret;
602 }
603
604 ret = ipu_ic_task_init(priv->ic, &csc,
605 infmt->width, infmt->height,
606 outfmt->width, outfmt->height);
607 if (ret) {
608 v4l2_err(&ic_priv->sd, "ipu_ic_task_init failed, %d\n", ret);
609 return ret;
610 }
611
612 prp_setup_vb2_buf(priv, phys);
613
614
615 ret = prp_setup_channel(priv, priv->out_ch, priv->rot_mode,
616 phys[0], phys[1], false);
617 if (ret) {
618 v4l2_err(&ic_priv->sd,
619 "prp_setup_channel(out_ch) failed, %d\n", ret);
620 goto unsetup_vb2;
621 }
622
623 ipu_cpmem_dump(priv->out_ch);
624 ipu_ic_dump(priv->ic);
625 ipu_dump(ic_priv->ipu);
626
627 ipu_ic_enable(priv->ic);
628
629
630 ipu_idmac_select_buffer(priv->out_ch, 0);
631 ipu_idmac_select_buffer(priv->out_ch, 1);
632
633
634 ipu_idmac_enable_channel(priv->out_ch);
635
636
637 ipu_ic_task_enable(priv->ic);
638
639 return 0;
640
641unsetup_vb2:
642 prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
643 return ret;
644}
645
646static void prp_unsetup_norotation(struct prp_priv *priv)
647{
648 ipu_ic_task_disable(priv->ic);
649 ipu_idmac_disable_channel(priv->out_ch);
650 ipu_ic_disable(priv->ic);
651}
652
653static void prp_unsetup(struct prp_priv *priv,
654 enum vb2_buffer_state state)
655{
656 if (ipu_rot_mode_is_irt(priv->rot_mode))
657 prp_unsetup_rotation(priv);
658 else
659 prp_unsetup_norotation(priv);
660
661 prp_unsetup_vb2_buf(priv, state);
662}
663
664static int prp_start(struct prp_priv *priv)
665{
666 struct imx_ic_priv *ic_priv = priv->ic_priv;
667 struct imx_media_video_dev *vdev = priv->vdev;
668 struct v4l2_pix_format *outfmt;
669 int ret;
670
671 ret = prp_get_ipu_resources(priv);
672 if (ret)
673 return ret;
674
675 outfmt = &vdev->fmt.fmt.pix;
676
677 ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf,
678 outfmt->sizeimage);
679 if (ret)
680 goto out_put_ipu;
681
682 priv->ipu_buf_num = 0;
683
684
685 init_completion(&priv->last_eof_comp);
686 priv->frame_sequence = 0;
687 priv->last_eof = false;
688 priv->nfb4eof = false;
689
690 if (ipu_rot_mode_is_irt(priv->rot_mode))
691 ret = prp_setup_rotation(priv);
692 else
693 ret = prp_setup_norotation(priv);
694 if (ret)
695 goto out_free_underrun;
696
697 priv->nfb4eof_irq = ipu_idmac_channel_irq(ic_priv->ipu,
698 priv->out_ch,
699 IPU_IRQ_NFB4EOF);
700 ret = devm_request_irq(ic_priv->ipu_dev, priv->nfb4eof_irq,
701 prp_nfb4eof_interrupt, 0,
702 "imx-ic-prp-nfb4eof", priv);
703 if (ret) {
704 v4l2_err(&ic_priv->sd,
705 "Error registering NFB4EOF irq: %d\n", ret);
706 goto out_unsetup;
707 }
708
709 if (ipu_rot_mode_is_irt(priv->rot_mode))
710 priv->eof_irq = ipu_idmac_channel_irq(
711 ic_priv->ipu, priv->rot_out_ch, IPU_IRQ_EOF);
712 else
713 priv->eof_irq = ipu_idmac_channel_irq(
714 ic_priv->ipu, priv->out_ch, IPU_IRQ_EOF);
715
716 ret = devm_request_irq(ic_priv->ipu_dev, priv->eof_irq,
717 prp_eof_interrupt, 0,
718 "imx-ic-prp-eof", priv);
719 if (ret) {
720 v4l2_err(&ic_priv->sd,
721 "Error registering eof irq: %d\n", ret);
722 goto out_free_nfb4eof_irq;
723 }
724
725
726 ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 1);
727 ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
728 if (ret) {
729 v4l2_err(&ic_priv->sd,
730 "upstream stream on failed: %d\n", ret);
731 goto out_free_eof_irq;
732 }
733
734
735 mod_timer(&priv->eof_timeout_timer,
736 jiffies + msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
737
738 return 0;
739
740out_free_eof_irq:
741 devm_free_irq(ic_priv->ipu_dev, priv->eof_irq, priv);
742out_free_nfb4eof_irq:
743 devm_free_irq(ic_priv->ipu_dev, priv->nfb4eof_irq, priv);
744out_unsetup:
745 prp_unsetup(priv, VB2_BUF_STATE_QUEUED);
746out_free_underrun:
747 imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf);
748out_put_ipu:
749 prp_put_ipu_resources(priv);
750 return ret;
751}
752
753static void prp_stop(struct prp_priv *priv)
754{
755 struct imx_ic_priv *ic_priv = priv->ic_priv;
756 unsigned long flags;
757 int ret;
758
759
760 spin_lock_irqsave(&priv->irqlock, flags);
761 priv->last_eof = true;
762 spin_unlock_irqrestore(&priv->irqlock, flags);
763
764
765
766
767 ret = wait_for_completion_timeout(
768 &priv->last_eof_comp,
769 msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
770 if (ret == 0)
771 v4l2_warn(&ic_priv->sd, "wait last EOF timeout\n");
772
773
774 ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
775 if (ret && ret != -ENOIOCTLCMD)
776 v4l2_warn(&ic_priv->sd,
777 "upstream stream off failed: %d\n", ret);
778
779 devm_free_irq(ic_priv->ipu_dev, priv->eof_irq, priv);
780 devm_free_irq(ic_priv->ipu_dev, priv->nfb4eof_irq, priv);
781
782 prp_unsetup(priv, VB2_BUF_STATE_ERROR);
783
784 imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf);
785
786
787 del_timer_sync(&priv->eof_timeout_timer);
788
789 prp_put_ipu_resources(priv);
790}
791
792static struct v4l2_mbus_framefmt *
793__prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_pad_config *cfg,
794 unsigned int pad, enum v4l2_subdev_format_whence which)
795{
796 struct imx_ic_priv *ic_priv = priv->ic_priv;
797
798 if (which == V4L2_SUBDEV_FORMAT_TRY)
799 return v4l2_subdev_get_try_format(&ic_priv->sd, cfg, pad);
800 else
801 return &priv->format_mbus[pad];
802}
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817static bool prp_bound_align_output(struct v4l2_mbus_framefmt *outfmt,
818 struct v4l2_mbus_framefmt *infmt,
819 enum ipu_rotate_mode rot_mode)
820{
821 u32 orig_width = outfmt->width;
822 u32 orig_height = outfmt->height;
823
824 if (ipu_rot_mode_is_irt(rot_mode))
825 v4l_bound_align_image(&outfmt->width,
826 infmt->height / 4, MAX_H_SRC,
827 W_ALIGN_SRC,
828 &outfmt->height,
829 infmt->width / 4, MAX_W_SRC,
830 W_ALIGN_SRC, S_ALIGN);
831 else
832 v4l_bound_align_image(&outfmt->width,
833 infmt->width / 4, MAX_W_SRC,
834 W_ALIGN_SRC,
835 &outfmt->height,
836 infmt->height / 4, MAX_H_SRC,
837 H_ALIGN_SRC, S_ALIGN);
838
839 return outfmt->width != orig_width || outfmt->height != orig_height;
840}
841
842
843
844
845
846static int prp_enum_mbus_code(struct v4l2_subdev *sd,
847 struct v4l2_subdev_pad_config *cfg,
848 struct v4l2_subdev_mbus_code_enum *code)
849{
850 if (code->pad >= PRPENCVF_NUM_PADS)
851 return -EINVAL;
852
853 return imx_media_enum_ipu_formats(&code->code, code->index,
854 PIXFMT_SEL_YUV_RGB);
855}
856
857static int prp_get_fmt(struct v4l2_subdev *sd,
858 struct v4l2_subdev_pad_config *cfg,
859 struct v4l2_subdev_format *sdformat)
860{
861 struct prp_priv *priv = sd_to_priv(sd);
862 struct v4l2_mbus_framefmt *fmt;
863 int ret = 0;
864
865 if (sdformat->pad >= PRPENCVF_NUM_PADS)
866 return -EINVAL;
867
868 mutex_lock(&priv->lock);
869
870 fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
871 if (!fmt) {
872 ret = -EINVAL;
873 goto out;
874 }
875
876 sdformat->format = *fmt;
877out:
878 mutex_unlock(&priv->lock);
879 return ret;
880}
881
882static void prp_try_fmt(struct prp_priv *priv,
883 struct v4l2_subdev_pad_config *cfg,
884 struct v4l2_subdev_format *sdformat,
885 const struct imx_media_pixfmt **cc)
886{
887 struct v4l2_mbus_framefmt *infmt;
888
889 *cc = imx_media_find_ipu_format(sdformat->format.code,
890 PIXFMT_SEL_YUV_RGB);
891 if (!*cc) {
892 u32 code;
893
894 imx_media_enum_ipu_formats(&code, 0, PIXFMT_SEL_YUV_RGB);
895 *cc = imx_media_find_ipu_format(code, PIXFMT_SEL_YUV_RGB);
896
897 sdformat->format.code = (*cc)->codes[0];
898 }
899
900 infmt = __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD, sdformat->which);
901
902 if (sdformat->pad == PRPENCVF_SRC_PAD) {
903 sdformat->format.field = infmt->field;
904
905 prp_bound_align_output(&sdformat->format, infmt,
906 priv->rot_mode);
907
908
909 sdformat->format.colorspace = infmt->colorspace;
910 sdformat->format.xfer_func = infmt->xfer_func;
911 } else {
912 v4l_bound_align_image(&sdformat->format.width,
913 MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK,
914 &sdformat->format.height,
915 MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
916 S_ALIGN);
917
918 if (sdformat->format.field == V4L2_FIELD_ANY)
919 sdformat->format.field = V4L2_FIELD_NONE;
920 }
921
922 imx_media_try_colorimetry(&sdformat->format, true);
923}
924
925static int prp_set_fmt(struct v4l2_subdev *sd,
926 struct v4l2_subdev_pad_config *cfg,
927 struct v4l2_subdev_format *sdformat)
928{
929 struct prp_priv *priv = sd_to_priv(sd);
930 const struct imx_media_pixfmt *cc;
931 struct v4l2_mbus_framefmt *fmt;
932 int ret = 0;
933
934 if (sdformat->pad >= PRPENCVF_NUM_PADS)
935 return -EINVAL;
936
937 mutex_lock(&priv->lock);
938
939 if (priv->stream_count > 0) {
940 ret = -EBUSY;
941 goto out;
942 }
943
944 prp_try_fmt(priv, cfg, sdformat, &cc);
945
946 fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
947 *fmt = sdformat->format;
948
949
950 if (sdformat->pad == PRPENCVF_SINK_PAD) {
951 const struct imx_media_pixfmt *outcc;
952 struct v4l2_mbus_framefmt *outfmt;
953 struct v4l2_subdev_format format;
954
955 format.pad = PRPENCVF_SRC_PAD;
956 format.which = sdformat->which;
957 format.format = sdformat->format;
958 prp_try_fmt(priv, cfg, &format, &outcc);
959
960 outfmt = __prp_get_fmt(priv, cfg, PRPENCVF_SRC_PAD,
961 sdformat->which);
962 *outfmt = format.format;
963 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
964 priv->cc[PRPENCVF_SRC_PAD] = outcc;
965 }
966
967 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
968 priv->cc[sdformat->pad] = cc;
969
970out:
971 mutex_unlock(&priv->lock);
972 return ret;
973}
974
975static int prp_enum_frame_size(struct v4l2_subdev *sd,
976 struct v4l2_subdev_pad_config *cfg,
977 struct v4l2_subdev_frame_size_enum *fse)
978{
979 struct prp_priv *priv = sd_to_priv(sd);
980 struct v4l2_subdev_format format = {};
981 const struct imx_media_pixfmt *cc;
982 int ret = 0;
983
984 if (fse->pad >= PRPENCVF_NUM_PADS || fse->index != 0)
985 return -EINVAL;
986
987 mutex_lock(&priv->lock);
988
989 format.pad = fse->pad;
990 format.which = fse->which;
991 format.format.code = fse->code;
992 format.format.width = 1;
993 format.format.height = 1;
994 prp_try_fmt(priv, cfg, &format, &cc);
995 fse->min_width = format.format.width;
996 fse->min_height = format.format.height;
997
998 if (format.format.code != fse->code) {
999 ret = -EINVAL;
1000 goto out;
1001 }
1002
1003 format.format.code = fse->code;
1004 format.format.width = -1;
1005 format.format.height = -1;
1006 prp_try_fmt(priv, cfg, &format, &cc);
1007 fse->max_width = format.format.width;
1008 fse->max_height = format.format.height;
1009out:
1010 mutex_unlock(&priv->lock);
1011 return ret;
1012}
1013
1014static int prp_link_setup(struct media_entity *entity,
1015 const struct media_pad *local,
1016 const struct media_pad *remote, u32 flags)
1017{
1018 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1019 struct imx_ic_priv *ic_priv = v4l2_get_subdevdata(sd);
1020 struct prp_priv *priv = ic_priv->task_priv;
1021 struct v4l2_subdev *remote_sd;
1022 int ret = 0;
1023
1024 dev_dbg(ic_priv->ipu_dev, "%s: link setup %s -> %s",
1025 ic_priv->sd.name, remote->entity->name, local->entity->name);
1026
1027 mutex_lock(&priv->lock);
1028
1029 if (local->flags & MEDIA_PAD_FL_SINK) {
1030 if (!is_media_entity_v4l2_subdev(remote->entity)) {
1031 ret = -EINVAL;
1032 goto out;
1033 }
1034
1035 remote_sd = media_entity_to_v4l2_subdev(remote->entity);
1036
1037 if (flags & MEDIA_LNK_FL_ENABLED) {
1038 if (priv->src_sd) {
1039 ret = -EBUSY;
1040 goto out;
1041 }
1042 priv->src_sd = remote_sd;
1043 } else {
1044 priv->src_sd = NULL;
1045 }
1046
1047 goto out;
1048 }
1049
1050
1051
1052
1053 if (!is_media_entity_v4l2_video_device(remote->entity)) {
1054 ret = -EINVAL;
1055 goto out;
1056 }
1057
1058 if (flags & MEDIA_LNK_FL_ENABLED) {
1059 if (priv->sink) {
1060 ret = -EBUSY;
1061 goto out;
1062 }
1063 } else {
1064 priv->sink = NULL;
1065 goto out;
1066 }
1067
1068 priv->sink = remote->entity;
1069out:
1070 mutex_unlock(&priv->lock);
1071 return ret;
1072}
1073
1074static int prp_s_ctrl(struct v4l2_ctrl *ctrl)
1075{
1076 struct prp_priv *priv = container_of(ctrl->handler,
1077 struct prp_priv, ctrl_hdlr);
1078 struct imx_ic_priv *ic_priv = priv->ic_priv;
1079 enum ipu_rotate_mode rot_mode;
1080 int rotation, ret = 0;
1081 bool hflip, vflip;
1082
1083 mutex_lock(&priv->lock);
1084
1085 rotation = priv->rotation;
1086 hflip = priv->hflip;
1087 vflip = priv->vflip;
1088
1089 switch (ctrl->id) {
1090 case V4L2_CID_HFLIP:
1091 hflip = (ctrl->val == 1);
1092 break;
1093 case V4L2_CID_VFLIP:
1094 vflip = (ctrl->val == 1);
1095 break;
1096 case V4L2_CID_ROTATE:
1097 rotation = ctrl->val;
1098 break;
1099 default:
1100 v4l2_err(&ic_priv->sd, "Invalid control\n");
1101 ret = -EINVAL;
1102 goto out;
1103 }
1104
1105 ret = ipu_degrees_to_rot_mode(&rot_mode, rotation, hflip, vflip);
1106 if (ret)
1107 goto out;
1108
1109 if (rot_mode != priv->rot_mode) {
1110 struct v4l2_mbus_framefmt outfmt, infmt;
1111
1112
1113 if (priv->stream_count > 0) {
1114 ret = -EBUSY;
1115 goto out;
1116 }
1117
1118 outfmt = priv->format_mbus[PRPENCVF_SRC_PAD];
1119 infmt = priv->format_mbus[PRPENCVF_SINK_PAD];
1120
1121 if (prp_bound_align_output(&outfmt, &infmt, rot_mode)) {
1122 ret = -EINVAL;
1123 goto out;
1124 }
1125
1126 priv->rot_mode = rot_mode;
1127 priv->rotation = rotation;
1128 priv->hflip = hflip;
1129 priv->vflip = vflip;
1130 }
1131
1132out:
1133 mutex_unlock(&priv->lock);
1134 return ret;
1135}
1136
1137static const struct v4l2_ctrl_ops prp_ctrl_ops = {
1138 .s_ctrl = prp_s_ctrl,
1139};
1140
1141static int prp_init_controls(struct prp_priv *priv)
1142{
1143 struct imx_ic_priv *ic_priv = priv->ic_priv;
1144 struct v4l2_ctrl_handler *hdlr = &priv->ctrl_hdlr;
1145 int ret;
1146
1147 v4l2_ctrl_handler_init(hdlr, 3);
1148
1149 v4l2_ctrl_new_std(hdlr, &prp_ctrl_ops, V4L2_CID_HFLIP,
1150 0, 1, 1, 0);
1151 v4l2_ctrl_new_std(hdlr, &prp_ctrl_ops, V4L2_CID_VFLIP,
1152 0, 1, 1, 0);
1153 v4l2_ctrl_new_std(hdlr, &prp_ctrl_ops, V4L2_CID_ROTATE,
1154 0, 270, 90, 0);
1155
1156 ic_priv->sd.ctrl_handler = hdlr;
1157
1158 if (hdlr->error) {
1159 ret = hdlr->error;
1160 goto out_free;
1161 }
1162
1163 v4l2_ctrl_handler_setup(hdlr);
1164 return 0;
1165
1166out_free:
1167 v4l2_ctrl_handler_free(hdlr);
1168 return ret;
1169}
1170
1171static int prp_s_stream(struct v4l2_subdev *sd, int enable)
1172{
1173 struct imx_ic_priv *ic_priv = v4l2_get_subdevdata(sd);
1174 struct prp_priv *priv = ic_priv->task_priv;
1175 int ret = 0;
1176
1177 mutex_lock(&priv->lock);
1178
1179 if (!priv->src_sd || !priv->sink) {
1180 ret = -EPIPE;
1181 goto out;
1182 }
1183
1184
1185
1186
1187
1188 if (priv->stream_count != !enable)
1189 goto update_count;
1190
1191 dev_dbg(ic_priv->ipu_dev, "%s: stream %s\n", sd->name,
1192 enable ? "ON" : "OFF");
1193
1194 if (enable)
1195 ret = prp_start(priv);
1196 else
1197 prp_stop(priv);
1198 if (ret)
1199 goto out;
1200
1201update_count:
1202 priv->stream_count += enable ? 1 : -1;
1203 if (priv->stream_count < 0)
1204 priv->stream_count = 0;
1205out:
1206 mutex_unlock(&priv->lock);
1207 return ret;
1208}
1209
1210static int prp_g_frame_interval(struct v4l2_subdev *sd,
1211 struct v4l2_subdev_frame_interval *fi)
1212{
1213 struct prp_priv *priv = sd_to_priv(sd);
1214
1215 if (fi->pad >= PRPENCVF_NUM_PADS)
1216 return -EINVAL;
1217
1218 mutex_lock(&priv->lock);
1219 fi->interval = priv->frame_interval;
1220 mutex_unlock(&priv->lock);
1221
1222 return 0;
1223}
1224
1225static int prp_s_frame_interval(struct v4l2_subdev *sd,
1226 struct v4l2_subdev_frame_interval *fi)
1227{
1228 struct prp_priv *priv = sd_to_priv(sd);
1229
1230 if (fi->pad >= PRPENCVF_NUM_PADS)
1231 return -EINVAL;
1232
1233 mutex_lock(&priv->lock);
1234
1235
1236 if (fi->interval.numerator == 0 || fi->interval.denominator == 0)
1237 fi->interval = priv->frame_interval;
1238 else
1239 priv->frame_interval = fi->interval;
1240
1241 mutex_unlock(&priv->lock);
1242
1243 return 0;
1244}
1245
1246static int prp_registered(struct v4l2_subdev *sd)
1247{
1248 struct prp_priv *priv = sd_to_priv(sd);
1249 struct imx_ic_priv *ic_priv = priv->ic_priv;
1250 int i, ret;
1251 u32 code;
1252
1253
1254 imx_media_enum_ipu_formats(&code, 0, PIXFMT_SEL_YUV);
1255
1256 for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
1257 ret = imx_media_init_mbus_fmt(&priv->format_mbus[i],
1258 640, 480, code, V4L2_FIELD_NONE,
1259 &priv->cc[i]);
1260 if (ret)
1261 return ret;
1262 }
1263
1264
1265 priv->frame_interval.numerator = 1;
1266 priv->frame_interval.denominator = 30;
1267
1268 priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev,
1269 &ic_priv->sd,
1270 PRPENCVF_SRC_PAD);
1271 if (IS_ERR(priv->vdev))
1272 return PTR_ERR(priv->vdev);
1273
1274 ret = imx_media_capture_device_register(priv->vdev);
1275 if (ret)
1276 goto remove_vdev;
1277
1278 ret = prp_init_controls(priv);
1279 if (ret)
1280 goto unreg_vdev;
1281
1282 return 0;
1283
1284unreg_vdev:
1285 imx_media_capture_device_unregister(priv->vdev);
1286remove_vdev:
1287 imx_media_capture_device_remove(priv->vdev);
1288 return ret;
1289}
1290
1291static void prp_unregistered(struct v4l2_subdev *sd)
1292{
1293 struct prp_priv *priv = sd_to_priv(sd);
1294
1295 imx_media_capture_device_unregister(priv->vdev);
1296 imx_media_capture_device_remove(priv->vdev);
1297
1298 v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
1299}
1300
1301static const struct v4l2_subdev_pad_ops prp_pad_ops = {
1302 .init_cfg = imx_media_init_cfg,
1303 .enum_mbus_code = prp_enum_mbus_code,
1304 .enum_frame_size = prp_enum_frame_size,
1305 .get_fmt = prp_get_fmt,
1306 .set_fmt = prp_set_fmt,
1307};
1308
1309static const struct v4l2_subdev_video_ops prp_video_ops = {
1310 .g_frame_interval = prp_g_frame_interval,
1311 .s_frame_interval = prp_s_frame_interval,
1312 .s_stream = prp_s_stream,
1313};
1314
1315static const struct media_entity_operations prp_entity_ops = {
1316 .link_setup = prp_link_setup,
1317 .link_validate = v4l2_subdev_link_validate,
1318};
1319
1320static const struct v4l2_subdev_ops prp_subdev_ops = {
1321 .video = &prp_video_ops,
1322 .pad = &prp_pad_ops,
1323};
1324
1325static const struct v4l2_subdev_internal_ops prp_internal_ops = {
1326 .registered = prp_registered,
1327 .unregistered = prp_unregistered,
1328};
1329
1330static int prp_init(struct imx_ic_priv *ic_priv)
1331{
1332 struct prp_priv *priv;
1333 int i, ret;
1334
1335 priv = devm_kzalloc(ic_priv->ipu_dev, sizeof(*priv), GFP_KERNEL);
1336 if (!priv)
1337 return -ENOMEM;
1338
1339 ic_priv->task_priv = priv;
1340 priv->ic_priv = ic_priv;
1341
1342 spin_lock_init(&priv->irqlock);
1343 timer_setup(&priv->eof_timeout_timer, prp_eof_timeout, 0);
1344
1345 mutex_init(&priv->lock);
1346
1347 for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
1348 priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ?
1349 MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
1350 }
1351
1352 ret = media_entity_pads_init(&ic_priv->sd.entity, PRPENCVF_NUM_PADS,
1353 priv->pad);
1354 if (ret)
1355 mutex_destroy(&priv->lock);
1356
1357 return ret;
1358}
1359
1360static void prp_remove(struct imx_ic_priv *ic_priv)
1361{
1362 struct prp_priv *priv = ic_priv->task_priv;
1363
1364 mutex_destroy(&priv->lock);
1365}
1366
1367struct imx_ic_ops imx_ic_prpencvf_ops = {
1368 .subdev_ops = &prp_subdev_ops,
1369 .internal_ops = &prp_internal_ops,
1370 .entity_ops = &prp_entity_ops,
1371 .init = prp_init,
1372 .remove = prp_remove,
1373};
1374