media: ov7670: add V4L2_CID_TEST_PATTERN control

The ov7670 has the test pattern generator features.  This makes use of
it through V4L2_CID_TEST_PATTERN control.

Cc: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Akinobu Mita 2017-11-24 09:40:45 -05:00 committed by Mauro Carvalho Chehab
parent 344aa836e8
commit b48d908d2b
1 changed files with 45 additions and 1 deletions

View File

@ -163,6 +163,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define DBLV_X6 0x10 /* clock x6 */
#define DBLV_X8 0x11 /* clock x8 */
#define REG_SCALING_XSC 0x70 /* Test pattern and horizontal scale factor */
#define TEST_PATTTERN_0 0x80
#define REG_SCALING_YSC 0x71 /* Test pattern and vertical scale factor */
#define TEST_PATTTERN_1 0x80
#define REG_REG76 0x76 /* OV's name */
#define R76_BLKPCOR 0x80 /* Black pixel correction enable */
#define R76_WHTPCOR 0x40 /* White pixel correction enable */
@ -292,7 +297,8 @@ static struct regval_list ov7670_default_regs[] = {
{ REG_COM3, 0 }, { REG_COM14, 0 },
/* Mystery scaling numbers */
{ 0x70, 0x3a }, { 0x71, 0x35 },
{ REG_SCALING_XSC, 0x3a },
{ REG_SCALING_YSC, 0x35 },
{ 0x72, 0x11 }, { 0x73, 0xf0 },
{ 0xa2, 0x02 }, { REG_COM10, 0x0 },
@ -568,6 +574,19 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
return ov7670_write_i2c(sd, reg, value);
}
static int ov7670_update_bits(struct v4l2_subdev *sd, unsigned char reg,
unsigned char mask, unsigned char value)
{
unsigned char orig;
int ret;
ret = ov7670_read(sd, reg, &orig);
if (ret)
return ret;
return ov7670_write(sd, reg, (orig & ~mask) | (value & mask));
}
/*
* Write a list of register settings; ff/ff stops the process.
*/
@ -1470,6 +1489,25 @@ static int ov7670_s_autoexp(struct v4l2_subdev *sd,
return ret;
}
static const char * const ov7670_test_pattern_menu[] = {
"No test output",
"Shifting \"1\"",
"8-bar color bar",
"Fade to gray color bar",
};
static int ov7670_s_test_pattern(struct v4l2_subdev *sd, int value)
{
int ret;
ret = ov7670_update_bits(sd, REG_SCALING_XSC, TEST_PATTTERN_0,
value & BIT(0) ? TEST_PATTTERN_0 : 0);
if (ret)
return ret;
return ov7670_update_bits(sd, REG_SCALING_YSC, TEST_PATTTERN_1,
value & BIT(1) ? TEST_PATTTERN_1 : 0);
}
static int ov7670_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
@ -1516,6 +1554,8 @@ static int ov7670_s_ctrl(struct v4l2_ctrl *ctrl)
return ov7670_s_exp(sd, info->exposure->val);
}
return ov7670_s_autoexp(sd, ctrl->val);
case V4L2_CID_TEST_PATTERN:
return ov7670_s_test_pattern(sd, ctrl->val);
}
return -EINVAL;
}
@ -1770,6 +1810,10 @@ static int ov7670_probe(struct i2c_client *client,
info->auto_exposure = v4l2_ctrl_new_std_menu(&info->hdl, &ov7670_ctrl_ops,
V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0,
V4L2_EXPOSURE_AUTO);
v4l2_ctrl_new_std_menu_items(&info->hdl, &ov7670_ctrl_ops,
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(ov7670_test_pattern_menu) - 1, 0, 0,
ov7670_test_pattern_menu);
sd->ctrl_handler = &info->hdl;
if (info->hdl.error) {
ret = info->hdl.error;