Please test it.

I have to admit I ad a bit deja-vu feeling here - didn't we already do this when we added autogain?


GWater
From d44c858d3d857506fb774805ee1694e62346827c Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Wed, 17 Dec 2008 23:07:56 +0100
Subject: [PATCH] Add support for hv7131r sensors

        devices 627c and 62bc should now work

Signed-off-by: GWater <[email protected]>
---
 Makefile       |    2 +-
 hv7131r.c      |  128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 microdia-dev.c |   14 ++++++
 microdia.h     |    7 +++
 sn9c20x.c      |   14 +-----
 5 files changed, 152 insertions(+), 13 deletions(-)
 create mode 100644 hv7131r.c

diff --git a/Makefile b/Makefile
index 379ae58..59d10ba 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ include $(src)/.config
 
 microdia-objs := microdia-usb.o microdia-v4l.o microdia-sysfs.o
 microdia-objs += microdia-dev.o microdia-queue.o
-microdia-objs += sn9c20x.o omnivision.o micron.o
+microdia-objs += sn9c20x.o omnivision.o micron.o hv7131r.o
 
 ifeq ($(CONFIG_MICRODIA_DEBUGFS),y)
 microdia-objs += microdia-debugfs.o
diff --git a/hv7131r.c b/hv7131r.c
new file mode 100644
index 0000000..ea44300
--- /dev/null
+++ b/hv7131r.c
@@ -0,0 +1,128 @@
+/**
+ * @file hv7131r.c
+ * @author GWater
+ * @date 2008-12-17
+ *
+ * @brief Common control functions the HV7131R Image Sensor
+ *
+ * @note Copyright (C) GWater
+ *
+ * @par Licences
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "microdia.h"
+#include "sn9c20x.h"
+
+static __u8 hv7131r_init[][2] = {
+       {0x02, 0x08},
+       {0x02, 0x00},
+       {0x01, 0x08},
+       {0x02, 0x00},
+       {0x20, 0x00},
+       {0x21, 0xd0},
+       {0x22, 0x00},
+       {0x23, 0x09},
+       {0x01, 0x08},
+       {0x01, 0x08},
+       {0x01, 0x08},
+       {0x25, 0x07},
+       {0x26, 0xc3},
+       {0x27, 0x50},
+       {0x30, 0x62},
+       {0x31, 0x10},
+       {0x32, 0x06},
+       {0x33, 0x10},
+       {0x20, 0x00},
+       {0x21, 0xd0},
+       {0x22, 0x00},
+       {0x23, 0x09},
+       {0x01, 0x08},
+};
+
+int hv7131r_initialize(struct usb_microdia *dev)
+{
+       int i;
+       int ret = 0;
+
+       dev->camera.i2c_flags |= SN9C20X_I2C_400KHZ;
+
+       for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
+               ret = sn9c20x_write_i2c_data(dev, 1, hv7131r_init[i][0],
+                       &hv7131r_init[i][1]);
+               if (ret < 0)
+                       goto err;
+       }
+
+       return ret;
+
+err:
+       UDIA_ERROR("Sensor Init failed (%d)! - line %d\n", ret, i);
+       return ret;
+}
+
+int hv7131r_set_exposure(struct usb_microdia *dev)
+{
+       __u8 buf[3];
+       int ret;
+       __u32 val;
+
+       val = (dev->vsettings.exposure * 0xffffff) / 0xffff;
+
+       buf[0] = (val >> 16) & 0xff;
+       buf[1] = (val >> 8) & 0xff;
+       buf[2] = val & 0xff;
+
+       ret = sn9c20x_write_i2c_data_ext(dev, 3, 0x25, buf, 0x1e);
+
+       return ret;
+}
+
+/* int hv7131r_set_gain(struct usb_microdia *dev)
+{
+       __u8 buf;
+       int ret;
+
+       buf = (dev->vsettings.gain >> 8) & 0xff;
+
+       ret = sn9c20x_write_i2c_data_ext(dev, 1, 0x30, &buf, 0x1d);
+
+       return ret;
+} */
+
+int hv7131r_set_hvflip(struct usb_microdia *dev)
+{
+       __u8 buf;
+       int ret;
+
+       ret = sn9c20x_read_i2c_data(dev, 1, 0x01, &buf);
+       if (ret < 0)
+               return ret;
+
+       if (dev->vsettings.hflip)
+               buf |= 0x02;
+       else
+               buf &= ~0x02;
+
+       if (dev->vsettings.vflip)
+               buf |= 0x01;
+       else
+               buf &= ~0x01;
+
+       ret = sn9c20x_write_i2c_data(dev, 1, 0x01, &buf);
+
+       return ret;
+}
diff --git a/microdia-dev.c b/microdia-dev.c
index 2f684ce..d16481b 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -139,6 +139,18 @@ static struct sensor_info sensors[] = {
                .hstart = 2,
                .vstart = 2,
        },
