linux/drivers/media/video/soc_mediabus.c
<<
>>
Prefs
   1/*
   2 * soc-camera media bus helper routines
   3 *
   4 * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13
  14#include <media/v4l2-device.h>
  15#include <media/v4l2-mediabus.h>
  16#include <media/soc_mediabus.h>
  17
  18static const struct soc_mbus_lookup mbus_fmt[] = {
  19{
  20        .code = V4L2_MBUS_FMT_YUYV8_2X8,
  21        .fmt = {
  22                .fourcc                 = V4L2_PIX_FMT_YUYV,
  23                .name                   = "YUYV",
  24                .bits_per_sample        = 8,
  25                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  26                .order                  = SOC_MBUS_ORDER_LE,
  27        },
  28}, {
  29        .code = V4L2_MBUS_FMT_YVYU8_2X8,
  30        .fmt = {
  31                .fourcc                 = V4L2_PIX_FMT_YVYU,
  32                .name                   = "YVYU",
  33                .bits_per_sample        = 8,
  34                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  35                .order                  = SOC_MBUS_ORDER_LE,
  36        },
  37}, {
  38        .code = V4L2_MBUS_FMT_UYVY8_2X8,
  39        .fmt = {
  40                .fourcc                 = V4L2_PIX_FMT_UYVY,
  41                .name                   = "UYVY",
  42                .bits_per_sample        = 8,
  43                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  44                .order                  = SOC_MBUS_ORDER_LE,
  45        },
  46}, {
  47        .code = V4L2_MBUS_FMT_VYUY8_2X8,
  48        .fmt = {
  49                .fourcc                 = V4L2_PIX_FMT_VYUY,
  50                .name                   = "VYUY",
  51                .bits_per_sample        = 8,
  52                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  53                .order                  = SOC_MBUS_ORDER_LE,
  54        },
  55}, {
  56        .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
  57        .fmt = {
  58                .fourcc                 = V4L2_PIX_FMT_RGB555,
  59                .name                   = "RGB555",
  60                .bits_per_sample        = 8,
  61                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  62                .order                  = SOC_MBUS_ORDER_LE,
  63        },
  64}, {
  65        .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
  66        .fmt = {
  67                .fourcc                 = V4L2_PIX_FMT_RGB555X,
  68                .name                   = "RGB555X",
  69                .bits_per_sample        = 8,
  70                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  71                .order                  = SOC_MBUS_ORDER_LE,
  72        },
  73}, {
  74        .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
  75        .fmt = {
  76                .fourcc                 = V4L2_PIX_FMT_RGB565,
  77                .name                   = "RGB565",
  78                .bits_per_sample        = 8,
  79                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  80                .order                  = SOC_MBUS_ORDER_LE,
  81        },
  82}, {
  83        .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
  84        .fmt = {
  85                .fourcc                 = V4L2_PIX_FMT_RGB565X,
  86                .name                   = "RGB565X",
  87                .bits_per_sample        = 8,
  88                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
  89                .order                  = SOC_MBUS_ORDER_LE,
  90        },
  91}, {
  92        .code = V4L2_MBUS_FMT_SBGGR8_1X8,
  93        .fmt = {
  94                .fourcc                 = V4L2_PIX_FMT_SBGGR8,
  95                .name                   = "Bayer 8 BGGR",
  96                .bits_per_sample        = 8,
  97                .packing                = SOC_MBUS_PACKING_NONE,
  98                .order                  = SOC_MBUS_ORDER_LE,
  99        },
 100}, {
 101        .code = V4L2_MBUS_FMT_SBGGR10_1X10,
 102        .fmt = {
 103                .fourcc                 = V4L2_PIX_FMT_SBGGR10,
 104                .name                   = "Bayer 10 BGGR",
 105                .bits_per_sample        = 10,
 106                .packing                = SOC_MBUS_PACKING_EXTEND16,
 107                .order                  = SOC_MBUS_ORDER_LE,
 108        },
 109}, {
 110        .code = V4L2_MBUS_FMT_Y8_1X8,
 111        .fmt = {
 112                .fourcc                 = V4L2_PIX_FMT_GREY,
 113                .name                   = "Grey",
 114                .bits_per_sample        = 8,
 115                .packing                = SOC_MBUS_PACKING_NONE,
 116                .order                  = SOC_MBUS_ORDER_LE,
 117        },
 118}, {
 119        .code = V4L2_MBUS_FMT_Y10_1X10,
 120        .fmt = {
 121                .fourcc                 = V4L2_PIX_FMT_Y10,
 122                .name                   = "Grey 10bit",
 123                .bits_per_sample        = 10,
 124                .packing                = SOC_MBUS_PACKING_EXTEND16,
 125                .order                  = SOC_MBUS_ORDER_LE,
 126        },
 127}, {
 128        .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
 129        .fmt = {
 130                .fourcc                 = V4L2_PIX_FMT_SBGGR10,
 131                .name                   = "Bayer 10 BGGR",
 132                .bits_per_sample        = 8,
 133                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
 134                .order                  = SOC_MBUS_ORDER_LE,
 135        },
 136}, {
 137        .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
 138        .fmt = {
 139                .fourcc                 = V4L2_PIX_FMT_SBGGR10,
 140                .name                   = "Bayer 10 BGGR",
 141                .bits_per_sample        = 8,
 142                .packing                = SOC_MBUS_PACKING_2X8_PADLO,
 143                .order                  = SOC_MBUS_ORDER_LE,
 144        },
 145}, {
 146        .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
 147        .fmt = {
 148                .fourcc                 = V4L2_PIX_FMT_SBGGR10,
 149                .name                   = "Bayer 10 BGGR",
 150                .bits_per_sample        = 8,
 151                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
 152                .order                  = SOC_MBUS_ORDER_BE,
 153        },
 154}, {
 155        .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
 156        .fmt = {
 157                .fourcc                 = V4L2_PIX_FMT_SBGGR10,
 158                .name                   = "Bayer 10 BGGR",
 159                .bits_per_sample        = 8,
 160                .packing                = SOC_MBUS_PACKING_2X8_PADLO,
 161                .order                  = SOC_MBUS_ORDER_BE,
 162        },
 163}, {
 164        .code = V4L2_MBUS_FMT_JPEG_1X8,
 165        .fmt = {
 166                .fourcc                 = V4L2_PIX_FMT_JPEG,
 167                .name                   = "JPEG",
 168                .bits_per_sample        = 8,
 169                .packing                = SOC_MBUS_PACKING_VARIABLE,
 170                .order                  = SOC_MBUS_ORDER_LE,
 171        },
 172}, {
 173        .code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
 174        .fmt = {
 175                .fourcc                 = V4L2_PIX_FMT_RGB444,
 176                .name                   = "RGB444",
 177                .bits_per_sample        = 8,
 178                .packing                = SOC_MBUS_PACKING_2X8_PADHI,
 179                .order                  = SOC_MBUS_ORDER_BE,
 180        },
 181}, {
 182        .code = V4L2_MBUS_FMT_YUYV8_1_5X8,
 183        .fmt = {
 184                .fourcc                 = V4L2_PIX_FMT_YUV420,
 185                .name                   = "YUYV 4:2:0",
 186                .bits_per_sample        = 8,
 187                .packing                = SOC_MBUS_PACKING_1_5X8,
 188                .order                  = SOC_MBUS_ORDER_LE,
 189        },
 190}, {
 191        .code = V4L2_MBUS_FMT_YVYU8_1_5X8,
 192        .fmt = {
 193                .fourcc                 = V4L2_PIX_FMT_YVU420,
 194                .name                   = "YVYU 4:2:0",
 195                .bits_per_sample        = 8,
 196                .packing                = SOC_MBUS_PACKING_1_5X8,
 197                .order                  = SOC_MBUS_ORDER_LE,
 198        },
 199}, {
 200        .code = V4L2_MBUS_FMT_UYVY8_1X16,
 201        .fmt = {
 202                .fourcc                 = V4L2_PIX_FMT_UYVY,
 203                .name                   = "UYVY 16bit",
 204                .bits_per_sample        = 16,
 205                .packing                = SOC_MBUS_PACKING_EXTEND16,
 206                .order                  = SOC_MBUS_ORDER_LE,
 207        },
 208}, {
 209        .code = V4L2_MBUS_FMT_VYUY8_1X16,
 210        .fmt = {
 211                .fourcc                 = V4L2_PIX_FMT_VYUY,
 212                .name                   = "VYUY 16bit",
 213                .bits_per_sample        = 16,
 214                .packing                = SOC_MBUS_PACKING_EXTEND16,
 215                .order                  = SOC_MBUS_ORDER_LE,
 216        },
 217}, {
 218        .code = V4L2_MBUS_FMT_YUYV8_1X16,
 219        .fmt = {
 220                .fourcc                 = V4L2_PIX_FMT_YUYV,
 221                .name                   = "YUYV 16bit",
 222                .bits_per_sample        = 16,
 223                .packing                = SOC_MBUS_PACKING_EXTEND16,
 224                .order                  = SOC_MBUS_ORDER_LE,
 225        },
 226}, {
 227        .code = V4L2_MBUS_FMT_YVYU8_1X16,
 228        .fmt = {
 229                .fourcc                 = V4L2_PIX_FMT_YVYU,
 230                .name                   = "YVYU 16bit",
 231                .bits_per_sample        = 16,
 232                .packing                = SOC_MBUS_PACKING_EXTEND16,
 233                .order                  = SOC_MBUS_ORDER_LE,
 234        },
 235}, {
 236        .code = V4L2_MBUS_FMT_SGRBG8_1X8,
 237        .fmt = {
 238                .fourcc                 = V4L2_PIX_FMT_SGRBG8,
 239                .name                   = "Bayer 8 GRBG",
 240                .bits_per_sample        = 8,
 241                .packing                = SOC_MBUS_PACKING_NONE,
 242                .order                  = SOC_MBUS_ORDER_LE,
 243        },
 244}, {
 245        .code = V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
 246        .fmt = {
 247                .fourcc                 = V4L2_PIX_FMT_SGRBG10DPCM8,
 248                .name                   = "Bayer 10 BGGR DPCM 8",
 249                .bits_per_sample        = 8,
 250                .packing                = SOC_MBUS_PACKING_NONE,
 251                .order                  = SOC_MBUS_ORDER_LE,
 252        },
 253}, {
 254        .code = V4L2_MBUS_FMT_SGBRG10_1X10,
 255        .fmt = {
 256                .fourcc                 = V4L2_PIX_FMT_SGBRG10,
 257                .name                   = "Bayer 10 GBRG",
 258                .bits_per_sample        = 10,
 259                .packing                = SOC_MBUS_PACKING_EXTEND16,
 260                .order                  = SOC_MBUS_ORDER_LE,
 261        },
 262}, {
 263        .code = V4L2_MBUS_FMT_SGRBG10_1X10,
 264        .fmt = {
 265                .fourcc                 = V4L2_PIX_FMT_SGRBG10,
 266                .name                   = "Bayer 10 GRBG",
 267                .bits_per_sample        = 10,
 268                .packing                = SOC_MBUS_PACKING_EXTEND16,
 269                .order                  = SOC_MBUS_ORDER_LE,
 270        },
 271}, {
 272        .code = V4L2_MBUS_FMT_SRGGB10_1X10,
 273        .fmt = {
 274                .fourcc                 = V4L2_PIX_FMT_SRGGB10,
 275                .name                   = "Bayer 10 RGGB",
 276                .bits_per_sample        = 10,
 277                .packing                = SOC_MBUS_PACKING_EXTEND16,
 278                .order                  = SOC_MBUS_ORDER_LE,
 279        },
 280}, {
 281        .code = V4L2_MBUS_FMT_SBGGR12_1X12,
 282        .fmt = {
 283                .fourcc                 = V4L2_PIX_FMT_SBGGR12,
 284                .name                   = "Bayer 12 BGGR",
 285                .bits_per_sample        = 12,
 286                .packing                = SOC_MBUS_PACKING_EXTEND16,
 287                .order                  = SOC_MBUS_ORDER_LE,
 288        },
 289}, {
 290        .code = V4L2_MBUS_FMT_SGBRG12_1X12,
 291        .fmt = {
 292                .fourcc                 = V4L2_PIX_FMT_SGBRG12,
 293                .name                   = "Bayer 12 GBRG",
 294                .bits_per_sample        = 12,
 295                .packing                = SOC_MBUS_PACKING_EXTEND16,
 296                .order                  = SOC_MBUS_ORDER_LE,
 297        },
 298}, {
 299        .code = V4L2_MBUS_FMT_SGRBG12_1X12,
 300        .fmt = {
 301                .fourcc                 = V4L2_PIX_FMT_SGRBG12,
 302                .name                   = "Bayer 12 GRBG",
 303                .bits_per_sample        = 12,
 304                .packing                = SOC_MBUS_PACKING_EXTEND16,
 305                .order                  = SOC_MBUS_ORDER_LE,
 306        },
 307}, {
 308        .code = V4L2_MBUS_FMT_SRGGB12_1X12,
 309        .fmt = {
 310                .fourcc                 = V4L2_PIX_FMT_SRGGB12,
 311                .name                   = "Bayer 12 RGGB",
 312                .bits_per_sample        = 12,
 313                .packing                = SOC_MBUS_PACKING_EXTEND16,
 314                .order                  = SOC_MBUS_ORDER_LE,
 315        },
 316},
 317};
 318
 319int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf,
 320                        unsigned int *numerator, unsigned int *denominator)
 321{
 322        switch (mf->packing) {
 323        case SOC_MBUS_PACKING_NONE:
 324        case SOC_MBUS_PACKING_EXTEND16:
 325                *numerator = 1;
 326                *denominator = 1;
 327                return 0;
 328        case SOC_MBUS_PACKING_2X8_PADHI:
 329        case SOC_MBUS_PACKING_2X8_PADLO:
 330                *numerator = 2;
 331                *denominator = 1;
 332                return 0;
 333        case SOC_MBUS_PACKING_1_5X8:
 334                *numerator = 3;
 335                *denominator = 2;
 336                return 0;
 337        case SOC_MBUS_PACKING_VARIABLE:
 338                *numerator = 0;
 339                *denominator = 1;
 340                return 0;
 341        }
 342        return -EINVAL;
 343}
 344EXPORT_SYMBOL(soc_mbus_samples_per_pixel);
 345
 346s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
 347{
 348        switch (mf->packing) {
 349        case SOC_MBUS_PACKING_NONE:
 350                return width * mf->bits_per_sample / 8;
 351        case SOC_MBUS_PACKING_2X8_PADHI:
 352        case SOC_MBUS_PACKING_2X8_PADLO:
 353        case SOC_MBUS_PACKING_EXTEND16:
 354                return width * 2;
 355        case SOC_MBUS_PACKING_1_5X8:
 356                return width * 3 / 2;
 357        case SOC_MBUS_PACKING_VARIABLE:
 358                return 0;
 359        }
 360        return -EINVAL;
 361}
 362EXPORT_SYMBOL(soc_mbus_bytes_per_line);
 363
 364const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
 365        enum v4l2_mbus_pixelcode code,
 366        const struct soc_mbus_lookup *lookup,
 367        int n)
 368{
 369        int i;
 370
 371        for (i = 0; i < n; i++)
 372                if (lookup[i].code == code)
 373                        return &lookup[i].fmt;
 374
 375        return NULL;
 376}
 377EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
 378
 379const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
 380        enum v4l2_mbus_pixelcode code)
 381{
 382        return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
 383}
 384EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
 385
 386static int __init soc_mbus_init(void)
 387{
 388        return 0;
 389}
 390
 391static void __exit soc_mbus_exit(void)
 392{
 393}
 394
 395module_init(soc_mbus_init);
 396module_exit(soc_mbus_exit);
 397
 398MODULE_DESCRIPTION("soc-camera media bus interface");
 399MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
 400MODULE_LICENSE("GPL v2");
 401