diff mbox

[v2,2/2] ov772x: Add image flip support

Message ID u63kbpxm9.wl%morimoto.kuninori@renesas.com (mailing list archive)
State Accepted
Headers show

Commit Message

Kuninori Morimoto Jan. 19, 2009, 6:32 a.m. UTC
o ov772x_camera_info :: flags supports default image flip.
o V4L2_CID_VFLIP/HFLIP supports image flip on user side.
Thank Magnus for advice.

Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
---
 drivers/media/video/ov772x.c |   97 ++++++++++++++++++++++++++++++++++++++++--
 include/media/ov772x.h       |    5 ++
 2 files changed, 98 insertions(+), 4 deletions(-)

Comments

Guennadi Liakhovetski Jan. 19, 2009, 7:54 a.m. UTC | #1
On Mon, 19 Jan 2009, Kuninori Morimoto wrote:

> o ov772x_camera_info :: flags supports default image flip.
> o V4L2_CID_VFLIP/HFLIP supports image flip on user side.
> Thank Magnus for advice.
> 
> Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
> ---
>  drivers/media/video/ov772x.c |   97 ++++++++++++++++++++++++++++++++++++++++--
>  include/media/ov772x.h       |    5 ++
>  2 files changed, 98 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
> index 3341857..ca0cf3c 100644
> --- a/drivers/media/video/ov772x.c
> +++ b/drivers/media/video/ov772x.c
> @@ -218,9 +218,10 @@
>  
>  /* COM3 */
>  #define SWAP_MASK       0x38
> +#define IMG_MASK        0xC0
>  
> -#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 */

Please, put SWAP_MASK and IMG_MASK below single bit defines and define 
them as

#define SWAP_MASK	(SWAP_RGB | SWAP_YUV | SWAP_ML)
#define IMG_MASK	(VFLIP_IMG | HFLIP_IMG)

> @@ -540,6 +541,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 +672,60 @@ 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);
> +	s32 val;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_VFLIP:
> +		val = i2c_smbus_read_byte_data(priv->client, COM3);
> +		if (val < 0)
> +			return val;
> +		if (priv->info->flags & OV772X_FLAG_VFLIP)
> +			val ^= VFLIP_IMG;
> +		val &= VFLIP_IMG;
> +		ctrl->value = !!val;
> +		break;
> +	case V4L2_CID_HFLIP:
> +		val = i2c_smbus_read_byte_data(priv->client, COM3);
> +		if (val < 0)
> +			return val;
> +		if (priv->info->flags & OV772X_FLAG_HFLIP)
> +			val ^= HFLIP_IMG;
> +		val &= HFLIP_IMG;
> +		ctrl->value = !!val;
> +		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;

Superfluous parenthesis

> +		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;

ditto

