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
  ...
This commit is contained in:
Linus Torvalds 2008-08-07 18:06:19 -07:00
commit b80b601f00
30 changed files with 686 additions and 593 deletions

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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 -- */

View File

@ -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"

View File

@ -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...) \

View File

@ -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 }, */
/* 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) */
/* PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); */
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); */
}
/* 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 */
default:
/* case 15: */
reg_w(sd, 0xa4, 0x10);
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,8 +1583,6 @@ 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);
@ -1638,7 +1598,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd,
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)");

View File

@ -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 -- */

View File

@ -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;

View File

@ -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,
/* 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, 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 */
{}
};
/* reg 0x04 reg 0x07 reg 0x10 */
/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
/* 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);
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 -- */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 -- */

View File

@ -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},

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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 = {

View File

@ -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);

View File

@ -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;
}

View File

@ -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) },
{}

View File

@ -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;
ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size,
UVC_CTRL_STREAMING_TIMEOUT);
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,
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,

View File

@ -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

View File

@ -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>

View File

@ -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 *);