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