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/moduleparam.h> 9 #include <linux/platform_device.h> 10 #include <linux/vmalloc.h> 11 #include <linux/v4l2-mediabus.h> 12 #include <media/v4l2-ctrls.h> 13 #include <media/v4l2-event.h> 14 #include <media/v4l2-subdev.h> 15 16 #include "vimc-common.h" 17 18 enum vimc_debayer_rgb_colors { 19 VIMC_DEBAYER_RED = 0, 20 VIMC_DEBAYER_GREEN = 1, 21 VIMC_DEBAYER_BLUE = 2, 22 }; 23 24 struct vimc_debayer_pix_map { 25 u32 code; 26 enum vimc_debayer_rgb_colors order[2][2]; 27 }; 28 29 struct vimc_debayer_device { 30 struct vimc_ent_device ved; 31 struct v4l2_subdev sd; 32 /* The active format */ 33 struct v4l2_mbus_framefmt sink_fmt; 34 u32 src_code; 35 void (*set_rgb_src)(struct vimc_debayer_device *vdebayer, 36 unsigned int lin, unsigned int col, 37 unsigned int rgb[3]); 38 /* Values calculated when the stream starts */ 39 u8 *src_frame; 40 const struct vimc_debayer_pix_map *sink_pix_map; 41 unsigned int sink_bpp; 42 unsigned int mean_win_size; 43 struct v4l2_ctrl_handler hdl; 44 struct media_pad pads[2]; 45 }; 46 47 static const struct v4l2_mbus_framefmt sink_fmt_default = { 48 .width = 640, 49 .height = 480, 50 .code = MEDIA_BUS_FMT_SRGGB8_1X8, 51 .field = V4L2_FIELD_NONE, 52 .colorspace = V4L2_COLORSPACE_SRGB, 53 }; 54 55 static const u32 vimc_debayer_src_mbus_codes[] = { 56 MEDIA_BUS_FMT_GBR888_1X24, 57 MEDIA_BUS_FMT_BGR888_1X24, 58 MEDIA_BUS_FMT_BGR888_3X8, 59 MEDIA_BUS_FMT_RGB888_1X24, 60 MEDIA_BUS_FMT_RGB888_2X12_BE, 61 MEDIA_BUS_FMT_RGB888_2X12_LE, 62 MEDIA_BUS_FMT_RGB888_3X8, 63 MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 64 MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 65 MEDIA_BUS_FMT_RGB888_1X32_PADHI, 66 }; 67 68 static const struct vimc_debayer_pix_map vimc_debayer_pix_map_list[] = { 69 { 70 .code = MEDIA_BUS_FMT_SBGGR8_1X8, 71 .order = { { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN }, 72 { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED } } 73 }, 74 { 75 .code = MEDIA_BUS_FMT_SGBRG8_1X8, 76 .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE }, 77 { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN } } 78 }, 79 { 80 .code = MEDIA_BUS_FMT_SGRBG8_1X8, 81 .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED }, 82 { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN } } 83 }, 84 { 85 .code = MEDIA_BUS_FMT_SRGGB8_1X8, 86 .order = { { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN }, 87 { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE } } 88 }, 89 { 90 .code = MEDIA_BUS_FMT_SBGGR10_1X10, 91 .order = { { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN }, 92 { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED } } 93 }, 94 { 95 .code = MEDIA_BUS_FMT_SGBRG10_1X10, 96 .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE }, 97 { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN } } 98 }, 99 { 100 .code = MEDIA_BUS_FMT_SGRBG10_1X10, 101 .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED }, 102 { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN } } 103 }, 104 { 105 .code = MEDIA_BUS_FMT_SRGGB10_1X10, 106 .order = { { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN }, 107 { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE } } 108 }, 109 { 110 .code = MEDIA_BUS_FMT_SBGGR12_1X12, 111 .order = { { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN }, 112 { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED } } 113 }, 114 { 115 .code = MEDIA_BUS_FMT_SGBRG12_1X12, 116 .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE }, 117 { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN } } 118 }, 119 { 120 .code = MEDIA_BUS_FMT_SGRBG12_1X12, 121 .order = { { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_RED }, 122 { VIMC_DEBAYER_BLUE, VIMC_DEBAYER_GREEN } } 123 }, 124 { 125 .code = MEDIA_BUS_FMT_SRGGB12_1X12, 126 .order = { { VIMC_DEBAYER_RED, VIMC_DEBAYER_GREEN }, 127 { VIMC_DEBAYER_GREEN, VIMC_DEBAYER_BLUE } } 128 }, 129 }; 130 131 static const struct vimc_debayer_pix_map *vimc_debayer_pix_map_by_code(u32 code) 132 { 133 unsigned int i; 134 135 for (i = 0; i < ARRAY_SIZE(vimc_debayer_pix_map_list); i++) 136 if (vimc_debayer_pix_map_list[i].code == code) 137 return &vimc_debayer_pix_map_list[i]; 138 139 return NULL; 140 } 141 142 static bool vimc_debayer_src_code_is_valid(u32 code) 143 { 144 unsigned int i; 145 146 for (i = 0; i < ARRAY_SIZE(vimc_debayer_src_mbus_codes); i++) 147 if (vimc_debayer_src_mbus_codes[i] == code) 148 return true; 149 150 return false; 151 } 152 153 static int vimc_debayer_init_state(struct v4l2_subdev *sd, 154 struct v4l2_subdev_state *sd_state) 155 { 156 struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd); 157 struct v4l2_mbus_framefmt *mf; 158 unsigned int i; 159 160 mf = v4l2_subdev_state_get_format(sd_state, 0); 161 *mf = sink_fmt_default; 162 163 for (i = 1; i < sd->entity.num_pads; i++) { 164 mf = v4l2_subdev_state_get_format(sd_state, i); 165 *mf = sink_fmt_default; 166 mf->code = vdebayer->src_code; 167 } 168 169 return 0; 170 } 171 172 static int vimc_debayer_enum_mbus_code(struct v4l2_subdev *sd, 173 struct v4l2_subdev_state *sd_state, 174 struct v4l2_subdev_mbus_code_enum *code) 175 { 176 if (VIMC_IS_SRC(code->pad)) { 177 if (code->index >= ARRAY_SIZE(vimc_debayer_src_mbus_codes)) 178 return -EINVAL; 179 180 code->code = vimc_debayer_src_mbus_codes[code->index]; 181 } else { 182 if (code->index >= ARRAY_SIZE(vimc_debayer_pix_map_list)) 183 return -EINVAL; 184 185 code->code = vimc_debayer_pix_map_list[code->index].code; 186 } 187 188 return 0; 189 } 190 191 static int vimc_debayer_enum_frame_size(struct v4l2_subdev *sd, 192 struct v4l2_subdev_state *sd_state, 193 struct v4l2_subdev_frame_size_enum *fse) 194 { 195 if (fse->index) 196 return -EINVAL; 197 198 if (VIMC_IS_SINK(fse->pad)) { 199 const struct vimc_debayer_pix_map *vpix = 200 vimc_debayer_pix_map_by_code(fse->code); 201 202 if (!vpix) 203 return -EINVAL; 204 } else if (!vimc_debayer_src_code_is_valid(fse->code)) { 205 return -EINVAL; 206 } 207 208 fse->min_width = VIMC_FRAME_MIN_WIDTH; 209 fse->max_width = VIMC_FRAME_MAX_WIDTH; 210 fse->min_height = VIMC_FRAME_MIN_HEIGHT; 211 fse->max_height = VIMC_FRAME_MAX_HEIGHT; 212 213 return 0; 214 } 215 216 static int vimc_debayer_get_fmt(struct v4l2_subdev *sd, 217 struct v4l2_subdev_state *sd_state, 218 struct v4l2_subdev_format *fmt) 219 { 220 struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd); 221 222 /* Get the current sink format */ 223 fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ? 224 *v4l2_subdev_state_get_format(sd_state, 0) : 225 vdebayer->sink_fmt; 226 227 /* Set the right code for the source pad */ 228 if (VIMC_IS_SRC(fmt->pad)) 229 fmt->format.code = vdebayer->src_code; 230 231 return 0; 232 } 233 234 static void vimc_debayer_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt) 235 { 236 const struct vimc_debayer_pix_map *vpix; 237 238 /* Don't accept a code that is not on the debayer table */ 239 vpix = vimc_debayer_pix_map_by_code(fmt->code); 240 if (!vpix) 241 fmt->code = sink_fmt_default.code; 242 243 fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH, 244 VIMC_FRAME_MAX_WIDTH) & ~1; 245 fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT, 246 VIMC_FRAME_MAX_HEIGHT) & ~1; 247 248 if (fmt->field == V4L2_FIELD_ANY) 249 fmt->field = sink_fmt_default.field; 250 251 vimc_colorimetry_clamp(fmt); 252 } 253 254 static int vimc_debayer_set_fmt(struct v4l2_subdev *sd, 255 struct v4l2_subdev_state *sd_state, 256 struct v4l2_subdev_format *fmt) 257 { 258 struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd); 259 struct v4l2_mbus_framefmt *sink_fmt; 260 u32 *src_code; 261 262 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 263 /* Do not change the format while stream is on */ 264 if (vdebayer->src_frame) 265 return -EBUSY; 266 267 sink_fmt = &vdebayer->sink_fmt; 268 src_code = &vdebayer->src_code; 269 } else { 270 sink_fmt = v4l2_subdev_state_get_format(sd_state, 0); 271 src_code = &v4l2_subdev_state_get_format(sd_state, 1)->code; 272 } 273 274 /* 275 * Do not change the format of the source pad, 276 * it is propagated from the sink 277 */ 278 if (VIMC_IS_SRC(fmt->pad)) { 279 u32 code = fmt->format.code; 280 281 fmt->format = *sink_fmt; 282 283 if (vimc_debayer_src_code_is_valid(code)) 284 *src_code = code; 285 286 fmt->format.code = *src_code; 287 } else { 288 /* Set the new format in the sink pad */ 289 vimc_debayer_adjust_sink_fmt(&fmt->format); 290 291 dev_dbg(vdebayer->ved.dev, "%s: sink format update: " 292 "old:%dx%d (0x%x, %d, %d, %d, %d) " 293 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdebayer->sd.name, 294 /* old */ 295 sink_fmt->width, sink_fmt->height, sink_fmt->code, 296 sink_fmt->colorspace, sink_fmt->quantization, 297 sink_fmt->xfer_func, sink_fmt->ycbcr_enc, 298 /* new */ 299 fmt->format.width, fmt->format.height, fmt->format.code, 300 fmt->format.colorspace, fmt->format.quantization, 301 fmt->format.xfer_func, fmt->format.ycbcr_enc); 302 303 *sink_fmt = fmt->format; 304 } 305 306 return 0; 307 } 308 309 static const struct v4l2_subdev_pad_ops vimc_debayer_pad_ops = { 310 .enum_mbus_code = vimc_debayer_enum_mbus_code, 311 .enum_frame_size = vimc_debayer_enum_frame_size, 312 .get_fmt = vimc_debayer_get_fmt, 313 .set_fmt = vimc_debayer_set_fmt, 314 }; 315 316 static void vimc_debayer_process_rgb_frame(struct vimc_debayer_device *vdebayer, 317 unsigned int lin, 318 unsigned int col, 319 unsigned int rgb[3]) 320 { 321 const struct vimc_pix_map *vpix; 322 unsigned int i, index; 323 324 vpix = vimc_pix_map_by_code(vdebayer->src_code); 325 index = VIMC_FRAME_INDEX(lin, col, vdebayer->sink_fmt.width, 3); 326 for (i = 0; i < 3; i++) { 327 switch (vpix->pixelformat) { 328 case V4L2_PIX_FMT_RGB24: 329 vdebayer->src_frame[index + i] = rgb[i]; 330 break; 331 case V4L2_PIX_FMT_BGR24: 332 vdebayer->src_frame[index + i] = rgb[2 - i]; 333 break; 334 } 335 } 336 } 337 338 static int vimc_debayer_s_stream(struct v4l2_subdev *sd, int enable) 339 { 340 struct vimc_debayer_device *vdebayer = v4l2_get_subdevdata(sd); 341 342 if (enable) { 343 const struct vimc_pix_map *vpix; 344 unsigned int frame_size; 345 346 if (vdebayer->src_frame) 347 return 0; 348 349 /* Calculate the frame size of the source pad */ 350 vpix = vimc_pix_map_by_code(vdebayer->src_code); 351 frame_size = vdebayer->sink_fmt.width * vdebayer->sink_fmt.height * 352 vpix->bpp; 353 354 /* Save the bytes per pixel of the sink */ 355 vpix = vimc_pix_map_by_code(vdebayer->sink_fmt.code); 356 vdebayer->sink_bpp = vpix->bpp; 357 358 /* Get the corresponding pixel map from the table */ 359 vdebayer->sink_pix_map = 360 vimc_debayer_pix_map_by_code(vdebayer->sink_fmt.code); 361 362 /* 363 * Allocate the frame buffer. Use vmalloc to be able to 364 * allocate a large amount of memory 365 */ 366 vdebayer->src_frame = vmalloc(frame_size); 367 if (!vdebayer->src_frame) 368 return -ENOMEM; 369 370 } else { 371 if (!vdebayer->src_frame) 372 return 0; 373 374 vfree(vdebayer->src_frame); 375 vdebayer->src_frame = NULL; 376 } 377 378 return 0; 379 } 380 381 static const struct v4l2_subdev_core_ops vimc_debayer_core_ops = { 382 .log_status = v4l2_ctrl_subdev_log_status, 383 .subscribe_event = v4l2_ctrl_subdev_subscribe_event, 384 .unsubscribe_event = v4l2_event_subdev_unsubscribe, 385 }; 386 387 static const struct v4l2_subdev_video_ops vimc_debayer_video_ops = { 388 .s_stream = vimc_debayer_s_stream, 389 }; 390 391 static const struct v4l2_subdev_ops vimc_debayer_ops = { 392 .core = &vimc_debayer_core_ops, 393 .pad = &vimc_debayer_pad_ops, 394 .video = &vimc_debayer_video_ops, 395 }; 396 397 static const struct v4l2_subdev_internal_ops vimc_debayer_internal_ops = { 398 .init_state = vimc_debayer_init_state, 399 }; 400 401 static unsigned int vimc_debayer_get_val(const u8 *bytes, 402 const unsigned int n_bytes) 403 { 404 unsigned int i; 405 unsigned int acc = 0; 406 407 for (i = 0; i < n_bytes; i++) 408 acc = acc + (bytes[i] << (8 * i)); 409 410 return acc; 411 } 412 413 static void vimc_debayer_calc_rgb_sink(struct vimc_debayer_device *vdebayer, 414 const u8 *frame, 415 const unsigned int lin, 416 const unsigned int col, 417 unsigned int rgb[3]) 418 { 419 unsigned int i, seek, wlin, wcol; 420 unsigned int n_rgb[3] = {0, 0, 0}; 421 422 for (i = 0; i < 3; i++) 423 rgb[i] = 0; 424 425 /* 426 * Calculate how many we need to subtract to get to the pixel in 427 * the top left corner of the mean window (considering the current 428 * pixel as the center) 429 */ 430 seek = vdebayer->mean_win_size / 2; 431 432 /* Sum the values of the colors in the mean window */ 433 434 dev_dbg(vdebayer->ved.dev, 435 "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n", 436 vdebayer->sd.name, lin, col, vdebayer->sink_fmt.height, seek); 437 438 /* 439 * Iterate through all the lines in the mean window, start 440 * with zero if the pixel is outside the frame and don't pass 441 * the height when the pixel is in the bottom border of the 442 * frame 443 */ 444 for (wlin = seek > lin ? 0 : lin - seek; 445 wlin < lin + seek + 1 && wlin < vdebayer->sink_fmt.height; 446 wlin++) { 447 448 /* 449 * Iterate through all the columns in the mean window, start 450 * with zero if the pixel is outside the frame and don't pass 451 * the width when the pixel is in the right border of the 452 * frame 453 */ 454 for (wcol = seek > col ? 0 : col - seek; 455 wcol < col + seek + 1 && wcol < vdebayer->sink_fmt.width; 456 wcol++) { 457 enum vimc_debayer_rgb_colors color; 458 unsigned int index; 459 460 /* Check which color this pixel is */ 461 color = vdebayer->sink_pix_map->order[wlin % 2][wcol % 2]; 462 463 index = VIMC_FRAME_INDEX(wlin, wcol, 464 vdebayer->sink_fmt.width, 465 vdebayer->sink_bpp); 466 467 dev_dbg(vdebayer->ved.dev, 468 "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n", 469 vdebayer->sd.name, index, wlin, wcol, color); 470 471 /* Get its value */ 472 rgb[color] = rgb[color] + 473 vimc_debayer_get_val(&frame[index], 474 vdebayer->sink_bpp); 475 476 /* Save how many values we already added */ 477 n_rgb[color]++; 478 479 dev_dbg(vdebayer->ved.dev, "deb: %s: RGB CALC: val %d, n %d\n", 480 vdebayer->sd.name, rgb[color], n_rgb[color]); 481 } 482 } 483 484 /* Calculate the mean */ 485 for (i = 0; i < 3; i++) { 486 dev_dbg(vdebayer->ved.dev, 487 "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n", 488 vdebayer->sd.name, lin, col, i, rgb[i], n_rgb[i]); 489 490 if (n_rgb[i]) 491 rgb[i] = rgb[i] / n_rgb[i]; 492 493 dev_dbg(vdebayer->ved.dev, 494 "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n", 495 vdebayer->sd.name, lin, col, i, rgb[i]); 496 } 497 } 498 499 static void *vimc_debayer_process_frame(struct vimc_ent_device *ved, 500 const void *sink_frame) 501 { 502 struct vimc_debayer_device *vdebayer = 503 container_of(ved, struct vimc_debayer_device, ved); 504 505 unsigned int rgb[3]; 506 unsigned int i, j; 507 508 /* If the stream in this node is not active, just return */ 509 if (!vdebayer->src_frame) 510 return ERR_PTR(-EINVAL); 511 512 for (i = 0; i < vdebayer->sink_fmt.height; i++) 513 for (j = 0; j < vdebayer->sink_fmt.width; j++) { 514 vimc_debayer_calc_rgb_sink(vdebayer, sink_frame, i, j, rgb); 515 vdebayer->set_rgb_src(vdebayer, i, j, rgb); 516 } 517 518 return vdebayer->src_frame; 519 } 520 521 static int vimc_debayer_s_ctrl(struct v4l2_ctrl *ctrl) 522 { 523 struct vimc_debayer_device *vdebayer = 524 container_of(ctrl->handler, struct vimc_debayer_device, hdl); 525 526 switch (ctrl->id) { 527 case VIMC_CID_MEAN_WIN_SIZE: 528 vdebayer->mean_win_size = ctrl->val; 529 break; 530 default: 531 return -EINVAL; 532 } 533 return 0; 534 } 535 536 static const struct v4l2_ctrl_ops vimc_debayer_ctrl_ops = { 537 .s_ctrl = vimc_debayer_s_ctrl, 538 }; 539 540 static void vimc_debayer_release(struct vimc_ent_device *ved) 541 { 542 struct vimc_debayer_device *vdebayer = 543 container_of(ved, struct vimc_debayer_device, ved); 544 545 v4l2_ctrl_handler_free(&vdebayer->hdl); 546 media_entity_cleanup(vdebayer->ved.ent); 547 kfree(vdebayer); 548 } 549 550 static const struct v4l2_ctrl_config vimc_debayer_ctrl_class = { 551 .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY, 552 .id = VIMC_CID_VIMC_CLASS, 553 .name = "VIMC Controls", 554 .type = V4L2_CTRL_TYPE_CTRL_CLASS, 555 }; 556 557 static const struct v4l2_ctrl_config vimc_debayer_ctrl_mean_win_size = { 558 .ops = &vimc_debayer_ctrl_ops, 559 .id = VIMC_CID_MEAN_WIN_SIZE, 560 .name = "Debayer Mean Window Size", 561 .type = V4L2_CTRL_TYPE_INTEGER, 562 .min = 1, 563 .max = 25, 564 .step = 2, 565 .def = 3, 566 }; 567 568 static struct vimc_ent_device *vimc_debayer_add(struct vimc_device *vimc, 569 const char *vcfg_name) 570 { 571 struct v4l2_device *v4l2_dev = &vimc->v4l2_dev; 572 struct vimc_debayer_device *vdebayer; 573 int ret; 574 575 /* Allocate the vdebayer struct */ 576 vdebayer = kzalloc(sizeof(*vdebayer), GFP_KERNEL); 577 if (!vdebayer) 578 return ERR_PTR(-ENOMEM); 579 580 /* Create controls: */ 581 v4l2_ctrl_handler_init(&vdebayer->hdl, 2); 582 v4l2_ctrl_new_custom(&vdebayer->hdl, &vimc_debayer_ctrl_class, NULL); 583 v4l2_ctrl_new_custom(&vdebayer->hdl, &vimc_debayer_ctrl_mean_win_size, NULL); 584 vdebayer->sd.ctrl_handler = &vdebayer->hdl; 585 if (vdebayer->hdl.error) { 586 ret = vdebayer->hdl.error; 587 goto err_free_vdebayer; 588 } 589 590 /* Initialize ved and sd */ 591 vdebayer->pads[0].flags = MEDIA_PAD_FL_SINK; 592 vdebayer->pads[1].flags = MEDIA_PAD_FL_SOURCE; 593 594 ret = vimc_ent_sd_register(&vdebayer->ved, &vdebayer->sd, v4l2_dev, 595 vcfg_name, 596 MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2, 597 vdebayer->pads, &vimc_debayer_ops); 598 if (ret) 599 goto err_free_hdl; 600 601 vdebayer->sd.internal_ops = &vimc_debayer_internal_ops; 602 603 vdebayer->ved.process_frame = vimc_debayer_process_frame; 604 vdebayer->ved.dev = vimc->mdev.dev; 605 vdebayer->mean_win_size = vimc_debayer_ctrl_mean_win_size.def; 606 607 /* Initialize the frame format */ 608 vdebayer->sink_fmt = sink_fmt_default; 609 /* 610 * TODO: Add support for more output formats, we only support 611 * RGB888 for now 612 * NOTE: the src format is always the same as the sink, except 613 * for the code 614 */ 615 vdebayer->src_code = MEDIA_BUS_FMT_RGB888_1X24; 616 vdebayer->set_rgb_src = vimc_debayer_process_rgb_frame; 617 618 return &vdebayer->ved; 619 620 err_free_hdl: 621 v4l2_ctrl_handler_free(&vdebayer->hdl); 622 err_free_vdebayer: 623 kfree(vdebayer); 624 625 return ERR_PTR(ret); 626 } 627 628 struct vimc_ent_type vimc_debayer_type = { 629 .add = vimc_debayer_add, 630 .release = vimc_debayer_release 631 }; 632