Commit 76df2e6c authored by Arthur Moraes do Lago's avatar Arthur Moraes do Lago Committed by Mauro Carvalho Chehab
Browse files

media: vimc: Implement debayer control for mean window size



Add mean window size parameter for debayer filter as a control in
vimc-debayer.

vimc-debayer was patched to allow changing mean window parameter
of the filter without needing to reload the driver. The parameter
can now be set using a v4l2-ctl control(mean_window_size).

Co-developed-by: default avatarLaís Pessine do Carmo <laispc19@gmail.com>
Signed-off-by: default avatarLaís Pessine do Carmo <laispc19@gmail.com>
Signed-off-by: default avatarArthur Moraes do Lago <arthurmoraeslago@gmail.com>
Acked-by: default avatarHelen Koike <helen.koike@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent b1f8e931
Loading
Loading
Loading
Loading
+1 −9
Original line number Diff line number Diff line
@@ -80,9 +80,7 @@ vimc-capture:
Module options
--------------

Vimc has a few module parameters to configure the driver.

        param=value
Vimc has a module parameter to configure the driver.

* ``sca_mult=<unsigned int>``

@@ -91,12 +89,6 @@ Vimc has a few module parameters to configure the driver.
        original one. Currently, only supports scaling up (the default value
        is 3).

* ``deb_mean_win_size=<unsigned int>``

        Window size to calculate the mean. Note: the window size needs to be an
        odd number, as the main pixel stays in the center of the window,
        otherwise the next odd number is considered (the default value is 3).

Source code documentation
-------------------------

+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define VIMC_CID_VIMC_BASE		(0x00f00000 | 0xf000)
#define VIMC_CID_VIMC_CLASS		(0x00f00000 | 1)
#define VIMC_CID_TEST_PATTERN		(VIMC_CID_VIMC_BASE + 0)
#define VIMC_CID_MEAN_WIN_SIZE		(VIMC_CID_VIMC_BASE + 1)

#define VIMC_FRAME_MAX_WIDTH 4096
#define VIMC_FRAME_MAX_HEIGHT 2160
+69 −12
Original line number Diff line number Diff line
@@ -9,17 +9,12 @@
#include <linux/platform_device.h>
#include <linux/vmalloc.h>
#include <linux/v4l2-mediabus.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-subdev.h>

#include "vimc-common.h"

static unsigned int deb_mean_win_size = 3;
module_param(deb_mean_win_size, uint, 0000);
MODULE_PARM_DESC(deb_mean_win_size, " the window size to calculate the mean.\n"
	"NOTE: the window size needs to be an odd number, as the main pixel "
	"stays in the center of the window, otherwise the next odd number "
	"is considered");

enum vimc_deb_rgb_colors {
	VIMC_DEB_RED = 0,
	VIMC_DEB_GREEN = 1,
@@ -43,6 +38,8 @@ struct vimc_deb_device {
	u8 *src_frame;
	const struct vimc_deb_pix_map *sink_pix_map;
	unsigned int sink_bpp;
	unsigned int mean_win_size;
	struct v4l2_ctrl_handler hdl;
	struct media_pad pads[2];
};

@@ -344,11 +341,18 @@ static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
	return 0;
}

static const struct v4l2_subdev_core_ops vimc_deb_core_ops = {
	.log_status = v4l2_ctrl_subdev_log_status,
	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};

static const struct v4l2_subdev_video_ops vimc_deb_video_ops = {
	.s_stream = vimc_deb_s_stream,
};

static const struct v4l2_subdev_ops vimc_deb_ops = {
	.core = &vimc_deb_core_ops,
	.pad = &vimc_deb_pad_ops,
	.video = &vimc_deb_video_ops,
};
@@ -382,7 +386,7 @@ static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb,
	 * the top left corner of the mean window (considering the current
	 * pixel as the center)
	 */
	seek = deb_mean_win_size / 2;
	seek = vdeb->mean_win_size / 2;

	/* Sum the values of the colors in the mean window */

@@ -469,14 +473,33 @@ static void *vimc_deb_process_frame(struct vimc_ent_device *ved,
		}

	return vdeb->src_frame;
}

static int vimc_deb_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct vimc_deb_device *vdeb =
		container_of(ctrl->handler, struct vimc_deb_device, hdl);

	switch (ctrl->id) {
	case VIMC_CID_MEAN_WIN_SIZE:
		vdeb->mean_win_size = ctrl->val;
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

static const struct v4l2_ctrl_ops vimc_deb_ctrl_ops = {
	.s_ctrl = vimc_deb_s_ctrl,
};

static void vimc_deb_release(struct v4l2_subdev *sd)
{
	struct vimc_deb_device *vdeb =
				container_of(sd, struct vimc_deb_device, sd);

	v4l2_ctrl_handler_free(&vdeb->hdl);
	media_entity_cleanup(vdeb->ved.ent);
	kfree(vdeb);
}
@@ -493,6 +516,24 @@ void vimc_deb_rm(struct vimc_device *vimc, struct vimc_ent_device *ved)
	v4l2_device_unregister_subdev(&vdeb->sd);
}

static const struct v4l2_ctrl_config vimc_deb_ctrl_class = {
	.flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
	.id = VIMC_CID_VIMC_CLASS,
	.name = "VIMC Controls",
	.type = V4L2_CTRL_TYPE_CTRL_CLASS,
};

static const struct v4l2_ctrl_config vimc_deb_ctrl_mean_win_size = {
	.ops = &vimc_deb_ctrl_ops,
	.id = VIMC_CID_MEAN_WIN_SIZE,
	.name = "Debayer Mean Window Size",
	.type = V4L2_CTRL_TYPE_INTEGER,
	.min = 1,
	.max = 25,
	.step = 2,
	.def = 3,
};

struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
				     const char *vcfg_name)
{
@@ -505,6 +546,16 @@ struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
	if (!vdeb)
		return NULL;

	/* Create controls: */
	v4l2_ctrl_handler_init(&vdeb->hdl, 2);
	v4l2_ctrl_new_custom(&vdeb->hdl, &vimc_deb_ctrl_class, NULL);
	v4l2_ctrl_new_custom(&vdeb->hdl, &vimc_deb_ctrl_mean_win_size, NULL);
	vdeb->sd.ctrl_handler = &vdeb->hdl;
	if (vdeb->hdl.error) {
		ret = vdeb->hdl.error;
		goto err_free_vdeb;
	}

	/* Initialize ved and sd */
	vdeb->pads[0].flags = MEDIA_PAD_FL_SINK;
	vdeb->pads[1].flags = MEDIA_PAD_FL_SOURCE;
@@ -514,13 +565,12 @@ struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
				   MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2,
				   vdeb->pads,
				   &vimc_deb_int_ops, &vimc_deb_ops);
	if (ret) {
		kfree(vdeb);
		return NULL;
	}
	if (ret)
		goto err_free_hdl;

	vdeb->ved.process_frame = vimc_deb_process_frame;
	vdeb->ved.dev = &vimc->pdev.dev;
	vdeb->mean_win_size = vimc_deb_ctrl_mean_win_size.def;

	/* Initialize the frame format */
	vdeb->sink_fmt = sink_fmt_default;
@@ -534,4 +584,11 @@ struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
	vdeb->set_rgb_src = vimc_deb_set_rgb_mbus_fmt_rgb888_1x24;

	return &vdeb->ved;

err_free_hdl:
	v4l2_ctrl_handler_free(&vdeb->hdl);
err_free_vdeb:
	kfree(vdeb);

	return NULL;
}