root/drivers/media/platform/vimc/vimc-debayer.c

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

DEFINITIONS

This source file includes following definitions.
  1. vimc_deb_pix_map_by_code
  2. vimc_deb_init_cfg
  3. vimc_deb_enum_mbus_code
  4. vimc_deb_enum_frame_size
  5. vimc_deb_get_fmt
  6. vimc_deb_adjust_sink_fmt
  7. vimc_deb_set_fmt
  8. vimc_deb_set_rgb_mbus_fmt_rgb888_1x24
  9. vimc_deb_s_stream
  10. vimc_deb_get_val
  11. vimc_deb_calc_rgb_sink
  12. vimc_deb_process_frame
  13. vimc_deb_release
  14. vimc_deb_comp_unbind
  15. vimc_deb_comp_bind
  16. vimc_deb_probe
  17. vimc_deb_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * vimc-debayer.c Virtual Media Controller Driver
   4  *
   5  * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
   6  */
   7 
   8 #include <linux/component.h>
   9 #include <linux/module.h>
  10 #include <linux/mod_devicetable.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/vmalloc.h>
  13 #include <linux/v4l2-mediabus.h>
  14 #include <media/v4l2-subdev.h>
  15 
  16 #include "vimc-common.h"
  17 
  18 #define VIMC_DEB_DRV_NAME "vimc-debayer"
  19 
  20 static unsigned int deb_mean_win_size = 3;
  21 module_param(deb_mean_win_size, uint, 0000);
  22 MODULE_PARM_DESC(deb_mean_win_size, " the window size to calculate the mean.\n"
  23         "NOTE: the window size needs to be an odd number, as the main pixel "
  24         "stays in the center of the window, otherwise the next odd number "
  25         "is considered");
  26 
  27 #define IS_SINK(pad) (!pad)
  28 #define IS_SRC(pad)  (pad)
  29 
  30 enum vimc_deb_rgb_colors {
  31         VIMC_DEB_RED = 0,
  32         VIMC_DEB_GREEN = 1,
  33         VIMC_DEB_BLUE = 2,
  34 };
  35 
  36 struct vimc_deb_pix_map {
  37         u32 code;
  38         enum vimc_deb_rgb_colors order[2][2];
  39 };
  40 
  41 struct vimc_deb_device {
  42         struct vimc_ent_device ved;
  43         struct v4l2_subdev sd;
  44         struct device *dev;
  45         /* The active format */
  46         struct v4l2_mbus_framefmt sink_fmt;
  47         u32 src_code;
  48         void (*set_rgb_src)(struct vimc_deb_device *vdeb, unsigned int lin,
  49                             unsigned int col, unsigned int rgb[3]);
  50         /* Values calculated when the stream starts */
  51         u8 *src_frame;
  52         const struct vimc_deb_pix_map *sink_pix_map;
  53         unsigned int sink_bpp;
  54 };
  55 
  56 static const struct v4l2_mbus_framefmt sink_fmt_default = {
  57         .width = 640,
  58         .height = 480,
  59         .code = MEDIA_BUS_FMT_SRGGB8_1X8,
  60         .field = V4L2_FIELD_NONE,
  61         .colorspace = V4L2_COLORSPACE_DEFAULT,
  62 };
  63 
  64 static const struct vimc_deb_pix_map vimc_deb_pix_map_list[] = {
  65         {
  66                 .code = MEDIA_BUS_FMT_SBGGR8_1X8,
  67                 .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
  68                            { VIMC_DEB_GREEN, VIMC_DEB_RED } }
  69         },
  70         {
  71                 .code = MEDIA_BUS_FMT_SGBRG8_1X8,
  72                 .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
  73                            { VIMC_DEB_RED, VIMC_DEB_GREEN } }
  74         },
  75         {
  76                 .code = MEDIA_BUS_FMT_SGRBG8_1X8,
  77                 .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
  78                            { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
  79         },
  80         {
  81                 .code = MEDIA_BUS_FMT_SRGGB8_1X8,
  82                 .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
  83                            { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
  84         },
  85         {
  86                 .code = MEDIA_BUS_FMT_SBGGR10_1X10,
  87                 .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
  88                            { VIMC_DEB_GREEN, VIMC_DEB_RED } }
  89         },
  90         {
  91                 .code = MEDIA_BUS_FMT_SGBRG10_1X10,
  92                 .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
  93                            { VIMC_DEB_RED, VIMC_DEB_GREEN } }
  94         },
  95         {
  96                 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
  97                 .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
  98                            { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
  99         },
 100         {
 101                 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
 102                 .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
 103                            { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
 104         },
 105         {
 106                 .code = MEDIA_BUS_FMT_SBGGR12_1X12,
 107                 .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
 108                            { VIMC_DEB_GREEN, VIMC_DEB_RED } }
 109         },
 110         {
 111                 .code = MEDIA_BUS_FMT_SGBRG12_1X12,
 112                 .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
 113                            { VIMC_DEB_RED, VIMC_DEB_GREEN } }
 114         },
 115         {
 116                 .code = MEDIA_BUS_FMT_SGRBG12_1X12,
 117                 .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
 118                            { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
 119         },
 120         {
 121                 .code = MEDIA_BUS_FMT_SRGGB12_1X12,
 122                 .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
 123                            { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
 124         },
 125 };
 126 
 127 static const struct vimc_deb_pix_map *vimc_deb_pix_map_by_code(u32 code)
 128 {
 129         unsigned int i;
 130 
 131         for (i = 0; i < ARRAY_SIZE(vimc_deb_pix_map_list); i++)
 132                 if (vimc_deb_pix_map_list[i].code == code)
 133                         return &vimc_deb_pix_map_list[i];
 134 
 135         return NULL;
 136 }
 137 
 138 static int vimc_deb_init_cfg(struct v4l2_subdev *sd,
 139                              struct v4l2_subdev_pad_config *cfg)
 140 {
 141         struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
 142         struct v4l2_mbus_framefmt *mf;
 143         unsigned int i;
 144 
 145         mf = v4l2_subdev_get_try_format(sd, cfg, 0);
 146         *mf = sink_fmt_default;
 147 
 148         for (i = 1; i < sd->entity.num_pads; i++) {
 149                 mf = v4l2_subdev_get_try_format(sd, cfg, i);
 150                 *mf = sink_fmt_default;
 151                 mf->code = vdeb->src_code;
 152         }
 153 
 154         return 0;
 155 }
 156 
 157 static int vimc_deb_enum_mbus_code(struct v4l2_subdev *sd,
 158                                    struct v4l2_subdev_pad_config *cfg,
 159                                    struct v4l2_subdev_mbus_code_enum *code)
 160 {
 161         /* We only support one format for source pads */
 162         if (IS_SRC(code->pad)) {
 163                 struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
 164 
 165                 if (code->index)
 166                         return -EINVAL;
 167 
 168                 code->code = vdeb->src_code;
 169         } else {
 170                 if (code->index >= ARRAY_SIZE(vimc_deb_pix_map_list))
 171                         return -EINVAL;
 172 
 173                 code->code = vimc_deb_pix_map_list[code->index].code;
 174         }
 175 
 176         return 0;
 177 }
 178 
 179 static int vimc_deb_enum_frame_size(struct v4l2_subdev *sd,
 180                                     struct v4l2_subdev_pad_config *cfg,
 181                                     struct v4l2_subdev_frame_size_enum *fse)
 182 {
 183         struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
 184 
 185         if (fse->index)
 186                 return -EINVAL;
 187 
 188         if (IS_SINK(fse->pad)) {
 189                 const struct vimc_deb_pix_map *vpix =
 190                         vimc_deb_pix_map_by_code(fse->code);
 191 
 192                 if (!vpix)
 193                         return -EINVAL;
 194         } else if (fse->code != vdeb->src_code) {
 195                 return -EINVAL;
 196         }
 197 
 198         fse->min_width = VIMC_FRAME_MIN_WIDTH;
 199         fse->max_width = VIMC_FRAME_MAX_WIDTH;
 200         fse->min_height = VIMC_FRAME_MIN_HEIGHT;
 201         fse->max_height = VIMC_FRAME_MAX_HEIGHT;
 202 
 203         return 0;
 204 }
 205 
 206 static int vimc_deb_get_fmt(struct v4l2_subdev *sd,
 207                             struct v4l2_subdev_pad_config *cfg,
 208                             struct v4l2_subdev_format *fmt)
 209 {
 210         struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
 211 
 212         /* Get the current sink format */
 213         fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
 214                       *v4l2_subdev_get_try_format(sd, cfg, 0) :
 215                       vdeb->sink_fmt;
 216 
 217         /* Set the right code for the source pad */
 218         if (IS_SRC(fmt->pad))
 219                 fmt->format.code = vdeb->src_code;
 220 
 221         return 0;
 222 }
 223 
 224 static void vimc_deb_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
 225 {
 226         const struct vimc_deb_pix_map *vpix;
 227 
 228         /* Don't accept a code that is not on the debayer table */
 229         vpix = vimc_deb_pix_map_by_code(fmt->code);
 230         if (!vpix)
 231                 fmt->code = sink_fmt_default.code;
 232 
 233         fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
 234                              VIMC_FRAME_MAX_WIDTH) & ~1;
 235         fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
 236                               VIMC_FRAME_MAX_HEIGHT) & ~1;
 237 
 238         if (fmt->field == V4L2_FIELD_ANY)
 239                 fmt->field = sink_fmt_default.field;
 240 
 241         vimc_colorimetry_clamp(fmt);
 242 }
 243 
 244 static int vimc_deb_set_fmt(struct v4l2_subdev *sd,
 245                             struct v4l2_subdev_pad_config *cfg,
 246                             struct v4l2_subdev_format *fmt)
 247 {
 248         struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
 249         struct v4l2_mbus_framefmt *sink_fmt;
 250 
 251         if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 252                 /* Do not change the format while stream is on */
 253                 if (vdeb->src_frame)
 254                         return -EBUSY;
 255 
 256                 sink_fmt = &vdeb->sink_fmt;
 257         } else {
 258                 sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
 259         }
 260 
 261         /*
 262          * Do not change the format of the source pad,
 263          * it is propagated from the sink
 264          */
 265         if (IS_SRC(fmt->pad)) {
 266                 fmt->format = *sink_fmt;
 267                 /* TODO: Add support for other formats */
 268                 fmt->format.code = vdeb->src_code;
 269         } else {
 270                 /* Set the new format in the sink pad */
 271                 vimc_deb_adjust_sink_fmt(&fmt->format);
 272 
 273                 dev_dbg(vdeb->dev, "%s: sink format update: "
 274                         "old:%dx%d (0x%x, %d, %d, %d, %d) "
 275                         "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdeb->sd.name,
 276                         /* old */
 277                         sink_fmt->width, sink_fmt->height, sink_fmt->code,
 278                         sink_fmt->colorspace, sink_fmt->quantization,
 279                         sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
 280                         /* new */
 281                         fmt->format.width, fmt->format.height, fmt->format.code,
 282                         fmt->format.colorspace, fmt->format.quantization,
 283                         fmt->format.xfer_func, fmt->format.ycbcr_enc);
 284 
 285                 *sink_fmt = fmt->format;
 286         }
 287 
 288         return 0;
 289 }
 290 
 291 static const struct v4l2_subdev_pad_ops vimc_deb_pad_ops = {
 292         .init_cfg               = vimc_deb_init_cfg,
 293         .enum_mbus_code         = vimc_deb_enum_mbus_code,
 294         .enum_frame_size        = vimc_deb_enum_frame_size,
 295         .get_fmt                = vimc_deb_get_fmt,
 296         .set_fmt                = vimc_deb_set_fmt,
 297 };
 298 
 299 static void vimc_deb_set_rgb_mbus_fmt_rgb888_1x24(struct vimc_deb_device *vdeb,
 300                                                   unsigned int lin,
 301                                                   unsigned int col,
 302                                                   unsigned int rgb[3])
 303 {
 304         unsigned int i, index;
 305 
 306         index = VIMC_FRAME_INDEX(lin, col, vdeb->sink_fmt.width, 3);
 307         for (i = 0; i < 3; i++)
 308                 vdeb->src_frame[index + i] = rgb[i];
 309 }
 310 
 311 static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
 312 {
 313         struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
 314 
 315         if (enable) {
 316                 const struct vimc_pix_map *vpix;
 317                 unsigned int frame_size;
 318 
 319                 if (vdeb->src_frame)
 320                         return 0;
 321 
 322                 /* Calculate the frame size of the source pad */
 323                 vpix = vimc_pix_map_by_code(vdeb->src_code);
 324                 frame_size = vdeb->sink_fmt.width * vdeb->sink_fmt.height *
 325                                 vpix->bpp;
 326 
 327                 /* Save the bytes per pixel of the sink */
 328                 vpix = vimc_pix_map_by_code(vdeb->sink_fmt.code);
 329                 vdeb->sink_bpp = vpix->bpp;
 330 
 331                 /* Get the corresponding pixel map from the table */
 332                 vdeb->sink_pix_map =
 333                         vimc_deb_pix_map_by_code(vdeb->sink_fmt.code);
 334 
 335                 /*
 336                  * Allocate the frame buffer. Use vmalloc to be able to
 337                  * allocate a large amount of memory
 338                  */
 339                 vdeb->src_frame = vmalloc(frame_size);
 340                 if (!vdeb->src_frame)
 341                         return -ENOMEM;
 342 
 343         } else {
 344                 if (!vdeb->src_frame)
 345                         return 0;
 346 
 347                 vfree(vdeb->src_frame);
 348                 vdeb->src_frame = NULL;
 349         }
 350 
 351         return 0;
 352 }
 353 
 354 static const struct v4l2_subdev_video_ops vimc_deb_video_ops = {
 355         .s_stream = vimc_deb_s_stream,
 356 };
 357 
 358 static const struct v4l2_subdev_ops vimc_deb_ops = {
 359         .pad = &vimc_deb_pad_ops,
 360         .video = &vimc_deb_video_ops,
 361 };
 362 
 363 static unsigned int vimc_deb_get_val(const u8 *bytes,
 364                                      const unsigned int n_bytes)
 365 {
 366         unsigned int i;
 367         unsigned int acc = 0;
 368 
 369         for (i = 0; i < n_bytes; i++)
 370                 acc = acc + (bytes[i] << (8 * i));
 371 
 372         return acc;
 373 }
 374 
 375 static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb,
 376                                    const u8 *frame,
 377                                    const unsigned int lin,
 378                                    const unsigned int col,
 379                                    unsigned int rgb[3])
 380 {
 381         unsigned int i, seek, wlin, wcol;
 382         unsigned int n_rgb[3] = {0, 0, 0};
 383 
 384         for (i = 0; i < 3; i++)
 385                 rgb[i] = 0;
 386 
 387         /*
 388          * Calculate how many we need to subtract to get to the pixel in
 389          * the top left corner of the mean window (considering the current
 390          * pixel as the center)
 391          */
 392         seek = deb_mean_win_size / 2;
 393 
 394         /* Sum the values of the colors in the mean window */
 395 
 396         dev_dbg(vdeb->dev,
 397                 "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n",
 398                 vdeb->sd.name, lin, col, vdeb->sink_fmt.height, seek);
 399 
 400         /*
 401          * Iterate through all the lines in the mean window, start
 402          * with zero if the pixel is outside the frame and don't pass
 403          * the height when the pixel is in the bottom border of the
 404          * frame
 405          */
 406         for (wlin = seek > lin ? 0 : lin - seek;
 407              wlin < lin + seek + 1 && wlin < vdeb->sink_fmt.height;
 408              wlin++) {
 409 
 410                 /*
 411                  * Iterate through all the columns in the mean window, start
 412                  * with zero if the pixel is outside the frame and don't pass
 413                  * the width when the pixel is in the right border of the
 414                  * frame
 415                  */
 416                 for (wcol = seek > col ? 0 : col - seek;
 417                      wcol < col + seek + 1 && wcol < vdeb->sink_fmt.width;
 418                      wcol++) {
 419                         enum vimc_deb_rgb_colors color;
 420                         unsigned int index;
 421 
 422                         /* Check which color this pixel is */
 423                         color = vdeb->sink_pix_map->order[wlin % 2][wcol % 2];
 424 
 425                         index = VIMC_FRAME_INDEX(wlin, wcol,
 426                                                  vdeb->sink_fmt.width,
 427                                                  vdeb->sink_bpp);
 428 
 429                         dev_dbg(vdeb->dev,
 430                                 "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n",
 431                                 vdeb->sd.name, index, wlin, wcol, color);
 432 
 433                         /* Get its value */
 434                         rgb[color] = rgb[color] +
 435                                 vimc_deb_get_val(&frame[index], vdeb->sink_bpp);
 436 
 437                         /* Save how many values we already added */
 438                         n_rgb[color]++;
 439 
 440                         dev_dbg(vdeb->dev, "deb: %s: RGB CALC: val %d, n %d\n",
 441                                 vdeb->sd.name, rgb[color], n_rgb[color]);
 442                 }
 443         }
 444 
 445         /* Calculate the mean */
 446         for (i = 0; i < 3; i++) {
 447                 dev_dbg(vdeb->dev,
 448                         "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n",
 449                         vdeb->sd.name, lin, col, i, rgb[i], n_rgb[i]);
 450 
 451                 if (n_rgb[i])
 452                         rgb[i] = rgb[i] / n_rgb[i];
 453 
 454                 dev_dbg(vdeb->dev,
 455                         "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n",
 456                         vdeb->sd.name, lin, col, i, rgb[i]);
 457         }
 458 }
 459 
 460 static void *vimc_deb_process_frame(struct vimc_ent_device *ved,
 461                                     const void *sink_frame)
 462 {
 463         struct vimc_deb_device *vdeb = container_of(ved, struct vimc_deb_device,
 464                                                     ved);
 465         unsigned int rgb[3];
 466         unsigned int i, j;
 467 
 468         /* If the stream in this node is not active, just return */
 469         if (!vdeb->src_frame)
 470                 return ERR_PTR(-EINVAL);
 471 
 472         for (i = 0; i < vdeb->sink_fmt.height; i++)
 473                 for (j = 0; j < vdeb->sink_fmt.width; j++) {
 474                         vimc_deb_calc_rgb_sink(vdeb, sink_frame, i, j, rgb);
 475                         vdeb->set_rgb_src(vdeb, i, j, rgb);
 476                 }
 477 
 478         return vdeb->src_frame;
 479 
 480 }
 481 
 482 static void vimc_deb_release(struct v4l2_subdev *sd)
 483 {
 484         struct vimc_deb_device *vdeb =
 485                                 container_of(sd, struct vimc_deb_device, sd);
 486 
 487         vimc_pads_cleanup(vdeb->ved.pads);
 488         kfree(vdeb);
 489 }
 490 
 491 static const struct v4l2_subdev_internal_ops vimc_deb_int_ops = {
 492         .release = vimc_deb_release,
 493 };
 494 
 495 static void vimc_deb_comp_unbind(struct device *comp, struct device *master,
 496                                  void *master_data)
 497 {
 498         struct vimc_ent_device *ved = dev_get_drvdata(comp);
 499         struct vimc_deb_device *vdeb = container_of(ved, struct vimc_deb_device,
 500                                                     ved);
 501 
 502         vimc_ent_sd_unregister(ved, &vdeb->sd);
 503 }
 504 
 505 static int vimc_deb_comp_bind(struct device *comp, struct device *master,
 506                               void *master_data)
 507 {
 508         struct v4l2_device *v4l2_dev = master_data;
 509         struct vimc_platform_data *pdata = comp->platform_data;
 510         struct vimc_deb_device *vdeb;
 511         int ret;
 512 
 513         /* Allocate the vdeb struct */
 514         vdeb = kzalloc(sizeof(*vdeb), GFP_KERNEL);
 515         if (!vdeb)
 516                 return -ENOMEM;
 517 
 518         /* Initialize ved and sd */
 519         ret = vimc_ent_sd_register(&vdeb->ved, &vdeb->sd, v4l2_dev,
 520                                    pdata->entity_name,
 521                                    MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2,
 522                                    (const unsigned long[2]) {MEDIA_PAD_FL_SINK,
 523                                    MEDIA_PAD_FL_SOURCE},
 524                                    &vimc_deb_int_ops, &vimc_deb_ops);
 525         if (ret) {
 526                 kfree(vdeb);
 527                 return ret;
 528         }
 529 
 530         vdeb->ved.process_frame = vimc_deb_process_frame;
 531         dev_set_drvdata(comp, &vdeb->ved);
 532         vdeb->dev = comp;
 533 
 534         /* Initialize the frame format */
 535         vdeb->sink_fmt = sink_fmt_default;
 536         /*
 537          * TODO: Add support for more output formats, we only support
 538          * RGB888 for now
 539          * NOTE: the src format is always the same as the sink, except
 540          * for the code
 541          */
 542         vdeb->src_code = MEDIA_BUS_FMT_RGB888_1X24;
 543         vdeb->set_rgb_src = vimc_deb_set_rgb_mbus_fmt_rgb888_1x24;
 544 
 545         return 0;
 546 }
 547 
 548 static const struct component_ops vimc_deb_comp_ops = {
 549         .bind = vimc_deb_comp_bind,
 550         .unbind = vimc_deb_comp_unbind,
 551 };
 552 
 553 static int vimc_deb_probe(struct platform_device *pdev)
 554 {
 555         return component_add(&pdev->dev, &vimc_deb_comp_ops);
 556 }
 557 
 558 static int vimc_deb_remove(struct platform_device *pdev)
 559 {
 560         component_del(&pdev->dev, &vimc_deb_comp_ops);
 561 
 562         return 0;
 563 }
 564 
 565 static const struct platform_device_id vimc_deb_driver_ids[] = {
 566         {
 567                 .name           = VIMC_DEB_DRV_NAME,
 568         },
 569         { }
 570 };
 571 
 572 static struct platform_driver vimc_deb_pdrv = {
 573         .probe          = vimc_deb_probe,
 574         .remove         = vimc_deb_remove,
 575         .id_table       = vimc_deb_driver_ids,
 576         .driver         = {
 577                 .name   = VIMC_DEB_DRV_NAME,
 578         },
 579 };
 580 
 581 module_platform_driver(vimc_deb_pdrv);
 582 
 583 MODULE_DEVICE_TABLE(platform, vimc_deb_driver_ids);
 584 
 585 MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Debayer");
 586 MODULE_AUTHOR("Helen Mae Koike Fornazier <helen.fornazier@gmail.com>");
 587 MODULE_LICENSE("GPL");

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