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
signature.asc
Description: OpenPGP digital signature
