summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-08-08 03:06:19 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2008-08-08 03:06:19 +0200
commitb80b601f0087391e55d3859e70f08278632b1185 (patch)
tree1fa138af8da80bf523a6f259c726e162fe387fb7
parentMerge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6 (diff)
parentV4L/DVB (8617): uvcvideo: don't use stack-based buffers for USB transfers. (diff)
downloadlinux-b80b601f0087391e55d3859e70f08278632b1185.tar.xz
linux-b80b601f0087391e55d3859e70f08278632b1185.zip
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (23 commits) V4L/DVB (8617): uvcvideo: don't use stack-based buffers for USB transfers. V4L/DVB (8616): uvcvideo: Add support for two Bison Electronics webcams V4L/DVB (8611): Add suspend/resume to pxa_camera driver V4L/DVB (8610): Add suspend/resume capabilities to soc_camera. V4L/DVB (8609): media: Clean up platform_driver_unregister() bogosity. V4L/DVB (8607): cxusb: fix OOPS and broken tuning regression on FusionHDTV Dual Digital 4 V4L/DVB (8605): gspca: Fix of gspca_zc3xx oops - 2.6.27-rc1 V4L/DVB (8604): gspca: Fix of "scheduling while atomic" crash. V4L/DVB (8602): gspca: Fix small bugs, simplify and cleanup ov519. V4L/DVB (8582): set mts_firmware for em2882 based Pinnacle Hybrid Pro V4L/DVB (8574): gspca: Bad bytesperlines of pixelformat in spca505/506/508 and vc023x. V4L/DVB (8573): gspca: Bad scan of frame in spca505/506/508. V4L/DVB (8572): gspca: Webcam 0c45:6143 in documentation. V4L/DVB (8571): gspca: Don't use CONFIG_VIDEO_ADV_DEBUG as a compile option. V4L/DVB (8569): gspca: Set back the old values of Sonix sn9c120 and cleanup source. V4L/DVB (8567): gspca: hflip and vflip controls added for ov519 - ov7670 plus init cleanup. V4L/DVB (8564): fix vino driver build error V4L/DVB (8563): fix drivers/media/video/arv.c compilation V4L/DVB (8562): DVB_DRX397XD: remove FW_LOADER select V4L/DVB (8558): media/video/Kconfig: fix a typo ...
-rw-r--r--Documentation/video4linux/gspca.txt1
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c7
-rw-r--r--drivers/media/dvb/frontends/Kconfig3
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/arv.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c1
-rw-r--r--drivers/media/video/gspca/conex.c4
-rw-r--r--drivers/media/video/gspca/etoms.c137
-rw-r--r--drivers/media/video/gspca/gspca.c12
-rw-r--r--drivers/media/video/gspca/gspca.h5
-rw-r--r--drivers/media/video/gspca/ov519.c476
-rw-r--r--drivers/media/video/gspca/pac7311.c54
-rw-r--r--drivers/media/video/gspca/sonixb.c2
-rw-r--r--drivers/media/video/gspca/sonixj.c287
-rw-r--r--drivers/media/video/gspca/spca505.c12
-rw-r--r--drivers/media/video/gspca/spca506.c12
-rw-r--r--drivers/media/video/gspca/spca508.c18
-rw-r--r--drivers/media/video/gspca/spca561.c42
-rw-r--r--drivers/media/video/gspca/vc032x.c4
-rw-r--r--drivers/media/video/gspca/zc3xx.c6
-rw-r--r--drivers/media/video/pxa_camera.c58
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c2
-rw-r--r--drivers/media/video/soc_camera.c26
-rw-r--r--drivers/media/video/soc_camera_platform.c2
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c33
-rw-r--r--drivers/media/video/uvc/uvc_driver.c26
-rw-r--r--drivers/media/video/uvc/uvc_video.c33
-rw-r--r--drivers/media/video/v4l2-dev.c4
-rw-r--r--drivers/media/video/vino.c1
-rw-r--r--include/media/soc_camera.h5
30 files changed, 685 insertions, 592 deletions
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index bcaf4ab383be..78a863ab8a5a 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -226,6 +226,7 @@ sonixj 0c45:6130 Sonix Pccam
sonixj 0c45:6138 Sn9c120 Mo4000
sonixj 0c45:613b Surfer SN-206
sonixj 0c45:613c Sonix Pccam168
+sonixj 0c45:6143 Sonix Pccam168
sunplus 0d64:0303 Sunplus FashionCam DXG
etoms 102c:6151 Qcam Sangha CIF
etoms 102c:6251 Qcam xxxxxx VGA
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 578afce6884c..aaa0b6f0b521 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -565,7 +565,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
{
- struct dvb_usb_device *d = ptr;
+ struct dvb_usb_adapter *adap = ptr;
+ struct dvb_usb_device *d = adap->dev;
switch (command) {
case XC2028_TUNER_RESET:
@@ -593,9 +594,9 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
.callback = dvico_bluebird_xc2028_callback,
};
static struct xc2028_ctrl ctl = {
- .fname = "xc3028-dvico-au-01.fw",
+ .fname = "xc3028-v27.fw",
.max_len = 64,
- .scode_table = XC3028_FE_ZARLINK456,
+ .demod = XC3028_FE_ZARLINK456,
};
fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 574dffe91b68..7dbb4a223c99 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -135,9 +135,8 @@ config DVB_CX22702
config DVB_DRX397XD
tristate "Micronas DRX3975D/DRX3977D based"
- depends on DVB_CORE && I2C && HOTPLUG
+ depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index d4a6e56a7135..ecbfa1b39b70 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -630,7 +630,7 @@ config VIDEO_ZORAN_ZR36060
depends on VIDEO_ZORAN
help
Say Y to support Zoran boards based on 36060 chips.
- This includes Iomega Bus, Pinnacle DC10, Linux media Labs 33
+ This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
and 33 R10 and AverMedia 6 boards.
config VIDEO_ZORAN_BUZ
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 56ebfd5ef6fa..9e436ad3d34b 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -29,6 +29,7 @@
#include <linux/sched.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -755,7 +756,6 @@ static const struct file_operations ar_fops = {
static struct video_device ar_template = {
.name = "Colour AR VGA",
- .type = VID_TYPE_CAPTURE,
.fops = &ar_fops,
.release = ar_release,
.minor = -1,
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 476ae44a62d2..452da70e719f 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -1015,6 +1015,7 @@ struct em28xx_board em28xx_boards[] = {
.valid = EM28XX_BOARD_NOT_VALIDATED,
.vchannels = 3,
.tuner_type = TUNER_XC2028,
+ .mts_firmware = 1,
.decoder = EM28XX_TVP5150,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index 44b0bffeb20e..cd3a3f5829b2 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -123,7 +123,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
{
struct usb_device *dev = gspca_dev->dev;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
err("reg_r: buffer overflow");
return;
@@ -163,7 +163,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
{
struct usb_device *dev = gspca_dev->dev;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
err("reg_w: buffer overflow");
return;
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
index c8c2f02fcf00..1dbe92d01e6a 100644
--- a/drivers/media/video/gspca/etoms.c
+++ b/drivers/media/video/gspca/etoms.c
@@ -233,7 +233,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
{
struct usb_device *dev = gspca_dev->dev;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
err("reg_r: buffer overflow");
return;
@@ -271,7 +271,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
{
struct usb_device *dev = gspca_dev->dev;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
err("reg_w: buffer overflow");
return;
@@ -461,6 +461,52 @@ static void Et_init2(struct gspca_dev *gspca_dev)
reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */
}
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i;
+ __u8 brightness = sd->brightness;
+
+ for (i = 0; i < 4; i++)
+ reg_w_val(gspca_dev, ET_O_RED + i, brightness);
+}
+
+static void getbrightness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i;
+ int brightness = 0;
+
+ for (i = 0; i < 4; i++) {
+ reg_r(gspca_dev, ET_O_RED + i, 1);
+ brightness += gspca_dev->usb_buf[0];
+ }
+ sd->brightness = brightness >> 3;
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
+ __u8 contrast = sd->contrast;
+
+ memset(RGBG, contrast, sizeof(RGBG) - 2);
+ reg_w(gspca_dev, ET_G_RED, RGBG, 6);
+}
+
+static void getcontrast(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i;
+ int contrast = 0;
+
+ for (i = 0; i < 4; i++) {
+ reg_r(gspca_dev, ET_G_RED + i, 1);
+ contrast += gspca_dev->usb_buf[0];
+ }
+ sd->contrast = contrast >> 2;
+}
+
static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -492,6 +538,16 @@ static void getcolors(struct gspca_dev *gspca_dev)
}
}
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->autogain)
+ sd->ag_cnt = AG_CNT_START;
+ else
+ sd->ag_cnt = -1;
+}
+
static void Et_init1(struct gspca_dev *gspca_dev)
{
__u8 value;
@@ -614,6 +670,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->contrast = CONTRAST_DEF;
sd->colors = COLOR_DEF;
sd->autogain = AUTOGAIN_DEF;
+ sd->ag_cnt = -1;
return 0;
}
@@ -641,6 +698,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
else
Et_init2(gspca_dev);
+ setautogain(gspca_dev);
+
reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
et_video(gspca_dev, 1); /* video on */
}
@@ -658,52 +717,6 @@ static void sd_close(struct gspca_dev *gspca_dev)
{
}
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- int i;
- __u8 brightness = sd->brightness;
-
- for (i = 0; i < 4; i++)
- reg_w_val(gspca_dev, ET_O_RED + i, brightness);
-}
-
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- int i;
- int brightness = 0;
-
- for (i = 0; i < 4; i++) {
- reg_r(gspca_dev, ET_O_RED + i, 1);
- brightness += gspca_dev->usb_buf[0];
- }
- sd->brightness = brightness >> 3;
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
- __u8 contrast = sd->contrast;
-
- memset(RGBG, contrast, sizeof(RGBG) - 2);
- reg_w(gspca_dev, ET_G_RED, RGBG, 6);
-}
-
-static void getcontrast(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- int i;
- int contrast = 0;
-
- for (i = 0; i < 4; i++) {
- reg_r(gspca_dev, ET_G_RED + i, 1);
- contrast += gspca_dev->usb_buf[0];
- }
- sd->contrast = contrast >> 2;
-}
-
static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -733,15 +746,22 @@ static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
#define LIMIT(color) \
(unsigned char)((color > 0xff)?0xff:((color < 0)?0:color))
-static void setautogain(struct gspca_dev *gspca_dev)
+static void do_autogain(struct gspca_dev *gspca_dev)
{
- __u8 luma = 0;
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u8 luma;
__u8 luma_mean = 128;
__u8 luma_delta = 20;
__u8 spring = 4;
- int Gbright = 0;
+ int Gbright;
__u8 r, g, b;
+ if (sd->ag_cnt < 0)
+ return;
+ if (--sd->ag_cnt >= 0)
+ return;
+ sd->ag_cnt = AG_CNT_START;
+
Gbright = Et_getgainG(gspca_dev);
reg_r(gspca_dev, ET_LUMA_CENTER, 4);
g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
@@ -768,7 +788,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
__u8 *data, /* isoc packet */
int len) /* iso packet length */
{
- struct sd *sd;
int seqframe;
seqframe = data[0] & 0x3f;
@@ -783,13 +802,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
data, 0);
gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
- sd = (struct sd *) gspca_dev;
- if (sd->ag_cnt >= 0) {
- if (--sd->ag_cnt < 0) {
- sd->ag_cnt = AG_CNT_START;
- setautogain(gspca_dev);
- }
- }
return;
}
if (len) {
@@ -862,10 +874,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
- if (val)
- sd->ag_cnt = AG_CNT_START;
- else
- sd->ag_cnt = -1;
+ if (gspca_dev->streaming)
+ setautogain(gspca_dev);
return 0;
}
@@ -889,6 +899,7 @@ static struct sd_desc sd_desc = {
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
+ .dq_callback = do_autogain,
};
/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 3a051c925ff6..15d302b28b79 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -47,7 +47,7 @@ MODULE_LICENSE("GPL");
static int video_nr = -1;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
int gspca_debug = D_ERR | D_PROBE;
EXPORT_SYMBOL(gspca_debug);
@@ -677,7 +677,7 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
w = fmt->fmt.pix.width;
h = fmt->fmt.pix.height;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (gspca_debug & D_CONF)
PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
#endif
@@ -785,7 +785,7 @@ static int dev_open(struct inode *inode, struct file *file)
}
gspca_dev->users++;
file->private_data = gspca_dev;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
/* activate the v4l2 debug */
if (gspca_debug & D_V4L2)
gspca_dev->vdev.debug |= 3;
@@ -904,7 +904,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
if (ctrl->id != ctrls->qctrl.id)
continue;
if (ctrl->value < ctrls->qctrl.minimum
- && ctrl->value > ctrls->qctrl.maximum)
+ || ctrl->value > ctrls->qctrl.maximum)
return -ERANGE;
PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
@@ -1080,7 +1080,7 @@ static int vidioc_streamon(struct file *file, void *priv,
if (ret < 0)
goto out;
}
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (gspca_debug & D_STREAM) {
PDEBUG_MODE("stream on OK",
gspca_dev->pixfmt,
@@ -1913,7 +1913,7 @@ static void __exit gspca_exit(void)
module_init(gspca_init);
module_exit(gspca_exit);
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
module_param_named(debug, gspca_debug, int, 0644);
MODULE_PARM_DESC(debug,
"Debug (bit) 0x01:error 0x02:probe 0x04:config"
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 3fd2c4eee204..67e448940eaa 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -9,7 +9,10 @@
#include <media/v4l2-common.h>
#include <linux/mutex.h>
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+/* compilation option */
+#define GSPCA_DEBUG 1
+
+#ifdef GSPCA_DEBUG
/* GSPCA our debug messages */
extern int gspca_debug;
#define PDEBUG(level, fmt, args...) \
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 83139efc4629..b4f00ec0885c 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -40,14 +40,15 @@ struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
/* Determined by sensor type */
- short maxwidth;
- short maxheight;
+ char sif;
unsigned char primary_i2c_slave; /* I2C write id of sensor */
unsigned char brightness;
unsigned char contrast;
unsigned char colors;
+ __u8 hflip;
+ __u8 vflip;
char compress; /* Should the next frame be compressed? */
char compress_inited; /* Are compression params uploaded? */
@@ -77,9 +78,12 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
@@ -88,12 +92,12 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 255,
.step = 1,
- .default_value = 127,
+#define BRIGHTNESS_DEF 127
+ .default_value = BRIGHTNESS_DEF,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
-#define SD_CONTRAST 1
{
{
.id = V4L2_CID_CONTRAST,
@@ -102,31 +106,61 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 255,
.step = 1,
- .default_value = 127,
+#define CONTRAST_DEF 127
+ .default_value = CONTRAST_DEF,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
},
-#define SD_COLOR 2
{
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Saturation",
+ .name = "Color",
.minimum = 0,
.maximum = 255,
.step = 1,
- .default_value = 127,
+#define COLOR_DEF 127
+ .default_value = COLOR_DEF,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
+/* next controls work with ov7670 only */
+ {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define HFLIP_DEF 0
+ .default_value = HFLIP_DEF,
+ },
+ .set = sd_sethflip,
+ .get = sd_gethflip,
+ },
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vflip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define VFLIP_DEF 0
+ .default_value = VFLIP_DEF,
+ },
+ .set = sd_setvflip,
+ .get = sd_getvflip,
+ },
};
static struct v4l2_pix_format vga_mode[] = {
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 320,
- .sizeimage = 320 * 240 * 3 / 8 + 589,
+ .sizeimage = 320 * 240 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 1},
{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -138,12 +172,12 @@ static struct v4l2_pix_format vga_mode[] = {
static struct v4l2_pix_format sif_mode[] = {
{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 176,
- .sizeimage = 176 * 144 * 3 / 8 + 589,
+ .sizeimage = 176 * 144 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 1},
{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 352,
- .sizeimage = 352 * 288 * 3 / 8 + 589,
+ .sizeimage = 352 * 288 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0},
};
@@ -225,6 +259,7 @@ static struct v4l2_pix_format sif_mode[] = {
#define OV7670_REG_VSTART 0x19 /* Vert start high bits */
#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */
#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */
+#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */
#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */
#define OV7670_REG_AEW 0x24 /* AGC upper limit */
#define OV7670_REG_AEB 0x25 /* AGC lower limit */
@@ -258,16 +293,6 @@ static struct v4l2_pix_format sif_mode[] = {
#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */
-struct ovsensor_window {
- short x;
- short y;
- short width;
- short height;
-/* int format; */
- short quarter; /* Scale width and height down 2x */
- short clockdiv; /* Clock divisor setting */
-};
-
static unsigned char ov7670_abs_to_sm(unsigned char v)
{
if (v > 127)
@@ -499,19 +524,6 @@ static int init_ov_sensor(struct sd *sd)
return 0;
}
-/* Switch on standard JPEG compression. Returns 0 for success. */
-static int ov519_init_compression(struct sd *sd)
-{
- if (!sd->compress_inited) {
- if (reg_w_mask(sd, OV519_SYS_EN_CLK1, 1 << 2, 1 << 2) < 0) {
- PDEBUG(D_ERR, "Error switching to compressed mode");
- return -EIO;
- }
- sd->compress_inited = 1;
- }
- return 0;
-}
-
/* Set the read and write slave IDs. The "slave" argument is the write slave,
* and the read slave will be set to (slave + 1).
* This should not be called from outside the i2c I/O functions.
@@ -681,21 +693,17 @@ static int ov8xx0_configure(struct sd *sd)
return -1;
}
if ((rc & 3) == 1) {
- PDEBUG(D_PROBE, "Sensor is an OV8610");
sd->sensor = SEN_OV8610;
} else {
PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
return -1;
}
PDEBUG(D_PROBE, "Writing 8610 registers");
- if (write_i2c_regvals(sd,
- norm_8610,
- sizeof norm_8610 / sizeof norm_8610[0]))
+ if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
return -1;
/* Set sensor-specific vars */
- sd->maxwidth = 640;
- sd->maxheight = 480;
+/* sd->sif = 0; already done */
return 0;
}
@@ -825,7 +833,7 @@ static int ov7xx0_configure(struct sd *sd)
{ OV7670_REG_COM7, OV7670_COM7_RESET },
{ OV7670_REG_TSLB, 0x04 }, /* OV */
{ OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
- { OV7670_REG_CLKRC, 0x1 },
+ { OV7670_REG_CLKRC, 0x01 },
/*
* Set the hardware window. These values from OV don't entirely
* make sense - hstop is less than hstart. But they work...
@@ -839,16 +847,12 @@ static int ov7xx0_configure(struct sd *sd)
{ 0x70, 0x3a }, { 0x71, 0x35 },
{ 0x72, 0x11 }, { 0x73, 0xf0 },
{ 0xa2, 0x02 },
-/* jfm */
-/* { OV7670_REG_COM10, 0x0 }, */
+/* { OV7670_REG_COM10, 0x0 }, */
/* Gamma curve values */
{ 0x7a, 0x20 },
-/* jfm:win 7b=1c */
{ 0x7b, 0x10 },
-/* jfm:win 7c=28 */
{ 0x7c, 0x1e },
-/* jfm:win 7d=3c */
{ 0x7d, 0x35 },
{ 0x7e, 0x5a }, { 0x7f, 0x69 },
{ 0x80, 0x76 }, { 0x81, 0x80 },
@@ -864,13 +868,11 @@ static int ov7xx0_configure(struct sd *sd)
| OV7670_COM8_BFILT },
{ OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 },
{ OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
-/* jfm:win 14=38 */
{ OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
{ OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 },
{ OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 },
{ OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 },
{ OV7670_REG_HAECC2, 0x68 },
-/* jfm:win a1=0b */
{ 0xa1, 0x03 }, /* magic */
{ OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 },
{ OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 },
@@ -884,8 +886,6 @@ static int ov7xx0_configure(struct sd *sd)
/* Almost all of these are magic "reserved" values. */
{ OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b },
{ 0x16, 0x02 },
-/* jfm */
-/* { OV7670_REG_MVFP, 0x07|OV7670_MVFP_MIRROR }, */
{ OV7670_REG_MVFP, 0x07 },
{ 0x21, 0x02 }, { 0x22, 0x91 },
{ 0x29, 0x07 }, { 0x33, 0x0b },
@@ -930,7 +930,10 @@ static int ov7xx0_configure(struct sd *sd)
{ OV7670_REG_EDGE, 0 },
{ 0x75, 0x05 }, { 0x76, 0xe1 },
{ 0x4c, 0 }, { 0x77, 0x01 },
- { OV7670_REG_COM13, 0xc3 }, { 0x4b, 0x09 },
+ { OV7670_REG_COM13, OV7670_COM13_GAMMA
+ | OV7670_COM13_UVSAT
+ | 2}, /* was 3 */
+ { 0x4b, 0x09 },
{ 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 },
{ 0x56, 0x40 },
@@ -956,30 +959,10 @@ static int ov7xx0_configure(struct sd *sd)
{ 0x79, 0x03 }, { 0xc8, 0x40 },
{ 0x79, 0x05 }, { 0xc8, 0x30 },
{ 0x79, 0x26 },
-
- /* Format YUV422 */
- { OV7670_REG_COM7, OV7670_COM7_YUV }, /* Selects YUV mode */
- { OV7670_REG_RGB444, 0 }, /* No RGB444 please */
- { OV7670_REG_COM1, 0 },
- { OV7670_REG_COM15, OV7670_COM15_R00FF },
- { OV7670_REG_COM9, 0x18 },
- /* 4x gain ceiling; 0x8 is reserved bit */
- { 0x4f, 0x80 }, /* "matrix coefficient 1" */
- { 0x50, 0x80 }, /* "matrix coefficient 2" */
- { 0x52, 0x22 }, /* "matrix coefficient 4" */
- { 0x53, 0x5e }, /* "matrix coefficient 5" */
- { 0x54, 0x80 }, /* "matrix coefficient 6" */
- { OV7670_REG_COM13, OV7670_COM13_GAMMA|OV7670_COM13_UVSAT },
-};
+ };
PDEBUG(D_PROBE, "starting OV7xx0 configuration");
-/* jfm:already done? */
- if (init_ov_sensor(sd) < 0)
- PDEBUG(D_ERR, "Failed to read sensor ID");
- else
- PDEBUG(D_PROBE, "OV7xx0 initialized");
-
/* Detect sensor (sub)type */
rc = i2c_r(sd, OV7610_REG_COM_I);
@@ -1025,20 +1008,25 @@ static int ov7xx0_configure(struct sd *sd)
return low;
}
if (high == 0x76) {
- if (low == 0x30) {
+ switch (low) {
+ case 0x30:
PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
sd->sensor = SEN_OV7630;
- } else if (low == 0x40) {
+ break;
+ case 0x40:
PDEBUG(D_PROBE, "Sensor is an OV7645");
sd->sensor = SEN_OV7640; /* FIXME */
- } else if (low == 0x45) {
+ break;
+ case 0x45:
PDEBUG(D_PROBE, "Sensor is an OV7645B");
sd->sensor = SEN_OV7640; /* FIXME */
- } else if (low == 0x48) {
+ break;
+ case 0x48:
PDEBUG(D_PROBE, "Sensor is an OV7648");
sd->sensor = SEN_OV7640; /* FIXME */
- } else {
- PDEBUG(D_PROBE, "Unknown sensor: 0x76%X", low);
+ break;
+ default:
+ PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
return -1;
}
} else {
@@ -1050,34 +1038,34 @@ static int ov7xx0_configure(struct sd *sd)
return -1;
}
- if (sd->sensor == SEN_OV7620) {
+ switch (sd->sensor) {
+ case SEN_OV7620:
PDEBUG(D_PROBE, "Writing 7620 registers");
- if (write_i2c_regvals(sd, norm_7620,
- sizeof norm_7620 / sizeof norm_7620[0]))
+ if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
return -1;
- } else if (sd->sensor == SEN_OV7630) {
+ break;
+ case SEN_OV7630:
PDEBUG(D_ERR, "7630 is not supported by this driver version");
return -1;
- } else if (sd->sensor == SEN_OV7640) {
+ case SEN_OV7640:
PDEBUG(D_PROBE, "Writing 7640 registers");
- if (write_i2c_regvals(sd, norm_7640,
- sizeof norm_7640 / sizeof norm_7640[0]))
+ if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
return -1;
- } else if (sd->sensor == SEN_OV7670) {
+ break;
+ case SEN_OV7670:
PDEBUG(D_PROBE, "Writing 7670 registers");
- if (write_i2c_regvals(sd, norm_7670,
- sizeof norm_7670 / sizeof norm_7670[0]))
+ if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
return -1;
- } else {
+ break;
+ default:
PDEBUG(D_PROBE, "Writing 7610 registers");
- if (write_i2c_regvals(sd, norm_7610,
- sizeof norm_7610 / sizeof norm_7610[0]))
+ if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
return -1;
+ break;
}
/* Set sensor-specific vars */
- sd->maxwidth = 640;
- sd->maxheight = 480;
+/* sd->sif = 0; already done */
return 0;
}
@@ -1231,43 +1219,45 @@ static int ov6xx0_configure(struct sd *sd)
/* Ugh. The first two bits are the version bits, but
* the entire register value must be used. I guess OVT
* underestimated how many variants they would make. */
- if (rc == 0x00) {
+ switch (rc) {
+ case 0x00:
sd->sensor = SEN_OV6630;
PDEBUG(D_ERR,
"WARNING: Sensor is an OV66308. Your camera may have");
PDEBUG(D_ERR, "been misdetected in previous driver versions.");
- } else if (rc == 0x01) {
+ break;
+ case 0x01:
sd->sensor = SEN_OV6620;
- PDEBUG(D_PROBE, "Sensor is an OV6620");
- } else if (rc == 0x02) {
+ break;
+ case 0x02:
sd->sensor = SEN_OV6630;
PDEBUG(D_PROBE, "Sensor is an OV66308AE");
- } else if (rc == 0x03) {
+ break;
+ case 0x03:
sd->sensor = SEN_OV6630;
PDEBUG(D_PROBE, "Sensor is an OV66308AF");
- } else if (rc == 0x90) {
+ break;
+ case 0x90:
sd->sensor = SEN_OV6630;
PDEBUG(D_ERR,
"WARNING: Sensor is an OV66307. Your camera may have");
PDEBUG(D_ERR, "been misdetected in previous driver versions.");
- } else {
+ break;
+ default:
PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc);
return -1;
}
/* Set sensor-specific vars */
- sd->maxwidth = 352;
- sd->maxheight = 288;
+ sd->sif = 1;
if (sd->sensor == SEN_OV6620) {
PDEBUG(D_PROBE, "Writing 6x20 registers");
- if (write_i2c_regvals(sd, norm_6x20,
- sizeof norm_6x20 / sizeof norm_6x20[0]))
+ if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
return -1;
} else {
PDEBUG(D_PROBE, "Writing 6x30 registers");
- if (write_i2c_regvals(sd, norm_6x30,
- sizeof norm_6x30 / sizeof norm_6x30[0]))
+ if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
return -1;
}
return 0;
@@ -1276,14 +1266,8 @@ static int ov6xx0_configure(struct sd *sd)
/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
static void ov51x_led_control(struct sd *sd, int on)
{
- PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off");
-
-/* if (sd->bridge == BRG_OV511PLUS) */
-/* reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); */
-/* else if (sd->bridge == BRG_OV519) */
- reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
-/* else if (sd->bclass == BCL_OV518) */
-/* reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); */
+/* PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); */
+ reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
}
/* this function is called at probe time */
@@ -1293,11 +1277,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
-/* (from ov519_configure) */
static const struct ov_regvals init_519[] = {
{ 0x5a, 0x6d }, /* EnableSystem */
-/* jfm trace usbsnoop3-1.txt */
-/* jfm 53 = fb */
{ 0x53, 0x9b },
{ 0x54, 0xff }, /* set bit2 to enable jpeg */
{ 0x5d, 0x03 },
@@ -1314,9 +1295,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
if (write_regvals(sd, init_519, ARRAY_SIZE(init_519)))
goto error;
-/* jfm: not seen in windows trace */
- if (ov519_init_compression(sd))
- goto error;
ov51x_led_control(sd, 0); /* turn LED off */
/* Test for 76xx */
@@ -1365,16 +1343,18 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
cam->epaddr = OV511_ENDPOINT_ADDRESS;
- if (sd->maxwidth == 640) {
+ if (!sd->sif) {
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
} else {
cam->cam_mode = sif_mode;
- cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
+ cam->nmodes = ARRAY_SIZE(sif_mode);
}
- sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
- sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
- sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
+ sd->brightness = BRIGHTNESS_DEF;
+ sd->contrast = CONTRAST_DEF;
+ sd->colors = COLOR_DEF;
+ sd->hflip = HFLIP_DEF;
+ sd->vflip = VFLIP_DEF;
return 0;
error:
PDEBUG(D_ERR, "OV519 Config failed");
@@ -1394,8 +1374,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
*
* Do not put any sensor-specific code in here (including I2C I/O functions)
*/
-static int ov519_mode_init_regs(struct sd *sd,
- int width, int height)
+static int ov519_mode_init_regs(struct sd *sd)
{
static const struct ov_regvals mode_init_519_ov7670[] = {
{ 0x5d, 0x03 }, /* Turn off suspend mode */
@@ -1441,36 +1420,23 @@ static int ov519_mode_init_regs(struct sd *sd,
/* windows reads 0x55 at this point, why? */
};
-/* int hi_res; */
-
- PDEBUG(D_CONF, "mode init %dx%d", width, height);
-
-/* if (width >= 800 && height >= 600)
- hi_res = 1;
- else
- hi_res = 0; */
-
-/* if (ov51x_stop(sd) < 0)
- return -EIO; */
-
/******** Set the mode ********/
if (sd->sensor != SEN_OV7670) {
if (write_regvals(sd, mode_init_519,
ARRAY_SIZE(mode_init_519)))
return -EIO;
+ if (sd->sensor == SEN_OV7640) {
+ /* Select 8-bit input mode */
+ reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10);
+ }
} else {
if (write_regvals(sd, mode_init_519_ov7670,
ARRAY_SIZE(mode_init_519_ov7670)))
return -EIO;
}
- if (sd->sensor == SEN_OV7640) {
- /* Select 8-bit input mode */
- reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10);
- }
-
- reg_w(sd, OV519_CAM_H_SIZE, width >> 4);
- reg_w(sd, OV519_CAM_V_SIZE, height >> 3);
+ reg_w(sd, OV519_CAM_H_SIZE, sd->gspca_dev.width >> 4);
+ reg_w(sd, OV519_CAM_V_SIZE, sd->gspca_dev.height >> 3);
reg_w(sd, OV519_CAM_X_OFFSETL, 0x00);
reg_w(sd, OV519_CAM_X_OFFSETH, 0x00);
reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00);
@@ -1485,9 +1451,10 @@ static int ov519_mode_init_regs(struct sd *sd,
/* FIXME: These are only valid at the max resolution. */
sd->clockdiv = 0;
- if (sd->sensor == SEN_OV7640) {
+ switch (sd->sensor) {
+ case SEN_OV7640:
switch (sd->frame_rate) {
-/*jfm: default was 30 fps */
+/*fixme: default was 30 fps */
case 30:
reg_w(sd, 0xa4, 0x0c);
reg_w(sd, 0x23, 0xff);
@@ -1517,7 +1484,8 @@ static int ov519_mode_init_regs(struct sd *sd,
sd->clockdiv = 1;
break;
}
- } else if (sd->sensor == SEN_OV8610) {
+ break;
+ case SEN_OV8610:
switch (sd->frame_rate) {
default: /* 15 fps */
/* case 15: */
@@ -1533,41 +1501,37 @@ static int ov519_mode_init_regs(struct sd *sd,
reg_w(sd, 0x23, 0x1b);
break;
}
- sd->clockdiv = 0;
- } else if (sd->sensor == SEN_OV7670) { /* guesses, based on 7640 */
+ break;
+ case SEN_OV7670: /* guesses, based on 7640 */
PDEBUG(D_STREAM, "Setting framerate to %d fps",
(sd->frame_rate == 0) ? 15 : sd->frame_rate);
+ reg_w(sd, 0xa4, 0x10);
switch (sd->frame_rate) {
case 30:
- reg_w(sd, 0xa4, 0x10);
reg_w(sd, 0x23, 0xff);
break;
case 20:
- reg_w(sd, 0xa4, 0x10);
reg_w(sd, 0x23, 0x1b);
break;
- default: /* 15 fps */
-/* case 15: */
- reg_w(sd, 0xa4, 0x10);
+ default:
+/* case 15: */
reg_w(sd, 0x23, 0xff);
sd->clockdiv = 1;
break;
}
+ break;
}
-/* if (ov51x_restart(sd) < 0)
- return -EIO; */
-
- /* Reset it just for good measure */
-/* if (ov51x_reset(sd, OV511_RESET_NOREGS) < 0)
- return -EIO; */
return 0;
}
-static int mode_init_ov_sensor_regs(struct sd *sd,
- struct ovsensor_window *win)
+static int mode_init_ov_sensor_regs(struct sd *sd)
{
- int qvga = win->quarter;
+ struct gspca_dev *gspca_dev;
+ int qvga;
+
+ gspca_dev = &sd->gspca_dev;
+ qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
/******** Mode (VGA/QVGA) and sensor specific regs ********/
switch (sd->sensor) {
@@ -1611,8 +1575,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
OV7670_COM7_FMT_MASK);
break;
case SEN_OV6620:
- i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
- break;
case SEN_OV6630:
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
break;
@@ -1621,24 +1583,21 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
}
/******** Palette-specific regs ********/
-/* Need to do work here for the OV7670 */
-
- if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
- /* not valid on the OV6620/OV7620/6630? */
- i2c_w_mask(sd, 0x0e, 0x00, 0x40);
- }
+ if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
+ /* not valid on the OV6620/OV7620/6630? */
+ i2c_w_mask(sd, 0x0e, 0x00, 0x40);
+ }
- /* The OV518 needs special treatment. Although both the OV518
- * and the OV6630 support a 16-bit video bus, only the 8 bit Y
- * bus is actually used. The UV bus is tied to ground.
- * Therefore, the OV6630 needs to be in 8-bit multiplexed
- * output mode */
+ /* The OV518 needs special treatment. Although both the OV518
+ * and the OV6630 support a 16-bit video bus, only the 8 bit Y
+ * bus is actually used. The UV bus is tied to ground.
+ * Therefore, the OV6630 needs to be in 8-bit multiplexed
+ * output mode */
- /* OV7640 is 8-bit only */
+ /* OV7640 is 8-bit only */
- if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)
- i2c_w_mask(sd, 0x13, 0x00, 0x20);
-/* } */
+ if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)
+ i2c_w_mask(sd, 0x13, 0x00, 0x20);
/******** Clock programming ********/
/* The OV6620 needs special handling. This prevents the
@@ -1647,14 +1606,14 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
/* Clock down */
i2c_w(sd, 0x2a, 0x04);
- i2c_w(sd, 0x11, win->clockdiv);
+ i2c_w(sd, 0x11, sd->clockdiv);
i2c_w(sd, 0x2a, 0x84);
/* This next setting is critical. It seems to improve
* the gain or the contrast. The "reserved" bits seem
* to have some effect in this case. */
i2c_w(sd, 0x2d, 0x85);
- } else if (win->clockdiv >= 0) {
- i2c_w(sd, 0x11, win->clockdiv);
+ } else if (sd->clockdiv >= 0) {
+ i2c_w(sd, 0x11, sd->clockdiv);
}
/******** Special Features ********/
@@ -1674,7 +1633,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
/* is fully tested. */
/* 7620/6620/6630? don't have register 0x35, so play it safe */
if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
- if (win->width == 640 /*&& win->height == 480*/)
+ if (!qvga)
i2c_w(sd, 0x35, 0x9e);
else
i2c_w(sd, 0x35, 0x1e);
@@ -1682,13 +1641,31 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
return 0;
}
-static int set_ov_sensor_window(struct sd *sd,
- struct ovsensor_window *win)
+static void sethvflip(struct sd *sd)
{
+ if (sd->sensor != SEN_OV7670)
+ return;
+ if (sd->gspca_dev.streaming)
+ ov51x_stop(sd);
+ i2c_w_mask(sd, OV7670_REG_MVFP,
+ OV7670_MVFP_MIRROR * sd->hflip
+ | OV7670_MVFP_VFLIP * sd->vflip,
+ OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
+ if (sd->gspca_dev.streaming)
+ ov51x_restart(sd);
+}
+
+static int set_ov_sensor_window(struct sd *sd)
+{
+ struct gspca_dev *gspca_dev;
+ int qvga;
int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
int ret, hstart, hstop, vstop, vstart;
__u8 v;
+ gspca_dev = &sd->gspca_dev;
+ qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+
/* The different sensor ICs handle setting up of window differently.
* IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
switch (sd->sensor) {
@@ -1733,7 +1710,7 @@ static int set_ov_sensor_window(struct sd *sd,
switch (sd->sensor) {
case SEN_OV6620:
case SEN_OV6630:
- if (win->quarter) { /* QCIF */
+ if (qvga) { /* QCIF */
hwscale = 0;
vwscale = 0;
} else { /* CIF */
@@ -1743,7 +1720,7 @@ static int set_ov_sensor_window(struct sd *sd,
}
break;
case SEN_OV8610:
- if (win->quarter) { /* QSVGA */
+ if (qvga) { /* QSVGA */
hwscale = 1;
vwscale = 1;
} else { /* SVGA */
@@ -1752,7 +1729,7 @@ static int set_ov_sensor_window(struct sd *sd,
}
break;
default: /* SEN_OV7xx0 */
- if (win->quarter) { /* QVGA */
+ if (qvga) { /* QVGA */
hwscale = 1;
vwscale = 0;
} else { /* VGA */
@@ -1761,7 +1738,7 @@ static int set_ov_sensor_window(struct sd *sd,
}
}
- ret = mode_init_ov_sensor_regs(sd, win);
+ ret = mode_init_ov_sensor_regs(sd);
if (ret < 0)
return ret;
@@ -1782,7 +1759,7 @@ static int set_ov_sensor_window(struct sd *sd,
/* I can hard code this for OV7670s */
/* Yes, these numbers do look odd, but they're tested and work! */
if (sd->sensor == SEN_OV7670) {
- if (win->quarter) { /* QVGA from ov7670.c by
+ if (qvga) { /* QVGA from ov7670.c by
* Jonathan Corbet */
hstart = 164;
hstop = 20;
@@ -1796,75 +1773,45 @@ static int set_ov_sensor_window(struct sd *sd,
}
/* OV7670 hardware window registers are split across
* multiple locations */
- i2c_w(sd, OV7670_REG_HSTART, (hstart >> 3) & 0xff);
- i2c_w(sd, OV7670_REG_HSTOP, (hstop >> 3) & 0xff);
+ i2c_w(sd, OV7670_REG_HSTART, hstart >> 3);
+ i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3);
v = i2c_r(sd, OV7670_REG_HREF);
v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07);
msleep(10); /* need to sleep between read and write to
* same reg! */
i2c_w(sd, OV7670_REG_HREF, v);
- i2c_w(sd, OV7670_REG_VSTART, (vstart >> 2) & 0xff);
- i2c_w(sd, OV7670_REG_VSTOP, (vstop >> 2) & 0xff);
+ i2c_w(sd, OV7670_REG_VSTART, vstart >> 2);
+ i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2);
v = i2c_r(sd, OV7670_REG_VREF);
v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03);
msleep(10); /* need to sleep between read and write to
* same reg! */
i2c_w(sd, OV7670_REG_VREF, v);
-
+ sethvflip(sd);
} else {
- i2c_w(sd, 0x17, hwsbase + (win->x >> hwscale));
- i2c_w(sd, 0x18, hwebase + ((win->x + win->width) >> hwscale));
- i2c_w(sd, 0x19, vwsbase + (win->y >> vwscale));
- i2c_w(sd, 0x1a, vwebase + ((win->y + win->height) >> vwscale));
+ i2c_w(sd, 0x17, hwsbase);
+ i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale));
+ i2c_w(sd, 0x19, vwsbase);
+ i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale));
}
return 0;
}
-static int ov_sensor_mode_setup(struct sd *sd,
- int width, int height)
-{
- struct ovsensor_window win;
-
-/* win.format = mode; */
-
- /* Unless subcapture is enabled,
- * center the image window and downsample
- * if possible to increase the field of view */
- /* NOTE: OV518(+) and OV519 does downsampling on its own */
- win.width = width;
- win.height = height;
- if (width == sd->maxwidth)
- win.quarter = 0;
- else
- win.quarter = 1;
-
- /* Center it */
- win.x = (win.width - width) / 2;
- win.y = (win.height - height) / 2;
-
- /* Clock is determined by OV519 frame rate code */
- win.clockdiv = sd->clockdiv;
-
- PDEBUG(D_CONF, "Setting clock divider to %d", win.clockdiv);
- return set_ov_sensor_window(sd, &win);
-}
-
/* -- start the camera -- */
static void sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret;
-
- ret = ov519_mode_init_regs(sd, gspca_dev->width, gspca_dev->height);
+ ret = ov519_mode_init_regs(sd);
if (ret < 0)
goto out;
- ret = ov_sensor_mode_setup(sd, gspca_dev->width, gspca_dev->height);
+ ret = set_ov_sensor_window(sd);
if (ret < 0)
goto out;
- ret = ov51x_restart((struct sd *) gspca_dev);
+ ret = ov51x_restart(sd);
if (ret < 0)
goto out;
PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
@@ -1938,12 +1885,10 @@ static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int val;
-/* int was_streaming; */
val = sd->brightness;
PDEBUG(D_CONF, "brightness:%d", val);
-/* was_streaming = gspca_dev->streaming;
- * if (was_streaming)
+/* if (gspca_dev->streaming)
* ov51x_stop(sd); */
switch (sd->sensor) {
case SEN_OV8610:
@@ -1961,12 +1906,12 @@ static void setbrightness(struct gspca_dev *gspca_dev)
i2c_w(sd, OV7610_REG_BRT, val);
break;
case SEN_OV7670:
-/*jfm - from windblows
+/*win trace
* i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */
i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
break;
}
-/* if (was_streaming)
+/* if (gspca_dev->streaming)
* ov51x_restart(sd); */
}
@@ -1974,12 +1919,10 @@ static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int val;
-/* int was_streaming; */
val = sd->contrast;
PDEBUG(D_CONF, "contrast:%d", val);
-/* was_streaming = gspca_dev->streaming;
- if (was_streaming)
+/* if (gspca_dev->streaming)
ov51x_stop(sd); */
switch (sd->sensor) {
case SEN_OV7610:
@@ -2016,7 +1959,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
break;
}
-/* if (was_streaming)
+/* if (gspca_dev->streaming)
ov51x_restart(sd); */
}
@@ -2024,12 +1967,10 @@ static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int val;
-/* int was_streaming; */
val = sd->colors;
PDEBUG(D_CONF, "saturation:%d", val);
-/* was_streaming = gspca_dev->streaming;
- if (was_streaming)
+/* if (gspca_dev->streaming)
ov51x_stop(sd); */
switch (sd->sensor) {
case SEN_OV8610:
@@ -2055,7 +1996,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
/* set REG_COM13 values for UV sat auto mode */
break;
}
-/* if (was_streaming)
+/* if (gspca_dev->streaming)
ov51x_restart(sd); */
}
@@ -2110,6 +2051,40 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->hflip = val;
+ sethvflip(sd);
+ return 0;
+}
+
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->hflip;
+ return 0;
+}
+
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->vflip = val;
+ sethvflip(sd);
+ return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->vflip;
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -2178,4 +2153,3 @@ module_exit(sd_mod_exit);
module_param(frame_rate, int, 0644);
MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
-
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index ea3d7021f401..815bea6edc44 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -31,7 +31,9 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- int avg_lum;
+ int lum_sum;
+ atomic_t avg_lum;
+ atomic_t do_gain;
unsigned char brightness;
unsigned char contrast;
@@ -271,6 +273,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->contrast = CONTRAST_DEF;
sd->colors = COLOR_DEF;
sd->autogain = AUTOGAIN_DEF;
+ sd->ag_cnt = -1;
return 0;
}
@@ -311,6 +314,18 @@ static void setcolors(struct gspca_dev *gspca_dev)
PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
}
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->autogain) {
+ sd->lum_sum = 0;
+ sd->ag_cnt = AG_CNT_START;
+ } else {
+ sd->ag_cnt = -1;
+ }
+}
+
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
@@ -320,8 +335,6 @@ static int sd_open(struct gspca_dev *gspca_dev)
static void sd_start(struct gspca_dev *gspca_dev)
{
- struct sd *sd = (struct sd *) gspca_dev;
-
reg_w(gspca_dev, 0xff, 0x01);
reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
@@ -394,6 +407,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
setcontrast(gspca_dev);
setbrightness(gspca_dev);
setcolors(gspca_dev);
+ setautogain(gspca_dev);
/* set correct resolution */
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
@@ -431,13 +445,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x04);
reg_w(gspca_dev, 0x78, 0x05);
-
- if (sd->autogain) {
- sd->ag_cnt = AG_CNT_START;
- sd->avg_lum = 0;
- } else {
- sd->ag_cnt = -1;
- }
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -473,13 +480,20 @@ static void sd_close(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
}
-static void setautogain(struct gspca_dev *gspca_dev, int luma)
+static void do_autogain(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int luma;
int luma_mean = 128;
int luma_delta = 20;
__u8 spring = 5;
int Gbright;
+ if (!atomic_read(&sd->do_gain))
+ return;
+ atomic_set(&sd->do_gain, 0);
+
+ luma = atomic_read(&sd->avg_lum);
Gbright = reg_r(gspca_dev, 0x02);
PDEBUG(D_FRAM, "luma mean %d", luma);
if (luma < luma_mean - luma_delta ||
@@ -523,12 +537,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* start of frame */
if (sd->ag_cnt >= 0 && p > 28) {
- sd->avg_lum += data[p - 23];
+ sd->lum_sum += data[p - 23];
if (--sd->ag_cnt < 0) {
sd->ag_cnt = AG_CNT_START;
- setautogain(gspca_dev,
- sd->avg_lum / AG_CNT_START);
- sd->avg_lum = 0;
+ atomic_set(&sd->avg_lum,
+ sd->lum_sum / AG_CNT_START);
+ sd->lum_sum = 0;
+ atomic_set(&sd->do_gain, 1);
}
}
@@ -677,12 +692,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
- if (val) {
- sd->ag_cnt = AG_CNT_START;
- sd->avg_lum = 0;
- } else {
- sd->ag_cnt = -1;
- }
+ if (gspca_dev->streaming)
+ setautogain(gspca_dev);
return 0;
}
@@ -706,6 +717,7 @@ static struct sd_desc sd_desc = {
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
+ .dq_callback = do_autogain,
};
/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index e18748c5a14d..11210c71f66c 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -408,7 +408,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
const __u8 *buffer,
int len)
{
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
return;
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index 33a3df1f6915..245a30ec5fb1 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -32,7 +32,7 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- int avg_lum;
+ atomic_t avg_lum;
unsigned int exposure;
unsigned short brightness;
@@ -148,55 +148,58 @@ static struct v4l2_pix_format vga_mode[] = {
/*Data from sn9c102p+hv71331r */
static const __u8 sn_hv7131[] = {
-/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
- 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
-/* rega regb regc regd rege regf reg10 reg11 */
- 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
-/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
- 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
-/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
+ 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
+/* reg8 reg9 rega regb regc regd rege regf */
+ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
+ 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
+/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const __u8 sn_mi0360[] = {
-/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
- 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
-/* rega regb regc regd rege regf reg10 reg11 */
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
-/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
- 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
-/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
+ 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
+/* reg8 reg9 rega regb regc regd rege regf */
+ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
+ 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
+/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const __u8 sn_mo4000[] = {
-/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
- 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
-/* reg9 rega regb regc regd rege regf reg10 reg11*/
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
-/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
- 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
-/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
- 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
- 0xd3, 0xdf, 0xea, 0xf5
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
+ 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
+/* reg8 reg9 rega regb regc regd rege regf */
+ 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
+ 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
+/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const __u8 sn_ov7648[] = {
- 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
- 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
+ 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
+/* reg8 reg9 rega regb regc regd rege regf */
+ 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
+ 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
+/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const __u8 sn_ov7660[] = {
-/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
- 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
-/* reg9 rega regb regc regd rege regf reg10 reg11*/
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
-/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
- 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
-/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
+ 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
+/* reg8 reg9 rega regb regc regd rege regf */
+ 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
+ 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
+/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* sequence specific to the sensors - !! index = SENSOR_xxx */
@@ -212,10 +215,6 @@ static const __u8 regsn20[] = {
0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
};
-static const __u8 regsn20_sn9c120[] = {
- 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
- 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
-};
static const __u8 regsn20_sn9c325[] = {
0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
@@ -227,21 +226,6 @@ static const __u8 reg84[] = {
/* 0x00, 0x00, 0x00, 0x00, 0x00 */
0xf7, 0x0f, 0x0a, 0x00, 0x00
};
-static const __u8 reg84_sn9c120_1[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x0c, 0x00, 0x00
-};
-static const __u8 reg84_sn9c120_2[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x0c, 0x02, 0x3b
-};
-static const __u8 reg84_sn9c120_3[] = {
- 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
- 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
- 0xf5, 0x0f, 0x0c, 0x02, 0x3b
-};
static const __u8 reg84_sn9c325[] = {
0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
@@ -360,17 +344,15 @@ static const __u8 ov7660_sensor_init[][8] = {
{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
/* (delay 20ms) */
{0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
- /* Outformat ?? rawRGB */
+ /* Outformat = rawRGB */
{0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
- {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
-/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
+ {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
/* GAIN BLUE RED VREF */
{0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
/* COM 1 BAVE GEAVE AECHH */
{0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
{0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
- {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
-/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
+ {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
/* AECH CLKRC COM7 COM8 */
{0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
{0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
@@ -379,8 +361,8 @@ static const __u8 ov7660_sensor_init[][8] = {
{0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
{0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
/* BOS GBOS GROS ROS (BGGR offset) */
- {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
-/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
+/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
+ {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
/* AEW AEB VPT BBIAS */
{0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
/* GbBIAS RSVD EXHCH EXHCL */
@@ -407,9 +389,9 @@ static const __u8 ov7660_sensor_init[][8] = {
{0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
/* LCC1 LCC2 LCC3 LCC4 */
{0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
- {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
+ {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
{0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
- /* band gap reference [0..3] DBLV */
+ /* band gap reference [0:3] DBLV */
{0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
{0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
{0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
@@ -419,37 +401,35 @@ static const __u8 ov7660_sensor_init[][8] = {
{0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
- {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
/****** (some exchanges in the win trace) ******/
- {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
/* bits[3..0]reserved */
{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
/* VREF vertical frame ctrl */
{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
- {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
-/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
- {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
- {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
+ {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
+ {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
+ {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
+/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
/****** (some exchanges in the win trace) ******/
{0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
- {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
- {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
+ {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
+ {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
+/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
/****** (some exchanges in the win trace) ******/
-/**********startsensor KO if changed !!****/
+/******!! startsensor KO if changed !!****/
{0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
-/* here may start the isoc exchanges */
{}
};
-/* reg0x04 reg0x07 reg 0x10 */
-/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
+/* reg 0x04 reg 0x07 reg 0x10 */
+/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
static const __u8 ov7648_sensor_init[][8] = {
{0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
@@ -680,13 +660,12 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
const __u8 *reg9a;
static const __u8 reg9a_def[] =
{0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
- static const __u8 reg9a_sn9c120[] = /* from win trace */
- {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
static const __u8 reg9a_sn9c325[] =
{0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
+ static const __u8 regd4[] = {0x60, 0x00, 0x00};
reg_w1(gspca_dev, 0xf1, 0x00);
- reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
+ reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
/* configure gpio */
reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
@@ -696,25 +675,17 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
case BRIDGE_SN9C325:
reg9a = reg9a_sn9c325;
break;
- case BRIDGE_SN9C120:
- reg9a = reg9a_sn9c120;
- break;
default:
reg9a = reg9a_def;
break;
}
reg_w(gspca_dev, 0x9a, reg9a, 6);
- reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
+ reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
switch (sd->bridge) {
- case BRIDGE_SN9C120: /* from win trace */
- reg_w1(gspca_dev, 0x01, 0x61);
- reg_w1(gspca_dev, 0x17, 0x20);
- reg_w1(gspca_dev, 0x01, 0x60);
- break;
case BRIDGE_SN9C325:
reg_w1(gspca_dev, 0x01, 0x43);
reg_w1(gspca_dev, 0x17, 0xae);
@@ -810,6 +781,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->contrast = CONTRAST_DEF;
sd->colors = COLOR_DEF;
sd->autogain = AUTOGAIN_DEF;
+ sd->ag_cnt = -1;
+
return 0;
}
@@ -823,10 +796,11 @@ static int sd_open(struct gspca_dev *gspca_dev)
/* setup a selector by bridge */
reg_w1(gspca_dev, 0xf1, 0x01);
- reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
- reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
reg_r(gspca_dev, 0x00, 1);
+ reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
+ reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
regF1 = gspca_dev->usb_buf[0];
+ PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
switch (sd->bridge) {
case BRIDGE_SN9C102P:
if (regF1 != 0x11)
@@ -937,15 +911,10 @@ static void setbrightness(struct gspca_dev *gspca_dev)
sd->exposure = setexposure(gspca_dev, expo);
break;
case SENSOR_MI0360:
- expo = sd->brightness >> 4;
- sd->exposure = setexposure(gspca_dev, expo);
- break;
case SENSOR_MO4000:
expo = sd->brightness >> 4;
sd->exposure = setexposure(gspca_dev, expo);
break;
- case SENSOR_OV7660:
- return; /*jfm??*/
}
k2 = sd->brightness >> 10;
@@ -958,8 +927,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
__u8 k2;
__u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
- if (sd->sensor == SENSOR_OV7660)
- return; /*jfm??*/
k2 = sd->contrast;
contrast[2] = k2;
contrast[0] = (k2 + 1) >> 1;
@@ -981,20 +948,32 @@ static void setcolors(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x05, data);
}
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ switch (sd->sensor) {
+ case SENSOR_HV7131R:
+ case SENSOR_MO4000:
+ case SENSOR_MI0360:
+ if (sd->autogain)
+ sd->ag_cnt = AG_CNT_START;
+ else
+ sd->ag_cnt = -1;
+ break;
+ }
+}
+
/* -- start the camera -- */
static void sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
- __u8 data;
- __u8 reg1;
- __u8 reg17;
+ __u8 reg1, reg17, reg18;
const __u8 *sn9c1xx;
int mode;
static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
- static const __u8 CA_sn9c120[] =
- { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
static const __u8 CE_sn9c325[] =
{ 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
@@ -1002,9 +981,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
sn9c1xx = sn_tb[(int) sd->sensor];
configure_gpio(gspca_dev, sn9c1xx);
-/*fixme:jfm this sequence should appear at end of sd_start */
-/* with
- reg_w1(gspca_dev, 0x01, 0x44); */
+/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
@@ -1016,20 +993,16 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0xc7, 0x00);
reg_w1(gspca_dev, 0xc8, 0x50);
reg_w1(gspca_dev, 0xc9, 0x3c);
-/*fixme:jfm end of ending sequence */
reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
switch (sd->bridge) {
case BRIDGE_SN9C325:
- data = 0xae;
- break;
- case BRIDGE_SN9C120:
- data = 0xa0;
+ reg17 = 0xae;
break;
default:
- data = 0x60;
+ reg17 = 0x60;
break;
}
- reg_w1(gspca_dev, 0x17, data);
+ reg_w1(gspca_dev, 0x17, reg17);
reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
@@ -1044,20 +1017,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x9a, 0x0a);
reg_w1(gspca_dev, 0x99, 0x60);
break;
- case BRIDGE_SN9C120:
- reg_w(gspca_dev, 0x20, regsn20_sn9c120,
- sizeof regsn20_sn9c120);
- for (i = 0; i < 2; i++)
- reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
- sizeof reg84_sn9c120_1);
- for (i = 0; i < 6; i++)
- reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
- sizeof reg84_sn9c120_2);
- reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
- sizeof reg84_sn9c120_3);
- reg_w1(gspca_dev, 0x9a, 0x05);
- reg_w1(gspca_dev, 0x99, 0x5b);
- break;
default:
reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
for (i = 0; i < 8; i++)
@@ -1107,22 +1066,14 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* reg1 = 0x44; */
/* reg1 = 0x46; (done) */
} else {
- reg17 = 0xa2; /* 640 */
- reg1 = 0x40;
+ reg17 = 0x22; /* 640 MCKSIZE */
+ reg1 = 0x06;
}
break;
}
reg_w(gspca_dev, 0xc0, C0, 6);
+ reg_w(gspca_dev, 0xca, CA, 4);
switch (sd->bridge) {
- case BRIDGE_SN9C120: /*jfm ?? */
- reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
- break;
- default:
- reg_w(gspca_dev, 0xca, CA, 4);
- break;
- }
- switch (sd->bridge) {
- case BRIDGE_SN9C120: /*jfm ?? */
case BRIDGE_SN9C325:
reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
break;
@@ -1133,19 +1084,19 @@ static void sd_start(struct gspca_dev *gspca_dev)
}
/* here change size mode 0 -> VGA; 1 -> CIF */
- data = 0x40 | sn9c1xx[0x18] | (mode << 4);
- reg_w1(gspca_dev, 0x18, data);
+ reg18 = sn9c1xx[0x18] | (mode << 4);
+ reg_w1(gspca_dev, 0x18, reg18 | 0x40);
reg_w(gspca_dev, 0x100, qtable4, 0x40);
reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
- data = sn9c1xx[0x18] | (mode << 4);
- reg_w1(gspca_dev, 0x18, data);
+ reg_w1(gspca_dev, 0x18, reg18);
reg_w1(gspca_dev, 0x17, reg17);
reg_w1(gspca_dev, 0x01, reg1);
setbrightness(gspca_dev);
setcontrast(gspca_dev);
+ setautogain(gspca_dev);
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1168,12 +1119,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
i2c_w8(gspca_dev, stopmi0360);
data = 0x29;
break;
- case SENSOR_MO4000:
- break;
case SENSOR_OV7648:
data = 0x29;
break;
default:
+/* case SENSOR_MO4000: */
/* case SENSOR_OV7660: */
break;
}
@@ -1193,16 +1143,23 @@ static void sd_close(struct gspca_dev *gspca_dev)
{
}
-static void setautogain(struct gspca_dev *gspca_dev)
+static void do_autogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- /* Thanks S., without your advice, autobright should not work :) */
int delta;
- int expotimes = 0;
+ int expotimes;
__u8 luma_mean = 130;
__u8 luma_delta = 20;
- delta = sd->avg_lum;
+ /* Thanks S., without your advice, autobright should not work :) */
+ if (sd->ag_cnt < 0)
+ return;
+ if (--sd->ag_cnt >= 0)
+ return;
+ sd->ag_cnt = AG_CNT_START;
+
+ delta = atomic_read(&sd->avg_lum);
+ PDEBUG(D_FRAM, "mean lum %d", delta);
if (delta < luma_mean - luma_delta ||
delta > luma_mean + luma_delta) {
switch (sd->sensor) {
@@ -1214,8 +1171,9 @@ static void setautogain(struct gspca_dev *gspca_dev)
sd->exposure = setexposure(gspca_dev,
(unsigned int) (expotimes << 8));
break;
- case SENSOR_MO4000:
- case SENSOR_MI0360:
+ default:
+/* case SENSOR_MO4000: */
+/* case SENSOR_MI0360: */
expotimes = sd->exposure;
expotimes += (luma_mean - delta) >> 6;
if (expotimes < 0)
@@ -1228,6 +1186,8 @@ static void setautogain(struct gspca_dev *gspca_dev)
}
}
+/* scan the URB packets */
+/* This function is run at interrupt level. */
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -1244,9 +1204,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
frame, data, sof + 2);
if (sd->ag_cnt < 0)
return;
- if (--sd->ag_cnt >= 0)
- return;
- sd->ag_cnt = AG_CNT_START;
/* w1 w2 w3 */
/* w4 w5 w6 */
/* w7 w8 */
@@ -1261,9 +1218,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* w5 */
avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
avg_lum >>= 4;
- sd->avg_lum = avg_lum;
- PDEBUG(D_PACK, "mean lum %d", avg_lum);
- setautogain(gspca_dev);
+ atomic_set(&sd->avg_lum, avg_lum);
return;
}
if (gspca_dev->last_packet_type == LAST_PACKET) {
@@ -1300,6 +1255,7 @@ static unsigned int getexposure(struct gspca_dev *gspca_dev)
(hexpo << 10) | (mexpo << 2) | lexpo);
return (hexpo << 10) | (mexpo << 2) | lexpo;
default:
+/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
/* case SENSOR_OV7660: */
/* read sensor exposure */
i2c_r5(gspca_dev, 0x04);
@@ -1318,14 +1274,12 @@ static void getbrightness(struct gspca_dev *gspca_dev)
/* hardcoded registers seem not readable */
switch (sd->sensor) {
case SENSOR_HV7131R:
-/* sd->brightness = 0x7fff; */
sd->brightness = getexposure(gspca_dev) >> 4;
break;
case SENSOR_MI0360:
sd->brightness = getexposure(gspca_dev) << 4;
break;
case SENSOR_MO4000:
-/* sd->brightness = 0x1fff; */
sd->brightness = getexposure(gspca_dev) << 4;
break;
}
@@ -1391,10 +1345,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
- if (val)
- sd->ag_cnt = AG_CNT_START;
- else
- sd->ag_cnt = -1;
+ if (gspca_dev->streaming)
+ setautogain(gspca_dev);
return 0;
}
@@ -1418,6 +1370,7 @@ static const struct sd_desc sd_desc = {
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
+ .dq_callback = do_autogain,
};
/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
index 3c2be80cbd65..eda29d609359 100644
--- a/drivers/media/video/gspca/spca505.c
+++ b/drivers/media/video/gspca/spca505.c
@@ -61,27 +61,27 @@ static struct ctrl sd_ctrls[] = {
static struct v4l2_pix_format vga_mode[] = {
{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 160 * 3,
+ .bytesperline = 160,
.sizeimage = 160 * 120 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 5},
{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 176 * 3,
+ .bytesperline = 176,
.sizeimage = 176 * 144 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 4},
{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 320 * 3,
+ .bytesperline = 320,
.sizeimage = 320 * 240 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 2},
{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 352 * 3,
+ .bytesperline = 352,
.sizeimage = 352 * 288 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 640 * 3,
+ .bytesperline = 640,
.sizeimage = 640 * 480 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0},
@@ -776,7 +776,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
default:
data += 1;
len -= 1;
- gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
data, len);
break;
}
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
index 6fe715c80ad2..f622fa75766d 100644
--- a/drivers/media/video/gspca/spca506.c
+++ b/drivers/media/video/gspca/spca506.c
@@ -112,27 +112,27 @@ static struct ctrl sd_ctrls[] = {
static struct v4l2_pix_format vga_mode[] = {
{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 160 * 3,
+ .bytesperline = 160,
.sizeimage = 160 * 120 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 5},
{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 176 * 3,
+ .bytesperline = 176,
.sizeimage = 176 * 144 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 4},
{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 320 * 3,
+ .bytesperline = 320,
.sizeimage = 320 * 240 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 2},
{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 352 * 3,
+ .bytesperline = 352,
.sizeimage = 352 * 288 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
- .bytesperline = 640 * 3,
+ .bytesperline = 640,
.sizeimage = 640 * 480 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0},
@@ -588,7 +588,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
default:
data += 1;
len -= 1;
- gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
data, len);
break;
}
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
index b608a27ad115..699340c17dea 100644
--- a/drivers/media/video/gspca/spca508.c
+++ b/drivers/media/video/gspca/spca508.c
@@ -63,23 +63,23 @@ static struct ctrl sd_ctrls[] = {
};
static struct v4l2_pix_format sif_mode[] = {
- {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
- .bytesperline = 160 * 3,
+ {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+ .bytesperline = 160,
.sizeimage = 160 * 120 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 3},
- {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
- .bytesperline = 176 * 3,
+ {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+ .bytesperline = 176,
.sizeimage = 176 * 144 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 2},
- {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
- .bytesperline = 320 * 3,
+ {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+ .bytesperline = 320,
.sizeimage = 320 * 240 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
- {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
- .bytesperline = 352 * 3,
+ {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+ .bytesperline = 352,
.sizeimage = 352 * 288 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0},
@@ -1583,7 +1583,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
default:
data += 1;
len -= 1;
- gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame,
data, len);
break;
}
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index a26174508cb9..1073ac3d2ec6 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -644,6 +644,18 @@ static void setcontrast(struct gspca_dev *gspca_dev)
}
}
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->chip_revision == Rev072A) {
+ if (sd->autogain)
+ sd->ag_cnt = AG_CNT_START;
+ else
+ sd->ag_cnt = -1;
+ }
+}
+
static void sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -671,6 +683,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w_val(dev, 0x8500, mode); /* mode */
reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
reg_w_val(dev, 0x8112, 0x10 | 0x20);
+ setautogain(gspca_dev);
break;
default:
/* case Rev012A: */
@@ -720,18 +733,24 @@ static void sd_close(struct gspca_dev *gspca_dev)
reg_w_val(gspca_dev->dev, 0x8114, 0);
}
-static void setautogain(struct gspca_dev *gspca_dev)
+static void do_autogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int expotimes = 0;
- int pixelclk = 0;
- int gainG = 0;
+ int expotimes;
+ int pixelclk;
+ int gainG;
__u8 R, Gr, Gb, B;
int y;
__u8 luma_mean = 110;
__u8 luma_delta = 20;
__u8 spring = 4;
+ if (sd->ag_cnt < 0)
+ return;
+ if (--sd->ag_cnt >= 0)
+ return;
+ sd->ag_cnt = AG_CNT_START;
+
switch (sd->chip_revision) {
case Rev072A:
reg_r(gspca_dev, 0x8621, 1);
@@ -795,18 +814,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
__u8 *data, /* isoc packet */
int len) /* iso packet length */
{
- struct sd *sd = (struct sd *) gspca_dev;
-
switch (data[0]) {
case 0: /* start of frame */
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
data, 0);
- if (sd->ag_cnt >= 0) {
- if (--sd->ag_cnt < 0) {
- sd->ag_cnt = AG_CNT_START;
- setautogain(gspca_dev);
- }
- }
data += SPCA561_OFFSET_DATA;
len -= SPCA561_OFFSET_DATA;
if (data[1] & 0x10) {
@@ -944,10 +955,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
- if (val)
- sd->ag_cnt = AG_CNT_START;
- else
- sd->ag_cnt = -1;
+ if (gspca_dev->streaming)
+ setautogain(gspca_dev);
return 0;
}
@@ -971,6 +980,7 @@ static const struct sd_desc sd_desc = {
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
+ .dq_callback = do_autogain,
};
/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index a4221753e1bf..f4a52956e0d9 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -88,12 +88,12 @@ static struct ctrl sd_ctrls[] = {
static struct v4l2_pix_format vc0321_mode[] = {
{320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
- .bytesperline = 320 * 2,
+ .bytesperline = 320,
.sizeimage = 320 * 240 * 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1},
{640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
- .bytesperline = 640 * 2,
+ .bytesperline = 640,
.sizeimage = 640 * 480 * 2,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0},
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 22a994ccb1d5..bc7d0eedcd81 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -6469,7 +6469,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
NULL, Tgradient_1, Tgradient_2,
Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6
};
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
__u8 v[16];
#endif
@@ -6487,7 +6487,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
else if (g <= 0)
g = 1;
reg_w(dev, g, 0x0120 + i); /* gamma */
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (gspca_debug & D_CONF)
v[i] = g;
#endif
@@ -6507,7 +6507,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
g = 1;
}
reg_w(dev, g, 0x0130 + i); /* gradient */
-#ifdef CONFIG_VIDEO_ADV_DEBUG
+#ifdef GSPCA_DEBUG
if (gspca_debug & D_CONF)
v[i] = g;
#endif
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index b15f82c49766..ead87ddaf7fb 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -128,6 +128,8 @@ struct pxa_camera_dev {
struct pxa_buffer *active;
struct pxa_dma_desc *sg_tail[3];
+
+ u32 save_cicr[5];
};
static const char *pxa_cam_driver_description = "PXA_Camera";
@@ -997,10 +999,64 @@ static int pxa_camera_querycap(struct soc_camera_host *ici,
return 0;
}
+static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
+{
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
+ struct pxa_camera_dev *pcdev = ici->priv;
+ int i = 0, ret = 0;
+
+ pcdev->save_cicr[i++] = CICR0;
+ pcdev->save_cicr[i++] = CICR1;
+ pcdev->save_cicr[i++] = CICR2;
+ pcdev->save_cicr[i++] = CICR3;
+ pcdev->save_cicr[i++] = CICR4;
+
+ if ((pcdev->icd) && (pcdev->icd->ops->suspend))
+ ret = pcdev->icd->ops->suspend(pcdev->icd, state);
+
+ return ret;
+}
+
+static int pxa_camera_resume(struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
+ struct pxa_camera_dev *pcdev = ici->priv;
+ int i = 0, ret = 0;
+
+ DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
+ DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
+ DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
+
+ CICR0 = pcdev->save_cicr[i++] & ~CICR0_ENB;
+ CICR1 = pcdev->save_cicr[i++];
+ CICR2 = pcdev->save_cicr[i++];
+ CICR3 = pcdev->save_cicr[i++];
+ CICR4 = pcdev->save_cicr[i++];
+
+ if ((pcdev->icd) && (pcdev->icd->ops->resume))
+ ret = pcdev->icd->ops->resume(pcdev->icd);
+
+ /* Restart frame capture if active buffer exists */
+ if (!ret && pcdev->active) {
+ /* Reset the FIFOs */
+ CIFR |= CIFR_RESET_F;
+ /* Enable End-Of-Frame Interrupt */
+ CICR0 &= ~CICR0_EOFM;
+ /* Restart the Capture Interface */
+ CICR0 |= CICR0_ENB;
+ }
+
+ return ret;
+}
+
static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
.owner = THIS_MODULE,
.add = pxa_camera_add_device,
.remove = pxa_camera_remove_device,
+ .suspend = pxa_camera_suspend,
+ .resume = pxa_camera_resume,
.set_fmt_cap = pxa_camera_set_fmt_cap,
.try_fmt_cap = pxa_camera_try_fmt_cap,
.init_videobuf = pxa_camera_init_videobuf,
@@ -1198,7 +1254,7 @@ static int __devinit pxa_camera_init(void)
static void __exit pxa_camera_exit(void)
{
- return platform_driver_unregister(&pxa_camera_driver);
+ platform_driver_unregister(&pxa_camera_driver);
}
module_init(pxa_camera_init);
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index f7ca3cb9340a..318754e73132 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -647,7 +647,7 @@ static int __init sh_mobile_ceu_init(void)
static void __exit sh_mobile_ceu_exit(void)
{
- return platform_driver_unregister(&sh_mobile_ceu_driver);
+ platform_driver_unregister(&sh_mobile_ceu_driver);
}
module_init(sh_mobile_ceu_init);
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index b6be5ee678b6..66ebe5956a87 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -732,10 +732,36 @@ static int soc_camera_remove(struct device *dev)
return 0;
}
+static int soc_camera_suspend(struct device *dev, pm_message_t state)
+{
+ struct soc_camera_device *icd = to_soc_camera_dev(dev);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ int ret = 0;
+
+ if (ici->ops->suspend)
+ ret = ici->ops->suspend(icd, state);
+
+ return ret;
+}
+
+static int soc_camera_resume(struct device *dev)
+{
+ struct soc_camera_device *icd = to_soc_camera_dev(dev);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ int ret = 0;
+
+ if (ici->ops->resume)
+ ret = ici->ops->resume(icd);
+
+ return ret;
+}
+
static struct bus_type soc_camera_bus_type = {
.name = "soc-camera",
.probe = soc_camera_probe,
.remove = soc_camera_remove,
+ .suspend = soc_camera_suspend,
+ .resume = soc_camera_resume,
};
static struct device_driver ic_drv = {
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index eefb0327ebb6..1adc257ebdb9 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -187,7 +187,7 @@ static int __init soc_camera_platform_module_init(void)
static void __exit soc_camera_platform_module_exit(void)
{
- return platform_driver_unregister(&soc_camera_platform_driver);
+ platform_driver_unregister(&soc_camera_platform_driver);
}
module_init(soc_camera_platform_module_init);
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 626f4ad7e876..6ef3e5297de8 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -585,13 +585,17 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
struct uvc_control_mapping *mapping;
struct uvc_menu_info *menu;
unsigned int i;
- __u8 data[8];
+ __u8 *data;
int ret;
ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping);
if (ctrl == NULL)
return -EINVAL;
+ data = kmalloc(8, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
v4l2_ctrl->id = mapping->id;
v4l2_ctrl->type = mapping->v4l2_type;
@@ -604,8 +608,8 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
if (ctrl->info->flags & UVC_CONTROL_GET_DEF) {
if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id,
video->dev->intfnum, ctrl->info->selector,
- &data, ctrl->info->size)) < 0)
- return ret;
+ data, ctrl->info->size)) < 0)
+ goto out;
v4l2_ctrl->default_value = uvc_get_le_value(data, mapping);
}
@@ -623,13 +627,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
}
}
- return 0;
+ ret = 0;
+ goto out;
case V4L2_CTRL_TYPE_BOOLEAN:
v4l2_ctrl->minimum = 0;
v4l2_ctrl->maximum = 1;
v4l2_ctrl->step = 1;
- return 0;
+ ret = 0;
+ goto out;
default:
break;
@@ -638,26 +644,29 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
if (ctrl->info->flags & UVC_CONTROL_GET_MIN) {
if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id,
video->dev->intfnum, ctrl->info->selector,
- &data, ctrl->info->size)) < 0)
- return ret;
+ data, ctrl->info->size)) < 0)
+ goto out;
v4l2_ctrl->minimum = uvc_get_le_value(data, mapping);
}
if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id,
video->dev->intfnum, ctrl->info->selector,
- &data, ctrl->info->size)) < 0)
- return ret;
+ data, ctrl->info->size)) < 0)
+ goto out;
v4l2_ctrl->maximum = uvc_get_le_value(data, mapping);
}
if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id,
video->dev->intfnum, ctrl->info->selector,
- &data, ctrl->info->size)) < 0)
- return ret;
+ data, ctrl->info->size)) < 0)
+ goto out;
v4l2_ctrl->step = uvc_get_le_value(data, mapping);
}
- return 0;
+ ret = 0;
+out:
+ kfree(data);
+ return ret;
}
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index b3c4d75e8490..7e102034d38d 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1884,7 +1884,7 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Packard Bell OEM Webcam */
+ /* Packard Bell OEM Webcam - Bison Electronics */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x5986,
@@ -1893,7 +1893,7 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Acer Crystal Eye webcam */
+ /* Acer Crystal Eye webcam - Bison Electronics */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x5986,
@@ -1902,7 +1902,7 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Medion Akoya Mini E1210 */
+ /* Medion Akoya Mini E1210 - Bison Electronics */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x5986,
@@ -1911,7 +1911,7 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Acer OrbiCam - Unknown vendor */
+ /* Acer OrbiCam - Bison Electronics */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x5986,
@@ -1920,6 +1920,24 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Bison Electronics */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x5986,
+ .idProduct = 0x0300,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
+ /* Clevo M570TU - Bison Electronics */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x5986,
+ .idProduct = 0x0303,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
{}
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index ad63794fda77..6854ac78a161 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -90,17 +90,20 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video,
static int uvc_get_video_ctrl(struct uvc_video_device *video,
struct uvc_streaming_control *ctrl, int probe, __u8 query)
{
- __u8 data[34];
- __u8 size;
+ __u8 *data;
+ __u16 size;
int ret;
size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
+ data = kmalloc(size, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum,
- probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size,
+ probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
UVC_CTRL_STREAMING_TIMEOUT);
-
if (ret < 0)
- return ret;
+ goto out;
ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
ctrl->bFormatIndex = data[2];
@@ -136,17 +139,22 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
*/
uvc_fixup_buffer_size(video, ctrl);
- return 0;
+out:
+ kfree(data);
+ return ret;
}
int uvc_set_video_ctrl(struct uvc_video_device *video,
struct uvc_streaming_control *ctrl, int probe)
{
- __u8 data[34];
- __u8 size;
+ __u8 *data;
+ __u16 size;
+ int ret;
size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
- memset(data, 0, sizeof data);
+ data = kzalloc(size, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
*(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);
data[2] = ctrl->bFormatIndex;
@@ -174,10 +182,13 @@ int uvc_set_video_ctrl(struct uvc_video_device *video,
data[33] = ctrl->bMaxVersion;
}
- return __uvc_query_ctrl(video->dev, SET_CUR, 0,
+ ret = __uvc_query_ctrl(video->dev, SET_CUR, 0,
video->streaming->intfnum,
- probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size,
+ probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
UVC_CTRL_STREAMING_TIMEOUT);
+
+ kfree(data);
+ return ret;
}
int uvc_probe_video(struct uvc_video_device *video,
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 556615fe93de..6f36006aecda 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -222,11 +222,13 @@ int video_register_device(struct video_device *vfd, int type, int nr)
EXPORT_SYMBOL(video_register_device);
/**
- * video_register_device - register video4linux devices
+ * video_register_device_index - register video4linux devices
* @vfd: video device structure we want to register
* @type: type of device to register
* @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ...
* -1 == first free)
+ * @index: stream number based on parent device;
+ * -1 if auto assign, requested number otherwise
*
* The registration code assigns minor numbers based on the type
* requested. -ENFILE is returned in all the device slots for this
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index ef7572cbc4ab..1edda456fc64 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -41,6 +41,7 @@
#include <linux/videodev2.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
#include <linux/video_decoder.h>
#include <linux/mutex.h>
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 1de98f150e99..d548de326722 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -14,6 +14,7 @@
#include <linux/videodev2.h>
#include <media/videobuf-core.h>
+#include <linux/pm.h>
struct soc_camera_device {
struct list_head list;
@@ -63,6 +64,8 @@ struct soc_camera_host_ops {
struct module *owner;
int (*add)(struct soc_camera_device *);
void (*remove)(struct soc_camera_device *);
+ int (*suspend)(struct soc_camera_device *, pm_message_t state);
+ int (*resume)(struct soc_camera_device *);
int (*set_fmt_cap)(struct soc_camera_device *, __u32,
struct v4l2_rect *);
int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
@@ -111,6 +114,8 @@ struct soc_camera_ops {
struct module *owner;
int (*probe)(struct soc_camera_device *);
void (*remove)(struct soc_camera_device *);
+ int (*suspend)(struct soc_camera_device *, pm_message_t state);
+ int (*resume)(struct soc_camera_device *);
int (*init)(struct soc_camera_device *);
int (*release)(struct soc_camera_device *);
int (*start_capture)(struct soc_camera_device *);