Lines Matching +full:pixel +full:- +full:format
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>
11 #include <linux/v4l2-mediabus.h>
12 #include <media/v4l2-ctrls.h>
13 #include <media/v4l2-event.h>
14 #include <media/v4l2-subdev.h>
16 #include "vimc-common.h"
173 mf->code = VIMC_DEBAYER_SOURCE_MBUS_FMT; in vimc_debayer_init_state()
182 if (VIMC_IS_SRC(code->pad)) { in vimc_debayer_enum_mbus_code()
183 if (code->index >= ARRAY_SIZE(vimc_debayer_src_mbus_codes)) in vimc_debayer_enum_mbus_code()
184 return -EINVAL; in vimc_debayer_enum_mbus_code()
186 code->code = vimc_debayer_src_mbus_codes[code->index]; in vimc_debayer_enum_mbus_code()
188 if (code->index >= ARRAY_SIZE(vimc_debayer_pix_map_list)) in vimc_debayer_enum_mbus_code()
189 return -EINVAL; in vimc_debayer_enum_mbus_code()
191 code->code = vimc_debayer_pix_map_list[code->index].code; in vimc_debayer_enum_mbus_code()
201 if (fse->index) in vimc_debayer_enum_frame_size()
202 return -EINVAL; in vimc_debayer_enum_frame_size()
204 if (VIMC_IS_SINK(fse->pad)) { in vimc_debayer_enum_frame_size()
206 vimc_debayer_pix_map_by_code(fse->code); in vimc_debayer_enum_frame_size()
209 return -EINVAL; in vimc_debayer_enum_frame_size()
210 } else if (!vimc_debayer_src_code_is_valid(fse->code)) { in vimc_debayer_enum_frame_size()
211 return -EINVAL; in vimc_debayer_enum_frame_size()
214 fse->min_width = VIMC_FRAME_MIN_WIDTH; in vimc_debayer_enum_frame_size()
215 fse->max_width = VIMC_FRAME_MAX_WIDTH; in vimc_debayer_enum_frame_size()
216 fse->min_height = VIMC_FRAME_MIN_HEIGHT; in vimc_debayer_enum_frame_size()
217 fse->max_height = VIMC_FRAME_MAX_HEIGHT; in vimc_debayer_enum_frame_size()
227 vpix = vimc_debayer_pix_map_by_code(fmt->code); in vimc_debayer_adjust_sink_fmt()
229 fmt->code = sink_fmt_default.code; in vimc_debayer_adjust_sink_fmt()
231 fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH, in vimc_debayer_adjust_sink_fmt()
233 fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT, in vimc_debayer_adjust_sink_fmt()
236 if (fmt->field == V4L2_FIELD_ANY) in vimc_debayer_adjust_sink_fmt()
237 fmt->field = sink_fmt_default.field; in vimc_debayer_adjust_sink_fmt()
247 struct v4l2_mbus_framefmt *format; in vimc_debayer_set_fmt() local
249 /* Do not change the format while stream is on. */ in vimc_debayer_set_fmt()
250 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && vdebayer->src_frame) in vimc_debayer_set_fmt()
251 return -EBUSY; in vimc_debayer_set_fmt()
254 * Do not change the format of the source pad, it is propagated from in vimc_debayer_set_fmt()
257 if (VIMC_IS_SRC(fmt->pad)) in vimc_debayer_set_fmt()
260 /* Set the new format in the sink pad. */ in vimc_debayer_set_fmt()
261 vimc_debayer_adjust_sink_fmt(&fmt->format); in vimc_debayer_set_fmt()
263 format = v4l2_subdev_state_get_format(sd_state, 0); in vimc_debayer_set_fmt()
265 dev_dbg(vdebayer->ved.dev, "%s: sink format update: " in vimc_debayer_set_fmt()
267 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdebayer->sd.name, in vimc_debayer_set_fmt()
269 format->width, format->height, format->code, in vimc_debayer_set_fmt()
270 format->colorspace, format->quantization, in vimc_debayer_set_fmt()
271 format->xfer_func, format->ycbcr_enc, in vimc_debayer_set_fmt()
273 fmt->format.width, fmt->format.height, fmt->format.code, in vimc_debayer_set_fmt()
274 fmt->format.colorspace, fmt->format.quantization, in vimc_debayer_set_fmt()
275 fmt->format.xfer_func, fmt->format.ycbcr_enc); in vimc_debayer_set_fmt()
277 *format = fmt->format; in vimc_debayer_set_fmt()
279 /* Propagate the format to the source pad. */ in vimc_debayer_set_fmt()
280 format = v4l2_subdev_state_get_format(sd_state, 1); in vimc_debayer_set_fmt()
281 *format = fmt->format; in vimc_debayer_set_fmt()
282 format->code = VIMC_DEBAYER_SOURCE_MBUS_FMT; in vimc_debayer_set_fmt()
302 vpix = vimc_pix_map_by_code(vdebayer->hw.src_code); in vimc_debayer_process_rgb_frame()
303 index = VIMC_FRAME_INDEX(lin, col, vdebayer->hw.size.width, 3); in vimc_debayer_process_rgb_frame()
305 switch (vpix->pixelformat) { in vimc_debayer_process_rgb_frame()
307 vdebayer->src_frame[index + i] = rgb[i]; in vimc_debayer_process_rgb_frame()
310 vdebayer->src_frame[index + i] = rgb[2 - i]; in vimc_debayer_process_rgb_frame()
327 if (vdebayer->src_frame) in vimc_debayer_s_stream()
335 vpix = vimc_pix_map_by_code(src_fmt->code); in vimc_debayer_s_stream()
336 frame_size = src_fmt->width * src_fmt->height * vpix->bpp; in vimc_debayer_s_stream()
338 /* Save the bytes per pixel of the sink */ in vimc_debayer_s_stream()
339 vpix = vimc_pix_map_by_code(sink_fmt->code); in vimc_debayer_s_stream()
340 vdebayer->hw.sink_bpp = vpix->bpp; in vimc_debayer_s_stream()
342 /* Get the corresponding pixel map from the table */ in vimc_debayer_s_stream()
343 vdebayer->hw.sink_pix_map = in vimc_debayer_s_stream()
344 vimc_debayer_pix_map_by_code(sink_fmt->code); in vimc_debayer_s_stream()
346 vdebayer->hw.size.width = sink_fmt->width; in vimc_debayer_s_stream()
347 vdebayer->hw.size.height = sink_fmt->height; in vimc_debayer_s_stream()
349 vdebayer->hw.src_code = src_fmt->code; in vimc_debayer_s_stream()
357 vdebayer->src_frame = vmalloc(frame_size); in vimc_debayer_s_stream()
358 if (!vdebayer->src_frame) in vimc_debayer_s_stream()
359 return -ENOMEM; in vimc_debayer_s_stream()
361 if (!vdebayer->src_frame) in vimc_debayer_s_stream()
364 vfree(vdebayer->src_frame); in vimc_debayer_s_stream()
365 vdebayer->src_frame = NULL; in vimc_debayer_s_stream()
416 * Calculate how many we need to subtract to get to the pixel in in vimc_debayer_calc_rgb_sink()
418 * pixel as the center) in vimc_debayer_calc_rgb_sink()
420 seek = vdebayer->hw.mean_win_size / 2; in vimc_debayer_calc_rgb_sink()
424 dev_dbg(vdebayer->ved.dev, in vimc_debayer_calc_rgb_sink()
425 "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n", in vimc_debayer_calc_rgb_sink()
426 vdebayer->sd.name, lin, col, vdebayer->hw.size.height, seek); in vimc_debayer_calc_rgb_sink()
430 * with zero if the pixel is outside the frame and don't pass in vimc_debayer_calc_rgb_sink()
431 * the height when the pixel is in the bottom border of the in vimc_debayer_calc_rgb_sink()
434 for (wlin = seek > lin ? 0 : lin - seek; in vimc_debayer_calc_rgb_sink()
435 wlin < lin + seek + 1 && wlin < vdebayer->hw.size.height; in vimc_debayer_calc_rgb_sink()
440 * with zero if the pixel is outside the frame and don't pass in vimc_debayer_calc_rgb_sink()
441 * the width when the pixel is in the right border of the in vimc_debayer_calc_rgb_sink()
444 for (wcol = seek > col ? 0 : col - seek; in vimc_debayer_calc_rgb_sink()
445 wcol < col + seek + 1 && wcol < vdebayer->hw.size.width; in vimc_debayer_calc_rgb_sink()
450 /* Check which color this pixel is */ in vimc_debayer_calc_rgb_sink()
451 color = vdebayer->hw.sink_pix_map->order[wlin % 2][wcol % 2]; in vimc_debayer_calc_rgb_sink()
454 vdebayer->hw.size.width, in vimc_debayer_calc_rgb_sink()
455 vdebayer->hw.sink_bpp); in vimc_debayer_calc_rgb_sink()
457 dev_dbg(vdebayer->ved.dev, in vimc_debayer_calc_rgb_sink()
459 vdebayer->sd.name, index, wlin, wcol, color); in vimc_debayer_calc_rgb_sink()
464 vdebayer->hw.sink_bpp); in vimc_debayer_calc_rgb_sink()
469 dev_dbg(vdebayer->ved.dev, "deb: %s: RGB CALC: val %d, n %d\n", in vimc_debayer_calc_rgb_sink()
470 vdebayer->sd.name, rgb[color], n_rgb[color]); in vimc_debayer_calc_rgb_sink()
476 dev_dbg(vdebayer->ved.dev, in vimc_debayer_calc_rgb_sink()
478 vdebayer->sd.name, lin, col, i, rgb[i], n_rgb[i]); in vimc_debayer_calc_rgb_sink()
483 dev_dbg(vdebayer->ved.dev, in vimc_debayer_calc_rgb_sink()
485 vdebayer->sd.name, lin, col, i, rgb[i]); in vimc_debayer_calc_rgb_sink()
499 if (!vdebayer->src_frame) in vimc_debayer_process_frame()
500 return ERR_PTR(-EINVAL); in vimc_debayer_process_frame()
502 for (i = 0; i < vdebayer->hw.size.height; i++) in vimc_debayer_process_frame()
503 for (j = 0; j < vdebayer->hw.size.width; j++) { in vimc_debayer_process_frame()
505 vdebayer->set_rgb_src(vdebayer, i, j, rgb); in vimc_debayer_process_frame()
508 return vdebayer->src_frame; in vimc_debayer_process_frame()
514 container_of(ctrl->handler, struct vimc_debayer_device, hdl); in vimc_debayer_s_ctrl()
516 switch (ctrl->id) { in vimc_debayer_s_ctrl()
518 vdebayer->hw.mean_win_size = ctrl->val; in vimc_debayer_s_ctrl()
521 return -EINVAL; in vimc_debayer_s_ctrl()
535 v4l2_ctrl_handler_free(&vdebayer->hdl); in vimc_debayer_release()
536 v4l2_subdev_cleanup(&vdebayer->sd); in vimc_debayer_release()
537 media_entity_cleanup(vdebayer->ved.ent); in vimc_debayer_release()
562 struct v4l2_device *v4l2_dev = &vimc->v4l2_dev; in vimc_debayer_add()
569 return ERR_PTR(-ENOMEM); in vimc_debayer_add()
572 v4l2_ctrl_handler_init(&vdebayer->hdl, 2); in vimc_debayer_add()
573 v4l2_ctrl_new_custom(&vdebayer->hdl, &vimc_debayer_ctrl_class, NULL); in vimc_debayer_add()
574 v4l2_ctrl_new_custom(&vdebayer->hdl, &vimc_debayer_ctrl_mean_win_size, NULL); in vimc_debayer_add()
575 vdebayer->sd.ctrl_handler = &vdebayer->hdl; in vimc_debayer_add()
576 if (vdebayer->hdl.error) { in vimc_debayer_add()
577 ret = vdebayer->hdl.error; in vimc_debayer_add()
582 vdebayer->pads[0].flags = MEDIA_PAD_FL_SINK; in vimc_debayer_add()
583 vdebayer->pads[1].flags = MEDIA_PAD_FL_SOURCE; in vimc_debayer_add()
585 ret = vimc_ent_sd_register(&vdebayer->ved, &vdebayer->sd, v4l2_dev, in vimc_debayer_add()
588 vdebayer->pads, &vimc_debayer_internal_ops, in vimc_debayer_add()
593 vdebayer->ved.process_frame = vimc_debayer_process_frame; in vimc_debayer_add()
594 vdebayer->ved.dev = vimc->mdev.dev; in vimc_debayer_add()
595 vdebayer->hw.mean_win_size = vimc_debayer_ctrl_mean_win_size.def; in vimc_debayer_add()
597 vdebayer->set_rgb_src = vimc_debayer_process_rgb_frame; in vimc_debayer_add()
599 return &vdebayer->ved; in vimc_debayer_add()
602 v4l2_ctrl_handler_free(&vdebayer->hdl); in vimc_debayer_add()