1 // SPDX-License-Identifier: GPL-2.0+
3 * V4L2 Media Controller Driver for Freescale i.MX5/6 SOC
5 * Copyright (c) 2016 Mentor Graphics Inc.
7 #include <linux/module.h>
11 * List of supported pixel formats for the subdevs.
13 * In all of these tables, the non-mbus formats (with no
14 * mbus codes) must all fall at the end of the table.
17 static const struct imx_media_pixfmt yuv_formats[] = {
19 .fourcc = V4L2_PIX_FMT_UYVY,
21 MEDIA_BUS_FMT_UYVY8_2X8,
22 MEDIA_BUS_FMT_UYVY8_1X16
24 .cs = IPUV3_COLORSPACE_YUV,
27 .fourcc = V4L2_PIX_FMT_YUYV,
29 MEDIA_BUS_FMT_YUYV8_2X8,
30 MEDIA_BUS_FMT_YUYV8_1X16
32 .cs = IPUV3_COLORSPACE_YUV,
36 * non-mbus YUV formats start here. NOTE! when adding non-mbus
37 * formats, NUM_NON_MBUS_YUV_FORMATS must be updated below.
40 .fourcc = V4L2_PIX_FMT_YUV420,
41 .cs = IPUV3_COLORSPACE_YUV,
45 .fourcc = V4L2_PIX_FMT_YVU420,
46 .cs = IPUV3_COLORSPACE_YUV,
50 .fourcc = V4L2_PIX_FMT_YUV422P,
51 .cs = IPUV3_COLORSPACE_YUV,
55 .fourcc = V4L2_PIX_FMT_NV12,
56 .cs = IPUV3_COLORSPACE_YUV,
60 .fourcc = V4L2_PIX_FMT_NV16,
61 .cs = IPUV3_COLORSPACE_YUV,
67 #define NUM_NON_MBUS_YUV_FORMATS 5
68 #define NUM_YUV_FORMATS ARRAY_SIZE(yuv_formats)
69 #define NUM_MBUS_YUV_FORMATS (NUM_YUV_FORMATS - NUM_NON_MBUS_YUV_FORMATS)
71 static const struct imx_media_pixfmt rgb_formats[] = {
73 .fourcc = V4L2_PIX_FMT_RGB565,
74 .codes = {MEDIA_BUS_FMT_RGB565_2X8_LE},
75 .cs = IPUV3_COLORSPACE_RGB,
79 .fourcc = V4L2_PIX_FMT_RGB24,
81 MEDIA_BUS_FMT_RGB888_1X24,
82 MEDIA_BUS_FMT_RGB888_2X12_LE
84 .cs = IPUV3_COLORSPACE_RGB,
87 .fourcc = V4L2_PIX_FMT_XRGB32,
88 .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
89 .cs = IPUV3_COLORSPACE_RGB,
93 /*** raw bayer and grayscale formats start here ***/
95 .fourcc = V4L2_PIX_FMT_SBGGR8,
96 .codes = {MEDIA_BUS_FMT_SBGGR8_1X8},
97 .cs = IPUV3_COLORSPACE_RGB,
101 .fourcc = V4L2_PIX_FMT_SGBRG8,
102 .codes = {MEDIA_BUS_FMT_SGBRG8_1X8},
103 .cs = IPUV3_COLORSPACE_RGB,
107 .fourcc = V4L2_PIX_FMT_SGRBG8,
108 .codes = {MEDIA_BUS_FMT_SGRBG8_1X8},
109 .cs = IPUV3_COLORSPACE_RGB,
113 .fourcc = V4L2_PIX_FMT_SRGGB8,
114 .codes = {MEDIA_BUS_FMT_SRGGB8_1X8},
115 .cs = IPUV3_COLORSPACE_RGB,
119 .fourcc = V4L2_PIX_FMT_SBGGR16,
121 MEDIA_BUS_FMT_SBGGR10_1X10,
122 MEDIA_BUS_FMT_SBGGR12_1X12,
123 MEDIA_BUS_FMT_SBGGR14_1X14,
124 MEDIA_BUS_FMT_SBGGR16_1X16
126 .cs = IPUV3_COLORSPACE_RGB,
130 .fourcc = V4L2_PIX_FMT_SGBRG16,
132 MEDIA_BUS_FMT_SGBRG10_1X10,
133 MEDIA_BUS_FMT_SGBRG12_1X12,
134 MEDIA_BUS_FMT_SGBRG14_1X14,
135 MEDIA_BUS_FMT_SGBRG16_1X16,
137 .cs = IPUV3_COLORSPACE_RGB,
141 .fourcc = V4L2_PIX_FMT_SGRBG16,
143 MEDIA_BUS_FMT_SGRBG10_1X10,
144 MEDIA_BUS_FMT_SGRBG12_1X12,
145 MEDIA_BUS_FMT_SGRBG14_1X14,
146 MEDIA_BUS_FMT_SGRBG16_1X16,
148 .cs = IPUV3_COLORSPACE_RGB,
152 .fourcc = V4L2_PIX_FMT_SRGGB16,
154 MEDIA_BUS_FMT_SRGGB10_1X10,
155 MEDIA_BUS_FMT_SRGGB12_1X12,
156 MEDIA_BUS_FMT_SRGGB14_1X14,
157 MEDIA_BUS_FMT_SRGGB16_1X16,
159 .cs = IPUV3_COLORSPACE_RGB,
163 .fourcc = V4L2_PIX_FMT_GREY,
165 MEDIA_BUS_FMT_Y8_1X8,
166 MEDIA_BUS_FMT_Y10_1X10,
167 MEDIA_BUS_FMT_Y12_1X12,
169 .cs = IPUV3_COLORSPACE_RGB,
173 .fourcc = V4L2_PIX_FMT_Y10,
174 .codes = {MEDIA_BUS_FMT_Y10_1X10},
175 .cs = IPUV3_COLORSPACE_RGB,
179 .fourcc = V4L2_PIX_FMT_Y12,
180 .codes = {MEDIA_BUS_FMT_Y12_1X12},
181 .cs = IPUV3_COLORSPACE_RGB,
186 * non-mbus RGB formats start here. NOTE! when adding non-mbus
187 * formats, NUM_NON_MBUS_RGB_FORMATS must be updated below.
190 .fourcc = V4L2_PIX_FMT_BGR24,
191 .cs = IPUV3_COLORSPACE_RGB,
194 .fourcc = V4L2_PIX_FMT_XBGR32,
195 .cs = IPUV3_COLORSPACE_RGB,
198 .fourcc = V4L2_PIX_FMT_BGRX32,
199 .cs = IPUV3_COLORSPACE_RGB,
202 .fourcc = V4L2_PIX_FMT_RGBX32,
203 .cs = IPUV3_COLORSPACE_RGB,
208 #define NUM_NON_MBUS_RGB_FORMATS 2
209 #define NUM_RGB_FORMATS ARRAY_SIZE(rgb_formats)
210 #define NUM_MBUS_RGB_FORMATS (NUM_RGB_FORMATS - NUM_NON_MBUS_RGB_FORMATS)
212 static const struct imx_media_pixfmt ipu_yuv_formats[] = {
214 .fourcc = V4L2_PIX_FMT_YUV32,
215 .codes = {MEDIA_BUS_FMT_AYUV8_1X32},
216 .cs = IPUV3_COLORSPACE_YUV,
222 #define NUM_IPU_YUV_FORMATS ARRAY_SIZE(ipu_yuv_formats)
224 static const struct imx_media_pixfmt ipu_rgb_formats[] = {
226 .fourcc = V4L2_PIX_FMT_XRGB32,
227 .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
228 .cs = IPUV3_COLORSPACE_RGB,
234 #define NUM_IPU_RGB_FORMATS ARRAY_SIZE(ipu_rgb_formats)
236 static void init_mbus_colorimetry(struct v4l2_mbus_framefmt *mbus,
237 const struct imx_media_pixfmt *fmt)
239 mbus->colorspace = (fmt->cs == IPUV3_COLORSPACE_RGB) ?
240 V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_SMPTE170M;
241 mbus->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(mbus->colorspace);
242 mbus->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(mbus->colorspace);
244 V4L2_MAP_QUANTIZATION_DEFAULT(fmt->cs == IPUV3_COLORSPACE_RGB,
250 struct imx_media_pixfmt *__find_format(u32 fourcc,
254 const struct imx_media_pixfmt *array,
257 const struct imx_media_pixfmt *fmt;
260 for (i = 0; i < array_size; i++) {
263 if ((!allow_non_mbus && !fmt->codes[0]) ||
264 (!allow_bayer && fmt->bayer))
267 if (fourcc && fmt->fourcc == fourcc)
273 for (j = 0; fmt->codes[j]; j++) {
274 if (code == fmt->codes[j])
281 static const struct imx_media_pixfmt *find_format(u32 fourcc,
283 enum codespace_sel cs_sel,
287 const struct imx_media_pixfmt *ret;
291 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
292 yuv_formats, NUM_YUV_FORMATS);
294 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
295 rgb_formats, NUM_RGB_FORMATS);
297 ret = __find_format(fourcc, code, allow_non_mbus, allow_bayer,
298 yuv_formats, NUM_YUV_FORMATS);
301 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
302 rgb_formats, NUM_RGB_FORMATS);
308 static int enum_format(u32 *fourcc, u32 *code, u32 index,
309 enum codespace_sel cs_sel,
313 const struct imx_media_pixfmt *fmt;
314 u32 mbus_yuv_sz = NUM_MBUS_YUV_FORMATS;
315 u32 mbus_rgb_sz = NUM_MBUS_RGB_FORMATS;
316 u32 yuv_sz = NUM_YUV_FORMATS;
317 u32 rgb_sz = NUM_RGB_FORMATS;
321 if (index >= yuv_sz ||
322 (!allow_non_mbus && index >= mbus_yuv_sz))
324 fmt = &yuv_formats[index];
327 if (index >= rgb_sz ||
328 (!allow_non_mbus && index >= mbus_rgb_sz))
330 fmt = &rgb_formats[index];
331 if (!allow_bayer && fmt->bayer)
335 if (!allow_non_mbus) {
336 if (index >= mbus_yuv_sz) {
337 index -= mbus_yuv_sz;
338 if (index >= mbus_rgb_sz)
340 fmt = &rgb_formats[index];
341 if (!allow_bayer && fmt->bayer)
344 fmt = &yuv_formats[index];
347 if (index >= yuv_sz + rgb_sz)
349 if (index >= yuv_sz) {
350 fmt = &rgb_formats[index - yuv_sz];
351 if (!allow_bayer && fmt->bayer)
354 fmt = &yuv_formats[index];
363 *fourcc = fmt->fourcc;
365 *code = fmt->codes[0];
370 const struct imx_media_pixfmt *
371 imx_media_find_format(u32 fourcc, enum codespace_sel cs_sel, bool allow_bayer)
373 return find_format(fourcc, 0, cs_sel, true, allow_bayer);
375 EXPORT_SYMBOL_GPL(imx_media_find_format);
377 int imx_media_enum_format(u32 *fourcc, u32 index, enum codespace_sel cs_sel)
379 return enum_format(fourcc, NULL, index, cs_sel, true, false);
381 EXPORT_SYMBOL_GPL(imx_media_enum_format);
383 const struct imx_media_pixfmt *
384 imx_media_find_mbus_format(u32 code, enum codespace_sel cs_sel,
387 return find_format(0, code, cs_sel, false, allow_bayer);
389 EXPORT_SYMBOL_GPL(imx_media_find_mbus_format);
391 int imx_media_enum_mbus_format(u32 *code, u32 index, enum codespace_sel cs_sel,
394 return enum_format(NULL, code, index, cs_sel, false, allow_bayer);
396 EXPORT_SYMBOL_GPL(imx_media_enum_mbus_format);
398 const struct imx_media_pixfmt *
399 imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel)
401 const struct imx_media_pixfmt *array, *fmt, *ret = NULL;
407 array_size = NUM_IPU_YUV_FORMATS;
408 array = ipu_yuv_formats;
411 array_size = NUM_IPU_RGB_FORMATS;
412 array = ipu_rgb_formats;
415 array_size = NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS;
416 array = ipu_yuv_formats;
422 for (i = 0; i < array_size; i++) {
423 if (cs_sel == CS_SEL_ANY && i >= NUM_IPU_YUV_FORMATS)
424 fmt = &ipu_rgb_formats[i - NUM_IPU_YUV_FORMATS];
428 for (j = 0; code && fmt->codes[j]; j++) {
429 if (code == fmt->codes[j]) {
439 EXPORT_SYMBOL_GPL(imx_media_find_ipu_format);
441 int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel)
445 if (index >= NUM_IPU_YUV_FORMATS)
447 *code = ipu_yuv_formats[index].codes[0];
450 if (index >= NUM_IPU_RGB_FORMATS)
452 *code = ipu_rgb_formats[index].codes[0];
455 if (index >= NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS)
457 if (index >= NUM_IPU_YUV_FORMATS) {
458 index -= NUM_IPU_YUV_FORMATS;
459 *code = ipu_rgb_formats[index].codes[0];
461 *code = ipu_yuv_formats[index].codes[0];
470 EXPORT_SYMBOL_GPL(imx_media_enum_ipu_format);
472 int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
473 u32 width, u32 height, u32 code, u32 field,
474 const struct imx_media_pixfmt **cc)
476 const struct imx_media_pixfmt *lcc;
479 mbus->height = height;
482 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
483 lcc = imx_media_find_mbus_format(code, CS_SEL_ANY, false);
485 lcc = imx_media_find_ipu_format(code, CS_SEL_ANY);
491 init_mbus_colorimetry(mbus, lcc);
497 EXPORT_SYMBOL_GPL(imx_media_init_mbus_fmt);
500 * Initializes the TRY format to the ACTIVE format on all pads
501 * of a subdev. Can be used as the .init_cfg pad operation.
503 int imx_media_init_cfg(struct v4l2_subdev *sd,
504 struct v4l2_subdev_pad_config *cfg)
506 struct v4l2_mbus_framefmt *mf_try;
507 struct v4l2_subdev_format format;
511 for (pad = 0; pad < sd->entity.num_pads; pad++) {
512 memset(&format, 0, sizeof(format));
515 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
516 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);
520 mf_try = v4l2_subdev_get_try_format(sd, cfg, pad);
521 *mf_try = format.format;
526 EXPORT_SYMBOL_GPL(imx_media_init_cfg);
529 * Default the colorspace in tryfmt to SRGB if set to an unsupported
530 * colorspace or not initialized. Then set the remaining colorimetry
531 * parameters based on the colorspace if they are uninitialized.
533 * tryfmt->code must be set on entry.
535 * If this format is destined to be routed through the Image Converter,
536 * Y`CbCr encoding must be fixed. The IC supports only BT.601 Y`CbCr
537 * or Rec.709 Y`CbCr encoding.
539 void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
542 const struct imx_media_pixfmt *cc;
545 cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true);
547 cc = imx_media_find_ipu_format(tryfmt->code, CS_SEL_ANY);
548 if (cc && cc->cs == IPUV3_COLORSPACE_RGB)
551 switch (tryfmt->colorspace) {
552 case V4L2_COLORSPACE_SMPTE170M:
553 case V4L2_COLORSPACE_REC709:
554 case V4L2_COLORSPACE_JPEG:
555 case V4L2_COLORSPACE_SRGB:
556 case V4L2_COLORSPACE_BT2020:
557 case V4L2_COLORSPACE_OPRGB:
558 case V4L2_COLORSPACE_DCI_P3:
559 case V4L2_COLORSPACE_RAW:
562 tryfmt->colorspace = V4L2_COLORSPACE_SRGB;
566 if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT)
568 V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace);
571 if (tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_601 &&
572 tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_709)
573 tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
575 if (tryfmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
577 V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace);
581 if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT)
582 tryfmt->quantization =
583 V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb,
587 EXPORT_SYMBOL_GPL(imx_media_try_colorimetry);
589 int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
590 struct v4l2_mbus_framefmt *mbus,
591 const struct imx_media_pixfmt *cc)
597 cc = imx_media_find_ipu_format(mbus->code, CS_SEL_ANY);
599 cc = imx_media_find_mbus_format(mbus->code, CS_SEL_ANY,
606 * TODO: the IPU currently does not support the AYUV32 format,
607 * so until it does convert to a supported YUV format.
609 if (cc->ipufmt && cc->cs == IPUV3_COLORSPACE_YUV) {
612 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
613 cc = imx_media_find_mbus_format(code, CS_SEL_YUV, false);
616 /* Round up width for minimum burst size */
617 width = round_up(mbus->width, 8);
619 /* Round up stride for IDMAC line start address alignment */
621 stride = round_up(width, 16);
623 stride = round_up((width * cc->bpp) >> 3, 8);
626 pix->height = mbus->height;
627 pix->pixelformat = cc->fourcc;
628 pix->colorspace = mbus->colorspace;
629 pix->xfer_func = mbus->xfer_func;
630 pix->ycbcr_enc = mbus->ycbcr_enc;
631 pix->quantization = mbus->quantization;
632 pix->field = mbus->field;
633 pix->bytesperline = stride;
634 pix->sizeimage = cc->planar ? ((stride * pix->height * cc->bpp) >> 3) :
635 stride * pix->height;
639 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_pix_fmt);
641 int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image,
642 struct v4l2_mbus_framefmt *mbus)
646 memset(image, 0, sizeof(*image));
648 ret = imx_media_mbus_fmt_to_pix_fmt(&image->pix, mbus, NULL);
652 image->rect.width = mbus->width;
653 image->rect.height = mbus->height;
657 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_ipu_image);
659 int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
660 struct ipu_image *image)
662 const struct imx_media_pixfmt *fmt;
664 fmt = imx_media_find_format(image->pix.pixelformat, CS_SEL_ANY, true);
668 memset(mbus, 0, sizeof(*mbus));
669 mbus->width = image->pix.width;
670 mbus->height = image->pix.height;
671 mbus->code = fmt->codes[0];
672 mbus->field = image->pix.field;
673 mbus->colorspace = image->pix.colorspace;
674 mbus->xfer_func = image->pix.xfer_func;
675 mbus->ycbcr_enc = image->pix.ycbcr_enc;
676 mbus->quantization = image->pix.quantization;
680 EXPORT_SYMBOL_GPL(imx_media_ipu_image_to_mbus_fmt);
682 void imx_media_free_dma_buf(struct device *dev,
683 struct imx_media_dma_buf *buf)
686 dma_free_coherent(dev, buf->len, buf->virt, buf->phys);
691 EXPORT_SYMBOL_GPL(imx_media_free_dma_buf);
693 int imx_media_alloc_dma_buf(struct device *dev,
694 struct imx_media_dma_buf *buf,
697 imx_media_free_dma_buf(dev, buf);
699 buf->len = PAGE_ALIGN(size);
700 buf->virt = dma_alloc_coherent(dev, buf->len, &buf->phys,
701 GFP_DMA | GFP_KERNEL);
703 dev_err(dev, "%s: failed\n", __func__);
709 EXPORT_SYMBOL_GPL(imx_media_alloc_dma_buf);
711 /* form a subdev name given a group id and ipu id */
712 void imx_media_grp_id_to_sd_name(char *sd_name, int sz, u32 grp_id, int ipu_id)
717 case IMX_MEDIA_GRP_ID_IPU_CSI0...IMX_MEDIA_GRP_ID_IPU_CSI1:
718 id = (grp_id >> IMX_MEDIA_GRP_ID_IPU_CSI_BIT) - 1;
719 snprintf(sd_name, sz, "ipu%d_csi%d", ipu_id + 1, id);
721 case IMX_MEDIA_GRP_ID_IPU_VDIC:
722 snprintf(sd_name, sz, "ipu%d_vdic", ipu_id + 1);
724 case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
725 snprintf(sd_name, sz, "ipu%d_ic_prp", ipu_id + 1);
727 case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
728 snprintf(sd_name, sz, "ipu%d_ic_prpenc", ipu_id + 1);
730 case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
731 snprintf(sd_name, sz, "ipu%d_ic_prpvf", ipu_id + 1);
737 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name);
740 imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
741 struct fwnode_handle *fwnode)
743 struct v4l2_subdev *sd;
745 list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
746 if (sd->fwnode == fwnode)
752 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_fwnode);
755 imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
758 struct v4l2_subdev *sd;
760 list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
761 if (!strcmp(devname, dev_name(sd->dev)))
767 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
770 * Adds a video device to the master video device list. This is called
771 * when a video device is registered.
773 void imx_media_add_video_device(struct imx_media_dev *imxmd,
774 struct imx_media_video_dev *vdev)
776 mutex_lock(&imxmd->mutex);
778 list_add_tail(&vdev->list, &imxmd->vdev_list);
780 mutex_unlock(&imxmd->mutex);
782 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
785 * Search upstream/downstream for a subdevice or video device pad in the
786 * current pipeline, starting from start_entity. Returns the device's
787 * source/sink pad that it was reached from. Must be called with
788 * mdev->graph_mutex held.
790 * If grp_id != 0, finds a subdevice's pad of given grp_id.
791 * Else If buftype != 0, finds a video device's pad of given buffer type.
792 * Else, returns the nearest source/sink pad to start_entity.
795 imx_media_pipeline_pad(struct media_entity *start_entity, u32 grp_id,
796 enum v4l2_buf_type buftype, bool upstream)
798 struct media_entity *me = start_entity;
799 struct media_pad *pad = NULL;
800 struct video_device *vfd;
801 struct v4l2_subdev *sd;
804 for (i = 0; i < me->num_pads; i++) {
805 struct media_pad *spad = &me->pads[i];
807 if ((upstream && !(spad->flags & MEDIA_PAD_FL_SINK)) ||
808 (!upstream && !(spad->flags & MEDIA_PAD_FL_SOURCE)))
811 pad = media_entity_remote_pad(spad);
816 if (is_media_entity_v4l2_subdev(pad->entity)) {
817 sd = media_entity_to_v4l2_subdev(pad->entity);
818 if (sd->grp_id & grp_id)
822 return imx_media_pipeline_pad(pad->entity, grp_id,
824 } else if (buftype) {
825 if (is_media_entity_v4l2_video_device(pad->entity)) {
826 vfd = media_entity_to_video_device(pad->entity);
827 if (buftype == vfd->queue->type)
831 return imx_media_pipeline_pad(pad->entity, grp_id,
840 EXPORT_SYMBOL_GPL(imx_media_pipeline_pad);
843 * Search upstream/downstream for a subdev or video device in the current
844 * pipeline. Must be called with mdev->graph_mutex held.
846 static struct media_entity *
847 find_pipeline_entity(struct media_entity *start, u32 grp_id,
848 enum v4l2_buf_type buftype, bool upstream)
850 struct media_pad *pad = NULL;
851 struct video_device *vfd;
852 struct v4l2_subdev *sd;
854 if (grp_id && is_media_entity_v4l2_subdev(start)) {
855 sd = media_entity_to_v4l2_subdev(start);
856 if (sd->grp_id & grp_id)
858 } else if (buftype && is_media_entity_v4l2_video_device(start)) {
859 vfd = media_entity_to_video_device(start);
860 if (buftype == vfd->queue->type)
864 pad = imx_media_pipeline_pad(start, grp_id, buftype, upstream);
866 return pad ? pad->entity : NULL;
870 * Find the upstream mipi-csi2 virtual channel reached from the given
871 * start entity in the current pipeline.
872 * Must be called with mdev->graph_mutex held.
874 int imx_media_pipeline_csi2_channel(struct media_entity *start_entity)
876 struct media_pad *pad;
879 pad = imx_media_pipeline_pad(start_entity, IMX_MEDIA_GRP_ID_CSI2,
882 ret = pad->index - 1;
886 EXPORT_SYMBOL_GPL(imx_media_pipeline_csi2_channel);
889 * Find a subdev reached upstream from the given start entity in
890 * the current pipeline.
891 * Must be called with mdev->graph_mutex held.
894 imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id,
897 struct media_entity *me;
899 me = find_pipeline_entity(start_entity, grp_id, 0, upstream);
901 return ERR_PTR(-ENODEV);
903 return media_entity_to_v4l2_subdev(me);
905 EXPORT_SYMBOL_GPL(imx_media_pipeline_subdev);
908 * Find a subdev reached upstream from the given start entity in
909 * the current pipeline.
910 * Must be called with mdev->graph_mutex held.
912 struct video_device *
913 imx_media_pipeline_video_device(struct media_entity *start_entity,
914 enum v4l2_buf_type buftype, bool upstream)
916 struct media_entity *me;
918 me = find_pipeline_entity(start_entity, 0, buftype, upstream);
920 return ERR_PTR(-ENODEV);
922 return media_entity_to_video_device(me);
924 EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device);
927 * Turn current pipeline streaming on/off starting from entity.
929 int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd,
930 struct media_entity *entity,
933 struct v4l2_subdev *sd;
936 if (!is_media_entity_v4l2_subdev(entity))
938 sd = media_entity_to_v4l2_subdev(entity);
940 mutex_lock(&imxmd->md.graph_mutex);
943 ret = __media_pipeline_start(entity, &imxmd->pipe);
946 ret = v4l2_subdev_call(sd, video, s_stream, 1);
948 __media_pipeline_stop(entity);
950 v4l2_subdev_call(sd, video, s_stream, 0);
952 __media_pipeline_stop(entity);
956 mutex_unlock(&imxmd->md.graph_mutex);
959 EXPORT_SYMBOL_GPL(imx_media_pipeline_set_stream);
961 MODULE_DESCRIPTION("i.MX5/6 v4l2 media controller driver");
962 MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
963 MODULE_LICENSE("GPL");