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