media: vimc: add test_pattern and h/vflip controls to the sensor

Add support for the test_pattern control and the h/vflip controls.

This makes it possible to switch to more interesting test patterns and to
test control handling in v4l-subdevs.

There are more tpg-related controls that can be added, but this is a good
start.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
[hans.verkuil@cisco.com: fix small whitespace checkpatch warning]
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Hans Verkuil 2017-11-06 05:20:01 -05:00 committed by Mauro Carvalho Chehab
parent e2a067048d
commit 52cf1d964e
2 changed files with 67 additions and 1 deletions

View file

@ -22,6 +22,11 @@
#include <media/media-device.h>
#include <media/v4l2-device.h>
/* VIMC-specific controls */
#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_FRAME_MAX_WIDTH 4096
#define VIMC_FRAME_MAX_HEIGHT 2160
#define VIMC_FRAME_MIN_WIDTH 16

View file

@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/v4l2-mediabus.h>
#include <linux/vmalloc.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-tpg.h>
@ -38,6 +39,7 @@ struct vimc_sen_device {
u8 *frame;
/* The active format */
struct v4l2_mbus_framefmt mbus_format;
struct v4l2_ctrl_handler hdl;
};
static const struct v4l2_mbus_framefmt fmt_default = {
@ -291,6 +293,31 @@ static const struct v4l2_subdev_ops vimc_sen_ops = {
.video = &vimc_sen_video_ops,
};
static int vimc_sen_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct vimc_sen_device *vsen =
container_of(ctrl->handler, struct vimc_sen_device, hdl);
switch (ctrl->id) {
case VIMC_CID_TEST_PATTERN:
tpg_s_pattern(&vsen->tpg, ctrl->val);
break;
case V4L2_CID_HFLIP:
tpg_s_hflip(&vsen->tpg, ctrl->val);
break;
case V4L2_CID_VFLIP:
tpg_s_vflip(&vsen->tpg, ctrl->val);
break;
default:
return -EINVAL;
}
return 0;
}
static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = {
.s_ctrl = vimc_sen_s_ctrl,
};
static void vimc_sen_comp_unbind(struct device *comp, struct device *master,
void *master_data)
{
@ -299,10 +326,28 @@ static void vimc_sen_comp_unbind(struct device *comp, struct device *master,
container_of(ved, struct vimc_sen_device, ved);
vimc_ent_sd_unregister(ved, &vsen->sd);
v4l2_ctrl_handler_free(&vsen->hdl);
tpg_free(&vsen->tpg);
kfree(vsen);
}
/* Image Processing Controls */
static const struct v4l2_ctrl_config vimc_sen_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_sen_ctrl_test_pattern = {
.ops = &vimc_sen_ctrl_ops,
.id = VIMC_CID_TEST_PATTERN,
.name = "Test Pattern",
.type = V4L2_CTRL_TYPE_MENU,
.max = TPG_PAT_NOISE,
.qmenu = tpg_pattern_strings,
};
static int vimc_sen_comp_bind(struct device *comp, struct device *master,
void *master_data)
{
@ -316,6 +361,20 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master,
if (!vsen)
return -ENOMEM;
v4l2_ctrl_handler_init(&vsen->hdl, 4);
v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_class, NULL);
v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_test_pattern, NULL);
v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
vsen->sd.ctrl_handler = &vsen->hdl;
if (vsen->hdl.error) {
ret = vsen->hdl.error;
goto err_free_vsen;
}
/* Initialize ved and sd */
ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev,
pdata->entity_name,
@ -323,7 +382,7 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master,
(const unsigned long[1]) {MEDIA_PAD_FL_SOURCE},
&vimc_sen_ops);
if (ret)
goto err_free_vsen;
goto err_free_hdl;
dev_set_drvdata(comp, &vsen->ved);
vsen->dev = comp;
@ -342,6 +401,8 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master,
err_unregister_ent_sd:
vimc_ent_sd_unregister(&vsen->ved, &vsen->sd);
err_free_hdl:
v4l2_ctrl_handler_free(&vsen->hdl);
err_free_vsen:
kfree(vsen);