> +		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)
>  {
> @@ -720,7 +796,7 @@ static int ov772x_set_fmt(struct soc_camera_device *icd,
>  {
>  	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
>  	int ret = -EINVAL;
> -	u8  val;
> +	u8  val, mask;
>  	int i;
>  
>  	/*
> @@ -768,8 +844,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;
> +
> +	mask = SWAP_MASK;
> +	if (IMG_MASK & val)
> +		mask |= IMG_MASK;
> +
>  	ret = ov772x_mask_set(priv->client,
> -			      COM3, SWAP_MASK, val);
> +			      COM3, mask, val);

Do I understand it right, that this throws away any flip control settings 
performed before S_FMT? You probably want to set priv->fmt->com3 in your 
set_control and XOR instead of an OR here as well. Or was this 
intentional?

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kuninori Morimoto Jan. 19, 2009, 9:02 a.m. UTC | #2
Dear Guennadi

Thank you for checking patch


> > @@ -768,8 +844,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;
> > +
> > +	mask = SWAP_MASK;
> > +	if (IMG_MASK & val)
> > +		mask |= IMG_MASK;
> > +
> >  	ret = ov772x_mask_set(priv->client,
> > -			      COM3, SWAP_MASK, val);
> > +			      COM3, mask, val);
> 
> Do I understand it right, that this throws away any flip control settings 
> performed before S_FMT? You probably want to set priv->fmt->com3 in your 
> set_control and XOR instead of an OR here as well. Or was this 
> intentional?

Sorry, I can not understand what you want to say.
I think set_fmt function set default flip control.
And set_control function change flip on/off.
Therefore OR operation on set_fmt is correct I think.
And set_control use only XOR. priv->fmt->com3 is not needed here.
Do you say should I remember flip value ?
Or am I wrong understanding ?

Best regards
--
Kuninori Morimoto
 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Guennadi Liakhovetski Jan. 19, 2009, 9:11 a.m. UTC | #3
On Mon, 19 Jan 2009, morimoto.kuninori@renesas.com wrote:

> > > @@ -768,8 +844,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;
> > > +
> > > +	mask = SWAP_MASK;
> > > +	if (IMG_MASK & val)
> > > +		mask |= IMG_MASK;
> > > +
> > >  	ret = ov772x_mask_set(priv->client,
> > > -			      COM3, SWAP_MASK, val);
> > > +			      COM3, mask, val);
> > 
> > Do I understand it right, that this throws away any flip control settings 
> > performed before S_FMT? You probably want to set priv->fmt->com3 in your 
> > set_control and XOR instead of an OR here as well. Or was this 
> > intentional?
> 
> Sorry, I can not understand what you want to say.
> I think set_fmt function set default flip control.
> And set_control function change flip on/off.
> Therefore OR operation on set_fmt is correct I think.
> And set_control use only XOR. priv->fmt->com3 is not needed here.
> Do you say should I remember flip value ?

I think, yes. If someone sets vertical or horizontal flip using the 
respective control, and then calls S_FMT, I think, flip should be 
preserved. S_FMT is in no way a reset, it only sets fields that are 
explicitly passed with it - pixel format, image size, etc.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 3341857..ca0cf3c 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -218,9 +218,10 @@ 
 
 /* COM3 */
 #define SWAP_MASK       0x38
+#define IMG_MASK        0xC0
 
-#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 */
@@ -540,6 +541,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 +672,60 @@  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);
+	s32 val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		val = i2c_smbus_read_byte_data(priv->client, COM3);
+		if (val < 0)
+			return val;
+		if (priv->info->flags & OV772X_FLAG_VFLIP)
+			val ^= VFLIP_IMG;
+		val &= VFLIP_IMG;
+		ctrl->value = !!val;
+		break;
+	case V4L2_CID_HFLIP:
+		val = i2c_smbus_read_byte_data(priv->client, COM3);
+		if (val < 0)
+			return val;
+		if (priv->info->flags & OV772X_FLAG_HFLIP)
+			val ^= HFLIP_IMG;
+		val &= HFLIP_IMG;
+		ctrl->value = !!val;
+		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;
+		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;
+		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)
 {
@@ -720,7 +796,7 @@  static int ov772x_set_fmt(struct soc_camera_device *icd,
 {
 	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
 	int ret = -EINVAL;
-	u8  val;
+	u8  val, mask;
 	int i;
 
 	/*
@@ -768,8 +844,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;
+
+	mask = SWAP_MASK;
+	if (IMG_MASK & val)
+		mask |= IMG_MASK;
+
 	ret = ov772x_mask_set(priv->client,
-			      COM3, SWAP_MASK, val);
+			      COM3, mask, val);
 	if (ret < 0)
 		goto ov772x_set_fmt_error;
 
@@ -887,6 +972,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,
diff --git a/include/media/ov772x.h b/include/media/ov772x.h
index e391d55..57db48d 100644
--- a/include/media/ov772x.h
+++ b/include/media/ov772x.h
@@ -13,8 +13,13 @@ 
 
 #include <media/soc_camera.h>
 
+/* for flags */
+#define OV772X_FLAG_VFLIP     0x00000001 /* Vertical flip image */
+#define OV772X_FLAG_HFLIP     0x00000002 /* Horizontal flip image */
+
 struct ov772x_camera_info {
 	unsigned long          buswidth;
+	unsigned long          flags;
 	struct soc_camera_link link;
 };