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