2 * V4L2 Media Controller Driver for Freescale i.MX5/6 SOC
4 * Copyright (c) 2016 Mentor Graphics Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 #include <linux/module.h>
12 #include "imx-media.h"
15 * List of supported pixel formats for the subdevs.
17 * In all of these tables, the non-mbus formats (with no
18 * mbus codes) must all fall at the end of the table.
21 static const struct imx_media_pixfmt yuv_formats[] = {
23 .fourcc = V4L2_PIX_FMT_UYVY,
25 MEDIA_BUS_FMT_UYVY8_2X8,
26 MEDIA_BUS_FMT_UYVY8_1X16
28 .cs = IPUV3_COLORSPACE_YUV,
31 .fourcc = V4L2_PIX_FMT_YUYV,
33 MEDIA_BUS_FMT_YUYV8_2X8,
34 MEDIA_BUS_FMT_YUYV8_1X16
36 .cs = IPUV3_COLORSPACE_YUV,
40 * non-mbus YUV formats start here. NOTE! when adding non-mbus
41 * formats, NUM_NON_MBUS_YUV_FORMATS must be updated below.
44 .fourcc = V4L2_PIX_FMT_YUV420,
45 .cs = IPUV3_COLORSPACE_YUV,
49 .fourcc = V4L2_PIX_FMT_YVU420,
50 .cs = IPUV3_COLORSPACE_YUV,
54 .fourcc = V4L2_PIX_FMT_YUV422P,
55 .cs = IPUV3_COLORSPACE_YUV,
59 .fourcc = V4L2_PIX_FMT_NV12,
60 .cs = IPUV3_COLORSPACE_YUV,
64 .fourcc = V4L2_PIX_FMT_NV16,
65 .cs = IPUV3_COLORSPACE_YUV,
71 #define NUM_NON_MBUS_YUV_FORMATS 5
72 #define NUM_YUV_FORMATS ARRAY_SIZE(yuv_formats)
73 #define NUM_MBUS_YUV_FORMATS (NUM_YUV_FORMATS - NUM_NON_MBUS_YUV_FORMATS)
75 static const struct imx_media_pixfmt rgb_formats[] = {
77 .fourcc = V4L2_PIX_FMT_RGB565,
78 .codes = {MEDIA_BUS_FMT_RGB565_2X8_LE},
79 .cs = IPUV3_COLORSPACE_RGB,
83 .fourcc = V4L2_PIX_FMT_RGB24,
85 MEDIA_BUS_FMT_RGB888_1X24,
86 MEDIA_BUS_FMT_RGB888_2X12_LE
88 .cs = IPUV3_COLORSPACE_RGB,
91 .fourcc = V4L2_PIX_FMT_RGB32,
92 .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
93 .cs = IPUV3_COLORSPACE_RGB,
97 /*** raw bayer and grayscale formats start here ***/
99 .fourcc = V4L2_PIX_FMT_SBGGR8,
100 .codes = {MEDIA_BUS_FMT_SBGGR8_1X8},
101 .cs = IPUV3_COLORSPACE_RGB,
105 .fourcc = V4L2_PIX_FMT_SGBRG8,
106 .codes = {MEDIA_BUS_FMT_SGBRG8_1X8},
107 .cs = IPUV3_COLORSPACE_RGB,
111 .fourcc = V4L2_PIX_FMT_SGRBG8,
112 .codes = {MEDIA_BUS_FMT_SGRBG8_1X8},
113 .cs = IPUV3_COLORSPACE_RGB,
117 .fourcc = V4L2_PIX_FMT_SRGGB8,
118 .codes = {MEDIA_BUS_FMT_SRGGB8_1X8},
119 .cs = IPUV3_COLORSPACE_RGB,
123 .fourcc = V4L2_PIX_FMT_SBGGR16,
125 MEDIA_BUS_FMT_SBGGR10_1X10,
126 MEDIA_BUS_FMT_SBGGR12_1X12,
127 MEDIA_BUS_FMT_SBGGR14_1X14,
128 MEDIA_BUS_FMT_SBGGR16_1X16
130 .cs = IPUV3_COLORSPACE_RGB,
134 .fourcc = V4L2_PIX_FMT_SGBRG16,
136 MEDIA_BUS_FMT_SGBRG10_1X10,
137 MEDIA_BUS_FMT_SGBRG12_1X12,
138 MEDIA_BUS_FMT_SGBRG14_1X14,
139 MEDIA_BUS_FMT_SGBRG16_1X16,
141 .cs = IPUV3_COLORSPACE_RGB,
145 .fourcc = V4L2_PIX_FMT_SGRBG16,
147 MEDIA_BUS_FMT_SGRBG10_1X10,
148 MEDIA_BUS_FMT_SGRBG12_1X12,
149 MEDIA_BUS_FMT_SGRBG14_1X14,
150 MEDIA_BUS_FMT_SGRBG16_1X16,
152 .cs = IPUV3_COLORSPACE_RGB,
156 .fourcc = V4L2_PIX_FMT_SRGGB16,
158 MEDIA_BUS_FMT_SRGGB10_1X10,
159 MEDIA_BUS_FMT_SRGGB12_1X12,
160 MEDIA_BUS_FMT_SRGGB14_1X14,
161 MEDIA_BUS_FMT_SRGGB16_1X16,
163 .cs = IPUV3_COLORSPACE_RGB,
167 .fourcc = V4L2_PIX_FMT_GREY,
168 .codes = {MEDIA_BUS_FMT_Y8_1X8},
169 .cs = IPUV3_COLORSPACE_RGB,
173 .fourcc = V4L2_PIX_FMT_Y16,
175 MEDIA_BUS_FMT_Y10_1X10,
176 MEDIA_BUS_FMT_Y12_1X12,
178 .cs = IPUV3_COLORSPACE_RGB,
183 * non-mbus RGB formats start here. NOTE! when adding non-mbus
184 * formats, NUM_NON_MBUS_RGB_FORMATS must be updated below.
187 .fourcc = V4L2_PIX_FMT_BGR24,
188 .cs = IPUV3_COLORSPACE_RGB,
191 .fourcc = V4L2_PIX_FMT_BGR32,
192 .cs = IPUV3_COLORSPACE_RGB,
197 #define NUM_NON_MBUS_RGB_FORMATS 2
198 #define NUM_RGB_FORMATS ARRAY_SIZE(rgb_formats)
199 #define NUM_MBUS_RGB_FORMATS (NUM_RGB_FORMATS - NUM_NON_MBUS_RGB_FORMATS)
201 static const struct imx_media_pixfmt ipu_yuv_formats[] = {
203 .fourcc = V4L2_PIX_FMT_YUV32,
204 .codes = {MEDIA_BUS_FMT_AYUV8_1X32},
205 .cs = IPUV3_COLORSPACE_YUV,
211 #define NUM_IPU_YUV_FORMATS ARRAY_SIZE(ipu_yuv_formats)
213 static const struct imx_media_pixfmt ipu_rgb_formats[] = {
215 .fourcc = V4L2_PIX_FMT_RGB32,
216 .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
217 .cs = IPUV3_COLORSPACE_RGB,
223 #define NUM_IPU_RGB_FORMATS ARRAY_SIZE(ipu_rgb_formats)
225 static void init_mbus_colorimetry(struct v4l2_mbus_framefmt *mbus,
226 const struct imx_media_pixfmt *fmt)
228 mbus->colorspace = (fmt->cs == IPUV3_COLORSPACE_RGB) ?
229 V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_SMPTE170M;
230 mbus->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(mbus->colorspace);
231 mbus->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(mbus->colorspace);
233 V4L2_MAP_QUANTIZATION_DEFAULT(fmt->cs == IPUV3_COLORSPACE_RGB,
239 struct imx_media_pixfmt *__find_format(u32 fourcc,
243 const struct imx_media_pixfmt *array,
246 const struct imx_media_pixfmt *fmt;
249 for (i = 0; i < array_size; i++) {
252 if ((!allow_non_mbus && !fmt->codes[0]) ||
253 (!allow_bayer && fmt->bayer))
256 if (fourcc && fmt->fourcc == fourcc)
262 for (j = 0; fmt->codes[j]; j++) {
263 if (code == fmt->codes[j])
270 static const struct imx_media_pixfmt *find_format(u32 fourcc,
272 enum codespace_sel cs_sel,
276 const struct imx_media_pixfmt *ret;
280 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
281 yuv_formats, NUM_YUV_FORMATS);
283 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
284 rgb_formats, NUM_RGB_FORMATS);
286 ret = __find_format(fourcc, code, allow_non_mbus, allow_bayer,
287 yuv_formats, NUM_YUV_FORMATS);
290 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
291 rgb_formats, NUM_RGB_FORMATS);
297 static int enum_format(u32 *fourcc, u32 *code, u32 index,
298 enum codespace_sel cs_sel,
302 const struct imx_media_pixfmt *fmt;
303 u32 mbus_yuv_sz = NUM_MBUS_YUV_FORMATS;
304 u32 mbus_rgb_sz = NUM_MBUS_RGB_FORMATS;
305 u32 yuv_sz = NUM_YUV_FORMATS;
306 u32 rgb_sz = NUM_RGB_FORMATS;
310 if (index >= yuv_sz ||
311 (!allow_non_mbus && index >= mbus_yuv_sz))
313 fmt = &yuv_formats[index];
316 if (index >= rgb_sz ||
317 (!allow_non_mbus && index >= mbus_rgb_sz))
319 fmt = &rgb_formats[index];
320 if (!allow_bayer && fmt->bayer)
324 if (!allow_non_mbus) {
325 if (index >= mbus_yuv_sz) {
326 index -= mbus_yuv_sz;
327 if (index >= mbus_rgb_sz)
329 fmt = &rgb_formats[index];
330 if (!allow_bayer && fmt->bayer)
333 fmt = &yuv_formats[index];
336 if (index >= yuv_sz + rgb_sz)
338 if (index >= yuv_sz) {
339 fmt = &rgb_formats[index - yuv_sz];
340 if (!allow_bayer && fmt->bayer)
343 fmt = &yuv_formats[index];
352 *fourcc = fmt->fourcc;
354 *code = fmt->codes[0];
359 const struct imx_media_pixfmt *
360 imx_media_find_format(u32 fourcc, enum codespace_sel cs_sel, bool allow_bayer)
362 return find_format(fourcc, 0, cs_sel, true, allow_bayer);
364 EXPORT_SYMBOL_GPL(imx_media_find_format);
366 int imx_media_enum_format(u32 *fourcc, u32 index, enum codespace_sel cs_sel)
368 return enum_format(fourcc, NULL, index, cs_sel, true, false);
370 EXPORT_SYMBOL_GPL(imx_media_enum_format);
372 const struct imx_media_pixfmt *
373 imx_media_find_mbus_format(u32 code, enum codespace_sel cs_sel,
376 return find_format(0, code, cs_sel, false, allow_bayer);
378 EXPORT_SYMBOL_GPL(imx_media_find_mbus_format);
380 int imx_media_enum_mbus_format(u32 *code, u32 index, enum codespace_sel cs_sel,
383 return enum_format(NULL, code, index, cs_sel, false, allow_bayer);
385 EXPORT_SYMBOL_GPL(imx_media_enum_mbus_format);
387 const struct imx_media_pixfmt *
388 imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel)
390 const struct imx_media_pixfmt *array, *fmt, *ret = NULL;
396 array_size = NUM_IPU_YUV_FORMATS;
397 array = ipu_yuv_formats;
400 array_size = NUM_IPU_RGB_FORMATS;
401 array = ipu_rgb_formats;
404 array_size = NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS;
405 array = ipu_yuv_formats;
411 for (i = 0; i < array_size; i++) {
412 if (cs_sel == CS_SEL_ANY && i >= NUM_IPU_YUV_FORMATS)
413 fmt = &ipu_rgb_formats[i - NUM_IPU_YUV_FORMATS];
417 for (j = 0; code && fmt->codes[j]; j++) {
418 if (code == fmt->codes[j]) {
428 EXPORT_SYMBOL_GPL(imx_media_find_ipu_format);
430 int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel)
434 if (index >= NUM_IPU_YUV_FORMATS)
436 *code = ipu_yuv_formats[index].codes[0];
439 if (index >= NUM_IPU_RGB_FORMATS)
441 *code = ipu_rgb_formats[index].codes[0];
444 if (index >= NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS)
446 if (index >= NUM_IPU_YUV_FORMATS) {
447 index -= NUM_IPU_YUV_FORMATS;
448 *code = ipu_rgb_formats[index].codes[0];
450 *code = ipu_yuv_formats[index].codes[0];
459 EXPORT_SYMBOL_GPL(imx_media_enum_ipu_format);
461 int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
462 u32 width, u32 height, u32 code, u32 field,
463 const struct imx_media_pixfmt **cc)
465 const struct imx_media_pixfmt *lcc;
468 mbus->height = height;
471 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
472 lcc = imx_media_find_mbus_format(code, CS_SEL_ANY, false);
474 lcc = imx_media_find_ipu_format(code, CS_SEL_ANY);
480 init_mbus_colorimetry(mbus, lcc);
486 EXPORT_SYMBOL_GPL(imx_media_init_mbus_fmt);
489 * Initializes the TRY format to the ACTIVE format on all pads
490 * of a subdev. Can be used as the .init_cfg pad operation.
492 int imx_media_init_cfg(struct v4l2_subdev *sd,
493 struct v4l2_subdev_pad_config *cfg)
495 struct v4l2_mbus_framefmt *mf_try;
496 struct v4l2_subdev_format format;
500 for (pad = 0; pad < sd->entity.num_pads; pad++) {
501 memset(&format, 0, sizeof(format));
504 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
505 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);
509 mf_try = v4l2_subdev_get_try_format(sd, cfg, pad);
510 *mf_try = format.format;
515 EXPORT_SYMBOL_GPL(imx_media_init_cfg);
518 * Check whether the field and colorimetry parameters in tryfmt are
519 * uninitialized, and if so fill them with the values from fmt,
520 * or if tryfmt->colorspace has been initialized, all the default
521 * colorimetry params can be derived from tryfmt->colorspace.
523 * tryfmt->code must be set on entry.
525 * If this format is destined to be routed through the Image Converter,
526 * quantization and Y`CbCr encoding must be fixed. The IC expects and
527 * produces fixed quantization and Y`CbCr encoding at its input and output
528 * (full range for RGB, limited range for YUV, and V4L2_YCBCR_ENC_601).
530 void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt,
531 struct v4l2_mbus_framefmt *fmt,
534 const struct imx_media_pixfmt *cc;
537 cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true);
539 cc = imx_media_find_ipu_format(tryfmt->code, CS_SEL_ANY);
540 if (cc && cc->cs != IPUV3_COLORSPACE_YUV)
543 /* fill field if necessary */
544 if (tryfmt->field == V4L2_FIELD_ANY)
545 tryfmt->field = fmt->field;
547 /* fill colorimetry if necessary */
548 if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) {
549 tryfmt->colorspace = fmt->colorspace;
550 tryfmt->xfer_func = fmt->xfer_func;
551 tryfmt->ycbcr_enc = fmt->ycbcr_enc;
552 tryfmt->quantization = fmt->quantization;
554 if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT) {
556 V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace);
558 if (tryfmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
560 V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace);
562 if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT) {
563 tryfmt->quantization =
564 V4L2_MAP_QUANTIZATION_DEFAULT(
565 is_rgb, tryfmt->colorspace,
571 tryfmt->quantization = is_rgb ?
572 V4L2_QUANTIZATION_FULL_RANGE :
573 V4L2_QUANTIZATION_LIM_RANGE;
574 tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
577 EXPORT_SYMBOL_GPL(imx_media_fill_default_mbus_fields);
579 int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
580 struct v4l2_mbus_framefmt *mbus,
581 const struct imx_media_pixfmt *cc)
586 cc = imx_media_find_ipu_format(mbus->code, CS_SEL_ANY);
588 cc = imx_media_find_mbus_format(mbus->code, CS_SEL_ANY,
595 * TODO: the IPU currently does not support the AYUV32 format,
596 * so until it does convert to a supported YUV format.
598 if (cc->ipufmt && cc->cs == IPUV3_COLORSPACE_YUV) {
601 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
602 cc = imx_media_find_mbus_format(code, CS_SEL_YUV, false);
605 stride = cc->planar ? mbus->width : (mbus->width * cc->bpp) >> 3;
607 pix->width = mbus->width;
608 pix->height = mbus->height;
609 pix->pixelformat = cc->fourcc;
610 pix->colorspace = mbus->colorspace;
611 pix->xfer_func = mbus->xfer_func;
612 pix->ycbcr_enc = mbus->ycbcr_enc;
613 pix->quantization = mbus->quantization;
614 pix->field = mbus->field;
615 pix->bytesperline = stride;
616 pix->sizeimage = (pix->width * pix->height * cc->bpp) >> 3;
620 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_pix_fmt);
622 int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image,
623 struct v4l2_mbus_framefmt *mbus)
627 memset(image, 0, sizeof(*image));
629 ret = imx_media_mbus_fmt_to_pix_fmt(&image->pix, mbus, NULL);
633 image->rect.width = mbus->width;
634 image->rect.height = mbus->height;
638 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_ipu_image);
640 int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
641 struct ipu_image *image)
643 const struct imx_media_pixfmt *fmt;
645 fmt = imx_media_find_format(image->pix.pixelformat, CS_SEL_ANY, true);
649 memset(mbus, 0, sizeof(*mbus));
650 mbus->width = image->pix.width;
651 mbus->height = image->pix.height;
652 mbus->code = fmt->codes[0];
653 mbus->field = image->pix.field;
654 mbus->colorspace = image->pix.colorspace;
655 mbus->xfer_func = image->pix.xfer_func;
656 mbus->ycbcr_enc = image->pix.ycbcr_enc;
657 mbus->quantization = image->pix.quantization;
661 EXPORT_SYMBOL_GPL(imx_media_ipu_image_to_mbus_fmt);
663 void imx_media_free_dma_buf(struct imx_media_dev *imxmd,
664 struct imx_media_dma_buf *buf)
667 dma_free_coherent(imxmd->md.dev, buf->len,
668 buf->virt, buf->phys);
673 EXPORT_SYMBOL_GPL(imx_media_free_dma_buf);
675 int imx_media_alloc_dma_buf(struct imx_media_dev *imxmd,
676 struct imx_media_dma_buf *buf,
679 imx_media_free_dma_buf(imxmd, buf);
681 buf->len = PAGE_ALIGN(size);
682 buf->virt = dma_alloc_coherent(imxmd->md.dev, buf->len, &buf->phys,
683 GFP_DMA | GFP_KERNEL);
685 dev_err(imxmd->md.dev, "failed to alloc dma buffer\n");
691 EXPORT_SYMBOL_GPL(imx_media_alloc_dma_buf);
693 /* form a subdev name given a group id and ipu id */
694 void imx_media_grp_id_to_sd_name(char *sd_name, int sz, u32 grp_id, int ipu_id)
699 case IMX_MEDIA_GRP_ID_CSI0...IMX_MEDIA_GRP_ID_CSI1:
700 id = (grp_id >> IMX_MEDIA_GRP_ID_CSI_BIT) - 1;
701 snprintf(sd_name, sz, "ipu%d_csi%d", ipu_id + 1, id);
703 case IMX_MEDIA_GRP_ID_VDIC:
704 snprintf(sd_name, sz, "ipu%d_vdic", ipu_id + 1);
706 case IMX_MEDIA_GRP_ID_IC_PRP:
707 snprintf(sd_name, sz, "ipu%d_ic_prp", ipu_id + 1);
709 case IMX_MEDIA_GRP_ID_IC_PRPENC:
710 snprintf(sd_name, sz, "ipu%d_ic_prpenc", ipu_id + 1);
712 case IMX_MEDIA_GRP_ID_IC_PRPVF:
713 snprintf(sd_name, sz, "ipu%d_ic_prpvf", ipu_id + 1);
719 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name);
722 imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
723 struct fwnode_handle *fwnode)
725 struct v4l2_subdev *sd;
727 list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
728 if (sd->fwnode == fwnode)
734 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_fwnode);
737 imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
740 struct v4l2_subdev *sd;
742 list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
743 if (!strcmp(devname, dev_name(sd->dev)))
749 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
752 * Adds a video device to the master video device list. This is called by
753 * an async subdev that owns a video device when it is registered.
755 int imx_media_add_video_device(struct imx_media_dev *imxmd,
756 struct imx_media_video_dev *vdev)
758 mutex_lock(&imxmd->mutex);
760 list_add_tail(&vdev->list, &imxmd->vdev_list);
762 mutex_unlock(&imxmd->mutex);
765 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
768 * Search upstream/downstream for a subdevice in the current pipeline
769 * with given grp_id, starting from start_entity. Returns the subdev's
770 * source/sink pad that it was reached from. If grp_id is zero, just
771 * returns the nearest source/sink pad to start_entity. Must be called
772 * with mdev->graph_mutex held.
774 static struct media_pad *
775 find_pipeline_pad(struct imx_media_dev *imxmd,
776 struct media_entity *start_entity,
777 u32 grp_id, bool upstream)
779 struct media_entity *me = start_entity;
780 struct media_pad *pad = NULL;
781 struct v4l2_subdev *sd;
784 for (i = 0; i < me->num_pads; i++) {
785 struct media_pad *spad = &me->pads[i];
787 if ((upstream && !(spad->flags & MEDIA_PAD_FL_SINK)) ||
788 (!upstream && !(spad->flags & MEDIA_PAD_FL_SOURCE)))
791 pad = media_entity_remote_pad(spad);
792 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
796 sd = media_entity_to_v4l2_subdev(pad->entity);
797 if (sd->grp_id & grp_id)
800 return find_pipeline_pad(imxmd, pad->entity,
811 * Search upstream for a subdev in the current pipeline with
812 * given grp_id. Must be called with mdev->graph_mutex held.
814 static struct v4l2_subdev *
815 find_upstream_subdev(struct imx_media_dev *imxmd,
816 struct media_entity *start_entity,
819 struct v4l2_subdev *sd;
820 struct media_pad *pad;
822 if (is_media_entity_v4l2_subdev(start_entity)) {
823 sd = media_entity_to_v4l2_subdev(start_entity);
824 if (sd->grp_id & grp_id)
828 pad = find_pipeline_pad(imxmd, start_entity, grp_id, true);
830 return pad ? media_entity_to_v4l2_subdev(pad->entity) : NULL;
834 * Find the upstream mipi-csi2 virtual channel reached from the given
835 * start entity in the current pipeline.
836 * Must be called with mdev->graph_mutex held.
838 int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
839 struct media_entity *start_entity)
841 struct media_pad *pad;
844 pad = find_pipeline_pad(imxmd, start_entity, IMX_MEDIA_GRP_ID_CSI2,
847 ret = pad->index - 1;
848 dev_dbg(imxmd->md.dev, "found vc%d from %s\n",
849 ret, start_entity->name);
854 EXPORT_SYMBOL_GPL(imx_media_find_mipi_csi2_channel);
857 * Find a source pad reached upstream from the given start entity in
858 * the current pipeline. Must be called with mdev->graph_mutex held.
861 imx_media_find_upstream_pad(struct imx_media_dev *imxmd,
862 struct media_entity *start_entity,
865 struct media_pad *pad;
867 pad = find_pipeline_pad(imxmd, start_entity, grp_id, true);
869 return ERR_PTR(-ENODEV);
873 EXPORT_SYMBOL_GPL(imx_media_find_upstream_pad);
876 * Find a subdev reached upstream from the given start entity in
877 * the current pipeline.
878 * Must be called with mdev->graph_mutex held.
881 imx_media_find_upstream_subdev(struct imx_media_dev *imxmd,
882 struct media_entity *start_entity,
885 struct v4l2_subdev *sd;
887 sd = find_upstream_subdev(imxmd, start_entity, grp_id);
889 return ERR_PTR(-ENODEV);
893 EXPORT_SYMBOL_GPL(imx_media_find_upstream_subdev);
896 * Turn current pipeline streaming on/off starting from entity.
898 int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd,
899 struct media_entity *entity,
902 struct v4l2_subdev *sd;
905 if (!is_media_entity_v4l2_subdev(entity))
907 sd = media_entity_to_v4l2_subdev(entity);
909 mutex_lock(&imxmd->md.graph_mutex);
912 ret = __media_pipeline_start(entity, &imxmd->pipe);
915 ret = v4l2_subdev_call(sd, video, s_stream, 1);
917 __media_pipeline_stop(entity);
919 v4l2_subdev_call(sd, video, s_stream, 0);
921 __media_pipeline_stop(entity);
925 mutex_unlock(&imxmd->md.graph_mutex);
928 EXPORT_SYMBOL_GPL(imx_media_pipeline_set_stream);
930 MODULE_DESCRIPTION("i.MX5/6 v4l2 media controller driver");
931 MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
932 MODULE_LICENSE("GPL");