Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * vimc-debayer.c Virtual Media Controller Driver
0004  *
0005  * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
0006  */
0007 
0008 #include <linux/moduleparam.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/vmalloc.h>
0011 #include <linux/v4l2-mediabus.h>
0012 #include <media/v4l2-ctrls.h>
0013 #include <media/v4l2-event.h>
0014 #include <media/v4l2-subdev.h>
0015 
0016 #include "vimc-common.h"
0017 
0018 enum vimc_debayer_rgb_colors {
0019     VIMC_DEBAYER_RED = 0,
0020     VIMC_DEBAYER_GREEN = 1,
0021     VIMC_DEBAYER_BLUE = 2,
0022 };
0023 
0024 struct vimc_debayer_pix_map {
0025     u32 code;
0026     enum vimc_debayer_rgb_colors order[2][2];
0027 };
0028 
0029 struct vimc_debayer_device {
0030     struct vimc_ent_device ved;
0031     struct v4l2_subdev sd;
0032     /* The active format */
0033     struct v4l2_mbus_framefmt sink_fmt;
0034     u32 src_code;
0035     void (*set_rgb_src)(struct vimc_debayer_device *vdebayer,
0036                 unsigned int lin, unsigned int col,
0037                 unsigned int rgb[3]);
0038     /* Values calculated when the stream starts */
0039     u8 *src_frame;
0040     const struct vimc_debayer_pix_map *sink_pix_map;
0041     unsigned int sink_bpp;
0042     unsigned int mean_win_size;
0043     struct v4l2_ctrl_handler hdl;
0044     struct media_pad pads[2];
0045 };
0046 
0047 static const struct v4l2_mbus_framefmt sink_fmt_default = {
0048     .width = 640,
0049     .height = 480,
0050     .code = MEDIA_BUS_FMT_SRGGB8_1X8,
0051     .field = V4L2_FIELD_NONE,
0052     .colorspace = V4L2_COLORSPACE_SRGB,
0053 };
0054 
0055 static const u32 vimc_debayer_src_mbus_codes[] = {
0056     MEDIA_BUS_FMT_GBR888_1X24,
0057     MEDIA_BUS_FMT_BGR888_1X24,
0058     MEDIA_BUS_FMT_BGR888_3X8,
0059     MEDIA_BUS_FMT_RGB888_1X24,
0060     MEDIA_BUS_FMT_RGB888_2X12_BE,
0061     MEDIA_BUS_FMT_RGB888_2X12_LE,
0062     MEDIA_BUS_FMT_RGB888_3X8,
0063     MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
0064     MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
0065     MEDIA_BUS_FMT_RGB888_1X32_PADHI,
0066 };
0067 
0068 static const struct vimc_debayer_pix_map vimc_debayer_pix_map_list[] = {
0069     {
0070         .code = MEDIA_BUS_FMT_SBGGR8_1X8,
0071         .order = { { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN },
0072                { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED } }
0073     },
0074     {
0075         .code = MEDIA_BUS_FMT_SGBRG8_1X8,
0076         .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE },
0077                { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN } }
0078     },
0079     {
0080         .code = MEDIA_BUS_FMT_SGRBG8_1X8,
0081         .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED },
0082                { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN } }
0083     },
0084     {
0085         .code = MEDIA_BUS_FMT_SRGGB8_1X8,
0086         .order = { { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN },
0087                { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE } }
0088     },
0089     {
0090         .code = MEDIA_BUS_FMT_SBGGR10_1X10,
0091         .order = { { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN },
0092                { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED } }
0093     },
0094     {
0095         .code = MEDIA_BUS_FMT_SGBRG10_1X10,
0096         .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE },
0097                { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN } }
0098     },
0099     {
0100         .code = MEDIA_BUS_FMT_SGRBG10_1X10,
0101         .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED },
0102                { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN } }
0103     },
0104     {
0105         .code = MEDIA_BUS_FMT_SRGGB10_1X10,
0106         .order = { { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN },
0107                { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE } }
0108     },
0109     {
0110         .code = MEDIA_BUS_FMT_SBGGR12_1X12,
0111         .order = { { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN },
0112                { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED } }
0113     },
0114     {
0115         .code = MEDIA_BUS_FMT_SGBRG12_1X12,
0116         .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE },
0117                { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN } }
0118     },
0119     {
0120         .code = MEDIA_BUS_FMT_SGRBG12_1X12,
0121         .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED },
0122                { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN } }
0123     },
0124     {
0125         .code = MEDIA_BUS_FMT_SRGGB12_1X12,
0126         .order = { { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN },
0127                { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE } }
0128     },
0129 };
0130 
0131 static const struct vimc_debayer_pix_map *vimc_debayer_pix_map_by_code(u32 code)
0132 {
0133     unsigned int i;
0134 
0135     for (i = 0; i < ARRAY_SIZE(vimc_debayer_pix_map_list); i++)
0136         if (vimc_debayer_pix_map_list[i].code == code)
0137             return &vimc_debayer_pix_map_list[i];
0138 
0139     return NULL;
0140 }
0141 
0142 static bool vimc_debayer_src_code_is_valid(u32 code)
0143 {
0144     unsigned int i;
0145 
0146     for (i = 0; i < ARRAY_SIZE(vimc_debayer_src_mbus_codes); i++)
0147         if (vimc_debayer_src_mbus_codes[i] == code)
0148             return true;
0149 
0150     return false;
0151 }
0152 
0153 static int vimc_debayer_init_cfg(struct v4l2_subdev *sd,
0154                  struct v4l2_subdev_state *sd_state)
0155 {
0156     struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd);
0157     struct v4l2_mbus_framefmt *mf;
0158     unsigned int i;
0159 
0160     mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
0161     *mf = sink_fmt_default;
0162 
0163     for (i = 1; i < sd->entity.num_pads; i++) {
0164         mf = v4l2_subdev_get_try_format(sd, sd_state, i);
0165         *mf = sink_fmt_default;
0166         mf->code = vdebayer->src_code;
0167     }
0168 
0169     return 0;
0170 }
0171 
0172 static int vimc_debayer_enum_mbus_code(struct v4l2_subdev *sd,
0173                        struct v4l2_subdev_state *sd_state,
0174                        struct v4l2_subdev_mbus_code_enum *code)
0175 {
0176     if (VIMC_IS_SRC(code->pad)) {
0177         if (code->index >= ARRAY_SIZE(vimc_debayer_src_mbus_codes))
0178             return -EINVAL;
0179 
0180         code->code = vimc_debayer_src_mbus_codes[code->index];
0181     } else {
0182         if (code->index >= ARRAY_SIZE(vimc_debayer_pix_map_list))
0183             return -EINVAL;
0184 
0185         code->code = vimc_debayer_pix_map_list[code->index].code;
0186     }
0187 
0188     return 0;
0189 }
0190 
0191 static int vimc_debayer_enum_frame_size(struct v4l2_subdev *sd,
0192                     struct v4l2_subdev_state *sd_state,
0193                     struct v4l2_subdev_frame_size_enum *fse)
0194 {
0195     if (fse->index)
0196         return -EINVAL;
0197 
0198     if (VIMC_IS_SINK(fse->pad)) {
0199         const struct vimc_debayer_pix_map *vpix =
0200             vimc_debayer_pix_map_by_code(fse->code);
0201 
0202         if (!vpix)
0203             return -EINVAL;
0204     } else if (!vimc_debayer_src_code_is_valid(fse->code)) {
0205         return -EINVAL;
0206     }
0207 
0208     fse->min_width = VIMC_FRAME_MIN_WIDTH;
0209     fse->max_width = VIMC_FRAME_MAX_WIDTH;
0210     fse->min_height = VIMC_FRAME_MIN_HEIGHT;
0211     fse->max_height = VIMC_FRAME_MAX_HEIGHT;
0212 
0213     return 0;
0214 }
0215 
0216 static int vimc_debayer_get_fmt(struct v4l2_subdev *sd,
0217                 struct v4l2_subdev_state *sd_state,
0218                 struct v4l2_subdev_format *fmt)
0219 {
0220     struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd);
0221 
0222     /* Get the current sink format */
0223     fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
0224               *v4l2_subdev_get_try_format(sd, sd_state, 0) :
0225               vdebayer->sink_fmt;
0226 
0227     /* Set the right code for the source pad */
0228     if (VIMC_IS_SRC(fmt->pad))
0229         fmt->format.code = vdebayer->src_code;
0230 
0231     return 0;
0232 }
0233 
0234 static void vimc_debayer_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
0235 {
0236     const struct vimc_debayer_pix_map *vpix;
0237 
0238     /* Don't accept a code that is not on the debayer table */
0239     vpix = vimc_debayer_pix_map_by_code(fmt->code);
0240     if (!vpix)
0241         fmt->code = sink_fmt_default.code;
0242 
0243     fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
0244                  VIMC_FRAME_MAX_WIDTH) & ~1;
0245     fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
0246                   VIMC_FRAME_MAX_HEIGHT) & ~1;
0247 
0248     if (fmt->field == V4L2_FIELD_ANY)
0249         fmt->field = sink_fmt_default.field;
0250 
0251     vimc_colorimetry_clamp(fmt);
0252 }
0253 
0254 static int vimc_debayer_set_fmt(struct v4l2_subdev *sd,
0255                 struct v4l2_subdev_state *sd_state,
0256                 struct v4l2_subdev_format *fmt)
0257 {
0258     struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd);
0259     struct v4l2_mbus_framefmt *sink_fmt;
0260     u32 *src_code;
0261 
0262     if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
0263         /* Do not change the format while stream is on */
0264         if (vdebayer->src_frame)
0265             return -EBUSY;
0266 
0267         sink_fmt = &vdebayer->sink_fmt;
0268         src_code = &vdebayer->src_code;
0269     } else {
0270         sink_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
0271         src_code = &v4l2_subdev_get_try_format(sd, sd_state, 1)->code;
0272     }
0273 
0274     /*
0275      * Do not change the format of the source pad,
0276      * it is propagated from the sink
0277      */
0278     if (VIMC_IS_SRC(fmt->pad)) {
0279         u32 code = fmt->format.code;
0280 
0281         fmt->format = *sink_fmt;
0282 
0283         if (vimc_debayer_src_code_is_valid(code))
0284             *src_code = code;
0285 
0286         fmt->format.code = *src_code;
0287     } else {
0288         /* Set the new format in the sink pad */
0289         vimc_debayer_adjust_sink_fmt(&fmt->format);
0290 
0291         dev_dbg(vdebayer->ved.dev, "%s: sink format update: "
0292             "old:%dx%d (0x%x, %d, %d, %d, %d) "
0293             "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdebayer->sd.name,
0294             /* old */
0295             sink_fmt->width, sink_fmt->height, sink_fmt->code,
0296             sink_fmt->colorspace, sink_fmt->quantization,
0297             sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
0298             /* new */
0299             fmt->format.width, fmt->format.height, fmt->format.code,
0300             fmt->format.colorspace, fmt->format.quantization,
0301             fmt->format.xfer_func, fmt->format.ycbcr_enc);
0302 
0303         *sink_fmt = fmt->format;
0304     }
0305 
0306     return 0;
0307 }
0308 
0309 static const struct v4l2_subdev_pad_ops vimc_debayer_pad_ops = {
0310     .init_cfg       = vimc_debayer_init_cfg,
0311     .enum_mbus_code     = vimc_debayer_enum_mbus_code,
0312     .enum_frame_size    = vimc_debayer_enum_frame_size,
0313     .get_fmt        = vimc_debayer_get_fmt,
0314     .set_fmt        = vimc_debayer_set_fmt,
0315 };
0316 
0317 static void vimc_debayer_process_rgb_frame(struct vimc_debayer_device *vdebayer,
0318                        unsigned int lin,
0319                        unsigned int col,
0320                        unsigned int rgb[3])
0321 {
0322     const struct vimc_pix_map *vpix;
0323     unsigned int i, index;
0324 
0325     vpix = vimc_pix_map_by_code(vdebayer->src_code);
0326     index = VIMC_FRAME_INDEX(lin, col, vdebayer->sink_fmt.width, 3);
0327     for (i = 0; i < 3; i++) {
0328         switch (vpix->pixelformat) {
0329         case V4L2_PIX_FMT_RGB24:
0330             vdebayer->src_frame[index + i] = rgb[i];
0331             break;
0332         case V4L2_PIX_FMT_BGR24:
0333             vdebayer->src_frame[index + i] = rgb[2 - i];
0334             break;
0335         }
0336     }
0337 }
0338 
0339 static int vimc_debayer_s_stream(struct v4l2_subdev *sd, int enable)
0340 {
0341     struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd);
0342 
0343     if (enable) {
0344         const struct vimc_pix_map *vpix;
0345         unsigned int frame_size;
0346 
0347         if (vdebayer->src_frame)
0348             return 0;
0349 
0350         /* Calculate the frame size of the source pad */
0351         vpix = vimc_pix_map_by_code(vdebayer->src_code);
0352         frame_size = vdebayer->sink_fmt.width * vdebayer->sink_fmt.height *
0353                 vpix->bpp;
0354 
0355         /* Save the bytes per pixel of the sink */
0356         vpix = vimc_pix_map_by_code(vdebayer->sink_fmt.code);
0357         vdebayer->sink_bpp = vpix->bpp;
0358 
0359         /* Get the corresponding pixel map from the table */
0360         vdebayer->sink_pix_map =
0361             vimc_debayer_pix_map_by_code(vdebayer->sink_fmt.code);
0362 
0363         /*
0364          * Allocate the frame buffer. Use vmalloc to be able to
0365          * allocate a large amount of memory
0366          */
0367         vdebayer->src_frame = vmalloc(frame_size);
0368         if (!vdebayer->src_frame)
0369             return -ENOMEM;
0370 
0371     } else {
0372         if (!vdebayer->src_frame)
0373             return 0;
0374 
0375         vfree(vdebayer->src_frame);
0376         vdebayer->src_frame = NULL;
0377     }
0378 
0379     return 0;
0380 }
0381 
0382 static const struct v4l2_subdev_core_ops vimc_debayer_core_ops = {
0383     .log_status = v4l2_ctrl_subdev_log_status,
0384     .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
0385     .unsubscribe_event = v4l2_event_subdev_unsubscribe,
0386 };
0387 
0388 static const struct v4l2_subdev_video_ops vimc_debayer_video_ops = {
0389     .s_stream = vimc_debayer_s_stream,
0390 };
0391 
0392 static const struct v4l2_subdev_ops vimc_debayer_ops = {
0393     .core = &vimc_debayer_core_ops,
0394     .pad = &vimc_debayer_pad_ops,
0395     .video = &vimc_debayer_video_ops,
0396 };
0397 
0398 static unsigned int vimc_debayer_get_val(const u8 *bytes,
0399                      const unsigned int n_bytes)
0400 {
0401     unsigned int i;
0402     unsigned int acc = 0;
0403 
0404     for (i = 0; i < n_bytes; i++)
0405         acc = acc + (bytes[i] << (8 * i));
0406 
0407     return acc;
0408 }
0409 
0410 static void vimc_debayer_calc_rgb_sink(struct vimc_debayer_device *vdebayer,
0411                        const u8 *frame,
0412                        const unsigned int lin,
0413                        const unsigned int col,
0414                        unsigned int rgb[3])
0415 {
0416     unsigned int i, seek, wlin, wcol;
0417     unsigned int n_rgb[3] = {0, 0, 0};
0418 
0419     for (i = 0; i < 3; i++)
0420         rgb[i] = 0;
0421 
0422     /*
0423      * Calculate how many we need to subtract to get to the pixel in
0424      * the top left corner of the mean window (considering the current
0425      * pixel as the center)
0426      */
0427     seek = vdebayer->mean_win_size / 2;
0428 
0429     /* Sum the values of the colors in the mean window */
0430 
0431     dev_dbg(vdebayer->ved.dev,
0432         "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n",
0433         vdebayer->sd.name, lin, col, vdebayer->sink_fmt.height, seek);
0434 
0435     /*
0436      * Iterate through all the lines in the mean window, start
0437      * with zero if the pixel is outside the frame and don't pass
0438      * the height when the pixel is in the bottom border of the
0439      * frame
0440      */
0441     for (wlin = seek > lin ? 0 : lin - seek;
0442          wlin < lin + seek + 1 && wlin < vdebayer->sink_fmt.height;
0443          wlin++) {
0444 
0445         /*
0446          * Iterate through all the columns in the mean window, start
0447          * with zero if the pixel is outside the frame and don't pass
0448          * the width when the pixel is in the right border of the
0449          * frame
0450          */
0451         for (wcol = seek > col ? 0 : col - seek;
0452              wcol < col + seek + 1 && wcol < vdebayer->sink_fmt.width;
0453              wcol++) {
0454             enum vimc_debayer_rgb_colors color;
0455             unsigned int index;
0456 
0457             /* Check which color this pixel is */
0458             color = vdebayer->sink_pix_map->order[wlin % 2][wcol % 2];
0459 
0460             index = VIMC_FRAME_INDEX(wlin, wcol,
0461                          vdebayer->sink_fmt.width,
0462                          vdebayer->sink_bpp);
0463 
0464             dev_dbg(vdebayer->ved.dev,
0465                 "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n",
0466                 vdebayer->sd.name, index, wlin, wcol, color);
0467 
0468             /* Get its value */
0469             rgb[color] = rgb[color] +
0470                 vimc_debayer_get_val(&frame[index],
0471                              vdebayer->sink_bpp);
0472 
0473             /* Save how many values we already added */
0474             n_rgb[color]++;
0475 
0476             dev_dbg(vdebayer->ved.dev, "deb: %s: RGB CALC: val %d, n %d\n",
0477                 vdebayer->sd.name, rgb[color], n_rgb[color]);
0478         }
0479     }
0480 
0481     /* Calculate the mean */
0482     for (i = 0; i < 3; i++) {
0483         dev_dbg(vdebayer->ved.dev,
0484             "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n",
0485             vdebayer->sd.name, lin, col, i, rgb[i], n_rgb[i]);
0486 
0487         if (n_rgb[i])
0488             rgb[i] = rgb[i] / n_rgb[i];
0489 
0490         dev_dbg(vdebayer->ved.dev,
0491             "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n",
0492             vdebayer->sd.name, lin, col, i, rgb[i]);
0493     }
0494 }
0495 
0496 static void *vimc_debayer_process_frame(struct vimc_ent_device *ved,
0497                     const void *sink_frame)
0498 {
0499     struct vimc_debayer_device *vdebayer =
0500         container_of(ved, struct vimc_debayer_device, ved);
0501 
0502     unsigned int rgb[3];
0503     unsigned int i, j;
0504 
0505     /* If the stream in this node is not active, just return */
0506     if (!vdebayer->src_frame)
0507         return ERR_PTR(-EINVAL);
0508 
0509     for (i = 0; i < vdebayer->sink_fmt.height; i++)
0510         for (j = 0; j < vdebayer->sink_fmt.width; j++) {
0511             vimc_debayer_calc_rgb_sink(vdebayer, sink_frame, i, j, rgb);
0512             vdebayer->set_rgb_src(vdebayer, i, j, rgb);
0513         }
0514 
0515     return vdebayer->src_frame;
0516 }
0517 
0518 static int vimc_debayer_s_ctrl(struct v4l2_ctrl *ctrl)
0519 {
0520     struct vimc_debayer_device *vdebayer =
0521         container_of(ctrl->handler, struct vimc_debayer_device, hdl);
0522 
0523     switch (ctrl->id) {
0524     case VIMC_CID_MEAN_WIN_SIZE:
0525         vdebayer->mean_win_size = ctrl->val;
0526         break;
0527     default:
0528         return -EINVAL;
0529     }
0530     return 0;
0531 }
0532 
0533 static const struct v4l2_ctrl_ops vimc_debayer_ctrl_ops = {
0534     .s_ctrl = vimc_debayer_s_ctrl,
0535 };
0536 
0537 static void vimc_debayer_release(struct vimc_ent_device *ved)
0538 {
0539     struct vimc_debayer_device *vdebayer =
0540         container_of(ved, struct vimc_debayer_device, ved);
0541 
0542     v4l2_ctrl_handler_free(&vdebayer->hdl);
0543     media_entity_cleanup(vdebayer->ved.ent);
0544     kfree(vdebayer);
0545 }
0546 
0547 static const struct v4l2_ctrl_config vimc_debayer_ctrl_class = {
0548     .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
0549     .id = VIMC_CID_VIMC_CLASS,
0550     .name = "VIMC Controls",
0551     .type = V4L2_CTRL_TYPE_CTRL_CLASS,
0552 };
0553 
0554 static const struct v4l2_ctrl_config vimc_debayer_ctrl_mean_win_size = {
0555     .ops = &vimc_debayer_ctrl_ops,
0556     .id = VIMC_CID_MEAN_WIN_SIZE,
0557     .name = "Debayer Mean Window Size",
0558     .type = V4L2_CTRL_TYPE_INTEGER,
0559     .min = 1,
0560     .max = 25,
0561     .step = 2,
0562     .def = 3,
0563 };
0564 
0565 static struct vimc_ent_device *vimc_debayer_add(struct vimc_device *vimc,
0566                         const char *vcfg_name)
0567 {
0568     struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
0569     struct vimc_debayer_device *vdebayer;
0570     int ret;
0571 
0572     /* Allocate the vdebayer struct */
0573     vdebayer = kzalloc(sizeof(*vdebayer), GFP_KERNEL);
0574     if (!vdebayer)
0575         return ERR_PTR(-ENOMEM);
0576 
0577     /* Create controls: */
0578     v4l2_ctrl_handler_init(&vdebayer->hdl, 2);
0579     v4l2_ctrl_new_custom(&vdebayer->hdl, &vimc_debayer_ctrl_class, NULL);
0580     v4l2_ctrl_new_custom(&vdebayer->hdl, &vimc_debayer_ctrl_mean_win_size, NULL);
0581     vdebayer->sd.ctrl_handler = &vdebayer->hdl;
0582     if (vdebayer->hdl.error) {
0583         ret = vdebayer->hdl.error;
0584         goto err_free_vdebayer;
0585     }
0586 
0587     /* Initialize ved and sd */
0588     vdebayer->pads[0].flags = MEDIA_PAD_FL_SINK;
0589     vdebayer->pads[1].flags = MEDIA_PAD_FL_SOURCE;
0590 
0591     ret = vimc_ent_sd_register(&vdebayer->ved, &vdebayer->sd, v4l2_dev,
0592                    vcfg_name,
0593                    MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2,
0594                    vdebayer->pads, &vimc_debayer_ops);
0595     if (ret)
0596         goto err_free_hdl;
0597 
0598     vdebayer->ved.process_frame = vimc_debayer_process_frame;
0599     vdebayer->ved.dev = vimc->mdev.dev;
0600     vdebayer->mean_win_size = vimc_debayer_ctrl_mean_win_size.def;
0601 
0602     /* Initialize the frame format */
0603     vdebayer->sink_fmt = sink_fmt_default;
0604     /*
0605      * TODO: Add support for more output formats, we only support
0606      * RGB888 for now
0607      * NOTE: the src format is always the same as the sink, except
0608      * for the code
0609      */
0610     vdebayer->src_code = MEDIA_BUS_FMT_RGB888_1X24;
0611     vdebayer->set_rgb_src = vimc_debayer_process_rgb_frame;
0612 
0613     return &vdebayer->ved;
0614 
0615 err_free_hdl:
0616     v4l2_ctrl_handler_free(&vdebayer->hdl);
0617 err_free_vdebayer:
0618     kfree(vdebayer);
0619 
0620     return ERR_PTR(ret);
0621 }
0622 
0623 struct vimc_ent_type vimc_debayer_type = {
0624     .add = vimc_debayer_add,
0625     .release = vimc_debayer_release
0626 };