From 6c7ebe661716fc23c52cd800a173e4675b10202a Mon Sep 17 00:00:00 2001 From: Mathias Anhalt Date: Wed, 3 Feb 2021 20:34:09 +0100 Subject: [PATCH] Added hflip and vflip controls to ov9281 Signed-off-by: Mathias Anhalt --- drivers/media/i2c/ov9281.c | 58 +++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) --- a/drivers/media/i2c/ov9281.c +++ b/drivers/media/i2c/ov9281.c @@ -40,6 +40,10 @@ #define CHIP_ID 0x9281 #define OV9281_REG_CHIP_ID 0x300a +#define OV9281_REG_TIMING_FORMAT_1 0x3820 +#define OV9281_REG_TIMING_FORMAT_2 0x3821 +#define OV9281_FLIP_BIT BIT(2) + #define OV9281_REG_CTRL_MODE 0x0100 #define OV9281_MODE_SW_STANDBY 0x0 #define OV9281_MODE_STREAMING BIT(0) @@ -123,6 +127,8 @@ struct ov9281 { struct v4l2_ctrl *digi_gain; struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *vflip; struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *test_pattern; struct mutex mutex; @@ -615,6 +621,42 @@ static int ov9281_enable_test_pattern(st OV9281_REG_VALUE_08BIT, val); } +static int ov9281_set_ctrl_hflip(struct ov9281 *ov9281, int value) +{ + u32 current_val; + int ret = ov9281_read_reg(ov9281->client, OV9281_REG_TIMING_FORMAT_2, + OV9281_REG_VALUE_08BIT, ¤t_val); + if (!ret) { + if (value) + current_val |= OV9281_FLIP_BIT; + else + current_val &= ~OV9281_FLIP_BIT; + return ov9281_write_reg(ov9281->client, + OV9281_REG_TIMING_FORMAT_2, + OV9281_REG_VALUE_08BIT, + current_val); + } + return ret; +} + +static int ov9281_set_ctrl_vflip(struct ov9281 *ov9281, int value) +{ + u32 current_val; + int ret = ov9281_read_reg(ov9281->client, OV9281_REG_TIMING_FORMAT_1, + OV9281_REG_VALUE_08BIT, ¤t_val); + if (!ret) { + if (value) + current_val |= OV9281_FLIP_BIT; + else + current_val &= ~OV9281_FLIP_BIT; + return ov9281_write_reg(ov9281->client, + OV9281_REG_TIMING_FORMAT_1, + OV9281_REG_VALUE_08BIT, + current_val); + } + return ret; +} + static const struct v4l2_rect * __ov9281_get_pad_crop(struct ov9281 *ov9281, struct v4l2_subdev_pad_config *cfg, unsigned int pad, enum v4l2_subdev_format_whence which) @@ -933,6 +975,12 @@ static int ov9281_set_ctrl(struct v4l2_c return 0; switch (ctrl->id) { + case V4L2_CID_HFLIP: + ret = ov9281_set_ctrl_hflip(ov9281, ctrl->val); + break; + case V4L2_CID_VFLIP: + ret = ov9281_set_ctrl_vflip(ov9281, ctrl->val); + break; case V4L2_CID_EXPOSURE: /* 4 least significant bits of expsoure are fractional part */ ret = ov9281_write_reg(ov9281->client, OV9281_REG_EXPOSURE, @@ -981,7 +1029,7 @@ static int ov9281_initialize_controls(st handler = &ov9281->ctrl_handler; mode = ov9281->cur_mode; - ret = v4l2_ctrl_handler_init(handler, 8); + ret = v4l2_ctrl_handler_init(handler, 9); if (ret) return ret; handler->lock = &ov9281->mutex; @@ -1022,6 +1070,14 @@ static int ov9281_initialize_controls(st OV9281_GAIN_STEP, OV9281_GAIN_DEFAULT); + ov9281->vflip = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops, + V4L2_CID_VFLIP, + 0, 1, 1, 0); + + ov9281->hflip = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops, + V4L2_CID_HFLIP, + 0, 1, 1, 0); + ov9281->test_pattern = v4l2_ctrl_new_std_menu_items(handler, &ov9281_ctrl_ops, V4L2_CID_TEST_PATTERN,