GWater schrieb:
I already told you that I asked scott bertin to help me with our auto-exposure problem. (Currently auto-exposure doesn't show up in v4l2ucp because it has an id which isn't queried.)Scott Bertin answered me with a nice patch (v4l2ucp-extcontrols.patch) which led me to conlude that our code contains the problem. I found it and fixed it in the attached patch 0006. However I still face some difficulties with V4L2_CTRL_FLAG_NEXT_CTRL.V4L2_CTRL_FLAG_NEXT_CTRL can be used by an app to automagically get the next available CID. That works fine as long as all CIDs are in a nice order like:1,2,3,4 However in our code they are a bit mixed: 1,3,2,4This leads to CID number 2 being missed because my algorithm can't process the fact that before CID 3 CID 2 should be sent. However CID 1 should not be sent twice.Help me, Obi-Wan. GWaterPS:The other patches are just there to provide a nice line from origin to patch 0006. But please free to discuss them, too.
And he's talking while he could fix it himself, ...So here's a patch with full V4L2_CTRL_FLAG_NEXT_CTRL as described in the V4L2 spec. It is fully operational now, no more missing controls.
Have fun with auto-exposure.I'll ask Scott Bertin to commit his own patch to v4l2ucp now with a screenshot to proof that it fixes our problems.
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
From 1357d1e426eb80f5de9a6fb40092fa2828a25a86 Mon Sep 17 00:00:00 2001 From: GWater <[email protected]> Date: Fri, 19 Dec 2008 21:58:36 +0100 Subject: [PATCH] YUV422 omnivision sensors This patch is based on an older version by Brian Johnson <[email protected]> . Signed-off-by: GWater <[email protected]> --- microdia-dev.c | 2 ++ microdia-v4l.c | 9 +++++++-- omnivision.c | 23 +++++++++++++++++++++-- omnivision.h | 3 +++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/microdia-dev.c b/microdia-dev.c index c0b7cb3..b17e921 100644 --- a/microdia-dev.c +++ b/microdia-dev.c @@ -51,6 +51,8 @@ static struct sensor_info sensors[] = { .max_yavg = 60, .min_stable_yavg = 32, .max_stable_yavg = 58, + .set_yuv422 = ov965x_set_yuv422, + .set_bayer = ov965x_set_bayer, }, { .id = OV9655_SENSOR, diff --git a/microdia-v4l.c b/microdia-v4l.c index 7be3909..1985fa3 100644 --- a/microdia-v4l.c +++ b/microdia-v4l.c @@ -374,9 +374,13 @@ int v4l2_enable_video(struct usb_microdia *dev, int mode) dev_microdia_enable_video(dev, 1); dev_microdia_camera_settings(dev); - dev->queue.flags &= ~MICRODIA_QUEUE_DROP_INCOMPLETE; dev->mode = mode; + if(dev->vsettings.format.pixelformat == V4L2_PIX_FMT_JPEG) + dev->queue.flags &= ~MICRODIA_QUEUE_DROP_INCOMPLETE; + else + dev->queue.flags |= MICRODIA_QUEUE_DROP_INCOMPLETE; + return 0; } @@ -1061,9 +1065,10 @@ int microdia_vidioc_s_fmt_cap(struct file *file, void *priv, if (ret) return -EINVAL; + memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix)); + sn9c20x_set_resolution(dev, fmt->fmt.pix.width, fmt->fmt.pix.height); dev->camera.fmts[fmt->fmt.pix.priv].set_format(dev); - memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix)); return 0; } diff --git a/omnivision.c b/omnivision.c index b67742f..eb6bd5c 100644 --- a/omnivision.c +++ b/omnivision.c @@ -352,8 +352,7 @@ static __u8 ov9650_init[][2] = { {OV965X_CTL_ADC, 0x00}, /* reserved */ {OV965X_CTL_ACOM, 0x93}, /* reserved */ {OV965X_CTL_OFON, 0x50}, - {OV965X_CTL_TSLB, OV965X_TSLB_OUTPUT_SEQ_UYVY | - OV965X_TSLB_DIGITAL_BLC_ENABLE}, + {OV965X_CTL_TSLB, OV965X_TSLB_DIGITAL_BLC_ENABLE}, {OV965X_CTL_COM11, OV965X_COM11_MANUAL_BANDING_FILTER}, {OV965X_CTL_COM12, 0x73}, {OV965X_CTL_COM13, OV965X_COM13_ENABLE_COLOR_MATRIX | @@ -810,6 +809,26 @@ int ov_set_autoexposure(struct usb_microdia *dev) return ret; } +int ov965x_set_yuv422(struct usb_microdia *dev) +{ + __u8 buf = OV965X_COM7_OUTPUT_VGA; + sn9c20x_write_i2c_data(dev, 1, 0x12, &buf); + + sn9c20x_set_raw(dev); + + return 0; +} + +int ov965x_set_bayer(struct usb_microdia *dev) +{ + __u8 buf = OV965X_COM7_OUTPUT_RAW_RGB; + sn9c20x_write_i2c_data(dev, 1, 0x12, &buf); + + sn9c20x_set_raw(dev); + + return 0; +} + /** * @brief Set autogain for omnivision sensors * diff --git a/omnivision.h b/omnivision.h index 5840fb7..5246275 100644 --- a/omnivision.h +++ b/omnivision.h @@ -546,6 +546,9 @@ int ov965x_set_hvflip(struct usb_microdia *); int ov965x_set_exposure(struct usb_microdia *); int ov965x_flip_detect(struct usb_microdia *dev); int ov965x_get_yavg(struct usb_microdia *dev); +int ov965x_set_yuv422(struct usb_microdia *dev); +int ov965x_set_bayer(struct usb_microdia *dev); + int ov_initialize(struct usb_microdia *dev); int ov_set_autogain(struct usb_microdia *dev); -- 1.6.0.4
From b94ab6a234cbb32d684f4fce8e7371bda8169f65 Mon Sep 17 00:00:00 2001 From: GWater <[email protected]> Date: Fri, 19 Dec 2008 22:21:59 +0100 Subject: [PATCH] Copy default_fmts for every microdia device to avoid problems with multiple webcams on one host Signed-off-by: GWater <[email protected]> --- microdia-dev.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/microdia-dev.c b/microdia-dev.c index b17e921..056b83f 100644 --- a/microdia-dev.c +++ b/microdia-dev.c @@ -279,12 +279,17 @@ static struct microdia_video_format default_fmts[] = { }, }; +static struct microdia_video_format sensor_fmts[ARRAY_SIZE(default_fmts)]; + int dev_microdia_assign_fmts(struct usb_microdia *dev) { int i, j; - dev->camera.fmts = default_fmts; - dev->camera.nfmts = ARRAY_SIZE(default_fmts); + for (i = 0; i < ARRAY_SIZE(sensor_fmts); i++) + sensor_fmts[i] = default_fmts[i]; + + dev->camera.fmts = sensor_fmts; + dev->camera.nfmts = ARRAY_SIZE(sensor_fmts); for (i = 0; i < ARRAY_SIZE(default_fmts); i++) { if ((dev->camera.sensor->set_yuv422 != NULL) && -- 1.6.0.4
From f8ed8f236af8ecc8dd50d32d55145c10fe1fe746 Mon Sep 17 00:00:00 2001 From: GWater <[email protected]> Date: Sat, 20 Dec 2008 00:36:32 +0100 Subject: [PATCH] Implement V4L2_CTRL_FLAG_NEXT_CTRL This fixes the problem with V4L2_CID_EXPOSURE_AUTO Signed-off-by: GWater <[email protected]> --- microdia-v4l.c | 50 +++++++++++++++++++++++++++++++++++++------------- 1 files changed, 37 insertions(+), 13 deletions(-) diff --git a/microdia-v4l.c b/microdia-v4l.c index 1985fa3..e67056a 100644 --- a/microdia-v4l.c +++ b/microdia-v4l.c @@ -743,18 +743,42 @@ int microdia_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *ctrl) { int i; - int nbr; - - UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", ctrl->id); - - nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl); - - for (i = 0; i < nbr; i++) { - if (microdia_controls[i].id == ctrl->id) { + int nbr = ARRAY_SIZE(microdia_controls); +#ifdef V4L2_CTRL_FLAG_NEXT_CTRL + int min; + __u32 idnew, idlast; +#endif + UDIA_DEBUG("VIDIOC_QUERYCTRL id = 0x%x\n", ctrl->id); + +#ifdef V4L2_CTRL_FLAG_NEXT_CTRL + if (ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL) { + min = 0; + idnew = V4L2_CTRL_FLAG_NEXT_CTRL; + idlast = ctrl->id & ~V4L2_CTRL_FLAG_NEXT_CTRL; + for (i = 0; i < nbr; i++) { + if ((microdia_controls[i].id < idnew) && + (microdia_controls[i].id > idlast)) { + idnew = microdia_controls[i].id; + min = i; + } + } + if (microdia_controls[min].id > idlast) { UDIA_DEBUG("VIDIOC_QUERYCTRL found\n"); - memcpy(ctrl, µdia_controls[i], - sizeof(struct v4l2_queryctrl)); - break; + memcpy(ctrl, µdia_controls[min], + sizeof(struct v4l2_queryctrl)); + return 0; + } else + return -EINVAL; + } else +#endif + { + for (i = 0; i < nbr; i++) { + if (microdia_controls[i].id == ctrl->id) { + UDIA_DEBUG("VIDIOC_QUERYCTRL found\n"); + memcpy(ctrl, µdia_controls[i], + sizeof(struct v4l2_queryctrl)); + break; + } } } @@ -779,7 +803,7 @@ int microdia_vidioc_g_ctrl(struct file *file, void *priv, dev = video_get_drvdata(priv); - UDIA_DEBUG("GET CTRL id=%d\n", ctrl->id); + UDIA_DEBUG("GET CTRL id=0x%x\n", ctrl->id); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -861,7 +885,7 @@ int microdia_vidioc_s_ctrl(struct file *file, void *priv, dev = video_get_drvdata(priv); - UDIA_DEBUG("SET CTRL id=%d value=%d\n", ctrl->id, ctrl->value); + UDIA_DEBUG("SET CTRL id=0x%x value=%d\n", ctrl->id, ctrl->value); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: -- 1.6.0.4
Index: mainWindow.cpp
===================================================================
RCS file: /cvsroot/v4l2ucp/v4l2ucp/mainWindow.cpp,v
retrieving revision 1.8
diff -u -r1.8 mainWindow.cpp
--- mainWindow.cpp 5 Mar 2006 06:06:06 -0000 1.8
+++ mainWindow.cpp 4 Dec 2008 02:44:07 -0000
@@ -155,24 +155,37 @@
new QLabel(grid);
new QLabel(grid);
- /* Check all the standard controls */
- for(int i=V4L2_CID_BASE; i<V4L2_CID_LASTP1; i++) {
- struct v4l2_queryctrl ctrl;
- ctrl.id = i;
- if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
- mw->add_control(ctrl, fd, grid);
- }
- }
- /* Check any custom controls */
- for(int i=V4L2_CID_PRIVATE_BASE; ; i++) {
- struct v4l2_queryctrl ctrl;
- ctrl.id = i;
- if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
- mw->add_control(ctrl, fd, grid);
- } else {
- break;
- }
+ struct v4l2_queryctrl ctrl;
+#ifdef V4L2_CTRL_FLAG_NEXT_CTRL
+ /* Try the extended control API first */
+ ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
+ if(0 == ioctl (fd, VIDIOC_QUERYCTRL, &ctrl)) {
+ do {
+ mw->add_control(ctrl, fd, grid);
+ ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+ } while(0 == ioctl (fd, VIDIOC_QUERYCTRL, &ctrl));
+ } else
+#endif
+ {
+ /* Fall back on the standard API */
+ /* Check all the standard controls */
+ for(int i=V4L2_CID_BASE; i<V4L2_CID_LASTP1; i++) {
+ ctrl.id = i;
+ if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
+ mw->add_control(ctrl, fd, grid);
+ }
+ }
+
+ /* Check any custom controls */
+ for(int i=V4L2_CID_PRIVATE_BASE; ; i++) {
+ ctrl.id = i;
+ if(ioctl(fd, VIDIOC_QUERYCTRL, &ctrl) == 0) {
+ mw->add_control(ctrl, fd, grid);
+ } else {
+ break;
+ }
+ }
}
mw->setCentralWidget(sv);
signature.asc
Description: OpenPGP digital signature
