0001
0002
0003
0004
0005
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
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
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
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
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
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
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
0276
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
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
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
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
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
0356 vpix = vimc_pix_map_by_code(vdebayer->sink_fmt.code);
0357 vdebayer->sink_bpp = vpix->bpp;
0358
0359
0360 vdebayer->sink_pix_map =
0361 vimc_debayer_pix_map_by_code(vdebayer->sink_fmt.code);
0362
0363
0364
0365
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
0424
0425
0426
0427 seek = vdebayer->mean_win_size / 2;
0428
0429
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
0437
0438
0439
0440
0441 for (wlin = seek > lin ? 0 : lin - seek;
0442 wlin < lin + seek + 1 && wlin < vdebayer->sink_fmt.height;
0443 wlin++) {
0444
0445
0446
0447
0448
0449
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
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
0469 rgb[color] = rgb[color] +
0470 vimc_debayer_get_val(&frame[index],
0471 vdebayer->sink_bpp);
0472
0473
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
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
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
0573 vdebayer = kzalloc(sizeof(*vdebayer), GFP_KERNEL);
0574 if (!vdebayer)
0575 return ERR_PTR(-ENOMEM);
0576
0577
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
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
0603 vdebayer->sink_fmt = sink_fmt_default;
0604
0605
0606
0607
0608
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 };