+       {
+               .id = HV7131R_SENSOR,
+               .name = "HV7131R",
+               .address = 0x11,
+               .initialize = hv7131r_initialize,
+               /* not yet available via V4L2:
+               .set_gain = hv7131r_set_gain, */
+               .set_exposure = hv7131r_set_exposure,
+               .set_hvflip = hv7131r_set_hvflip,
+               .hstart = 0,
+               .vstart = 1,
+       },
 };
 
 static __u16 known_cams[][2] = {
@@ -151,6 +163,7 @@ static __u16 known_cams[][2] = {
        {0x6253, OV9650_SENSOR},
        {0x6260, OV7670_SENSOR},
        {0x627b, OV7660_SENSOR},
+       {0x627c, HV7131R_SENSOR},
        {0x627f, OV9650_SENSOR},
        {0x6280, MT9M001_SENSOR},
        {0x6282, MT9M111_SENSOR},
@@ -160,6 +173,7 @@ static __u16 known_cams[][2] = {
        {0x62a0, OV7670_SENSOR},
        {0x62b3, OV9655_SENSOR},
        {0x62bb, OV7660_SENSOR},
+       {0x62bc, HV7131R_SENSOR},
        /* The following PIDs have VIDs different from 0x0c45. */
        {0x00f4, OV9650_SENSOR},
        {0x013d, OV7660_SENSOR},
diff --git a/microdia.h b/microdia.h
index 1134542..3f5dd7c 100644
--- a/microdia.h
+++ b/microdia.h
@@ -324,6 +324,7 @@ enum microdia_sensors {
        MT9V111_SENSOR          = 7,
        MT9V011_SENSOR          = 8,
        MT9M001_SENSOR          = 9,
+       HV7131R_SENSOR          = 10,
 };
 
 
@@ -522,4 +523,10 @@ static inline int microdia_queue_streaming(struct 
microdia_video_queue *queue)
        return queue->flags & MICRODIA_QUEUE_STREAMING;
 }
 
+/* sensor hv7131r has no header-file of its own: */
+int hv7131r_initialize(struct usb_microdia *dev);
+int hv7131r_set_exposure(struct usb_microdia *dev);
+/* int hv7131r_set_gain(struct usb_microdia *dev); */
+int hv7131r_set_hvflip(struct usb_microdia *dev);
+
 #endif
diff --git a/sn9c20x.c b/sn9c20x.c
index 328dad2..b66c1e1 100644
--- a/sn9c20x.c
+++ b/sn9c20x.c
@@ -227,17 +227,12 @@ int sn9c20x_set_LEDs(struct usb_microdia *dev, int enable)
        if (enable) {
                switch (sensor) {
                case MT9M001_SENSOR:
-                       led[0] = 0x80;
-                       led[1] = 0xa0;
-               break;
+               case HV7131R_SENSOR:
                case SOI968_SENSOR:
                        led[0] = 0x80;
                        led[1] = 0xa0;
                break;
                case MT9V011_SENSOR:
-                       led[0] = 0x40;
-                       led[1] = 0x60;
-               break;
                case OV7660_SENSOR:
                        led[0] = 0x40;
                        led[1] = 0x60;
@@ -252,18 +247,13 @@ int sn9c20x_set_LEDs(struct usb_microdia *dev, int enable)
                }
        } else {
                switch (sensor) {
+               case HV7131R_SENSOR:
                case MT9M001_SENSOR:
-                       led[0] = 0xa0;
-                       led[1] = 0xa0;
-               break;
                case MT9V011_SENSOR:
                        led[0] = 0xa0;
                        led[1] = 0xa0;
                break;
                case MT9M111_SENSOR:
-                       led[0] = 0x20;
-                       led[1] = 0x60;
-               break;
                case OV7660_SENSOR:
                        led[0] = 0x20;
                        led[1] = 0x60;
-- 
1.6.0.4

From 33746012cc98aeecd489659bb9e5422038cd7906 Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Fri, 19 Dec 2008 20:45:34 +0100
Subject: [PATCH] Add module parameter gain/V4L2_CID_GAIN

Signed-off-by: GWater <[email protected]>
---
 hv7131r.c      |    4 ++--
 microdia-dev.c |   19 +++++++++++++++++--
 microdia-usb.c |    8 ++++++++
 microdia-v4l.c |   18 ++++++++++++++++++
 microdia.h     |    5 ++++-
 5 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/hv7131r.c b/hv7131r.c
index ea44300..291fbec 100644
--- a/hv7131r.c
+++ b/hv7131r.c
@@ -91,7 +91,7 @@ int hv7131r_set_exposure(struct usb_microdia *dev)
        return ret;
 }
 
-/* int hv7131r_set_gain(struct usb_microdia *dev)
+int hv7131r_set_gain(struct usb_microdia *dev)
 {
        __u8 buf;
        int ret;
@@ -101,7 +101,7 @@ int hv7131r_set_exposure(struct usb_microdia *dev)
        ret = sn9c20x_write_i2c_data_ext(dev, 1, 0x30, &buf, 0x1d);
 
        return ret;
-} */
+}
 
 int hv7131r_set_hvflip(struct usb_microdia *dev)
 {
diff --git a/microdia-dev.c b/microdia-dev.c
index d16481b..a6070f5 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -144,8 +144,7 @@ static struct sensor_info sensors[] = {
                .name = "HV7131R",
                .address = 0x11,
                .initialize = hv7131r_initialize,
-               /* not yet available via V4L2:
-               .set_gain = hv7131r_set_gain, */
+               .set_gain = hv7131r_set_gain,
                .set_exposure = hv7131r_set_exposure,
                .set_hvflip = hv7131r_set_hvflip,
                .hstart = 0,
@@ -441,6 +440,22 @@ int dev_microdia_camera_set_exposure(struct usb_microdia 
*dev)
 }
 
 /**
+ * @brief Wrapper function for device-specific gain functions
+ *
+ * @param dev Pointer to device structure
+ *
+ * @returns 0 or negative error value
+ *
+ */
+int dev_microdia_camera_set_gain(struct usb_microdia *dev)
+{
+       if (dev && dev->camera.sensor->set_gain != NULL)
+               return dev->camera.sensor->set_gain(dev);
+
+       return 0;
+}
+
+/**
  * @brief Wrapper function for device-specific hvflip functions
  *
  * @param dev Pointer to device structure
diff --git a/microdia-usb.c b/microdia-usb.c
index e9b405b..a06bdeb 100644
--- a/microdia-usb.c
+++ b/microdia-usb.c
@@ -96,6 +96,12 @@ static int contrast = MICRODIA_PERCENT(50, 0xFFFF);
 static int exposure = MICRODIA_PERCENT(20, 0xFFFF);
 
 /**
+ * @var gain
+ *   Module parameter to set the gain
+ */
+static int gain = MICRODIA_PERCENT(20, 0xFFFF);
+
+/**
  * @var sharpness
  *   Module parameter to set the sharpness
  */
@@ -705,6 +711,7 @@ static int usb_microdia_default_settings(struct 
usb_microdia *dev)
        dev->vsettings.contrast = contrast & 0xffff;
        dev->vsettings.whiteness = whiteness & 0xffff;
        dev->vsettings.exposure = exposure & 0xffff;
+       dev->vsettings.gain = gain & 0xffff;
        dev->vsettings.sharpness = sharpness & 0x3f;
        dev->vsettings.rgb_gain[0] = (rgb_gain >> 16) & 0x7f;
        dev->vsettings.rgb_gain[1] = (rgb_gain >> 8) & 0x7f;
@@ -1023,6 +1030,7 @@ MODULE_PARM_DESC(auto_whitebalance, "Automatic 
whitebalance");    /**< @brief Descr
 MODULE_PARM_DESC(brightness, "Brightness setting");    /**< @brief Description 
of 'brightness' parameter */
 MODULE_PARM_DESC(whiteness, "Whiteness setting");      /**< @brief Description 
of 'whiteness' parameter */
 MODULE_PARM_DESC(exposure, "Exposure setting");                /**< @brief 
Description of 'exposure' parameter */
+MODULE_PARM_DESC(gain, "Gain setting");                        /**< @brief 
Description of 'gain' parameter */
 MODULE_PARM_DESC(contrast, "Contrast setting");                /**< @brief 
Description of 'contrast' parameter */
 MODULE_PARM_DESC(sharpness, "Sharpness setting");      /**< @brief Description 
of 'sharpness' parameter */
 MODULE_PARM_DESC(rgb_gain, "Red/Green/Blue Gain setting"); /**< @brief 
Description of 'RGB Gain' parameter */
diff --git a/microdia-v4l.c b/microdia-v4l.c
index 4f6f11d..7be3909 100644
--- a/microdia-v4l.c
+++ b/microdia-v4l.c
@@ -96,6 +96,15 @@ static struct v4l2_queryctrl microdia_controls[] = {
                .default_value = 0x1000,
        },
        {
+               .id      = V4L2_CID_GAIN,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gain",
+               .minimum = 0,
+               .maximum = 0xff00,
+               .step    = 1,
+               .default_value = 0x1000,
+       },
+       {
                .id      = V4L2_CID_HFLIP,
                .type    = V4L2_CTRL_TYPE_BOOLEAN,
                .name    = "Horizontal flip",
@@ -777,6 +786,10 @@ int microdia_vidioc_g_ctrl(struct file *file, void *priv,
                ctrl->value = dev->vsettings.exposure;
                break;
 
+       case V4L2_CID_GAIN:
+               ctrl->value = dev->vsettings.gain;
+               break;
+
        case V4L2_CID_WHITENESS:
                ctrl->value = dev->vsettings.whiteness;
                break;
@@ -857,6 +870,11 @@ int microdia_vidioc_s_ctrl(struct file *file, void *priv,
                dev_microdia_camera_set_exposure(dev);
                break;
 
+       case V4L2_CID_GAIN:
+               dev->vsettings.gain = (0xff00 & ctrl->value);
+               dev_microdia_camera_set_gain(dev);
+               break;
+
        case V4L2_CID_WHITENESS:
                dev->vsettings.whiteness = (0xff00 & ctrl->value);
                dev_microdia_camera_set_gamma(dev);
diff --git a/microdia.h b/microdia.h
index 3f5dd7c..5a474b6 100644
--- a/microdia.h
+++ b/microdia.h
@@ -282,6 +282,7 @@ struct microdia_video {
        int hflip;                              /**< Horizontal flip */
        int vflip;                              /**< Vertical flip */
        int exposure;                           /**< Exposure */
+       int gain;                               /**< Gain */
        int sharpness;                          /**< Sharpness */
        __u8 rgb_gain[4];                       /**< RGB Gain (RGGB) */
        int auto_exposure;                      /**< Automatic exposure */
@@ -362,6 +363,7 @@ struct sensor_info {
 /* sensor specific functions */
        int (*initialize) (struct usb_microdia *dev);
        int (*set_exposure) (struct usb_microdia *dev);
+       int (*set_gain) (struct usb_microdia *dev);
        int (*set_auto_exposure) (struct usb_microdia *dev);
        int (*set_auto_gain) (struct usb_microdia *dev);
        int (*set_auto_whitebalance) (struct usb_microdia *dev);
@@ -467,6 +469,7 @@ int dev_microdia_camera_set_contrast(struct usb_microdia *);
 int dev_microdia_camera_set_brightness(struct usb_microdia *);
 int dev_microdia_camera_set_gamma(struct usb_microdia *);
 int dev_microdia_camera_set_exposure(struct usb_microdia *);
+int dev_microdia_camera_set_gain(struct usb_microdia *);
 int dev_microdia_camera_set_hvflip(struct usb_microdia *);
 int dev_microdia_camera_set_sharpness(struct usb_microdia *dev);
 int dev_microdia_camera_set_rgb_gain(struct usb_microdia *dev);
@@ -526,7 +529,7 @@ static inline int microdia_queue_streaming(struct 
microdia_video_queue *queue)
 /* sensor hv7131r has no header-file of its own: */
 int hv7131r_initialize(struct usb_microdia *dev);
 int hv7131r_set_exposure(struct usb_microdia *dev);
-/* int hv7131r_set_gain(struct usb_microdia *dev); */
+int hv7131r_set_gain(struct usb_microdia *dev);
 int hv7131r_set_hvflip(struct usb_microdia *dev);
 
 #endif
-- 
1.6.0.4

From 1b85a720869456c9180e12109254f330a41ef0e4 Mon Sep 17 00:00:00 2001
From: GWater <[email protected]>
Date: Fri, 19 Dec 2008 21:14:18 +0100
Subject: [PATCH] Add gain control for omnivision sensors

Signed-off-by: GWater <[email protected]>
---
 microdia-dev.c |    5 +++++
 omnivision.c   |   32 ++++++++++++++++++++++++++++++++
 omnivision.h   |    1 +
 3 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/microdia-dev.c b/microdia-dev.c
index a6070f5..c0b7cb3 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -44,6 +44,7 @@ static struct sensor_info sensors[] = {
                .set_hvflip = ov965x_set_hvflip,
                .set_exposure = ov965x_set_exposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .flip_detect = ov965x_flip_detect,
                .get_yavg = ov965x_get_yavg,
                .min_yavg = 30,
@@ -58,6 +59,7 @@ static struct sensor_info sensors[] = {
                .initialize = ov_initialize,
                .set_auto_exposure = ov_set_autoexposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .hstart = 0,
                .vstart = 7,
        },
@@ -69,6 +71,7 @@ static struct sensor_info sensors[] = {
                .set_exposure = soi968_set_exposure,
                .set_auto_exposure = ov_set_autoexposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .button_detect = soi968_button_detect,
                .hstart = 60,
                .vstart = 11,
@@ -80,6 +83,7 @@ static struct sensor_info sensors[] = {
                .initialize = ov_initialize,
                .set_exposure = ov7660_set_exposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .hstart = 1,
                .vstart = 1,
                .get_yavg = ov965x_get_yavg,
@@ -96,6 +100,7 @@ static struct sensor_info sensors[] = {
                .set_auto_exposure = ov_set_autoexposure,
                .set_exposure = ov7660_set_exposure,
                .set_auto_gain = ov_set_autogain,
+               .set_gain = ov_set_gain,
                .flip_detect = ov7670_flip_detect,
                .hstart = 0,
                .vstart = 1,
diff --git a/omnivision.c b/omnivision.c
index 7cfc230..b67742f 100644
--- a/omnivision.c
+++ b/omnivision.c
@@ -892,6 +892,38 @@ int soi968_set_exposure(struct usb_microdia *dev)
        return 0;
 }
 
+int ov_set_gain(struct usb_microdia *dev)
+{
+       __u8 buf, buf2;
+       int ret;
+       __u16 val = dev->vsettings.gain;
+
+       switch (dev->camera.sensor->id) {
+       case SOI968_SENSOR:
+               buf = (val >> 10) & 0x3f;
+       break;
+       case OV7660_SENSOR:
+               buf = (val >> 9) & 0x7f;
+       break;
+       case OV7670_SENSOR:
+               buf = (val >> 6) & 0xff;
+               ret = sn9c20x_read_i2c_data(dev, 1, 0x03, &buf2);
+               if (ret < 0)
+                       return ret;
+               buf2 |= ((val >> 8) & 0xc0);
+               ret = sn9c20x_write_i2c_data(dev, 1, 0x03, &buf2);
+               if (ret < 0)
+                       return ret;
+       break;
+       default:
+               buf = (val >> 8) & 0xff;
+       }
+
+       ret = sn9c20x_write_i2c_data(dev, 1, 0x00, &buf);
+
+       return ret;
+}
+
 /**
  * @brief Detect whether the image for 6260 has to be flipped
  *
diff --git a/omnivision.h b/omnivision.h
index 391fbf1..5840fb7 100644
--- a/omnivision.h
+++ b/omnivision.h
@@ -550,4 +550,5 @@ int ov965x_get_yavg(struct usb_microdia *dev);
 int ov_initialize(struct usb_microdia *dev);
 int ov_set_autogain(struct usb_microdia *dev);
 int ov_set_autoexposure(struct usb_microdia *dev);
+int ov_set_gain(struct usb_microdia *dev);
 #endif
-- 
1.6.0.4

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to