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