cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

imx-ic-prpencvf.c (33940B)


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