diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/ov772x.c | 88 |
1 files changed, 84 insertions, 4 deletions
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 6b18da7c3c0..880e51f0e9f 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -217,10 +217,11 @@ #define OCAP_4x 0x03 /* 4x */ /* COM3 */ -#define SWAP_MASK 0x38 +#define SWAP_MASK (SWAP_RGB | SWAP_YUV | SWAP_ML) +#define IMG_MASK (VFLIP_IMG | HFLIP_IMG) -#define VFIMG_ON_OFF 0x80 /* Vertical flip image ON/OFF selection */ -#define HMIMG_ON_OFF 0x40 /* Horizontal mirror image ON/OFF selection */ +#define VFLIP_IMG 0x80 /* Vertical flip image ON/OFF selection */ +#define HFLIP_IMG 0x40 /* Horizontal mirror image ON/OFF selection */ #define SWAP_RGB 0x20 /* Swap B/R output sequence in RGB mode */ #define SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV mode */ #define SWAP_ML 0x08 /* Swap output MSB/LSB */ @@ -395,6 +396,8 @@ struct ov772x_priv { const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; + unsigned int flag_vflip:1; + unsigned int flag_hflip:1; }; #define ENDMARKER { 0xff, 0xff } @@ -540,6 +543,27 @@ static const struct ov772x_win_size ov772x_win_qvga = { .regs = ov772x_qvga_regs, }; +static const struct v4l2_queryctrl ov772x_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, +}; + /* * general function @@ -650,6 +674,49 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } +static int ov772x_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + ctrl->value = priv->flag_vflip; + break; + case V4L2_CID_HFLIP: + ctrl->value = priv->flag_hflip; + break; + } + return 0; +} + +static int ov772x_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + int ret = 0; + u8 val; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + val = ctrl->value ? VFLIP_IMG : 0x00; + priv->flag_vflip = ctrl->value; + if (priv->info->flags & OV772X_FLAG_VFLIP) + val ^= VFLIP_IMG; + ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); + break; + case V4L2_CID_HFLIP: + val = ctrl->value ? HFLIP_IMG : 0x00; + priv->flag_hflip = ctrl->value; + if (priv->info->flags & OV772X_FLAG_HFLIP) + val ^= HFLIP_IMG; + ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); + break; + } + + return ret; +} + static int ov772x_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { @@ -768,8 +835,17 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, * set COM3 */ val = priv->fmt->com3; + if (priv->info->flags & OV772X_FLAG_VFLIP) + val |= VFLIP_IMG; + if (priv->info->flags & OV772X_FLAG_HFLIP) + val |= HFLIP_IMG; + if (priv->flag_vflip) + val ^= VFLIP_IMG; + if (priv->flag_hflip) + val ^= HFLIP_IMG; + ret = ov772x_mask_set(priv->client, - COM3, SWAP_MASK, val); + COM3, SWAP_MASK | IMG_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -887,6 +963,10 @@ static struct soc_camera_ops ov772x_ops = { .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, + .controls = ov772x_controls, + .num_controls = ARRAY_SIZE(ov772x_controls), + .get_control = ov772x_get_control, + .set_control = ov772x_set_control, .get_chip_id = ov772x_get_chip_id, #ifdef CONFIG_VIDEO_ADV_DEBUG .get_register = ov772x_get_register, |