V4L/DVB (10669): ov772x: Add image flip support
authorKuninori Morimoto <morimoto.kuninori@renesas.com>
Mon, 23 Feb 2009 15:12:58 +0000 (12:12 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:42:52 +0000 (12:42 -0300)
o ov772x_camera_info :: flags supports default image flip.
o V4L2_CID_VFLIP/HFLIP supports image flip for user side.
Thank Magnus for advice.

Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/ov772x.c
include/media/ov772x.h

index 6b18da7c3c0ac02272a8f38a99171436edbf641a..880e51f0e9fd8303a62fd18be6dad944252fe597 100644 (file)
 #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,
index e391d55edb951df8fe9d037c569a2dce324298d6..57db48dd85b8ffd1dfe5d4ee2b8cb56eda765f85 100644 (file)
 
 #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;
 };