root/drivers/staging/media/imx/imx-ic-prpencvf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sd_to_priv
  2. prp_put_ipu_resources
  3. prp_get_ipu_resources
  4. prp_vb2_buf_done
  5. prp_eof_interrupt
  6. prp_nfb4eof_interrupt
  7. prp_eof_timeout
  8. prp_setup_vb2_buf
  9. prp_unsetup_vb2_buf
  10. prp_setup_channel
  11. prp_setup_rotation
  12. prp_unsetup_rotation
  13. prp_setup_norotation
  14. prp_unsetup_norotation
  15. prp_unsetup
  16. prp_start
  17. prp_stop
  18. __prp_get_fmt
  19. prp_bound_align_output
  20. prp_enum_mbus_code
  21. prp_get_fmt
  22. prp_try_fmt
  23. prp_set_fmt
  24. prp_enum_frame_size
  25. prp_link_setup
  26. prp_s_ctrl
  27. prp_init_controls
  28. prp_s_stream
  29. prp_g_frame_interval
  30. prp_s_frame_interval
  31. prp_registered
  32. prp_unregistered
  33. prp_init
  34. prp_remove

   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  176
  39 #define MIN_H_SINK  144
  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 
  52 struct 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 
 107 static 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 
 124 static 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 
 131 static 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 
 150 static 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;
 193 out:
 194         prp_put_ipu_resources(priv);
 195         return ret;
 196 }
 197 
 198 static void prp_vb2_buf_done(struct prp_priv *priv, struct ipuv3_channel *ch)
 199 {
 200         struct imx_media_video_dev *vdev = priv->vdev;
 201         struct imx_media_buffer *done, *next;
 202         struct vb2_buffer *vb;
 203         dma_addr_t phys;
 204 
 205         done = priv->active_vb2_buf[priv->ipu_buf_num];
 206         if (done) {
 207                 done->vbuf.field = vdev->fmt.fmt.pix.field;
 208                 done->vbuf.sequence = priv->frame_sequence;
 209                 vb = &done->vbuf.vb2_buf;
 210                 vb->timestamp = ktime_get_ns();
 211                 vb2_buffer_done(vb, priv->nfb4eof ?
 212                                 VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 213         }
 214 
 215         priv->frame_sequence++;
 216         priv->nfb4eof = false;
 217 
 218         /* 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.fmt.pix.bytesperline;
 233 
 234         ipu_cpmem_set_buffer(ch, priv->ipu_buf_num, phys);
 235 }
 236 
 237 static 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 
 264 unlock:
 265         spin_unlock(&priv->irqlock);
 266         return IRQ_HANDLED;
 267 }
 268 
 269 static 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  */
 296 static 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 
 308 static 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 
 327 static 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 
 345 static int prp_setup_channel(struct prp_priv *priv,
 346                              struct ipuv3_channel *channel,
 347                              enum ipu_rotate_mode rot_mode,
 348                              dma_addr_t addr0, dma_addr_t addr1,
 349                              bool rot_swap_width_height)
 350 {
 351         struct imx_media_video_dev *vdev = priv->vdev;
 352         const struct imx_media_pixfmt *outcc;
 353         struct v4l2_mbus_framefmt *outfmt;
 354         unsigned int burst_size;
 355         struct ipu_image image;
 356         bool interweave;
 357         int ret;
 358 
 359         outfmt = &priv->format_mbus[PRPENCVF_SRC_PAD];
 360         outcc = vdev->cc;
 361 
 362         ipu_cpmem_zero(channel);
 363 
 364         memset(&image, 0, sizeof(image));
 365         image.pix = vdev->fmt.fmt.pix;
 366         image.rect = vdev->compose;
 367 
 368         /*
 369          * 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 
 448 static int prp_setup_rotation(struct prp_priv *priv)
 449 {
 450         struct imx_media_video_dev *vdev = priv->vdev;
 451         struct imx_ic_priv *ic_priv = priv->ic_priv;
 452         const struct imx_media_pixfmt *outcc, *incc;
 453         struct v4l2_mbus_framefmt *infmt;
 454         struct v4l2_pix_format *outfmt;
 455         struct ipu_ic_csc csc;
 456         dma_addr_t phys[2];
 457         int ret;
 458 
 459         infmt = &priv->format_mbus[PRPENCVF_SINK_PAD];
 460         outfmt = &vdev->fmt.fmt.pix;
 461         incc = priv->cc[PRPENCVF_SINK_PAD];
 462         outcc = vdev->cc;
 463 
 464         ret = ipu_ic_calc_csc(&csc,
 465                               infmt->ycbcr_enc, infmt->quantization,
 466                               incc->cs,
 467                               outfmt->ycbcr_enc, outfmt->quantization,
 468                               outcc->cs);
 469         if (ret) {
 470                 v4l2_err(&ic_priv->sd, "ipu_ic_calc_csc failed, %d\n",
 471                          ret);
 472                 return ret;
 473         }
 474 
 475         ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0],
 476                                       outfmt->sizeimage);
 477         if (ret) {
 478                 v4l2_err(&ic_priv->sd, "failed to alloc rot_buf[0], %d\n", ret);
 479                 return ret;
 480         }
 481         ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1],
 482                                       outfmt->sizeimage);
 483         if (ret) {
 484                 v4l2_err(&ic_priv->sd, "failed to alloc rot_buf[1], %d\n", ret);
 485                 goto free_rot0;
 486         }
 487 
 488         ret = ipu_ic_task_init(priv->ic, &csc,
 489                                infmt->width, infmt->height,
 490                                outfmt->height, outfmt->width);
 491         if (ret) {
 492                 v4l2_err(&ic_priv->sd, "ipu_ic_task_init failed, %d\n", ret);
 493                 goto free_rot1;
 494         }
 495 
 496         /* 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 
 550 unsetup_vb2:
 551         prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
 552 free_rot1:
 553         imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1]);
 554 free_rot0:
 555         imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0]);
 556         return ret;
 557 }
 558 
 559 static 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 
 577 static int prp_setup_norotation(struct prp_priv *priv)
 578 {
 579         struct imx_media_video_dev *vdev = priv->vdev;
 580         struct imx_ic_priv *ic_priv = priv->ic_priv;
 581         const struct imx_media_pixfmt *outcc, *incc;
 582         struct v4l2_mbus_framefmt *infmt;
 583         struct v4l2_pix_format *outfmt;
 584         struct ipu_ic_csc csc;
 585         dma_addr_t phys[2];
 586         int ret;
 587 
 588         infmt = &priv->format_mbus[PRPENCVF_SINK_PAD];
 589         outfmt = &vdev->fmt.fmt.pix;
 590         incc = priv->cc[PRPENCVF_SINK_PAD];
 591         outcc = vdev->cc;
 592 
 593         ret = ipu_ic_calc_csc(&csc,
 594                               infmt->ycbcr_enc, infmt->quantization,
 595                               incc->cs,
 596                               outfmt->ycbcr_enc, outfmt->quantization,
 597                               outcc->cs);
 598         if (ret) {
 599                 v4l2_err(&ic_priv->sd, "ipu_ic_calc_csc failed, %d\n",
 600                          ret);
 601                 return ret;
 602         }
 603 
 604         ret = ipu_ic_task_init(priv->ic, &csc,
 605                                infmt->width, infmt->height,
 606                                outfmt->width, outfmt->height);
 607         if (ret) {
 608                 v4l2_err(&ic_priv->sd, "ipu_ic_task_init failed, %d\n", ret);
 609                 return ret;
 610         }
 611 
 612         prp_setup_vb2_buf(priv, phys);
 613 
 614         /* 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 
 641 unsetup_vb2:
 642         prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
 643         return ret;
 644 }
 645 
 646 static 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 
 653 static 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 
 664 static int prp_start(struct prp_priv *priv)
 665 {
 666         struct imx_ic_priv *ic_priv = priv->ic_priv;
 667         struct imx_media_video_dev *vdev = priv->vdev;
 668         struct v4l2_pix_format *outfmt;
 669         int ret;
 670 
 671         ret = prp_get_ipu_resources(priv);
 672         if (ret)
 673                 return ret;
 674 
 675         outfmt = &vdev->fmt.fmt.pix;
 676 
 677         ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf,
 678                                       outfmt->sizeimage);
 679         if (ret)
 680                 goto out_put_ipu;
 681 
 682         priv->ipu_buf_num = 0;
 683 
 684         /* init EOF completion waitq */
 685         init_completion(&priv->last_eof_comp);
 686         priv->frame_sequence = 0;
 687         priv->last_eof = false;
 688         priv->nfb4eof = false;
 689 
 690         if (ipu_rot_mode_is_irt(priv->rot_mode))
 691                 ret = prp_setup_rotation(priv);
 692         else
 693                 ret = prp_setup_norotation(priv);
 694         if (ret)
 695                 goto out_free_underrun;
 696 
 697         priv->nfb4eof_irq = ipu_idmac_channel_irq(ic_priv->ipu,
 698                                                   priv->out_ch,
 699                                                   IPU_IRQ_NFB4EOF);
 700         ret = devm_request_irq(ic_priv->ipu_dev, priv->nfb4eof_irq,
 701                                prp_nfb4eof_interrupt, 0,
 702                                "imx-ic-prp-nfb4eof", priv);
 703         if (ret) {
 704                 v4l2_err(&ic_priv->sd,
 705                          "Error registering NFB4EOF irq: %d\n", ret);
 706                 goto out_unsetup;
 707         }
 708 
 709         if (ipu_rot_mode_is_irt(priv->rot_mode))
 710                 priv->eof_irq = ipu_idmac_channel_irq(
 711                         ic_priv->ipu, priv->rot_out_ch, IPU_IRQ_EOF);
 712         else
 713                 priv->eof_irq = ipu_idmac_channel_irq(
 714                         ic_priv->ipu, priv->out_ch, IPU_IRQ_EOF);
 715 
 716         ret = devm_request_irq(ic_priv->ipu_dev, priv->eof_irq,
 717                                prp_eof_interrupt, 0,
 718                                "imx-ic-prp-eof", priv);
 719         if (ret) {
 720                 v4l2_err(&ic_priv->sd,
 721                          "Error registering eof irq: %d\n", ret);
 722                 goto out_free_nfb4eof_irq;
 723         }
 724 
 725         /* start upstream */
 726         ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 1);
 727         ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
 728         if (ret) {
 729                 v4l2_err(&ic_priv->sd,
 730                          "upstream stream on failed: %d\n", ret);
 731                 goto out_free_eof_irq;
 732         }
 733 
 734         /* start the EOF timeout timer */
 735         mod_timer(&priv->eof_timeout_timer,
 736                   jiffies + msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
 737 
 738         return 0;
 739 
 740 out_free_eof_irq:
 741         devm_free_irq(ic_priv->ipu_dev, priv->eof_irq, priv);
 742 out_free_nfb4eof_irq:
 743         devm_free_irq(ic_priv->ipu_dev, priv->nfb4eof_irq, priv);
 744 out_unsetup:
 745         prp_unsetup(priv, VB2_BUF_STATE_QUEUED);
 746 out_free_underrun:
 747         imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf);
 748 out_put_ipu:
 749         prp_put_ipu_resources(priv);
 750         return ret;
 751 }
 752 
 753 static void prp_stop(struct prp_priv *priv)
 754 {
 755         struct imx_ic_priv *ic_priv = priv->ic_priv;
 756         unsigned long flags;
 757         int ret;
 758 
 759         /* mark next EOF interrupt as the last before stream off */
 760         spin_lock_irqsave(&priv->irqlock, flags);
 761         priv->last_eof = true;
 762         spin_unlock_irqrestore(&priv->irqlock, flags);
 763 
 764         /*
 765          * and then wait for interrupt handler to mark completion.
 766          */
 767         ret = wait_for_completion_timeout(
 768                 &priv->last_eof_comp,
 769                 msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
 770         if (ret == 0)
 771                 v4l2_warn(&ic_priv->sd, "wait last EOF timeout\n");
 772 
 773         /* stop upstream */
 774         ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
 775         if (ret && ret != -ENOIOCTLCMD)
 776                 v4l2_warn(&ic_priv->sd,
 777                           "upstream stream off failed: %d\n", ret);
 778 
 779         devm_free_irq(ic_priv->ipu_dev, priv->eof_irq, priv);
 780         devm_free_irq(ic_priv->ipu_dev, priv->nfb4eof_irq, priv);
 781 
 782         prp_unsetup(priv, VB2_BUF_STATE_ERROR);
 783 
 784         imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf);
 785 
 786         /* cancel the EOF timeout timer */
 787         del_timer_sync(&priv->eof_timeout_timer);
 788 
 789         prp_put_ipu_resources(priv);
 790 }
 791 
 792 static struct v4l2_mbus_framefmt *
 793 __prp_get_fmt(struct prp_priv *priv, struct v4l2_subdev_pad_config *cfg,
 794               unsigned int pad, enum v4l2_subdev_format_whence which)
 795 {
 796         struct imx_ic_priv *ic_priv = priv->ic_priv;
 797 
 798         if (which == V4L2_SUBDEV_FORMAT_TRY)
 799                 return v4l2_subdev_get_try_format(&ic_priv->sd, cfg, pad);
 800         else
 801                 return &priv->format_mbus[pad];
 802 }
 803 
 804 /*
 805  * Applies IC resizer and IDMAC alignment restrictions to output
 806  * rectangle given the input rectangle, and depending on given
 807  * rotation mode.
 808  *
 809  * The IC resizer cannot downsize more than 4:1. Note also that
 810  * for 90 or 270 rotation, _both_ output width and height must
 811  * be aligned by W_ALIGN_SRC, because the intermediate rotation
 812  * buffer swaps output width/height, and the final output buffer
 813  * does not.
 814  *
 815  * Returns true if the output rectangle was modified.
 816  */
 817 static bool prp_bound_align_output(struct v4l2_mbus_framefmt *outfmt,
 818                                    struct v4l2_mbus_framefmt *infmt,
 819                                    enum ipu_rotate_mode rot_mode)
 820 {
 821         u32 orig_width = outfmt->width;
 822         u32 orig_height = outfmt->height;
 823 
 824         if (ipu_rot_mode_is_irt(rot_mode))
 825                 v4l_bound_align_image(&outfmt->width,
 826                                       infmt->height / 4, MAX_H_SRC,
 827                                       W_ALIGN_SRC,
 828                                       &outfmt->height,
 829                                       infmt->width / 4, MAX_W_SRC,
 830                                       W_ALIGN_SRC, S_ALIGN);
 831         else
 832                 v4l_bound_align_image(&outfmt->width,
 833                                       infmt->width / 4, MAX_W_SRC,
 834                                       W_ALIGN_SRC,
 835                                       &outfmt->height,
 836                                       infmt->height / 4, MAX_H_SRC,
 837                                       H_ALIGN_SRC, S_ALIGN);
 838 
 839         return outfmt->width != orig_width || outfmt->height != orig_height;
 840 }
 841 
 842 /*
 843  * V4L2 subdev operations.
 844  */
 845 
 846 static int prp_enum_mbus_code(struct v4l2_subdev *sd,
 847                               struct v4l2_subdev_pad_config *cfg,
 848                               struct v4l2_subdev_mbus_code_enum *code)
 849 {
 850         if (code->pad >= PRPENCVF_NUM_PADS)
 851                 return -EINVAL;
 852 
 853         return imx_media_enum_ipu_format(&code->code, code->index, CS_SEL_ANY);
 854 }
 855 
 856 static int prp_get_fmt(struct v4l2_subdev *sd,
 857                        struct v4l2_subdev_pad_config *cfg,
 858                        struct v4l2_subdev_format *sdformat)
 859 {
 860         struct prp_priv *priv = sd_to_priv(sd);
 861         struct v4l2_mbus_framefmt *fmt;
 862         int ret = 0;
 863 
 864         if (sdformat->pad >= PRPENCVF_NUM_PADS)
 865                 return -EINVAL;
 866 
 867         mutex_lock(&priv->lock);
 868 
 869         fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
 870         if (!fmt) {
 871                 ret = -EINVAL;
 872                 goto out;
 873         }
 874 
 875         sdformat->format = *fmt;
 876 out:
 877         mutex_unlock(&priv->lock);
 878         return ret;
 879 }
 880 
 881 static void prp_try_fmt(struct prp_priv *priv,
 882                         struct v4l2_subdev_pad_config *cfg,
 883                         struct v4l2_subdev_format *sdformat,
 884                         const struct imx_media_pixfmt **cc)
 885 {
 886         struct v4l2_mbus_framefmt *infmt;
 887 
 888         *cc = imx_media_find_ipu_format(sdformat->format.code, CS_SEL_ANY);
 889         if (!*cc) {
 890                 u32 code;
 891 
 892                 imx_media_enum_ipu_format(&code, 0, CS_SEL_ANY);
 893                 *cc = imx_media_find_ipu_format(code, CS_SEL_ANY);
 894                 sdformat->format.code = (*cc)->codes[0];
 895         }
 896 
 897         infmt = __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD, sdformat->which);
 898 
 899         if (sdformat->pad == PRPENCVF_SRC_PAD) {
 900                 sdformat->format.field = infmt->field;
 901 
 902                 prp_bound_align_output(&sdformat->format, infmt,
 903                                        priv->rot_mode);
 904 
 905                 /* propagate colorimetry from sink */
 906                 sdformat->format.colorspace = infmt->colorspace;
 907                 sdformat->format.xfer_func = infmt->xfer_func;
 908         } else {
 909                 v4l_bound_align_image(&sdformat->format.width,
 910                                       MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK,
 911                                       &sdformat->format.height,
 912                                       MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
 913                                       S_ALIGN);
 914 
 915                 if (sdformat->format.field == V4L2_FIELD_ANY)
 916                         sdformat->format.field = V4L2_FIELD_NONE;
 917         }
 918 
 919         imx_media_try_colorimetry(&sdformat->format, true);
 920 }
 921 
 922 static int prp_set_fmt(struct v4l2_subdev *sd,
 923                        struct v4l2_subdev_pad_config *cfg,
 924                        struct v4l2_subdev_format *sdformat)
 925 {
 926         struct prp_priv *priv = sd_to_priv(sd);
 927         const struct imx_media_pixfmt *cc;
 928         struct v4l2_mbus_framefmt *fmt;
 929         int ret = 0;
 930 
 931         if (sdformat->pad >= PRPENCVF_NUM_PADS)
 932                 return -EINVAL;
 933 
 934         mutex_lock(&priv->lock);
 935 
 936         if (priv->stream_count > 0) {
 937                 ret = -EBUSY;
 938                 goto out;
 939         }
 940 
 941         prp_try_fmt(priv, cfg, sdformat, &cc);
 942 
 943         fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
 944         *fmt = sdformat->format;
 945 
 946         /* propagate a default format to source pad */
 947         if (sdformat->pad == PRPENCVF_SINK_PAD) {
 948                 const struct imx_media_pixfmt *outcc;
 949                 struct v4l2_mbus_framefmt *outfmt;
 950                 struct v4l2_subdev_format format;
 951 
 952                 format.pad = PRPENCVF_SRC_PAD;
 953                 format.which = sdformat->which;
 954                 format.format = sdformat->format;
 955                 prp_try_fmt(priv, cfg, &format, &outcc);
 956 
 957                 outfmt = __prp_get_fmt(priv, cfg, PRPENCVF_SRC_PAD,
 958                                        sdformat->which);
 959                 *outfmt = format.format;
 960                 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 961                         priv->cc[PRPENCVF_SRC_PAD] = outcc;
 962         }
 963 
 964         if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 965                 priv->cc[sdformat->pad] = cc;
 966 
 967 out:
 968         mutex_unlock(&priv->lock);
 969         return ret;
 970 }
 971 
 972 static int prp_enum_frame_size(struct v4l2_subdev *sd,
 973                                struct v4l2_subdev_pad_config *cfg,
 974                                struct v4l2_subdev_frame_size_enum *fse)
 975 {
 976         struct prp_priv *priv = sd_to_priv(sd);
 977         struct v4l2_subdev_format format = {};
 978         const struct imx_media_pixfmt *cc;
 979         int ret = 0;
 980 
 981         if (fse->pad >= PRPENCVF_NUM_PADS || fse->index != 0)
 982                 return -EINVAL;
 983 
 984         mutex_lock(&priv->lock);
 985 
 986         format.pad = fse->pad;
 987         format.which = fse->which;
 988         format.format.code = fse->code;
 989         format.format.width = 1;
 990         format.format.height = 1;
 991         prp_try_fmt(priv, cfg, &format, &cc);
 992         fse->min_width = format.format.width;
 993         fse->min_height = format.format.height;
 994 
 995         if (format.format.code != fse->code) {
 996                 ret = -EINVAL;
 997                 goto out;
 998         }
 999 
1000         format.format.code = fse->code;
1001         format.format.width = -1;
1002         format.format.height = -1;
1003         prp_try_fmt(priv, cfg, &format, &cc);
1004         fse->max_width = format.format.width;
1005         fse->max_height = format.format.height;
1006 out:
1007         mutex_unlock(&priv->lock);
1008         return ret;
1009 }
1010 
1011 static int prp_link_setup(struct media_entity *entity,
1012                           const struct media_pad *local,
1013                           const struct media_pad *remote, u32 flags)
1014 {
1015         struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1016         struct imx_ic_priv *ic_priv = v4l2_get_subdevdata(sd);
1017         struct prp_priv *priv = ic_priv->task_priv;
1018         struct v4l2_subdev *remote_sd;
1019         int ret = 0;
1020 
1021         dev_dbg(ic_priv->ipu_dev, "%s: link setup %s -> %s",
1022                 ic_priv->sd.name, remote->entity->name, local->entity->name);
1023 
1024         mutex_lock(&priv->lock);
1025 
1026         if (local->flags & MEDIA_PAD_FL_SINK) {
1027                 if (!is_media_entity_v4l2_subdev(remote->entity)) {
1028                         ret = -EINVAL;
1029                         goto out;
1030                 }
1031 
1032                 remote_sd = media_entity_to_v4l2_subdev(remote->entity);
1033 
1034                 if (flags & MEDIA_LNK_FL_ENABLED) {
1035                         if (priv->src_sd) {
1036                                 ret = -EBUSY;
1037                                 goto out;
1038                         }
1039                         priv->src_sd = remote_sd;
1040                 } else {
1041                         priv->src_sd = NULL;
1042                 }
1043 
1044                 goto out;
1045         }
1046 
1047         /* this is the source pad */
1048 
1049         /* the remote must be the device node */
1050         if (!is_media_entity_v4l2_video_device(remote->entity)) {
1051                 ret = -EINVAL;
1052                 goto out;
1053         }
1054 
1055         if (flags & MEDIA_LNK_FL_ENABLED) {
1056                 if (priv->sink) {
1057                         ret = -EBUSY;
1058                         goto out;
1059                 }
1060         } else {
1061                 priv->sink = NULL;
1062                 goto out;
1063         }
1064 
1065         priv->sink = remote->entity;
1066 out:
1067         mutex_unlock(&priv->lock);
1068         return ret;
1069 }
1070 
1071 static int prp_s_ctrl(struct v4l2_ctrl *ctrl)
1072 {
1073         struct prp_priv *priv = container_of(ctrl->handler,
1074                                                struct prp_priv, ctrl_hdlr);
1075         struct imx_ic_priv *ic_priv = priv->ic_priv;
1076         enum ipu_rotate_mode rot_mode;
1077         int rotation, ret = 0;
1078         bool hflip, vflip;
1079 
1080         mutex_lock(&priv->lock);
1081 
1082         rotation = priv->rotation;
1083         hflip = priv->hflip;
1084         vflip = priv->vflip;
1085 
1086         switch (ctrl->id) {
1087         case V4L2_CID_HFLIP:
1088                 hflip = (ctrl->val == 1);
1089                 break;
1090         case V4L2_CID_VFLIP:
1091                 vflip = (ctrl->val == 1);
1092                 break;
1093         case V4L2_CID_ROTATE:
1094                 rotation = ctrl->val;
1095                 break;
1096         default:
1097                 v4l2_err(&ic_priv->sd, "Invalid control\n");
1098                 ret = -EINVAL;
1099                 goto out;
1100         }
1101 
1102         ret = ipu_degrees_to_rot_mode(&rot_mode, rotation, hflip, vflip);
1103         if (ret)
1104                 goto out;
1105 
1106         if (rot_mode != priv->rot_mode) {
1107                 struct v4l2_mbus_framefmt outfmt, infmt;
1108 
1109                 /* can't change rotation mid-streaming */
1110                 if (priv->stream_count > 0) {
1111                         ret = -EBUSY;
1112                         goto out;
1113                 }
1114 
1115                 outfmt = priv->format_mbus[PRPENCVF_SRC_PAD];
1116                 infmt = priv->format_mbus[PRPENCVF_SINK_PAD];
1117 
1118                 if (prp_bound_align_output(&outfmt, &infmt, rot_mode)) {
1119                         ret = -EINVAL;
1120                         goto out;
1121                 }
1122 
1123                 priv->rot_mode = rot_mode;
1124                 priv->rotation = rotation;
1125                 priv->hflip = hflip;
1126                 priv->vflip = vflip;
1127         }
1128 
1129 out:
1130         mutex_unlock(&priv->lock);
1131         return ret;
1132 }
1133 
1134 static const struct v4l2_ctrl_ops prp_ctrl_ops = {
1135         .s_ctrl = prp_s_ctrl,
1136 };
1137 
1138 static int prp_init_controls(struct prp_priv *priv)
1139 {
1140         struct imx_ic_priv *ic_priv = priv->ic_priv;
1141         struct v4l2_ctrl_handler *hdlr = &priv->ctrl_hdlr;
1142         int ret;
1143 
1144         v4l2_ctrl_handler_init(hdlr, 3);
1145 
1146         v4l2_ctrl_new_std(hdlr, &prp_ctrl_ops, V4L2_CID_HFLIP,
1147                           0, 1, 1, 0);
1148         v4l2_ctrl_new_std(hdlr, &prp_ctrl_ops, V4L2_CID_VFLIP,
1149                           0, 1, 1, 0);
1150         v4l2_ctrl_new_std(hdlr, &prp_ctrl_ops, V4L2_CID_ROTATE,
1151                           0, 270, 90, 0);
1152 
1153         ic_priv->sd.ctrl_handler = hdlr;
1154 
1155         if (hdlr->error) {
1156                 ret = hdlr->error;
1157                 goto out_free;
1158         }
1159 
1160         v4l2_ctrl_handler_setup(hdlr);
1161         return 0;
1162 
1163 out_free:
1164         v4l2_ctrl_handler_free(hdlr);
1165         return ret;
1166 }
1167 
1168 static int prp_s_stream(struct v4l2_subdev *sd, int enable)
1169 {
1170         struct imx_ic_priv *ic_priv = v4l2_get_subdevdata(sd);
1171         struct prp_priv *priv = ic_priv->task_priv;
1172         int ret = 0;
1173 
1174         mutex_lock(&priv->lock);
1175 
1176         if (!priv->src_sd || !priv->sink) {
1177                 ret = -EPIPE;
1178                 goto out;
1179         }
1180 
1181         /*
1182          * enable/disable streaming only if stream_count is
1183          * going from 0 to 1 / 1 to 0.
1184          */
1185         if (priv->stream_count != !enable)
1186                 goto update_count;
1187 
1188         dev_dbg(ic_priv->ipu_dev, "%s: stream %s\n", sd->name,
1189                 enable ? "ON" : "OFF");
1190 
1191         if (enable)
1192                 ret = prp_start(priv);
1193         else
1194                 prp_stop(priv);
1195         if (ret)
1196                 goto out;
1197 
1198 update_count:
1199         priv->stream_count += enable ? 1 : -1;
1200         if (priv->stream_count < 0)
1201                 priv->stream_count = 0;
1202 out:
1203         mutex_unlock(&priv->lock);
1204         return ret;
1205 }
1206 
1207 static int prp_g_frame_interval(struct v4l2_subdev *sd,
1208                                 struct v4l2_subdev_frame_interval *fi)
1209 {
1210         struct prp_priv *priv = sd_to_priv(sd);
1211 
1212         if (fi->pad >= PRPENCVF_NUM_PADS)
1213                 return -EINVAL;
1214 
1215         mutex_lock(&priv->lock);
1216         fi->interval = priv->frame_interval;
1217         mutex_unlock(&priv->lock);
1218 
1219         return 0;
1220 }
1221 
1222 static int prp_s_frame_interval(struct v4l2_subdev *sd,
1223                                 struct v4l2_subdev_frame_interval *fi)
1224 {
1225         struct prp_priv *priv = sd_to_priv(sd);
1226 
1227         if (fi->pad >= PRPENCVF_NUM_PADS)
1228                 return -EINVAL;
1229 
1230         mutex_lock(&priv->lock);
1231 
1232         /* No limits on valid frame intervals */
1233         if (fi->interval.numerator == 0 || fi->interval.denominator == 0)
1234                 fi->interval = priv->frame_interval;
1235         else
1236                 priv->frame_interval = fi->interval;
1237 
1238         mutex_unlock(&priv->lock);
1239 
1240         return 0;
1241 }
1242 
1243 /*
1244  * retrieve our pads parsed from the OF graph by the media device
1245  */
1246 static int prp_registered(struct v4l2_subdev *sd)
1247 {
1248         struct prp_priv *priv = sd_to_priv(sd);
1249         int i, ret;
1250         u32 code;
1251 
1252         for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
1253                 priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ?
1254                         MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
1255 
1256                 /* set a default mbus format  */
1257                 imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
1258                 ret = imx_media_init_mbus_fmt(&priv->format_mbus[i],
1259                                               640, 480, code, V4L2_FIELD_NONE,
1260                                               &priv->cc[i]);
1261                 if (ret)
1262                         return ret;
1263         }
1264 
1265         /* init default frame interval */
1266         priv->frame_interval.numerator = 1;
1267         priv->frame_interval.denominator = 30;
1268 
1269         ret = media_entity_pads_init(&sd->entity, PRPENCVF_NUM_PADS,
1270                                      priv->pad);
1271         if (ret)
1272                 return ret;
1273 
1274         ret = imx_media_capture_device_register(priv->vdev);
1275         if (ret)
1276                 return ret;
1277 
1278         ret = prp_init_controls(priv);
1279         if (ret)
1280                 goto unreg;
1281 
1282         return 0;
1283 unreg:
1284         imx_media_capture_device_unregister(priv->vdev);
1285         return ret;
1286 }
1287 
1288 static void prp_unregistered(struct v4l2_subdev *sd)
1289 {
1290         struct prp_priv *priv = sd_to_priv(sd);
1291 
1292         imx_media_capture_device_unregister(priv->vdev);
1293         v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
1294 }
1295 
1296 static const struct v4l2_subdev_pad_ops prp_pad_ops = {
1297         .init_cfg = imx_media_init_cfg,
1298         .enum_mbus_code = prp_enum_mbus_code,
1299         .enum_frame_size = prp_enum_frame_size,
1300         .get_fmt = prp_get_fmt,
1301         .set_fmt = prp_set_fmt,
1302 };
1303 
1304 static const struct v4l2_subdev_video_ops prp_video_ops = {
1305         .g_frame_interval = prp_g_frame_interval,
1306         .s_frame_interval = prp_s_frame_interval,
1307         .s_stream = prp_s_stream,
1308 };
1309 
1310 static const struct media_entity_operations prp_entity_ops = {
1311         .link_setup = prp_link_setup,
1312         .link_validate = v4l2_subdev_link_validate,
1313 };
1314 
1315 static const struct v4l2_subdev_ops prp_subdev_ops = {
1316         .video = &prp_video_ops,
1317         .pad = &prp_pad_ops,
1318 };
1319 
1320 static const struct v4l2_subdev_internal_ops prp_internal_ops = {
1321         .registered = prp_registered,
1322         .unregistered = prp_unregistered,
1323 };
1324 
1325 static int prp_init(struct imx_ic_priv *ic_priv)
1326 {
1327         struct prp_priv *priv;
1328 
1329         priv = devm_kzalloc(ic_priv->ipu_dev, sizeof(*priv), GFP_KERNEL);
1330         if (!priv)
1331                 return -ENOMEM;
1332 
1333         ic_priv->task_priv = priv;
1334         priv->ic_priv = ic_priv;
1335 
1336         spin_lock_init(&priv->irqlock);
1337         timer_setup(&priv->eof_timeout_timer, prp_eof_timeout, 0);
1338 
1339         priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev,
1340                                                    &ic_priv->sd,
1341                                                    PRPENCVF_SRC_PAD);
1342         if (IS_ERR(priv->vdev))
1343                 return PTR_ERR(priv->vdev);
1344 
1345         mutex_init(&priv->lock);
1346 
1347         return 0;
1348 }
1349 
1350 static void prp_remove(struct imx_ic_priv *ic_priv)
1351 {
1352         struct prp_priv *priv = ic_priv->task_priv;
1353 
1354         mutex_destroy(&priv->lock);
1355         imx_media_capture_device_remove(priv->vdev);
1356 }
1357 
1358 struct imx_ic_ops imx_ic_prpencvf_ops = {
1359         .subdev_ops = &prp_subdev_ops,
1360         .internal_ops = &prp_internal_ops,
1361         .entity_ops = &prp_entity_ops,
1362         .init = prp_init,
1363         .remove = prp_remove,
1364 };

/* [<][>][^][v][top][bottom][index][help] */