This source file includes following definitions.
- vimc_deb_pix_map_by_code
- vimc_deb_init_cfg
- vimc_deb_enum_mbus_code
- vimc_deb_enum_frame_size
- vimc_deb_get_fmt
- vimc_deb_adjust_sink_fmt
- vimc_deb_set_fmt
- vimc_deb_set_rgb_mbus_fmt_rgb888_1x24
- vimc_deb_s_stream
- vimc_deb_get_val
- vimc_deb_calc_rgb_sink
- vimc_deb_process_frame
- vimc_deb_release
- vimc_deb_comp_unbind
- vimc_deb_comp_bind
- vimc_deb_probe
- vimc_deb_remove
1
2
3
4
5
6
7
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>
15
16 #include "vimc-common.h"
17
18 #define VIMC_DEB_DRV_NAME "vimc-debayer"
19
20 static unsigned int deb_mean_win_size = 3;
21 module_param(deb_mean_win_size, uint, 0000);
22 MODULE_PARM_DESC(deb_mean_win_size, " the window size to calculate the mean.\n"
23 "NOTE: the window size needs to be an odd number, as the main pixel "
24 "stays in the center of the window, otherwise the next odd number "
25 "is considered");
26
27 #define IS_SINK(pad) (!pad)
28 #define IS_SRC(pad) (pad)
29
30 enum vimc_deb_rgb_colors {
31 VIMC_DEB_RED = 0,
32 VIMC_DEB_GREEN = 1,
33 VIMC_DEB_BLUE = 2,
34 };
35
36 struct vimc_deb_pix_map {
37 u32 code;
38 enum vimc_deb_rgb_colors order[2][2];
39 };
40
41 struct vimc_deb_device {
42 struct vimc_ent_device ved;
43 struct v4l2_subdev sd;
44 struct device *dev;
45
46 struct v4l2_mbus_framefmt sink_fmt;
47 u32 src_code;
48 void (*set_rgb_src)(struct vimc_deb_device *vdeb, unsigned int lin,
49 unsigned int col, unsigned int rgb[3]);
50
51 u8 *src_frame;
52 const struct vimc_deb_pix_map *sink_pix_map;
53 unsigned int sink_bpp;
54 };
55
56 static const struct v4l2_mbus_framefmt sink_fmt_default = {
57 .width = 640,
58 .height = 480,
59 .code = MEDIA_BUS_FMT_SRGGB8_1X8,
60 .field = V4L2_FIELD_NONE,
61 .colorspace = V4L2_COLORSPACE_DEFAULT,
62 };
63
64 static const struct vimc_deb_pix_map vimc_deb_pix_map_list[] = {
65 {
66 .code = MEDIA_BUS_FMT_SBGGR8_1X8,
67 .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
68 { VIMC_DEB_GREEN, VIMC_DEB_RED } }
69 },
70 {
71 .code = MEDIA_BUS_FMT_SGBRG8_1X8,
72 .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
73 { VIMC_DEB_RED, VIMC_DEB_GREEN } }
74 },
75 {
76 .code = MEDIA_BUS_FMT_SGRBG8_1X8,
77 .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
78 { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
79 },
80 {
81 .code = MEDIA_BUS_FMT_SRGGB8_1X8,
82 .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
83 { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
84 },
85 {
86 .code = MEDIA_BUS_FMT_SBGGR10_1X10,
87 .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
88 { VIMC_DEB_GREEN, VIMC_DEB_RED } }
89 },
90 {
91 .code = MEDIA_BUS_FMT_SGBRG10_1X10,
92 .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
93 { VIMC_DEB_RED, VIMC_DEB_GREEN } }
94 },
95 {
96 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
97 .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
98 { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
99 },
100 {
101 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
102 .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
103 { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
104 },
105 {
106 .code = MEDIA_BUS_FMT_SBGGR12_1X12,
107 .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
108 { VIMC_DEB_GREEN, VIMC_DEB_RED } }
109 },
110 {
111 .code = MEDIA_BUS_FMT_SGBRG12_1X12,
112 .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
113 { VIMC_DEB_RED, VIMC_DEB_GREEN } }
114 },
115 {
116 .code = MEDIA_BUS_FMT_SGRBG12_1X12,
117 .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
118 { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
119 },
120 {
121 .code = MEDIA_BUS_FMT_SRGGB12_1X12,
122 .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
123 { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
124 },
125 };
126
127 static const struct vimc_deb_pix_map *vimc_deb_pix_map_by_code(u32 code)
128 {
129 unsigned int i;
130
131 for (i = 0; i < ARRAY_SIZE(vimc_deb_pix_map_list); i++)
132 if (vimc_deb_pix_map_list[i].code == code)
133 return &vimc_deb_pix_map_list[i];
134
135 return NULL;
136 }
137
138 static int vimc_deb_init_cfg(struct v4l2_subdev *sd,
139 struct v4l2_subdev_pad_config *cfg)
140 {
141 struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
142 struct v4l2_mbus_framefmt *mf;
143 unsigned int i;
144
145 mf = v4l2_subdev_get_try_format(sd, cfg, 0);
146 *mf = sink_fmt_default;
147
148 for (i = 1; i < sd->entity.num_pads; i++) {
149 mf = v4l2_subdev_get_try_format(sd, cfg, i);
150 *mf = sink_fmt_default;
151 mf->code = vdeb->src_code;
152 }
153
154 return 0;
155 }
156
157 static int vimc_deb_enum_mbus_code(struct v4l2_subdev *sd,
158 struct v4l2_subdev_pad_config *cfg,
159 struct v4l2_subdev_mbus_code_enum *code)
160 {
161
162 if (IS_SRC(code->pad)) {
163 struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
164
165 if (code->index)
166 return -EINVAL;
167
168 code->code = vdeb->src_code;
169 } else {
170 if (code->index >= ARRAY_SIZE(vimc_deb_pix_map_list))
171 return -EINVAL;
172
173 code->code = vimc_deb_pix_map_list[code->index].code;
174 }
175
176 return 0;
177 }
178
179 static int vimc_deb_enum_frame_size(struct v4l2_subdev *sd,
180 struct v4l2_subdev_pad_config *cfg,
181 struct v4l2_subdev_frame_size_enum *fse)
182 {
183 struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
184
185 if (fse->index)
186 return -EINVAL;
187
188 if (IS_SINK(fse->pad)) {
189 const struct vimc_deb_pix_map *vpix =
190 vimc_deb_pix_map_by_code(fse->code);
191
192 if (!vpix)
193 return -EINVAL;
194 } else if (fse->code != vdeb->src_code) {
195 return -EINVAL;
196 }
197
198 fse->min_width = VIMC_FRAME_MIN_WIDTH;
199 fse->max_width = VIMC_FRAME_MAX_WIDTH;
200 fse->min_height = VIMC_FRAME_MIN_HEIGHT;
201 fse->max_height = VIMC_FRAME_MAX_HEIGHT;
202
203 return 0;
204 }
205
206 static int vimc_deb_get_fmt(struct v4l2_subdev *sd,
207 struct v4l2_subdev_pad_config *cfg,
208 struct v4l2_subdev_format *fmt)
209 {
210 struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
211
212
213 fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
214 *v4l2_subdev_get_try_format(sd, cfg, 0) :
215 vdeb->sink_fmt;
216
217
218 if (IS_SRC(fmt->pad))
219 fmt->format.code = vdeb->src_code;
220
221 return 0;
222 }
223
224 static void vimc_deb_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
225 {
226 const struct vimc_deb_pix_map *vpix;
227
228
229 vpix = vimc_deb_pix_map_by_code(fmt->code);
230 if (!vpix)
231 fmt->code = sink_fmt_default.code;
232
233 fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
234 VIMC_FRAME_MAX_WIDTH) & ~1;
235 fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
236 VIMC_FRAME_MAX_HEIGHT) & ~1;
237
238 if (fmt->field == V4L2_FIELD_ANY)
239 fmt->field = sink_fmt_default.field;
240
241 vimc_colorimetry_clamp(fmt);
242 }
243
244 static int vimc_deb_set_fmt(struct v4l2_subdev *sd,
245 struct v4l2_subdev_pad_config *cfg,
246 struct v4l2_subdev_format *fmt)
247 {
248 struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
249 struct v4l2_mbus_framefmt *sink_fmt;
250
251 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
252
253 if (vdeb->src_frame)
254 return -EBUSY;
255
256 sink_fmt = &vdeb->sink_fmt;
257 } else {
258 sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
259 }
260
261
262
263
264
265 if (IS_SRC(fmt->pad)) {
266 fmt->format = *sink_fmt;
267
268 fmt->format.code = vdeb->src_code;
269 } else {
270
271 vimc_deb_adjust_sink_fmt(&fmt->format);
272
273 dev_dbg(vdeb->dev, "%s: sink format update: "
274 "old:%dx%d (0x%x, %d, %d, %d, %d) "
275 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdeb->sd.name,
276
277 sink_fmt->width, sink_fmt->height, sink_fmt->code,
278 sink_fmt->colorspace, sink_fmt->quantization,
279 sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
280
281 fmt->format.width, fmt->format.height, fmt->format.code,
282 fmt->format.colorspace, fmt->format.quantization,
283 fmt->format.xfer_func, fmt->format.ycbcr_enc);
284
285 *sink_fmt = fmt->format;
286 }
287
288 return 0;
289 }
290
291 static const struct v4l2_subdev_pad_ops vimc_deb_pad_ops = {
292 .init_cfg = vimc_deb_init_cfg,
293 .enum_mbus_code = vimc_deb_enum_mbus_code,
294 .enum_frame_size = vimc_deb_enum_frame_size,
295 .get_fmt = vimc_deb_get_fmt,
296 .set_fmt = vimc_deb_set_fmt,
297 };
298
299 static void vimc_deb_set_rgb_mbus_fmt_rgb888_1x24(struct vimc_deb_device *vdeb,
300 unsigned int lin,
301 unsigned int col,
302 unsigned int rgb[3])
303 {
304 unsigned int i, index;
305
306 index = VIMC_FRAME_INDEX(lin, col, vdeb->sink_fmt.width, 3);
307 for (i = 0; i < 3; i++)
308 vdeb->src_frame[index + i] = rgb[i];
309 }
310
311 static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
312 {
313 struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
314
315 if (enable) {
316 const struct vimc_pix_map *vpix;
317 unsigned int frame_size;
318
319 if (vdeb->src_frame)
320 return 0;
321
322
323 vpix = vimc_pix_map_by_code(vdeb->src_code);
324 frame_size = vdeb->sink_fmt.width * vdeb->sink_fmt.height *
325 vpix->bpp;
326
327
328 vpix = vimc_pix_map_by_code(vdeb->sink_fmt.code);
329 vdeb->sink_bpp = vpix->bpp;
330
331
332 vdeb->sink_pix_map =
333 vimc_deb_pix_map_by_code(vdeb->sink_fmt.code);
334
335
336
337
338
339 vdeb->src_frame = vmalloc(frame_size);
340 if (!vdeb->src_frame)
341 return -ENOMEM;
342
343 } else {
344 if (!vdeb->src_frame)
345 return 0;
346
347 vfree(vdeb->src_frame);
348 vdeb->src_frame = NULL;
349 }
350
351 return 0;
352 }
353
354 static const struct v4l2_subdev_video_ops vimc_deb_video_ops = {
355 .s_stream = vimc_deb_s_stream,
356 };
357
358 static const struct v4l2_subdev_ops vimc_deb_ops = {
359 .pad = &vimc_deb_pad_ops,
360 .video = &vimc_deb_video_ops,
361 };
362
363 static unsigned int vimc_deb_get_val(const u8 *bytes,
364 const unsigned int n_bytes)
365 {
366 unsigned int i;
367 unsigned int acc = 0;
368
369 for (i = 0; i < n_bytes; i++)
370 acc = acc + (bytes[i] << (8 * i));
371
372 return acc;
373 }
374
375 static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb,
376 const u8 *frame,
377 const unsigned int lin,
378 const unsigned int col,
379 unsigned int rgb[3])
380 {
381 unsigned int i, seek, wlin, wcol;
382 unsigned int n_rgb[3] = {0, 0, 0};
383
384 for (i = 0; i < 3; i++)
385 rgb[i] = 0;
386
387
388
389
390
391
392 seek = deb_mean_win_size / 2;
393
394
395
396 dev_dbg(vdeb->dev,
397 "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n",
398 vdeb->sd.name, lin, col, vdeb->sink_fmt.height, seek);
399
400
401
402
403
404
405
406 for (wlin = seek > lin ? 0 : lin - seek;
407 wlin < lin + seek + 1 && wlin < vdeb->sink_fmt.height;
408 wlin++) {
409
410
411
412
413
414
415
416 for (wcol = seek > col ? 0 : col - seek;
417 wcol < col + seek + 1 && wcol < vdeb->sink_fmt.width;
418 wcol++) {
419 enum vimc_deb_rgb_colors color;
420 unsigned int index;
421
422
423 color = vdeb->sink_pix_map->order[wlin % 2][wcol % 2];
424
425 index = VIMC_FRAME_INDEX(wlin, wcol,
426 vdeb->sink_fmt.width,
427 vdeb->sink_bpp);
428
429 dev_dbg(vdeb->dev,
430 "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n",
431 vdeb->sd.name, index, wlin, wcol, color);
432
433
434 rgb[color] = rgb[color] +
435 vimc_deb_get_val(&frame[index], vdeb->sink_bpp);
436
437
438 n_rgb[color]++;
439
440 dev_dbg(vdeb->dev, "deb: %s: RGB CALC: val %d, n %d\n",
441 vdeb->sd.name, rgb[color], n_rgb[color]);
442 }
443 }
444
445
446 for (i = 0; i < 3; i++) {
447 dev_dbg(vdeb->dev,
448 "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n",
449 vdeb->sd.name, lin, col, i, rgb[i], n_rgb[i]);
450
451 if (n_rgb[i])
452 rgb[i] = rgb[i] / n_rgb[i];
453
454 dev_dbg(vdeb->dev,
455 "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n",
456 vdeb->sd.name, lin, col, i, rgb[i]);
457 }
458 }
459
460 static void *vimc_deb_process_frame(struct vimc_ent_device *ved,
461 const void *sink_frame)
462 {
463 struct vimc_deb_device *vdeb = container_of(ved, struct vimc_deb_device,
464 ved);
465 unsigned int rgb[3];
466 unsigned int i, j;
467
468
469 if (!vdeb->src_frame)
470 return ERR_PTR(-EINVAL);
471
472 for (i = 0; i < vdeb->sink_fmt.height; i++)
473 for (j = 0; j < vdeb->sink_fmt.width; j++) {
474 vimc_deb_calc_rgb_sink(vdeb, sink_frame, i, j, rgb);
475 vdeb->set_rgb_src(vdeb, i, j, rgb);
476 }
477
478 return vdeb->src_frame;
479
480 }
481
482 static void vimc_deb_release(struct v4l2_subdev *sd)
483 {
484 struct vimc_deb_device *vdeb =
485 container_of(sd, struct vimc_deb_device, sd);
486
487 vimc_pads_cleanup(vdeb->ved.pads);
488 kfree(vdeb);
489 }
490
491 static const struct v4l2_subdev_internal_ops vimc_deb_int_ops = {
492 .release = vimc_deb_release,
493 };
494
495 static void vimc_deb_comp_unbind(struct device *comp, struct device *master,
496 void *master_data)
497 {
498 struct vimc_ent_device *ved = dev_get_drvdata(comp);
499 struct vimc_deb_device *vdeb = container_of(ved, struct vimc_deb_device,
500 ved);
501
502 vimc_ent_sd_unregister(ved, &vdeb->sd);
503 }
504
505 static int vimc_deb_comp_bind(struct device *comp, struct device *master,
506 void *master_data)
507 {
508 struct v4l2_device *v4l2_dev = master_data;
509 struct vimc_platform_data *pdata = comp->platform_data;
510 struct vimc_deb_device *vdeb;
511 int ret;
512
513
514 vdeb = kzalloc(sizeof(*vdeb), GFP_KERNEL);
515 if (!vdeb)
516 return -ENOMEM;
517
518
519 ret = vimc_ent_sd_register(&vdeb->ved, &vdeb->sd, v4l2_dev,
520 pdata->entity_name,
521 MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2,
522 (const unsigned long[2]) {MEDIA_PAD_FL_SINK,
523 MEDIA_PAD_FL_SOURCE},
524 &vimc_deb_int_ops, &vimc_deb_ops);
525 if (ret) {
526 kfree(vdeb);
527 return ret;
528 }
529
530 vdeb->ved.process_frame = vimc_deb_process_frame;
531 dev_set_drvdata(comp, &vdeb->ved);
532 vdeb->dev = comp;
533
534
535 vdeb->sink_fmt = sink_fmt_default;
536
537
538
539
540
541
542 vdeb->src_code = MEDIA_BUS_FMT_RGB888_1X24;
543 vdeb->set_rgb_src = vimc_deb_set_rgb_mbus_fmt_rgb888_1x24;
544
545 return 0;
546 }
547
548 static const struct component_ops vimc_deb_comp_ops = {
549 .bind = vimc_deb_comp_bind,
550 .unbind = vimc_deb_comp_unbind,
551 };
552
553 static int vimc_deb_probe(struct platform_device *pdev)
554 {
555 return component_add(&pdev->dev, &vimc_deb_comp_ops);
556 }
557
558 static int vimc_deb_remove(struct platform_device *pdev)
559 {
560 component_del(&pdev->dev, &vimc_deb_comp_ops);
561
562 return 0;
563 }
564
565 static const struct platform_device_id vimc_deb_driver_ids[] = {
566 {
567 .name = VIMC_DEB_DRV_NAME,
568 },
569 { }
570 };
571
572 static struct platform_driver vimc_deb_pdrv = {
573 .probe = vimc_deb_probe,
574 .remove = vimc_deb_remove,
575 .id_table = vimc_deb_driver_ids,
576 .driver = {
577 .name = VIMC_DEB_DRV_NAME,
578 },
579 };
580
581 module_platform_driver(vimc_deb_pdrv);
582
583 MODULE_DEVICE_TABLE(platform, vimc_deb_driver_ids);
584
585 MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Debayer");
586 MODULE_AUTHOR("Helen Mae Koike Fornazier <helen.fornazier@gmail.com>");
587 MODULE_LICENSE("GPL");