diff options
author | James Morris <jmorris@namei.org> | 2011-01-10 09:46:24 +1100 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-01-10 09:46:24 +1100 |
commit | d2e7ad19229f982fc1eb731827d82ceac90abfb3 (patch) | |
tree | 98a3741b4d4b27a48b3c7ea9babe331e539416a8 /drivers/media/video/gspca | |
parent | d03a5d888fb688c832d470b749acc5ed38e0bc1d (diff) | |
parent | 0c21e3aaf6ae85bee804a325aa29c325209180fd (diff) |
Merge branch 'master' into next
Conflicts:
security/smack/smack_lsm.c
Verified and added fix by Stephen Rothwell <sfr@canb.auug.org.au>
Ok'd by Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'drivers/media/video/gspca')
30 files changed, 2151 insertions, 1774 deletions
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 9b121681d13..c1ae05f4661 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); /* constant value's */ #define MAGIC_0 0x19 #define MAGIC_1 0x68 -#define DATA_IN 0xC0 +#define DATA_IN 0xc0 #define DATA_OUT 0x40 #define VIDEOSIZE_QCIF 0 /* 176x144 */ #define VIDEOSIZE_CIF 1 /* 352x288 */ @@ -660,9 +660,9 @@ static int do_command(struct gspca_dev *gspca_dev, u16 command, if (sd->params.qx3.button) { /* button pressed - unlock the latch */ do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xDF, 0xDF, 0); + 3, 0xdf, 0xdf, 0); do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xFF, 0xFF, 0); + 3, 0xff, 0xff, 0); } /* test whether microscope is cradled */ @@ -829,7 +829,7 @@ static int goto_low_power(struct gspca_dev *gspca_dev) if (ret) return ret; - do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); + ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); if (ret) return ret; @@ -1110,12 +1110,12 @@ static int command_setlights(struct gspca_dev *gspca_dev) p2 = (sd->params.qx3.toplight == 0) << 3; ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg, - 0x90, 0x8F, 0x50, 0); + 0x90, 0x8f, 0x50, 0); if (ret) return ret; return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, - p1 | p2 | 0xE0, 0); + p1 | p2 | 0xe0, 0); } static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 8fe8fb486d6..442970073e8 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -55,7 +55,7 @@ MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 10, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 11, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; @@ -224,12 +224,12 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, buffer, buffer_len, int_irq, (void *)gspca_dev, interval); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - gspca_dev->int_urb = urb; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret < 0) { PDEBUG(D_ERR, "submit int URB failed with error %i", ret); goto error_submit; } + gspca_dev->int_urb = urb; return ret; error_submit: @@ -318,14 +318,9 @@ static void fill_frame(struct gspca_dev *gspca_dev, } pkt_scan = gspca_dev->sd_desc->pkt_scan; for (i = 0; i < urb->number_of_packets; i++) { + len = urb->iso_frame_desc[i].actual_length; /* check the packet status and length */ - len = urb->iso_frame_desc[i].actual_length; - if (len == 0) { - if (gspca_dev->empty_packet == 0) - gspca_dev->empty_packet = 1; - continue; - } st = urb->iso_frame_desc[i].status; if (st) { err("ISOC data error: [%d] len=%d, status=%d", @@ -333,6 +328,11 @@ static void fill_frame(struct gspca_dev *gspca_dev, gspca_dev->last_packet_type = DISCARD_PACKET; continue; } + if (len == 0) { + if (gspca_dev->empty_packet == 0) + gspca_dev->empty_packet = 1; + continue; + } /* let the packet be analyzed by the subdriver */ PDEBUG(D_PACK, "packet [%d] o:%d l:%d", @@ -652,16 +652,12 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) : USB_ENDPOINT_XFER_ISOC; i = gspca_dev->alt; /* previous alt setting */ if (gspca_dev->cam.reverse_alts) { - if (gspca_dev->audio && i < gspca_dev->nbalt - 2) - i++; while (++i < gspca_dev->nbalt) { ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) break; } } else { - if (gspca_dev->audio && i > 1) - i--; while (--i >= 0) { ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) @@ -676,13 +672,11 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) i, ep->desc.bEndpointAddress); gspca_dev->alt = i; /* memorize the current alt setting */ if (gspca_dev->nbalt > 1) { - gspca_input_destroy_urb(gspca_dev); ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { err("set alt %d err %d", i, ret); ep = NULL; } - gspca_input_create_urb(gspca_dev); } return ep; } @@ -759,7 +753,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, } } else { /* bulk */ urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, - ep->desc.bEndpointAddress), + ep->desc.bEndpointAddress); urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; urb->complete = bulk_irq; } @@ -781,7 +775,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (!gspca_dev->present) { ret = -ENODEV; - goto out; + goto unlock; } /* reset the streaming variables */ @@ -802,8 +796,10 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (gspca_dev->sd_desc->isoc_init) { ret = gspca_dev->sd_desc->isoc_init(gspca_dev); if (ret < 0) - goto out; + goto unlock; } + + gspca_input_destroy_urb(gspca_dev); ep = get_ep(gspca_dev); if (ep == NULL) { ret = -EIO; @@ -873,6 +869,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) } } out: + gspca_input_create_urb(gspca_dev); +unlock: mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1299,17 +1297,19 @@ static int vidioc_querycap(struct file *file, void *priv, ret = -ENODEV; goto out; } - strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); + strncpy((char *) cap->driver, gspca_dev->sd_desc->name, + sizeof cap->driver); if (gspca_dev->dev->product != NULL) { - strncpy(cap->card, gspca_dev->dev->product, + strncpy((char *) cap->card, gspca_dev->dev->product, sizeof cap->card); } else { - snprintf(cap->card, sizeof cap->card, + snprintf((char *) cap->card, sizeof cap->card, "USB Camera (%04x:%04x)", le16_to_cpu(gspca_dev->dev->descriptor.idVendor), le16_to_cpu(gspca_dev->dev->descriptor.idProduct)); } - usb_make_path(gspca_dev->dev, cap->bus_info, sizeof(cap->bus_info)); + usb_make_path(gspca_dev->dev, (char *) cap->bus_info, + sizeof(cap->bus_info)); cap->version = DRIVER_VERSION_NUMBER; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING @@ -1710,12 +1710,13 @@ static int vidioc_g_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - gspca_dev->usb_err = 0; - if (gspca_dev->present) - ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, - parm); - else + if (gspca_dev->present) { + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); + ret = gspca_dev->usb_err; + } else { ret = -ENODEV; + } mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1740,12 +1741,13 @@ static int vidioc_s_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - gspca_dev->usb_err = 0; - if (gspca_dev->present) - ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, - parm); - else + if (gspca_dev->present) { + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); + ret = gspca_dev->usb_err; + } else { ret = -ENODEV; + } mutex_unlock(&gspca_dev->usb_lock); return ret; } diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index d4d210b56b4..97b77a26a2e 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -62,7 +62,7 @@ struct gspca_ctrl { /* device information - set at probe time */ struct cam { const struct v4l2_pix_format *cam_mode; /* size nmodes */ - const struct framerates *mode_framerates; /* must have size nmode, + const struct framerates *mode_framerates; /* must have size nmodes, * just like cam_mode */ struct gspca_ctrl *ctrls; /* control table - size nctrls */ /* may be NULL */ @@ -93,7 +93,7 @@ typedef int (*cam_reg_op) (struct gspca_dev *, struct v4l2_dbg_register *); typedef int (*cam_ident_op) (struct gspca_dev *, struct v4l2_dbg_chip_ident *); -typedef int (*cam_streamparm_op) (struct gspca_dev *, +typedef void (*cam_streamparm_op) (struct gspca_dev *, struct v4l2_streamparm *); typedef int (*cam_qmnu_op) (struct gspca_dev *, struct v4l2_querymenu *); diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index 8ded8b10057..703d48670a2 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -624,7 +624,7 @@ static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | - (i2c_data & 0x3F); + (i2c_data & 0x3f); err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) return err; diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 6cf6855aa50..e1c3b9328ac 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -75,14 +75,14 @@ struct sd { struct gspca_ctrl ctrls[NCTRL]; - __u8 packet_nr; + u8 packet_nr; char bridge; #define BRIDGE_OV511 0 #define BRIDGE_OV511PLUS 1 #define BRIDGE_OV518 2 #define BRIDGE_OV518PLUS 3 -#define BRIDGE_OV519 4 +#define BRIDGE_OV519 4 /* = ov530 */ #define BRIDGE_OVFX2 5 #define BRIDGE_W9968CF 6 #define BRIDGE_MASK 7 @@ -94,42 +94,44 @@ struct sd { char snapshot_needs_reset; /* Determined by sensor type */ - __u8 sif; + u8 sif; - __u8 quality; + u8 quality; #define QUALITY_MIN 50 #define QUALITY_MAX 70 #define QUALITY_DEF 50 - __u8 stopped; /* Streaming is temporarily paused */ - __u8 first_frame; - - __u8 frame_rate; /* current Framerate */ - __u8 clockdiv; /* clockdiv override */ - - char sensor; /* Type of image sensor chip (SEN_*) */ -#define SEN_UNKNOWN 0 -#define SEN_OV2610 1 -#define SEN_OV3610 2 -#define SEN_OV6620 3 -#define SEN_OV6630 4 -#define SEN_OV66308AF 5 -#define SEN_OV7610 6 -#define SEN_OV7620 7 -#define SEN_OV7620AE 8 -#define SEN_OV7640 9 -#define SEN_OV7648 10 -#define SEN_OV7670 11 -#define SEN_OV76BE 12 -#define SEN_OV8610 13 + u8 stopped; /* Streaming is temporarily paused */ + u8 first_frame; + + u8 frame_rate; /* current Framerate */ + u8 clockdiv; /* clockdiv override */ + + s8 sensor; /* Type of image sensor chip (SEN_*) */ u8 sensor_addr; - int sensor_width; - int sensor_height; - int sensor_reg_cache[256]; + u16 sensor_width; + u16 sensor_height; + s16 sensor_reg_cache[256]; u8 jpeg_hdr[JPEG_HDR_SZ]; }; +enum sensors { + SEN_OV2610, + SEN_OV3610, + SEN_OV6620, + SEN_OV6630, + SEN_OV66308AF, + SEN_OV7610, + SEN_OV7620, + SEN_OV7620AE, + SEN_OV7640, + SEN_OV7648, + SEN_OV7660, + SEN_OV7670, + SEN_OV76BE, + SEN_OV8610, +}; /* Note this is a bit of a hack, but the w9968cf driver needs the code for all the ov sensors which is already present here. When we have the time we @@ -182,7 +184,7 @@ static const struct ctrl sd_ctrls[] = { }, .set_control = setcolors, }, -/* The flip controls work with ov7670 only */ +/* The flip controls work for sensors ov7660 and ov7670 only */ [HFLIP] = { { .id = V4L2_CID_HFLIP, @@ -225,7 +227,7 @@ static const struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_MENU, .name = "Light frequency filter", .minimum = 0, - .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ + .maximum = 2, /* 0: no flicker, 1: 50Hz, 2:60Hz, 3: auto */ .step = 1, .default_value = 0, }, @@ -233,6 +235,53 @@ static const struct ctrl sd_ctrls[] = { }, }; +/* table of the disabled controls */ +static const unsigned ctrl_dis[] = { +[SEN_OV2610] = (1 << NCTRL) - 1, /* no control */ + +[SEN_OV3610] = (1 << NCTRL) - 1, /* no control */ + +[SEN_OV6620] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV6630] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV66308AF] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7610] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7620] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7620AE] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7640] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << AUTOBRIGHT) | + (1 << CONTRAST), + +[SEN_OV7648] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << AUTOBRIGHT) | + (1 << CONTRAST), + +[SEN_OV7660] = (1 << AUTOBRIGHT), + +[SEN_OV7670] = (1 << COLORS) | + (1 << AUTOBRIGHT), + +[SEN_OV76BE] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV8610] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), +}; + static const struct v4l2_pix_format ov519_vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, @@ -412,7 +461,6 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { .priv = 0}, }; - /* Registers common to OV511 / OV518 */ #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ #define R51x_SYS_RESET 0x50 @@ -420,7 +468,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV511_RESET_OMNICE 0x08 #define R51x_SYS_INIT 0x53 #define R51x_SYS_SNAP 0x52 -#define R51x_SYS_CUST_ID 0x5F +#define R51x_SYS_CUST_ID 0x5f #define R51x_COMP_LUT_BEGIN 0x80 /* OV511 Camera interface register numbers */ @@ -435,13 +483,13 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define R511_CAM_OPTS 0x18 #define R511_SNAP_FRAME 0x19 -#define R511_SNAP_PXCNT 0x1A -#define R511_SNAP_LNCNT 0x1B -#define R511_SNAP_PXDIV 0x1C -#define R511_SNAP_LNDIV 0x1D -#define R511_SNAP_UV_EN 0x1E -#define R511_SNAP_UV_EN 0x1E -#define R511_SNAP_OPTS 0x1F +#define R511_SNAP_PXCNT 0x1a +#define R511_SNAP_LNCNT 0x1b +#define R511_SNAP_PXDIV 0x1c +#define R511_SNAP_LNDIV 0x1d +#define R511_SNAP_UV_EN 0x1e +#define R511_SNAP_UV_EN 0x1e +#define R511_SNAP_OPTS 0x1f #define R511_DRAM_FLOW_CTL 0x20 #define R511_FIFO_OPTS 0x31 @@ -466,13 +514,14 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV519_R25_FORMAT 0x25 /* OV519 System Controller register numbers */ -#define OV519_SYS_RESET1 0x51 -#define OV519_SYS_EN_CLK1 0x54 +#define OV519_R51_RESET1 0x51 +#define OV519_R54_EN_CLK1 0x54 +#define OV519_R57_SNAPSHOT 0x57 #define OV519_GPIO_DATA_OUT0 0x71 #define OV519_GPIO_IO_CTRL0 0x72 -#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ +/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */ /* * The FX2 chip does not give us a zero length read at end of frame. @@ -526,80 +575,81 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ #define OV7610_REG_COM_I 0x29 /* misc settings */ -/* OV7670 registers */ -#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ -#define OV7670_REG_BLUE 0x01 /* blue gain */ -#define OV7670_REG_RED 0x02 /* red gain */ -#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ -#define OV7670_REG_COM1 0x04 /* Control 1 */ -#define OV7670_REG_AECHH 0x07 /* AEC MS 5 bits */ -#define OV7670_REG_COM3 0x0c /* Control 3 */ -#define OV7670_REG_COM4 0x0d /* Control 4 */ -#define OV7670_REG_COM5 0x0e /* All "reserved" */ -#define OV7670_REG_COM6 0x0f /* Control 6 */ -#define OV7670_REG_AECH 0x10 /* More bits of AEC value */ -#define OV7670_REG_CLKRC 0x11 /* Clock control */ -#define OV7670_REG_COM7 0x12 /* Control 7 */ -#define OV7670_COM7_FMT_VGA 0x00 -#define OV7670_COM7_YUV 0x00 /* YUV */ -#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ -#define OV7670_COM7_FMT_MASK 0x38 -#define OV7670_COM7_RESET 0x80 /* Register reset */ -#define OV7670_REG_COM8 0x13 /* Control 8 */ -#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ -#define OV7670_COM8_AWB 0x02 /* White balance enable */ -#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ -#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ -#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ -#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ -#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */ -#define OV7670_REG_COM10 0x15 /* Control 10 */ -#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */ -#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */ -#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 */ -#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */ -#define OV7670_REG_HREF 0x32 /* HREF pieces */ -#define OV7670_REG_TSLB 0x3a /* lots of stuff */ -#define OV7670_REG_COM11 0x3b /* Control 11 */ -#define OV7670_COM11_EXP 0x02 -#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ -#define OV7670_REG_COM12 0x3c /* Control 12 */ -#define OV7670_REG_COM13 0x3d /* Control 13 */ -#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ -#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ -#define OV7670_REG_COM14 0x3e /* Control 14 */ -#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */ -#define OV7670_REG_COM15 0x40 /* Control 15 */ -#define OV7670_COM15_R00FF 0xc0 /* 00 to FF */ -#define OV7670_REG_COM16 0x41 /* Control 16 */ -#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ -#define OV7670_REG_BRIGHT 0x55 /* Brightness */ -#define OV7670_REG_CONTRAS 0x56 /* Contrast control */ -#define OV7670_REG_GFIX 0x69 /* Fix gain control */ -#define OV7670_REG_RGB444 0x8c /* RGB 444 control */ -#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ -#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ -#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */ -#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ -#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ -#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ -#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ -#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ -#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ +/* OV7660 and OV7670 registers */ +#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ +#define OV7670_R01_BLUE 0x01 /* blue gain */ +#define OV7670_R02_RED 0x02 /* red gain */ +#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ +#define OV7670_R04_COM1 0x04 /* Control 1 */ +/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */ +#define OV7670_R0C_COM3 0x0c /* Control 3 */ +#define OV7670_R0D_COM4 0x0d /* Control 4 */ +#define OV7670_R0E_COM5 0x0e /* All "reserved" */ +#define OV7670_R0F_COM6 0x0f /* Control 6 */ +#define OV7670_R10_AECH 0x10 /* More bits of AEC value */ +#define OV7670_R11_CLKRC 0x11 /* Clock control */ +#define OV7670_R12_COM7 0x12 /* Control 7 */ +#define OV7670_COM7_FMT_VGA 0x00 +/*#define OV7670_COM7_YUV 0x00 * YUV */ +#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ +#define OV7670_COM7_FMT_MASK 0x38 +#define OV7670_COM7_RESET 0x80 /* Register reset */ +#define OV7670_R13_COM8 0x13 /* Control 8 */ +#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ +#define OV7670_COM8_AWB 0x02 /* White balance enable */ +#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ +#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ +#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ +#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ +#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */ +#define OV7670_R15_COM10 0x15 /* Control 10 */ +#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */ +#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */ +#define OV7670_R19_VSTART 0x19 /* Vert start high bits */ +#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */ +#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */ +#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ +#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ +#define OV7670_R24_AEW 0x24 /* AGC upper limit */ +#define OV7670_R25_AEB 0x25 /* AGC lower limit */ +#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */ +#define OV7670_R32_HREF 0x32 /* HREF pieces */ +#define OV7670_R3A_TSLB 0x3a /* lots of stuff */ +#define OV7670_R3B_COM11 0x3b /* Control 11 */ +#define OV7670_COM11_EXP 0x02 +#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ +#define OV7670_R3C_COM12 0x3c /* Control 12 */ +#define OV7670_R3D_COM13 0x3d /* Control 13 */ +#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ +#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ +#define OV7670_R3E_COM14 0x3e /* Control 14 */ +#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */ +#define OV7670_R40_COM15 0x40 /* Control 15 */ +/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ +#define OV7670_R41_COM16 0x41 /* Control 16 */ +#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ +/* end of ov7660 common registers */ +#define OV7670_R55_BRIGHT 0x55 /* Brightness */ +#define OV7670_R56_CONTRAS 0x56 /* Contrast control */ +#define OV7670_R69_GFIX 0x69 /* Fix gain control */ +/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */ +#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */ +#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ +#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */ +#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ +#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ +#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ +#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ +#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */ +#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */ struct ov_regvals { - __u8 reg; - __u8 val; + u8 reg; + u8 val; }; struct ov_i2c_regvals { - __u8 reg; - __u8 val; + u8 reg; + u8 val; }; /* Settings for OV2610 camera chip */ @@ -617,7 +667,6 @@ static const struct ov_i2c_regvals norm_3620b[] = { * "wait 4096 external clock ... to make sure the sensor is * stable and ready to access registers" i.e. 160us at 24MHz */ - { 0x12, 0x80 }, /* COMH reset */ { 0x12, 0x00 }, /* QXGA, master */ @@ -650,7 +699,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMI[0] "Exposure control" * = 0 (0x00) .......0 "Manual" */ - { 0x13, 0xC0 }, + { 0x13, 0xc0 }, /* * 09 COMC "Common Control C" @@ -706,7 +755,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COME[0] "Auto zero circuit select" * = 1 (0x01) .......1 "On" */ - { 0x0d, 0xA1 }, + { 0x0d, 0xa1 }, /* * 0E COMF "Common Control F" @@ -770,7 +819,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMJ[0] "Reserved" * = 0 (0x00) .......0 */ - { 0x14, 0xC6 }, + { 0x14, 0xc6 }, /* * 15 COMK "Common Control K" @@ -876,7 +925,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * FVOPT[7:0] "Range" * = 31 (0x1F) 00011111 */ - { 0x3c, 0x1F }, + { 0x3c, 0x1f }, /* * 44 Undocumented = 0 (0x00) 00000000 @@ -925,7 +974,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * 48[7:0] "It's a secret" * = 192 (0xC0) 11000000 */ - { 0x48, 0xC0 }, + { 0x48, 0xc0 }, /* * 49 Undocumented = 25 (0x19) 00011001 @@ -939,18 +988,18 @@ static const struct ov_i2c_regvals norm_3620b[] = { * 4B[7:0] "It's a secret" * = 128 (0x80) 10000000 */ - { 0x4B, 0x80 }, + { 0x4b, 0x80 }, /* * 4D Undocumented = 196 (0xC4) 11000100 * 4D[7:0] "It's a secret" * = 196 (0xC4) 11000100 */ - { 0x4D, 0xC4 }, + { 0x4d, 0xc4 }, /* * 35 VREF "Reference Voltage Control" - * = 76 (0x4C) 01001100 + * = 76 (0x4c) 01001100 * VREF[7:5] "Column high reference control" * = 2 (0x02) 010..... "higher voltage" * VREF[4:2] "Column low reference control" @@ -958,21 +1007,21 @@ static const struct ov_i2c_regvals norm_3620b[] = { * VREF[1:0] "Reserved" * = 0 (0x00) ......00 */ - { 0x35, 0x4C }, + { 0x35, 0x4c }, /* * 3D Undocumented = 0 (0x00) 00000000 * 3D[7:0] "It's a secret" * = 0 (0x00) 00000000 */ - { 0x3D, 0x00 }, + { 0x3d, 0x00 }, /* * 3E Undocumented = 0 (0x00) 00000000 * 3E[7:0] "It's a secret" * = 0 (0x00) 00000000 */ - { 0x3E, 0x00 }, + { 0x3e, 0x00 }, /* * 3B FREFB "Internal Reference Adjustment" @@ -1012,7 +1061,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * VBLM[3:0] "Sensor current control" * = 10 (0x0A) ....1010 */ - { 0x34, 0x5A }, + { 0x34, 0x5a }, /* * 3B FREFB "Internal Reference Adjustment" @@ -1078,7 +1127,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFST[7:0] "Horizontal window start, 8 MSBs" * = 31 (0x1F) 00011111 */ - { 0x17, 0x1F }, + { 0x17, 0x1f }, /* * 18 HREFEND "Horizontal window end" @@ -1086,7 +1135,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFEND[7:0] "Horizontal Window End, 8 MSBs" * = 95 (0x5F) 01011111 */ - { 0x18, 0x5F }, + { 0x18, 0x5f }, /* * 19 VSTRT "Vertical window start" @@ -1126,7 +1175,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMA[1:0] "Vertical window start line control 2 LSBs" * = 2 (0x02) ......10 */ - { 0x03, 0x4A }, + { 0x03, 0x4a }, /* * 11 CLKRC "Clock Rate Control" @@ -1183,7 +1232,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFST[7:0] "Horizontal window start, 8 MSBs" * = 31 (0x1F) 00011111 */ - { 0x17, 0x1F }, + { 0x17, 0x1f }, /* * 18 HREFEND "Horizontal window end" @@ -1191,7 +1240,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFEND[7:0] "Horizontal Window End, 8 MSBs" * = 95 (0x5F) 01011111 */ - { 0x18, 0x5F }, + { 0x18, 0x5f }, /* * 19 VSTRT "Vertical window start" @@ -1231,7 +1280,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMA[1:0] "Vertical window start line control 2 LSBs" * = 2 (0x02) ......10 */ - { 0x03, 0x4A }, + { 0x03, 0x4a }, /* * 02 RED "Red Gain Control" @@ -1241,7 +1290,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * RED[6:0] "Value" * = 47 (0x2F) .0101111 */ - { 0x02, 0xAF }, + { 0x02, 0xaf }, /* * 2D ADDVSL "VSYNC Pulse Width" @@ -1249,7 +1298,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * ADDVSL[7:0] "VSYNC pulse width, LSB" * = 210 (0xD2) 11010010 */ - { 0x2d, 0xD2 }, + { 0x2d, 0xd2 }, /* * 00 GAIN = 24 (0x18) 00011000 @@ -1272,7 +1321,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * BLUE[6:0] "Value" * = 112 (0x70) .1110000 */ - { 0x01, 0xF0 }, + { 0x01, 0xf0 }, /* * 10 AEC "Automatic Exposure Control" @@ -1280,14 +1329,14 @@ static const struct ov_i2c_regvals norm_3620b[] = { * AEC[7:0] "Automatic Exposure Control, 8 MSBs" * = 10 (0x0A) 00001010 */ - { 0x10, 0x0A }, - - { 0xE1, 0x67 }, - { 0xE3, 0x03 }, - { 0xE4, 0x26 }, - { 0xE5, 0x3E }, - { 0xF8, 0x01 }, - { 0xFF, 0x01 }, + { 0x10, 0x0a }, + + { 0xe1, 0x67 }, + { 0xe3, 0x03 }, + { 0xe4, 0x26 }, + { 0xe5, 0x3e }, + { 0xf8, 0x01 }, + { 0xff, 0x01 }, }; static const struct ov_i2c_regvals norm_6x20[] = { @@ -1296,7 +1345,7 @@ static const struct ov_i2c_regvals norm_6x20[] = { { 0x03, 0x60 }, { 0x05, 0x7f }, /* For when autoadjust is off */ { 0x07, 0xa8 }, - /* The ratio of 0x0c and 0x0d controls the white point */ + /* The ratio of 0x0c and 0x0d controls the white point */ { 0x0c, 0x24 }, { 0x0d, 0x24 }, { 0x0f, 0x15 }, /* COMS */ @@ -1464,7 +1513,7 @@ static const struct ov_i2c_regvals norm_7620[] = { { 0x00, 0x00 }, /* gain */ { 0x01, 0x80 }, /* blue gain */ { 0x02, 0x80 }, /* red gain */ - { 0x03, 0xc0 }, /* OV7670_REG_VREF */ + { 0x03, 0xc0 }, /* OV7670_R03_VREF */ { 0x06, 0x60 }, { 0x07, 0x00 }, { 0x0c, 0x24 }, @@ -1532,33 +1581,177 @@ static const struct ov_i2c_regvals norm_7640[] = { { 0x12, 0x14 }, }; +static const struct ov_regvals init_519_ov7660[] = { + { 0x5d, 0x03 }, /* Turn off suspend mode */ + { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */ + { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { 0xa2, 0x20 }, /* a2-a5 are undocumented */ + { 0xa3, 0x18 }, + { 0xa4, 0x04 }, + { 0xa5, 0x28 }, + { 0x37, 0x00 }, /* SetUsbInit */ + { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ + /* Enable both fields, YUV Input, disable defect comp (why?) */ + { 0x20, 0x0c }, /* 0x0d does U <-> V swap */ + { 0x21, 0x38 }, + { 0x22, 0x1d }, + { 0x17, 0x50 }, /* undocumented */ + { 0x37, 0x00 }, /* undocumented */ + { 0x40, 0xff }, /* I2C timeout counter */ + { 0x46, 0x00 }, /* I2C clock prescaler */ +}; +static const struct ov_i2c_regvals norm_7660[] = { + {OV7670_R12_COM7, OV7670_COM7_RESET}, + {OV7670_R11_CLKRC, 0x81}, + {0x92, 0x00}, /* DM_LNL */ + {0x93, 0x00}, /* DM_LNH */ + {0x9d, 0x4c}, /* BD50ST */ + {0x9e, 0x3f}, /* BD60ST */ + {OV7670_R3B_COM11, 0x02}, + {OV7670_R13_COM8, 0xf5}, + {OV7670_R10_AECH, 0x00}, + {OV7670_R00_GAIN, 0x00}, + {OV7670_R01_BLUE, 0x7c}, + {OV7670_R02_RED, 0x9d}, + {OV7670_R12_COM7, 0x00}, + {OV7670_R04_COM1, 00}, + {OV7670_R18_HSTOP, 0x01}, + {OV7670_R17_HSTART, 0x13}, + {OV7670_R32_HREF, 0x92}, + {OV7670_R19_VSTART, 0x02}, + {OV7670_R1A_VSTOP, 0x7a}, + {OV7670_R03_VREF, 0x00}, + {OV7670_R0E_COM5, 0x04}, + {OV7670_R0F_COM6, 0x62}, + {OV7670_R15_COM10, 0x00}, + {0x16, 0x02}, /* RSVD */ + {0x1b, 0x00}, /* PSHFT */ + {OV7670_R1E_MVFP, 0x01}, + {0x29, 0x3c}, /* RSVD */ + {0x33, 0x00}, /* CHLF */ + {0x34, 0x07}, /* ARBLM */ + {0x35, 0x84}, /* RSVD */ + {0x36, 0x00}, /* RSVD */ + {0x37, 0x04}, /* ADC */ + {0x39, 0x43}, /* OFON */ + {OV7670_R3A_TSLB, 0x00}, + {OV7670_R3C_COM12, 0x6c}, + {OV7670_R3D_COM13, 0x98}, + {OV7670_R3F_EDGE, 0x23}, + {OV7670_R40_COM15, 0xc1}, + {OV7670_R41_COM16, 0x22}, + {0x6b, 0x0a}, /* DBLV */ + {0xa1, 0x08}, /* RSVD */ + {0x69, 0x80}, /* HV */ + {0x43, 0xf0}, /* RSVD.. */ + {0x44, 0x10}, + {0x45, 0x78}, + {0x46, 0xa8}, + {0x47, 0x60}, + {0x48, 0x80}, + {0x59, 0xba}, + {0x5a, 0x9a}, + {0x5b, 0x22}, + {0x5c, 0xb9}, + {0x5d, 0x9b}, + {0x5e, 0x10}, + {0x5f, 0xe0}, + {0x60, 0x85}, + {0x61, 0x60}, + {0x9f, 0x9d}, /* RSVD */ + {0xa0, 0xa0}, /* DSPC2 */ + {0x4f, 0x60}, /* matrix */ + {0x50, 0x64}, + {0x51, 0x04}, + {0x52, 0x18}, + {0x53, 0x3c}, + {0x54, 0x54}, + {0x55, 0x40}, + {0x56, 0x40}, + {0x57, 0x40}, + {0x58, 0x0d}, /* matrix sign */ + {0x8b, 0xcc}, /* RSVD */ + {0x8c, 0xcc}, + {0x8d, 0xcf}, + {0x6c, 0x40}, /* gamma curve */ + {0x6d, 0xe0}, + {0x6e, 0xa0}, + {0x6f, 0x80}, + {0x70, 0x70}, + {0x71, 0x80}, + {0x72, 0x60}, + {0x73, 0x60}, + {0x74, 0x50}, + {0x75, 0x40}, + {0x76, 0x38}, + {0x77, 0x3c}, + {0x78, 0x32}, + {0x79, 0x1a}, + {0x7a, 0x28}, + {0x7b, 0x24}, + {0x7c, 0x04}, /* gamma curve */ + {0x7d, 0x12}, + {0x7e, 0x26}, + {0x7f, 0x46}, + {0x80, 0x54}, + {0x81, 0x64}, + {0x82, 0x70}, + {0x83, 0x7c}, + {0x84, 0x86}, + {0x85, 0x8e}, + {0x86, 0x9c}, + {0x87, 0xab}, + {0x88, 0xc4}, + {0x89, 0xd1}, + {0x8a, 0xe5}, + {OV7670_R14_COM9, 0x1e}, + {OV7670_R24_AEW, 0x80}, + {OV7670_R25_AEB, 0x72}, + {OV7670_R26_VPT, 0xb3}, + {0x62, 0x80}, /* LCC1 */ + {0x63, 0x80}, /* LCC2 */ + {0x64, 0x06}, /* LCC3 */ + {0x65, 0x00}, /* LCC4 */ + {0x66, 0x01}, /* LCC5 */ + {0x94, 0x0e}, /* RSVD.. */ + {0x95, 0x14}, + {OV7670_R13_COM8, OV7670_COM8_FASTAEC + | OV7670_COM8_AECSTEP + | OV7670_COM8_BFILT + | 0x10 + | OV7670_COM8_AGC + | OV7670_COM8_AWB + | OV7670_COM8_AEC}, + {0xa1, 0xc8} +}; + /* 7670. Defaults taken from OmniVision provided data, * as provided by Jonathan Corbet of OLPC */ static const struct ov_i2c_regvals norm_7670[] = { - { OV7670_REG_COM7, OV7670_COM7_RESET }, - { OV7670_REG_TSLB, 0x04 }, /* OV */ - { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ - { OV7670_REG_CLKRC, 0x01 }, + { OV7670_R12_COM7, OV7670_COM7_RESET }, + { OV7670_R3A_TSLB, 0x04 }, /* OV */ + { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ + { OV7670_R11_CLKRC, 0x01 }, /* * Set the hardware window. These values from OV don't entirely * make sense - hstop is less than hstart. But they work... */ - { OV7670_REG_HSTART, 0x13 }, - { OV7670_REG_HSTOP, 0x01 }, - { OV7670_REG_HREF, 0xb6 }, - { OV7670_REG_VSTART, 0x02 }, - { OV7670_REG_VSTOP, 0x7a }, - { OV7670_REG_VREF, 0x0a }, - - { OV7670_REG_COM3, 0x00 }, - { OV7670_REG_COM14, 0x00 }, + { OV7670_R17_HSTART, 0x13 }, + { OV7670_R18_HSTOP, 0x01 }, + { OV7670_R32_HREF, 0xb6 }, + { OV7670_R19_VSTART, 0x02 }, + { OV7670_R1A_VSTOP, 0x7a }, + { OV7670_R03_VREF, 0x0a }, + + { OV7670_R0C_COM3, 0x00 }, + { OV7670_R3E_COM14, 0x00 }, /* Mystery scaling numbers */ { 0x70, 0x3a }, { 0x71, 0x35 }, { 0x72, 0x11 }, { 0x73, 0xf0 }, { 0xa2, 0x02 }, -/* { OV7670_REG_COM10, 0x0 }, */ +/* { OV7670_R15_COM10, 0x0 }, */ /* Gamma curve values */ { 0x7a, 0x20 }, @@ -1580,37 +1773,37 @@ static const struct ov_i2c_regvals norm_7670[] = { /* AGC and AEC parameters. Note we start by disabling those features, then turn them only after tweaking the values. */ - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT }, - { OV7670_REG_GAIN, 0x00 }, - { OV7670_REG_AECH, 0x00 }, - { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ - { 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 }, + { OV7670_R00_GAIN, 0x00 }, + { OV7670_R10_AECH, 0x00 }, + { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */ + { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ + { OV7670_RA5_BD50MAX, 0x05 }, + { OV7670_RAB_BD60MAX, 0x07 }, + { OV7670_R24_AEW, 0x95 }, + { OV7670_R25_AEB, 0x33 }, + { OV7670_R26_VPT, 0xe3 }, + { OV7670_R9F_HAECC1, 0x78 }, + { OV7670_RA0_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */ - { OV7670_REG_HAECC3, 0xd8 }, - { OV7670_REG_HAECC4, 0xd8 }, - { OV7670_REG_HAECC5, 0xf0 }, - { OV7670_REG_HAECC6, 0x90 }, - { OV7670_REG_HAECC7, 0x94 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_RA6_HAECC3, 0xd8 }, + { OV7670_RA7_HAECC4, 0xd8 }, + { OV7670_RA8_HAECC5, 0xf0 }, + { OV7670_RA9_HAECC6, 0x90 }, + { OV7670_RAA_HAECC7, 0x94 }, + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT | OV7670_COM8_AGC | OV7670_COM8_AEC }, /* Almost all of these are magic "reserved" values. */ - { OV7670_REG_COM5, 0x61 }, - { OV7670_REG_COM6, 0x4b }, + { OV7670_R0E_COM5, 0x61 }, + { OV7670_R0F_COM6, 0x4b }, { 0x16, 0x02 }, - { OV7670_REG_MVFP, 0x07 }, + { OV7670_R1E_MVFP, 0x07 }, { 0x21, 0x02 }, { 0x22, 0x91 }, { 0x29, 0x07 }, @@ -1619,10 +1812,10 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x37, 0x1d }, { 0x38, 0x71 }, { 0x39, 0x2a }, - { OV7670_REG_COM12, 0x78 }, + { OV7670_R3C_COM12, 0x78 }, { 0x4d, 0x40 }, { 0x4e, 0x20 }, - { OV7670_REG_GFIX, 0x00 }, + { OV7670_R69_GFIX, 0x00 }, { 0x6b, 0x4a }, { 0x74, 0x10 }, { 0x8d, 0x4f }, @@ -1657,9 +1850,9 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x6f, 0x9f }, /* "9e for advance AWB" */ { 0x6a, 0x40 }, - { OV7670_REG_BLUE, 0x40 }, - { OV7670_REG_RED, 0x60 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_R01_BLUE, 0x40 }, + { OV7670_R02_RED, 0x60 }, + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT | OV7670_COM8_AGC @@ -1675,22 +1868,22 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x54, 0x80 }, { 0x58, 0x9e }, - { OV7670_REG_COM16, OV7670_COM16_AWBGAIN }, - { OV7670_REG_EDGE, 0x00 }, + { OV7670_R41_COM16, OV7670_COM16_AWBGAIN }, + { OV7670_R3F_EDGE, 0x00 }, { 0x75, 0x05 }, { 0x76, 0xe1 }, { 0x4c, 0x00 }, { 0x77, 0x01 }, - { OV7670_REG_COM13, OV7670_COM13_GAMMA + { OV7670_R3D_COM13, OV7670_COM13_GAMMA | OV7670_COM13_UVSAT | 2}, /* was 3 */ { 0x4b, 0x09 }, { 0xc9, 0x60 }, - { OV7670_REG_COM16, 0x38 }, + { OV7670_R41_COM16, 0x38 }, { 0x56, 0x40 }, { 0x34, 0x11 }, - { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, + { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, { 0xa4, 0x88 }, { 0x96, 0x00 }, { 0x97, 0x30 }, @@ -1825,10 +2018,13 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) } /* Write a OV519 register */ -static int reg_w(struct sd *sd, __u16 index, __u16 value) +static void reg_w(struct sd *sd, u16 index, u16 value) { int ret, req = 0; + if (sd->gspca_dev.usb_err < 0) + return; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -1838,6 +2034,8 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value) req = 0x0a; /* fall through */ case BRIDGE_W9968CF: + PDEBUG(D_USBO, "SET %02x %04x %04x", + req, value, index); ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), req, @@ -1848,6 +2046,8 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value) req = 1; } + PDEBUG(D_USBO, "SET %02x 0000 %04x %02x", + req, index, value); sd->gspca_dev.usb_buf[0] = value; ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), @@ -1857,22 +2057,22 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value) sd->gspca_dev.usb_buf, 1, 500); leave: if (ret < 0) { - err("Write reg 0x%04x -> [0x%02x] failed", - value, index); - return ret; + err("reg_w %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; + return; } - - PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); - return 0; } /* Read from a OV519 register, note not valid for the w9968cf!! */ /* returns: negative is error, pos or zero is data */ -static int reg_r(struct sd *sd, __u16 index) +static int reg_r(struct sd *sd, u16 index) { int ret; int req; + if (sd->gspca_dev.usb_err < 0) + return -1; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -1893,29 +2093,37 @@ static int reg_r(struct sd *sd, __u16 index) if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); - } else - err("Read reg [0x%02x] failed", index); + PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", + req, index, ret); + } else { + err("reg_r %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; + } return ret; } /* Read 8 values from a OV519 register */ static int reg_r8(struct sd *sd, - __u16 index) + u16 index) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 1, /* REQ_IO */ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, 8, 500); - if (ret >= 0) + if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - else - err("Read reg 8 [0x%02x] failed", index); + } else { + err("reg_r8 %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; + } return ret; } @@ -1926,34 +2134,37 @@ static int reg_r8(struct sd *sd, * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */ -static int reg_w_mask(struct sd *sd, - __u16 index, - __u8 value, - __u8 mask) +static void reg_w_mask(struct sd *sd, + u16 index, + u8 value, + u8 mask) { int ret; - __u8 oldval; + u8 oldval; if (mask != 0xff) { value &= mask; /* Enforce mask on value */ ret = reg_r(sd, index); if (ret < 0) - return ret; + return; oldval = ret & ~mask; /* Clear the masked bits */ value |= oldval; /* Set the desired bits */ } - return reg_w(sd, index, value); + reg_w(sd, index, value); } /* * Writes multiple (n) byte value to a single register. Only valid with certain * registers (0x30 and 0xc4 - 0xce). */ -static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) +static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); ret = usb_control_msg(sd->gspca_dev.dev, @@ -1963,69 +2174,55 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) 0, index, sd->gspca_dev.usb_buf, n, 500); if (ret < 0) { - err("Write reg32 [%02x] %08x failed", index, value); - return ret; + err("reg_w32 %02x failed %d", index, ret); + sd->gspca_dev.usb_err = ret; } - - return 0; } -static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) +static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value) { int rc, retries; - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value); /* Three byte write cycle */ for (retries = 6; ; ) { /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_3, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_3, reg); /* Write "value" to I2C data port of OV511 */ - rc = reg_w(sd, R51x_I2C_DATA, value); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_DATA, value); /* Initiate 3-byte write cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x01); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x01); do { rc = reg_r(sd, R511_I2C_CTL); } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ if (rc < 0) - return rc; + return; if ((rc & 2) == 0) /* Ack? */ break; if (--retries < 0) { PDEBUG(D_USBO, "i2c write retries exhausted"); - return -1; + return; } } - - return 0; } -static int ov511_i2c_r(struct sd *sd, __u8 reg) +static int ov511_i2c_r(struct sd *sd, u8 reg) { int rc, value, retries; /* Two byte write cycle */ for (retries = 6; ; ) { /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_2, reg); /* Initiate 2-byte write cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x03); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x03); do { rc = reg_r(sd, R511_I2C_CTL); @@ -2049,9 +2246,7 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) /* Two byte read cycle */ for (retries = 6; ; ) { /* Initiate 2-byte read cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x05); do { rc = reg_r(sd, R511_I2C_CTL); @@ -2064,9 +2259,7 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) break; /* I2C abort */ - rc = reg_w(sd, R511_I2C_CTL, 0x10); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x10); if (--retries < 0) { PDEBUG(D_USBI, "i2c read retries exhausted"); @@ -2076,12 +2269,10 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) value = reg_r(sd, R51x_I2C_DATA); - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value); /* This is needed to make i2c_w() work */ - rc = reg_w(sd, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x05); return value; } @@ -2091,32 +2282,24 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) * This is normally only called from i2c_w(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int ov518_i2c_w(struct sd *sd, - __u8 reg, - __u8 value) +static void ov518_i2c_w(struct sd *sd, + u8 reg, + u8 value) { - int rc; - - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value); /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_3, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_3, reg); /* Write "value" to I2C data port of OV511 */ - rc = reg_w(sd, R51x_I2C_DATA, value); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_DATA, value); /* Initiate 3-byte write cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x01); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x01); /* wait for write complete */ msleep(4); - return reg_r8(sd, R518_I2C_CTL); + reg_r8(sd, R518_I2C_CTL); } /* @@ -2126,105 +2309,102 @@ static int ov518_i2c_w(struct sd *sd, * This is normally only called from i2c_r(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int ov518_i2c_r(struct sd *sd, __u8 reg) +static int ov518_i2c_r(struct sd *sd, u8 reg) { - int rc, value; + int value; /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_2, reg); /* Initiate 2-byte write cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x03); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x03); /* Initiate 2-byte read cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x05); value = reg_r(sd, R51x_I2C_DATA); - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value); return value; } -static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) +static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), 0x02, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (__u16)value, (__u16)reg, NULL, 0, 500); + (u16) value, (u16) reg, NULL, 0, 500); if (ret < 0) { - err("i2c 0x%02x -> [0x%02x] failed", value, reg); - return ret; + err("ovfx2_i2c_w %02x failed %d", reg, ret); + sd->gspca_dev.usb_err = ret; } - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); - return 0; + PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value); } -static int ovfx2_i2c_r(struct sd *sd, __u8 reg) +static int ovfx2_i2c_r(struct sd *sd, u8 reg) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 0x03, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500); + 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500); if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); - } else - err("i2c read [0x%02x] failed", reg); + PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret); + } else { + err("ovfx2_i2c_r %02x failed %d", reg, ret); + sd->gspca_dev.usb_err = ret; + } return ret; } -static int i2c_w(struct sd *sd, __u8 reg, __u8 value) +static void i2c_w(struct sd *sd, u8 reg, u8 value) { - int ret = -1; - if (sd->sensor_reg_cache[reg] == value) - return 0; + return; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_i2c_w(sd, reg, value); + ov511_i2c_w(sd, reg, value); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: case BRIDGE_OV519: - ret = ov518_i2c_w(sd, reg, value); + ov518_i2c_w(sd, reg, value); break; case BRIDGE_OVFX2: - ret = ovfx2_i2c_w(sd, reg, value); + ovfx2_i2c_w(sd, reg, value); break; case BRIDGE_W9968CF: - ret = w9968cf_i2c_w(sd, reg, value); + w9968cf_i2c_w(sd, reg, value); break; } - if (ret >= 0) { + if (sd->gspca_dev.usb_err >= 0) { /* Up on sensor reset empty the register cache */ if (reg == 0x12 && (value & 0x80)) memset(sd->sensor_reg_cache, -1, - sizeof(sd->sensor_reg_cache)); + sizeof(sd->sensor_reg_cache)); else sd->sensor_reg_cache[reg] = value; } - - return ret; } -static int i2c_r(struct sd *sd, __u8 reg) +static int i2c_r(struct sd *sd, u8 reg) { int ret = -1; @@ -2260,95 +2440,99 @@ static int i2c_r(struct sd *sd, __u8 reg) * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */ -static int i2c_w_mask(struct sd *sd, - __u8 reg, - __u8 value, - __u8 mask) +static void i2c_w_mask(struct sd *sd, + u8 reg, + u8 value, + u8 mask) { int rc; - __u8 oldval; + u8 oldval; value &= mask; /* Enforce mask on value */ rc = i2c_r(sd, reg); if (rc < 0) - return rc; + return; oldval = rc & ~mask; /* Clear the masked bits */ value |= oldval; /* Set the desired bits */ - return i2c_w(sd, reg, value); + i2c_w(sd, reg, value); } /* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */ -static inline int ov51x_stop(struct sd *sd) +static inline void ov51x_stop(struct sd *sd) { PDEBUG(D_STREAM, "stopping"); sd->stopped = 1; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return reg_w(sd, R51x_SYS_RESET, 0x3d); + reg_w(sd, R51x_SYS_RESET, 0x3d); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); + reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); + break; case BRIDGE_OV519: - return reg_w(sd, OV519_SYS_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x00); + reg_w(sd, 0x22, 0x00); /* FRAR */ + break; case BRIDGE_OVFX2: - return reg_w_mask(sd, 0x0f, 0x00, 0x02); + reg_w_mask(sd, 0x0f, 0x00, 0x02); + break; case BRIDGE_W9968CF: - return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ + reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ + break; } - - return 0; } /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not * actually stopped (for performance). */ -static inline int ov51x_restart(struct sd *sd) +static inline void ov51x_restart(struct sd *sd) { - int rc; - PDEBUG(D_STREAM, "restarting"); if (!sd->stopped) - return 0; + return; sd->stopped = 0; /* Reinitialize the stream */ switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return reg_w(sd, R51x_SYS_RESET, 0x00); + reg_w(sd, R51x_SYS_RESET, 0x00); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - rc = reg_w(sd, 0x2f, 0x80); - if (rc < 0) - return rc; - return reg_w(sd, R51x_SYS_RESET, 0x00); + reg_w(sd, 0x2f, 0x80); + reg_w(sd, R51x_SYS_RESET, 0x00); + break; case BRIDGE_OV519: - return reg_w(sd, OV519_SYS_RESET1, 0x00); + reg_w(sd, OV519_R51_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x00); + reg_w(sd, 0x22, 0x1d); /* FRAR */ + break; case BRIDGE_OVFX2: - return reg_w_mask(sd, 0x0f, 0x02, 0x02); + reg_w_mask(sd, 0x0f, 0x02, 0x02); + break; case BRIDGE_W9968CF: - return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ + reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ + break; } - - return 0; } -static int ov51x_set_slave_ids(struct sd *sd, __u8 slave); +static void ov51x_set_slave_ids(struct sd *sd, u8 slave); /* This does an initial reset of an OmniVision sensor and ensures that I2C * is synchronized. Returns <0 on failure. */ -static int init_ov_sensor(struct sd *sd, __u8 slave) +static int init_ov_sensor(struct sd *sd, u8 slave) { int i; - if (ov51x_set_slave_ids(sd, slave) < 0) - return -EIO; + ov51x_set_slave_ids(sd, slave); /* Reset the sensor */ - if (i2c_w(sd, 0x12, 0x80) < 0) - return -EIO; + i2c_w(sd, 0x12, 0x80); /* Wait for it to initialize */ msleep(150); @@ -2361,15 +2545,16 @@ static int init_ov_sensor(struct sd *sd, __u8 slave) } /* Reset the sensor */ - if (i2c_w(sd, 0x12, 0x80) < 0) - return -EIO; + i2c_w(sd, 0x12, 0x80); + /* Wait for it to initialize */ msleep(150); + /* Dummy read to sync I2C */ if (i2c_r(sd, 0x00) < 0) - return -EIO; + return -1; } - return -EIO; + return -1; } /* Set the read and write slave IDs. The "slave" argument is the write slave, @@ -2377,53 +2562,40 @@ static int init_ov_sensor(struct sd *sd, __u8 slave) * This should not be called from outside the i2c I/O functions. * Sets I2C read and write slave IDs. Returns <0 for error */ -static int ov51x_set_slave_ids(struct sd *sd, - __u8 slave) +static void ov51x_set_slave_ids(struct sd *sd, + u8 slave) { - int rc; - switch (sd->bridge) { case BRIDGE_OVFX2: - return reg_w(sd, OVFX2_I2C_ADDR, slave); + reg_w(sd, OVFX2_I2C_ADDR, slave); + return; case BRIDGE_W9968CF: sd->sensor_addr = slave; - return 0; + return; } - rc = reg_w(sd, R51x_I2C_W_SID, slave); - if (rc < 0) - return rc; - return reg_w(sd, R51x_I2C_R_SID, slave + 1); + reg_w(sd, R51x_I2C_W_SID, slave); + reg_w(sd, R51x_I2C_R_SID, slave + 1); } -static int write_regvals(struct sd *sd, +static void write_regvals(struct sd *sd, const struct ov_regvals *regvals, int n) { - int rc; - while (--n >= 0) { - rc = reg_w(sd, regvals->reg, regvals->val); - if (rc < 0) - return rc; + reg_w(sd, regvals->reg, regvals->val); regvals++; } - return 0; } -static int write_i2c_regvals(struct sd *sd, - const struct ov_i2c_regvals *regvals, - int n) +static void write_i2c_regvals(struct sd *sd, + const struct ov_i2c_regvals *regvals, + int n) { - int rc; - while (--n >= 0) { - rc = i2c_w(sd, regvals->reg, regvals->val); - if (rc < 0) - return rc; + i2c_w(sd, regvals->reg, regvals->val); regvals++; } - return 0; } /**************************************************************************** @@ -2433,13 +2605,13 @@ static int write_i2c_regvals(struct sd *sd, ***************************************************************************/ /* This initializes the OV2x10 / OV3610 / OV3620 */ -static int ov_hires_configure(struct sd *sd) +static void ov_hires_configure(struct sd *sd) { int high, low; if (sd->bridge != BRIDGE_OVFX2) { err("error hires sensors only supported with ovfx2"); - return -1; + return; } PDEBUG(D_PROBE, "starting ov hires configuration"); @@ -2455,20 +2627,15 @@ static int ov_hires_configure(struct sd *sd) PDEBUG(D_PROBE, "Sensor is an OV3610"); sd->sensor = SEN_OV3610; } else { - err("Error unknown sensor type: 0x%02x%02x", - high, low); - return -1; + err("Error unknown sensor type: %02x%02x", + high, low); } - - /* Set sensor-specific vars */ - return 0; } - /* This initializes the OV8110, OV8610 sensor. The OV8110 uses * the same register settings as the OV8610, since they are very similar. */ -static int ov8xx0_configure(struct sd *sd) +static void ov8xx0_configure(struct sd *sd) { int rc; @@ -2478,27 +2645,21 @@ static int ov8xx0_configure(struct sd *sd) rc = i2c_r(sd, OV7610_REG_COM_I); if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } - if ((rc & 3) == 1) { + if ((rc & 3) == 1) sd->sensor = SEN_OV8610; - } else { + else err("Unknown image sensor version: %d", rc & 3); - return -1; - } - - /* Set sensor-specific vars */ - return 0; } /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses * the same register settings as the OV7610, since they are very similar. */ -static int ov7xx0_configure(struct sd *sd) +static void ov7xx0_configure(struct sd *sd) { int rc, high, low; - PDEBUG(D_PROBE, "starting OV7xx0 configuration"); /* Detect sensor (sub)type */ @@ -2508,15 +2669,15 @@ static int ov7xx0_configure(struct sd *sd) * it appears to be wrongly detected as a 7610 by default */ if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } if ((rc & 3) == 3) { /* quick hack to make OV7670s work */ high = i2c_r(sd, 0x0a); low = i2c_r(sd, 0x0b); /* info("%x, %x", high, low); */ - if (high == 0x76 && low == 0x73) { - PDEBUG(D_PROBE, "Sensor is an OV7670"); + if (high == 0x76 && (low & 0xf0) == 0x70) { + PDEBUG(D_PROBE, "Sensor is an OV76%02x", low); sd->sensor = SEN_OV7670; } else { PDEBUG(D_PROBE, "Sensor is an OV7610"); @@ -2536,19 +2697,19 @@ static int ov7xx0_configure(struct sd *sd) high = i2c_r(sd, 0x0a); if (high < 0) { PDEBUG(D_ERR, "Error detecting camera chip PID"); - return high; + return; } low = i2c_r(sd, 0x0b); if (low < 0) { PDEBUG(D_ERR, "Error detecting camera chip VER"); - return low; + return; } if (high == 0x76) { switch (low) { case 0x30: err("Sensor is an OV7630/OV7635"); err("7630 is not supported by this driver"); - return -1; + return; case 0x40: PDEBUG(D_PROBE, "Sensor is an OV7645"); sd->sensor = SEN_OV7640; /* FIXME */ @@ -2561,9 +2722,14 @@ static int ov7xx0_configure(struct sd *sd) PDEBUG(D_PROBE, "Sensor is an OV7648"); sd->sensor = SEN_OV7648; break; + case 0x60: + PDEBUG(D_PROBE, "Sensor is a OV7660"); + sd->sensor = SEN_OV7660; + sd->invert_led = 0; + break; default: PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); - return -1; + return; } } else { PDEBUG(D_PROBE, "Sensor is an OV7620"); @@ -2571,15 +2737,11 @@ static int ov7xx0_configure(struct sd *sd) } } else { err("Unknown image sensor version: %d", rc & 3); - return -1; } - - /* Set sensor-specific vars */ - return 0; } /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ -static int ov6xx0_configure(struct sd *sd) +static void ov6xx0_configure(struct sd *sd) { int rc; PDEBUG(D_PROBE, "starting OV6xx0 configuration"); @@ -2588,7 +2750,7 @@ static int ov6xx0_configure(struct sd *sd) rc = i2c_r(sd, OV7610_REG_COM_I); if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } /* Ugh. The first two bits are the version bits, but @@ -2619,13 +2781,11 @@ static int ov6xx0_configure(struct sd *sd) break; default: err("FATAL: Unknown sensor version: 0x%02x", rc); - return -1; + return; } /* Set sensor-specific vars */ sd->sif = 1; - - return 0; } /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ @@ -2637,14 +2797,14 @@ static void ov51x_led_control(struct sd *sd, int on) switch (sd->bridge) { /* OV511 has no LED control */ case BRIDGE_OV511PLUS: - reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); + reg_w(sd, R511_SYS_LED_CTL, on); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); + reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02); break; case BRIDGE_OV519: - reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ + reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1); break; } } @@ -2679,7 +2839,7 @@ static void sd_reset_snapshot(struct gspca_dev *gspca_dev) } } -static int ov51x_upload_quan_tables(struct sd *sd) +static void ov51x_upload_quan_tables(struct sd *sd) { const unsigned char yQuanTable511[] = { 0, 1, 1, 2, 2, 3, 3, 4, @@ -2710,7 +2870,6 @@ static int ov51x_upload_quan_tables(struct sd *sd) 6, 6, 6, 6, 7, 7, 7, 8, 7, 7, 6, 7, 7, 7, 8, 8 }; - const unsigned char uvQuanTable518[] = { 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 7, 7, 7, 7, 7, @@ -2720,18 +2879,18 @@ static int ov51x_upload_quan_tables(struct sd *sd) const unsigned char *pYTable, *pUVTable; unsigned char val0, val1; - int i, size, rc, reg = R51x_COMP_LUT_BEGIN; + int i, size, reg = R51x_COMP_LUT_BEGIN; PDEBUG(D_PROBE, "Uploading quantization tables"); if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { pYTable = yQuanTable511; pUVTable = uvQuanTable511; - size = 32; + size = 32; } else { pYTable = yQuanTable518; pUVTable = uvQuanTable518; - size = 16; + size = 16; } for (i = 0; i < size; i++) { @@ -2740,30 +2899,23 @@ static int ov51x_upload_quan_tables(struct sd *sd) val0 &= 0x0f; val1 &= 0x0f; val0 |= val1 << 4; - rc = reg_w(sd, reg, val0); - if (rc < 0) - return rc; + reg_w(sd, reg, val0); val0 = *pUVTable++; val1 = *pUVTable++; val0 &= 0x0f; val1 &= 0x0f; val0 |= val1 << 4; - rc = reg_w(sd, reg + size, val0); - if (rc < 0) - return rc; + reg_w(sd, reg + size, val0); reg++; } - - return 0; } /* This initializes the OV511/OV511+ and the sensor */ -static int ov511_configure(struct gspca_dev *gspca_dev) +static void ov511_configure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int rc; /* For 511 and 511+ */ const struct ov_regvals init_511[] = { @@ -2809,42 +2961,27 @@ static int ov511_configure(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); - rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511)); - if (rc < 0) - return rc; + write_regvals(sd, init_511, ARRAY_SIZE(init_511)); switch (sd->bridge) { case BRIDGE_OV511: - rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); - if (rc < 0) - return rc; + write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); break; case BRIDGE_OV511PLUS: - rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); - if (rc < 0) - return rc; + write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); break; } /* Init compression */ - rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); - if (rc < 0) - return rc; - - rc = ov51x_upload_quan_tables(sd); - if (rc < 0) { - PDEBUG(D_ERR, "Error uploading quantization tables"); - return rc; - } + write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); - return 0; + ov51x_upload_quan_tables(sd); } /* This initializes the OV518/OV518+ and the sensor */ -static int ov518_configure(struct gspca_dev *gspca_dev) +static void ov518_configure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int rc; /* For 518 and 518+ */ const struct ov_regvals init_518[] = { @@ -2892,65 +3029,49 @@ static int ov518_configure(struct gspca_dev *gspca_dev) /* First 5 bits of custom ID reg are a revision ID on OV518 */ PDEBUG(D_PROBE, "Device revision %d", - 0x1F & reg_r(sd, R51x_SYS_CUST_ID)); + 0x1f & reg_r(sd, R51x_SYS_CUST_ID)); - rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518)); - if (rc < 0) - return rc; + write_regvals(sd, init_518, ARRAY_SIZE(init_518)); /* Set LED GPIO pin to output mode */ - rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); - if (rc < 0) - return rc; + reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); switch (sd->bridge) { case BRIDGE_OV518: - rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); - if (rc < 0) - return rc; + write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); break; case BRIDGE_OV518PLUS: - rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); - if (rc < 0) - return rc; + write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); break; } - rc = ov51x_upload_quan_tables(sd); - if (rc < 0) { - PDEBUG(D_ERR, "Error uploading quantization tables"); - return rc; - } + ov51x_upload_quan_tables(sd); - rc = reg_w(sd, 0x2f, 0x80); - if (rc < 0) - return rc; - - return 0; + reg_w(sd, 0x2f, 0x80); } -static int ov519_configure(struct sd *sd) +static void ov519_configure(struct sd *sd) { static const struct ov_regvals init_519[] = { - { 0x5a, 0x6d }, /* EnableSystem */ - { 0x53, 0x9b }, - { 0x54, 0xff }, /* set bit2 to enable jpeg */ - { 0x5d, 0x03 }, - { 0x49, 0x01 }, - { 0x48, 0x00 }, + { 0x5a, 0x6d }, /* EnableSystem */ + { 0x53, 0x9b }, + { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */ + { 0x5d, 0x03 }, + { 0x49, 0x01 }, + { 0x48, 0x00 }, /* Set LED pin to output mode. Bit 4 must be cleared or sensor * detection will fail. This deserves further investigation. */ { OV519_GPIO_IO_CTRL0, 0xee }, - { 0x51, 0x0f }, /* SetUsbInit */ - { 0x51, 0x00 }, - { 0x22, 0x00 }, + { OV519_R51_RESET1, 0x0f }, + { OV519_R51_RESET1, 0x00 }, + { 0x22, 0x00 }, /* windows reads 0x55 at this point*/ }; - return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); + write_regvals(sd, init_519, ARRAY_SIZE(init_519)); } -static int ovfx2_configure(struct sd *sd) +static void ovfx2_configure(struct sd *sd) { static const struct ov_regvals init_fx2[] = { { 0x00, 0x60 }, @@ -2964,7 +3085,92 @@ static int ovfx2_configure(struct sd *sd) sd->stopped = 1; - return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); + write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); +} + +/* set the mode */ +/* This function works for ov7660 only */ +static void ov519_set_mode(struct sd *sd) +{ + static const struct ov_regvals bridge_ov7660[2][10] = { + {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00}, + {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, + {0x25, 0x01}, {0x26, 0x00}}, + {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00}, + {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, + {0x25, 0x03}, {0x26, 0x00}} + }; + static const struct ov_i2c_regvals sensor_ov7660[2][3] = { + {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}}, + {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}} + }; + static const struct ov_i2c_regvals sensor_ov7660_2[] = { + {OV7670_R17_HSTART, 0x13}, + {OV7670_R18_HSTOP, 0x01}, + {OV7670_R32_HREF, 0x92}, + {OV7670_R19_VSTART, 0x02}, + {OV7670_R1A_VSTOP, 0x7a}, + {OV7670_R03_VREF, 0x00}, +/* {0x33, 0x00}, */ +/* {0x34, 0x07}, */ +/* {0x36, 0x00}, */ +/* {0x6b, 0x0a}, */ + }; + + write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode], + ARRAY_SIZE(bridge_ov7660[0])); + write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode], + ARRAY_SIZE(sensor_ov7660[0])); + write_i2c_regvals(sd, sensor_ov7660_2, + ARRAY_SIZE(sensor_ov7660_2)); +} + +/* set the frame rate */ +/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */ +static void ov519_set_fr(struct sd *sd) +{ + int fr; + u8 clock; + /* frame rate table with indices: + * - mode = 0: 320x240, 1: 640x480 + * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5 + * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock) + */ + static const u8 fr_tb[2][6][3] = { + {{0x04, 0xff, 0x00}, + {0x04, 0x1f, 0x00}, + {0x04, 0x1b, 0x00}, + {0x04, 0x15, 0x00}, + {0x04, 0x09, 0x00}, + {0x04, 0x01, 0x00}}, + {{0x0c, 0xff, 0x00}, + {0x0c, 0x1f, 0x00}, + {0x0c, 0x1b, 0x00}, + {0x04, 0xff, 0x01}, + {0x04, 0x1f, 0x01}, + {0x04, 0x1b, 0x01}}, + }; + + if (frame_rate > 0) + sd->frame_rate = frame_rate; + if (sd->frame_rate >= 30) + fr = 0; + else if (sd->frame_rate >= 25) + fr = 1; + else if (sd->frame_rate >= 20) + fr = 2; + else if (sd->frame_rate >= 15) + fr = 3; + else if (sd->frame_rate >= 10) + fr = 4; + else + fr = 5; + reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]); + reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]); + clock = fr_tb[sd->gspca_dev.curr_mode][fr][2]; + if (sd->sensor == SEN_OV7660) + clock |= 0x80; /* enable double clock */ + ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); } /* this function is called at probe time */ @@ -2973,99 +3179,119 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; - int ret = 0; sd->bridge = id->driver_info & BRIDGE_MASK; - sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; + sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_configure(gspca_dev); + cam->cam_mode = ov511_vga_mode; + cam->nmodes = ARRAY_SIZE(ov511_vga_mode); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ret = ov518_configure(gspca_dev); + cam->cam_mode = ov518_vga_mode; + cam->nmodes = ARRAY_SIZE(ov518_vga_mode); break; case BRIDGE_OV519: - ret = ov519_configure(sd); + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); + sd->invert_led = !sd->invert_led; break; case BRIDGE_OVFX2: - ret = ovfx2_configure(sd); + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); cam->bulk_size = OVFX2_BULK_SIZE; cam->bulk_nurbs = MAX_NURBS; cam->bulk = 1; break; case BRIDGE_W9968CF: - ret = w9968cf_configure(sd); + cam->cam_mode = w9968cf_vga_mode; + cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); cam->reverse_alts = 1; break; } - if (ret) - goto error; + gspca_dev->cam.ctrls = sd->ctrls; + sd->quality = QUALITY_DEF; - ov51x_led_control(sd, 0); /* turn LED off */ + return 0; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; + + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + ov511_configure(gspca_dev); + break; + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + ov518_configure(gspca_dev); + break; + case BRIDGE_OV519: + ov519_configure(sd); + break; + case BRIDGE_OVFX2: + ovfx2_configure(sd); + break; + case BRIDGE_W9968CF: + w9968cf_configure(sd); + break; + } /* The OV519 must be more aggressive about sensor detection since * I2C write will never fail if the sensor is not present. We have * to try to initialize the sensor to detect its presence */ + sd->sensor = -1; /* Test for 76xx */ if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { - if (ov7xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV7xx0"); - goto error; - } + ov7xx0_configure(sd); + /* Test for 6xx0 */ } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { - if (ov6xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV6xx0"); - goto error; - } + ov6xx0_configure(sd); + /* Test for 8xx0 */ } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { - if (ov8xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV8xx0"); - goto error; - } + ov8xx0_configure(sd); + /* Test for 3xxx / 2xxx */ } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { - if (ov_hires_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure high res OV"); - goto error; - } + ov_hires_configure(sd); } else { err("Can't determine sensor slave IDs"); goto error; } + if (sd->sensor < 0) + goto error; + + ov51x_led_control(sd, 0); /* turn LED off */ + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - if (!sd->sif) { - cam->cam_mode = ov511_vga_mode; - cam->nmodes = ARRAY_SIZE(ov511_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov511_sif_mode; cam->nmodes = ARRAY_SIZE(ov511_sif_mode); } break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - if (!sd->sif) { - cam->cam_mode = ov518_vga_mode; - cam->nmodes = ARRAY_SIZE(ov518_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov518_sif_mode; cam->nmodes = ARRAY_SIZE(ov518_sif_mode); } break; case BRIDGE_OV519: - if (!sd->sif) { - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov519_sif_mode; cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } @@ -3077,118 +3303,107 @@ static int sd_config(struct gspca_dev *gspca_dev, } else if (sd->sensor == SEN_OV3610) { cam->cam_mode = ovfx2_ov3610_mode; cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); - } else if (!sd->sif) { - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - } else { + } else if (sd->sif) { cam->cam_mode = ov519_sif_mode; cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } break; case BRIDGE_W9968CF: - cam->cam_mode = w9968cf_vga_mode; - cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); if (sd->sif) - cam->nmodes--; + cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1; /* w9968cf needs initialisation once the sensor is known */ - if (w9968cf_init(sd) < 0) - goto error; + w9968cf_init(sd); break; } - gspca_dev->cam.ctrls = sd->ctrls; - if (sd->sensor == SEN_OV7670) - gspca_dev->ctrl_dis = 1 << COLORS; - else - gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); - sd->quality = QUALITY_DEF; - if (sd->sensor == SEN_OV7640 || - sd->sensor == SEN_OV7648) - gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT) | (1 << CONTRAST); - if (sd->sensor == SEN_OV7670) - gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT; - /* OV8610 Frequency filter control should work but needs testing */ - if (sd->sensor == SEN_OV8610) - gspca_dev->ctrl_dis |= 1 << FREQ; - /* No controls for the OV2610/OV3610 */ - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - gspca_dev->ctrl_dis |= (1 << NCTRL) - 1; - return 0; -error: - PDEBUG(D_ERR, "OV519 Config failed"); - return -EBUSY; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; + gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; /* initialize the sensor */ switch (sd->sensor) { case SEN_OV2610: - if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610))) - return -EIO; + write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)); + /* Enable autogain, autoexpo, awb, bandfilter */ - if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) - return -EIO; + i2c_w_mask(sd, 0x13, 0x27, 0x27); break; case SEN_OV3610: - if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b))) - return -EIO; + write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)); + /* Enable autogain, autoexpo, awb, bandfilter */ - if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) - return -EIO; + i2c_w_mask(sd, 0x13, 0x27, 0x27); break; case SEN_OV6620: - if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) - return -EIO; + write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)); break; case SEN_OV6630: case SEN_OV66308AF: sd->ctrls[CONTRAST].def = 200; /* The default is too low for the ov6630 */ - if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) - return -EIO; + write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)); break; default: /* case SEN_OV7610: */ /* case SEN_OV76BE: */ - if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) - return -EIO; - if (i2c_w_mask(sd, 0x0e, 0x00, 0x40)) - return -EIO; + write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)); + i2c_w_mask(sd, 0x0e, 0x00, 0x40); break; case SEN_OV7620: case SEN_OV7620AE: - if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) - return -EIO; + write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)); break; case SEN_OV7640: case SEN_OV7648: - if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) - return -EIO; + write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); + break; + case SEN_OV7660: + i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET); + msleep(14); + reg_w(sd, OV519_R57_SNAPSHOT, 0x23); + write_regvals(sd, init_519_ov7660, + ARRAY_SIZE(init_519_ov7660)); + write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); + sd->gspca_dev.curr_mode = 1; /* 640x480 */ + sd->frame_rate = 15; + ov519_set_mode(sd); + ov519_set_fr(sd); + sd->ctrls[COLORS].max = 4; /* 0..4 */ + sd->ctrls[COLORS].val = + sd->ctrls[COLORS].def = 2; + setcolors(gspca_dev); + sd->ctrls[CONTRAST].max = 6; /* 0..6 */ + sd->ctrls[CONTRAST].val = + sd->ctrls[CONTRAST].def = 3; + setcontrast(gspca_dev); + sd->ctrls[BRIGHTNESS].max = 6; /* 0..6 */ + sd->ctrls[BRIGHTNESS].val = + sd->ctrls[BRIGHTNESS].def = 3; + setbrightness(gspca_dev); + sd_reset_snapshot(gspca_dev); + ov51x_restart(sd); + ov51x_stop(sd); /* not in win traces */ + ov51x_led_control(sd, 0); break; case SEN_OV7670: sd->ctrls[FREQ].max = 3; /* auto */ sd->ctrls[FREQ].def = 3; - if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) - return -EIO; + write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)); break; case SEN_OV8610: - if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) - return -EIO; + write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)); break; } - return 0; + return gspca_dev->usb_err; +error: + PDEBUG(D_ERR, "OV519 Config failed"); + return -EINVAL; } /* Set up the OV511/OV511+ with the given image parameters. * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov511_mode_init_regs(struct sd *sd) +static void ov511_mode_init_regs(struct sd *sd) { int hsegs, vsegs, packet_size, fps, needed; int interlaced = 0; @@ -3199,7 +3414,8 @@ static int ov511_mode_init_regs(struct sd *sd) alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); if (!alt) { err("Couldn't get altsetting"); - return -EIO; + sd->gspca_dev.usb_err = -EIO; + return; } packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); @@ -3302,8 +3518,6 @@ static int ov511_mode_init_regs(struct sd *sd) reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); reg_w(sd, R51x_SYS_RESET, 0); - - return 0; } /* Sets up the OV518/OV518+ with the given image parameters @@ -3313,7 +3527,7 @@ static int ov511_mode_init_regs(struct sd *sd) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov518_mode_init_regs(struct sd *sd) +static void ov518_mode_init_regs(struct sd *sd) { int hsegs, vsegs, packet_size; struct usb_host_interface *alt; @@ -3323,14 +3537,14 @@ static int ov518_mode_init_regs(struct sd *sd) alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); if (!alt) { err("Couldn't get altsetting"); - return -EIO; + sd->gspca_dev.usb_err = -EIO; + return; } packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); /******** Set the mode ********/ - reg_w(sd, 0x2b, 0); reg_w(sd, 0x2c, 0); reg_w(sd, 0x2d, 0); @@ -3364,7 +3578,7 @@ static int ov518_mode_init_regs(struct sd *sd) /* Windows driver does this here; who knows why */ reg_w(sd, 0x2f, 0x80); - /******** Set the framerate ********/ + /******** Set the framerate ********/ sd->clockdiv = 1; /* Mode independent, but framerate dependent, regs */ @@ -3427,11 +3641,8 @@ static int ov518_mode_init_regs(struct sd *sd) } reg_w(sd, 0x2f, 0x80); - - return 0; } - /* Sets up the OV519 with the given image parameters * * OV519 needs a completely different approach, until we can figure out what @@ -3439,12 +3650,12 @@ static int ov518_mode_init_regs(struct sd *sd) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov519_mode_init_regs(struct sd *sd) +static void ov519_mode_init_regs(struct sd *sd) { static const struct ov_regvals mode_init_519_ov7670[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ { 0xa2, 0x20 }, /* a2-a5 are undocumented */ { 0xa3, 0x18 }, { 0xa4, 0x04 }, @@ -3467,7 +3678,7 @@ static int ov519_mode_init_regs(struct sd *sd) static const struct ov_regvals mode_init_519[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ { 0xa2, 0x20 }, /* a2-a5 are undocumented */ { 0xa3, 0x18 }, { 0xa4, 0x04 }, @@ -3486,19 +3697,21 @@ static int ov519_mode_init_regs(struct sd *sd) }; /******** Set the mode ********/ - if (sd->sensor != SEN_OV7670) { - if (write_regvals(sd, mode_init_519, - ARRAY_SIZE(mode_init_519))) - return -EIO; + switch (sd->sensor) { + default: + write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); } - } else { - if (write_regvals(sd, mode_init_519_ov7670, - ARRAY_SIZE(mode_init_519_ov7670))) - return -EIO; + break; + case SEN_OV7660: + return; /* done by ov519_set_mode/fr() */ + case SEN_OV7670: + write_regvals(sd, mode_init_519_ov7670, + ARRAY_SIZE(mode_init_519_ov7670)); + break; } reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); @@ -3594,17 +3807,16 @@ static int ov519_mode_init_regs(struct sd *sd) } break; } - return 0; } -static int mode_init_ov_sensor_regs(struct sd *sd) +static void mode_init_ov_sensor_regs(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga, xstart, xend, ystart, yend; - __u8 v; + u8 v; gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; + qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; /******** Mode (VGA/QVGA) and sensor specific regs ********/ switch (sd->sensor) { @@ -3616,7 +3828,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); - return 0; + return; case SEN_OV3610: if (qvga) { xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); @@ -3640,7 +3852,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w(sd, 0x18, xend >> 4); i2c_w(sd, 0x19, ystart >> 3); i2c_w(sd, 0x1a, yend >> 3); - return 0; + return; case SEN_OV8610: /* For OV8610 qvga means qsvga */ i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); @@ -3687,11 +3899,11 @@ static int mode_init_ov_sensor_regs(struct sd *sd) /* set COM7_FMT_VGA or COM7_FMT_QVGA * do we need to set anything else? * HSTART etc are set in set_ov_sensor_window itself */ - i2c_w_mask(sd, OV7670_REG_COM7, + i2c_w_mask(sd, OV7670_R12_COM7, qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, OV7670_COM7_FMT_MASK); i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB, OV7670_COM8_AWB); if (qvga) { /* QVGA from ov7670.c by * Jonathan Corbet */ @@ -3707,21 +3919,21 @@ static int mode_init_ov_sensor_regs(struct sd *sd) } /* OV7670 hardware window registers are split across * multiple locations */ - i2c_w(sd, OV7670_REG_HSTART, xstart >> 3); - i2c_w(sd, OV7670_REG_HSTOP, xend >> 3); - v = i2c_r(sd, OV7670_REG_HREF); + i2c_w(sd, OV7670_R17_HSTART, xstart >> 3); + i2c_w(sd, OV7670_R18_HSTOP, xend >> 3); + v = i2c_r(sd, OV7670_R32_HREF); v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); msleep(10); /* need to sleep between read and write to * same reg! */ - i2c_w(sd, OV7670_REG_HREF, v); + i2c_w(sd, OV7670_R32_HREF, v); - i2c_w(sd, OV7670_REG_VSTART, ystart >> 2); - i2c_w(sd, OV7670_REG_VSTOP, yend >> 2); - v = i2c_r(sd, OV7670_REG_VREF); + i2c_w(sd, OV7670_R19_VSTART, ystart >> 2); + i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2); + v = i2c_r(sd, OV7670_R03_VREF); v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); msleep(10); /* need to sleep between read and write to * same reg! */ - i2c_w(sd, OV7670_REG_VREF, v); + i2c_w(sd, OV7670_R03_VREF, v); break; case SEN_OV6620: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); @@ -3734,46 +3946,50 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ break; default: - return -EINVAL; + return; } /******** Clock programming ********/ i2c_w(sd, 0x11, sd->clockdiv); - - return 0; } +/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */ static void sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor != SEN_OV7670) - return; if (sd->gspca_dev.streaming) - ov51x_stop(sd); - i2c_w_mask(sd, OV7670_REG_MVFP, + reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */ + i2c_w_mask(sd, OV7670_R1E_MVFP, OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val | OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val, OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); if (sd->gspca_dev.streaming) - ov51x_restart(sd); + reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */ } -static int set_ov_sensor_window(struct sd *sd) +static void set_ov_sensor_window(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga, crop; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; - int ret; /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || - sd->sensor == SEN_OV7670) - return mode_init_ov_sensor_regs(sd); + switch (sd->sensor) { + case SEN_OV2610: + case SEN_OV3610: + case SEN_OV7670: + mode_init_ov_sensor_regs(sd); + return; + case SEN_OV7660: + ov519_set_mode(sd); + ov519_set_fr(sd); + return; + } gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; - crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2; + qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; + crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; /* The different sensor ICs handle setting up of window differently. * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ @@ -3820,7 +4036,7 @@ static int set_ov_sensor_window(struct sd *sd) vwsbase = vwebase = 0x03; break; default: - return -EINVAL; + return; } switch (sd->sensor) { @@ -3855,23 +4071,18 @@ static int set_ov_sensor_window(struct sd *sd) } } - ret = mode_init_ov_sensor_regs(sd); - if (ret < 0) - return ret; + mode_init_ov_sensor_regs(sd); i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); i2c_w(sd, 0x19, vwsbase); i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); - - return 0; } /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int ret = 0; /* Default for most bridges, allow bridge_mode_init_regs to override */ sd->sensor_width = sd->gspca_dev.width; @@ -3880,50 +4091,46 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_mode_init_regs(sd); + ov511_mode_init_regs(sd); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ret = ov518_mode_init_regs(sd); + ov518_mode_init_regs(sd); break; case BRIDGE_OV519: - ret = ov519_mode_init_regs(sd); + ov519_mode_init_regs(sd); break; /* case BRIDGE_OVFX2: nothing to do */ case BRIDGE_W9968CF: - ret = w9968cf_mode_init_regs(sd); + w9968cf_mode_init_regs(sd); break; } - if (ret < 0) - goto out; - - ret = set_ov_sensor_window(sd); - if (ret < 0) - goto out; - - setcontrast(gspca_dev); - setbrightness(gspca_dev); - setcolors(gspca_dev); - sethvflip(gspca_dev); - setautobright(gspca_dev); - setfreq_i(sd); + + set_ov_sensor_window(sd); + + if (!(sd->gspca_dev.ctrl_dis & (1 << CONTRAST))) + setcontrast(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS))) + setbrightness(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS))) + setcolors(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP)))) + sethvflip(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT))) + setautobright(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ))) + setfreq_i(sd); /* Force clear snapshot state in case the snapshot button was pressed while we weren't streaming */ sd->snapshot_needs_reset = 1; sd_reset_snapshot(gspca_dev); - sd->snapshot_pressed = 0; sd->first_frame = 3; - ret = ov51x_restart(sd); - if (ret < 0) - goto out; + ov51x_restart(sd); ov51x_led_control(sd, 1); - return 0; -out: - PDEBUG(D_ERR, "camera start error:%d", ret); - return ret; + return gspca_dev->usb_err; } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -3938,8 +4145,21 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!sd->gspca_dev.present) + return; if (sd->bridge == BRIDGE_W9968CF) w9968cf_stop0(sd); + +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + /* If the last button state is pressed, release it now! */ + if (sd->snapshot_pressed) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + sd->snapshot_pressed = 0; + } +#endif + if (sd->bridge == BRIDGE_OV519) + reg_w(sd, OV519_R57_SNAPSHOT, 0x23); } static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) @@ -4160,6 +4380,22 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals brit_7660[][7] = { + {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90}, + {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}}, + {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1}, + {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}}, + {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2}, + {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}}, + {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3}, + {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}}, + {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3}, + {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}}, + {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3}, + {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}}, + {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4}, + {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}} + }; val = sd->ctrls[BRIGHTNESS].val; switch (sd->sensor) { @@ -4179,10 +4415,14 @@ static void setbrightness(struct gspca_dev *gspca_dev) if (!sd->ctrls[AUTOBRIGHT].val) i2c_w(sd, OV7610_REG_BRT, val); break; + case SEN_OV7660: + write_i2c_regvals(sd, brit_7660[val], + ARRAY_SIZE(brit_7660[0])); + break; case SEN_OV7670: /*win trace - * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ - i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); + * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ + i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val)); break; } } @@ -4191,6 +4431,64 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals contrast_7660[][31] = { + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0}, + {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30}, + {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24}, + {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65}, + {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83}, + {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f}, + {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94}, + {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30}, + {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24}, + {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62}, + {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81}, + {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1}, + {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84}, + {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40}, + {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24}, + {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d}, + {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81}, + {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e}, + {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70}, + {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48}, + {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34}, + {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58}, + {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80}, + {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9}, + {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}}, + {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80}, + {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60}, + {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38}, + {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e}, + {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46}, + {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c}, + {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4}, + {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}}, + {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80}, + {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30}, + {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50}, + {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08}, + {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a}, + {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b}, + {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3}, + {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}}, + {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60}, + {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8}, + {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c}, + {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04}, + {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22}, + {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b}, + {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde}, + {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}}, + }; val = sd->ctrls[CONTRAST].val; switch (sd->sensor) { @@ -4203,7 +4501,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); break; case SEN_OV8610: { - static const __u8 ctab[] = { + static const u8 ctab[] = { 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f }; @@ -4213,7 +4511,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) } case SEN_OV7620: case SEN_OV7620AE: { - static const __u8 ctab[] = { + static const u8 ctab[] = { 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff }; @@ -4222,9 +4520,13 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w(sd, 0x64, ctab[val >> 4]); break; } + case SEN_OV7660: + write_i2c_regvals(sd, contrast_7660[val], + ARRAY_SIZE(contrast_7660[0])); + break; case SEN_OV7670: /* check that this isn't just the same as ov7610 */ - i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); + i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); break; } } @@ -4233,6 +4535,18 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals colors_7660[][6] = { + {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a}, + {0x53, 0x19}, {0x54, 0x23}}, + {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11}, + {0x53, 0x2c}, {0x54, 0x3e}}, + {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19}, + {0x53, 0x40}, {0x54, 0x59}}, + {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20}, + {0x53, 0x53}, {0x54, 0x73}}, + {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28}, + {0x53, 0x66}, {0x54, 0x8e}}, + }; val = sd->ctrls[COLORS].val; switch (sd->sensor) { @@ -4256,6 +4570,10 @@ static void setcolors(struct gspca_dev *gspca_dev) case SEN_OV7648: i2c_w(sd, OV7610_REG_SAT, val & 0xf0); break; + case SEN_OV7660: + write_i2c_regvals(sd, colors_7660[val], + ARRAY_SIZE(colors_7660[0])); + break; case SEN_OV7670: /* supported later once I work out how to do it * transparently fail now! */ @@ -4268,38 +4586,31 @@ static void setautobright(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 || - sd->sensor == SEN_OV7670 || - sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - return; - i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10); } static void setfreq_i(struct sd *sd) { - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - return; - - if (sd->sensor == SEN_OV7670) { + if (sd->sensor == SEN_OV7660 + || sd->sensor == SEN_OV7670) { switch (sd->ctrls[FREQ].val) { case 0: /* Banding filter disabled */ - i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT); + i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); break; case 1: /* 50 hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18); + i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18); break; case 2: /* 60 hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18); + i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18); break; - case 3: /* Auto hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + case 3: /* Auto hz - ov7670 only */ + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO, + i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO, 0x18); break; } @@ -4443,14 +4754,14 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4064), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4068), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0155), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, @@ -4464,7 +4775,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, - {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, + {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 }, {} }; diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 88ef03f6235..0edf93973b1 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1243,34 +1243,26 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, } /* get stream parameters (framerate) */ -static int sd_get_streamparm(struct gspca_dev *gspca_dev, +static void sd_get_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - cp->capability |= V4L2_CAP_TIMEPERFRAME; tpf->numerator = 1; tpf->denominator = sd->frame_rate; - - return 0; } /* set stream parameters (framerate) */ -static int sd_set_streamparm(struct gspca_dev *gspca_dev, +static void sd_set_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - /* Set requested framerate */ sd->frame_rate = tpf->denominator / tpf->numerator; if (gspca_dev->streaming) @@ -1279,8 +1271,6 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, /* Return the actual framerate */ tpf->numerator = 1; tpf->denominator = sd->frame_rate; - - return 0; } /* sub-driver description */ diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c index e831f0d280e..c5244b4b477 100644 --- a/drivers/media/video/gspca/ov534_9.c +++ b/drivers/media/video/gspca/ov534_9.c @@ -945,7 +945,6 @@ static void setautogain(struct gspca_dev *gspca_dev) u8 val; /*fixme: should adjust agc/awb/aec by different controls */ - val = sd->autogain; val = sccb_read(gspca_dev, 0x13); /* com8 */ sccb_write(gspca_dev, 0xff, 0x00); if (sd->autogain) diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 15e97fa4c33..96f9986305b 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -162,7 +162,7 @@ static const __u8 pac207_sensor_init[][8] = { {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84}, {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, - {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00}, + {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00}, }; static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, @@ -228,7 +228,7 @@ static int sd_config(struct gspca_dev *gspca_dev, idreg[0] = pac207_read_reg(gspca_dev, 0x0000); idreg[1] = pac207_read_reg(gspca_dev, 0x0001); - idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4); + idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4); idreg[1] = idreg[1] & 0x0f; PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X", idreg[0], idreg[1]); diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 55fbea7381b..2700975abce 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -393,7 +393,7 @@ static const __u8 page3_7302[] = { static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, - const char *buffer, int len) + const u8 *buffer, int len) { int ret; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 7657b43b320..6820f5d58b1 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -261,7 +261,7 @@ static const __u8 page4_7311[] = { static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, - const char *buffer, int len) + const u8 *buffer, int len) { int ret; diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 6b155ae3a74..cb08d00d0a3 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -33,6 +33,14 @@ MODULE_LICENSE("GPL"); #define MODULE_NAME "sn9c20x" +/* + * Pixel format private data + */ +#define SCALE_MASK 0x0f +#define SCALE_160x120 0 +#define SCALE_320x240 1 +#define SCALE_640x480 2 +#define SCALE_1280x1024 3 #define MODE_RAW 0x10 #define MODE_JPEG 0x20 #define MODE_SXGA 0x80 @@ -348,47 +356,47 @@ static const struct v4l2_pix_format vga_mode[] = { .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0 | MODE_JPEG}, + .priv = SCALE_160x120 | MODE_JPEG}, {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 | MODE_RAW}, + .priv = SCALE_160x120 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 240 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, + .priv = SCALE_160x120}, {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1 | MODE_JPEG}, + .priv = SCALE_320x240 | MODE_JPEG}, {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW}, + .priv = SCALE_320x240 | MODE_RAW}, {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 480 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, + .priv = SCALE_320x240}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2 | MODE_JPEG}, + .priv = SCALE_640x480 | MODE_JPEG}, {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 | MODE_RAW}, + .priv = SCALE_640x480 | MODE_RAW}, {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 960 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, + .priv = SCALE_640x480}, }; static const struct v4l2_pix_format sxga_mode[] = { @@ -396,52 +404,75 @@ static const struct v4l2_pix_format sxga_mode[] = { .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0 | MODE_JPEG}, + .priv = SCALE_160x120 | MODE_JPEG}, {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 | MODE_RAW}, + .priv = SCALE_160x120 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 240 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, + .priv = SCALE_160x120}, {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1 | MODE_JPEG}, + .priv = SCALE_320x240 | MODE_JPEG}, {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW}, + .priv = SCALE_320x240 | MODE_RAW}, {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 480 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, + .priv = SCALE_320x240}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2 | MODE_JPEG}, + .priv = SCALE_640x480 | MODE_JPEG}, {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 | MODE_RAW}, + .priv = SCALE_640x480 | MODE_RAW}, {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 960 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, + .priv = SCALE_640x480}, {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 1280, .sizeimage = 1280 * 1024, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3 | MODE_RAW | MODE_SXGA}, + .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, +}; + +static const struct v4l2_pix_format mono_mode[] = { + {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_160x120 | MODE_RAW}, + {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 , + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_320x240 | MODE_RAW}, + {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_640x480 | MODE_RAW}, + {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, }; static const s16 hsv_red_x[] = { @@ -1029,16 +1060,19 @@ static struct i2c_reg_u16 mt9v011_init[] = { }; static struct i2c_reg_u16 mt9m001_init[] = { - {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e}, - {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501}, - {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, - {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000}, - {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000}, - {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000}, - {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2}, - {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003}, - {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a}, - {0x2e, 0x0029}, {0x07, 0x0002}, + {0x0d, 0x0001}, + {0x0d, 0x0000}, + {0x04, 0x0500}, /* hres = 1280 */ + {0x03, 0x0400}, /* vres = 1024 */ + {0x20, 0x1100}, + {0x06, 0x0010}, + {0x2b, 0x0024}, + {0x2e, 0x0024}, + {0x35, 0x0024}, + {0x2d, 0x0020}, + {0x2c, 0x0020}, + {0x09, 0x0ad4}, + {0x35, 0x0057}, }; static struct i2c_reg_u16 mt9m111_init[] = { @@ -1224,8 +1258,17 @@ static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) static int ov9650_init_sensor(struct gspca_dev *gspca_dev) { int i; + u16 id; struct sd *sd = (struct sd *) gspca_dev; + if (i2c_r2(gspca_dev, 0x1c, &id) < 0) + return -EINVAL; + + if (id != 0x7fa2) { + err("sensor id for ov9650 doesn't match (0x%04x)", id); + return -ENODEV; + } + for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { if (i2c_w1(gspca_dev, ov9650_init[i].reg, ov9650_init[i].val) < 0) { @@ -1425,6 +1468,25 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; + u16 id; + + if (i2c_r2(gspca_dev, 0x00, &id) < 0) + return -EINVAL; + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (id) { + case 0x8411: + case 0x8421: + info("MT9M001 color sensor detected"); + break; + case 0x8431: + info("MT9M001 mono sensor detected"); + break; + default: + err("No MT9M001 chip detected, ID = %x\n", id); + return -ENODEV; + } + for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { if (i2c_w2(gspca_dev, mt9m001_init[i].reg, mt9m001_init[i].val) < 0) { @@ -1434,8 +1496,8 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) } /* disable hflip and vflip */ gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); - sd->hstart = 2; - sd->vstart = 2; + sd->hstart = 1; + sd->vstart = 1; return 0; } @@ -1977,6 +2039,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sxga_mode; cam->nmodes = ARRAY_SIZE(sxga_mode); break; + case SENSOR_MT9M001: + cam->cam_mode = mono_mode; + cam->nmodes = ARRAY_SIZE(mono_mode); + break; default: cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); @@ -2075,7 +2141,6 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_MT9M001: if (mt9m001_init_sensor(gspca_dev) < 0) return -ENODEV; - info("MT9M001 sensor detected"); break; case SENSOR_HV7131R: if (hv7131r_init_sensor(gspca_dev) < 0) @@ -2173,22 +2238,22 @@ static int sd_start(struct gspca_dev *gspca_dev) else if (mode & MODE_JPEG) fmt = 0x2c; else - fmt = 0x2f; + fmt = 0x2f; /* YUV 420 */ - switch (mode & 0x0f) { - case 3: + switch (mode & SCALE_MASK) { + case SCALE_1280x1024: scale = 0xc0; info("Set 1280x1024"); break; - case 2: + case SCALE_640x480: scale = 0x80; info("Set 640x480"); break; - case 1: + case SCALE_320x240: scale = 0x90; info("Set 320x240"); break; - case 0: + case SCALE_160x120: scale = 0xa0; info("Set 160x120"); break; diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 706f96f9265..73504a3f87b 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -56,6 +56,8 @@ struct sd { int prev_avg_lum; int exp_too_low_cnt; int exp_too_high_cnt; + int header_read; + u8 header[12]; /* Header without sof marker */ unsigned short exposure; unsigned char gain; @@ -71,14 +73,15 @@ struct sd { #define BRIDGE_103 1 __u8 sensor; /* Type of image sensor chip */ -#define SENSOR_HV7131R 0 -#define SENSOR_OV6650 1 -#define SENSOR_OV7630 2 -#define SENSOR_PAS106 3 -#define SENSOR_PAS202 4 -#define SENSOR_TAS5110C 5 -#define SENSOR_TAS5110D 6 -#define SENSOR_TAS5130CXX 7 +#define SENSOR_HV7131D 0 +#define SENSOR_HV7131R 1 +#define SENSOR_OV6650 2 +#define SENSOR_OV7630 3 +#define SENSOR_PAS106 4 +#define SENSOR_PAS202 5 +#define SENSOR_TAS5110C 6 +#define SENSOR_TAS5110D 7 +#define SENSOR_TAS5130CXX 8 __u8 reg11; }; @@ -303,14 +306,29 @@ static const struct v4l2_pix_format sif_mode[] = { .priv = 0}, }; -static const __u8 initHv7131[] = { +static const __u8 initHv7131d[] = { + 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, + 0x28, 0x1e, 0x60, 0x8e, 0x42, + 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c +}; +static const __u8 hv7131d_sensor_init[][8] = { + {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */ + {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */ +}; + +static const __u8 initHv7131r[] = { 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x28, 0x1e, 0x60, 0x8a, 0x20, 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c }; -static const __u8 hv7131_sensor_init[][8] = { +static const __u8 hv7131r_sensor_init[][8] = { {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10}, {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10}, {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10}, @@ -340,7 +358,7 @@ static const __u8 ov6650_sensor_init[][8] = { * but blue wont be there. Avoid this data ... */ {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */ {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, - {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10}, + {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10}, /* Enable rgb brightness control */ {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10}, /* HDG: Note windows uses the line below, which sets both register 0x60 @@ -505,7 +523,7 @@ static const __u8 pas202_sensor_init[][8] = { {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, - {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10}, + {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10}, {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, @@ -551,7 +569,8 @@ static const __u8 tas5130_sensor_init[][8] = { }; static struct sensor_data sensor_data[] = { -SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), +SENS(initHv7131d, NULL, hv7131d_sensor_init, NULL, NULL, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0), +SENS(initHv7131r, NULL, hv7131r_sensor_init, NULL, NULL, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, F_GAIN, 0, 0x21), @@ -701,7 +720,18 @@ static void setsensorgain(struct gspca_dev *gspca_dev) unsigned char gain = sd->gain; switch (sd->sensor) { + case SENSOR_HV7131D: { + __u8 i2c[] = + {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; + i2c[3] = 0x3f - (sd->gain / 4); + i2c[4] = 0x3f - (sd->gain / 4); + i2c[5] = 0x3f - (sd->gain / 4); + + if (i2c_w(gspca_dev, i2c) < 0) + goto err; + break; + } case SENSOR_TAS5110C: case SENSOR_TAS5110D: { __u8 i2c[] = @@ -788,6 +818,23 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; switch (sd->sensor) { + case SENSOR_HV7131D: { + /* Note the datasheet wrongly says line mode exposure uses reg + 0x26 and 0x27, testing has shown 0x25 + 0x26 */ + __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17}; + /* The HV7131D's exposure goes from 0 - 65535, we scale our + exposure of 0-1023 to 0-6138. There are 2 reasons for this: + 1) This puts our exposure knee of 200 at approx the point + where the framerate starts dropping + 2) At 6138 the framerate has already dropped to 2 fps, + going any lower makes little sense */ + __u16 reg = sd->exposure * 6; + i2c[3] = reg >> 8; + i2c[4] = reg & 0xff; + if (i2c_w(gspca_dev, i2c) != 0) + goto err; + break; + } case SENSOR_TAS5110C: case SENSOR_TAS5110D: { /* register 19's high nibble contains the sn9c10x clock divider @@ -1177,13 +1224,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev) sd_init(gspca_dev); } -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ +static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) { - int i; struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; + int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12; /* frames start with: * ff ff 00 c4 c4 96 synchro @@ -1194,58 +1238,84 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * ll mm brightness sum outside auto exposure * (xx xx xx xx xx) audio values for snc103 */ - if (len > 6 && len < 24) { - for (i = 0; i < len - 6; i++) { - if (data[0 + i] == 0xff - && data[1 + i] == 0xff - && data[2 + i] == 0x00 - && data[3 + i] == 0xc4 - && data[4 + i] == 0xc4 - && data[5 + i] == 0x96) { /* start of frame */ - int lum = -1; - int pkt_type = LAST_PACKET; - int fr_h_sz = (sd->bridge == BRIDGE_103) ? - 18 : 12; - - if (len - i < fr_h_sz) { - PDEBUG(D_STREAM, "packet too short to" - " get avg brightness"); - } else if (sd->bridge == BRIDGE_103) { - lum = data[i + 9] + - (data[i + 10] << 8); - } else { - lum = data[i + 8] + (data[i + 9] << 8); - } - /* When exposure changes midway a frame we - get a lum of 0 in this case drop 2 frames - as the frames directly after an exposure - change have an unstable image. Sometimes lum - *really* is 0 (cam used in low light with - low exposure setting), so do not drop frames - if the previous lum was 0 too. */ - if (lum == 0 && sd->prev_avg_lum != 0) { - lum = -1; - sd->frames_to_drop = 2; - sd->prev_avg_lum = 0; - } else - sd->prev_avg_lum = lum; - atomic_set(&sd->avg_lum, lum); - - if (sd->frames_to_drop) { - sd->frames_to_drop--; - pkt_type = DISCARD_PACKET; - } - - gspca_frame_add(gspca_dev, pkt_type, - NULL, 0); - data += i + fr_h_sz; - len -= i + fr_h_sz; - gspca_frame_add(gspca_dev, FIRST_PACKET, - data, len); - return; + for (i = 0; i < len; i++) { + switch (sd->header_read) { + case 0: + if (data[i] == 0xff) + sd->header_read++; + break; + case 1: + if (data[i] == 0xff) + sd->header_read++; + else + sd->header_read = 0; + break; + case 2: + if (data[i] == 0x00) + sd->header_read++; + else if (data[i] != 0xff) + sd->header_read = 0; + break; + case 3: + if (data[i] == 0xc4) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + case 4: + if (data[i] == 0xc4) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + case 5: + if (data[i] == 0x96) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + default: + sd->header[sd->header_read - 6] = data[i]; + sd->header_read++; + if (sd->header_read == header_size) { + sd->header_read = 0; + return data + i + 1; } } } + return NULL; +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0; + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; + u8 *sof; + + sof = find_sof(gspca_dev, data, len); + if (sof) { + if (sd->bridge == BRIDGE_103) { + fr_h_sz = 18; + lum_offset = 3; + } else { + fr_h_sz = 12; + lum_offset = 2; + } + + len_after_sof = len - (sof - data); + len = (sof - data) - fr_h_sz; + if (len < 0) + len = 0; + } if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { /* In raw mode we sometimes get some garbage after the frame @@ -1259,6 +1329,33 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + + if (sof) { + int lum = sd->header[lum_offset] + + (sd->header[lum_offset + 1] << 8); + + /* When exposure changes midway a frame we + get a lum of 0 in this case drop 2 frames + as the frames directly after an exposure + change have an unstable image. Sometimes lum + *really* is 0 (cam used in low light with + low exposure setting), so do not drop frames + if the previous lum was 0 too. */ + if (lum == 0 && sd->prev_avg_lum != 0) { + lum = -1; + sd->frames_to_drop = 2; + sd->prev_avg_lum = 0; + } else + sd->prev_avg_lum = lum; + atomic_set(&sd->avg_lum, lum); + + if (sd->frames_to_drop) + sd->frames_to_drop--; + else + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); + + gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof); + } } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) @@ -1431,9 +1528,7 @@ static const struct sd_desc sd_desc = { static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ -#endif {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, @@ -1444,9 +1539,12 @@ static const struct usb_device_id device_table[] __devinitconst = { #endif {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, + {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)}, + /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */ {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, + /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */ {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 330dadc0010..2d0bb17a30a 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -63,7 +63,10 @@ struct sd { #define QUALITY_DEF 80 u8 jpegqual; /* webcam quality */ + u8 reg01; + u8 reg17; u8 reg18; + u8 flags; s8 ag_cnt; #define AG_CNT_START 13 @@ -96,6 +99,22 @@ enum sensors { SENSOR_SP80708, }; +/* device flags */ +#define PDN_INV 1 /* inverse pin S_PWR_DN / sn_xxx tables */ + +/* sn9c1xx definitions */ +/* register 0x01 */ +#define S_PWR_DN 0x01 /* sensor power down */ +#define S_PDN_INV 0x02 /* inverse pin S_PWR_DN */ +#define V_TX_EN 0x04 /* video transfer enable */ +#define LED 0x08 /* output to pin LED */ +#define SCL_SEL_OD 0x20 /* open-drain mode */ +#define SYS_SEL_48M 0x40 /* system clock 0: 24MHz, 1: 48MHz */ +/* register 0x17 */ +#define MCK_SIZE_MASK 0x1f /* sensor master clock */ +#define SEN_CLK_EN 0x20 /* enable sensor clock */ +#define DEF_EN 0x80 /* defect pixel by 0: soft, 1: hard */ + /* V4L2 controls supported by the driver */ static void setbrightness(struct gspca_dev *gspca_dev); static void setcontrast(struct gspca_dev *gspca_dev); @@ -1579,22 +1598,22 @@ static void i2c_w_seq(struct gspca_dev *gspca_dev, } } +/* check the ID of the hv7131 sensor */ +/* this sequence is needed because it activates the sensor */ static void hv7131r_probe(struct gspca_dev *gspca_dev) { - i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ + i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ msleep(10); - reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ + reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ msleep(10); - i2c_r(gspca_dev, 0, 5); /* read sensor id */ - if (gspca_dev->usb_buf[0] == 0x02 + i2c_r(gspca_dev, 0, 5); /* read sensor id */ + if (gspca_dev->usb_buf[0] == 0x02 /* chip ID (02 is R) */ && gspca_dev->usb_buf[1] == 0x09 - && gspca_dev->usb_buf[2] == 0x01 - && gspca_dev->usb_buf[3] == 0x00 - && gspca_dev->usb_buf[4] == 0x00) { - PDEBUG(D_PROBE, "Sensor sn9c102P HV7131R found"); + && gspca_dev->usb_buf[2] == 0x01) { + PDEBUG(D_PROBE, "Sensor HV7131R found"); return; } - PDEBUG(D_PROBE, "Sensor 0x%02x 0x%02x 0x%02x - sn9c102P not found", + warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x", gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], gspca_dev->usb_buf[2]); } @@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev) } } -static void bridge_init(struct gspca_dev *gspca_dev, - const u8 *sn9c1xx) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 reg0102[2]; - const u8 *reg9a; - static const u8 reg9a_def[] = - {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; - static const u8 reg9a_spec[] = - {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; - static const u8 regd4[] = {0x60, 0x00, 0x00}; - - /* sensor clock already enabled in sd_init */ - /* reg_w1(gspca_dev, 0xf1, 0x00); */ - reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - - /* configure gpio */ - reg0102[0] = sn9c1xx[1]; - reg0102[1] = sn9c1xx[2]; - if (gspca_dev->audio) - reg0102[1] |= 0x04; /* keep the audio connection */ - reg_w(gspca_dev, 0x01, reg0102, 2); - reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); - reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); - switch (sd->sensor) { - case SENSOR_GC0307: - case SENSOR_OV7660: - case SENSOR_PO1030: - case SENSOR_PO2030N: - case SENSOR_SOI768: - case SENSOR_SP80708: - reg9a = reg9a_spec; - break; - default: - reg9a = reg9a_def; - break; - } - reg_w(gspca_dev, 0x9a, reg9a, 6); - - reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); - - reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); - - switch (sd->sensor) { - case SENSOR_ADCM1700: - reg_w1(gspca_dev, 0x01, 0x43); - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - reg_w1(gspca_dev, 0x01, 0x42); - break; - case SENSOR_GC0307: - msleep(50); - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x22); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - msleep(50); - break; - case SENSOR_MI0360B: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x60); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_MT9V111: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x61); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_OM6802: - msleep(10); - reg_w1(gspca_dev, 0x02, 0x73); - reg_w1(gspca_dev, 0x17, 0x60); - reg_w1(gspca_dev, 0x01, 0x22); - msleep(100); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x17, 0x64); - reg_w1(gspca_dev, 0x17, 0x64); - reg_w1(gspca_dev, 0x01, 0x42); - msleep(10); - reg_w1(gspca_dev, 0x01, 0x42); - i2c_w8(gspca_dev, om6802_init0[0]); - i2c_w8(gspca_dev, om6802_init0[1]); - msleep(15); - reg_w1(gspca_dev, 0x02, 0x71); - msleep(150); - break; - case SENSOR_OV7630: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0xe2); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_OV7648: - reg_w1(gspca_dev, 0x01, 0x63); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - break; - case SENSOR_PO1030: - case SENSOR_SOI768: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - case SENSOR_PO2030N: - case SENSOR_OV7660: - reg_w1(gspca_dev, 0x01, 0x63); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - break; - case SENSOR_SP80708: - reg_w1(gspca_dev, 0x01, 0x63); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x62); - reg_w1(gspca_dev, 0x01, 0x42); - msleep(100); - reg_w1(gspca_dev, 0x02, 0x62); - break; - default: -/* case SENSOR_HV7131R: */ -/* case SENSOR_MI0360: */ -/* case SENSOR_MO4000: */ - reg_w1(gspca_dev, 0x01, 0x43); - reg_w1(gspca_dev, 0x17, 0x61); - reg_w1(gspca_dev, 0x01, 0x42); - if (sd->sensor == SENSOR_HV7131R) - hv7131r_probe(gspca_dev); - break; - } -} - /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; sd->bridge = id->driver_info >> 16; - sd->sensor = id->driver_info; + sd->sensor = id->driver_info >> 8; + sd->flags = id->driver_info; cam = &gspca_dev->cam; if (sd->sensor == SENSOR_ADCM1700) { @@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev) /* setup a selector by bridge */ reg_w1(gspca_dev, 0xf1, 0x01); reg_r(gspca_dev, 0x00, 1); - reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]); + reg_w1(gspca_dev, 0xf1, 0x00); reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */ regF1 = gspca_dev->usb_buf[0]; if (gspca_dev->usb_err < 0) @@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; - u8 reg1, reg17; + u8 reg01, reg17; + u8 reg0102[2]; const u8 *sn9c1xx; const u8 (*init)[8]; + const u8 *reg9a; int mode; + static const u8 reg9a_def[] = + {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; + static const u8 reg9a_spec[] = + {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; + static const u8 regd4[] = {0x60, 0x00, 0x00}; static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; static const u8 CA_adcm1700[] = @@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev) /* initialize the bridge */ sn9c1xx = sn_tb[sd->sensor]; - bridge_init(gspca_dev, sn9c1xx); + + /* sensor clock already enabled in sd_init */ + /* reg_w1(gspca_dev, 0xf1, 0x00); */ + reg01 = sn9c1xx[1]; + if (sd->flags & PDN_INV) + reg01 ^= S_PDN_INV; /* power down inverted */ + reg_w1(gspca_dev, 0x01, reg01); + + /* configure gpio */ + reg0102[0] = reg01; + reg0102[1] = sn9c1xx[2]; + if (gspca_dev->audio) + reg0102[1] |= 0x04; /* keep the audio connection */ + reg_w(gspca_dev, 0x01, reg0102, 2); + reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); + reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); + switch (sd->sensor) { + case SENSOR_GC0307: + case SENSOR_OV7660: + case SENSOR_PO1030: + case SENSOR_PO2030N: + case SENSOR_SOI768: + case SENSOR_SP80708: + reg9a = reg9a_spec; + break; + default: + reg9a = reg9a_def; + break; + } + reg_w(gspca_dev, 0x9a, reg9a, 6); + + reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); + + reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); + + reg17 = sn9c1xx[0x17]; + switch (sd->sensor) { + case SENSOR_GC0307: + msleep(50); /*fixme: is it useful? */ + break; + case SENSOR_OM6802: + msleep(10); + reg_w1(gspca_dev, 0x02, 0x73); + reg17 |= SEN_CLK_EN; + reg_w1(gspca_dev, 0x17, reg17); + reg_w1(gspca_dev, 0x01, 0x22); + msleep(100); + reg01 = SCL_SEL_OD | S_PDN_INV; + reg17 &= MCK_SIZE_MASK; + reg17 |= 0x04; /* clock / 4 */ + break; + } + reg01 |= SYS_SEL_48M; + reg_w1(gspca_dev, 0x01, reg01); + reg17 |= SEN_CLK_EN; + reg_w1(gspca_dev, 0x17, reg17); + reg01 &= ~S_PWR_DN; /* sensor power on */ + reg_w1(gspca_dev, 0x01, reg01); + reg01 &= ~SYS_SEL_48M; + reg_w1(gspca_dev, 0x01, reg01); + + switch (sd->sensor) { + case SENSOR_HV7131R: + hv7131r_probe(gspca_dev); /*fixme: is it useful? */ + break; + case SENSOR_OM6802: + msleep(10); + reg_w1(gspca_dev, 0x01, reg01); + i2c_w8(gspca_dev, om6802_init0[0]); + i2c_w8(gspca_dev, om6802_init0[1]); + msleep(15); + reg_w1(gspca_dev, 0x02, 0x71); + msleep(150); + break; + case SENSOR_SP80708: + msleep(100); + reg_w1(gspca_dev, 0x02, 0x62); + break; + } /* initialize the sensor */ i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); @@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev) } reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); switch (sd->sensor) { - case SENSOR_GC0307: - reg17 = 0xa2; - break; - case SENSOR_MT9V111: - case SENSOR_MI0360B: - reg17 = 0xe0; - break; - case SENSOR_ADCM1700: - case SENSOR_OV7630: - reg17 = 0xe2; - break; - case SENSOR_OV7648: - reg17 = 0x20; - break; - case SENSOR_OV7660: - case SENSOR_SOI768: - reg17 = 0xa0; - break; - case SENSOR_PO1030: - case SENSOR_PO2030N: - reg17 = 0xa0; + case SENSOR_OM6802: +/* case SENSOR_OV7648: * fixme: sometimes */ break; default: - reg17 = 0x60; + reg17 |= DEF_EN; break; } reg_w1(gspca_dev, 0x17, reg17); @@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev) init = NULL; mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - if (mode) - reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */ - else - reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ - reg17 = 0x61; /* 0x:20: enable sensor clock */ + reg01 |= SYS_SEL_48M | V_TX_EN; + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x02; /* clock / 2 */ switch (sd->sensor) { case SENSOR_ADCM1700: init = adcm1700_sensor_param1; - reg1 = 0x46; - reg17 = 0xe2; break; case SENSOR_GC0307: init = gc0307_sensor_param1; - reg17 = 0xa2; - reg1 = 0x44; + break; + case SENSOR_HV7131R: + case SENSOR_MI0360: + if (mode) + reg01 |= SYS_SEL_48M; /* 320x240: clk 48Mhz */ + else + reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x01; /* clock / 1 */ break; case SENSOR_MI0360B: init = mi0360b_sensor_param1; - reg1 &= ~0x02; /* don't inverse pin S_PWR_DN */ - reg17 = 0xe2; break; case SENSOR_MO4000: - if (mode) { -/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ - reg1 = 0x06; /* clk 24Mz */ - } else { - reg17 = 0x22; /* 640 MCKSIZE */ -/* reg1 = 0x06; * 640 clk 24Mz (done) */ + if (mode) { /* if 320x240 */ + reg01 &= ~SYS_SEL_48M; /* clk 24Mz */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x01; /* clock / 1 */ } break; case SENSOR_MT9V111: init = mt9v111_sensor_param1; - if (mode) { - reg1 = 0x04; /* 320 clk 48Mhz */ - } else { -/* reg1 = 0x06; * 640 clk 24Mz (done) */ - reg17 = 0xc2; - } break; case SENSOR_OM6802: init = om6802_sensor_param1; - reg17 = 0x64; /* 640 MCKSIZE */ + if (!mode) { /* if 640x480 */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x04; /* clock / 4 */ + } break; case SENSOR_OV7630: init = ov7630_sensor_param1; - reg17 = 0xe2; - reg1 = 0x44; break; case SENSOR_OV7648: init = ov7648_sensor_param1; - reg17 = 0x21; -/* reg1 = 0x42; * 42 - 46? */ + reg17 &= ~MCK_SIZE_MASK; + reg17 |= 0x01; /* clock / 1 */ break; case SENSOR_OV7660: init = ov7660_sensor_param1; - if (sd->bridge == BRIDGE_SN9C120) { - if (mode) { /* 320x240 - 160x120 */ - reg17 = 0xa2; - reg1 = 0x44; /* 48 Mhz, video trf eneble */ - } - } else { - reg17 = 0x22; - reg1 = 0x06; /* 24 Mhz, video trf eneble - * inverse power down */ - } break; case SENSOR_PO1030: init = po1030_sensor_param1; - reg17 = 0xa2; - reg1 = 0x44; break; case SENSOR_PO2030N: init = po2030n_sensor_param1; - reg1 = 0x46; - reg17 = 0xa2; break; case SENSOR_SOI768: init = soi768_sensor_param1; - reg1 = 0x44; - reg17 = 0xa2; break; case SENSOR_SP80708: init = sp80708_sensor_param1; - if (mode) { -/*?? reg1 = 0x04; * 320 clk 48Mhz */ - } else { - reg1 = 0x46; /* 640 clk 48Mz */ - reg17 = 0xa2; - } break; } @@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev) setjpegqual(gspca_dev); reg_w1(gspca_dev, 0x17, reg17); - reg_w1(gspca_dev, 0x01, reg1); + reg_w1(gspca_dev, 0x01, reg01); + sd->reg01 = reg01; + sd->reg17 = reg17; sethvflip(gspca_dev); setbrightness(gspca_dev); @@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev) { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 }; static const u8 stopsoi768[] = { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 }; - u8 data; - const u8 *sn9c1xx; + u8 reg01; + u8 reg17; - data = 0x0b; + reg01 = sd->reg01; + reg17 = sd->reg17 & ~SEN_CLK_EN; switch (sd->sensor) { + case SENSOR_ADCM1700: case SENSOR_GC0307: - data = 0x29; + case SENSOR_PO2030N: + case SENSOR_SP80708: + reg01 |= LED; + reg_w1(gspca_dev, 0x01, reg01); + reg01 &= ~(LED | V_TX_EN); + reg_w1(gspca_dev, 0x01, reg01); +/* reg_w1(gspca_dev, 0x02, 0x??); * LED off ? */ break; case SENSOR_HV7131R: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); i2c_w8(gspca_dev, stophv7131); - data = 0x2b; break; case SENSOR_MI0360: case SENSOR_MI0360B: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); +/* reg_w1(gspca_dev, 0x02, 0x40); * LED off ? */ i2c_w8(gspca_dev, stopmi0360); - data = 0x29; break; - case SENSOR_OV7648: - i2c_w8(gspca_dev, stopov7648); - /* fall thru */ case SENSOR_MT9V111: - case SENSOR_OV7630: + case SENSOR_OM6802: case SENSOR_PO1030: - data = 0x29; + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); + break; + case SENSOR_OV7630: + case SENSOR_OV7648: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); + i2c_w8(gspca_dev, stopov7648); + break; + case SENSOR_OV7660: + reg01 &= ~V_TX_EN; + reg_w1(gspca_dev, 0x01, reg01); break; case SENSOR_SOI768: i2c_w8(gspca_dev, stopsoi768); - data = 0x29; break; } - sn9c1xx = sn_tb[sd->sensor]; - reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); - reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - reg_w1(gspca_dev, 0x01, data); + + reg01 |= SCL_SEL_OD; + reg_w1(gspca_dev, 0x01, reg01); + reg01 |= S_PWR_DN; /* sensor power down */ + reg_w1(gspca_dev, 0x01, reg01); + reg_w1(gspca_dev, 0x17, reg17); + reg01 &= ~SYS_SEL_48M; /* clock 24MHz */ + reg_w1(gspca_dev, 0x01, reg01); + reg01 |= LED; + reg_w1(gspca_dev, 0x01, reg01); /* Don't disable sensor clock as that disables the button on the cam */ /* reg_w1(gspca_dev, 0xf1, 0x01); */ } @@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ #define BS(bridge, sensor) \ .driver_info = (BRIDGE_ ## bridge << 16) \ - | SENSOR_ ## sensor + | (SENSOR_ ## sensor << 8) +#define BSF(bridge, sensor, flags) \ + .driver_info = (BRIDGE_ ## bridge << 16) \ + | (SENSOR_ ## sensor << 8) \ + | (flags) static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)}, {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)}, #endif - {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, - {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, + {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)}, + {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)}, {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index ad73f4812c0..3a162c6d546 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -597,7 +597,7 @@ static void setgain(struct gspca_dev *gspca_dev) else if (sd->gain < 128) gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40; else - gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0; + gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xc0; gspca_dev->usb_buf[1] = 0; reg_w_buf(gspca_dev, 0x8335, 2); diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index c2e88b5303c..8ba19954385 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c @@ -301,6 +301,7 @@ static int sd_start(struct gspca_dev *gspca_dev) static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x2770, 0x905c)}, {USB_DEVICE(0x2770, 0x9050)}, + {USB_DEVICE(0x2770, 0x9051)}, {USB_DEVICE(0x2770, 0x9052)}, {USB_DEVICE(0x2770, 0x913d)}, {} diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c index 3e4b0b94c70..a4a98811b9e 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/video/gspca/sq930x.c @@ -687,10 +687,19 @@ static void cmos_probe(struct gspca_dev *gspca_dev) if (gspca_dev->usb_buf[0] != 0) break; } - if (i >= ARRAY_SIZE(probe_order)) + if (i >= ARRAY_SIZE(probe_order)) { err("Unknown sensor"); - else - sd->sensor = probe_order[i]; + gspca_dev->usb_err = -EINVAL; + return; + } + sd->sensor = probe_order[i]; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV9630: + err("Sensor %s not yet treated", sensor_tb[sd->sensor].name); + gspca_dev->usb_err = -EINVAL; + break; + } } static void mt9v111_init(struct gspca_dev *gspca_dev) @@ -867,6 +876,9 @@ static int sd_init(struct gspca_dev *gspca_dev) */ reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8); + if (gspca_dev->usb_err < 0) + return gspca_dev->usb_err; + /* it returns: * 03 00 12 93 0b f6 c9 00 live! ultra * 03 00 07 93 0b f6 ca 00 live! ultra for notebook @@ -900,15 +912,15 @@ static int sd_init(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_MI0360) { /* no sensor probe for icam tracer */ - if (gspca_dev->usb_buf[5] == 0xf6) /* if CMOS */ + if (gspca_dev->usb_buf[5] == 0xf6) /* if ccd */ sd->sensor = SENSOR_ICX098BQ; else cmos_probe(gspca_dev); } - - PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); - - global_init(sd, 1); + if (gspca_dev->usb_err >= 0) { + PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); + global_init(sd, 1); + } return gspca_dev->usb_err; } diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 086de44a6e5..28ea4175b80 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -263,7 +263,21 @@ static int stv06xx_init(struct gspca_dev *gspca_dev) static int stv06xx_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int err; + struct usb_host_interface *alt; + struct usb_interface *intf; + int err, packet_size; + + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) { + PDEBUG(D_ERR, "Couldn't get altsetting"); + return -EIO; + } + + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); + if (err < 0) + return err; /* Prepare the sensor for start */ err = sd->sensor->start(sd); @@ -282,6 +296,43 @@ out: return (err < 0) ? err : 0; } +static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) +{ + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = + cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); + + return 0; +} + +static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) +{ + int ret, packet_size, min_packet_size; + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; + if (packet_size <= min_packet_size) + return -EIO; + + packet_size -= 100; + if (packet_size < min_packet_size) + packet_size = min_packet_size; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); + + ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); + if (ret < 0) + PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret); + + return ret; +} + static void stv06xx_stopN(struct gspca_dev *gspca_dev) { int err; @@ -349,7 +400,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, } /* First byte seem to be 02=data 2nd byte is unknown??? */ - if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200) + if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200) goto frame_data; switch (id) { @@ -462,6 +513,8 @@ static const struct sd_desc sd_desc = { .start = stv06xx_start, .stopN = stv06xx_stopN, .pkt_scan = stv06xx_pkt_scan, + .isoc_init = stv06xx_isoc_init, + .isoc_nego = stv06xx_isoc_nego, #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) .int_pkt_scan = sd_int_pkt_scan, #endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h index cf3d0ccc112..b538dce96f7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h @@ -146,6 +146,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = { .i2c_addr = (0x55 << 1), .i2c_len = 1, + /* FIXME (see if we can lower min_packet_size, needs testing, and also + adjusting framerate when the bandwidth gets lower) */ + .min_packet_size = { 847 }, + .max_packet_size = { 847 }, + .init = hdcs_init, .probe = hdcs_probe_1x00, .start = hdcs_start, @@ -160,6 +165,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = { .i2c_addr = (0x55 << 1), .i2c_len = 1, + /* FIXME (see if we can lower min_packet_size, needs testing, and also + adjusting framerate when the bandwidthm gets lower) */ + .min_packet_size = { 847 }, + .max_packet_size = { 847 }, + .init = hdcs_init, .probe = hdcs_probe_1020, .start = hdcs_start, @@ -177,7 +187,6 @@ static const u16 stv_bridge_init[][2] = { {STV_REG04, 0x07}, {STV_SCAN_RATE, 0x20}, - {STV_ISO_SIZE_L, 847}, {STV_Y_CTRL, 0x01}, {STV_X_CTRL, 0x0a} }; diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c index 285221e6b39..ac47b4c9438 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c @@ -208,11 +208,24 @@ static int pb0100_probe(struct sd *sd) static int pb0100_start(struct sd *sd) { - int err; + int err, packet_size, max_packet_size; + struct usb_host_interface *alt; + struct usb_interface *intf; struct cam *cam = &sd->gspca_dev.cam; s32 *sensor_settings = sd->sensor_priv; u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv; + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + + /* If we don't have enough bandwidth use a lower framerate */ + max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode]; + if (packet_size < max_packet_size) + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); + else + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1)); + /* Setup sensor window */ if (mode & PB0100_CROP_TO_VGA) { stv06xx_write_sensor(sd, PB_RSTART, 30); @@ -328,9 +341,6 @@ static int pb0100_init(struct sd *sd) stv06xx_write_bridge(sd, STV_REG03, 0x45); stv06xx_write_bridge(sd, STV_REG04, 0x07); - /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */ - stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847); - /* Scan/timing for the sensor */ stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); stv06xx_write_sensor(sd, PB_CFILLIN, 14); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h index 4de4fa5ebc5..757de246dc7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h @@ -138,6 +138,9 @@ const struct stv06xx_sensor stv06xx_sensor_pb0100 = { .i2c_addr = 0xba, .i2c_len = 2, + .min_packet_size = { 635, 847 }, + .max_packet_size = { 847, 923 }, + .init = pb0100_init, .probe = pb0100_probe, .start = pb0100_start, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h index 934b9cebc1a..fb229d8ded5 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h @@ -53,6 +53,10 @@ struct stv06xx_sensor { /* length of an i2c word */ u8 i2c_len; + /* Isoc packet size (per mode) */ + int min_packet_size[4]; + int max_packet_size[4]; + /* Probes if the sensor is connected */ int (*probe)(struct sd *sd); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c index 3af53264a36..8a456de4970 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c @@ -28,6 +28,20 @@ #include "stv06xx_st6422.h" +/* controls */ +enum e_ctrl { + BRIGHTNESS, + CONTRAST, + GAIN, + EXPOSURE, + NCTRLS /* number of controls */ +}; + +/* sensor settings */ +struct st6422_settings { + struct gspca_ctrl ctrls[NCTRLS]; +}; + static struct v4l2_pix_format st6422_mode[] = { /* Note we actually get 124 lines of data, of which we skip the 4st 4 as they are garbage */ @@ -57,9 +71,14 @@ static struct v4l2_pix_format st6422_mode[] = { }, }; -static const struct ctrl st6422_ctrl[] = { -#define BRIGHTNESS_IDX 0 - { +/* V4L2 controls supported by the driver */ +static void st6422_set_brightness(struct gspca_dev *gspca_dev); +static void st6422_set_contrast(struct gspca_dev *gspca_dev); +static void st6422_set_gain(struct gspca_dev *gspca_dev); +static void st6422_set_exposure(struct gspca_dev *gspca_dev); + +static const struct ctrl st6422_ctrl[NCTRLS] = { +[BRIGHTNESS] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -69,11 +88,9 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 3 }, - .set = st6422_set_brightness, - .get = st6422_get_brightness + .set_control = st6422_set_brightness }, -#define CONTRAST_IDX 1 - { +[CONTRAST] = { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -83,11 +100,9 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 11 }, - .set = st6422_set_contrast, - .get = st6422_get_contrast + .set_control = st6422_set_contrast }, -#define GAIN_IDX 2 - { +[GAIN] = { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -97,49 +112,43 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 64 }, - .set = st6422_set_gain, - .get = st6422_get_gain + .set_control = st6422_set_gain }, -#define EXPOSURE_IDX 3 - { +[EXPOSURE] = { { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Exposure", .minimum = 0, - .maximum = 1023, +#define EXPOSURE_MAX 1023 + .maximum = EXPOSURE_MAX, .step = 1, .default_value = 256 }, - .set = st6422_set_exposure, - .get = st6422_get_exposure + .set_control = st6422_set_exposure }, }; static int st6422_probe(struct sd *sd) { - int i; - s32 *sensor_settings; + struct st6422_settings *sensor_settings; if (sd->bridge != BRIDGE_ST6422) return -ENODEV; info("st6422 sensor detected"); - sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32), - GFP_KERNEL); + sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL); if (!sensor_settings) return -ENOMEM; sd->gspca_dev.cam.cam_mode = st6422_mode; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); + sd->gspca_dev.cam.ctrls = sensor_settings->ctrls; sd->desc.ctrls = st6422_ctrl; sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl); sd->sensor_priv = sensor_settings; - for (i = 0; i < sd->desc.nctrls; i++) - sensor_settings[i] = st6422_ctrl[i].qctrl.default_value; - return 0; } @@ -151,11 +160,11 @@ static int st6422_init(struct sd *sd) { STV_ISO_ENABLE, 0x00 }, /* disable capture */ { 0x1436, 0x00 }, { 0x1432, 0x03 }, /* 0x00-0x1F brightness */ - { 0x143a, 0xF9 }, /* 0x00-0x0F contrast */ + { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */ { 0x0509, 0x38 }, /* R */ { 0x050a, 0x38 }, /* G */ { 0x050b, 0x38 }, /* B */ - { 0x050c, 0x2A }, + { 0x050c, 0x2a }, { 0x050d, 0x01 }, @@ -213,7 +222,6 @@ static int st6422_init(struct sd *sd) { 0x150e, 0x8e }, { 0x150f, 0x37 }, { 0x15c0, 0x00 }, - { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */ { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */ @@ -235,91 +243,92 @@ static void st6422_disconnect(struct sd *sd) kfree(sd->sensor_priv); } -static int st6422_start(struct sd *sd) +static int setbrightness(struct sd *sd) { - int err, packet_size; - struct cam *cam = &sd->gspca_dev.cam; - s32 *sensor_settings = sd->sensor_priv; - struct usb_host_interface *alt; - struct usb_interface *intf; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) { - err("Couldn't get altsetting"); - return -EIO; - } + struct st6422_settings *sensor_settings = sd->sensor_priv; - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - err = stv06xx_write_bridge(sd, 0x15c1, packet_size); - if (err < 0) - return err; + /* val goes from 0 -> 31 */ + return stv06xx_write_bridge(sd, 0x1432, + sensor_settings->ctrls[BRIGHTNESS].val); +} - if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) - err = stv06xx_write_bridge(sd, 0x1505, 0x0f); - else - err = stv06xx_write_bridge(sd, 0x1505, 0x02); - if (err < 0) - return err; +static int setcontrast(struct sd *sd) +{ + struct st6422_settings *sensor_settings = sd->sensor_priv; + + /* Val goes from 0 -> 15 */ + return stv06xx_write_bridge(sd, 0x143a, + sensor_settings->ctrls[CONTRAST].val | 0xf0); +} + +static int setgain(struct sd *sd) +{ + struct st6422_settings *sensor_settings = sd->sensor_priv; + u8 gain; + int err; + + gain = sensor_settings->ctrls[GAIN].val; - err = st6422_set_brightness(&sd->gspca_dev, - sensor_settings[BRIGHTNESS_IDX]); + /* Set red, green, blue, gain */ + err = stv06xx_write_bridge(sd, 0x0509, gain); if (err < 0) return err; - err = st6422_set_contrast(&sd->gspca_dev, - sensor_settings[CONTRAST_IDX]); + err = stv06xx_write_bridge(sd, 0x050a, gain); if (err < 0) return err; - err = st6422_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); + err = stv06xx_write_bridge(sd, 0x050b, gain); if (err < 0) return err; - err = st6422_set_gain(&sd->gspca_dev, - sensor_settings[GAIN_IDX]); + /* 2 mystery writes */ + err = stv06xx_write_bridge(sd, 0x050c, 0x2a); if (err < 0) return err; - PDEBUG(D_STREAM, "Starting stream"); - - return 0; + return stv06xx_write_bridge(sd, 0x050d, 0x01); } -static int st6422_stop(struct sd *sd) +static int setexposure(struct sd *sd) { - PDEBUG(D_STREAM, "Halting stream"); - - return 0; -} - -static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[BRIGHTNESS_IDX]; + struct st6422_settings *sensor_settings = sd->sensor_priv; + u16 expo; + int err; - PDEBUG(D_V4L2, "Read brightness %d", *val); + expo = sensor_settings->ctrls[EXPOSURE].val; + err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff); + if (err < 0) + return err; - return 0; + return stv06xx_write_bridge(sd, 0x143e, expo >> 8); } -static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +static int st6422_start(struct sd *sd) { int err; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; + struct cam *cam = &sd->gspca_dev.cam; - sensor_settings[BRIGHTNESS_IDX] = val; + if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) + err = stv06xx_write_bridge(sd, 0x1505, 0x0f); + else + err = stv06xx_write_bridge(sd, 0x1505, 0x02); + if (err < 0) + return err; - if (!gspca_dev->streaming) - return 0; + err = setbrightness(sd); + if (err < 0) + return err; - /* val goes from 0 -> 31 */ - PDEBUG(D_V4L2, "Set brightness to %d", val); - err = stv06xx_write_bridge(sd, 0x1432, val); + err = setcontrast(sd); + if (err < 0) + return err; + + err = setexposure(sd); + if (err < 0) + return err; + + err = setgain(sd); if (err < 0) return err; @@ -328,125 +337,65 @@ static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) return (err < 0) ? err : 0; } -static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val) +static int st6422_stop(struct sd *sd) { - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[CONTRAST_IDX]; - - PDEBUG(D_V4L2, "Read contrast %d", *val); + PDEBUG(D_STREAM, "Halting stream"); return 0; } -static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_brightness(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[CONTRAST_IDX] = val; - if (!gspca_dev->streaming) - return 0; - - /* Val goes from 0 -> 15 */ - PDEBUG(D_V4L2, "Set contrast to %d\n", val); - err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val); - if (err < 0) - return err; + err = setbrightness(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; -} - -static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - - PDEBUG(D_V4L2, "Read gain %d", *val); + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return 0; + gspca_dev->usb_err = err; } -static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_contrast(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[GAIN_IDX] = val; - - if (!gspca_dev->streaming) - return 0; - - PDEBUG(D_V4L2, "Set gain to %d", val); - /* Set red, green, blue, gain */ - err = stv06xx_write_bridge(sd, 0x0509, val); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050a, val); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050b, val); - if (err < 0) - return err; - - /* 2 mystery writes */ - err = stv06xx_write_bridge(sd, 0x050c, 0x2a); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050d, 0x01); - if (err < 0) - return err; + err = setcontrast(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + + gspca_dev->usb_err = err; } -static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +static void st6422_set_gain(struct gspca_dev *gspca_dev) { + int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - *val = sensor_settings[EXPOSURE_IDX]; + err = setgain(sd); - PDEBUG(D_V4L2, "Read exposure %d", *val); + /* commit settings */ + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return 0; + gspca_dev->usb_err = err; } -static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_exposure(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[EXPOSURE_IDX] = val; - if (!gspca_dev->streaming) - return 0; - - PDEBUG(D_V4L2, "Set exposure to %d\n", val); - err = stv06xx_write_bridge(sd, 0x143d, val & 0xff); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x143e, val >> 8); - if (err < 0) - return err; + err = setexposure(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + + gspca_dev->usb_err = err; } diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h index b2d45fe5052..d7498e06432 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h @@ -37,18 +37,11 @@ static int st6422_init(struct sd *sd); static int st6422_stop(struct sd *sd); static void st6422_disconnect(struct sd *sd); -/* V4L2 controls supported by the driver */ -static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val); - const struct stv06xx_sensor stv06xx_sensor_st6422 = { .name = "ST6422", + /* No known way to lower framerate in case of less bandwidth */ + .min_packet_size = { 300, 847 }, + .max_packet_size = { 300, 847 }, .init = st6422_init, .probe = st6422_probe, .start = st6422_start, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index b3b5508473b..7fe3587f5f7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -197,6 +197,10 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = { .i2c_flush = 5, .i2c_addr = 0x20, .i2c_len = 1, + /* FIXME (see if we can lower packet_size-s, needs testing, and also + adjusting framerate when the bandwidth gets lower) */ + .min_packet_size = { 1023 }, + .max_packet_size = { 1023 }, .init = vv6410_init, .probe = vv6410_probe, .start = vv6410_start, @@ -220,10 +224,6 @@ static const u8 x1536[] = { /* 0x1536 - 0x153b */ 0x02, 0x00, 0x60, 0x01, 0x20, 0x01 }; -static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */ - 0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */ -}; - static const struct stv_init stv_bridge_init[] = { /* This reg is written twice. Some kind of reset? */ {NULL, 0x1620, 0x80}, @@ -232,7 +232,6 @@ static const struct stv_init stv_bridge_init[] = { {NULL, 0x1423, 0x04}, {x1500, 0x1500, ARRAY_SIZE(x1500)}, {x1536, 0x1536, ARRAY_SIZE(x1536)}, - {x15c1, 0x15c1, ARRAY_SIZE(x15c1)} }; static const u8 vv6410_sensor_init[][2] = { diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index b45f4d0f399..8f0c33116e0 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -487,7 +487,7 @@ static const u8 gamma_table[GAMMA_MAX][17] = { {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */ 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6, 0xff}, - {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ + {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9, 0xff}, {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */ diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index d9e3c605078..38c22f0a426 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -132,7 +132,7 @@ static const struct v4l2_pix_format sif_mode[] = { #define R36_PID 0x36 #define R37_PIDH 0x37 #define R39_Test1 0x39 /* GPIO */ -#define R3B_Test3 0x3B /* GPIO */ +#define R3B_Test3 0x3b /* GPIO */ #define R83_AD_IDH 0x83 #define R91_AD_SLOPEREG 0x91 #define R94_AD_BITCONTROL 0x94 diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 38a6efe1a5f..9b2ae1b6cc7 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -47,24 +47,29 @@ struct sd { u8 image_offset; u8 bridge; -#define BRIDGE_VC0321 0 -#define BRIDGE_VC0323 1 u8 sensor; -#define SENSOR_HV7131R 0 -#define SENSOR_MI0360 1 -#define SENSOR_MI1310_SOC 2 -#define SENSOR_MI1320 3 -#define SENSOR_MI1320_SOC 4 -#define SENSOR_OV7660 5 -#define SENSOR_OV7670 6 -#define SENSOR_PO1200 7 -#define SENSOR_PO3130NC 8 -#define SENSOR_POxxxx 9 u8 flags; #define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ #define FL_HFLIP 0x02 /* mirrored by default */ #define FL_VFLIP 0x04 /* vertical flipped by default */ }; +enum bridges { + BRIDGE_VC0321, + BRIDGE_VC0323, +}; +enum sensors { + SENSOR_HV7131R, + SENSOR_MI0360, + SENSOR_MI1310_SOC, + SENSOR_MI1320, + SENSOR_MI1320_SOC, + SENSOR_OV7660, + SENSOR_OV7670, + SENSOR_PO1200, + SENSOR_PO3130NC, + SENSOR_POxxxx, + NSENSORS +}; /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); @@ -260,56 +265,56 @@ static const struct ctrl sd_ctrls[] = { }; /* table of the disabled controls */ -static u32 ctrl_dis[] = { -/* SENSOR_HV7131R 0 */ +static u32 ctrl_dis[NSENSORS] = { + [SENSOR_HV7131R] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI0360 1 */ + [SENSOR_MI0360] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1310_SOC 2 */ + [SENSOR_MI1310_SOC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1320 3 */ + [SENSOR_MI1320] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1320_SOC 4 */ + [SENSOR_MI1320_SOC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_OV7660 5 */ + [SENSOR_OV7660] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_OV7670 6 */ + [SENSOR_OV7670] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_PO1200 7 */ + [SENSOR_PO1200] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_PO3130NC 8 */ + [SENSOR_PO3130NC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_POxxxx 9 */ + [SENSOR_POxxxx] = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX), }; @@ -3420,17 +3425,18 @@ static int sd_init(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int sensor; - static u8 npkt[] = { /* number of packets per ISOC message */ - 64, /* HV7131R 0 */ - 32, /* MI0360 1 */ - 32, /* MI1310_SOC 2 */ - 64, /* MI1320 3 */ - 128, /* MI1320_SOC 4 */ - 32, /* OV7660 5 */ - 64, /* OV7670 6 */ - 128, /* PO1200 7 */ - 128, /* PO3130NC 8 */ - 128, /* POxxxx 9 */ + /* number of packets per ISOC message */ + static u8 npkt[NSENSORS] = { + [SENSOR_HV7131R] = 64, + [SENSOR_MI0360] = 32, + [SENSOR_MI1310_SOC] = 32, + [SENSOR_MI1320] = 64, + [SENSOR_MI1320_SOC] = 128, + [SENSOR_OV7660] = 32, + [SENSOR_OV7670] = 64, + [SENSOR_PO1200] = 128, + [SENSOR_PO3130NC] = 128, + [SENSOR_POxxxx] = 128, }; if (sd->sensor != SENSOR_POxxxx) diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 4066ac8c45a..4a9e622e5e1 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -59,18 +59,21 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG}, }; -static int reg_w(struct sd *sd, __u16 index, __u16 value); +static void reg_w(struct sd *sd, u16 index, u16 value); /*-------------------------------------------------------------------------- Write 64-bit data to the fast serial bus registers. Return 0 on success, -1 otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_write_fsb(struct sd *sd, u16* data) +static void w9968cf_write_fsb(struct sd *sd, u16* data) { struct usb_device *udev = sd->gspca_dev.dev; u16 value; int ret; + if (sd->gspca_dev.usb_err < 0) + return; + value = *data++; memcpy(sd->gspca_dev.usb_buf, data, 6); @@ -79,20 +82,21 @@ static int w9968cf_write_fsb(struct sd *sd, u16* data) value, 0x06, sd->gspca_dev.usb_buf, 6, 500); if (ret < 0) { err("Write FSB registers failed (%d)", ret); - return ret; + sd->gspca_dev.usb_err = ret; } - - return 0; } /*-------------------------------------------------------------------------- Write data to the serial bus control register. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_write_sb(struct sd *sd, u16 value) +static void w9968cf_write_sb(struct sd *sd, u16 value) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + /* We don't use reg_w here, as that would cause all writes when bitbanging i2c to be logged, making the logs impossible to read */ ret = usb_control_msg(sd->gspca_dev.dev, @@ -105,10 +109,8 @@ static int w9968cf_write_sb(struct sd *sd, u16 value) if (ret < 0) { err("Write SB reg [01] %04x failed", value); - return ret; + sd->gspca_dev.usb_err = ret; } - - return 0; } /*-------------------------------------------------------------------------- @@ -119,6 +121,9 @@ static int w9968cf_read_sb(struct sd *sd) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + /* We don't use reg_r here, as the w9968cf is special and has 16 bit registers instead of 8 bit */ ret = usb_control_msg(sd->gspca_dev.dev, @@ -126,11 +131,13 @@ static int w9968cf_read_sb(struct sd *sd) 1, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); - if (ret >= 0) + if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0] | (sd->gspca_dev.usb_buf[1] << 8); - else + } else { err("Read SB reg [01] failed"); + sd->gspca_dev.usb_err = ret; + } udelay(W9968CF_I2C_BUS_DELAY); @@ -142,22 +149,20 @@ static int w9968cf_read_sb(struct sd *sd) This function is called by w9968cf_start_transfer(). Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_upload_quantizationtables(struct sd *sd) +static void w9968cf_upload_quantizationtables(struct sd *sd) { u16 a, b; - int ret = 0, i, j; + int i, j; - ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ + reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ for (i = 0, j = 0; i < 32; i++, j += 2) { - a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); - b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); - ret += reg_w(sd, 0x40+i, a); - ret += reg_w(sd, 0x60+i, b); + a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); + b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8); + reg_w(sd, 0x40 + i, a); + reg_w(sd, 0x60 + i, b); } - ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ - - return ret; + reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ } /**************************************************************************** @@ -168,50 +173,39 @@ static int w9968cf_upload_quantizationtables(struct sd *sd) * i2c_adap_read_byte() * ****************************************************************************/ -static int w9968cf_smbus_start(struct sd *sd) +static void w9968cf_smbus_start(struct sd *sd) { - int ret = 0; - - ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - - return ret; + w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ } -static int w9968cf_smbus_stop(struct sd *sd) +static void w9968cf_smbus_stop(struct sd *sd) { - int ret = 0; - - ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - - return ret; + w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ } -static int w9968cf_smbus_write_byte(struct sd *sd, u8 v) +static void w9968cf_smbus_write_byte(struct sd *sd, u8 v) { u8 bit; - int ret = 0, sda; + int sda; for (bit = 0 ; bit < 8 ; bit++) { sda = (v & 0x80) ? 2 : 0; v <<= 1; /* SDE=1, SDA=sda, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x10 | sda); + w9968cf_write_sb(sd, 0x10 | sda); /* SDE=1, SDA=sda, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x11 | sda); + w9968cf_write_sb(sd, 0x11 | sda); /* SDE=1, SDA=sda, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x10 | sda); + w9968cf_write_sb(sd, 0x10 | sda); } - - return ret; } -static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) +static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v) { u8 bit; - int ret = 0; /* No need to ensure SDA is high as we are always called after read_ack which ends with SDA high */ @@ -219,51 +213,40 @@ static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) for (bit = 0 ; bit < 8 ; bit++) { *v <<= 1; /* SDE=1, SDA=1, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0013); + w9968cf_write_sb(sd, 0x0013); *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; /* SDE=1, SDA=1, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0012); + w9968cf_write_sb(sd, 0x0012); } - - return ret; } -static int w9968cf_smbus_write_nack(struct sd *sd) +static void w9968cf_smbus_write_nack(struct sd *sd) { - int ret = 0; - /* No need to ensure SDA is high as we are always called after read_byte which ends with SDA high */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - - return ret; + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ } -static int w9968cf_smbus_read_ack(struct sd *sd) +static void w9968cf_smbus_read_ack(struct sd *sd) { - int ret = 0, sda; + int sda; /* Ensure SDA is high before raising clock to avoid a spurious stop */ - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ sda = w9968cf_read_sb(sd); - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - if (sda < 0) - ret += sda; - else if (sda & 0x08) { + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + if (sda >= 0 && (sda & 0x08)) { PDEBUG(D_USBI, "Did not receive i2c ACK"); - ret += -1; + sd->gspca_dev.usb_err = -EIO; } - - return ret; } /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ -static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) +static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) { u16* data = (u16 *)sd->gspca_dev.usb_buf; - int ret = 0; data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; @@ -276,7 +259,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); data[0] |= (reg & 0x40) ? 0x0540 : 0x0; @@ -290,7 +273,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[2] |= (reg & 0x01) ? 0x5400 : 0x0; data[3] = 0x001d; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); data[0] |= (value & 0x40) ? 0x0540 : 0x0; @@ -304,14 +287,9 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[2] |= (value & 0x01) ? 0x5400 : 0x0; data[3] = 0xfe1d; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); - if (!ret) - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); - else - PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); - - return ret; + PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); } /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ @@ -321,28 +299,28 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) u8 value; /* Fast serial bus data control disable */ - ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */ - - ret += w9968cf_smbus_start(sd); - ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_write_byte(sd, reg); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_stop(sd); - ret += w9968cf_smbus_start(sd); - ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_read_byte(sd, &value); + w9968cf_write_sb(sd, 0x0013); /* don't change ! */ + + w9968cf_smbus_start(sd); + w9968cf_smbus_write_byte(sd, sd->sensor_addr); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_write_byte(sd, reg); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_stop(sd); + w9968cf_smbus_start(sd); + w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_read_byte(sd, &value); /* signal we don't want to read anymore, the v4l1 driver used to send an ack here which is very wrong! (and then fixed the issues this gave by retrying reads) */ - ret += w9968cf_smbus_write_nack(sd); - ret += w9968cf_smbus_stop(sd); + w9968cf_smbus_write_nack(sd); + w9968cf_smbus_stop(sd); /* Fast serial bus data control re-enable */ - ret += w9968cf_write_sb(sd, 0x0030); + w9968cf_write_sb(sd, 0x0030); - if (!ret) { + if (sd->gspca_dev.usb_err >= 0) { ret = value; PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); } else @@ -351,79 +329,68 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) return ret; } - /*-------------------------------------------------------------------------- Turn on the LED on some webcams. A beep should be heard too. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_configure(struct sd *sd) +static void w9968cf_configure(struct sd *sd) { - int ret = 0; - - ret += reg_w(sd, 0x00, 0xff00); /* power-down */ - ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ - ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ - ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ - ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ - ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ - ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ - - if (ret) - PDEBUG(D_ERR, "Couldn't turn on the LED"); + reg_w(sd, 0x00, 0xff00); /* power-down */ + reg_w(sd, 0x00, 0xbf17); /* reset everything */ + reg_w(sd, 0x00, 0xbf10); /* normal operation */ + reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ + reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ + reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ + reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ sd->stopped = 1; - - return ret; } -static int w9968cf_init(struct sd *sd) +static void w9968cf_init(struct sd *sd) { - int ret = 0; unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), y0 = 0x0000, - u0 = y0 + hw_bufsize/2, - v0 = u0 + hw_bufsize/4, - y1 = v0 + hw_bufsize/4, - u1 = y1 + hw_bufsize/2, - v1 = u1 + hw_bufsize/4; - - ret += reg_w(sd, 0x00, 0xff00); /* power off */ - ret += reg_w(sd, 0x00, 0xbf10); /* power on */ - - ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */ - ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ - - ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ - ret += reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ - ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ - ret += reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ - ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ - ret += reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ - - ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ - ret += reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ - ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ - ret += reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ - ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ - ret += reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ - - ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ - ret += reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ - - ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ - ret += reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ - - ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ - ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ - ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ - ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ - - return ret; + u0 = y0 + hw_bufsize / 2, + v0 = u0 + hw_bufsize / 4, + y1 = v0 + hw_bufsize / 4, + u1 = y1 + hw_bufsize / 2, + v1 = u1 + hw_bufsize / 4; + + reg_w(sd, 0x00, 0xff00); /* power off */ + reg_w(sd, 0x00, 0xbf10); /* power on */ + + reg_w(sd, 0x03, 0x405d); /* DRAM timings */ + reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ + + reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ + reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ + reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ + reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ + reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ + reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ + + reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ + reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ + reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ + reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ + reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ + reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ + + reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ + reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ + + reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ + reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ + + reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ + reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ + reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ + reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ } -static int w9968cf_set_crop_window(struct sd *sd) +static void w9968cf_set_crop_window(struct sd *sd) { - int ret = 0, start_cropx, start_cropy, x, y, fw, fh, cw, ch, + int start_cropx, start_cropy, x, y, fw, fh, cw, ch, max_width, max_height; if (sd->sif) { @@ -456,8 +423,8 @@ static int w9968cf_set_crop_window(struct sd *sd) fw = SC(sd->gspca_dev.width) / max_width; fh = SC(sd->gspca_dev.height) / max_height; - cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width)/fh; - ch = (fw >= fh) ? SC(sd->gspca_dev.height)/fw : max_height; + cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh; + ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height; sd->sensor_width = max_width; sd->sensor_height = max_height; @@ -465,42 +432,40 @@ static int w9968cf_set_crop_window(struct sd *sd) x = (max_width - cw) / 2; y = (max_height - ch) / 2; - ret += reg_w(sd, 0x10, start_cropx + x); - ret += reg_w(sd, 0x11, start_cropy + y); - ret += reg_w(sd, 0x12, start_cropx + x + cw); - ret += reg_w(sd, 0x13, start_cropy + y + ch); - - return ret; + reg_w(sd, 0x10, start_cropx + x); + reg_w(sd, 0x11, start_cropy + y); + reg_w(sd, 0x12, start_cropx + x + cw); + reg_w(sd, 0x13, start_cropy + y + ch); } -static int w9968cf_mode_init_regs(struct sd *sd) +static void w9968cf_mode_init_regs(struct sd *sd) { - int ret = 0, val, vs_polarity, hs_polarity; + int val, vs_polarity, hs_polarity; - ret += w9968cf_set_crop_window(sd); + w9968cf_set_crop_window(sd); - ret += reg_w(sd, 0x14, sd->gspca_dev.width); - ret += reg_w(sd, 0x15, sd->gspca_dev.height); + reg_w(sd, 0x14, sd->gspca_dev.width); + reg_w(sd, 0x15, sd->gspca_dev.height); /* JPEG width & height */ - ret += reg_w(sd, 0x30, sd->gspca_dev.width); - ret += reg_w(sd, 0x31, sd->gspca_dev.height); + reg_w(sd, 0x30, sd->gspca_dev.width); + reg_w(sd, 0x31, sd->gspca_dev.height); /* Y & UV frame buffer strides (in WORD) */ if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == V4L2_PIX_FMT_JPEG) { - ret += reg_w(sd, 0x2c, sd->gspca_dev.width/2); - ret += reg_w(sd, 0x2d, sd->gspca_dev.width/4); + reg_w(sd, 0x2c, sd->gspca_dev.width / 2); + reg_w(sd, 0x2d, sd->gspca_dev.width / 4); } else - ret += reg_w(sd, 0x2c, sd->gspca_dev.width); + reg_w(sd, 0x2c, sd->gspca_dev.width); - ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ - ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ + reg_w(sd, 0x00, 0xbf17); /* reset everything */ + reg_w(sd, 0x00, 0xbf10); /* normal operation */ /* Transfer size in WORDS (for UYVY format only) */ val = sd->gspca_dev.width * sd->gspca_dev.height; - ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ - ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ + reg_w(sd, 0x3d, val & 0xffff); /* low bits */ + reg_w(sd, 0x3e, val >> 16); /* high bits */ if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == V4L2_PIX_FMT_JPEG) { @@ -508,7 +473,7 @@ static int w9968cf_mode_init_regs(struct sd *sd) jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, sd->gspca_dev.width, 0x22); /* JPEG 420 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); - ret += w9968cf_upload_quantizationtables(sd); + w9968cf_upload_quantizationtables(sd); } /* Video Capture Control Register */ @@ -540,19 +505,15 @@ static int w9968cf_mode_init_regs(struct sd *sd) val |= 0x8000; /* capt. enable */ - ret += reg_w(sd, 0x16, val); + reg_w(sd, 0x16, val); sd->gspca_dev.empty_packet = 0; - - return ret; } static void w9968cf_stop0(struct sd *sd) { - if (sd->gspca_dev.present) { - reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ - reg_w(sd, 0x16, 0x0000); /* stop video capture */ - } + reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ + reg_w(sd, 0x16, 0x0000); /* stop video capture */ } /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c index 8715577bc2d..5b5039a0203 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/video/gspca/xirlink_cit.c @@ -29,6 +29,7 @@ #define MODULE_NAME "xirlink-cit" +#include <linux/input.h> #include "gspca.h" MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); @@ -58,6 +59,7 @@ struct sd { #define CIT_MODEL4 4 #define CIT_IBM_NETCAM_PRO 5 u8 input_index; + u8 button_state; u8 stop_on_control_change; u8 sof_read; u8 sof_len; @@ -185,60 +187,60 @@ static const struct ctrl sd_ctrls[] = { static const struct v4l2_pix_format cif_yuv_mode[] = { {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 2, + .sizeimage = 352 * 288 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format vga_yuv_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, + .sizeimage = 320 * 240 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 2, + .sizeimage = 640 * 480 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format model0_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, + .sizeimage = 320 * 240 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format model2_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240, + .sizeimage = 320 * 240 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288, + .sizeimage = 352 * 288 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; @@ -804,7 +806,7 @@ static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index) return 0; } -static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index) +static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose) { struct usb_device *udev = gspca_dev->dev; __u8 *buf = gspca_dev->usb_buf; @@ -819,10 +821,8 @@ static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index) return res; } - PDEBUG(D_PROBE, - "Register %04x value: %02x %02x %02x %02x %02x %02x %02x %02x", - index, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + if (verbose) + PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]); return 0; } @@ -907,7 +907,7 @@ static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val) cit_send_x_00_05(gspca_dev, 0x0089); cit_send_x_00(gspca_dev, fkey); cit_send_00_04_06(gspca_dev); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 0); cit_send_FF_04_02(gspca_dev); } @@ -1074,12 +1074,12 @@ static int cit_init_model0(struct gspca_dev *gspca_dev) static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev) { - cit_read_reg(gspca_dev, 0x128); + cit_read_reg(gspca_dev, 0x128, 1); cit_write_reg(gspca_dev, 0x0003, 0x0133); cit_write_reg(gspca_dev, 0x0000, 0x0117); cit_write_reg(gspca_dev, 0x0008, 0x0123); cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x0000, 0x0133); @@ -1098,7 +1098,7 @@ static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x00ff, 0x0130); cit_write_reg(gspca_dev, 0xcd41, 0x0124); cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 1); cit_model3_Packet1(gspca_dev, 0x0000, 0x0000); cit_model3_Packet1(gspca_dev, 0x0000, 0x0001); @@ -1557,18 +1557,20 @@ static int cit_restart_stream(struct gspca_dev *gspca_dev) switch (sd->model) { case CIT_MODEL0: case CIT_MODEL1: - case CIT_MODEL3: - case CIT_IBM_NETCAM_PRO: cit_write_reg(gspca_dev, 0x0001, 0x0114); /* Fall through */ case CIT_MODEL2: case CIT_MODEL4: cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - /* This happens repeatedly while streaming with the ibm netcam - pro and the ibmcam driver did it for model3 after changing - settings, but it does not seem to have any effect. */ - /* cit_write_reg(gspca_dev, 0x0001, 0x0113); */ + break; + case CIT_MODEL3: + case CIT_IBM_NETCAM_PRO: + cit_write_reg(gspca_dev, 0x0001, 0x0114); + cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ + usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); + /* Clear button events from while we were not streaming */ + cit_write_reg(gspca_dev, 0x0001, 0x0113); break; } @@ -1680,23 +1682,23 @@ static int cit_start_model1(struct gspca_dev *gspca_dev) if (clock_div < 0) return clock_div; - cit_read_reg(gspca_dev, 0x0128); - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0128, 1); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ cit_write_reg(gspca_dev, 0x01, 0x0108); cit_write_reg(gspca_dev, 0x03, 0x0112); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x06, 0x0115); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x44, 0x0116); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x40, 0x0116); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x0e, 0x0115); cit_write_reg(gspca_dev, 0x19, 0x012c); @@ -1878,7 +1880,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev) int clock_div = 0; cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */ - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x00bc, 0x012c); @@ -2070,10 +2072,10 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) /* HDG not in ibmcam driver, added to see if it helps with auto-detecting between model3 and ibm netcamera pro */ - cit_read_reg(gspca_dev, 0x128); + cit_read_reg(gspca_dev, 0x128, 1); cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x0000, 0x0123); @@ -2083,7 +2085,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0115); cit_write_reg(gspca_dev, 0x0003, 0x0115); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x000b, 0x0115); /* TESTME HDG not in ibmcam driver, added to see if it helps with @@ -2096,7 +2098,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x00ff, 0x0130); cit_write_reg(gspca_dev, 0xcd41, 0x0124); cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 1); } cit_model3_Packet1(gspca_dev, 0x000a, 0x0040); @@ -2293,7 +2295,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) if (rca_input) { for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2]); + cit_read_reg(gspca_dev, rca_initdata[i][2], 0); else cit_write_reg(gspca_dev, rca_initdata[i][1], rca_initdata[i][2]); @@ -2712,7 +2714,7 @@ static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev) if (rca_input) { for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2]); + cit_read_reg(gspca_dev, rca_initdata[i][2], 0); else cit_write_reg(gspca_dev, rca_initdata[i][1], rca_initdata[i][2]); @@ -2769,16 +2771,55 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } +static int sd_isoc_init(struct gspca_dev *gspca_dev) +{ + struct usb_host_interface *alt; + int max_packet_size; + + switch (gspca_dev->width) { + case 160: + max_packet_size = 450; + break; + case 176: + max_packet_size = 600; + break; + default: + max_packet_size = 1022; + break; + } + + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); + + return 0; +} + static int sd_isoc_nego(struct gspca_dev *gspca_dev) { - int ret, packet_size; + int ret, packet_size, min_packet_size; struct usb_host_interface *alt; + switch (gspca_dev->width) { + case 160: + min_packet_size = 200; + break; + case 176: + min_packet_size = 266; + break; + default: + min_packet_size = 400; + break; + } + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - packet_size -= 100; - if (packet_size < 300) + if (packet_size <= min_packet_size) return -EIO; + + packet_size -= 100; + if (packet_size < min_packet_size) + packet_size = min_packet_size; alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); @@ -2796,15 +2837,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_host_interface *alt; /* We cannot use gspca_dev->present here as that is not set when sd_init gets called and we get called from sd_init */ if (!gspca_dev->dev) return; - alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; - switch (sd->model) { case CIT_MODEL0: /* HDG windows does this, but it causes the cams autogain to @@ -2815,7 +2853,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) break; case CIT_MODEL1: cit_send_FF_04_02(gspca_dev); - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ break; case CIT_MODEL2: @@ -2834,9 +2872,9 @@ static void sd_stop0(struct gspca_dev *gspca_dev) case CIT_MODEL3: cit_write_reg(gspca_dev, 0x0006, 0x012c); cit_model3_Packet1(gspca_dev, 0x0046, 0x0000); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0064, 0x0116); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x0003, 0x0115); cit_write_reg(gspca_dev, 0x0008, 0x0123); cit_write_reg(gspca_dev, 0x0000, 0x0117); @@ -2859,12 +2897,17 @@ static void sd_stop0(struct gspca_dev *gspca_dev) restarting the stream after this */ /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */ cit_write_reg(gspca_dev, 0x00c0, 0x0100); - - /* Start isoc bandwidth "negotiation" at max isoc bandwith - next stream start */ - alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(1022); break; } + +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + /* If the last button state is pressed, release it now! */ + if (sd->button_state) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + sd->button_state = 0; + } +#endif } static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) @@ -3158,6 +3201,38 @@ static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) +static void cit_check_button(struct gspca_dev *gspca_dev) +{ + int new_button_state; + struct sd *sd = (struct sd *)gspca_dev; + + switch (sd->model) { + case CIT_MODEL3: + case CIT_IBM_NETCAM_PRO: + break; + default: /* TEST ME unknown if this works on other models too */ + return; + } + + /* Read the button state */ + cit_read_reg(gspca_dev, 0x0113, 0); + new_button_state = !gspca_dev->usb_buf[0]; + + /* Tell the cam we've seen the button press, notice that this + is a nop (iow the cam keeps reporting pressed) until the + button is actually released. */ + if (new_button_state) + cit_write_reg(gspca_dev, 0x01, 0x0113); + + if (sd->button_state != new_button_state) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, + new_button_state); + input_sync(gspca_dev->input_dev); + sd->button_state = new_button_state; + } +} +#endif /* sub-driver description */ static const struct sd_desc sd_desc = { @@ -3170,6 +3245,10 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .dq_callback = cit_check_button, + .other_input = 1, +#endif }; static const struct sd_desc sd_desc_isoc_nego = { @@ -3179,10 +3258,15 @@ static const struct sd_desc sd_desc_isoc_nego = { .config = sd_config, .init = sd_init, .start = sd_start, + .isoc_init = sd_isoc_init, .isoc_nego = sd_isoc_nego, .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .dq_callback = cit_check_button, + .other_input = 1, +#endif }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index c7e1970ca28..14b85d48316 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -35,16 +35,23 @@ static int force_sensor = -1; #define QUANT_VAL 1 /* quantization table */ #include "zc3xx-reg.h" +/* controls */ +enum e_ctrl { + BRIGHTNESS, + CONTRAST, + GAMMA, + AUTOGAIN, + LIGHTFREQ, + SHARPNESS, + NCTRLS /* number of controls */ +}; + /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 brightness; - u8 contrast; - u8 gamma; - u8 autogain; - u8 lightfreq; - u8 sharpness; + struct gspca_ctrl ctrls[NCTRLS]; + u8 quality; /* image quality */ #define QUALITY_MIN 50 #define QUALITY_MAX 80 @@ -64,6 +71,7 @@ enum sensors { SENSOR_ADCM2700, SENSOR_CS2102, SENSOR_CS2102K, + SENSOR_GC0303, SENSOR_GC0305, SENSOR_HDCS2020b, SENSOR_HV7131B, @@ -79,26 +87,17 @@ enum sensors { SENSOR_PB0330, SENSOR_PO2030, SENSOR_TAS5130C, - SENSOR_TAS5130C_VF0250, SENSOR_MAX }; /* V4L2 controls supported by the driver */ -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); -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_setautogain(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); - -static const struct ctrl sd_ctrls[] = { - { +static void setcontrast(struct gspca_dev *gspca_dev); +static void setautogain(struct gspca_dev *gspca_dev); +static void setlightfreq(struct gspca_dev *gspca_dev); +static void setsharpness(struct gspca_dev *gspca_dev); + +static const struct ctrl sd_ctrls[NCTRLS] = { +[BRIGHTNESS] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -106,13 +105,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define BRIGHTNESS_DEF 128 - .default_value = BRIGHTNESS_DEF, + .default_value = 128, }, - .set = sd_setbrightness, - .get = sd_getbrightness, + .set_control = setcontrast }, - { +[CONTRAST] = { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -120,13 +117,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define CONTRAST_DEF 128 - .default_value = CONTRAST_DEF, + .default_value = 128, }, - .set = sd_setcontrast, - .get = sd_getcontrast, + .set_control = setcontrast }, - { +[GAMMA] = { { .id = V4L2_CID_GAMMA, .type = V4L2_CTRL_TYPE_INTEGER, @@ -136,10 +131,9 @@ static const struct ctrl sd_ctrls[] = { .step = 1, .default_value = 4, }, - .set = sd_setgamma, - .get = sd_getgamma, + .set_control = setcontrast }, - { +[AUTOGAIN] = { { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -147,14 +141,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define AUTOGAIN_DEF 1 - .default_value = AUTOGAIN_DEF, + .default_value = 1, }, - .set = sd_setautogain, - .get = sd_getautogain, + .set_control = setautogain }, -#define LIGHTFREQ_IDX 4 - { +[LIGHTFREQ] = { { .id = V4L2_CID_POWER_LINE_FREQUENCY, .type = V4L2_CTRL_TYPE_MENU, @@ -162,13 +153,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ .step = 1, -#define FREQ_DEF 0 - .default_value = FREQ_DEF, + .default_value = 0, }, - .set = sd_setfreq, - .get = sd_getfreq, + .set_control = setlightfreq }, - { +[SHARPNESS] = { { .id = V4L2_CID_SHARPNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -176,11 +165,9 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 3, .step = 1, -#define SHARPNESS_DEF 2 - .default_value = SHARPNESS_DEF, + .default_value = 2, }, - .set = sd_setsharpness, - .get = sd_getsharpness, + .set_control = setsharpness }, }; @@ -4499,7 +4486,7 @@ static const struct usb_action mt9v111_3_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, + {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, @@ -5406,7 +5393,7 @@ static const struct usb_action tas5130c_NoFlikerScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_InitialScale[] = { +static const struct usb_action gc0303_InitialScale[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ @@ -5473,7 +5460,7 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_Initial[] = { +static const struct usb_action gc0303_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ @@ -5538,7 +5525,7 @@ static const struct usb_action tas5130c_vf0250_Initial[] = { {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ {} }; -static const struct usb_action tas5130c_vf0250_50HZScale[] = { +static const struct usb_action gc0303_50HZScale[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ @@ -5562,7 +5549,7 @@ static const struct usb_action tas5130c_vf0250_50HZScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_50HZ[] = { +static const struct usb_action gc0303_50HZ[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ @@ -5586,7 +5573,7 @@ static const struct usb_action tas5130c_vf0250_50HZ[] = { {} }; -static const struct usb_action tas5130c_vf0250_60HZScale[] = { +static const struct usb_action gc0303_60HZScale[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ @@ -5610,7 +5597,7 @@ static const struct usb_action tas5130c_vf0250_60HZScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_60HZ[] = { +static const struct usb_action gc0303_60HZ[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ @@ -5634,7 +5621,7 @@ static const struct usb_action tas5130c_vf0250_60HZ[] = { {} }; -static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { +static const struct usb_action gc0303_NoFlikerScale[] = { {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ @@ -5656,7 +5643,7 @@ static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_NoFliker[] = { +static const struct usb_action gc0303_NoFliker[] = { {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ @@ -5833,12 +5820,13 @@ static void setmatrix(struct gspca_dev *gspca_dev) {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; static const u8 tas5130c_matrix[9] = {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; - static const u8 vf0250_matrix[9] = + static const u8 gc0303_matrix[9] = {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; static const u8 *matrix_tb[SENSOR_MAX] = { [SENSOR_ADCM2700] = adcm2700_matrix, [SENSOR_CS2102] = ov7620_matrix, [SENSOR_CS2102K] = NULL, + [SENSOR_GC0303] = gc0303_matrix, [SENSOR_GC0305] = gc0305_matrix, [SENSOR_HDCS2020b] = NULL, [SENSOR_HV7131B] = NULL, @@ -5854,7 +5842,6 @@ static void setmatrix(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = gc0305_matrix, [SENSOR_PO2030] = po2030_matrix, [SENSOR_TAS5130C] = tas5130c_matrix, - [SENSOR_TAS5130C_VF0250] = vf0250_matrix, }; matrix = matrix_tb[sd->sensor]; @@ -5875,7 +5862,7 @@ static void setsharpness(struct gspca_dev *gspca_dev) {0x10, 0x1e} }; - sharpness = sd->sharpness; + sharpness = sd->ctrls[SHARPNESS].val; reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6); reg_r(gspca_dev, 0x01c8); reg_r(gspca_dev, 0x01c9); @@ -5910,10 +5897,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, }; - Tgamma = gamma_tb[sd->gamma - 1]; + Tgamma = gamma_tb[sd->ctrls[GAMMA].val - 1]; - contrast = ((int) sd->contrast - 128); /* -128 / 127 */ - brightness = ((int) sd->brightness - 128); /* -128 / 92 */ + contrast = ((int) sd->ctrls[CONTRAST].val - 128); /* -128 / 127 */ + brightness = ((int) sd->ctrls[BRIGHTNESS].val - 128); /* -128 / 92 */ adj = 0; gp1 = gp2 = 0; for (i = 0; i < 16; i++) { @@ -5994,6 +5981,10 @@ static void setlightfreq(struct gspca_dev *gspca_dev) {cs2102_NoFliker, cs2102_NoFlikerScale, NULL, NULL, /* currently disabled */ NULL, NULL}, + [SENSOR_GC0303] = + {gc0303_NoFliker, gc0303_NoFlikerScale, + gc0303_50HZ, gc0303_50HZScale, + gc0303_60HZ, gc0303_60HZScale}, [SENSOR_GC0305] = {gc0305_NoFliker, gc0305_NoFliker, gc0305_50HZ, gc0305_50HZ, @@ -6054,14 +6045,10 @@ static void setlightfreq(struct gspca_dev *gspca_dev) {tas5130c_NoFliker, tas5130c_NoFlikerScale, tas5130c_50HZ, tas5130c_50HZScale, tas5130c_60HZ, tas5130c_60HZScale}, - [SENSOR_TAS5130C_VF0250] = - {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, - tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, - tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, }; - i = sd->lightfreq * 2; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + i = sd->ctrls[LIGHTFREQ].val * 2; + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; if (mode) i++; /* 320x240 */ zc3_freq = freq_tb[sd->sensor][i]; @@ -6070,14 +6057,14 @@ static void setlightfreq(struct gspca_dev *gspca_dev) usb_exchange(gspca_dev, zc3_freq); switch (sd->sensor) { case SENSOR_GC0305: - if (mode /* if 320x240 */ - && sd->lightfreq == 1) /* and 50Hz */ + if (mode /* if 320x240 */ + && sd->ctrls[LIGHTFREQ].val == 1) /* and 50Hz */ reg_w(gspca_dev, 0x85, 0x018d); /* win: 0x80, 0x018d */ break; case SENSOR_OV7620: - if (!mode) { /* if 640x480 */ - if (sd->lightfreq != 0) /* and 50 or 60 Hz */ + if (!mode) { /* if 640x480 */ + if (sd->ctrls[LIGHTFREQ].val != 0) /* and filter */ reg_w(gspca_dev, 0x40, 0x0002); else reg_w(gspca_dev, 0x44, 0x0002); @@ -6094,7 +6081,7 @@ static void setautogain(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 autoval; - if (sd->autogain) + if (sd->ctrls[AUTOGAIN].val) autoval = 0x42; else autoval = 0x02; @@ -6330,8 +6317,8 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) retword = i2c_read(gspca_dev, 0x00); if (retword != 0) { PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword); - if (retword == 0x0011) /* VF0250 */ - return 0x0250; + if (retword == 0x0011) /* gc0303 */ + return 0x0303; if (retword == 0x0029) /* gc0305 */ send_unknown(gspca_dev, SENSOR_GC0305); return retword; @@ -6392,7 +6379,7 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_MC501CB: return -1; /* don't probe */ - case SENSOR_TAS5130C_VF0250: + case SENSOR_GC0303: /* may probe but with no write in reg 0x0010 */ return -1; /* don't probe */ case SENSOR_PAS106: @@ -6421,11 +6408,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* define some sensors from the vendor/product */ sd->sensor = id->driver_info; - sd->sharpness = SHARPNESS_DEF; - sd->brightness = BRIGHTNESS_DEF; - sd->contrast = CONTRAST_DEF; - sd->autogain = AUTOGAIN_DEF; - sd->lightfreq = FREQ_DEF; + gspca_dev->cam.ctrls = sd->ctrls; sd->quality = QUALITY_DEF; return 0; @@ -6441,6 +6424,7 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_ADCM2700] = 4, [SENSOR_CS2102] = 4, [SENSOR_CS2102K] = 5, + [SENSOR_GC0303] = 3, [SENSOR_GC0305] = 4, [SENSOR_HDCS2020b] = 4, [SENSOR_HV7131B] = 4, @@ -6456,12 +6440,12 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = 4, [SENSOR_PO2030] = 4, [SENSOR_TAS5130C] = 3, - [SENSOR_TAS5130C_VF0250] = 3, }; static const u8 mode_tb[SENSOR_MAX] = { [SENSOR_ADCM2700] = 2, [SENSOR_CS2102] = 1, [SENSOR_CS2102K] = 1, + [SENSOR_GC0303] = 1, [SENSOR_GC0305] = 1, [SENSOR_HDCS2020b] = 1, [SENSOR_HV7131B] = 1, @@ -6477,7 +6461,6 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = 1, [SENSOR_PO2030] = 1, [SENSOR_TAS5130C] = 1, - [SENSOR_TAS5130C_VF0250] = 1, }; sensor = zcxx_probeSensor(gspca_dev); @@ -6493,8 +6476,8 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_MC501CB: PDEBUG(D_PROBE, "Sensor MC501CB"); break; - case SENSOR_TAS5130C_VF0250: - PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)"); + case SENSOR_GC0303: + PDEBUG(D_PROBE, "Sensor GC0303"); break; default: warn("Unknown sensor - set to TAS5130C"); @@ -6581,14 +6564,14 @@ static int sd_init(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Find Sensor GC0305"); sd->sensor = SENSOR_GC0305; break; - case 0x0250: - PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)"); - sd->sensor = SENSOR_TAS5130C_VF0250; + case 0x0303: + PDEBUG(D_PROBE, "Sensor GC0303"); + sd->sensor = SENSOR_GC0303; break; case 0x2030: PDEBUG(D_PROBE, "Find Sensor PO2030"); sd->sensor = SENSOR_PO2030; - sd->sharpness = 0; /* from win traces */ + sd->ctrls[SHARPNESS].def = 0; /* from win traces */ break; case 0x7620: PDEBUG(D_PROBE, "Find Sensor OV7620"); @@ -6629,11 +6612,12 @@ static int sd_init(struct gspca_dev *gspca_dev) cam->nmodes = ARRAY_SIZE(broken_vga_mode); break; } - sd->gamma = gamma[sd->sensor]; + + sd->ctrls[GAMMA].def = gamma[sd->sensor]; switch (sd->sensor) { case SENSOR_OV7630C: - gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); + gspca_dev->ctrl_dis = (1 << LIGHTFREQ); break; } @@ -6653,6 +6637,8 @@ static int sd_start(struct gspca_dev *gspca_dev) {cs2102_Initial, cs2102_InitialScale}, [SENSOR_CS2102K] = {cs2102K_Initial, cs2102K_InitialScale}, + [SENSOR_GC0303] = + {gc0303_Initial, gc0303_InitialScale}, [SENSOR_GC0305] = {gc0305_Initial, gc0305_InitialScale}, [SENSOR_HDCS2020b] = @@ -6683,8 +6669,6 @@ static int sd_start(struct gspca_dev *gspca_dev) {po2030_Initial, po2030_InitialScale}, [SENSOR_TAS5130C] = {tas5130c_Initial, tas5130c_InitialScale}, - [SENSOR_TAS5130C_VF0250] = - {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale}, }; /* create the JPEG header */ @@ -6709,7 +6693,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7620: case SENSOR_PO2030: case SENSOR_TAS5130C: - case SENSOR_TAS5130C_VF0250: + case SENSOR_GC0303: /* msleep(100); * ?? */ reg_r(gspca_dev, 0x0002); /* --> 0x40 */ reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */ @@ -6843,114 +6827,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->brightness = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->brightness; - return 0; -} - -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->contrast = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->contrast; - return 0; -} - -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->autogain = val; - if (gspca_dev->streaming) - setautogain(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->autogain; - return 0; -} - -static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->gamma = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->gamma; - return 0; -} - -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->lightfreq = val; - if (gspca_dev->streaming) - setlightfreq(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->lightfreq; - return 0; -} - -static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->sharpness = val; - if (gspca_dev->streaming) - setsharpness(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->sharpness; - return 0; -} - static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { @@ -7045,8 +6921,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x4036)}, {USB_DEVICE(0x041e, 0x403a)}, - {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250}, - {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250}, + {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303}, + {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303}, {USB_DEVICE(0x0458, 0x7007)}, {USB_DEVICE(0x0458, 0x700c)}, {USB_DEVICE(0x0458, 0x700f)}, @@ -7066,8 +6942,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x08af)}, {USB_DEVICE(0x046d, 0x08b9)}, {USB_DEVICE(0x046d, 0x08d7)}, - {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08d8)}, + {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08da)}, {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB}, {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106}, |