root/drivers/staging/media/imx/imx-media-utils.c

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

DEFINITIONS

This source file includes following definitions.
  1. init_mbus_colorimetry
  2. __find_format
  3. find_format
  4. enum_format
  5. imx_media_find_format
  6. imx_media_enum_format
  7. imx_media_find_mbus_format
  8. imx_media_enum_mbus_format
  9. imx_media_find_ipu_format
  10. imx_media_enum_ipu_format
  11. imx_media_init_mbus_fmt
  12. imx_media_init_cfg
  13. imx_media_try_colorimetry
  14. imx_media_mbus_fmt_to_pix_fmt
  15. imx_media_mbus_fmt_to_ipu_image
  16. imx_media_ipu_image_to_mbus_fmt
  17. imx_media_free_dma_buf
  18. imx_media_alloc_dma_buf
  19. imx_media_grp_id_to_sd_name
  20. imx_media_find_subdev_by_fwnode
  21. imx_media_find_subdev_by_devname
  22. imx_media_add_video_device
  23. imx_media_pipeline_pad
  24. find_pipeline_entity
  25. imx_media_pipeline_csi2_channel
  26. imx_media_pipeline_subdev
  27. imx_media_pipeline_video_device
  28. imx_media_pipeline_set_stream

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * V4L2 Media Controller Driver for Freescale i.MX5/6 SOC
   4  *
   5  * Copyright (c) 2016 Mentor Graphics Inc.
   6  */
   7 #include <linux/module.h>
   8 #include "imx-media.h"
   9 
  10 /*
  11  * List of supported pixel formats for the subdevs.
  12  *
  13  * In all of these tables, the non-mbus formats (with no
  14  * mbus codes) must all fall at the end of the table.
  15  */
  16 
  17 static const struct imx_media_pixfmt yuv_formats[] = {
  18         {
  19                 .fourcc = V4L2_PIX_FMT_UYVY,
  20                 .codes  = {
  21                         MEDIA_BUS_FMT_UYVY8_2X8,
  22                         MEDIA_BUS_FMT_UYVY8_1X16
  23                 },
  24                 .cs     = IPUV3_COLORSPACE_YUV,
  25                 .bpp    = 16,
  26         }, {
  27                 .fourcc = V4L2_PIX_FMT_YUYV,
  28                 .codes  = {
  29                         MEDIA_BUS_FMT_YUYV8_2X8,
  30                         MEDIA_BUS_FMT_YUYV8_1X16
  31                 },
  32                 .cs     = IPUV3_COLORSPACE_YUV,
  33                 .bpp    = 16,
  34         },
  35         /***
  36          * non-mbus YUV formats start here. NOTE! when adding non-mbus
  37          * formats, NUM_NON_MBUS_YUV_FORMATS must be updated below.
  38          ***/
  39         {
  40                 .fourcc = V4L2_PIX_FMT_YUV420,
  41                 .cs     = IPUV3_COLORSPACE_YUV,
  42                 .bpp    = 12,
  43                 .planar = true,
  44         }, {
  45                 .fourcc = V4L2_PIX_FMT_YVU420,
  46                 .cs     = IPUV3_COLORSPACE_YUV,
  47                 .bpp    = 12,
  48                 .planar = true,
  49         }, {
  50                 .fourcc = V4L2_PIX_FMT_YUV422P,
  51                 .cs     = IPUV3_COLORSPACE_YUV,
  52                 .bpp    = 16,
  53                 .planar = true,
  54         }, {
  55                 .fourcc = V4L2_PIX_FMT_NV12,
  56                 .cs     = IPUV3_COLORSPACE_YUV,
  57                 .bpp    = 12,
  58                 .planar = true,
  59         }, {
  60                 .fourcc = V4L2_PIX_FMT_NV16,
  61                 .cs     = IPUV3_COLORSPACE_YUV,
  62                 .bpp    = 16,
  63                 .planar = true,
  64         },
  65 };
  66 
  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)
  70 
  71 static const struct imx_media_pixfmt rgb_formats[] = {
  72         {
  73                 .fourcc = V4L2_PIX_FMT_RGB565,
  74                 .codes  = {MEDIA_BUS_FMT_RGB565_2X8_LE},
  75                 .cs     = IPUV3_COLORSPACE_RGB,
  76                 .bpp    = 16,
  77                 .cycles = 2,
  78         }, {
  79                 .fourcc = V4L2_PIX_FMT_RGB24,
  80                 .codes  = {
  81                         MEDIA_BUS_FMT_RGB888_1X24,
  82                         MEDIA_BUS_FMT_RGB888_2X12_LE
  83                 },
  84                 .cs     = IPUV3_COLORSPACE_RGB,
  85                 .bpp    = 24,
  86         }, {
  87                 .fourcc = V4L2_PIX_FMT_XRGB32,
  88                 .codes  = {MEDIA_BUS_FMT_ARGB8888_1X32},
  89                 .cs     = IPUV3_COLORSPACE_RGB,
  90                 .bpp    = 32,
  91                 .ipufmt = true,
  92         },
  93         /*** raw bayer and grayscale formats start here ***/
  94         {
  95                 .fourcc = V4L2_PIX_FMT_SBGGR8,
  96                 .codes  = {MEDIA_BUS_FMT_SBGGR8_1X8},
  97                 .cs     = IPUV3_COLORSPACE_RGB,
  98                 .bpp    = 8,
  99                 .bayer  = true,
 100         }, {
 101                 .fourcc = V4L2_PIX_FMT_SGBRG8,
 102                 .codes  = {MEDIA_BUS_FMT_SGBRG8_1X8},
 103                 .cs     = IPUV3_COLORSPACE_RGB,
 104                 .bpp    = 8,
 105                 .bayer  = true,
 106         }, {
 107                 .fourcc = V4L2_PIX_FMT_SGRBG8,
 108                 .codes  = {MEDIA_BUS_FMT_SGRBG8_1X8},
 109                 .cs     = IPUV3_COLORSPACE_RGB,
 110                 .bpp    = 8,
 111                 .bayer  = true,
 112         }, {
 113                 .fourcc = V4L2_PIX_FMT_SRGGB8,
 114                 .codes  = {MEDIA_BUS_FMT_SRGGB8_1X8},
 115                 .cs     = IPUV3_COLORSPACE_RGB,
 116                 .bpp    = 8,
 117                 .bayer  = true,
 118         }, {
 119                 .fourcc = V4L2_PIX_FMT_SBGGR16,
 120                 .codes  = {
 121                         MEDIA_BUS_FMT_SBGGR10_1X10,
 122                         MEDIA_BUS_FMT_SBGGR12_1X12,
 123                         MEDIA_BUS_FMT_SBGGR14_1X14,
 124                         MEDIA_BUS_FMT_SBGGR16_1X16
 125                 },
 126                 .cs     = IPUV3_COLORSPACE_RGB,
 127                 .bpp    = 16,
 128                 .bayer  = true,
 129         }, {
 130                 .fourcc = V4L2_PIX_FMT_SGBRG16,
 131                 .codes  = {
 132                         MEDIA_BUS_FMT_SGBRG10_1X10,
 133                         MEDIA_BUS_FMT_SGBRG12_1X12,
 134                         MEDIA_BUS_FMT_SGBRG14_1X14,
 135                         MEDIA_BUS_FMT_SGBRG16_1X16,
 136                 },
 137                 .cs     = IPUV3_COLORSPACE_RGB,
 138                 .bpp    = 16,
 139                 .bayer  = true,
 140         }, {
 141                 .fourcc = V4L2_PIX_FMT_SGRBG16,
 142                 .codes  = {
 143                         MEDIA_BUS_FMT_SGRBG10_1X10,
 144                         MEDIA_BUS_FMT_SGRBG12_1X12,
 145                         MEDIA_BUS_FMT_SGRBG14_1X14,
 146                         MEDIA_BUS_FMT_SGRBG16_1X16,
 147                 },
 148                 .cs     = IPUV3_COLORSPACE_RGB,
 149                 .bpp    = 16,
 150                 .bayer  = true,
 151         }, {
 152                 .fourcc = V4L2_PIX_FMT_SRGGB16,
 153                 .codes  = {
 154                         MEDIA_BUS_FMT_SRGGB10_1X10,
 155                         MEDIA_BUS_FMT_SRGGB12_1X12,
 156                         MEDIA_BUS_FMT_SRGGB14_1X14,
 157                         MEDIA_BUS_FMT_SRGGB16_1X16,
 158                 },
 159                 .cs     = IPUV3_COLORSPACE_RGB,
 160                 .bpp    = 16,
 161                 .bayer  = true,
 162         }, {
 163                 .fourcc = V4L2_PIX_FMT_GREY,
 164                 .codes = {MEDIA_BUS_FMT_Y8_1X8},
 165                 .cs     = IPUV3_COLORSPACE_RGB,
 166                 .bpp    = 8,
 167                 .bayer  = true,
 168         }, {
 169                 .fourcc = V4L2_PIX_FMT_Y16,
 170                 .codes = {
 171                         MEDIA_BUS_FMT_Y10_1X10,
 172                         MEDIA_BUS_FMT_Y12_1X12,
 173                 },
 174                 .cs     = IPUV3_COLORSPACE_RGB,
 175                 .bpp    = 16,
 176                 .bayer  = true,
 177         },
 178         /***
 179          * non-mbus RGB formats start here. NOTE! when adding non-mbus
 180          * formats, NUM_NON_MBUS_RGB_FORMATS must be updated below.
 181          ***/
 182         {
 183                 .fourcc = V4L2_PIX_FMT_BGR24,
 184                 .cs     = IPUV3_COLORSPACE_RGB,
 185                 .bpp    = 24,
 186         }, {
 187                 .fourcc = V4L2_PIX_FMT_BGR32,
 188                 .cs     = IPUV3_COLORSPACE_RGB,
 189                 .bpp    = 32,
 190         },
 191 };
 192 
 193 #define NUM_NON_MBUS_RGB_FORMATS 2
 194 #define NUM_RGB_FORMATS ARRAY_SIZE(rgb_formats)
 195 #define NUM_MBUS_RGB_FORMATS (NUM_RGB_FORMATS - NUM_NON_MBUS_RGB_FORMATS)
 196 
 197 static const struct imx_media_pixfmt ipu_yuv_formats[] = {
 198         {
 199                 .fourcc = V4L2_PIX_FMT_YUV32,
 200                 .codes  = {MEDIA_BUS_FMT_AYUV8_1X32},
 201                 .cs     = IPUV3_COLORSPACE_YUV,
 202                 .bpp    = 32,
 203                 .ipufmt = true,
 204         },
 205 };
 206 
 207 #define NUM_IPU_YUV_FORMATS ARRAY_SIZE(ipu_yuv_formats)
 208 
 209 static const struct imx_media_pixfmt ipu_rgb_formats[] = {
 210         {
 211                 .fourcc = V4L2_PIX_FMT_XRGB32,
 212                 .codes  = {MEDIA_BUS_FMT_ARGB8888_1X32},
 213                 .cs     = IPUV3_COLORSPACE_RGB,
 214                 .bpp    = 32,
 215                 .ipufmt = true,
 216         },
 217 };
 218 
 219 #define NUM_IPU_RGB_FORMATS ARRAY_SIZE(ipu_rgb_formats)
 220 
 221 static void init_mbus_colorimetry(struct v4l2_mbus_framefmt *mbus,
 222                                   const struct imx_media_pixfmt *fmt)
 223 {
 224         mbus->colorspace = (fmt->cs == IPUV3_COLORSPACE_RGB) ?
 225                 V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_SMPTE170M;
 226         mbus->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(mbus->colorspace);
 227         mbus->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(mbus->colorspace);
 228         mbus->quantization =
 229                 V4L2_MAP_QUANTIZATION_DEFAULT(fmt->cs == IPUV3_COLORSPACE_RGB,
 230                                               mbus->colorspace,
 231                                               mbus->ycbcr_enc);
 232 }
 233 
 234 static const
 235 struct imx_media_pixfmt *__find_format(u32 fourcc,
 236                                        u32 code,
 237                                        bool allow_non_mbus,
 238                                        bool allow_bayer,
 239                                        const struct imx_media_pixfmt *array,
 240                                        u32 array_size)
 241 {
 242         const struct imx_media_pixfmt *fmt;
 243         int i, j;
 244 
 245         for (i = 0; i < array_size; i++) {
 246                 fmt = &array[i];
 247 
 248                 if ((!allow_non_mbus && !fmt->codes[0]) ||
 249                     (!allow_bayer && fmt->bayer))
 250                         continue;
 251 
 252                 if (fourcc && fmt->fourcc == fourcc)
 253                         return fmt;
 254 
 255                 if (!code)
 256                         continue;
 257 
 258                 for (j = 0; fmt->codes[j]; j++) {
 259                         if (code == fmt->codes[j])
 260                                 return fmt;
 261                 }
 262         }
 263         return NULL;
 264 }
 265 
 266 static const struct imx_media_pixfmt *find_format(u32 fourcc,
 267                                                   u32 code,
 268                                                   enum codespace_sel cs_sel,
 269                                                   bool allow_non_mbus,
 270                                                   bool allow_bayer)
 271 {
 272         const struct imx_media_pixfmt *ret;
 273 
 274         switch (cs_sel) {
 275         case CS_SEL_YUV:
 276                 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
 277                                      yuv_formats, NUM_YUV_FORMATS);
 278         case CS_SEL_RGB:
 279                 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
 280                                      rgb_formats, NUM_RGB_FORMATS);
 281         case CS_SEL_ANY:
 282                 ret = __find_format(fourcc, code, allow_non_mbus, allow_bayer,
 283                                     yuv_formats, NUM_YUV_FORMATS);
 284                 if (ret)
 285                         return ret;
 286                 return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
 287                                      rgb_formats, NUM_RGB_FORMATS);
 288         default:
 289                 return NULL;
 290         }
 291 }
 292 
 293 static int enum_format(u32 *fourcc, u32 *code, u32 index,
 294                        enum codespace_sel cs_sel,
 295                        bool allow_non_mbus,
 296                        bool allow_bayer)
 297 {
 298         const struct imx_media_pixfmt *fmt;
 299         u32 mbus_yuv_sz = NUM_MBUS_YUV_FORMATS;
 300         u32 mbus_rgb_sz = NUM_MBUS_RGB_FORMATS;
 301         u32 yuv_sz = NUM_YUV_FORMATS;
 302         u32 rgb_sz = NUM_RGB_FORMATS;
 303 
 304         switch (cs_sel) {
 305         case CS_SEL_YUV:
 306                 if (index >= yuv_sz ||
 307                     (!allow_non_mbus && index >= mbus_yuv_sz))
 308                         return -EINVAL;
 309                 fmt = &yuv_formats[index];
 310                 break;
 311         case CS_SEL_RGB:
 312                 if (index >= rgb_sz ||
 313                     (!allow_non_mbus && index >= mbus_rgb_sz))
 314                         return -EINVAL;
 315                 fmt = &rgb_formats[index];
 316                 if (!allow_bayer && fmt->bayer)
 317                         return -EINVAL;
 318                 break;
 319         case CS_SEL_ANY:
 320                 if (!allow_non_mbus) {
 321                         if (index >= mbus_yuv_sz) {
 322                                 index -= mbus_yuv_sz;
 323                                 if (index >= mbus_rgb_sz)
 324                                         return -EINVAL;
 325                                 fmt = &rgb_formats[index];
 326                                 if (!allow_bayer && fmt->bayer)
 327                                         return -EINVAL;
 328                         } else {
 329                                 fmt = &yuv_formats[index];
 330                         }
 331                 } else {
 332                         if (index >= yuv_sz + rgb_sz)
 333                                 return -EINVAL;
 334                         if (index >= yuv_sz) {
 335                                 fmt = &rgb_formats[index - yuv_sz];
 336                                 if (!allow_bayer && fmt->bayer)
 337                                         return -EINVAL;
 338                         } else {
 339                                 fmt = &yuv_formats[index];
 340                         }
 341                 }
 342                 break;
 343         default:
 344                 return -EINVAL;
 345         }
 346 
 347         if (fourcc)
 348                 *fourcc = fmt->fourcc;
 349         if (code)
 350                 *code = fmt->codes[0];
 351 
 352         return 0;
 353 }
 354 
 355 const struct imx_media_pixfmt *
 356 imx_media_find_format(u32 fourcc, enum codespace_sel cs_sel, bool allow_bayer)
 357 {
 358         return find_format(fourcc, 0, cs_sel, true, allow_bayer);
 359 }
 360 EXPORT_SYMBOL_GPL(imx_media_find_format);
 361 
 362 int imx_media_enum_format(u32 *fourcc, u32 index, enum codespace_sel cs_sel)
 363 {
 364         return enum_format(fourcc, NULL, index, cs_sel, true, false);
 365 }
 366 EXPORT_SYMBOL_GPL(imx_media_enum_format);
 367 
 368 const struct imx_media_pixfmt *
 369 imx_media_find_mbus_format(u32 code, enum codespace_sel cs_sel,
 370                            bool allow_bayer)
 371 {
 372         return find_format(0, code, cs_sel, false, allow_bayer);
 373 }
 374 EXPORT_SYMBOL_GPL(imx_media_find_mbus_format);
 375 
 376 int imx_media_enum_mbus_format(u32 *code, u32 index, enum codespace_sel cs_sel,
 377                                bool allow_bayer)
 378 {
 379         return enum_format(NULL, code, index, cs_sel, false, allow_bayer);
 380 }
 381 EXPORT_SYMBOL_GPL(imx_media_enum_mbus_format);
 382 
 383 const struct imx_media_pixfmt *
 384 imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel)
 385 {
 386         const struct imx_media_pixfmt *array, *fmt, *ret = NULL;
 387         u32 array_size;
 388         int i, j;
 389 
 390         switch (cs_sel) {
 391         case CS_SEL_YUV:
 392                 array_size = NUM_IPU_YUV_FORMATS;
 393                 array = ipu_yuv_formats;
 394                 break;
 395         case CS_SEL_RGB:
 396                 array_size = NUM_IPU_RGB_FORMATS;
 397                 array = ipu_rgb_formats;
 398                 break;
 399         case CS_SEL_ANY:
 400                 array_size = NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS;
 401                 array = ipu_yuv_formats;
 402                 break;
 403         default:
 404                 return NULL;
 405         }
 406 
 407         for (i = 0; i < array_size; i++) {
 408                 if (cs_sel == CS_SEL_ANY && i >= NUM_IPU_YUV_FORMATS)
 409                         fmt = &ipu_rgb_formats[i - NUM_IPU_YUV_FORMATS];
 410                 else
 411                         fmt = &array[i];
 412 
 413                 for (j = 0; code && fmt->codes[j]; j++) {
 414                         if (code == fmt->codes[j]) {
 415                                 ret = fmt;
 416                                 goto out;
 417                         }
 418                 }
 419         }
 420 
 421 out:
 422         return ret;
 423 }
 424 EXPORT_SYMBOL_GPL(imx_media_find_ipu_format);
 425 
 426 int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel)
 427 {
 428         switch (cs_sel) {
 429         case CS_SEL_YUV:
 430                 if (index >= NUM_IPU_YUV_FORMATS)
 431                         return -EINVAL;
 432                 *code = ipu_yuv_formats[index].codes[0];
 433                 break;
 434         case CS_SEL_RGB:
 435                 if (index >= NUM_IPU_RGB_FORMATS)
 436                         return -EINVAL;
 437                 *code = ipu_rgb_formats[index].codes[0];
 438                 break;
 439         case CS_SEL_ANY:
 440                 if (index >= NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS)
 441                         return -EINVAL;
 442                 if (index >= NUM_IPU_YUV_FORMATS) {
 443                         index -= NUM_IPU_YUV_FORMATS;
 444                         *code = ipu_rgb_formats[index].codes[0];
 445                 } else {
 446                         *code = ipu_yuv_formats[index].codes[0];
 447                 }
 448                 break;
 449         default:
 450                 return -EINVAL;
 451         }
 452 
 453         return 0;
 454 }
 455 EXPORT_SYMBOL_GPL(imx_media_enum_ipu_format);
 456 
 457 int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
 458                             u32 width, u32 height, u32 code, u32 field,
 459                             const struct imx_media_pixfmt **cc)
 460 {
 461         const struct imx_media_pixfmt *lcc;
 462 
 463         mbus->width = width;
 464         mbus->height = height;
 465         mbus->field = field;
 466         if (code == 0)
 467                 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
 468         lcc = imx_media_find_mbus_format(code, CS_SEL_ANY, false);
 469         if (!lcc) {
 470                 lcc = imx_media_find_ipu_format(code, CS_SEL_ANY);
 471                 if (!lcc)
 472                         return -EINVAL;
 473         }
 474 
 475         mbus->code = code;
 476         init_mbus_colorimetry(mbus, lcc);
 477         if (cc)
 478                 *cc = lcc;
 479 
 480         return 0;
 481 }
 482 EXPORT_SYMBOL_GPL(imx_media_init_mbus_fmt);
 483 
 484 /*
 485  * Initializes the TRY format to the ACTIVE format on all pads
 486  * of a subdev. Can be used as the .init_cfg pad operation.
 487  */
 488 int imx_media_init_cfg(struct v4l2_subdev *sd,
 489                        struct v4l2_subdev_pad_config *cfg)
 490 {
 491         struct v4l2_mbus_framefmt *mf_try;
 492         struct v4l2_subdev_format format;
 493         unsigned int pad;
 494         int ret;
 495 
 496         for (pad = 0; pad < sd->entity.num_pads; pad++) {
 497                 memset(&format, 0, sizeof(format));
 498 
 499                 format.pad = pad;
 500                 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 501                 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);
 502                 if (ret)
 503                         continue;
 504 
 505                 mf_try = v4l2_subdev_get_try_format(sd, cfg, pad);
 506                 *mf_try = format.format;
 507         }
 508 
 509         return 0;
 510 }
 511 EXPORT_SYMBOL_GPL(imx_media_init_cfg);
 512 
 513 /*
 514  * Default the colorspace in tryfmt to SRGB if set to an unsupported
 515  * colorspace or not initialized. Then set the remaining colorimetry
 516  * parameters based on the colorspace if they are uninitialized.
 517  *
 518  * tryfmt->code must be set on entry.
 519  *
 520  * If this format is destined to be routed through the Image Converter,
 521  * Y`CbCr encoding must be fixed. The IC supports only BT.601 Y`CbCr
 522  * or Rec.709 Y`CbCr encoding.
 523  */
 524 void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
 525                                bool ic_route)
 526 {
 527         const struct imx_media_pixfmt *cc;
 528         bool is_rgb = false;
 529 
 530         cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true);
 531         if (!cc)
 532                 cc = imx_media_find_ipu_format(tryfmt->code, CS_SEL_ANY);
 533         if (cc && cc->cs == IPUV3_COLORSPACE_RGB)
 534                 is_rgb = true;
 535 
 536         switch (tryfmt->colorspace) {
 537         case V4L2_COLORSPACE_SMPTE170M:
 538         case V4L2_COLORSPACE_REC709:
 539         case V4L2_COLORSPACE_JPEG:
 540         case V4L2_COLORSPACE_SRGB:
 541         case V4L2_COLORSPACE_BT2020:
 542         case V4L2_COLORSPACE_OPRGB:
 543         case V4L2_COLORSPACE_DCI_P3:
 544         case V4L2_COLORSPACE_RAW:
 545                 break;
 546         default:
 547                 tryfmt->colorspace = V4L2_COLORSPACE_SRGB;
 548                 break;
 549         }
 550 
 551         if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT)
 552                 tryfmt->xfer_func =
 553                         V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace);
 554 
 555         if (ic_route) {
 556                 if (tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_601 &&
 557                     tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_709)
 558                         tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
 559         } else {
 560                 if (tryfmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
 561                         tryfmt->ycbcr_enc =
 562                                 V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace);
 563                 }
 564         }
 565 
 566         if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT)
 567                 tryfmt->quantization =
 568                         V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb,
 569                                                       tryfmt->colorspace,
 570                                                       tryfmt->ycbcr_enc);
 571 }
 572 EXPORT_SYMBOL_GPL(imx_media_try_colorimetry);
 573 
 574 int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
 575                                   struct v4l2_mbus_framefmt *mbus,
 576                                   const struct imx_media_pixfmt *cc)
 577 {
 578         u32 width;
 579         u32 stride;
 580 
 581         if (!cc) {
 582                 cc = imx_media_find_ipu_format(mbus->code, CS_SEL_ANY);
 583                 if (!cc)
 584                         cc = imx_media_find_mbus_format(mbus->code, CS_SEL_ANY,
 585                                                         true);
 586                 if (!cc)
 587                         return -EINVAL;
 588         }
 589 
 590         /*
 591          * TODO: the IPU currently does not support the AYUV32 format,
 592          * so until it does convert to a supported YUV format.
 593          */
 594         if (cc->ipufmt && cc->cs == IPUV3_COLORSPACE_YUV) {
 595                 u32 code;
 596 
 597                 imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
 598                 cc = imx_media_find_mbus_format(code, CS_SEL_YUV, false);
 599         }
 600 
 601         /* Round up width for minimum burst size */
 602         width = round_up(mbus->width, 8);
 603 
 604         /* Round up stride for IDMAC line start address alignment */
 605         if (cc->planar)
 606                 stride = round_up(width, 16);
 607         else
 608                 stride = round_up((width * cc->bpp) >> 3, 8);
 609 
 610         pix->width = width;
 611         pix->height = mbus->height;
 612         pix->pixelformat = cc->fourcc;
 613         pix->colorspace = mbus->colorspace;
 614         pix->xfer_func = mbus->xfer_func;
 615         pix->ycbcr_enc = mbus->ycbcr_enc;
 616         pix->quantization = mbus->quantization;
 617         pix->field = mbus->field;
 618         pix->bytesperline = stride;
 619         pix->sizeimage = cc->planar ? ((stride * pix->height * cc->bpp) >> 3) :
 620                          stride * pix->height;
 621 
 622         return 0;
 623 }
 624 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_pix_fmt);
 625 
 626 int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image,
 627                                     struct v4l2_mbus_framefmt *mbus)
 628 {
 629         int ret;
 630 
 631         memset(image, 0, sizeof(*image));
 632 
 633         ret = imx_media_mbus_fmt_to_pix_fmt(&image->pix, mbus, NULL);
 634         if (ret)
 635                 return ret;
 636 
 637         image->rect.width = mbus->width;
 638         image->rect.height = mbus->height;
 639 
 640         return 0;
 641 }
 642 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_ipu_image);
 643 
 644 int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
 645                                     struct ipu_image *image)
 646 {
 647         const struct imx_media_pixfmt *fmt;
 648 
 649         fmt = imx_media_find_format(image->pix.pixelformat, CS_SEL_ANY, true);
 650         if (!fmt)
 651                 return -EINVAL;
 652 
 653         memset(mbus, 0, sizeof(*mbus));
 654         mbus->width = image->pix.width;
 655         mbus->height = image->pix.height;
 656         mbus->code = fmt->codes[0];
 657         mbus->field = image->pix.field;
 658         mbus->colorspace = image->pix.colorspace;
 659         mbus->xfer_func = image->pix.xfer_func;
 660         mbus->ycbcr_enc = image->pix.ycbcr_enc;
 661         mbus->quantization = image->pix.quantization;
 662 
 663         return 0;
 664 }
 665 EXPORT_SYMBOL_GPL(imx_media_ipu_image_to_mbus_fmt);
 666 
 667 void imx_media_free_dma_buf(struct device *dev,
 668                             struct imx_media_dma_buf *buf)
 669 {
 670         if (buf->virt)
 671                 dma_free_coherent(dev, buf->len, buf->virt, buf->phys);
 672 
 673         buf->virt = NULL;
 674         buf->phys = 0;
 675 }
 676 EXPORT_SYMBOL_GPL(imx_media_free_dma_buf);
 677 
 678 int imx_media_alloc_dma_buf(struct device *dev,
 679                             struct imx_media_dma_buf *buf,
 680                             int size)
 681 {
 682         imx_media_free_dma_buf(dev, buf);
 683 
 684         buf->len = PAGE_ALIGN(size);
 685         buf->virt = dma_alloc_coherent(dev, buf->len, &buf->phys,
 686                                        GFP_DMA | GFP_KERNEL);
 687         if (!buf->virt) {
 688                 dev_err(dev, "%s: failed\n", __func__);
 689                 return -ENOMEM;
 690         }
 691 
 692         return 0;
 693 }
 694 EXPORT_SYMBOL_GPL(imx_media_alloc_dma_buf);
 695 
 696 /* form a subdev name given a group id and ipu id */
 697 void imx_media_grp_id_to_sd_name(char *sd_name, int sz, u32 grp_id, int ipu_id)
 698 {
 699         int id;
 700 
 701         switch (grp_id) {
 702         case IMX_MEDIA_GRP_ID_IPU_CSI0...IMX_MEDIA_GRP_ID_IPU_CSI1:
 703                 id = (grp_id >> IMX_MEDIA_GRP_ID_IPU_CSI_BIT) - 1;
 704                 snprintf(sd_name, sz, "ipu%d_csi%d", ipu_id + 1, id);
 705                 break;
 706         case IMX_MEDIA_GRP_ID_IPU_VDIC:
 707                 snprintf(sd_name, sz, "ipu%d_vdic", ipu_id + 1);
 708                 break;
 709         case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
 710                 snprintf(sd_name, sz, "ipu%d_ic_prp", ipu_id + 1);
 711                 break;
 712         case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
 713                 snprintf(sd_name, sz, "ipu%d_ic_prpenc", ipu_id + 1);
 714                 break;
 715         case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
 716                 snprintf(sd_name, sz, "ipu%d_ic_prpvf", ipu_id + 1);
 717                 break;
 718         default:
 719                 break;
 720         }
 721 }
 722 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name);
 723 
 724 struct v4l2_subdev *
 725 imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
 726                                 struct fwnode_handle *fwnode)
 727 {
 728         struct v4l2_subdev *sd;
 729 
 730         list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
 731                 if (sd->fwnode == fwnode)
 732                         return sd;
 733         }
 734 
 735         return NULL;
 736 }
 737 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_fwnode);
 738 
 739 struct v4l2_subdev *
 740 imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
 741                                  const char *devname)
 742 {
 743         struct v4l2_subdev *sd;
 744 
 745         list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
 746                 if (!strcmp(devname, dev_name(sd->dev)))
 747                         return sd;
 748         }
 749 
 750         return NULL;
 751 }
 752 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
 753 
 754 /*
 755  * Adds a video device to the master video device list. This is called
 756  * when a video device is registered.
 757  */
 758 void imx_media_add_video_device(struct imx_media_dev *imxmd,
 759                                 struct imx_media_video_dev *vdev)
 760 {
 761         mutex_lock(&imxmd->mutex);
 762 
 763         list_add_tail(&vdev->list, &imxmd->vdev_list);
 764 
 765         mutex_unlock(&imxmd->mutex);
 766 }
 767 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
 768 
 769 /*
 770  * Search upstream/downstream for a subdevice or video device pad in the
 771  * current pipeline, starting from start_entity. Returns the device's
 772  * source/sink pad that it was reached from. Must be called with
 773  * mdev->graph_mutex held.
 774  *
 775  * If grp_id != 0, finds a subdevice's pad of given grp_id.
 776  * Else If buftype != 0, finds a video device's pad of given buffer type.
 777  * Else, returns the nearest source/sink pad to start_entity.
 778  */
 779 struct media_pad *
 780 imx_media_pipeline_pad(struct media_entity *start_entity, u32 grp_id,
 781                        enum v4l2_buf_type buftype, bool upstream)
 782 {
 783         struct media_entity *me = start_entity;
 784         struct media_pad *pad = NULL;
 785         struct video_device *vfd;
 786         struct v4l2_subdev *sd;
 787         int i;
 788 
 789         for (i = 0; i < me->num_pads; i++) {
 790                 struct media_pad *spad = &me->pads[i];
 791 
 792                 if ((upstream && !(spad->flags & MEDIA_PAD_FL_SINK)) ||
 793                     (!upstream && !(spad->flags & MEDIA_PAD_FL_SOURCE)))
 794                         continue;
 795 
 796                 pad = media_entity_remote_pad(spad);
 797                 if (!pad)
 798                         continue;
 799 
 800                 if (grp_id) {
 801                         if (is_media_entity_v4l2_subdev(pad->entity)) {
 802                                 sd = media_entity_to_v4l2_subdev(pad->entity);
 803                                 if (sd->grp_id & grp_id)
 804                                         return pad;
 805                         }
 806 
 807                         return imx_media_pipeline_pad(pad->entity, grp_id,
 808                                                       buftype, upstream);
 809                 } else if (buftype) {
 810                         if (is_media_entity_v4l2_video_device(pad->entity)) {
 811                                 vfd = media_entity_to_video_device(pad->entity);
 812                                 if (buftype == vfd->queue->type)
 813                                         return pad;
 814                         }
 815 
 816                         return imx_media_pipeline_pad(pad->entity, grp_id,
 817                                                       buftype, upstream);
 818                 } else {
 819                         return pad;
 820                 }
 821         }
 822 
 823         return NULL;
 824 }
 825 EXPORT_SYMBOL_GPL(imx_media_pipeline_pad);
 826 
 827 /*
 828  * Search upstream/downstream for a subdev or video device in the current
 829  * pipeline. Must be called with mdev->graph_mutex held.
 830  */
 831 static struct media_entity *
 832 find_pipeline_entity(struct media_entity *start, u32 grp_id,
 833                      enum v4l2_buf_type buftype, bool upstream)
 834 {
 835         struct media_pad *pad = NULL;
 836         struct video_device *vfd;
 837         struct v4l2_subdev *sd;
 838 
 839         if (grp_id && is_media_entity_v4l2_subdev(start)) {
 840                 sd = media_entity_to_v4l2_subdev(start);
 841                 if (sd->grp_id & grp_id)
 842                         return &sd->entity;
 843         } else if (buftype && is_media_entity_v4l2_video_device(start)) {
 844                 vfd = media_entity_to_video_device(start);
 845                 if (buftype == vfd->queue->type)
 846                         return &vfd->entity;
 847         }
 848 
 849         pad = imx_media_pipeline_pad(start, grp_id, buftype, upstream);
 850 
 851         return pad ? pad->entity : NULL;
 852 }
 853 
 854 /*
 855  * Find the upstream mipi-csi2 virtual channel reached from the given
 856  * start entity in the current pipeline.
 857  * Must be called with mdev->graph_mutex held.
 858  */
 859 int imx_media_pipeline_csi2_channel(struct media_entity *start_entity)
 860 {
 861         struct media_pad *pad;
 862         int ret = -EPIPE;
 863 
 864         pad = imx_media_pipeline_pad(start_entity, IMX_MEDIA_GRP_ID_CSI2,
 865                                      0, true);
 866         if (pad)
 867                 ret = pad->index - 1;
 868 
 869         return ret;
 870 }
 871 EXPORT_SYMBOL_GPL(imx_media_pipeline_csi2_channel);
 872 
 873 /*
 874  * Find a subdev reached upstream from the given start entity in
 875  * the current pipeline.
 876  * Must be called with mdev->graph_mutex held.
 877  */
 878 struct v4l2_subdev *
 879 imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id,
 880                           bool upstream)
 881 {
 882         struct media_entity *me;
 883 
 884         me = find_pipeline_entity(start_entity, grp_id, 0, upstream);
 885         if (!me)
 886                 return ERR_PTR(-ENODEV);
 887 
 888         return media_entity_to_v4l2_subdev(me);
 889 }
 890 EXPORT_SYMBOL_GPL(imx_media_pipeline_subdev);
 891 
 892 /*
 893  * Find a subdev reached upstream from the given start entity in
 894  * the current pipeline.
 895  * Must be called with mdev->graph_mutex held.
 896  */
 897 struct video_device *
 898 imx_media_pipeline_video_device(struct media_entity *start_entity,
 899                                 enum v4l2_buf_type buftype, bool upstream)
 900 {
 901         struct media_entity *me;
 902 
 903         me = find_pipeline_entity(start_entity, 0, buftype, upstream);
 904         if (!me)
 905                 return ERR_PTR(-ENODEV);
 906 
 907         return media_entity_to_video_device(me);
 908 }
 909 EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device);
 910 
 911 /*
 912  * Turn current pipeline streaming on/off starting from entity.
 913  */
 914 int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd,
 915                                   struct media_entity *entity,
 916                                   bool on)
 917 {
 918         struct v4l2_subdev *sd;
 919         int ret = 0;
 920 
 921         if (!is_media_entity_v4l2_subdev(entity))
 922                 return -EINVAL;
 923         sd = media_entity_to_v4l2_subdev(entity);
 924 
 925         mutex_lock(&imxmd->md.graph_mutex);
 926 
 927         if (on) {
 928                 ret = __media_pipeline_start(entity, &imxmd->pipe);
 929                 if (ret)
 930                         goto out;
 931                 ret = v4l2_subdev_call(sd, video, s_stream, 1);
 932                 if (ret)
 933                         __media_pipeline_stop(entity);
 934         } else {
 935                 v4l2_subdev_call(sd, video, s_stream, 0);
 936                 if (entity->pipe)
 937                         __media_pipeline_stop(entity);
 938         }
 939 
 940 out:
 941         mutex_unlock(&imxmd->md.graph_mutex);
 942         return ret;
 943 }
 944 EXPORT_SYMBOL_GPL(imx_media_pipeline_set_stream);
 945 
 946 MODULE_DESCRIPTION("i.MX5/6 v4l2 media controller driver");
 947 MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
 948 MODULE_LICENSE("GPL");

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