media: ov8856: add vflip/hflip control support
Add V4L2 controls: horizontal/vertical flip, keep SGRBG10 Bayer order output (via change v/hflip) Signed-off-by: Shawn Tu <shawnx.tu@intel.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
c492ec9ae9
commit
c19b93a69c
@ -80,6 +80,25 @@
|
||||
#define NUM_MODE_REGS 187
|
||||
#define NUM_MODE_REGS_2 200
|
||||
|
||||
/* Flip Mirror Controls from sensor */
|
||||
#define OV8856_REG_FORMAT1 0x3820
|
||||
#define OV8856_REG_FORMAT2 0x3821
|
||||
#define OV8856_REG_FORMAT1_OP_1 BIT(1)
|
||||
#define OV8856_REG_FORMAT1_OP_2 BIT(2)
|
||||
#define OV8856_REG_FORMAT1_OP_3 BIT(6)
|
||||
#define OV8856_REG_FORMAT2_OP_1 BIT(1)
|
||||
#define OV8856_REG_FORMAT2_OP_2 BIT(2)
|
||||
#define OV8856_REG_FORMAT2_OP_3 BIT(6)
|
||||
#define OV8856_REG_FLIP_OPT_1 0x376b
|
||||
#define OV8856_REG_FLIP_OPT_2 0x5001
|
||||
#define OV8856_REG_FLIP_OPT_3 0x502e
|
||||
#define OV8856_REG_MIRROR_OPT_1 0x5004
|
||||
#define OV8856_REG_FLIP_OP_0 BIT(0)
|
||||
#define OV8856_REG_FLIP_OP_1 BIT(1)
|
||||
#define OV8856_REG_FLIP_OP_2 BIT(2)
|
||||
#define OV8856_REG_MIRROR_OP_1 BIT(1)
|
||||
#define OV8856_REG_MIRROR_OP_2 BIT(2)
|
||||
|
||||
#define to_ov8856(_sd) container_of(_sd, struct ov8856, sd)
|
||||
|
||||
static const char * const ov8856_supply_names[] = {
|
||||
@ -1653,6 +1672,93 @@ static int ov8856_test_pattern(struct ov8856 *ov8856, u32 pattern)
|
||||
OV8856_REG_VALUE_08BIT, pattern);
|
||||
}
|
||||
|
||||
static int ov8856_set_ctrl_hflip(struct ov8856 *ov8856, u32 ctrl_val)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
ret = ov8856_read_reg(ov8856, OV8856_REG_MIRROR_OPT_1,
|
||||
OV8856_REG_VALUE_08BIT, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov8856_write_reg(ov8856, OV8856_REG_MIRROR_OPT_1,
|
||||
OV8856_REG_VALUE_08BIT,
|
||||
ctrl_val ? val & ~OV8856_REG_MIRROR_OP_2 :
|
||||
val | OV8856_REG_MIRROR_OP_2);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov8856_read_reg(ov8856, OV8856_REG_FORMAT2,
|
||||
OV8856_REG_VALUE_08BIT, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ov8856_write_reg(ov8856, OV8856_REG_FORMAT2,
|
||||
OV8856_REG_VALUE_08BIT,
|
||||
ctrl_val ? val & ~OV8856_REG_FORMAT2_OP_1 &
|
||||
~OV8856_REG_FORMAT2_OP_2 &
|
||||
~OV8856_REG_FORMAT2_OP_3 :
|
||||
val | OV8856_REG_FORMAT2_OP_1 |
|
||||
OV8856_REG_FORMAT2_OP_2 |
|
||||
OV8856_REG_FORMAT2_OP_3);
|
||||
}
|
||||
|
||||
static int ov8856_set_ctrl_vflip(struct ov8856 *ov8856, u8 ctrl_val)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
ret = ov8856_read_reg(ov8856, OV8856_REG_FLIP_OPT_1,
|
||||
OV8856_REG_VALUE_08BIT, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov8856_write_reg(ov8856, OV8856_REG_FLIP_OPT_1,
|
||||
OV8856_REG_VALUE_08BIT,
|
||||
ctrl_val ? val | OV8856_REG_FLIP_OP_1 |
|
||||
OV8856_REG_FLIP_OP_2 :
|
||||
val & ~OV8856_REG_FLIP_OP_1 &
|
||||
~OV8856_REG_FLIP_OP_2);
|
||||
|
||||
ret = ov8856_read_reg(ov8856, OV8856_REG_FLIP_OPT_2,
|
||||
OV8856_REG_VALUE_08BIT, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov8856_write_reg(ov8856, OV8856_REG_FLIP_OPT_2,
|
||||
OV8856_REG_VALUE_08BIT,
|
||||
ctrl_val ? val | OV8856_REG_FLIP_OP_2 :
|
||||
val & ~OV8856_REG_FLIP_OP_2);
|
||||
|
||||
ret = ov8856_read_reg(ov8856, OV8856_REG_FLIP_OPT_3,
|
||||
OV8856_REG_VALUE_08BIT, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov8856_write_reg(ov8856, OV8856_REG_FLIP_OPT_3,
|
||||
OV8856_REG_VALUE_08BIT,
|
||||
ctrl_val ? val & ~OV8856_REG_FLIP_OP_0 &
|
||||
~OV8856_REG_FLIP_OP_1 :
|
||||
val | OV8856_REG_FLIP_OP_0 |
|
||||
OV8856_REG_FLIP_OP_1);
|
||||
|
||||
ret = ov8856_read_reg(ov8856, OV8856_REG_FORMAT1,
|
||||
OV8856_REG_VALUE_08BIT, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ov8856_write_reg(ov8856, OV8856_REG_FORMAT1,
|
||||
OV8856_REG_VALUE_08BIT,
|
||||
ctrl_val ? val | OV8856_REG_FORMAT1_OP_1 |
|
||||
OV8856_REG_FORMAT1_OP_3 |
|
||||
OV8856_REG_FORMAT1_OP_2 :
|
||||
val & ~OV8856_REG_FORMAT1_OP_1 &
|
||||
~OV8856_REG_FORMAT1_OP_3 &
|
||||
~OV8856_REG_FORMAT1_OP_2);
|
||||
}
|
||||
|
||||
static int ov8856_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct ov8856 *ov8856 = container_of(ctrl->handler,
|
||||
@ -1702,6 +1808,14 @@ static int ov8856_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
ret = ov8856_test_pattern(ov8856, ctrl->val);
|
||||
break;
|
||||
|
||||
case V4L2_CID_HFLIP:
|
||||
ret = ov8856_set_ctrl_hflip(ov8856, ctrl->val);
|
||||
break;
|
||||
|
||||
case V4L2_CID_VFLIP:
|
||||
ret = ov8856_set_ctrl_vflip(ov8856, ctrl->val);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
@ -1778,6 +1892,10 @@ static int ov8856_init_controls(struct ov8856 *ov8856)
|
||||
V4L2_CID_TEST_PATTERN,
|
||||
ARRAY_SIZE(ov8856_test_pattern_menu) - 1,
|
||||
0, 0, ov8856_test_pattern_menu);
|
||||
v4l2_ctrl_new_std(ctrl_hdlr, &ov8856_ctrl_ops,
|
||||
V4L2_CID_HFLIP, 0, 1, 1, 0);
|
||||
v4l2_ctrl_new_std(ctrl_hdlr, &ov8856_ctrl_ops,
|
||||
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
||||
if (ctrl_hdlr->error)
|
||||
return ctrl_hdlr->error;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user