1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * vimc-debayer.c Virtual Media Controller Driver
5 * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
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>
16 #include "vimc-common.h"
18 #define VIMC_DEB_DRV_NAME "vimc-debayer"
19 /* This module only supports tranforming a bayer format to V4L2_PIX_FMT_RGB24 */
20 #define VIMC_DEB_SRC_PIXFMT V4L2_PIX_FMT_RGB24
21 #define VIMC_DEB_SRC_MBUS_FMT_DEFAULT MEDIA_BUS_FMT_RGB888_1X24
23 static unsigned int deb_mean_win_size
= 3;
24 module_param(deb_mean_win_size
, uint
, 0000);
25 MODULE_PARM_DESC(deb_mean_win_size
, " the window size to calculate the mean.\n"
26 "NOTE: the window size need to be an odd number, as the main pixel "
27 "stays in the center of the window, otherwise the next odd number "
30 #define IS_SINK(pad) (!pad)
31 #define IS_SRC(pad) (pad)
33 enum vimc_deb_rgb_colors
{
39 struct vimc_deb_pix_map
{
42 enum vimc_deb_rgb_colors order
[2][2];
45 struct vimc_deb_device
{
46 struct vimc_ent_device ved
;
47 struct v4l2_subdev sd
;
49 /* The active format */
50 struct v4l2_mbus_framefmt sink_fmt
;
52 void (*set_rgb_src
)(struct vimc_deb_device
*vdeb
, unsigned int lin
,
53 unsigned int col
, unsigned int rgb
[3]);
54 /* Values calculated when the stream starts */
56 const struct vimc_deb_pix_map
*sink_pix_map
;
57 unsigned int sink_bpp
;
60 static const struct v4l2_mbus_framefmt sink_fmt_default
= {
63 .code
= MEDIA_BUS_FMT_SRGGB8_1X8
,
64 .field
= V4L2_FIELD_NONE
,
65 .colorspace
= V4L2_COLORSPACE_DEFAULT
,
68 static const struct vimc_deb_pix_map vimc_deb_pix_map_list
[] = {
70 .pixelformat
= V4L2_PIX_FMT_SBGGR8
,
71 .code
= MEDIA_BUS_FMT_SBGGR8_1X8
,
72 .order
= { { VIMC_DEB_BLUE
, VIMC_DEB_GREEN
},
73 { VIMC_DEB_GREEN
, VIMC_DEB_RED
} }
76 .pixelformat
= V4L2_PIX_FMT_SGBRG8
,
77 .code
= MEDIA_BUS_FMT_SGBRG8_1X8
,
78 .order
= { { VIMC_DEB_GREEN
, VIMC_DEB_BLUE
},
79 { VIMC_DEB_RED
, VIMC_DEB_GREEN
} }
82 .pixelformat
= V4L2_PIX_FMT_SGRBG8
,
83 .code
= MEDIA_BUS_FMT_SGRBG8_1X8
,
84 .order
= { { VIMC_DEB_GREEN
, VIMC_DEB_RED
},
85 { VIMC_DEB_BLUE
, VIMC_DEB_GREEN
} }
88 .pixelformat
= V4L2_PIX_FMT_SRGGB8
,
89 .code
= MEDIA_BUS_FMT_SRGGB8_1X8
,
90 .order
= { { VIMC_DEB_RED
, VIMC_DEB_GREEN
},
91 { VIMC_DEB_GREEN
, VIMC_DEB_BLUE
} }
94 .pixelformat
= V4L2_PIX_FMT_SBGGR10
,
95 .code
= MEDIA_BUS_FMT_SBGGR10_1X10
,
96 .order
= { { VIMC_DEB_BLUE
, VIMC_DEB_GREEN
},
97 { VIMC_DEB_GREEN
, VIMC_DEB_RED
} }
100 .pixelformat
= V4L2_PIX_FMT_SGBRG10
,
101 .code
= MEDIA_BUS_FMT_SGBRG10_1X10
,
102 .order
= { { VIMC_DEB_GREEN
, VIMC_DEB_BLUE
},
103 { VIMC_DEB_RED
, VIMC_DEB_GREEN
} }
106 .pixelformat
= V4L2_PIX_FMT_SGRBG10
,
107 .code
= MEDIA_BUS_FMT_SGRBG10_1X10
,
108 .order
= { { VIMC_DEB_GREEN
, VIMC_DEB_RED
},
109 { VIMC_DEB_BLUE
, VIMC_DEB_GREEN
} }
112 .pixelformat
= V4L2_PIX_FMT_SRGGB10
,
113 .code
= MEDIA_BUS_FMT_SRGGB10_1X10
,
114 .order
= { { VIMC_DEB_RED
, VIMC_DEB_GREEN
},
115 { VIMC_DEB_GREEN
, VIMC_DEB_BLUE
} }
118 .pixelformat
= V4L2_PIX_FMT_SBGGR12
,
119 .code
= MEDIA_BUS_FMT_SBGGR12_1X12
,
120 .order
= { { VIMC_DEB_BLUE
, VIMC_DEB_GREEN
},
121 { VIMC_DEB_GREEN
, VIMC_DEB_RED
} }
124 .pixelformat
= V4L2_PIX_FMT_SGBRG12
,
125 .code
= MEDIA_BUS_FMT_SGBRG12_1X12
,
126 .order
= { { VIMC_DEB_GREEN
, VIMC_DEB_BLUE
},
127 { VIMC_DEB_RED
, VIMC_DEB_GREEN
} }
130 .pixelformat
= V4L2_PIX_FMT_SGRBG12
,
131 .code
= MEDIA_BUS_FMT_SGRBG12_1X12
,
132 .order
= { { VIMC_DEB_GREEN
, VIMC_DEB_RED
},
133 { VIMC_DEB_BLUE
, VIMC_DEB_GREEN
} }
136 .pixelformat
= V4L2_PIX_FMT_SRGGB12
,
137 .code
= MEDIA_BUS_FMT_SRGGB12_1X12
,
138 .order
= { { VIMC_DEB_RED
, VIMC_DEB_GREEN
},
139 { VIMC_DEB_GREEN
, VIMC_DEB_BLUE
} }
143 static const struct vimc_deb_pix_map
*vimc_deb_pix_map_by_code(u32 code
)
147 for (i
= 0; i
< ARRAY_SIZE(vimc_deb_pix_map_list
); i
++)
148 if (vimc_deb_pix_map_list
[i
].code
== code
)
149 return &vimc_deb_pix_map_list
[i
];
154 static int vimc_deb_init_cfg(struct v4l2_subdev
*sd
,
155 struct v4l2_subdev_pad_config
*cfg
)
157 struct vimc_deb_device
*vdeb
= v4l2_get_subdevdata(sd
);
158 struct v4l2_mbus_framefmt
*mf
;
161 mf
= v4l2_subdev_get_try_format(sd
, cfg
, 0);
162 *mf
= sink_fmt_default
;
164 for (i
= 1; i
< sd
->entity
.num_pads
; i
++) {
165 mf
= v4l2_subdev_get_try_format(sd
, cfg
, i
);
166 *mf
= sink_fmt_default
;
167 mf
->code
= vdeb
->src_code
;
173 static int vimc_deb_enum_mbus_code(struct v4l2_subdev
*sd
,
174 struct v4l2_subdev_pad_config
*cfg
,
175 struct v4l2_subdev_mbus_code_enum
*code
)
177 /* For the sink pad we only support codes in the map_list */
178 if (IS_SINK(code
->pad
)) {
179 if (code
->index
>= ARRAY_SIZE(vimc_deb_pix_map_list
))
182 code
->code
= vimc_deb_pix_map_list
[code
->index
].code
;
186 return vimc_enum_mbus_code(sd
, cfg
, code
);
189 static int vimc_deb_enum_frame_size(struct v4l2_subdev
*sd
,
190 struct v4l2_subdev_pad_config
*cfg
,
191 struct v4l2_subdev_frame_size_enum
*fse
)
196 /* For the sink pad we only support codes in the map_list */
197 if (IS_SINK(fse
->pad
)) {
198 const struct vimc_deb_pix_map
*vpix
=
199 vimc_deb_pix_map_by_code(fse
->code
);
205 fse
->min_width
= VIMC_FRAME_MIN_WIDTH
;
206 fse
->max_width
= VIMC_FRAME_MAX_WIDTH
;
207 fse
->min_height
= VIMC_FRAME_MIN_HEIGHT
;
208 fse
->max_height
= VIMC_FRAME_MAX_HEIGHT
;
213 static int vimc_deb_get_fmt(struct v4l2_subdev
*sd
,
214 struct v4l2_subdev_pad_config
*cfg
,
215 struct v4l2_subdev_format
*fmt
)
217 struct vimc_deb_device
*vdeb
= v4l2_get_subdevdata(sd
);
219 /* Get the current sink format */
220 fmt
->format
= fmt
->which
== V4L2_SUBDEV_FORMAT_TRY
?
221 *v4l2_subdev_get_try_format(sd
, cfg
, 0) :
224 /* Set the right code for the source pad */
225 if (IS_SRC(fmt
->pad
))
226 fmt
->format
.code
= vdeb
->src_code
;
231 static void vimc_deb_adjust_sink_fmt(struct v4l2_mbus_framefmt
*fmt
)
233 const struct vimc_deb_pix_map
*vpix
;
235 /* Don't accept a code that is not on the debayer table */
236 vpix
= vimc_deb_pix_map_by_code(fmt
->code
);
238 fmt
->code
= sink_fmt_default
.code
;
240 fmt
->width
= clamp_t(u32
, fmt
->width
, VIMC_FRAME_MIN_WIDTH
,
241 VIMC_FRAME_MAX_WIDTH
) & ~1;
242 fmt
->height
= clamp_t(u32
, fmt
->height
, VIMC_FRAME_MIN_HEIGHT
,
243 VIMC_FRAME_MAX_HEIGHT
) & ~1;
245 if (fmt
->field
== V4L2_FIELD_ANY
)
246 fmt
->field
= sink_fmt_default
.field
;
248 vimc_colorimetry_clamp(fmt
);
251 static int vimc_deb_set_fmt(struct v4l2_subdev
*sd
,
252 struct v4l2_subdev_pad_config
*cfg
,
253 struct v4l2_subdev_format
*fmt
)
255 struct vimc_deb_device
*vdeb
= v4l2_get_subdevdata(sd
);
256 struct v4l2_mbus_framefmt
*sink_fmt
;
258 if (!vimc_mbus_code_supported(fmt
->format
.code
))
259 fmt
->format
.code
= sink_fmt_default
.code
;
261 if (fmt
->which
== V4L2_SUBDEV_FORMAT_ACTIVE
) {
262 /* Do not change the format while stream is on */
266 sink_fmt
= &vdeb
->sink_fmt
;
268 sink_fmt
= v4l2_subdev_get_try_format(sd
, cfg
, 0);
272 * Do not change the format of the source pad,
273 * it is propagated from the sink (except for the code)
275 if (IS_SRC(fmt
->pad
)) {
276 vdeb
->src_code
= fmt
->format
.code
;
277 fmt
->format
= *sink_fmt
;
278 fmt
->format
.code
= vdeb
->src_code
;
280 /* Set the new format in the sink pad */
281 vimc_deb_adjust_sink_fmt(&fmt
->format
);
283 dev_dbg(vdeb
->dev
, "%s: sink format update: "
284 "old:%dx%d (0x%x, %d, %d, %d, %d) "
285 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdeb
->sd
.name
,
287 sink_fmt
->width
, sink_fmt
->height
, sink_fmt
->code
,
288 sink_fmt
->colorspace
, sink_fmt
->quantization
,
289 sink_fmt
->xfer_func
, sink_fmt
->ycbcr_enc
,
291 fmt
->format
.width
, fmt
->format
.height
, fmt
->format
.code
,
292 fmt
->format
.colorspace
, fmt
->format
.quantization
,
293 fmt
->format
.xfer_func
, fmt
->format
.ycbcr_enc
);
295 *sink_fmt
= fmt
->format
;
301 static const struct v4l2_subdev_pad_ops vimc_deb_pad_ops
= {
302 .init_cfg
= vimc_deb_init_cfg
,
303 .enum_mbus_code
= vimc_deb_enum_mbus_code
,
304 .enum_frame_size
= vimc_deb_enum_frame_size
,
305 .get_fmt
= vimc_deb_get_fmt
,
306 .set_fmt
= vimc_deb_set_fmt
,
309 static void vimc_deb_set_rgb_pix_rgb24(struct vimc_deb_device
*vdeb
,
314 unsigned int i
, index
;
316 index
= VIMC_FRAME_INDEX(lin
, col
, vdeb
->sink_fmt
.width
, 3);
317 for (i
= 0; i
< 3; i
++)
318 vdeb
->src_frame
[index
+ i
] = rgb
[i
];
321 static int vimc_deb_s_stream(struct v4l2_subdev
*sd
, int enable
)
323 struct vimc_deb_device
*vdeb
= v4l2_get_subdevdata(sd
);
326 u32 src_pixelformat
= vdeb
->ved
.stream
->producer_pixfmt
;
327 const struct v4l2_format_info
*pix_info
;
328 unsigned int frame_size
;
333 /* We only support translating bayer to RGB24 */
334 if (src_pixelformat
!= V4L2_PIX_FMT_RGB24
) {
336 "translating to pixfmt (0x%08x) is not supported\n",
341 /* Get the corresponding pixel map from the table */
343 vimc_deb_pix_map_by_code(vdeb
->sink_fmt
.code
);
345 /* Request bayer format from the pipeline for the sink pad */
346 vdeb
->ved
.stream
->producer_pixfmt
=
347 vdeb
->sink_pix_map
->pixelformat
;
349 /* Calculate frame_size of the source */
350 pix_info
= v4l2_format_info(src_pixelformat
);
351 frame_size
= vdeb
->sink_fmt
.width
* vdeb
->sink_fmt
.height
*
354 /* Get bpp from the sink */
355 pix_info
= v4l2_format_info(vdeb
->sink_pix_map
->pixelformat
);
356 vdeb
->sink_bpp
= pix_info
->bpp
[0];
359 * Allocate the frame buffer. Use vmalloc to be able to
360 * allocate a large amount of memory
362 vdeb
->src_frame
= vmalloc(frame_size
);
363 if (!vdeb
->src_frame
)
367 if (!vdeb
->src_frame
)
370 vfree(vdeb
->src_frame
);
371 vdeb
->src_frame
= NULL
;
377 static const struct v4l2_subdev_video_ops vimc_deb_video_ops
= {
378 .s_stream
= vimc_deb_s_stream
,
381 static const struct v4l2_subdev_ops vimc_deb_ops
= {
382 .pad
= &vimc_deb_pad_ops
,
383 .video
= &vimc_deb_video_ops
,
386 static unsigned int vimc_deb_get_val(const u8
*bytes
,
387 const unsigned int n_bytes
)
390 unsigned int acc
= 0;
392 for (i
= 0; i
< n_bytes
; i
++)
393 acc
= acc
+ (bytes
[i
] << (8 * i
));
398 static void vimc_deb_calc_rgb_sink(struct vimc_deb_device
*vdeb
,
400 const unsigned int lin
,
401 const unsigned int col
,
404 unsigned int i
, seek
, wlin
, wcol
;
405 unsigned int n_rgb
[3] = {0, 0, 0};
407 for (i
= 0; i
< 3; i
++)
411 * Calculate how many we need to subtract to get to the pixel in
412 * the top left corner of the mean window (considering the current
413 * pixel as the center)
415 seek
= deb_mean_win_size
/ 2;
417 /* Sum the values of the colors in the mean window */
420 "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n",
421 vdeb
->sd
.name
, lin
, col
, vdeb
->sink_fmt
.height
, seek
);
424 * Iterate through all the lines in the mean window, start
425 * with zero if the pixel is outside the frame and don't pass
426 * the height when the pixel is in the bottom border of the
429 for (wlin
= seek
> lin
? 0 : lin
- seek
;
430 wlin
< lin
+ seek
+ 1 && wlin
< vdeb
->sink_fmt
.height
;
434 * Iterate through all the columns in the mean window, start
435 * with zero if the pixel is outside the frame and don't pass
436 * the width when the pixel is in the right border of the
439 for (wcol
= seek
> col
? 0 : col
- seek
;
440 wcol
< col
+ seek
+ 1 && wcol
< vdeb
->sink_fmt
.width
;
442 enum vimc_deb_rgb_colors color
;
445 /* Check which color this pixel is */
446 color
= vdeb
->sink_pix_map
->order
[wlin
% 2][wcol
% 2];
448 index
= VIMC_FRAME_INDEX(wlin
, wcol
,
449 vdeb
->sink_fmt
.width
,
453 "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n",
454 vdeb
->sd
.name
, index
, wlin
, wcol
, color
);
457 rgb
[color
] = rgb
[color
] +
458 vimc_deb_get_val(&frame
[index
], vdeb
->sink_bpp
);
460 /* Save how many values we already added */
463 dev_dbg(vdeb
->dev
, "deb: %s: RGB CALC: val %d, n %d\n",
464 vdeb
->sd
.name
, rgb
[color
], n_rgb
[color
]);
468 /* Calculate the mean */
469 for (i
= 0; i
< 3; i
++) {
471 "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n",
472 vdeb
->sd
.name
, lin
, col
, i
, rgb
[i
], n_rgb
[i
]);
475 rgb
[i
] = rgb
[i
] / n_rgb
[i
];
478 "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n",
479 vdeb
->sd
.name
, lin
, col
, i
, rgb
[i
]);
483 static void *vimc_deb_process_frame(struct vimc_ent_device
*ved
,
484 const void *sink_frame
)
486 struct vimc_deb_device
*vdeb
= container_of(ved
, struct vimc_deb_device
,
491 /* If the stream in this node is not active, just return */
492 if (!vdeb
->src_frame
)
493 return ERR_PTR(-EINVAL
);
495 for (i
= 0; i
< vdeb
->sink_fmt
.height
; i
++)
496 for (j
= 0; j
< vdeb
->sink_fmt
.width
; j
++) {
497 vimc_deb_calc_rgb_sink(vdeb
, sink_frame
, i
, j
, rgb
);
498 vdeb
->set_rgb_src(vdeb
, i
, j
, rgb
);
501 return vdeb
->src_frame
;
505 static void vimc_deb_release(struct v4l2_subdev
*sd
)
507 struct vimc_deb_device
*vdeb
=
508 container_of(sd
, struct vimc_deb_device
, sd
);
513 static const struct v4l2_subdev_internal_ops vimc_deb_int_ops
= {
514 .release
= vimc_deb_release
,
517 static void vimc_deb_comp_unbind(struct device
*comp
, struct device
*master
,
520 struct vimc_ent_device
*ved
= dev_get_drvdata(comp
);
521 struct vimc_deb_device
*vdeb
= container_of(ved
, struct vimc_deb_device
,
524 vimc_ent_sd_unregister(ved
, &vdeb
->sd
);
527 static int vimc_deb_comp_bind(struct device
*comp
, struct device
*master
,
530 struct v4l2_device
*v4l2_dev
= master_data
;
531 struct vimc_platform_data
*pdata
= comp
->platform_data
;
532 struct vimc_deb_device
*vdeb
;
535 /* Allocate the vdeb struct */
536 vdeb
= kzalloc(sizeof(*vdeb
), GFP_KERNEL
);
540 /* Initialize ved and sd */
541 ret
= vimc_ent_sd_register(&vdeb
->ved
, &vdeb
->sd
, v4l2_dev
,
543 MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV
, 2,
544 (const unsigned long[2]) {MEDIA_PAD_FL_SINK
,
545 MEDIA_PAD_FL_SOURCE
},
546 &vimc_deb_int_ops
, &vimc_deb_ops
);
552 vdeb
->ved
.process_frame
= vimc_deb_process_frame
;
553 dev_set_drvdata(comp
, &vdeb
->ved
);
556 /* Initialize the frame format */
557 vdeb
->sink_fmt
= sink_fmt_default
;
558 vdeb
->src_code
= VIMC_DEB_SRC_MBUS_FMT_DEFAULT
;
560 * TODO: Add support for more output formats, we only support
562 * NOTE: the src format is always the same as the sink, except
565 vdeb
->set_rgb_src
= vimc_deb_set_rgb_pix_rgb24
;
570 static const struct component_ops vimc_deb_comp_ops
= {
571 .bind
= vimc_deb_comp_bind
,
572 .unbind
= vimc_deb_comp_unbind
,
575 static int vimc_deb_probe(struct platform_device
*pdev
)
577 return component_add(&pdev
->dev
, &vimc_deb_comp_ops
);
580 static int vimc_deb_remove(struct platform_device
*pdev
)
582 component_del(&pdev
->dev
, &vimc_deb_comp_ops
);
587 static const struct platform_device_id vimc_deb_driver_ids
[] = {
589 .name
= VIMC_DEB_DRV_NAME
,
594 static struct platform_driver vimc_deb_pdrv
= {
595 .probe
= vimc_deb_probe
,
596 .remove
= vimc_deb_remove
,
597 .id_table
= vimc_deb_driver_ids
,
599 .name
= VIMC_DEB_DRV_NAME
,
603 module_platform_driver(vimc_deb_pdrv
);
605 MODULE_DEVICE_TABLE(platform
, vimc_deb_driver_ids
);
607 MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Debayer");
608 MODULE_AUTHOR("Helen Mae Koike Fornazier <helen.fornazier@gmail.com>");
609 MODULE_LICENSE("GPL");