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,
82 .fourcc = V4L2_PIX_FMT_RGB24,
84 MEDIA_BUS_FMT_RGB888_1X24,
85 MEDIA_BUS_FMT_RGB888_2X12_LE
87 .cs = IPUV3_COLORSPACE_RGB,
90 .fourcc = V4L2_PIX_FMT_RGB32,
91 .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
92 .cs = IPUV3_COLORSPACE_RGB,
96 /*** raw bayer formats start here ***/
98 .fourcc = V4L2_PIX_FMT_SBGGR8,
99 .codes = {MEDIA_BUS_FMT_SBGGR8_1X8},
100 .cs = IPUV3_COLORSPACE_RGB,
104 .fourcc = V4L2_PIX_FMT_SGBRG8,
105 .codes = {MEDIA_BUS_FMT_SGBRG8_1X8},
106 .cs = IPUV3_COLORSPACE_RGB,
110 .fourcc = V4L2_PIX_FMT_SGRBG8,
111 .codes = {MEDIA_BUS_FMT_SGRBG8_1X8},
112 .cs = IPUV3_COLORSPACE_RGB,
116 .fourcc = V4L2_PIX_FMT_SRGGB8,
117 .codes = {MEDIA_BUS_FMT_SRGGB8_1X8},
118 .cs = IPUV3_COLORSPACE_RGB,
122 .fourcc = V4L2_PIX_FMT_SBGGR16,
124 MEDIA_BUS_FMT_SBGGR10_1X10,
125 MEDIA_BUS_FMT_SBGGR12_1X12,
126 MEDIA_BUS_FMT_SBGGR14_1X14,
127 MEDIA_BUS_FMT_SBGGR16_1X16
129 .cs = IPUV3_COLORSPACE_RGB,
133 .fourcc = V4L2_PIX_FMT_SGBRG16,
135 MEDIA_BUS_FMT_SGBRG10_1X10,
136 MEDIA_BUS_FMT_SGBRG12_1X12,
137 MEDIA_BUS_FMT_SGBRG14_1X14,
138 MEDIA_BUS_FMT_SGBRG16_1X16,
140 .cs = IPUV3_COLORSPACE_RGB,
144 .fourcc = V4L2_PIX_FMT_SGRBG16,
146 MEDIA_BUS_FMT_SGRBG10_1X10,
147 MEDIA_BUS_FMT_SGRBG12_1X12,
148 MEDIA_BUS_FMT_SGRBG14_1X14,
149 MEDIA_BUS_FMT_SGRBG16_1X16,
151 .cs = IPUV3_COLORSPACE_RGB,
155 .fourcc = V4L2_PIX_FMT_SRGGB16,
157 MEDIA_BUS_FMT_SRGGB10_1X10,
158 MEDIA_BUS_FMT_SRGGB12_1X12,
159 MEDIA_BUS_FMT_SRGGB14_1X14,
160 MEDIA_BUS_FMT_SRGGB16_1X16,
162 .cs = IPUV3_COLORSPACE_RGB,
167 * non-mbus RGB formats start here. NOTE! when adding non-mbus
168 * formats, NUM_NON_MBUS_RGB_FORMATS must be updated below.
171 .fourcc = V4L2_PIX_FMT_BGR24,
172 .cs = IPUV3_COLORSPACE_RGB,
175 .fourcc = V4L2_PIX_FMT_BGR32,
176 .cs = IPUV3_COLORSPACE_RGB,
181 #define NUM_NON_MBUS_RGB_FORMATS 2
182 #define NUM_RGB_FORMATS ARRAY_SIZE(rgb_formats)
183 #define NUM_MBUS_RGB_FORMATS (NUM_RGB_FORMATS - NUM_NON_MBUS_RGB_FORMATS)
185 static const struct imx_media_pixfmt ipu_yuv_formats[] = {
187 .fourcc = V4L2_PIX_FMT_YUV32,
188 .codes = {MEDIA_BUS_FMT_AYUV8_1X32},
189 .cs = IPUV3_COLORSPACE_YUV,
195 #define NUM_IPU_YUV_FORMATS ARRAY_SIZE(ipu_yuv_formats)
197 static const struct imx_media_pixfmt ipu_rgb_formats[] = {
199 .fourcc = V4L2_PIX_FMT_RGB32,
200 .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
201 .cs = IPUV3_COLORSPACE_RGB,
207 #define NUM_IPU_RGB_FORMATS ARRAY_SIZE(ipu_rgb_formats)
209 static void init_mbus_colorimetry(struct v4l2_mbus_framefmt *mbus,
210 const struct imx_media_pixfmt *fmt)
212 mbus->colorspace = (fmt->cs == IPUV3_COLORSPACE_RGB) ?
213 V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_SMPTE170M;
214 mbus->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(mbus->colorspace);
215 mbus->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(mbus->colorspace);
217 V4L2_MAP_QUANTIZATION_DEFAULT(fmt->cs == IPUV3_COLORSPACE_RGB,
222 static const struct imx_media_pixfmt *find_format(u32 fourcc,
224 enum codespace_sel cs_sel,
228 const struct imx_media_pixfmt *array, *fmt, *ret = NULL;
234 array_size = NUM_YUV_FORMATS;
238 array_size = NUM_RGB_FORMATS;
242 array_size = NUM_YUV_FORMATS + NUM_RGB_FORMATS;
249 for (i = 0; i < array_size; i++) {
250 if (cs_sel == CS_SEL_ANY && i >= NUM_YUV_FORMATS)
251 fmt = &rgb_formats[i - NUM_YUV_FORMATS];
255 if ((!allow_non_mbus && fmt->codes[0] == 0) ||
256 (!allow_bayer && fmt->bayer))
259 if (fourcc && fmt->fourcc == fourcc) {
264 for (j = 0; code && fmt->codes[j]; j++) {
265 if (code == fmt->codes[j]) {
276 static int enum_format(u32 *fourcc, u32 *code, u32 index,
277 enum codespace_sel cs_sel,
281 const struct imx_media_pixfmt *fmt;
282 u32 mbus_yuv_sz = NUM_MBUS_YUV_FORMATS;
283 u32 mbus_rgb_sz = NUM_MBUS_RGB_FORMATS;
284 u32 yuv_sz = NUM_YUV_FORMATS;
285 u32 rgb_sz = NUM_RGB_FORMATS;
289 if (index >= yuv_sz ||
290 (!allow_non_mbus && index >= mbus_yuv_sz))
292 fmt = &yuv_formats[index];
295 if (index >= rgb_sz ||
296 (!allow_non_mbus && index >= mbus_rgb_sz))
298 fmt = &rgb_formats[index];
299 if (!allow_bayer && fmt->bayer)
303 if (!allow_non_mbus) {
304 if (index >= mbus_yuv_sz) {
305 index -= mbus_yuv_sz;
306 if (index >= mbus_rgb_sz)
308 fmt = &rgb_formats[index];
309 if (!allow_bayer && fmt->bayer)
312 fmt = &yuv_formats[index];
315 if (index >= yuv_sz + rgb_sz)
317 if (index >= yuv_sz) {
318 fmt = &rgb_formats[index - yuv_sz];
319 if (!allow_bayer && fmt->bayer)
322 fmt = &yuv_formats[index];
331 *fourcc = fmt->fourcc;
333 *code = fmt->codes[0];
338 const struct imx_media_pixfmt *
339 imx_media_find_format(u32 fourcc, enum codespace_sel cs_sel, bool allow_bayer)
341 return find_format(fourcc, 0, cs_sel, true, allow_bayer);
343 EXPORT_SYMBOL_GPL(imx_media_find_format);
345 int imx_media_enum_format(u32 *fourcc, u32 index, enum codespace_sel cs_sel)
347 return enum_format(fourcc, NULL, index, cs_sel, true, false);
349 EXPORT_SYMBOL_GPL(imx_media_enum_format);
351 const struct imx_media_pixfmt *
352 imx_media_find_mbus_format(u32 code, enum codespace_sel cs_sel,
355 return find_format(0, code, cs_sel, false, allow_bayer);
357 EXPORT_SYMBOL_GPL(imx_media_find_mbus_format);
359 int imx_media_enum_mbus_format(u32 *code, u32 index, enum codespace_sel cs_sel,
362 return enum_format(NULL, code, index, cs_sel, false, allow_bayer);
364 EXPORT_SYMBOL_GPL(imx_media_enum_mbus_format);
366 const struct imx_media_pixfmt *
367 imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel)
369 const struct imx_media_pixfmt *array, *fmt, *ret = NULL;
375 array_size = NUM_IPU_YUV_FORMATS;
376 array = ipu_yuv_formats;
379 array_size = NUM_IPU_RGB_FORMATS;
380 array = ipu_rgb_formats;
383 array_size = NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS;
384 array = ipu_yuv_formats;
390 for (i = 0; i < array_size; i++) {
391 if (cs_sel == CS_SEL_ANY && i >= NUM_IPU_YUV_FORMATS)
392 fmt = &ipu_rgb_formats[i - NUM_IPU_YUV_FORMATS];
396 for (j = 0; code && fmt->codes[j]; j++) {
397 if (code == fmt->codes[j]) {
407 EXPORT_SYMBOL_GPL(imx_media_find_ipu_format);
409 int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel)
413 if (index >= NUM_IPU_YUV_FORMATS)
415 *code = ipu_yuv_formats[index].codes[0];
418 if (index >= NUM_IPU_RGB_FORMATS)
420 *code = ipu_rgb_formats[index].codes[0];
423 if (index >= NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS)
425 if (index >= NUM_IPU_YUV_FORMATS) {
426 index -= NUM_IPU_YUV_FORMATS;
427 *code = ipu_rgb_formats[index].codes[0];
429 *code = ipu_yuv_formats[index].codes[0];
438 EXPORT_SYMBOL_GPL(imx_media_enum_ipu_format);
440 int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
441 u32 width, u32 height, u32 code, u32 field,
442 const struct imx_media_pixfmt **cc)
444 const struct imx_media_pixfmt *lcc;
447 mbus->height = height;
450 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
451 lcc = imx_media_find_mbus_format(code, CS_SEL_ANY, false);
453 lcc = imx_media_find_ipu_format(code, CS_SEL_ANY);
459 init_mbus_colorimetry(mbus, lcc);
465 EXPORT_SYMBOL_GPL(imx_media_init_mbus_fmt);
468 * Check whether the field and colorimetry parameters in tryfmt are
469 * uninitialized, and if so fill them with the values from fmt,
470 * or if tryfmt->colorspace has been initialized, all the default
471 * colorimetry params can be derived from tryfmt->colorspace.
473 * tryfmt->code must be set on entry.
475 * If this format is destined to be routed through the Image Converter,
476 * quantization and Y`CbCr encoding must be fixed. The IC expects and
477 * produces fixed quantization and Y`CbCr encoding at its input and output
478 * (full range for RGB, limited range for YUV, and V4L2_YCBCR_ENC_601).
480 void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt,
481 struct v4l2_mbus_framefmt *fmt,
484 const struct imx_media_pixfmt *cc;
487 cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true);
489 cc = imx_media_find_ipu_format(tryfmt->code, CS_SEL_ANY);
490 if (cc && cc->cs != IPUV3_COLORSPACE_YUV)
493 /* fill field if necessary */
494 if (tryfmt->field == V4L2_FIELD_ANY)
495 tryfmt->field = fmt->field;
497 /* fill colorimetry if necessary */
498 if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) {
499 tryfmt->colorspace = fmt->colorspace;
500 tryfmt->xfer_func = fmt->xfer_func;
501 tryfmt->ycbcr_enc = fmt->ycbcr_enc;
502 tryfmt->quantization = fmt->quantization;
504 if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT) {
506 V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace);
508 if (tryfmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
510 V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace);
512 if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT) {
513 tryfmt->quantization =
514 V4L2_MAP_QUANTIZATION_DEFAULT(
515 is_rgb, tryfmt->colorspace,
521 tryfmt->quantization = is_rgb ?
522 V4L2_QUANTIZATION_FULL_RANGE :
523 V4L2_QUANTIZATION_LIM_RANGE;
524 tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
527 EXPORT_SYMBOL_GPL(imx_media_fill_default_mbus_fields);
529 int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
530 struct v4l2_mbus_framefmt *mbus,
531 const struct imx_media_pixfmt *cc)
536 cc = imx_media_find_ipu_format(mbus->code, CS_SEL_ANY);
538 cc = imx_media_find_mbus_format(mbus->code, CS_SEL_ANY,
545 * TODO: the IPU currently does not support the AYUV32 format,
546 * so until it does convert to a supported YUV format.
548 if (cc->ipufmt && cc->cs == IPUV3_COLORSPACE_YUV) {
551 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
552 cc = imx_media_find_mbus_format(code, CS_SEL_YUV, false);
555 stride = cc->planar ? mbus->width : (mbus->width * cc->bpp) >> 3;
557 pix->width = mbus->width;
558 pix->height = mbus->height;
559 pix->pixelformat = cc->fourcc;
560 pix->colorspace = mbus->colorspace;
561 pix->xfer_func = mbus->xfer_func;
562 pix->ycbcr_enc = mbus->ycbcr_enc;
563 pix->quantization = mbus->quantization;
564 pix->field = mbus->field;
565 pix->bytesperline = stride;
566 pix->sizeimage = (pix->width * pix->height * cc->bpp) >> 3;
570 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_pix_fmt);
572 int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image,
573 struct v4l2_mbus_framefmt *mbus)
577 memset(image, 0, sizeof(*image));
579 ret = imx_media_mbus_fmt_to_pix_fmt(&image->pix, mbus, NULL);
583 image->rect.width = mbus->width;
584 image->rect.height = mbus->height;
588 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_ipu_image);
590 int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
591 struct ipu_image *image)
593 const struct imx_media_pixfmt *fmt;
595 fmt = imx_media_find_format(image->pix.pixelformat, CS_SEL_ANY, true);
599 memset(mbus, 0, sizeof(*mbus));
600 mbus->width = image->pix.width;
601 mbus->height = image->pix.height;
602 mbus->code = fmt->codes[0];
603 mbus->field = image->pix.field;
604 mbus->colorspace = image->pix.colorspace;
605 mbus->xfer_func = image->pix.xfer_func;
606 mbus->ycbcr_enc = image->pix.ycbcr_enc;
607 mbus->quantization = image->pix.quantization;
611 EXPORT_SYMBOL_GPL(imx_media_ipu_image_to_mbus_fmt);
613 void imx_media_free_dma_buf(struct imx_media_dev *imxmd,
614 struct imx_media_dma_buf *buf)
617 dma_free_coherent(imxmd->md.dev, buf->len,
618 buf->virt, buf->phys);
623 EXPORT_SYMBOL_GPL(imx_media_free_dma_buf);
625 int imx_media_alloc_dma_buf(struct imx_media_dev *imxmd,
626 struct imx_media_dma_buf *buf,
629 imx_media_free_dma_buf(imxmd, buf);
631 buf->len = PAGE_ALIGN(size);
632 buf->virt = dma_alloc_coherent(imxmd->md.dev, buf->len, &buf->phys,
633 GFP_DMA | GFP_KERNEL);
635 dev_err(imxmd->md.dev, "failed to alloc dma buffer\n");
641 EXPORT_SYMBOL_GPL(imx_media_alloc_dma_buf);
643 /* form a subdev name given a group id and ipu id */
644 void imx_media_grp_id_to_sd_name(char *sd_name, int sz, u32 grp_id, int ipu_id)
649 case IMX_MEDIA_GRP_ID_CSI0...IMX_MEDIA_GRP_ID_CSI1:
650 id = (grp_id >> IMX_MEDIA_GRP_ID_CSI_BIT) - 1;
651 snprintf(sd_name, sz, "ipu%d_csi%d", ipu_id + 1, id);
653 case IMX_MEDIA_GRP_ID_VDIC:
654 snprintf(sd_name, sz, "ipu%d_vdic", ipu_id + 1);
656 case IMX_MEDIA_GRP_ID_IC_PRP:
657 snprintf(sd_name, sz, "ipu%d_ic_prp", ipu_id + 1);
659 case IMX_MEDIA_GRP_ID_IC_PRPENC:
660 snprintf(sd_name, sz, "ipu%d_ic_prpenc", ipu_id + 1);
662 case IMX_MEDIA_GRP_ID_IC_PRPVF:
663 snprintf(sd_name, sz, "ipu%d_ic_prpvf", ipu_id + 1);
669 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name);
671 struct imx_media_subdev *
672 imx_media_find_subdev_by_sd(struct imx_media_dev *imxmd,
673 struct v4l2_subdev *sd)
675 struct imx_media_subdev *imxsd;
678 for (i = 0; i < imxmd->num_subdevs; i++) {
679 imxsd = &imxmd->subdev[i];
684 return ERR_PTR(-ENODEV);
686 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_sd);
688 struct imx_media_subdev *
689 imx_media_find_subdev_by_id(struct imx_media_dev *imxmd, u32 grp_id)
691 struct imx_media_subdev *imxsd;
694 for (i = 0; i < imxmd->num_subdevs; i++) {
695 imxsd = &imxmd->subdev[i];
696 if (imxsd->sd && imxsd->sd->grp_id == grp_id)
700 return ERR_PTR(-ENODEV);
702 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_id);
705 * Adds a video device to the master video device list. This is called by
706 * an async subdev that owns a video device when it is registered.
708 int imx_media_add_video_device(struct imx_media_dev *imxmd,
709 struct imx_media_video_dev *vdev)
711 int vdev_idx, ret = 0;
713 mutex_lock(&imxmd->mutex);
715 vdev_idx = imxmd->num_vdevs;
716 if (vdev_idx >= IMX_MEDIA_MAX_VDEVS) {
717 dev_err(imxmd->md.dev,
718 "%s: too many video devices! can't add %s\n",
719 __func__, vdev->vfd->name);
724 imxmd->vdev[vdev_idx] = vdev;
727 mutex_unlock(&imxmd->mutex);
730 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
733 * Search upstream or downstream for a subdevice in the current pipeline
734 * with given grp_id, starting from start_entity. Returns the subdev's
735 * source/sink pad that it was reached from. Must be called with
736 * mdev->graph_mutex held.
738 static struct media_pad *
739 find_pipeline_pad(struct imx_media_dev *imxmd,
740 struct media_entity *start_entity,
741 u32 grp_id, bool upstream)
743 struct media_entity *me = start_entity;
744 struct media_pad *pad = NULL;
745 struct v4l2_subdev *sd;
748 for (i = 0; i < me->num_pads; i++) {
749 struct media_pad *spad = &me->pads[i];
751 if ((upstream && !(spad->flags & MEDIA_PAD_FL_SINK)) ||
752 (!upstream && !(spad->flags & MEDIA_PAD_FL_SOURCE)))
755 pad = media_entity_remote_pad(spad);
756 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
759 sd = media_entity_to_v4l2_subdev(pad->entity);
760 if (sd->grp_id & grp_id)
763 return find_pipeline_pad(imxmd, pad->entity, grp_id, upstream);
770 * Search upstream for a subdev in the current pipeline with
771 * given grp_id. Must be called with mdev->graph_mutex held.
773 static struct v4l2_subdev *
774 find_upstream_subdev(struct imx_media_dev *imxmd,
775 struct media_entity *start_entity,
778 struct v4l2_subdev *sd;
779 struct media_pad *pad;
781 if (is_media_entity_v4l2_subdev(start_entity)) {
782 sd = media_entity_to_v4l2_subdev(start_entity);
783 if (sd->grp_id & grp_id)
787 pad = find_pipeline_pad(imxmd, start_entity, grp_id, true);
789 return pad ? media_entity_to_v4l2_subdev(pad->entity) : NULL;
794 * Find the upstream mipi-csi2 virtual channel reached from the given
795 * start entity in the current pipeline.
796 * Must be called with mdev->graph_mutex held.
798 int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
799 struct media_entity *start_entity)
801 struct media_pad *pad;
804 pad = find_pipeline_pad(imxmd, start_entity, IMX_MEDIA_GRP_ID_CSI2,
807 ret = pad->index - 1;
808 dev_dbg(imxmd->md.dev, "found vc%d from %s\n",
809 ret, start_entity->name);
814 EXPORT_SYMBOL_GPL(imx_media_find_mipi_csi2_channel);
817 * Find a subdev reached upstream from the given start entity in
818 * the current pipeline.
819 * Must be called with mdev->graph_mutex held.
821 struct imx_media_subdev *
822 imx_media_find_upstream_subdev(struct imx_media_dev *imxmd,
823 struct media_entity *start_entity,
826 struct v4l2_subdev *sd;
828 sd = find_upstream_subdev(imxmd, start_entity, grp_id);
830 return ERR_PTR(-ENODEV);
832 return imx_media_find_subdev_by_sd(imxmd, sd);
834 EXPORT_SYMBOL_GPL(imx_media_find_upstream_subdev);
836 struct imx_media_subdev *
837 __imx_media_find_sensor(struct imx_media_dev *imxmd,
838 struct media_entity *start_entity)
840 return imx_media_find_upstream_subdev(imxmd, start_entity,
841 IMX_MEDIA_GRP_ID_SENSOR);
843 EXPORT_SYMBOL_GPL(__imx_media_find_sensor);
845 struct imx_media_subdev *
846 imx_media_find_sensor(struct imx_media_dev *imxmd,
847 struct media_entity *start_entity)
849 struct imx_media_subdev *sensor;
851 mutex_lock(&imxmd->md.graph_mutex);
852 sensor = __imx_media_find_sensor(imxmd, start_entity);
853 mutex_unlock(&imxmd->md.graph_mutex);
857 EXPORT_SYMBOL_GPL(imx_media_find_sensor);
860 * Turn current pipeline streaming on/off starting from entity.
862 int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd,
863 struct media_entity *entity,
866 struct v4l2_subdev *sd;
869 if (!is_media_entity_v4l2_subdev(entity))
871 sd = media_entity_to_v4l2_subdev(entity);
873 mutex_lock(&imxmd->md.graph_mutex);
876 ret = __media_pipeline_start(entity, &imxmd->pipe);
879 ret = v4l2_subdev_call(sd, video, s_stream, 1);
881 __media_pipeline_stop(entity);
883 v4l2_subdev_call(sd, video, s_stream, 0);
885 __media_pipeline_stop(entity);
889 mutex_unlock(&imxmd->md.graph_mutex);
892 EXPORT_SYMBOL_GPL(imx_media_pipeline_set_stream);
894 MODULE_DESCRIPTION("i.MX5/6 v4l2 media controller driver");
895 MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
896 MODULE_LICENSE("GPL");