[media] move the remaining USB drivers to drivers/media/usb
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 14 Aug 2012 04:01:29 +0000 (01:01 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 15 Aug 2012 19:34:46 +0000 (16:34 -0300)
Move the 3 remaining usb drivers to their proper space.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
21 files changed:
MAINTAINERS
drivers/media/usb/Kconfig
drivers/media/usb/Makefile
drivers/media/usb/s2255/Kconfig [new file with mode: 0644]
drivers/media/usb/s2255/Makefile [new file with mode: 0644]
drivers/media/usb/s2255/s2255drv.c [new file with mode: 0644]
drivers/media/usb/stkwebcam/Kconfig [new file with mode: 0644]
drivers/media/usb/stkwebcam/Makefile [new file with mode: 0644]
drivers/media/usb/stkwebcam/stk-sensor.c [new file with mode: 0644]
drivers/media/usb/stkwebcam/stk-webcam.c [new file with mode: 0644]
drivers/media/usb/stkwebcam/stk-webcam.h [new file with mode: 0644]
drivers/media/usb/zr364xx/Kconfig [new file with mode: 0644]
drivers/media/usb/zr364xx/Makefile [new file with mode: 0644]
drivers/media/usb/zr364xx/zr364xx.c [new file with mode: 0644]
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/s2255drv.c [deleted file]
drivers/media/video/stk-sensor.c [deleted file]
drivers/media/video/stk-webcam.c [deleted file]
drivers/media/video/stk-webcam.h [deleted file]
drivers/media/video/zr364xx.c [deleted file]

index 13fd97f6466a398529f56eb82ac1595d636da44a..99a930d712cface470a90fd0c14214b2a9f2f9e0 100644 (file)
@@ -7371,7 +7371,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://royale.zerezo.com/zr364xx/
 S:     Maintained
 F:     Documentation/video4linux/zr364xx.txt
-F:     drivers/media/video/zr364xx.c
+F:     drivers/media/usb/zr364xx.c
 
 USER-MODE LINUX (UML)
 M:     Jeff Dike <jdike@addtoit.com>
index a1e25ee9d67183b36b46513f5c3f2fa7a521071f..069a3c1d03f56eb99198e04f26ec77fb8610dd3a 100644 (file)
@@ -11,6 +11,9 @@ source "drivers/media/usb/uvc/Kconfig"
 source "drivers/media/usb/gspca/Kconfig"
 source "drivers/media/usb/pwc/Kconfig"
 source "drivers/media/usb/cpia2/Kconfig"
+source "drivers/media/usb/zr364xx/Kconfig"
+source "drivers/media/usb/stkwebcam/Kconfig"
+source "drivers/media/usb/s2255/Kconfig"
 source "drivers/media/usb/sn9c102/Kconfig"
 endif
 
index 428827a4d97a24115103380908c91d5fca0e511f..63e37bb2ed748a817007e9a74a684aca124cea68 100644 (file)
@@ -4,6 +4,8 @@
 
 # DVB USB-only drivers
 obj-y := ttusb-dec/ ttusb-budget/ dvb-usb/ dvb-usb-v2/ siano/ b2c2/
+obj-y := zr364xx/ stkwebcam/ s2255/
+
 obj-$(CONFIG_USB_VIDEO_CLASS)  += uvc/
 obj-$(CONFIG_USB_GSPCA)         += gspca/
 obj-$(CONFIG_USB_PWC)           += pwc/
diff --git a/drivers/media/usb/s2255/Kconfig b/drivers/media/usb/s2255/Kconfig
new file mode 100644 (file)
index 0000000..7e8ee1f
--- /dev/null
@@ -0,0 +1,9 @@
+config USB_S2255
+       tristate "USB Sensoray 2255 video capture device"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_VMALLOC
+       default n
+       help
+         Say Y here if you want support for the Sensoray 2255 USB device.
+         This driver can be compiled as a module, called s2255drv.
+
diff --git a/drivers/media/usb/s2255/Makefile b/drivers/media/usb/s2255/Makefile
new file mode 100644 (file)
index 0000000..197d0bb
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_USB_S2255)                += s2255drv.o
+
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
new file mode 100644 (file)
index 0000000..6c7960c
--- /dev/null
@@ -0,0 +1,2689 @@
+/*
+ *  s2255drv.c - a driver for the Sensoray 2255 USB video capture device
+ *
+ *   Copyright (C) 2007-2010 by Sensoray Company Inc.
+ *                              Dean Anderson
+ *
+ * Some video buffer code based on vivi driver:
+ *
+ * Sensoray 2255 device supports 4 simultaneous channels.
+ * The channels are not "crossbar" inputs, they are physically
+ * attached to separate video decoders.
+ *
+ * Because of USB2.0 bandwidth limitations. There is only a
+ * certain amount of data which may be transferred at one time.
+ *
+ * Example maximum bandwidth utilization:
+ *
+ * -full size, color mode YUYV or YUV422P: 2 channels at once
+ * -full or half size Grey scale: all 4 channels at once
+ * -half size, color mode YUYV or YUV422P: all 4 channels at once
+ * -full size, color mode YUYV or YUV422P 1/2 frame rate: all 4 channels
+ *  at once.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/mm.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/vmalloc.h>
+#include <linux/usb.h>
+
+#define S2255_VERSION          "1.22.1"
+#define FIRMWARE_FILE_NAME "f2255usb.bin"
+
+/* default JPEG quality */
+#define S2255_DEF_JPEG_QUAL     50
+/* vendor request in */
+#define S2255_VR_IN            0
+/* vendor request out */
+#define S2255_VR_OUT           1
+/* firmware query */
+#define S2255_VR_FW            0x30
+/* USB endpoint number for configuring the device */
+#define S2255_CONFIG_EP         2
+/* maximum time for DSP to start responding after last FW word loaded(ms) */
+#define S2255_DSP_BOOTTIME      800
+/* maximum time to wait for firmware to load (ms) */
+#define S2255_LOAD_TIMEOUT      (5000 + S2255_DSP_BOOTTIME)
+#define S2255_DEF_BUFS          16
+#define S2255_SETMODE_TIMEOUT   500
+#define S2255_VIDSTATUS_TIMEOUT 350
+#define S2255_MARKER_FRAME     cpu_to_le32(0x2255DA4AL)
+#define S2255_MARKER_RESPONSE  cpu_to_le32(0x2255ACACL)
+#define S2255_RESPONSE_SETMODE  cpu_to_le32(0x01)
+#define S2255_RESPONSE_FW       cpu_to_le32(0x10)
+#define S2255_RESPONSE_STATUS   cpu_to_le32(0x20)
+#define S2255_USB_XFER_SIZE    (16 * 1024)
+#define MAX_CHANNELS           4
+#define SYS_FRAMES             4
+/* maximum size is PAL full size plus room for the marker header(s) */
+#define SYS_FRAMES_MAXSIZE     (720*288*2*2 + 4096)
+#define DEF_USB_BLOCK          S2255_USB_XFER_SIZE
+#define LINE_SZ_4CIFS_NTSC     640
+#define LINE_SZ_2CIFS_NTSC     640
+#define LINE_SZ_1CIFS_NTSC     320
+#define LINE_SZ_4CIFS_PAL      704
+#define LINE_SZ_2CIFS_PAL      704
+#define LINE_SZ_1CIFS_PAL      352
+#define NUM_LINES_4CIFS_NTSC   240
+#define NUM_LINES_2CIFS_NTSC   240
+#define NUM_LINES_1CIFS_NTSC   240
+#define NUM_LINES_4CIFS_PAL    288
+#define NUM_LINES_2CIFS_PAL    288
+#define NUM_LINES_1CIFS_PAL    288
+#define LINE_SZ_DEF            640
+#define NUM_LINES_DEF          240
+
+
+/* predefined settings */
+#define FORMAT_NTSC    1
+#define FORMAT_PAL     2
+
+#define SCALE_4CIFS    1       /* 640x480(NTSC) or 704x576(PAL) */
+#define SCALE_2CIFS    2       /* 640x240(NTSC) or 704x288(PAL) */
+#define SCALE_1CIFS    3       /* 320x240(NTSC) or 352x288(PAL) */
+/* SCALE_4CIFSI is the 2 fields interpolated into one */
+#define SCALE_4CIFSI   4       /* 640x480(NTSC) or 704x576(PAL) high quality */
+
+#define COLOR_YUVPL    1       /* YUV planar */
+#define COLOR_YUVPK    2       /* YUV packed */
+#define COLOR_Y8       4       /* monochrome */
+#define COLOR_JPG       5       /* JPEG */
+
+#define MASK_COLOR       0x000000ff
+#define MASK_JPG_QUALITY 0x0000ff00
+#define MASK_INPUT_TYPE  0x000f0000
+/* frame decimation. */
+#define FDEC_1         1       /* capture every frame. default */
+#define FDEC_2         2       /* capture every 2nd frame */
+#define FDEC_3         3       /* capture every 3rd frame */
+#define FDEC_5         5       /* capture every 5th frame */
+
+/*-------------------------------------------------------
+ * Default mode parameters.
+ *-------------------------------------------------------*/
+#define DEF_SCALE      SCALE_4CIFS
+#define DEF_COLOR      COLOR_YUVPL
+#define DEF_FDEC       FDEC_1
+#define DEF_BRIGHT     0
+#define DEF_CONTRAST   0x5c
+#define DEF_SATURATION 0x80
+#define DEF_HUE                0
+
+/* usb config commands */
+#define IN_DATA_TOKEN  cpu_to_le32(0x2255c0de)
+#define CMD_2255       0xc2255000
+#define CMD_SET_MODE   cpu_to_le32((CMD_2255 | 0x10))
+#define CMD_START      cpu_to_le32((CMD_2255 | 0x20))
+#define CMD_STOP       cpu_to_le32((CMD_2255 | 0x30))
+#define CMD_STATUS     cpu_to_le32((CMD_2255 | 0x40))
+
+struct s2255_mode {
+       u32 format;     /* input video format (NTSC, PAL) */
+       u32 scale;      /* output video scale */
+       u32 color;      /* output video color format */
+       u32 fdec;       /* frame decimation */
+       u32 bright;     /* brightness */
+       u32 contrast;   /* contrast */
+       u32 saturation; /* saturation */
+       u32 hue;        /* hue (NTSC only)*/
+       u32 single;     /* capture 1 frame at a time (!=0), continuously (==0)*/
+       u32 usb_block;  /* block size. should be 4096 of DEF_USB_BLOCK */
+       u32 restart;    /* if DSP requires restart */
+};
+
+
+#define S2255_READ_IDLE                0
+#define S2255_READ_FRAME       1
+
+/* frame structure */
+struct s2255_framei {
+       unsigned long size;
+       unsigned long ulState;  /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/
+       void *lpvbits;          /* image data */
+       unsigned long cur_size; /* current data copied to it */
+};
+
+/* image buffer structure */
+struct s2255_bufferi {
+       unsigned long dwFrames;                 /* number of frames in buffer */
+       struct s2255_framei frame[SYS_FRAMES];  /* array of FRAME structures */
+};
+
+#define DEF_MODEI_NTSC_CONT    {FORMAT_NTSC, DEF_SCALE, DEF_COLOR,     \
+                       DEF_FDEC, DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, \
+                       DEF_HUE, 0, DEF_USB_BLOCK, 0}
+
+struct s2255_dmaqueue {
+       struct list_head        active;
+       struct s2255_dev        *dev;
+};
+
+/* for firmware loading, fw_state */
+#define S2255_FW_NOTLOADED     0
+#define S2255_FW_LOADED_DSPWAIT        1
+#define S2255_FW_SUCCESS       2
+#define S2255_FW_FAILED                3
+#define S2255_FW_DISCONNECTING  4
+#define S2255_FW_MARKER                cpu_to_le32(0x22552f2f)
+/* 2255 read states */
+#define S2255_READ_IDLE         0
+#define S2255_READ_FRAME        1
+struct s2255_fw {
+       int                   fw_loaded;
+       int                   fw_size;
+       struct urb            *fw_urb;
+       atomic_t              fw_state;
+       void                  *pfw_data;
+       wait_queue_head_t     wait_fw;
+       const struct firmware *fw;
+};
+
+struct s2255_pipeinfo {
+       u32 max_transfer_size;
+       u32 cur_transfer_size;
+       u8 *transfer_buffer;
+       u32 state;
+       void *stream_urb;
+       void *dev;      /* back pointer to s2255_dev struct*/
+       u32 err_count;
+       u32 idx;
+};
+
+struct s2255_fmt; /*forward declaration */
+struct s2255_dev;
+
+struct s2255_channel {
+       struct video_device     vdev;
+       int                     resources;
+       struct s2255_dmaqueue   vidq;
+       struct s2255_bufferi    buffer;
+       struct s2255_mode       mode;
+       /* jpeg compression */
+       struct v4l2_jpegcompression jc;
+       /* capture parameters (for high quality mode full size) */
+       struct v4l2_captureparm cap_parm;
+       int                     cur_frame;
+       int                     last_frame;
+
+       int                     b_acquire;
+       /* allocated image size */
+       unsigned long           req_image_size;
+       /* received packet size */
+       unsigned long           pkt_size;
+       int                     bad_payload;
+       unsigned long           frame_count;
+       /* if JPEG image */
+       int                     jpg_size;
+       /* if channel configured to default state */
+       int                     configured;
+       wait_queue_head_t       wait_setmode;
+       int                     setmode_ready;
+       /* video status items */
+       int                     vidstatus;
+       wait_queue_head_t       wait_vidstatus;
+       int                     vidstatus_ready;
+       unsigned int            width;
+       unsigned int            height;
+       const struct s2255_fmt  *fmt;
+       int idx; /* channel number on device, 0-3 */
+};
+
+
+struct s2255_dev {
+       struct s2255_channel    channel[MAX_CHANNELS];
+       struct v4l2_device      v4l2_dev;
+       atomic_t                num_channels;
+       int                     frames;
+       struct mutex            lock;   /* channels[].vdev.lock */
+       struct usb_device       *udev;
+       struct usb_interface    *interface;
+       u8                      read_endpoint;
+       struct timer_list       timer;
+       struct s2255_fw *fw_data;
+       struct s2255_pipeinfo   pipe;
+       u32                     cc;     /* current channel */
+       int                     frame_ready;
+       int                     chn_ready;
+       spinlock_t              slock;
+       /* dsp firmware version (f2255usb.bin) */
+       int                     dsp_fw_ver;
+       u16                     pid; /* product id */
+};
+
+static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct s2255_dev, v4l2_dev);
+}
+
+struct s2255_fmt {
+       char *name;
+       u32 fourcc;
+       int depth;
+};
+
+/* buffer for one video frame */
+struct s2255_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+       const struct s2255_fmt *fmt;
+};
+
+struct s2255_fh {
+       struct s2255_dev        *dev;
+       struct videobuf_queue   vb_vidq;
+       enum v4l2_buf_type      type;
+       struct s2255_channel    *channel;
+       int                     resources;
+};
+
+/* current cypress EEPROM firmware version */
+#define S2255_CUR_USB_FWVER    ((3 << 8) | 12)
+/* current DSP FW version */
+#define S2255_CUR_DSP_FWVER     10104
+/* Need DSP version 5+ for video status feature */
+#define S2255_MIN_DSP_STATUS      5
+#define S2255_MIN_DSP_COLORFILTER 8
+#define S2255_NORMS            (V4L2_STD_PAL | V4L2_STD_NTSC)
+
+/* private V4L2 controls */
+
+/*
+ * The following chart displays how COLORFILTER should be set
+ *  =========================================================
+ *  =     fourcc              =     COLORFILTER             =
+ *  =                         ===============================
+ *  =                         =   0             =    1      =
+ *  =========================================================
+ *  =  V4L2_PIX_FMT_GREY(Y8)  = monochrome from = monochrome=
+ *  =                         = s-video or      = composite =
+ *  =                         = B/W camera      = input     =
+ *  =========================================================
+ *  =    other                = color, svideo   = color,    =
+ *  =                         =                 = composite =
+ *  =========================================================
+ *
+ * Notes:
+ *   channels 0-3 on 2255 are composite
+ *   channels 0-1 on 2257 are composite, 2-3 are s-video
+ * If COLORFILTER is 0 with a composite color camera connected,
+ * the output will appear monochrome but hatching
+ * will occur.
+ * COLORFILTER is different from "color killer" and "color effects"
+ * for reasons above.
+ */
+#define S2255_V4L2_YC_ON  1
+#define S2255_V4L2_YC_OFF 0
+#define V4L2_CID_PRIVATE_COLORFILTER (V4L2_CID_PRIVATE_BASE + 0)
+
+/* frame prefix size (sent once every frame) */
+#define PREFIX_SIZE            512
+
+/* Channels on box are in reverse order */
+static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0};
+
+static int debug;
+static int *s2255_debug = &debug;
+
+static int s2255_start_readpipe(struct s2255_dev *dev);
+static void s2255_stop_readpipe(struct s2255_dev *dev);
+static int s2255_start_acquire(struct s2255_channel *channel);
+static int s2255_stop_acquire(struct s2255_channel *channel);
+static void s2255_fillbuff(struct s2255_channel *chn, struct s2255_buffer *buf,
+                          int jpgsize);
+static int s2255_set_mode(struct s2255_channel *chan, struct s2255_mode *mode);
+static int s2255_board_shutdown(struct s2255_dev *dev);
+static void s2255_fwload_start(struct s2255_dev *dev, int reset);
+static void s2255_destroy(struct s2255_dev *dev);
+static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
+                            u16 index, u16 value, void *buf,
+                            s32 buf_len, int bOut);
+
+/* dev_err macro with driver name */
+#define S2255_DRIVER_NAME "s2255"
+#define s2255_dev_err(dev, fmt, arg...)                                        \
+               dev_err(dev, S2255_DRIVER_NAME " - " fmt, ##arg)
+
+#define dprintk(level, fmt, arg...)                                    \
+       do {                                                            \
+               if (*s2255_debug >= (level)) {                          \
+                       printk(KERN_DEBUG S2255_DRIVER_NAME             \
+                               ": " fmt, ##arg);                       \
+               }                                                       \
+       } while (0)
+
+static struct usb_driver s2255_driver;
+
+/* Declare static vars that will be used as parameters */
+static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
+
+/* start video number */
+static int video_nr = -1;      /* /dev/videoN, -1 for autodetect */
+
+/* Enable jpeg capture. */
+static int jpeg_enable = 1;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level(0-100) default 0");
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "video memory limit(Mb)");
+module_param(video_nr, int, 0644);
+MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)");
+module_param(jpeg_enable, int, 0644);
+MODULE_PARM_DESC(jpeg_enable, "Jpeg enable(1-on 0-off) default 1");
+
+/* USB device table */
+#define USB_SENSORAY_VID       0x1943
+static struct usb_device_id s2255_table[] = {
+       {USB_DEVICE(USB_SENSORAY_VID, 0x2255)},
+       {USB_DEVICE(USB_SENSORAY_VID, 0x2257)}, /*same family as 2255*/
+       { }                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, s2255_table);
+
+#define BUFFER_TIMEOUT msecs_to_jiffies(400)
+
+/* image formats.  */
+/* JPEG formats must be defined last to support jpeg_enable parameter */
+static const struct s2255_fmt formats[] = {
+       {
+               .name = "4:2:2, planar, YUV422P",
+               .fourcc = V4L2_PIX_FMT_YUV422P,
+               .depth = 16
+
+       }, {
+               .name = "4:2:2, packed, YUYV",
+               .fourcc = V4L2_PIX_FMT_YUYV,
+               .depth = 16
+
+       }, {
+               .name = "4:2:2, packed, UYVY",
+               .fourcc = V4L2_PIX_FMT_UYVY,
+               .depth = 16
+       }, {
+               .name = "8bpp GREY",
+               .fourcc = V4L2_PIX_FMT_GREY,
+               .depth = 8
+       }, {
+               .name = "JPG",
+               .fourcc = V4L2_PIX_FMT_JPEG,
+               .depth = 24
+       }, {
+               .name = "MJPG",
+               .fourcc = V4L2_PIX_FMT_MJPEG,
+               .depth = 24
+       }
+};
+
+static int norm_maxw(struct video_device *vdev)
+{
+       return (vdev->current_norm & V4L2_STD_NTSC) ?
+           LINE_SZ_4CIFS_NTSC : LINE_SZ_4CIFS_PAL;
+}
+
+static int norm_maxh(struct video_device *vdev)
+{
+       return (vdev->current_norm & V4L2_STD_NTSC) ?
+           (NUM_LINES_1CIFS_NTSC * 2) : (NUM_LINES_1CIFS_PAL * 2);
+}
+
+static int norm_minw(struct video_device *vdev)
+{
+       return (vdev->current_norm & V4L2_STD_NTSC) ?
+           LINE_SZ_1CIFS_NTSC : LINE_SZ_1CIFS_PAL;
+}
+
+static int norm_minh(struct video_device *vdev)
+{
+       return (vdev->current_norm & V4L2_STD_NTSC) ?
+           (NUM_LINES_1CIFS_NTSC) : (NUM_LINES_1CIFS_PAL);
+}
+
+
+/*
+ * TODO: fixme: move YUV reordering to hardware
+ * converts 2255 planar format to yuyv or uyvy
+ */
+static void planar422p_to_yuv_packed(const unsigned char *in,
+                                    unsigned char *out,
+                                    int width, int height,
+                                    int fmt)
+{
+       unsigned char *pY;
+       unsigned char *pCb;
+       unsigned char *pCr;
+       unsigned long size = height * width;
+       unsigned int i;
+       pY = (unsigned char *)in;
+       pCr = (unsigned char *)in + height * width;
+       pCb = (unsigned char *)in + height * width + (height * width / 2);
+       for (i = 0; i < size * 2; i += 4) {
+               out[i] = (fmt == V4L2_PIX_FMT_YUYV) ? *pY++ : *pCr++;
+               out[i + 1] = (fmt == V4L2_PIX_FMT_YUYV) ? *pCr++ : *pY++;
+               out[i + 2] = (fmt == V4L2_PIX_FMT_YUYV) ? *pY++ : *pCb++;
+               out[i + 3] = (fmt == V4L2_PIX_FMT_YUYV) ? *pCb++ : *pY++;
+       }
+       return;
+}
+
+static void s2255_reset_dsppower(struct s2255_dev *dev)
+{
+       s2255_vendor_req(dev, 0x40, 0x0000, 0x0001, NULL, 0, 1);
+       msleep(10);
+       s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1);
+       msleep(600);
+       s2255_vendor_req(dev, 0x10, 0x0000, 0x0000, NULL, 0, 1);
+       return;
+}
+
+/* kickstarts the firmware loading. from probe
+ */
+static void s2255_timer(unsigned long user_data)
+{
+       struct s2255_fw *data = (struct s2255_fw *)user_data;
+       dprintk(100, "%s\n", __func__);
+       if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
+               printk(KERN_ERR "s2255: can't submit urb\n");
+               atomic_set(&data->fw_state, S2255_FW_FAILED);
+               /* wake up anything waiting for the firmware */
+               wake_up(&data->wait_fw);
+               return;
+       }
+}
+
+
+/* this loads the firmware asynchronously.
+   Originally this was done synchroously in probe.
+   But it is better to load it asynchronously here than block
+   inside the probe function. Blocking inside probe affects boot time.
+   FW loading is triggered by the timer in the probe function
+*/
+static void s2255_fwchunk_complete(struct urb *urb)
+{
+       struct s2255_fw *data = urb->context;
+       struct usb_device *udev = urb->dev;
+       int len;
+       dprintk(100, "%s: udev %p urb %p", __func__, udev, urb);
+       if (urb->status) {
+               dev_err(&udev->dev, "URB failed with status %d\n", urb->status);
+               atomic_set(&data->fw_state, S2255_FW_FAILED);
+               /* wake up anything waiting for the firmware */
+               wake_up(&data->wait_fw);
+               return;
+       }
+       if (data->fw_urb == NULL) {
+               s2255_dev_err(&udev->dev, "disconnected\n");
+               atomic_set(&data->fw_state, S2255_FW_FAILED);
+               /* wake up anything waiting for the firmware */
+               wake_up(&data->wait_fw);
+               return;
+       }
+#define CHUNK_SIZE 512
+       /* all USB transfers must be done with continuous kernel memory.
+          can't allocate more than 128k in current linux kernel, so
+          upload the firmware in chunks
+        */
+       if (data->fw_loaded < data->fw_size) {
+               len = (data->fw_loaded + CHUNK_SIZE) > data->fw_size ?
+                   data->fw_size % CHUNK_SIZE : CHUNK_SIZE;
+
+               if (len < CHUNK_SIZE)
+                       memset(data->pfw_data, 0, CHUNK_SIZE);
+
+               dprintk(100, "completed len %d, loaded %d \n", len,
+                       data->fw_loaded);
+
+               memcpy(data->pfw_data,
+                      (char *) data->fw->data + data->fw_loaded, len);
+
+               usb_fill_bulk_urb(data->fw_urb, udev, usb_sndbulkpipe(udev, 2),
+                                 data->pfw_data, CHUNK_SIZE,
+                                 s2255_fwchunk_complete, data);
+               if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
+                       dev_err(&udev->dev, "failed submit URB\n");
+                       atomic_set(&data->fw_state, S2255_FW_FAILED);
+                       /* wake up anything waiting for the firmware */
+                       wake_up(&data->wait_fw);
+                       return;
+               }
+               data->fw_loaded += len;
+       } else {
+               atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT);
+               dprintk(100, "%s: firmware upload complete\n", __func__);
+       }
+       return;
+
+}
+
+static int s2255_got_frame(struct s2255_channel *channel, int jpgsize)
+{
+       struct s2255_dmaqueue *dma_q = &channel->vidq;
+       struct s2255_buffer *buf;
+       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+       unsigned long flags = 0;
+       int rc = 0;
+       spin_lock_irqsave(&dev->slock, flags);
+       if (list_empty(&dma_q->active)) {
+               dprintk(1, "No active queue to serve\n");
+               rc = -1;
+               goto unlock;
+       }
+       buf = list_entry(dma_q->active.next,
+                        struct s2255_buffer, vb.queue);
+       list_del(&buf->vb.queue);
+       do_gettimeofday(&buf->vb.ts);
+       s2255_fillbuff(channel, buf, jpgsize);
+       wake_up(&buf->vb.done);
+       dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i);
+unlock:
+       spin_unlock_irqrestore(&dev->slock, flags);
+       return rc;
+}
+
+static const struct s2255_fmt *format_by_fourcc(int fourcc)
+{
+       unsigned int i;
+       for (i = 0; i < ARRAY_SIZE(formats); i++) {
+               if (-1 == formats[i].fourcc)
+                       continue;
+       if (!jpeg_enable && ((formats[i].fourcc == V4L2_PIX_FMT_JPEG) ||
+                            (formats[i].fourcc == V4L2_PIX_FMT_MJPEG)))
+           continue;
+               if (formats[i].fourcc == fourcc)
+                       return formats + i;
+       }
+       return NULL;
+}
+
+/* video buffer vmalloc implementation based partly on VIVI driver which is
+ *          Copyright (c) 2006 by
+ *                  Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
+ *                  Ted Walther <ted--a.t--enumera.com>
+ *                  John Sokol <sokol--a.t--videotechnology.com>
+ *                  http://v4l.videotechnology.com/
+ *
+ */
+static void s2255_fillbuff(struct s2255_channel *channel,
+                          struct s2255_buffer *buf, int jpgsize)
+{
+       int pos = 0;
+       struct timeval ts;
+       const char *tmpbuf;
+       char *vbuf = videobuf_to_vmalloc(&buf->vb);
+       unsigned long last_frame;
+
+       if (!vbuf)
+               return;
+       last_frame = channel->last_frame;
+       if (last_frame != -1) {
+               tmpbuf =
+                   (const char *)channel->buffer.frame[last_frame].lpvbits;
+               switch (buf->fmt->fourcc) {
+               case V4L2_PIX_FMT_YUYV:
+               case V4L2_PIX_FMT_UYVY:
+                       planar422p_to_yuv_packed((const unsigned char *)tmpbuf,
+                                                vbuf, buf->vb.width,
+                                                buf->vb.height,
+                                                buf->fmt->fourcc);
+                       break;
+               case V4L2_PIX_FMT_GREY:
+                       memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height);
+                       break;
+               case V4L2_PIX_FMT_JPEG:
+               case V4L2_PIX_FMT_MJPEG:
+                       buf->vb.size = jpgsize;
+                       memcpy(vbuf, tmpbuf, buf->vb.size);
+                       break;
+               case V4L2_PIX_FMT_YUV422P:
+                       memcpy(vbuf, tmpbuf,
+                              buf->vb.width * buf->vb.height * 2);
+                       break;
+               default:
+                       printk(KERN_DEBUG "s2255: unknown format?\n");
+               }
+               channel->last_frame = -1;
+       } else {
+               printk(KERN_ERR "s2255: =======no frame\n");
+               return;
+
+       }
+       dprintk(2, "s2255fill at : Buffer 0x%08lx size= %d\n",
+               (unsigned long)vbuf, pos);
+       /* tell v4l buffer was filled */
+
+       buf->vb.field_count = channel->frame_count * 2;
+       do_gettimeofday(&ts);
+       buf->vb.ts = ts;
+       buf->vb.state = VIDEOBUF_DONE;
+}
+
+
+/* ------------------------------------------------------------------
+   Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+                       unsigned int *size)
+{
+       struct s2255_fh *fh = vq->priv_data;
+       struct s2255_channel *channel = fh->channel;
+       *size = channel->width * channel->height * (channel->fmt->depth >> 3);
+
+       if (0 == *count)
+               *count = S2255_DEF_BUFS;
+
+       if (*size * *count > vid_limit * 1024 * 1024)
+               *count = (vid_limit * 1024 * 1024) / *size;
+
+       return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct s2255_buffer *buf)
+{
+       dprintk(4, "%s\n", __func__);
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                         enum v4l2_field field)
+{
+       struct s2255_fh *fh = vq->priv_data;
+       struct s2255_channel *channel = fh->channel;
+       struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+       int rc;
+       int w = channel->width;
+       int h = channel->height;
+       dprintk(4, "%s, field=%d\n", __func__, field);
+       if (channel->fmt == NULL)
+               return -EINVAL;
+
+       if ((w < norm_minw(&channel->vdev)) ||
+           (w > norm_maxw(&channel->vdev)) ||
+           (h < norm_minh(&channel->vdev)) ||
+           (h > norm_maxh(&channel->vdev))) {
+               dprintk(4, "invalid buffer prepare\n");
+               return -EINVAL;
+       }
+       buf->vb.size = w * h * (channel->fmt->depth >> 3);
+       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) {
+               dprintk(4, "invalid buffer prepare\n");
+               return -EINVAL;
+       }
+
+       buf->fmt = channel->fmt;
+       buf->vb.width = w;
+       buf->vb.height = h;
+       buf->vb.field = field;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+       struct s2255_fh *fh = vq->priv_data;
+       struct s2255_channel *channel = fh->channel;
+       struct s2255_dmaqueue *vidq = &channel->vidq;
+       dprintk(1, "%s\n", __func__);
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+                          struct videobuf_buffer *vb)
+{
+       struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+       struct s2255_fh *fh = vq->priv_data;
+       dprintk(4, "%s %d\n", __func__, fh->channel->idx);
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops s2255_video_qops = {
+       .buf_setup = buffer_setup,
+       .buf_prepare = buffer_prepare,
+       .buf_queue = buffer_queue,
+       .buf_release = buffer_release,
+};
+
+
+static int res_get(struct s2255_fh *fh)
+{
+       struct s2255_channel *channel = fh->channel;
+       /* is it free? */
+       if (channel->resources)
+               return 0; /* no, someone else uses it */
+       /* it's free, grab it */
+       channel->resources = 1;
+       fh->resources = 1;
+       dprintk(1, "s2255: res: get\n");
+       return 1;
+}
+
+static int res_locked(struct s2255_fh *fh)
+{
+       return fh->channel->resources;
+}
+
+static int res_check(struct s2255_fh *fh)
+{
+       return fh->resources;
+}
+
+
+static void res_free(struct s2255_fh *fh)
+{
+       struct s2255_channel *channel = fh->channel;
+       channel->resources = 0;
+       fh->resources = 0;
+       dprintk(1, "res: put\n");
+}
+
+static int vidioc_querymenu(struct file *file, void *priv,
+                           struct v4l2_querymenu *qmenu)
+{
+       static const char *colorfilter[] = {
+               "Off",
+               "On",
+               NULL
+       };
+       if (qmenu->id == V4L2_CID_PRIVATE_COLORFILTER) {
+               int i;
+               const char **menu_items = colorfilter;
+               for (i = 0; i < qmenu->index && menu_items[i]; i++)
+                       ; /* do nothing (from v4l2-common.c) */
+               if (menu_items[i] == NULL || menu_items[i][0] == '\0')
+                       return -EINVAL;
+               strlcpy(qmenu->name, menu_items[qmenu->index],
+                       sizeof(qmenu->name));
+               return 0;
+       }
+       return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct s2255_fh *fh = file->private_data;
+       struct s2255_dev *dev = fh->dev;
+       strlcpy(cap->driver, "s2255", sizeof(cap->driver));
+       strlcpy(cap->card, "s2255", sizeof(cap->card));
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                              struct v4l2_fmtdesc *f)
+{
+       int index = f->index;
+
+       if (index >= ARRAY_SIZE(formats))
+               return -EINVAL;
+       if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) ||
+                       (formats[index].fourcc == V4L2_PIX_FMT_MJPEG)))
+               return -EINVAL;
+       dprintk(4, "name %s\n", formats[index].name);
+       strlcpy(f->description, formats[index].name, sizeof(f->description));
+       f->pixelformat = formats[index].fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                           struct v4l2_format *f)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+
+       f->fmt.pix.width = channel->width;
+       f->fmt.pix.height = channel->height;
+       f->fmt.pix.field = fh->vb_vidq.field;
+       f->fmt.pix.pixelformat = channel->fmt->fourcc;
+       f->fmt.pix.bytesperline = f->fmt.pix.width * (channel->fmt->depth >> 3);
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                             struct v4l2_format *f)
+{
+       const struct s2255_fmt *fmt;
+       enum v4l2_field field;
+       int  b_any_field = 0;
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+       int is_ntsc;
+       is_ntsc =
+               (channel->vdev.current_norm & V4L2_STD_NTSC) ? 1 : 0;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+
+       if (fmt == NULL)
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+       if (field == V4L2_FIELD_ANY)
+               b_any_field = 1;
+
+       dprintk(50, "%s NTSC: %d suggested width: %d, height: %d\n",
+               __func__, is_ntsc, f->fmt.pix.width, f->fmt.pix.height);
+       if (is_ntsc) {
+               /* NTSC */
+               if (f->fmt.pix.height >= NUM_LINES_1CIFS_NTSC * 2) {
+                       f->fmt.pix.height = NUM_LINES_1CIFS_NTSC * 2;
+                       if (b_any_field) {
+                               field = V4L2_FIELD_SEQ_TB;
+                       } else if (!((field == V4L2_FIELD_INTERLACED) ||
+                                     (field == V4L2_FIELD_SEQ_TB) ||
+                                     (field == V4L2_FIELD_INTERLACED_TB))) {
+                               dprintk(1, "unsupported field setting\n");
+                               return -EINVAL;
+                       }
+               } else {
+                       f->fmt.pix.height = NUM_LINES_1CIFS_NTSC;
+                       if (b_any_field) {
+                               field = V4L2_FIELD_TOP;
+                       } else if (!((field == V4L2_FIELD_TOP) ||
+                                     (field == V4L2_FIELD_BOTTOM))) {
+                               dprintk(1, "unsupported field setting\n");
+                               return -EINVAL;
+                       }
+
+               }
+               if (f->fmt.pix.width >= LINE_SZ_4CIFS_NTSC)
+                       f->fmt.pix.width = LINE_SZ_4CIFS_NTSC;
+               else if (f->fmt.pix.width >= LINE_SZ_2CIFS_NTSC)
+                       f->fmt.pix.width = LINE_SZ_2CIFS_NTSC;
+               else if (f->fmt.pix.width >= LINE_SZ_1CIFS_NTSC)
+                       f->fmt.pix.width = LINE_SZ_1CIFS_NTSC;
+               else
+                       f->fmt.pix.width = LINE_SZ_1CIFS_NTSC;
+       } else {
+               /* PAL */
+               if (f->fmt.pix.height >= NUM_LINES_1CIFS_PAL * 2) {
+                       f->fmt.pix.height = NUM_LINES_1CIFS_PAL * 2;
+                       if (b_any_field) {
+                               field = V4L2_FIELD_SEQ_TB;
+                       } else if (!((field == V4L2_FIELD_INTERLACED) ||
+                                     (field == V4L2_FIELD_SEQ_TB) ||
+                                     (field == V4L2_FIELD_INTERLACED_TB))) {
+                               dprintk(1, "unsupported field setting\n");
+                               return -EINVAL;
+                       }
+               } else {
+                       f->fmt.pix.height = NUM_LINES_1CIFS_PAL;
+                       if (b_any_field) {
+                               field = V4L2_FIELD_TOP;
+                       } else if (!((field == V4L2_FIELD_TOP) ||
+                                    (field == V4L2_FIELD_BOTTOM))) {
+                               dprintk(1, "unsupported field setting\n");
+                               return -EINVAL;
+                       }
+               }
+               if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL) {
+                       f->fmt.pix.width = LINE_SZ_4CIFS_PAL;
+                       field = V4L2_FIELD_SEQ_TB;
+               } else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL) {
+                       f->fmt.pix.width = LINE_SZ_2CIFS_PAL;
+                       field = V4L2_FIELD_TOP;
+               } else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL) {
+                       f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
+                       field = V4L2_FIELD_TOP;
+               } else {
+                       f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
+                       field = V4L2_FIELD_TOP;
+               }
+       }
+       f->fmt.pix.field = field;
+       f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       dprintk(50, "%s: set width %d height %d field %d\n", __func__,
+               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                           struct v4l2_format *f)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+       const struct s2255_fmt *fmt;
+       struct videobuf_queue *q = &fh->vb_vidq;
+       struct s2255_mode mode;
+       int ret;
+
+       ret = vidioc_try_fmt_vid_cap(file, fh, f);
+
+       if (ret < 0)
+               return ret;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+
+       if (fmt == NULL)
+               return -EINVAL;
+
+       mutex_lock(&q->vb_lock);
+
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               dprintk(1, "queue busy\n");
+               ret = -EBUSY;
+               goto out_s_fmt;
+       }
+
+       if (res_locked(fh)) {
+               dprintk(1, "%s: channel busy\n", __func__);
+               ret = -EBUSY;
+               goto out_s_fmt;
+       }
+       mode = channel->mode;
+       channel->fmt = fmt;
+       channel->width = f->fmt.pix.width;
+       channel->height = f->fmt.pix.height;
+       fh->vb_vidq.field = f->fmt.pix.field;
+       fh->type = f->type;
+       if (channel->width > norm_minw(&channel->vdev)) {
+               if (channel->height > norm_minh(&channel->vdev)) {
+                       if (channel->cap_parm.capturemode &
+                           V4L2_MODE_HIGHQUALITY)
+                               mode.scale = SCALE_4CIFSI;
+                       else
+                               mode.scale = SCALE_4CIFS;
+               } else
+                       mode.scale = SCALE_2CIFS;
+
+       } else {
+               mode.scale = SCALE_1CIFS;
+       }
+       /* color mode */
+       switch (channel->fmt->fourcc) {
+       case V4L2_PIX_FMT_GREY:
+               mode.color &= ~MASK_COLOR;
+               mode.color |= COLOR_Y8;
+               break;
+       case V4L2_PIX_FMT_JPEG:
+       case V4L2_PIX_FMT_MJPEG:
+               mode.color &= ~MASK_COLOR;
+               mode.color |= COLOR_JPG;
+               mode.color |= (channel->jc.quality << 8);
+               break;
+       case V4L2_PIX_FMT_YUV422P:
+               mode.color &= ~MASK_COLOR;
+               mode.color |= COLOR_YUVPL;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_UYVY:
+       default:
+               mode.color &= ~MASK_COLOR;
+               mode.color |= COLOR_YUVPK;
+               break;
+       }
+       if ((mode.color & MASK_COLOR) != (channel->mode.color & MASK_COLOR))
+               mode.restart = 1;
+       else if (mode.scale != channel->mode.scale)
+               mode.restart = 1;
+       else if (mode.format != channel->mode.format)
+               mode.restart = 1;
+       channel->mode = mode;
+       (void) s2255_set_mode(channel, &mode);
+       ret = 0;
+out_s_fmt:
+       mutex_unlock(&q->vb_lock);
+       return ret;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *p)
+{
+       int rc;
+       struct s2255_fh *fh = priv;
+       rc = videobuf_reqbufs(&fh->vb_vidq, p);
+       return rc;
+}
+
+static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       int rc;
+       struct s2255_fh *fh = priv;
+       rc = videobuf_querybuf(&fh->vb_vidq, p);
+       return rc;
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       int rc;
+       struct s2255_fh *fh = priv;
+       rc = videobuf_qbuf(&fh->vb_vidq, p);
+       return rc;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       int rc;
+       struct s2255_fh *fh = priv;
+       rc = videobuf_dqbuf(&fh->vb_vidq, p, file->f_flags & O_NONBLOCK);
+       return rc;
+}
+
+/* write to the configuration pipe, synchronously */
+static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
+                             int size)
+{
+       int pipe;
+       int done;
+       long retval = -1;
+       if (udev) {
+               pipe = usb_sndbulkpipe(udev, S2255_CONFIG_EP);
+               retval = usb_bulk_msg(udev, pipe, pbuf, size, &done, 500);
+       }
+       return retval;
+}
+
+static u32 get_transfer_size(struct s2255_mode *mode)
+{
+       int linesPerFrame = LINE_SZ_DEF;
+       int pixelsPerLine = NUM_LINES_DEF;
+       u32 outImageSize;
+       u32 usbInSize;
+       unsigned int mask_mult;
+
+       if (mode == NULL)
+               return 0;
+
+       if (mode->format == FORMAT_NTSC) {
+               switch (mode->scale) {
+               case SCALE_4CIFS:
+               case SCALE_4CIFSI:
+                       linesPerFrame = NUM_LINES_4CIFS_NTSC * 2;
+                       pixelsPerLine = LINE_SZ_4CIFS_NTSC;
+                       break;
+               case SCALE_2CIFS:
+                       linesPerFrame = NUM_LINES_2CIFS_NTSC;
+                       pixelsPerLine = LINE_SZ_2CIFS_NTSC;
+                       break;
+               case SCALE_1CIFS:
+                       linesPerFrame = NUM_LINES_1CIFS_NTSC;
+                       pixelsPerLine = LINE_SZ_1CIFS_NTSC;
+                       break;
+               default:
+                       break;
+               }
+       } else if (mode->format == FORMAT_PAL) {
+               switch (mode->scale) {
+               case SCALE_4CIFS:
+               case SCALE_4CIFSI:
+                       linesPerFrame = NUM_LINES_4CIFS_PAL * 2;
+                       pixelsPerLine = LINE_SZ_4CIFS_PAL;
+                       break;
+               case SCALE_2CIFS:
+                       linesPerFrame = NUM_LINES_2CIFS_PAL;
+                       pixelsPerLine = LINE_SZ_2CIFS_PAL;
+                       break;
+               case SCALE_1CIFS:
+                       linesPerFrame = NUM_LINES_1CIFS_PAL;
+                       pixelsPerLine = LINE_SZ_1CIFS_PAL;
+                       break;
+               default:
+                       break;
+               }
+       }
+       outImageSize = linesPerFrame * pixelsPerLine;
+       if ((mode->color & MASK_COLOR) != COLOR_Y8) {
+               /* 2 bytes/pixel if not monochrome */
+               outImageSize *= 2;
+       }
+
+       /* total bytes to send including prefix and 4K padding;
+          must be a multiple of USB_READ_SIZE */
+       usbInSize = outImageSize + PREFIX_SIZE; /* always send prefix */
+       mask_mult = 0xffffffffUL - DEF_USB_BLOCK + 1;
+       /* if size not a multiple of USB_READ_SIZE */
+       if (usbInSize & ~mask_mult)
+               usbInSize = (usbInSize & mask_mult) + (DEF_USB_BLOCK);
+       return usbInSize;
+}
+
+static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode)
+{
+       struct device *dev = &sdev->udev->dev;
+       dev_info(dev, "------------------------------------------------\n");
+       dev_info(dev, "format: %d\nscale %d\n", mode->format, mode->scale);
+       dev_info(dev, "fdec: %d\ncolor %d\n", mode->fdec, mode->color);
+       dev_info(dev, "bright: 0x%x\n", mode->bright);
+       dev_info(dev, "------------------------------------------------\n");
+}
+
+/*
+ * set mode is the function which controls the DSP.
+ * the restart parameter in struct s2255_mode should be set whenever
+ * the image size could change via color format, video system or image
+ * size.
+ * When the restart parameter is set, we sleep for ONE frame to allow the
+ * DSP time to get the new frame
+ */
+static int s2255_set_mode(struct s2255_channel *channel,
+                         struct s2255_mode *mode)
+{
+       int res;
+       __le32 *buffer;
+       unsigned long chn_rev;
+       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+       chn_rev = G_chnmap[channel->idx];
+       dprintk(3, "%s channel: %d\n", __func__, channel->idx);
+       /* if JPEG, set the quality */
+       if ((mode->color & MASK_COLOR) == COLOR_JPG) {
+               mode->color &= ~MASK_COLOR;
+               mode->color |= COLOR_JPG;
+               mode->color &= ~MASK_JPG_QUALITY;
+               mode->color |= (channel->jc.quality << 8);
+       }
+       /* save the mode */
+       channel->mode = *mode;
+       channel->req_image_size = get_transfer_size(mode);
+       dprintk(1, "%s: reqsize %ld\n", __func__, channel->req_image_size);
+       buffer = kzalloc(512, GFP_KERNEL);
+       if (buffer == NULL) {
+               dev_err(&dev->udev->dev, "out of mem\n");
+               return -ENOMEM;
+       }
+       /* set the mode */
+       buffer[0] = IN_DATA_TOKEN;
+       buffer[1] = (__le32) cpu_to_le32(chn_rev);
+       buffer[2] = CMD_SET_MODE;
+       memcpy(&buffer[3], &channel->mode, sizeof(struct s2255_mode));
+       channel->setmode_ready = 0;
+       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
+       if (debug)
+               s2255_print_cfg(dev, mode);
+       kfree(buffer);
+       /* wait at least 3 frames before continuing */
+       if (mode->restart) {
+               wait_event_timeout(channel->wait_setmode,
+                                  (channel->setmode_ready != 0),
+                                  msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
+               if (channel->setmode_ready != 1) {
+                       printk(KERN_DEBUG "s2255: no set mode response\n");
+                       res = -EFAULT;
+               }
+       }
+       /* clear the restart flag */
+       channel->mode.restart = 0;
+       dprintk(1, "%s chn %d, result: %d\n", __func__, channel->idx, res);
+       return res;
+}
+
+static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus)
+{
+       int res;
+       __le32 *buffer;
+       u32 chn_rev;
+       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+       chn_rev = G_chnmap[channel->idx];
+       dprintk(4, "%s chan %d\n", __func__, channel->idx);
+       buffer = kzalloc(512, GFP_KERNEL);
+       if (buffer == NULL) {
+               dev_err(&dev->udev->dev, "out of mem\n");
+               return -ENOMEM;
+       }
+       /* form the get vid status command */
+       buffer[0] = IN_DATA_TOKEN;
+       buffer[1] = (__le32) cpu_to_le32(chn_rev);
+       buffer[2] = CMD_STATUS;
+       *pstatus = 0;
+       channel->vidstatus_ready = 0;
+       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
+       kfree(buffer);
+       wait_event_timeout(channel->wait_vidstatus,
+                          (channel->vidstatus_ready != 0),
+                          msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT));
+       if (channel->vidstatus_ready != 1) {
+               printk(KERN_DEBUG "s2255: no vidstatus response\n");
+               res = -EFAULT;
+       }
+       *pstatus = channel->vidstatus;
+       dprintk(4, "%s, vid status %d\n", __func__, *pstatus);
+       return res;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       int res;
+       struct s2255_fh *fh = priv;
+       struct s2255_dev *dev = fh->dev;
+       struct s2255_channel *channel = fh->channel;
+       int j;
+       dprintk(4, "%s\n", __func__);
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               dev_err(&dev->udev->dev, "invalid fh type0\n");
+               return -EINVAL;
+       }
+       if (i != fh->type) {
+               dev_err(&dev->udev->dev, "invalid fh type1\n");
+               return -EINVAL;
+       }
+
+       if (!res_get(fh)) {
+               s2255_dev_err(&dev->udev->dev, "stream busy\n");
+               return -EBUSY;
+       }
+       channel->last_frame = -1;
+       channel->bad_payload = 0;
+       channel->cur_frame = 0;
+       channel->frame_count = 0;
+       for (j = 0; j < SYS_FRAMES; j++) {
+               channel->buffer.frame[j].ulState = S2255_READ_IDLE;
+               channel->buffer.frame[j].cur_size = 0;
+       }
+       res = videobuf_streamon(&fh->vb_vidq);
+       if (res == 0) {
+               s2255_start_acquire(channel);
+               channel->b_acquire = 1;
+       } else
+               res_free(fh);
+
+       return res;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct s2255_fh *fh = priv;
+       dprintk(4, "%s\n, channel: %d", __func__, fh->channel->idx);
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               printk(KERN_ERR "invalid fh type0\n");
+               return -EINVAL;
+       }
+       if (i != fh->type) {
+               printk(KERN_ERR "invalid type i\n");
+               return -EINVAL;
+       }
+       s2255_stop_acquire(fh->channel);
+       videobuf_streamoff(&fh->vb_vidq);
+       res_free(fh);
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_mode mode;
+       struct videobuf_queue *q = &fh->vb_vidq;
+       int ret = 0;
+       mutex_lock(&q->vb_lock);
+       if (videobuf_queue_is_busy(q)) {
+               dprintk(1, "queue busy\n");
+               ret = -EBUSY;
+               goto out_s_std;
+       }
+       if (res_locked(fh)) {
+               dprintk(1, "can't change standard after started\n");
+               ret = -EBUSY;
+               goto out_s_std;
+       }
+       mode = fh->channel->mode;
+       if (*i & V4L2_STD_NTSC) {
+               dprintk(4, "%s NTSC\n", __func__);
+               /* if changing format, reset frame decimation/intervals */
+               if (mode.format != FORMAT_NTSC) {
+                       mode.restart = 1;
+                       mode.format = FORMAT_NTSC;
+                       mode.fdec = FDEC_1;
+               }
+       } else if (*i & V4L2_STD_PAL) {
+               dprintk(4, "%s PAL\n", __func__);
+               if (mode.format != FORMAT_PAL) {
+                       mode.restart = 1;
+                       mode.format = FORMAT_PAL;
+                       mode.fdec = FDEC_1;
+               }
+       } else {
+               ret = -EINVAL;
+       }
+       if (mode.restart)
+               s2255_set_mode(fh->channel, &mode);
+out_s_std:
+       mutex_unlock(&q->vb_lock);
+       return ret;
+}
+
+/* Sensoray 2255 is a multiple channel capture device.
+   It does not have a "crossbar" of inputs.
+   We use one V4L device per channel. The user must
+   be aware that certain combinations are not allowed.
+   For instance, you cannot do full FPS on more than 2 channels(2 videodevs)
+   at once in color(you can do full fps on 4 channels with greyscale.
+*/
+static int vidioc_enum_input(struct file *file, void *priv,
+                            struct v4l2_input *inp)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_dev *dev = fh->dev;
+       struct s2255_channel *channel = fh->channel;
+       u32 status = 0;
+       if (inp->index != 0)
+               return -EINVAL;
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std = S2255_NORMS;
+       inp->status = 0;
+       if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) {
+               int rc;
+               rc = s2255_cmd_status(fh->channel, &status);
+               dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status);
+               if (rc == 0)
+                       inp->status =  (status & 0x01) ? 0
+                               : V4L2_IN_ST_NO_SIGNAL;
+       }
+       switch (dev->pid) {
+       case 0x2255:
+       default:
+               strlcpy(inp->name, "Composite", sizeof(inp->name));
+               break;
+       case 0x2257:
+               strlcpy(inp->name, (channel->idx < 2) ? "Composite" : "S-Video",
+                       sizeof(inp->name));
+               break;
+       }
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       if (i > 0)
+               return -EINVAL;
+       return 0;
+}
+
+/* --- controls ---------------------------------------------- */
+static int vidioc_queryctrl(struct file *file, void *priv,
+                           struct v4l2_queryctrl *qc)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+       struct s2255_dev *dev = fh->dev;
+       switch (qc->id) {
+       case V4L2_CID_BRIGHTNESS:
+               v4l2_ctrl_query_fill(qc, -127, 127, 1, DEF_BRIGHT);
+               break;
+       case V4L2_CID_CONTRAST:
+               v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_CONTRAST);
+               break;
+       case V4L2_CID_SATURATION:
+               v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_SATURATION);
+               break;
+       case V4L2_CID_HUE:
+               v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_HUE);
+               break;
+       case V4L2_CID_PRIVATE_COLORFILTER:
+               if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
+                       return -EINVAL;
+               if ((dev->pid == 0x2257) && (channel->idx > 1))
+                       return -EINVAL;
+               strlcpy(qc->name, "Color Filter", sizeof(qc->name));
+               qc->type = V4L2_CTRL_TYPE_MENU;
+               qc->minimum = 0;
+               qc->maximum = 1;
+               qc->step = 1;
+               qc->default_value = 1;
+               qc->flags = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       dprintk(4, "%s, id %d\n", __func__, qc->id);
+       return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_dev *dev = fh->dev;
+       struct s2255_channel *channel = fh->channel;
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = channel->mode.bright;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctrl->value = channel->mode.contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               ctrl->value = channel->mode.saturation;
+               break;
+       case V4L2_CID_HUE:
+               ctrl->value = channel->mode.hue;
+               break;
+       case V4L2_CID_PRIVATE_COLORFILTER:
+               if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
+                       return -EINVAL;
+               if ((dev->pid == 0x2257) && (channel->idx > 1))
+                       return -EINVAL;
+               ctrl->value = !((channel->mode.color & MASK_INPUT_TYPE) >> 16);
+               break;
+       default:
+               return -EINVAL;
+       }
+       dprintk(4, "%s, id %d val %d\n", __func__, ctrl->id, ctrl->value);
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+       struct s2255_mode mode;
+       mode = channel->mode;
+       dprintk(4, "%s\n", __func__);
+       /* update the mode to the corresponding value */
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               mode.bright = ctrl->value;
+               break;
+       case V4L2_CID_CONTRAST:
+               mode.contrast = ctrl->value;
+               break;
+       case V4L2_CID_HUE:
+               mode.hue = ctrl->value;
+               break;
+       case V4L2_CID_SATURATION:
+               mode.saturation = ctrl->value;
+               break;
+       case V4L2_CID_PRIVATE_COLORFILTER:
+               if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
+                       return -EINVAL;
+               if ((dev->pid == 0x2257) && (channel->idx > 1))
+                       return -EINVAL;
+               mode.color &= ~MASK_INPUT_TYPE;
+               mode.color |= ((ctrl->value ? 0 : 1) << 16);
+               break;
+       default:
+               return -EINVAL;
+       }
+       mode.restart = 0;
+       /* set mode here.  Note: stream does not need restarted.
+          some V4L programs restart stream unnecessarily
+          after a s_crtl.
+       */
+       s2255_set_mode(fh->channel, &mode);
+       return 0;
+}
+
+static int vidioc_g_jpegcomp(struct file *file, void *priv,
+                        struct v4l2_jpegcompression *jc)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+       *jc = channel->jc;
+       dprintk(2, "%s: quality %d\n", __func__, jc->quality);
+       return 0;
+}
+
+static int vidioc_s_jpegcomp(struct file *file, void *priv,
+                        struct v4l2_jpegcompression *jc)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+       if (jc->quality < 0 || jc->quality > 100)
+               return -EINVAL;
+       channel->jc.quality = jc->quality;
+       dprintk(2, "%s: quality %d\n", __func__, jc->quality);
+       return 0;
+}
+
+static int vidioc_g_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *sp)
+{
+       struct s2255_fh *fh = priv;
+       __u32 def_num, def_dem;
+       struct s2255_channel *channel = fh->channel;
+       if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       memset(sp, 0, sizeof(struct v4l2_streamparm));
+       sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+       sp->parm.capture.capturemode = channel->cap_parm.capturemode;
+       def_num = (channel->mode.format == FORMAT_NTSC) ? 1001 : 1000;
+       def_dem = (channel->mode.format == FORMAT_NTSC) ? 30000 : 25000;
+       sp->parm.capture.timeperframe.denominator = def_dem;
+       switch (channel->mode.fdec) {
+       default:
+       case FDEC_1:
+               sp->parm.capture.timeperframe.numerator = def_num;
+               break;
+       case FDEC_2:
+               sp->parm.capture.timeperframe.numerator = def_num * 2;
+               break;
+       case FDEC_3:
+               sp->parm.capture.timeperframe.numerator = def_num * 3;
+               break;
+       case FDEC_5:
+               sp->parm.capture.timeperframe.numerator = def_num * 5;
+               break;
+       }
+       dprintk(4, "%s capture mode, %d timeperframe %d/%d\n", __func__,
+               sp->parm.capture.capturemode,
+               sp->parm.capture.timeperframe.numerator,
+               sp->parm.capture.timeperframe.denominator);
+       return 0;
+}
+
+static int vidioc_s_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *sp)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_channel *channel = fh->channel;
+       struct s2255_mode mode;
+       int fdec = FDEC_1;
+       __u32 def_num, def_dem;
+       if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       mode = channel->mode;
+       /* high quality capture mode requires a stream restart */
+       if (channel->cap_parm.capturemode
+           != sp->parm.capture.capturemode && res_locked(fh))
+               return -EBUSY;
+       def_num = (mode.format == FORMAT_NTSC) ? 1001 : 1000;
+       def_dem = (mode.format == FORMAT_NTSC) ? 30000 : 25000;
+       if (def_dem != sp->parm.capture.timeperframe.denominator)
+               sp->parm.capture.timeperframe.numerator = def_num;
+       else if (sp->parm.capture.timeperframe.numerator <= def_num)
+               sp->parm.capture.timeperframe.numerator = def_num;
+       else if (sp->parm.capture.timeperframe.numerator <= (def_num * 2)) {
+               sp->parm.capture.timeperframe.numerator = def_num * 2;
+               fdec = FDEC_2;
+       } else if (sp->parm.capture.timeperframe.numerator <= (def_num * 3)) {
+               sp->parm.capture.timeperframe.numerator = def_num * 3;
+               fdec = FDEC_3;
+       } else {
+               sp->parm.capture.timeperframe.numerator = def_num * 5;
+               fdec = FDEC_5;
+       }
+       mode.fdec = fdec;
+       sp->parm.capture.timeperframe.denominator = def_dem;
+       s2255_set_mode(channel, &mode);
+       dprintk(4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n",
+               __func__,
+               sp->parm.capture.capturemode,
+               sp->parm.capture.timeperframe.numerator,
+               sp->parm.capture.timeperframe.denominator, fdec);
+       return 0;
+}
+
+static int vidioc_enum_frameintervals(struct file *file, void *priv,
+                           struct v4l2_frmivalenum *fe)
+{
+       int is_ntsc = 0;
+#define NUM_FRAME_ENUMS 4
+       int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5};
+       if (fe->index < 0 || fe->index >= NUM_FRAME_ENUMS)
+               return -EINVAL;
+       switch (fe->width) {
+       case 640:
+               if (fe->height != 240 && fe->height != 480)
+                       return -EINVAL;
+               is_ntsc = 1;
+               break;
+       case 320:
+               if (fe->height != 240)
+                       return -EINVAL;
+               is_ntsc = 1;
+               break;
+       case 704:
+               if (fe->height != 288 && fe->height != 576)
+                       return -EINVAL;
+               break;
+       case 352:
+               if (fe->height != 288)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       fe->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fe->discrete.denominator = is_ntsc ? 30000 : 25000;
+       fe->discrete.numerator = (is_ntsc ? 1001 : 1000) * frm_dec[fe->index];
+       dprintk(4, "%s discrete %d/%d\n", __func__, fe->discrete.numerator,
+               fe->discrete.denominator);
+       return 0;
+}
+
+static int __s2255_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct s2255_channel *channel = video_drvdata(file);
+       struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
+       struct s2255_fh *fh;
+       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       int state;
+       dprintk(1, "s2255: open called (dev=%s)\n",
+               video_device_node_name(vdev));
+       state = atomic_read(&dev->fw_data->fw_state);
+       switch (state) {
+       case S2255_FW_DISCONNECTING:
+               return -ENODEV;
+       case S2255_FW_FAILED:
+               s2255_dev_err(&dev->udev->dev,
+                       "firmware load failed. retrying.\n");
+               s2255_fwload_start(dev, 1);
+               wait_event_timeout(dev->fw_data->wait_fw,
+                                  ((atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_SUCCESS) ||
+                                   (atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_DISCONNECTING)),
+                                  msecs_to_jiffies(S2255_LOAD_TIMEOUT));
+               /* state may have changed, re-read */
+               state = atomic_read(&dev->fw_data->fw_state);
+               break;
+       case S2255_FW_NOTLOADED:
+       case S2255_FW_LOADED_DSPWAIT:
+               /* give S2255_LOAD_TIMEOUT time for firmware to load in case
+                  driver loaded and then device immediately opened */
+               printk(KERN_INFO "%s waiting for firmware load\n", __func__);
+               wait_event_timeout(dev->fw_data->wait_fw,
+                                  ((atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_SUCCESS) ||
+                                   (atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_DISCONNECTING)),
+                                  msecs_to_jiffies(S2255_LOAD_TIMEOUT));
+               /* state may have changed, re-read */
+               state = atomic_read(&dev->fw_data->fw_state);
+               break;
+       case S2255_FW_SUCCESS:
+       default:
+               break;
+       }
+       /* state may have changed in above switch statement */
+       switch (state) {
+       case S2255_FW_SUCCESS:
+               break;
+       case S2255_FW_FAILED:
+               printk(KERN_INFO "2255 firmware load failed.\n");
+               return -ENODEV;
+       case S2255_FW_DISCONNECTING:
+               printk(KERN_INFO "%s: disconnecting\n", __func__);
+               return -ENODEV;
+       case S2255_FW_LOADED_DSPWAIT:
+       case S2255_FW_NOTLOADED:
+               printk(KERN_INFO "%s: firmware not loaded yet"
+                      "please try again later\n",
+                      __func__);
+               /*
+                * Timeout on firmware load means device unusable.
+                * Set firmware failure state.
+                * On next s2255_open the firmware will be reloaded.
+                */
+               atomic_set(&dev->fw_data->fw_state,
+                          S2255_FW_FAILED);
+               return -EAGAIN;
+       default:
+               printk(KERN_INFO "%s: unknown state\n", __func__);
+               return -EFAULT;
+       }
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+       file->private_data = fh;
+       fh->dev = dev;
+       fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       fh->channel = channel;
+       if (!channel->configured) {
+               /* configure channel to default state */
+               channel->fmt = &formats[0];
+               s2255_set_mode(channel, &channel->mode);
+               channel->configured = 1;
+       }
+       dprintk(1, "%s: dev=%s type=%s\n", __func__,
+               video_device_node_name(vdev), v4l2_type_names[type]);
+       dprintk(2, "%s: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", __func__,
+               (unsigned long)fh, (unsigned long)dev,
+               (unsigned long)&channel->vidq);
+       dprintk(4, "%s: list_empty active=%d\n", __func__,
+               list_empty(&channel->vidq.active));
+       videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops,
+                                   NULL, &dev->slock,
+                                   fh->type,
+                                   V4L2_FIELD_INTERLACED,
+                                   sizeof(struct s2255_buffer),
+                                   fh, vdev->lock);
+       return 0;
+}
+
+static int s2255_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       int ret;
+
+       if (mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
+       ret = __s2255_open(file);
+       mutex_unlock(vdev->lock);
+       return ret;
+}
+
+static unsigned int s2255_poll(struct file *file,
+                              struct poll_table_struct *wait)
+{
+       struct s2255_fh *fh = file->private_data;
+       struct s2255_dev *dev = fh->dev;
+       int rc;
+       dprintk(100, "%s\n", __func__);
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+               return POLLERR;
+       mutex_lock(&dev->lock);
+       rc = videobuf_poll_stream(file, &fh->vb_vidq, wait);
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+static void s2255_destroy(struct s2255_dev *dev)
+{
+       /* board shutdown stops the read pipe if it is running */
+       s2255_board_shutdown(dev);
+       /* make sure firmware still not trying to load */
+       del_timer(&dev->timer);  /* only started in .probe and .open */
+       if (dev->fw_data->fw_urb) {
+               usb_kill_urb(dev->fw_data->fw_urb);
+               usb_free_urb(dev->fw_data->fw_urb);
+               dev->fw_data->fw_urb = NULL;
+       }
+       release_firmware(dev->fw_data->fw);
+       kfree(dev->fw_data->pfw_data);
+       kfree(dev->fw_data);
+       /* reset the DSP so firmware can be reloaded next time */
+       s2255_reset_dsppower(dev);
+       mutex_destroy(&dev->lock);
+       usb_put_dev(dev->udev);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       dprintk(1, "%s", __func__);
+       kfree(dev);
+}
+
+static int s2255_release(struct file *file)
+{
+       struct s2255_fh *fh = file->private_data;
+       struct s2255_dev *dev = fh->dev;
+       struct video_device *vdev = video_devdata(file);
+       struct s2255_channel *channel = fh->channel;
+       if (!dev)
+               return -ENODEV;
+       mutex_lock(&dev->lock);
+       /* turn off stream */
+       if (res_check(fh)) {
+               if (channel->b_acquire)
+                       s2255_stop_acquire(fh->channel);
+               videobuf_streamoff(&fh->vb_vidq);
+               res_free(fh);
+       }
+       videobuf_mmap_free(&fh->vb_vidq);
+       mutex_unlock(&dev->lock);
+       dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev));
+       kfree(fh);
+       return 0;
+}
+
+static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma)
+{
+       struct s2255_fh *fh = file->private_data;
+       struct s2255_dev *dev = fh->dev;
+       int ret;
+
+       if (!fh)
+               return -ENODEV;
+       dprintk(4, "%s, vma=0x%08lx\n", __func__, (unsigned long)vma);
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
+       dprintk(4, "%s vma start=0x%08lx, size=%ld, ret=%d\n", __func__,
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
+       return ret;
+}
+
+static const struct v4l2_file_operations s2255_fops_v4l = {
+       .owner = THIS_MODULE,
+       .open = s2255_open,
+       .release = s2255_release,
+       .poll = s2255_poll,
+       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+       .mmap = s2255_mmap_v4l,
+};
+
+static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
+       .vidioc_querymenu = vidioc_querymenu,
+       .vidioc_querycap = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+       .vidioc_reqbufs = vidioc_reqbufs,
+       .vidioc_querybuf = vidioc_querybuf,
+       .vidioc_qbuf = vidioc_qbuf,
+       .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_s_std = vidioc_s_std,
+       .vidioc_enum_input = vidioc_enum_input,
+       .vidioc_g_input = vidioc_g_input,
+       .vidioc_s_input = vidioc_s_input,
+       .vidioc_queryctrl = vidioc_queryctrl,
+       .vidioc_g_ctrl = vidioc_g_ctrl,
+       .vidioc_s_ctrl = vidioc_s_ctrl,
+       .vidioc_streamon = vidioc_streamon,
+       .vidioc_streamoff = vidioc_streamoff,
+       .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
+       .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
+       .vidioc_s_parm = vidioc_s_parm,
+       .vidioc_g_parm = vidioc_g_parm,
+       .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+};
+
+static void s2255_video_device_release(struct video_device *vdev)
+{
+       struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
+       dprintk(4, "%s, chnls: %d \n", __func__,
+               atomic_read(&dev->num_channels));
+       if (atomic_dec_and_test(&dev->num_channels))
+               s2255_destroy(dev);
+       return;
+}
+
+static struct video_device template = {
+       .name = "s2255v",
+       .fops = &s2255_fops_v4l,
+       .ioctl_ops = &s2255_ioctl_ops,
+       .release = s2255_video_device_release,
+       .tvnorms = S2255_NORMS,
+       .current_norm = V4L2_STD_NTSC_M,
+};
+
+static int s2255_probe_v4l(struct s2255_dev *dev)
+{
+       int ret;
+       int i;
+       int cur_nr = video_nr;
+       struct s2255_channel *channel;
+       ret = v4l2_device_register(&dev->interface->dev, &dev->v4l2_dev);
+       if (ret)
+               return ret;
+       /* initialize all video 4 linux */
+       /* register 4 video devices */
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               channel = &dev->channel[i];
+               INIT_LIST_HEAD(&channel->vidq.active);
+               channel->vidq.dev = dev;
+               /* register 4 video devices */
+               channel->vdev = template;
+               channel->vdev.lock = &dev->lock;
+               channel->vdev.v4l2_dev = &dev->v4l2_dev;
+               video_set_drvdata(&channel->vdev, channel);
+               if (video_nr == -1)
+                       ret = video_register_device(&channel->vdev,
+                                                   VFL_TYPE_GRABBER,
+                                                   video_nr);
+               else
+                       ret = video_register_device(&channel->vdev,
+                                                   VFL_TYPE_GRABBER,
+                                                   cur_nr + i);
+
+               if (ret) {
+                       dev_err(&dev->udev->dev,
+                               "failed to register video device!\n");
+                       break;
+               }
+               atomic_inc(&dev->num_channels);
+               v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
+                         video_device_node_name(&channel->vdev));
+
+       }
+       printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %s\n",
+              S2255_VERSION);
+       /* if no channels registered, return error and probe will fail*/
+       if (atomic_read(&dev->num_channels) == 0) {
+               v4l2_device_unregister(&dev->v4l2_dev);
+               return ret;
+       }
+       if (atomic_read(&dev->num_channels) != MAX_CHANNELS)
+               printk(KERN_WARNING "s2255: Not all channels available.\n");
+       return 0;
+}
+
+/* this function moves the usb stream read pipe data
+ * into the system buffers.
+ * returns 0 on success, EAGAIN if more data to process( call this
+ * function again).
+ *
+ * Received frame structure:
+ * bytes 0-3:  marker : 0x2255DA4AL (S2255_MARKER_FRAME)
+ * bytes 4-7:  channel: 0-3
+ * bytes 8-11: payload size:  size of the frame
+ * bytes 12-payloadsize+12:  frame data
+ */
+static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
+{
+       char *pdest;
+       u32 offset = 0;
+       int bframe = 0;
+       char *psrc;
+       unsigned long copy_size;
+       unsigned long size;
+       s32 idx = -1;
+       struct s2255_framei *frm;
+       unsigned char *pdata;
+       struct s2255_channel *channel;
+       dprintk(100, "buffer to user\n");
+       channel = &dev->channel[dev->cc];
+       idx = channel->cur_frame;
+       frm = &channel->buffer.frame[idx];
+       if (frm->ulState == S2255_READ_IDLE) {
+               int jj;
+               unsigned int cc;
+               __le32 *pdword; /*data from dsp is little endian */
+               int payload;
+               /* search for marker codes */
+               pdata = (unsigned char *)pipe_info->transfer_buffer;
+               pdword = (__le32 *)pdata;
+               for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) {
+                       switch (*pdword) {
+                       case S2255_MARKER_FRAME:
+                               dprintk(4, "found frame marker at offset:"
+                                       " %d [%x %x]\n", jj, pdata[0],
+                                       pdata[1]);
+                               offset = jj + PREFIX_SIZE;
+                               bframe = 1;
+                               cc = le32_to_cpu(pdword[1]);
+                               if (cc >= MAX_CHANNELS) {
+                                       printk(KERN_ERR
+                                              "bad channel\n");
+                                       return -EINVAL;
+                               }
+                               /* reverse it */
+                               dev->cc = G_chnmap[cc];
+                               channel = &dev->channel[dev->cc];
+                               payload =  le32_to_cpu(pdword[3]);
+                               if (payload > channel->req_image_size) {
+                                       channel->bad_payload++;
+                                       /* discard the bad frame */
+                                       return -EINVAL;
+                               }
+                               channel->pkt_size = payload;
+                               channel->jpg_size = le32_to_cpu(pdword[4]);
+                               break;
+                       case S2255_MARKER_RESPONSE:
+
+                               pdata += DEF_USB_BLOCK;
+                               jj += DEF_USB_BLOCK;
+                               if (le32_to_cpu(pdword[1]) >= MAX_CHANNELS)
+                                       break;
+                               cc = G_chnmap[le32_to_cpu(pdword[1])];
+                               if (cc >= MAX_CHANNELS)
+                                       break;
+                               channel = &dev->channel[cc];
+                               switch (pdword[2]) {
+                               case S2255_RESPONSE_SETMODE:
+                                       /* check if channel valid */
+                                       /* set mode ready */
+                                       channel->setmode_ready = 1;
+                                       wake_up(&channel->wait_setmode);
+                                       dprintk(5, "setmode ready %d\n", cc);
+                                       break;
+                               case S2255_RESPONSE_FW:
+                                       dev->chn_ready |= (1 << cc);
+                                       if ((dev->chn_ready & 0x0f) != 0x0f)
+                                               break;
+                                       /* all channels ready */
+                                       printk(KERN_INFO "s2255: fw loaded\n");
+                                       atomic_set(&dev->fw_data->fw_state,
+                                                  S2255_FW_SUCCESS);
+                                       wake_up(&dev->fw_data->wait_fw);
+                                       break;
+                               case S2255_RESPONSE_STATUS:
+                                       channel->vidstatus = le32_to_cpu(pdword[3]);
+                                       channel->vidstatus_ready = 1;
+                                       wake_up(&channel->wait_vidstatus);
+                                       dprintk(5, "got vidstatus %x chan %d\n",
+                                               le32_to_cpu(pdword[3]), cc);
+                                       break;
+                               default:
+                                       printk(KERN_INFO "s2255 unknown resp\n");
+                               }
+                       default:
+                               pdata++;
+                               break;
+                       }
+                       if (bframe)
+                               break;
+               } /* for */
+               if (!bframe)
+                       return -EINVAL;
+       }
+       channel = &dev->channel[dev->cc];
+       idx = channel->cur_frame;
+       frm = &channel->buffer.frame[idx];
+       /* search done.  now find out if should be acquiring on this channel */
+       if (!channel->b_acquire) {
+               /* we found a frame, but this channel is turned off */
+               frm->ulState = S2255_READ_IDLE;
+               return -EINVAL;
+       }
+
+       if (frm->ulState == S2255_READ_IDLE) {
+               frm->ulState = S2255_READ_FRAME;
+               frm->cur_size = 0;
+       }
+
+       /* skip the marker 512 bytes (and offset if out of sync) */
+       psrc = (u8 *)pipe_info->transfer_buffer + offset;
+
+
+       if (frm->lpvbits == NULL) {
+               dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d",
+                       frm, dev, dev->cc, idx);
+               return -ENOMEM;
+       }
+
+       pdest = frm->lpvbits + frm->cur_size;
+
+       copy_size = (pipe_info->cur_transfer_size - offset);
+
+       size = channel->pkt_size - PREFIX_SIZE;
+
+       /* sanity check on pdest */
+       if ((copy_size + frm->cur_size) < channel->req_image_size)
+               memcpy(pdest, psrc, copy_size);
+
+       frm->cur_size += copy_size;
+       dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size);
+
+       if (frm->cur_size >= size) {
+               dprintk(2, "****************[%d]Buffer[%d]full*************\n",
+                       dev->cc, idx);
+               channel->last_frame = channel->cur_frame;
+               channel->cur_frame++;
+               /* end of system frame ring buffer, start at zero */
+               if ((channel->cur_frame == SYS_FRAMES) ||
+                   (channel->cur_frame == channel->buffer.dwFrames))
+                       channel->cur_frame = 0;
+               /* frame ready */
+               if (channel->b_acquire)
+                       s2255_got_frame(channel, channel->jpg_size);
+               channel->frame_count++;
+               frm->ulState = S2255_READ_IDLE;
+               frm->cur_size = 0;
+
+       }
+       /* done successfully */
+       return 0;
+}
+
+static void s2255_read_video_callback(struct s2255_dev *dev,
+                                     struct s2255_pipeinfo *pipe_info)
+{
+       int res;
+       dprintk(50, "callback read video \n");
+
+       if (dev->cc >= MAX_CHANNELS) {
+               dev->cc = 0;
+               dev_err(&dev->udev->dev, "invalid channel\n");
+               return;
+       }
+       /* otherwise copy to the system buffers */
+       res = save_frame(dev, pipe_info);
+       if (res != 0)
+               dprintk(4, "s2255: read callback failed\n");
+
+       dprintk(50, "callback read video done\n");
+       return;
+}
+
+static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
+                            u16 Index, u16 Value, void *TransferBuffer,
+                            s32 TransferBufferLength, int bOut)
+{
+       int r;
+       if (!bOut) {
+               r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+                                   Request,
+                                   USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+                                   USB_DIR_IN,
+                                   Value, Index, TransferBuffer,
+                                   TransferBufferLength, HZ * 5);
+       } else {
+               r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+                                   Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                                   Value, Index, TransferBuffer,
+                                   TransferBufferLength, HZ * 5);
+       }
+       return r;
+}
+
+/*
+ * retrieve FX2 firmware version. future use.
+ * @param dev pointer to device extension
+ * @return -1 for fail, else returns firmware version as an int(16 bits)
+ */
+static int s2255_get_fx2fw(struct s2255_dev *dev)
+{
+       int fw;
+       int ret;
+       unsigned char transBuffer[64];
+       ret = s2255_vendor_req(dev, S2255_VR_FW, 0, 0, transBuffer, 2,
+                              S2255_VR_IN);
+       if (ret < 0)
+               dprintk(2, "get fw error: %x\n", ret);
+       fw = transBuffer[0] + (transBuffer[1] << 8);
+       dprintk(2, "Get FW %x %x\n", transBuffer[0], transBuffer[1]);
+       return fw;
+}
+
+/*
+ * Create the system ring buffer to copy frames into from the
+ * usb read pipe.
+ */
+static int s2255_create_sys_buffers(struct s2255_channel *channel)
+{
+       unsigned long i;
+       unsigned long reqsize;
+       dprintk(1, "create sys buffers\n");
+       channel->buffer.dwFrames = SYS_FRAMES;
+       /* always allocate maximum size(PAL) for system buffers */
+       reqsize = SYS_FRAMES_MAXSIZE;
+
+       if (reqsize > SYS_FRAMES_MAXSIZE)
+               reqsize = SYS_FRAMES_MAXSIZE;
+
+       for (i = 0; i < SYS_FRAMES; i++) {
+               /* allocate the frames */
+               channel->buffer.frame[i].lpvbits = vmalloc(reqsize);
+               dprintk(1, "valloc %p chan %d, idx %lu, pdata %p\n",
+                       &channel->buffer.frame[i], channel->idx, i,
+                       channel->buffer.frame[i].lpvbits);
+               channel->buffer.frame[i].size = reqsize;
+               if (channel->buffer.frame[i].lpvbits == NULL) {
+                       printk(KERN_INFO "out of memory.  using less frames\n");
+                       channel->buffer.dwFrames = i;
+                       break;
+               }
+       }
+
+       /* make sure internal states are set */
+       for (i = 0; i < SYS_FRAMES; i++) {
+               channel->buffer.frame[i].ulState = 0;
+               channel->buffer.frame[i].cur_size = 0;
+       }
+
+       channel->cur_frame = 0;
+       channel->last_frame = -1;
+       return 0;
+}
+
+static int s2255_release_sys_buffers(struct s2255_channel *channel)
+{
+       unsigned long i;
+       dprintk(1, "release sys buffers\n");
+       for (i = 0; i < SYS_FRAMES; i++) {
+               if (channel->buffer.frame[i].lpvbits) {
+                       dprintk(1, "vfree %p\n",
+                               channel->buffer.frame[i].lpvbits);
+                       vfree(channel->buffer.frame[i].lpvbits);
+               }
+               channel->buffer.frame[i].lpvbits = NULL;
+       }
+       return 0;
+}
+
+static int s2255_board_init(struct s2255_dev *dev)
+{
+       struct s2255_mode mode_def = DEF_MODEI_NTSC_CONT;
+       int fw_ver;
+       int j;
+       struct s2255_pipeinfo *pipe = &dev->pipe;
+       dprintk(4, "board init: %p", dev);
+       memset(pipe, 0, sizeof(*pipe));
+       pipe->dev = dev;
+       pipe->cur_transfer_size = S2255_USB_XFER_SIZE;
+       pipe->max_transfer_size = S2255_USB_XFER_SIZE;
+
+       pipe->transfer_buffer = kzalloc(pipe->max_transfer_size,
+                                       GFP_KERNEL);
+       if (pipe->transfer_buffer == NULL) {
+               dprintk(1, "out of memory!\n");
+               return -ENOMEM;
+       }
+       /* query the firmware */
+       fw_ver = s2255_get_fx2fw(dev);
+
+       printk(KERN_INFO "s2255: usb firmware version %d.%d\n",
+              (fw_ver >> 8) & 0xff,
+              fw_ver & 0xff);
+
+       if (fw_ver < S2255_CUR_USB_FWVER)
+               printk(KERN_INFO "s2255: newer USB firmware available\n");
+
+       for (j = 0; j < MAX_CHANNELS; j++) {
+               struct s2255_channel *channel = &dev->channel[j];
+               channel->b_acquire = 0;
+               channel->mode = mode_def;
+               if (dev->pid == 0x2257 && j > 1)
+                       channel->mode.color |= (1 << 16);
+               channel->jc.quality = S2255_DEF_JPEG_QUAL;
+               channel->width = LINE_SZ_4CIFS_NTSC;
+               channel->height = NUM_LINES_4CIFS_NTSC * 2;
+               channel->fmt = &formats[0];
+               channel->mode.restart = 1;
+               channel->req_image_size = get_transfer_size(&mode_def);
+               channel->frame_count = 0;
+               /* create the system buffers */
+               s2255_create_sys_buffers(channel);
+       }
+       /* start read pipe */
+       s2255_start_readpipe(dev);
+       dprintk(1, "%s: success\n", __func__);
+       return 0;
+}
+
+static int s2255_board_shutdown(struct s2255_dev *dev)
+{
+       u32 i;
+       dprintk(1, "%s: dev: %p", __func__,  dev);
+
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               if (dev->channel[i].b_acquire)
+                       s2255_stop_acquire(&dev->channel[i]);
+       }
+       s2255_stop_readpipe(dev);
+       for (i = 0; i < MAX_CHANNELS; i++)
+               s2255_release_sys_buffers(&dev->channel[i]);
+       /* release transfer buffer */
+       kfree(dev->pipe.transfer_buffer);
+       return 0;
+}
+
+static void read_pipe_completion(struct urb *purb)
+{
+       struct s2255_pipeinfo *pipe_info;
+       struct s2255_dev *dev;
+       int status;
+       int pipe;
+       pipe_info = purb->context;
+       dprintk(100, "%s: urb:%p, status %d\n", __func__, purb,
+               purb->status);
+       if (pipe_info == NULL) {
+               dev_err(&purb->dev->dev, "no context!\n");
+               return;
+       }
+
+       dev = pipe_info->dev;
+       if (dev == NULL) {
+               dev_err(&purb->dev->dev, "no context!\n");
+               return;
+       }
+       status = purb->status;
+       /* if shutting down, do not resubmit, exit immediately */
+       if (status == -ESHUTDOWN) {
+               dprintk(2, "%s: err shutdown\n", __func__);
+               pipe_info->err_count++;
+               return;
+       }
+
+       if (pipe_info->state == 0) {
+               dprintk(2, "%s: exiting USB pipe", __func__);
+               return;
+       }
+
+       if (status == 0)
+               s2255_read_video_callback(dev, pipe_info);
+       else {
+               pipe_info->err_count++;
+               dprintk(1, "%s: failed URB %d\n", __func__, status);
+       }
+
+       pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
+       /* reuse urb */
+       usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
+                         pipe,
+                         pipe_info->transfer_buffer,
+                         pipe_info->cur_transfer_size,
+                         read_pipe_completion, pipe_info);
+
+       if (pipe_info->state != 0) {
+               if (usb_submit_urb(pipe_info->stream_urb, GFP_ATOMIC)) {
+                       dev_err(&dev->udev->dev, "error submitting urb\n");
+               }
+       } else {
+               dprintk(2, "%s :complete state 0\n", __func__);
+       }
+       return;
+}
+
+static int s2255_start_readpipe(struct s2255_dev *dev)
+{
+       int pipe;
+       int retval;
+       struct s2255_pipeinfo *pipe_info = &dev->pipe;
+       pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
+       dprintk(2, "%s: IN %d\n", __func__, dev->read_endpoint);
+       pipe_info->state = 1;
+       pipe_info->err_count = 0;
+       pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!pipe_info->stream_urb) {
+               dev_err(&dev->udev->dev,
+                       "ReadStream: Unable to alloc URB\n");
+               return -ENOMEM;
+       }
+       /* transfer buffer allocated in board_init */
+       usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
+                         pipe,
+                         pipe_info->transfer_buffer,
+                         pipe_info->cur_transfer_size,
+                         read_pipe_completion, pipe_info);
+       retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
+       if (retval) {
+               printk(KERN_ERR "s2255: start read pipe failed\n");
+               return retval;
+       }
+       return 0;
+}
+
+/* starts acquisition process */
+static int s2255_start_acquire(struct s2255_channel *channel)
+{
+       unsigned char *buffer;
+       int res;
+       unsigned long chn_rev;
+       int j;
+       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+       chn_rev = G_chnmap[channel->idx];
+       buffer = kzalloc(512, GFP_KERNEL);
+       if (buffer == NULL) {
+               dev_err(&dev->udev->dev, "out of mem\n");
+               return -ENOMEM;
+       }
+
+       channel->last_frame = -1;
+       channel->bad_payload = 0;
+       channel->cur_frame = 0;
+       for (j = 0; j < SYS_FRAMES; j++) {
+               channel->buffer.frame[j].ulState = 0;
+               channel->buffer.frame[j].cur_size = 0;
+       }
+
+       /* send the start command */
+       *(__le32 *) buffer = IN_DATA_TOKEN;
+       *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev);
+       *((__le32 *) buffer + 2) = CMD_START;
+       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
+       if (res != 0)
+               dev_err(&dev->udev->dev, "CMD_START error\n");
+
+       dprintk(2, "start acquire exit[%d] %d \n", channel->idx, res);
+       kfree(buffer);
+       return 0;
+}
+
+static int s2255_stop_acquire(struct s2255_channel *channel)
+{
+       unsigned char *buffer;
+       int res;
+       unsigned long chn_rev;
+       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+       chn_rev = G_chnmap[channel->idx];
+       buffer = kzalloc(512, GFP_KERNEL);
+       if (buffer == NULL) {
+               dev_err(&dev->udev->dev, "out of mem\n");
+               return -ENOMEM;
+       }
+       /* send the stop command */
+       *(__le32 *) buffer = IN_DATA_TOKEN;
+       *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev);
+       *((__le32 *) buffer + 2) = CMD_STOP;
+       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
+       if (res != 0)
+               dev_err(&dev->udev->dev, "CMD_STOP error\n");
+       kfree(buffer);
+       channel->b_acquire = 0;
+       dprintk(4, "%s: chn %d, res %d\n", __func__, channel->idx, res);
+       return res;
+}
+
+static void s2255_stop_readpipe(struct s2255_dev *dev)
+{
+       struct s2255_pipeinfo *pipe = &dev->pipe;
+
+       pipe->state = 0;
+       if (pipe->stream_urb) {
+               /* cancel urb */
+               usb_kill_urb(pipe->stream_urb);
+               usb_free_urb(pipe->stream_urb);
+               pipe->stream_urb = NULL;
+       }
+       dprintk(4, "%s", __func__);
+       return;
+}
+
+static void s2255_fwload_start(struct s2255_dev *dev, int reset)
+{
+       if (reset)
+               s2255_reset_dsppower(dev);
+       dev->fw_data->fw_size = dev->fw_data->fw->size;
+       atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED);
+       memcpy(dev->fw_data->pfw_data,
+              dev->fw_data->fw->data, CHUNK_SIZE);
+       dev->fw_data->fw_loaded = CHUNK_SIZE;
+       usb_fill_bulk_urb(dev->fw_data->fw_urb, dev->udev,
+                         usb_sndbulkpipe(dev->udev, 2),
+                         dev->fw_data->pfw_data,
+                         CHUNK_SIZE, s2255_fwchunk_complete,
+                         dev->fw_data);
+       mod_timer(&dev->timer, jiffies + HZ);
+}
+
+/* standard usb probe function */
+static int s2255_probe(struct usb_interface *interface,
+                      const struct usb_device_id *id)
+{
+       struct s2255_dev *dev = NULL;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int i;
+       int retval = -ENOMEM;
+       __le32 *pdata;
+       int fw_size;
+       dprintk(2, "%s\n", __func__);
+       /* allocate memory for our device state and initialize it to zero */
+       dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
+       if (dev == NULL) {
+               s2255_dev_err(&interface->dev, "out of memory\n");
+               return -ENOMEM;
+       }
+       atomic_set(&dev->num_channels, 0);
+       dev->pid = id->idProduct;
+       dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
+       if (!dev->fw_data)
+               goto errorFWDATA1;
+       mutex_init(&dev->lock);
+       /* grab usb_device and save it */
+       dev->udev = usb_get_dev(interface_to_usbdev(interface));
+       if (dev->udev == NULL) {
+               dev_err(&interface->dev, "null usb device\n");
+               retval = -ENODEV;
+               goto errorUDEV;
+       }
+       dprintk(1, "dev: %p, udev %p interface %p\n", dev,
+               dev->udev, interface);
+       dev->interface = interface;
+       /* set up the endpoint information  */
+       iface_desc = interface->cur_altsetting;
+       dprintk(1, "num endpoints %d\n", iface_desc->desc.bNumEndpoints);
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (!dev->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
+                       /* we found the bulk in endpoint */
+                       dev->read_endpoint = endpoint->bEndpointAddress;
+               }
+       }
+
+       if (!dev->read_endpoint) {
+               dev_err(&interface->dev, "Could not find bulk-in endpoint\n");
+               goto errorEP;
+       }
+       init_timer(&dev->timer);
+       dev->timer.function = s2255_timer;
+       dev->timer.data = (unsigned long)dev->fw_data;
+       init_waitqueue_head(&dev->fw_data->wait_fw);
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               struct s2255_channel *channel = &dev->channel[i];
+               dev->channel[i].idx = i;
+               init_waitqueue_head(&channel->wait_setmode);
+               init_waitqueue_head(&channel->wait_vidstatus);
+       }
+
+       dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->fw_data->fw_urb) {
+               dev_err(&interface->dev, "out of memory!\n");
+               goto errorFWURB;
+       }
+
+       dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL);
+       if (!dev->fw_data->pfw_data) {
+               dev_err(&interface->dev, "out of memory!\n");
+               goto errorFWDATA2;
+       }
+       /* load the first chunk */
+       if (request_firmware(&dev->fw_data->fw,
+                            FIRMWARE_FILE_NAME, &dev->udev->dev)) {
+               printk(KERN_ERR "sensoray 2255 failed to get firmware\n");
+               goto errorREQFW;
+       }
+       /* check the firmware is valid */
+       fw_size = dev->fw_data->fw->size;
+       pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
+
+       if (*pdata != S2255_FW_MARKER) {
+               printk(KERN_INFO "Firmware invalid.\n");
+               retval = -ENODEV;
+               goto errorFWMARKER;
+       } else {
+               /* make sure firmware is the latest */
+               __le32 *pRel;
+               pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
+               printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
+               dev->dsp_fw_ver = le32_to_cpu(*pRel);
+               if (dev->dsp_fw_ver < S2255_CUR_DSP_FWVER)
+                       printk(KERN_INFO "s2255: f2255usb.bin out of date.\n");
+               if (dev->pid == 0x2257 &&
+                               dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
+                       printk(KERN_WARNING "s2255: 2257 requires firmware %d"
+                              " or above.\n", S2255_MIN_DSP_COLORFILTER);
+       }
+       usb_reset_device(dev->udev);
+       /* load 2255 board specific */
+       retval = s2255_board_init(dev);
+       if (retval)
+               goto errorBOARDINIT;
+       spin_lock_init(&dev->slock);
+       s2255_fwload_start(dev, 0);
+       /* loads v4l specific */
+       retval = s2255_probe_v4l(dev);
+       if (retval)
+               goto errorBOARDINIT;
+       dev_info(&interface->dev, "Sensoray 2255 detected\n");
+       return 0;
+errorBOARDINIT:
+       s2255_board_shutdown(dev);
+errorFWMARKER:
+       release_firmware(dev->fw_data->fw);
+errorREQFW:
+       kfree(dev->fw_data->pfw_data);
+errorFWDATA2:
+       usb_free_urb(dev->fw_data->fw_urb);
+errorFWURB:
+       del_timer(&dev->timer);
+errorEP:
+       usb_put_dev(dev->udev);
+errorUDEV:
+       kfree(dev->fw_data);
+       mutex_destroy(&dev->lock);
+errorFWDATA1:
+       kfree(dev);
+       printk(KERN_WARNING "Sensoray 2255 driver load failed: 0x%x\n", retval);
+       return retval;
+}
+
+/* disconnect routine. when board is removed physically or with rmmod */
+static void s2255_disconnect(struct usb_interface *interface)
+{
+       struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface));
+       int i;
+       int channels = atomic_read(&dev->num_channels);
+       mutex_lock(&dev->lock);
+       v4l2_device_disconnect(&dev->v4l2_dev);
+       mutex_unlock(&dev->lock);
+       /*see comments in the uvc_driver.c usb disconnect function */
+       atomic_inc(&dev->num_channels);
+       /* unregister each video device. */
+       for (i = 0; i < channels; i++)
+               video_unregister_device(&dev->channel[i].vdev);
+       /* wake up any of our timers */
+       atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
+       wake_up(&dev->fw_data->wait_fw);
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               dev->channel[i].setmode_ready = 1;
+               wake_up(&dev->channel[i].wait_setmode);
+               dev->channel[i].vidstatus_ready = 1;
+               wake_up(&dev->channel[i].wait_vidstatus);
+       }
+       if (atomic_dec_and_test(&dev->num_channels))
+               s2255_destroy(dev);
+       dev_info(&interface->dev, "%s\n", __func__);
+}
+
+static struct usb_driver s2255_driver = {
+       .name = S2255_DRIVER_NAME,
+       .probe = s2255_probe,
+       .disconnect = s2255_disconnect,
+       .id_table = s2255_table,
+};
+
+module_usb_driver(s2255_driver);
+
+MODULE_DESCRIPTION("Sensoray 2255 Video for Linux driver");
+MODULE_AUTHOR("Dean Anderson (Sensoray Company Inc.)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(S2255_VERSION);
+MODULE_FIRMWARE(FIRMWARE_FILE_NAME);
diff --git a/drivers/media/usb/stkwebcam/Kconfig b/drivers/media/usb/stkwebcam/Kconfig
new file mode 100644 (file)
index 0000000..2fb0c2b
--- /dev/null
@@ -0,0 +1,13 @@
+config USB_STKWEBCAM
+       tristate "USB Syntek DC1125 Camera support"
+       depends on VIDEO_V4L2 && EXPERIMENTAL
+       ---help---
+         Say Y here if you want to use this type of camera.
+         Supported devices are typically found in some Asus laptops,
+         with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
+         may be supported by the stk11xx driver, from which this is
+         derived, see <http://sourceforge.net/projects/syntekdriver/>
+
+         To compile this driver as a module, choose M here: the
+         module will be called stkwebcam.
+
diff --git a/drivers/media/usb/stkwebcam/Makefile b/drivers/media/usb/stkwebcam/Makefile
new file mode 100644 (file)
index 0000000..20ef8a4
--- /dev/null
@@ -0,0 +1,4 @@
+stkwebcam-objs :=      stk-webcam.o stk-sensor.o
+
+obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
+
diff --git a/drivers/media/usb/stkwebcam/stk-sensor.c b/drivers/media/usb/stkwebcam/stk-sensor.c
new file mode 100644 (file)
index 0000000..e546b01
--- /dev/null
@@ -0,0 +1,595 @@
+/* stk-sensor.c: Driver for ov96xx sensor (used in some Syntek webcams)
+ *
+ * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com>
+ *
+ * Some parts derived from ov7670.c:
+ * Copyright 2006 One Laptop Per Child Association, Inc.  Written
+ * by Jonathan Corbet with substantial inspiration from Mark
+ * McClelland's ovcamchip code.
+ *
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ *
+ * This file may be distributed under the terms of the GNU General
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Controlling the sensor via the STK1125 vendor specific control interface:
+ * The camera uses an OmniVision sensor and the stk1125 provides an
+ * SCCB(i2c)-USB bridge which let us program the sensor.
+ * In my case the sensor id is 0x9652, it can be read from sensor's register
+ * 0x0A and 0x0B as follows:
+ * - read register #R:
+ *   output #R to index 0x0208
+ *   output 0x0070 to index 0x0200
+ *   input 1 byte from index 0x0201 (some kind of status register)
+ *     until its value is 0x01
+ *   input 1 byte from index 0x0209. This is the value of #R
+ * - write value V to register #R
+ *   output #R to index 0x0204
+ *   output V to index 0x0205
+ *   output 0x0005 to index 0x0200
+ *   input 1 byte from index 0x0201 until its value becomes 0x04
+ */
+
+/* It seems the i2c bus is controlled with these registers */
+
+#include "stk-webcam.h"
+
+#define STK_IIC_BASE           (0x0200)
+#  define STK_IIC_OP           (STK_IIC_BASE)
+#    define STK_IIC_OP_TX      (0x05)
+#    define STK_IIC_OP_RX      (0x70)
+#  define STK_IIC_STAT         (STK_IIC_BASE+1)
+#    define STK_IIC_STAT_TX_OK (0x04)
+#    define STK_IIC_STAT_RX_OK (0x01)
+/* I don't know what does this register.
+ * when it is 0x00 or 0x01, we cannot talk to the sensor,
+ * other values work */
+#  define STK_IIC_ENABLE       (STK_IIC_BASE+2)
+#    define STK_IIC_ENABLE_NO  (0x00)
+/* This is what the driver writes in windows */
+#    define STK_IIC_ENABLE_YES (0x1e)
+/*
+ * Address of the slave. Seems like the binary driver look for the
+ * sensor in multiple places, attempting a reset sequence.
+ * We only know about the ov9650
+ */
+#  define STK_IIC_ADDR         (STK_IIC_BASE+3)
+#  define STK_IIC_TX_INDEX     (STK_IIC_BASE+4)
+#  define STK_IIC_TX_VALUE     (STK_IIC_BASE+5)
+#  define STK_IIC_RX_INDEX     (STK_IIC_BASE+8)
+#  define STK_IIC_RX_VALUE     (STK_IIC_BASE+9)
+
+#define MAX_RETRIES            (50)
+
+#define SENSOR_ADDRESS         (0x60)
+
+/* From ov7670.c (These registers aren't fully accurate) */
+
+/* Registers */
+#define REG_GAIN       0x00    /* Gain lower 8 bits (rest in vref) */
+#define REG_BLUE       0x01    /* blue gain */
+#define REG_RED                0x02    /* red gain */
+#define REG_VREF       0x03    /* Pieces of GAIN, VSTART, VSTOP */
+#define REG_COM1       0x04    /* Control 1 */
+#define  COM1_CCIR656    0x40  /* CCIR656 enable */
+#define  COM1_QFMT       0x20  /* QVGA/QCIF format */
+#define  COM1_SKIP_0     0x00  /* Do not skip any row */
+#define  COM1_SKIP_2     0x04  /* Skip 2 rows of 4 */
+#define  COM1_SKIP_3     0x08  /* Skip 3 rows of 4 */
+#define REG_BAVE       0x05    /* U/B Average level */
+#define REG_GbAVE      0x06    /* Y/Gb Average level */
+#define REG_AECHH      0x07    /* AEC MS 5 bits */
+#define REG_RAVE       0x08    /* V/R Average level */
+#define REG_COM2       0x09    /* Control 2 */
+#define  COM2_SSLEEP     0x10  /* Soft sleep mode */
+#define REG_PID                0x0a    /* Product ID MSB */
+#define REG_VER                0x0b    /* Product ID LSB */
+#define REG_COM3       0x0c    /* Control 3 */
+#define  COM3_SWAP       0x40    /* Byte swap */
+#define  COM3_SCALEEN    0x08    /* Enable scaling */
+#define  COM3_DCWEN      0x04    /* Enable downsamp/crop/window */
+#define REG_COM4       0x0d    /* Control 4 */
+#define REG_COM5       0x0e    /* All "reserved" */
+#define REG_COM6       0x0f    /* Control 6 */
+#define REG_AECH       0x10    /* More bits of AEC value */
+#define REG_CLKRC      0x11    /* Clock control */
+#define   CLK_PLL        0x80    /* Enable internal PLL */
+#define   CLK_EXT        0x40    /* Use external clock directly */
+#define   CLK_SCALE      0x3f    /* Mask for internal clock scale */
+#define REG_COM7       0x12    /* Control 7 */
+#define   COM7_RESET     0x80    /* Register reset */
+#define   COM7_FMT_MASK          0x38
+#define   COM7_FMT_SXGA          0x00
+#define   COM7_FMT_VGA   0x40
+#define          COM7_FMT_CIF    0x20    /* CIF format */
+#define   COM7_FMT_QVGA          0x10    /* QVGA format */
+#define   COM7_FMT_QCIF          0x08    /* QCIF format */
+#define          COM7_RGB        0x04    /* bits 0 and 2 - RGB format */
+#define          COM7_YUV        0x00    /* YUV */
+#define          COM7_BAYER      0x01    /* Bayer format */
+#define          COM7_PBAYER     0x05    /* "Processed bayer" */
+#define REG_COM8       0x13    /* Control 8 */
+#define   COM8_FASTAEC   0x80    /* Enable fast AGC/AEC */
+#define   COM8_AECSTEP   0x40    /* Unlimited AEC step size */
+#define   COM8_BFILT     0x20    /* Band filter enable */
+#define   COM8_AGC       0x04    /* Auto gain enable */
+#define   COM8_AWB       0x02    /* White balance enable */
+#define   COM8_AEC       0x01    /* Auto exposure enable */
+#define REG_COM9       0x14    /* Control 9  - gain ceiling */
+#define REG_COM10      0x15    /* Control 10 */
+#define   COM10_HSYNC    0x40    /* HSYNC instead of HREF */
+#define   COM10_PCLK_HB          0x20    /* Suppress PCLK on horiz blank */
+#define   COM10_HREF_REV  0x08   /* Reverse HREF */
+#define   COM10_VS_LEAD          0x04    /* VSYNC on clock leading edge */
+#define   COM10_VS_NEG   0x02    /* VSYNC negative */
+#define   COM10_HS_NEG   0x01    /* HSYNC negative */
+#define REG_HSTART     0x17    /* Horiz start high bits */
+#define REG_HSTOP      0x18    /* Horiz stop high bits */
+#define REG_VSTART     0x19    /* Vert start high bits */
+#define REG_VSTOP      0x1a    /* Vert stop high bits */
+#define REG_PSHFT      0x1b    /* Pixel delay after HREF */
+#define REG_MIDH       0x1c    /* Manuf. ID high */
+#define REG_MIDL       0x1d    /* Manuf. ID low */
+#define REG_MVFP       0x1e    /* Mirror / vflip */
+#define   MVFP_MIRROR    0x20    /* Mirror image */
+#define   MVFP_FLIP      0x10    /* Vertical flip */
+
+#define REG_AEW                0x24    /* AGC upper limit */
+#define REG_AEB                0x25    /* AGC lower limit */
+#define REG_VPT                0x26    /* AGC/AEC fast mode op region */
+#define REG_ADVFL      0x2d    /* Insert dummy lines (LSB) */
+#define REG_ADVFH      0x2e    /* Insert dummy lines (MSB) */
+#define REG_HSYST      0x30    /* HSYNC rising edge delay */
+#define REG_HSYEN      0x31    /* HSYNC falling edge delay */
+#define REG_HREF       0x32    /* HREF pieces */
+#define REG_TSLB       0x3a    /* lots of stuff */
+#define   TSLB_YLAST     0x04    /* UYVY or VYUY - see com13 */
+#define   TSLB_BYTEORD   0x08    /* swap bytes in 16bit mode? */
+#define REG_COM11      0x3b    /* Control 11 */
+#define   COM11_NIGHT    0x80    /* NIght mode enable */
+#define   COM11_NMFR     0x60    /* Two bit NM frame rate */
+#define   COM11_HZAUTO   0x10    /* Auto detect 50/60 Hz */
+#define          COM11_50HZ      0x08    /* Manual 50Hz select */
+#define   COM11_EXP      0x02
+#define REG_COM12      0x3c    /* Control 12 */
+#define   COM12_HREF     0x80    /* HREF always */
+#define REG_COM13      0x3d    /* Control 13 */
+#define   COM13_GAMMA    0x80    /* Gamma enable */
+#define          COM13_UVSAT     0x40    /* UV saturation auto adjustment */
+#define          COM13_CMATRIX   0x10    /* Enable color matrix for RGB or YUV */
+#define   COM13_UVSWAP   0x01    /* V before U - w/TSLB */
+#define REG_COM14      0x3e    /* Control 14 */
+#define   COM14_DCWEN    0x10    /* DCW/PCLK-scale enable */
+#define REG_EDGE       0x3f    /* Edge enhancement factor */
+#define REG_COM15      0x40    /* Control 15 */
+#define   COM15_R10F0    0x00    /* Data range 10 to F0 */
+#define          COM15_R01FE     0x80    /*            01 to FE */
+#define   COM15_R00FF    0xc0    /*            00 to FF */
+#define   COM15_RGB565   0x10    /* RGB565 output */
+#define   COM15_RGBFIXME         0x20    /* FIXME  */
+#define   COM15_RGB555   0x30    /* RGB555 output */
+#define REG_COM16      0x41    /* Control 16 */
+#define   COM16_AWBGAIN   0x08   /* AWB gain enable */
+#define REG_COM17      0x42    /* Control 17 */
+#define   COM17_AECWIN   0xc0    /* AEC window - must match COM4 */
+#define   COM17_CBAR     0x08    /* DSP Color bar */
+
+/*
+ * This matrix defines how the colors are generated, must be
+ * tweaked to adjust hue and saturation.
+ *
+ * Order: v-red, v-green, v-blue, u-red, u-green, u-blue
+ *
+ * They are nine-bit signed quantities, with the sign bit
+ * stored in 0x58.  Sign for v-red is bit 0, and up from there.
+ */
+#define        REG_CMATRIX_BASE 0x4f
+#define   CMATRIX_LEN 6
+#define REG_CMATRIX_SIGN 0x58
+
+
+#define REG_BRIGHT     0x55    /* Brightness */
+#define REG_CONTRAS    0x56    /* Contrast control */
+
+#define REG_GFIX       0x69    /* Fix gain control */
+
+#define REG_RGB444     0x8c    /* RGB 444 control */
+#define   R444_ENABLE    0x02    /* Turn on RGB444, overrides 5x5 */
+#define   R444_RGBX      0x01    /* Empty nibble at end */
+
+#define REG_HAECC1     0x9f    /* Hist AEC/AGC control 1 */
+#define REG_HAECC2     0xa0    /* Hist AEC/AGC control 2 */
+
+#define REG_BD50MAX    0xa5    /* 50hz banding step limit */
+#define REG_HAECC3     0xa6    /* Hist AEC/AGC control 3 */
+#define REG_HAECC4     0xa7    /* Hist AEC/AGC control 4 */
+#define REG_HAECC5     0xa8    /* Hist AEC/AGC control 5 */
+#define REG_HAECC6     0xa9    /* Hist AEC/AGC control 6 */
+#define REG_HAECC7     0xaa    /* Hist AEC/AGC control 7 */
+#define REG_BD60MAX    0xab    /* 60hz banding step limit */
+
+
+
+
+/* Returns 0 if OK */
+static int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val)
+{
+       int i = 0;
+       int tmpval = 0;
+
+       if (stk_camera_write_reg(dev, STK_IIC_TX_INDEX, reg))
+               return 1;
+       if (stk_camera_write_reg(dev, STK_IIC_TX_VALUE, val))
+               return 1;
+       if (stk_camera_write_reg(dev, STK_IIC_OP, STK_IIC_OP_TX))
+               return 1;
+       do {
+               if (stk_camera_read_reg(dev, STK_IIC_STAT, &tmpval))
+                       return 1;
+               i++;
+       } while (tmpval == 0 && i < MAX_RETRIES);
+       if (tmpval != STK_IIC_STAT_TX_OK) {
+               if (tmpval)
+                       STK_ERROR("stk_sensor_outb failed, status=0x%02x\n",
+                               tmpval);
+               return 1;
+       } else
+               return 0;
+}
+
+static int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val)
+{
+       int i = 0;
+       int tmpval = 0;
+
+       if (stk_camera_write_reg(dev, STK_IIC_RX_INDEX, reg))
+               return 1;
+       if (stk_camera_write_reg(dev, STK_IIC_OP, STK_IIC_OP_RX))
+               return 1;
+       do {
+               if (stk_camera_read_reg(dev, STK_IIC_STAT, &tmpval))
+                       return 1;
+               i++;
+       } while (tmpval == 0 && i < MAX_RETRIES);
+       if (tmpval != STK_IIC_STAT_RX_OK) {
+               if (tmpval)
+                       STK_ERROR("stk_sensor_inb failed, status=0x%02x\n",
+                               tmpval);
+               return 1;
+       }
+
+       if (stk_camera_read_reg(dev, STK_IIC_RX_VALUE, &tmpval))
+               return 1;
+
+       *val = (u8) tmpval;
+       return 0;
+}
+
+static int stk_sensor_write_regvals(struct stk_camera *dev,
+               struct regval *rv)
+{
+       int ret;
+       if (rv == NULL)
+               return 0;
+       while (rv->reg != 0xff || rv->val != 0xff) {
+               ret = stk_sensor_outb(dev, rv->reg, rv->val);
+               if (ret != 0)
+                       return ret;
+               rv++;
+       }
+       return 0;
+}
+
+int stk_sensor_sleep(struct stk_camera *dev)
+{
+       u8 tmp;
+       return stk_sensor_inb(dev, REG_COM2, &tmp)
+               || stk_sensor_outb(dev, REG_COM2, tmp|COM2_SSLEEP);
+}
+
+int stk_sensor_wakeup(struct stk_camera *dev)
+{
+       u8 tmp;
+       return stk_sensor_inb(dev, REG_COM2, &tmp)
+               || stk_sensor_outb(dev, REG_COM2, tmp&~COM2_SSLEEP);
+}
+
+static struct regval ov_initvals[] = {
+       {REG_CLKRC, CLK_PLL},
+       {REG_COM11, 0x01},
+       {0x6a, 0x7d},
+       {REG_AECH, 0x40},
+       {REG_GAIN, 0x00},
+       {REG_BLUE, 0x80},
+       {REG_RED, 0x80},
+       /* Do not enable fast AEC for now */
+       /*{REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC},*/
+       {REG_COM8, COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC},
+       {0x39, 0x50}, {0x38, 0x93},
+       {0x37, 0x00}, {0x35, 0x81},
+       {REG_COM5, 0x20},
+       {REG_COM1, 0x00},
+       {REG_COM3, 0x00},
+       {REG_COM4, 0x00},
+       {REG_PSHFT, 0x00},
+       {0x16, 0x07},
+       {0x33, 0xe2}, {0x34, 0xbf},
+       {REG_COM16, 0x00},
+       {0x96, 0x04},
+       /* Gamma curve values */
+/*     { 0x7a, 0x20 },         { 0x7b, 0x10 },
+       { 0x7c, 0x1e },         { 0x7d, 0x35 },
+       { 0x7e, 0x5a },         { 0x7f, 0x69 },
+       { 0x80, 0x76 },         { 0x81, 0x80 },
+       { 0x82, 0x88 },         { 0x83, 0x8f },
+       { 0x84, 0x96 },         { 0x85, 0xa3 },
+       { 0x86, 0xaf },         { 0x87, 0xc4 },
+       { 0x88, 0xd7 },         { 0x89, 0xe8 },
+*/
+       {REG_GFIX, 0x40},
+       {0x8e, 0x00},
+       {REG_COM12, 0x73},
+       {0x8f, 0xdf}, {0x8b, 0x06},
+       {0x8c, 0x20},
+       {0x94, 0x88}, {0x95, 0x88},
+/*     {REG_COM15, 0xc1}, TODO */
+       {0x29, 0x3f},
+       {REG_COM6, 0x42},
+       {REG_BD50MAX, 0x80},
+       {REG_HAECC6, 0xb8}, {REG_HAECC7, 0x92},
+       {REG_BD60MAX, 0x0a},
+       {0x90, 0x00}, {0x91, 0x00},
+       {REG_HAECC1, 0x00}, {REG_HAECC2, 0x00},
+       {REG_AEW, 0x68}, {REG_AEB, 0x5c},
+       {REG_VPT, 0xc3},
+       {REG_COM9, 0x2e},
+       {0x2a, 0x00}, {0x2b, 0x00},
+
+       {0xff, 0xff}, /* END MARKER */
+};
+
+/* Probe the I2C bus and initialise the sensor chip */
+int stk_sensor_init(struct stk_camera *dev)
+{
+       u8 idl = 0;
+       u8 idh = 0;
+
+       if (stk_camera_write_reg(dev, STK_IIC_ENABLE, STK_IIC_ENABLE_YES)
+               || stk_camera_write_reg(dev, STK_IIC_ADDR, SENSOR_ADDRESS)
+               || stk_sensor_outb(dev, REG_COM7, COM7_RESET)) {
+               STK_ERROR("Sensor resetting failed\n");
+               return -ENODEV;
+       }
+       msleep(10);
+       /* Read the manufacturer ID: ov = 0x7FA2 */
+       if (stk_sensor_inb(dev, REG_MIDH, &idh)
+           || stk_sensor_inb(dev, REG_MIDL, &idl)) {
+               STK_ERROR("Strange error reading sensor ID\n");
+               return -ENODEV;
+       }
+       if (idh != 0x7f || idl != 0xa2) {
+               STK_ERROR("Huh? you don't have a sensor from ovt\n");
+               return -ENODEV;
+       }
+       if (stk_sensor_inb(dev, REG_PID, &idh)
+           || stk_sensor_inb(dev, REG_VER, &idl)) {
+               STK_ERROR("Could not read sensor model\n");
+               return -ENODEV;
+       }
+       stk_sensor_write_regvals(dev, ov_initvals);
+       msleep(10);
+       STK_INFO("OmniVision sensor detected, id %02X%02X"
+               " at address %x\n", idh, idl, SENSOR_ADDRESS);
+       return 0;
+}
+
+/* V4L2_PIX_FMT_UYVY */
+static struct regval ov_fmt_uyvy[] = {
+       {REG_TSLB, TSLB_YLAST|0x08 },
+       { 0x4f, 0x80 },         /* "matrix coefficient 1" */
+       { 0x50, 0x80 },         /* "matrix coefficient 2" */
+       { 0x51, 0    },         /* vb */
+       { 0x52, 0x22 },         /* "matrix coefficient 4" */
+       { 0x53, 0x5e },         /* "matrix coefficient 5" */
+       { 0x54, 0x80 },         /* "matrix coefficient 6" */
+       {REG_COM13, COM13_UVSAT|COM13_CMATRIX},
+       {REG_COM15, COM15_R00FF },
+       {0xff, 0xff}, /* END MARKER */
+};
+/* V4L2_PIX_FMT_YUYV */
+static struct regval ov_fmt_yuyv[] = {
+       {REG_TSLB, 0 },
+       { 0x4f, 0x80 },         /* "matrix coefficient 1" */
+       { 0x50, 0x80 },         /* "matrix coefficient 2" */
+       { 0x51, 0    },         /* vb */
+       { 0x52, 0x22 },         /* "matrix coefficient 4" */
+       { 0x53, 0x5e },         /* "matrix coefficient 5" */
+       { 0x54, 0x80 },         /* "matrix coefficient 6" */
+       {REG_COM13, COM13_UVSAT|COM13_CMATRIX},
+       {REG_COM15, COM15_R00FF },
+       {0xff, 0xff}, /* END MARKER */
+};
+
+/* V4L2_PIX_FMT_RGB565X rrrrrggg gggbbbbb */
+static struct regval ov_fmt_rgbr[] = {
+       { REG_RGB444, 0 },      /* No RGB444 please */
+       {REG_TSLB, 0x00},
+       { REG_COM1, 0x0 },
+       { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
+       { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
+       { 0x50, 0xb3 },         /* "matrix coefficient 2" */
+       { 0x51, 0    },         /* vb */
+       { 0x52, 0x3d },         /* "matrix coefficient 4" */
+       { 0x53, 0xa7 },         /* "matrix coefficient 5" */
+       { 0x54, 0xe4 },         /* "matrix coefficient 6" */
+       { REG_COM13, COM13_GAMMA },
+       { REG_COM15, COM15_RGB565|COM15_R00FF },
+       { 0xff, 0xff },
+};
+
+/* V4L2_PIX_FMT_RGB565 gggbbbbb rrrrrggg */
+static struct regval ov_fmt_rgbp[] = {
+       { REG_RGB444, 0 },      /* No RGB444 please */
+       {REG_TSLB, TSLB_BYTEORD },
+       { REG_COM1, 0x0 },
+       { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
+       { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
+       { 0x50, 0xb3 },         /* "matrix coefficient 2" */
+       { 0x51, 0    },         /* vb */
+       { 0x52, 0x3d },         /* "matrix coefficient 4" */
+       { 0x53, 0xa7 },         /* "matrix coefficient 5" */
+       { 0x54, 0xe4 },         /* "matrix coefficient 6" */
+       { REG_COM13, COM13_GAMMA },
+       { REG_COM15, COM15_RGB565|COM15_R00FF },
+       { 0xff, 0xff },
+};
+
+/* V4L2_PIX_FMT_SRGGB8 */
+static struct regval ov_fmt_bayer[] = {
+       /* This changes color order */
+       {REG_TSLB, 0x40}, /* BGGR */
+       /* {REG_TSLB, 0x08}, */ /* BGGR with vertical image flipping */
+       {REG_COM15, COM15_R00FF },
+       {0xff, 0xff}, /* END MARKER */
+};
+/*
+ * Store a set of start/stop values into the camera.
+ */
+static int stk_sensor_set_hw(struct stk_camera *dev,
+               int hstart, int hstop, int vstart, int vstop)
+{
+       int ret;
+       unsigned char v;
+/*
+ * Horizontal: 11 bits, top 8 live in hstart and hstop.  Bottom 3 of
+ * hstart are in href[2:0], bottom 3 of hstop in href[5:3].  There is
+ * a mystery "edge offset" value in the top two bits of href.
+ */
+       ret =  stk_sensor_outb(dev, REG_HSTART, (hstart >> 3) & 0xff);
+       ret += stk_sensor_outb(dev, REG_HSTOP, (hstop >> 3) & 0xff);
+       ret += stk_sensor_inb(dev, REG_HREF, &v);
+       v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
+       msleep(10);
+       ret += stk_sensor_outb(dev, REG_HREF, v);
+/*
+ * Vertical: similar arrangement (note: this is different from ov7670.c)
+ */
+       ret += stk_sensor_outb(dev, REG_VSTART, (vstart >> 3) & 0xff);
+       ret += stk_sensor_outb(dev, REG_VSTOP, (vstop >> 3) & 0xff);
+       ret += stk_sensor_inb(dev, REG_VREF, &v);
+       v = (v & 0xc0) | ((vstop & 0x7) << 3) | (vstart & 0x7);
+       msleep(10);
+       ret += stk_sensor_outb(dev, REG_VREF, v);
+       return ret;
+}
+
+
+int stk_sensor_configure(struct stk_camera *dev)
+{
+       int com7;
+       /*
+        * We setup the sensor to output dummy lines in low-res modes,
+        * so we don't get absurdly hight framerates.
+        */
+       unsigned dummylines;
+       int flip;
+       struct regval *rv;
+
+       switch (dev->vsettings.mode) {
+       case MODE_QCIF: com7 = COM7_FMT_QCIF;
+               dummylines = 604;
+               break;
+       case MODE_QVGA: com7 = COM7_FMT_QVGA;
+               dummylines = 267;
+               break;
+       case MODE_CIF: com7 = COM7_FMT_CIF;
+               dummylines = 412;
+               break;
+       case MODE_VGA: com7 = COM7_FMT_VGA;
+               dummylines = 11;
+               break;
+       case MODE_SXGA: com7 = COM7_FMT_SXGA;
+               dummylines = 0;
+               break;
+       default: STK_ERROR("Unsupported mode %d\n", dev->vsettings.mode);
+               return -EFAULT;
+       }
+       switch (dev->vsettings.palette) {
+       case V4L2_PIX_FMT_UYVY:
+               com7 |= COM7_YUV;
+               rv = ov_fmt_uyvy;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               com7 |= COM7_YUV;
+               rv = ov_fmt_yuyv;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               com7 |= COM7_RGB;
+               rv = ov_fmt_rgbp;
+               break;
+       case V4L2_PIX_FMT_RGB565X:
+               com7 |= COM7_RGB;
+               rv = ov_fmt_rgbr;
+               break;
+       case V4L2_PIX_FMT_SBGGR8:
+               com7 |= COM7_PBAYER;
+               rv = ov_fmt_bayer;
+               break;
+       default: STK_ERROR("Unsupported colorspace\n");
+               return -EFAULT;
+       }
+       /*FIXME sometimes the sensor go to a bad state
+       stk_sensor_write_regvals(dev, ov_initvals); */
+       stk_sensor_outb(dev, REG_COM7, com7);
+       msleep(50);
+       stk_sensor_write_regvals(dev, rv);
+       flip = (dev->vsettings.vflip?MVFP_FLIP:0)
+               | (dev->vsettings.hflip?MVFP_MIRROR:0);
+       stk_sensor_outb(dev, REG_MVFP, flip);
+       if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8
+                       && !dev->vsettings.vflip)
+               stk_sensor_outb(dev, REG_TSLB, 0x08);
+       stk_sensor_outb(dev, REG_ADVFH, dummylines >> 8);
+       stk_sensor_outb(dev, REG_ADVFL, dummylines & 0xff);
+       msleep(50);
+       switch (dev->vsettings.mode) {
+       case MODE_VGA:
+               if (stk_sensor_set_hw(dev, 302, 1582, 6, 486))
+                       STK_ERROR("stk_sensor_set_hw failed (VGA)\n");
+               break;
+       case MODE_SXGA:
+       case MODE_CIF:
+       case MODE_QVGA:
+       case MODE_QCIF:
+               /*FIXME These settings seem ignored by the sensor
+               if (stk_sensor_set_hw(dev, 220, 1500, 10, 1034))
+                       STK_ERROR("stk_sensor_set_hw failed (SXGA)\n");
+               */
+               break;
+       }
+       msleep(10);
+       return 0;
+}
+
+int stk_sensor_set_brightness(struct stk_camera *dev, int br)
+{
+       if (br < 0 || br > 0xff)
+               return -EINVAL;
+       stk_sensor_outb(dev, REG_AEB, max(0x00, br - 6));
+       stk_sensor_outb(dev, REG_AEW, min(0xff, br + 6));
+       return 0;
+}
+
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
new file mode 100644 (file)
index 0000000..86a0fc5
--- /dev/null
@@ -0,0 +1,1380 @@
+/*
+ * stk-webcam.c : Driver for Syntek 1125 USB webcam controller
+ *
+ * Copyright (C) 2006 Nicolas VIVIEN
+ * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com>
+ *
+ * Some parts are inspired from cafe_ccic.c
+ * Copyright 2006-2007 Jonathan Corbet
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <linux/usb.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#include "stk-webcam.h"
+
+
+static bool hflip;
+module_param(hflip, bool, 0444);
+MODULE_PARM_DESC(hflip, "Horizontal image flip (mirror). Defaults to 0");
+
+static bool vflip;
+module_param(vflip, bool, 0444);
+MODULE_PARM_DESC(vflip, "Vertical image flip. Defaults to 0");
+
+static int debug;
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "Debug v4l ioctls. Defaults to 0");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN");
+MODULE_DESCRIPTION("Syntek DC1125 webcam driver");
+
+
+/* bool for webcam LED management */
+int first_init = 1;
+
+/* Some cameras have audio interfaces, we aren't interested in those */
+static struct usb_device_id stkwebcam_table[] = {
+       { USB_DEVICE_AND_INTERFACE_INFO(0x174f, 0xa311, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x05e1, 0x0501, 0xff, 0xff, 0xff) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, stkwebcam_table);
+
+/*
+ * Basic stuff
+ */
+int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value)
+{
+       struct usb_device *udev = dev->udev;
+       int ret;
+
+       ret =  usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                       0x01,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value,
+                       index,
+                       NULL,
+                       0,
+                       500);
+       if (ret < 0)
+               return ret;
+       else
+               return 0;
+}
+
+int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value)
+{
+       struct usb_device *udev = dev->udev;
+       int ret;
+
+       ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                       0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x00,
+                       index,
+                       (u8 *) value,
+                       sizeof(u8),
+                       500);
+       if (ret < 0)
+               return ret;
+       else
+               return 0;
+}
+
+static int stk_start_stream(struct stk_camera *dev)
+{
+       int value;
+       int i, ret;
+       int value_116, value_117;
+
+       if (!is_present(dev))
+               return -ENODEV;
+       if (!is_memallocd(dev) || !is_initialised(dev)) {
+               STK_ERROR("FIXME: Buffers are not allocated\n");
+               return -EFAULT;
+       }
+       ret = usb_set_interface(dev->udev, 0, 5);
+
+       if (ret < 0)
+               STK_ERROR("usb_set_interface failed !\n");
+       if (stk_sensor_wakeup(dev))
+               STK_ERROR("error awaking the sensor\n");
+
+       stk_camera_read_reg(dev, 0x0116, &value_116);
+       stk_camera_read_reg(dev, 0x0117, &value_117);
+
+       stk_camera_write_reg(dev, 0x0116, 0x0000);
+       stk_camera_write_reg(dev, 0x0117, 0x0000);
+
+       stk_camera_read_reg(dev, 0x0100, &value);
+       stk_camera_write_reg(dev, 0x0100, value | 0x80);
+
+       stk_camera_write_reg(dev, 0x0116, value_116);
+       stk_camera_write_reg(dev, 0x0117, value_117);
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               if (dev->isobufs[i].urb) {
+                       ret = usb_submit_urb(dev->isobufs[i].urb, GFP_KERNEL);
+                       atomic_inc(&dev->urbs_used);
+                       if (ret)
+                               return ret;
+               }
+       }
+       set_streaming(dev);
+       return 0;
+}
+
+static int stk_stop_stream(struct stk_camera *dev)
+{
+       int value;
+       int i;
+       if (is_present(dev)) {
+               stk_camera_read_reg(dev, 0x0100, &value);
+               stk_camera_write_reg(dev, 0x0100, value & ~0x80);
+               if (dev->isobufs != NULL) {
+                       for (i = 0; i < MAX_ISO_BUFS; i++) {
+                               if (dev->isobufs[i].urb)
+                                       usb_kill_urb(dev->isobufs[i].urb);
+                       }
+               }
+               unset_streaming(dev);
+
+               if (usb_set_interface(dev->udev, 0, 0))
+                       STK_ERROR("usb_set_interface failed !\n");
+               if (stk_sensor_sleep(dev))
+                       STK_ERROR("error suspending the sensor\n");
+       }
+       return 0;
+}
+
+/*
+ * This seems to be the shortest init sequence we
+ * must do in order to find the sensor
+ * Bit 5 of reg. 0x0000 here is important, when reset to 0 the sensor
+ * is also reset. Maybe powers down it?
+ * Rest of values don't make a difference
+ */
+
+static struct regval stk1125_initvals[] = {
+       /*TODO: What means this sequence? */
+       {0x0000, 0x24},
+       {0x0100, 0x21},
+       {0x0002, 0x68},
+       {0x0003, 0x80},
+       {0x0005, 0x00},
+       {0x0007, 0x03},
+       {0x000d, 0x00},
+       {0x000f, 0x02},
+       {0x0300, 0x12},
+       {0x0350, 0x41},
+       {0x0351, 0x00},
+       {0x0352, 0x00},
+       {0x0353, 0x00},
+       {0x0018, 0x10},
+       {0x0019, 0x00},
+       {0x001b, 0x0e},
+       {0x001c, 0x46},
+       {0x0300, 0x80},
+       {0x001a, 0x04},
+       {0x0110, 0x00},
+       {0x0111, 0x00},
+       {0x0112, 0x00},
+       {0x0113, 0x00},
+
+       {0xffff, 0xff},
+};
+
+
+static int stk_initialise(struct stk_camera *dev)
+{
+       struct regval *rv;
+       int ret;
+       if (!is_present(dev))
+               return -ENODEV;
+       if (is_initialised(dev))
+               return 0;
+       rv = stk1125_initvals;
+       while (rv->reg != 0xffff) {
+               ret = stk_camera_write_reg(dev, rv->reg, rv->val);
+               if (ret)
+                       return ret;
+               rv++;
+       }
+       if (stk_sensor_init(dev) == 0) {
+               set_initialised(dev);
+               return 0;
+       } else
+               return -1;
+}
+
+/* *********************************************** */
+/*
+ * This function is called as an URB transfert is complete (Isochronous pipe).
+ * So, the traitement is done in interrupt time, so it has be fast, not crash,
+ * and not stall. Neat.
+ */
+static void stk_isoc_handler(struct urb *urb)
+{
+       int i;
+       int ret;
+       int framelen;
+       unsigned long flags;
+
+       unsigned char *fill = NULL;
+       unsigned char *iso_buf = NULL;
+
+       struct stk_camera *dev;
+       struct stk_sio_buffer *fb;
+
+       dev = (struct stk_camera *) urb->context;
+
+       if (dev == NULL) {
+               STK_ERROR("isoc_handler called with NULL device !\n");
+               return;
+       }
+
+       if (urb->status == -ENOENT || urb->status == -ECONNRESET
+               || urb->status == -ESHUTDOWN) {
+               atomic_dec(&dev->urbs_used);
+               return;
+       }
+
+       spin_lock_irqsave(&dev->spinlock, flags);
+
+       if (urb->status != -EINPROGRESS && urb->status != 0) {
+               STK_ERROR("isoc_handler: urb->status == %d\n", urb->status);
+               goto resubmit;
+       }
+
+       if (list_empty(&dev->sio_avail)) {
+               /*FIXME Stop streaming after a while */
+               (void) (printk_ratelimit() &&
+               STK_ERROR("isoc_handler without available buffer!\n"));
+               goto resubmit;
+       }
+       fb = list_first_entry(&dev->sio_avail,
+                       struct stk_sio_buffer, list);
+       fill = fb->buffer + fb->v4lbuf.bytesused;
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               if (urb->iso_frame_desc[i].status != 0) {
+                       if (urb->iso_frame_desc[i].status != -EXDEV)
+                               STK_ERROR("Frame %d has error %d\n", i,
+                                       urb->iso_frame_desc[i].status);
+                       continue;
+               }
+               framelen = urb->iso_frame_desc[i].actual_length;
+               iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               if (framelen <= 4)
+                       continue; /* no data */
+
+               /*
+                * we found something informational from there
+                * the isoc frames have to type of headers
+                * type1: 00 xx 00 00 or 20 xx 00 00
+                * type2: 80 xx 00 00 00 00 00 00 or a0 xx 00 00 00 00 00 00
+                * xx is a sequencer which has never been seen over 0x3f
+                * imho data written down looks like bayer, i see similarities
+                * after every 640 bytes
+                */
+               if (*iso_buf & 0x80) {
+                       framelen -= 8;
+                       iso_buf += 8;
+                       /* This marks a new frame */
+                       if (fb->v4lbuf.bytesused != 0
+                               && fb->v4lbuf.bytesused != dev->frame_size) {
+                               (void) (printk_ratelimit() &&
+                               STK_ERROR("frame %d, "
+                                       "bytesused=%d, skipping\n",
+                                       i, fb->v4lbuf.bytesused));
+                               fb->v4lbuf.bytesused = 0;
+                               fill = fb->buffer;
+                       } else if (fb->v4lbuf.bytesused == dev->frame_size) {
+                               if (list_is_singular(&dev->sio_avail)) {
+                                       /* Always reuse the last buffer */
+                                       fb->v4lbuf.bytesused = 0;
+                                       fill = fb->buffer;
+                               } else {
+                                       list_move_tail(dev->sio_avail.next,
+                                               &dev->sio_full);
+                                       wake_up(&dev->wait_frame);
+                                       fb = list_first_entry(&dev->sio_avail,
+                                               struct stk_sio_buffer, list);
+                                       fb->v4lbuf.bytesused = 0;
+                                       fill = fb->buffer;
+                               }
+                       }
+               } else {
+                       framelen -= 4;
+                       iso_buf += 4;
+               }
+
+               /* Our buffer is full !!! */
+               if (framelen + fb->v4lbuf.bytesused > dev->frame_size) {
+                       (void) (printk_ratelimit() &&
+                       STK_ERROR("Frame buffer overflow, lost sync\n"));
+                       /*FIXME Do something here? */
+                       continue;
+               }
+               spin_unlock_irqrestore(&dev->spinlock, flags);
+               memcpy(fill, iso_buf, framelen);
+               spin_lock_irqsave(&dev->spinlock, flags);
+               fill += framelen;
+
+               /* New size of our buffer */
+               fb->v4lbuf.bytesused += framelen;
+       }
+
+resubmit:
+       spin_unlock_irqrestore(&dev->spinlock, flags);
+       urb->dev = dev->udev;
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret != 0) {
+               STK_ERROR("Error (%d) re-submitting urb in stk_isoc_handler.\n",
+                       ret);
+       }
+}
+
+/* -------------------------------------------- */
+
+static int stk_prepare_iso(struct stk_camera *dev)
+{
+       void *kbuf;
+       int i, j;
+       struct urb *urb;
+       struct usb_device *udev;
+
+       if (dev == NULL)
+               return -ENXIO;
+       udev = dev->udev;
+
+       if (dev->isobufs)
+               STK_ERROR("isobufs already allocated. Bad\n");
+       else
+               dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs),
+                                      GFP_KERNEL);
+       if (dev->isobufs == NULL) {
+               STK_ERROR("Unable to allocate iso buffers\n");
+               return -ENOMEM;
+       }
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               if (dev->isobufs[i].data == NULL) {
+                       kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+                       if (kbuf == NULL) {
+                               STK_ERROR("Failed to allocate iso buffer %d\n",
+                                       i);
+                               goto isobufs_out;
+                       }
+                       dev->isobufs[i].data = kbuf;
+               } else
+                       STK_ERROR("isobuf data already allocated\n");
+               if (dev->isobufs[i].urb == NULL) {
+                       urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
+                       if (urb == NULL) {
+                               STK_ERROR("Failed to allocate URB %d\n", i);
+                               goto isobufs_out;
+                       }
+                       dev->isobufs[i].urb = urb;
+               } else {
+                       STK_ERROR("Killing URB\n");
+                       usb_kill_urb(dev->isobufs[i].urb);
+                       urb = dev->isobufs[i].urb;
+               }
+               urb->interval = 1;
+               urb->dev = udev;
+               urb->pipe = usb_rcvisocpipe(udev, dev->isoc_ep);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = dev->isobufs[i].data;
+               urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+               urb->complete = stk_isoc_handler;
+               urb->context = dev;
+               urb->start_frame = 0;
+               urb->number_of_packets = ISO_FRAMES_PER_DESC;
+
+               for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+                       urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+                       urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
+               }
+       }
+       set_memallocd(dev);
+       return 0;
+
+isobufs_out:
+       for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].data; i++)
+               kfree(dev->isobufs[i].data);
+       for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].urb; i++)
+               usb_free_urb(dev->isobufs[i].urb);
+       kfree(dev->isobufs);
+       dev->isobufs = NULL;
+       return -ENOMEM;
+}
+
+static void stk_clean_iso(struct stk_camera *dev)
+{
+       int i;
+
+       if (dev == NULL || dev->isobufs == NULL)
+               return;
+
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               struct urb *urb;
+
+               urb = dev->isobufs[i].urb;
+               if (urb) {
+                       if (atomic_read(&dev->urbs_used) && is_present(dev))
+                               usb_kill_urb(urb);
+                       usb_free_urb(urb);
+               }
+               kfree(dev->isobufs[i].data);
+       }
+       kfree(dev->isobufs);
+       dev->isobufs = NULL;
+       unset_memallocd(dev);
+}
+
+static int stk_setup_siobuf(struct stk_camera *dev, int index)
+{
+       struct stk_sio_buffer *buf = dev->sio_bufs + index;
+       INIT_LIST_HEAD(&buf->list);
+       buf->v4lbuf.length = PAGE_ALIGN(dev->frame_size);
+       buf->buffer = vmalloc_user(buf->v4lbuf.length);
+       if (buf->buffer == NULL)
+               return -ENOMEM;
+       buf->mapcount = 0;
+       buf->dev = dev;
+       buf->v4lbuf.index = index;
+       buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf->v4lbuf.field = V4L2_FIELD_NONE;
+       buf->v4lbuf.memory = V4L2_MEMORY_MMAP;
+       buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length;
+       return 0;
+}
+
+static int stk_free_sio_buffers(struct stk_camera *dev)
+{
+       int i;
+       int nbufs;
+       unsigned long flags;
+       if (dev->n_sbufs == 0 || dev->sio_bufs == NULL)
+               return 0;
+       /*
+       * If any buffers are mapped, we cannot free them at all.
+       */
+       for (i = 0; i < dev->n_sbufs; i++) {
+               if (dev->sio_bufs[i].mapcount > 0)
+                       return -EBUSY;
+       }
+       /*
+       * OK, let's do it.
+       */
+       spin_lock_irqsave(&dev->spinlock, flags);
+       INIT_LIST_HEAD(&dev->sio_avail);
+       INIT_LIST_HEAD(&dev->sio_full);
+       nbufs = dev->n_sbufs;
+       dev->n_sbufs = 0;
+       spin_unlock_irqrestore(&dev->spinlock, flags);
+       for (i = 0; i < nbufs; i++) {
+               if (dev->sio_bufs[i].buffer != NULL)
+                       vfree(dev->sio_bufs[i].buffer);
+       }
+       kfree(dev->sio_bufs);
+       dev->sio_bufs = NULL;
+       return 0;
+}
+
+static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs)
+{
+       int i;
+       if (dev->sio_bufs != NULL)
+               STK_ERROR("sio_bufs already allocated\n");
+       else {
+               dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer),
+                               GFP_KERNEL);
+               if (dev->sio_bufs == NULL)
+                       return -ENOMEM;
+               for (i = 0; i < n_sbufs; i++) {
+                       if (stk_setup_siobuf(dev, i))
+                               return (dev->n_sbufs > 1 ? 0 : -ENOMEM);
+                       dev->n_sbufs = i+1;
+               }
+       }
+       return 0;
+}
+
+static int stk_allocate_buffers(struct stk_camera *dev, unsigned n_sbufs)
+{
+       int err;
+       err = stk_prepare_iso(dev);
+       if (err) {
+               stk_clean_iso(dev);
+               return err;
+       }
+       err = stk_prepare_sio_buffers(dev, n_sbufs);
+       if (err) {
+               stk_free_sio_buffers(dev);
+               return err;
+       }
+       return 0;
+}
+
+static void stk_free_buffers(struct stk_camera *dev)
+{
+       stk_clean_iso(dev);
+       stk_free_sio_buffers(dev);
+}
+/* -------------------------------------------- */
+
+/* v4l file operations */
+
+static int v4l_stk_open(struct file *fp)
+{
+       struct stk_camera *dev;
+       struct video_device *vdev;
+
+       vdev = video_devdata(fp);
+       dev = vdev_to_camera(vdev);
+
+       if (dev == NULL || !is_present(dev))
+               return -ENXIO;
+
+       if (!first_init)
+               stk_camera_write_reg(dev, 0x0, 0x24);
+       else
+               first_init = 0;
+
+       fp->private_data = dev;
+       usb_autopm_get_interface(dev->interface);
+
+       return 0;
+}
+
+static int v4l_stk_release(struct file *fp)
+{
+       struct stk_camera *dev = fp->private_data;
+
+       if (dev->owner == fp) {
+               stk_stop_stream(dev);
+               stk_free_buffers(dev);
+               stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */
+               unset_initialised(dev);
+               dev->owner = NULL;
+       }
+
+       if (is_present(dev))
+               usb_autopm_put_interface(dev->interface);
+
+       return 0;
+}
+
+static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
+               size_t count, loff_t *f_pos)
+{
+       int i;
+       int ret;
+       unsigned long flags;
+       struct stk_sio_buffer *sbuf;
+       struct stk_camera *dev = fp->private_data;
+
+       if (!is_present(dev))
+               return -EIO;
+       if (dev->owner && dev->owner != fp)
+               return -EBUSY;
+       dev->owner = fp;
+       if (!is_streaming(dev)) {
+               if (stk_initialise(dev)
+                       || stk_allocate_buffers(dev, 3)
+                       || stk_start_stream(dev))
+                       return -ENOMEM;
+               spin_lock_irqsave(&dev->spinlock, flags);
+               for (i = 0; i < dev->n_sbufs; i++) {
+                       list_add_tail(&dev->sio_bufs[i].list, &dev->sio_avail);
+                       dev->sio_bufs[i].v4lbuf.flags = V4L2_BUF_FLAG_QUEUED;
+               }
+               spin_unlock_irqrestore(&dev->spinlock, flags);
+       }
+       if (*f_pos == 0) {
+               if (fp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full))
+                       return -EWOULDBLOCK;
+               ret = wait_event_interruptible(dev->wait_frame,
+                       !list_empty(&dev->sio_full) || !is_present(dev));
+               if (ret)
+                       return ret;
+               if (!is_present(dev))
+                       return -EIO;
+       }
+       if (count + *f_pos > dev->frame_size)
+               count = dev->frame_size - *f_pos;
+       spin_lock_irqsave(&dev->spinlock, flags);
+       if (list_empty(&dev->sio_full)) {
+               spin_unlock_irqrestore(&dev->spinlock, flags);
+               STK_ERROR("BUG: No siobufs ready\n");
+               return 0;
+       }
+       sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list);
+       spin_unlock_irqrestore(&dev->spinlock, flags);
+
+       if (copy_to_user(buf, sbuf->buffer + *f_pos, count))
+               return -EFAULT;
+
+       *f_pos += count;
+
+       if (*f_pos >= dev->frame_size) {
+               *f_pos = 0;
+               spin_lock_irqsave(&dev->spinlock, flags);
+               list_move_tail(&sbuf->list, &dev->sio_avail);
+               spin_unlock_irqrestore(&dev->spinlock, flags);
+       }
+       return count;
+}
+
+static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
+{
+       struct stk_camera *dev = fp->private_data;
+
+       poll_wait(fp, &dev->wait_frame, wait);
+
+       if (!is_present(dev))
+               return POLLERR;
+
+       if (!list_empty(&dev->sio_full))
+               return POLLIN | POLLRDNORM;
+
+       return 0;
+}
+
+
+static void stk_v4l_vm_open(struct vm_area_struct *vma)
+{
+       struct stk_sio_buffer *sbuf = vma->vm_private_data;
+       sbuf->mapcount++;
+}
+static void stk_v4l_vm_close(struct vm_area_struct *vma)
+{
+       struct stk_sio_buffer *sbuf = vma->vm_private_data;
+       sbuf->mapcount--;
+       if (sbuf->mapcount == 0)
+               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED;
+}
+static const struct vm_operations_struct stk_v4l_vm_ops = {
+       .open = stk_v4l_vm_open,
+       .close = stk_v4l_vm_close
+};
+
+static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+       unsigned int i;
+       int ret;
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       struct stk_camera *dev = fp->private_data;
+       struct stk_sio_buffer *sbuf = NULL;
+
+       if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
+               return -EINVAL;
+
+       for (i = 0; i < dev->n_sbufs; i++) {
+               if (dev->sio_bufs[i].v4lbuf.m.offset == offset) {
+                       sbuf = dev->sio_bufs + i;
+                       break;
+               }
+       }
+       if (sbuf == NULL)
+               return -EINVAL;
+       ret = remap_vmalloc_range(vma, sbuf->buffer, 0);
+       if (ret)
+               return ret;
+       vma->vm_flags |= VM_DONTEXPAND;
+       vma->vm_private_data = sbuf;
+       vma->vm_ops = &stk_v4l_vm_ops;
+       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED;
+       stk_v4l_vm_open(vma);
+       return 0;
+}
+
+/* v4l ioctl handlers */
+
+static int stk_vidioc_querycap(struct file *filp,
+               void *priv, struct v4l2_capability *cap)
+{
+       strcpy(cap->driver, "stk");
+       strcpy(cap->card, "stk");
+       cap->version = DRIVER_VERSION_NUM;
+
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
+               | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+       return 0;
+}
+
+static int stk_vidioc_enum_input(struct file *filp,
+               void *priv, struct v4l2_input *input)
+{
+       if (input->index != 0)
+               return -EINVAL;
+
+       strcpy(input->name, "Syntek USB Camera");
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+       return 0;
+}
+
+
+static int stk_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int stk_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+       else
+               return 0;
+}
+
+/* from vivi.c */
+static int stk_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
+{
+       return 0;
+}
+
+/* List of all V4Lv2 controls supported by the driver */
+static struct v4l2_queryctrl stk_controls[] = {
+       {
+               .id      = V4L2_CID_BRIGHTNESS,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Brightness",
+               .minimum = 0,
+               .maximum = 0xffff,
+               .step    = 0x0100,
+               .default_value = 0x6000,
+       },
+       {
+               .id      = V4L2_CID_HFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Horizontal Flip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 1,
+       },
+       {
+               .id      = V4L2_CID_VFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Vertical Flip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 1,
+       },
+};
+
+static int stk_vidioc_queryctrl(struct file *filp,
+               void *priv, struct v4l2_queryctrl *c)
+{
+       int i;
+       int nbr;
+       nbr = ARRAY_SIZE(stk_controls);
+
+       for (i = 0; i < nbr; i++) {
+               if (stk_controls[i].id == c->id) {
+                       memcpy(c, &stk_controls[i],
+                               sizeof(struct v4l2_queryctrl));
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static int stk_vidioc_g_ctrl(struct file *filp,
+               void *priv, struct v4l2_control *c)
+{
+       struct stk_camera *dev = priv;
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               c->value = dev->vsettings.brightness;
+               break;
+       case V4L2_CID_HFLIP:
+               c->value = dev->vsettings.hflip;
+               break;
+       case V4L2_CID_VFLIP:
+               c->value = dev->vsettings.vflip;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int stk_vidioc_s_ctrl(struct file *filp,
+               void *priv, struct v4l2_control *c)
+{
+       struct stk_camera *dev = priv;
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               dev->vsettings.brightness = c->value;
+               return stk_sensor_set_brightness(dev, c->value >> 8);
+       case V4L2_CID_HFLIP:
+               dev->vsettings.hflip = c->value;
+               return 0;
+       case V4L2_CID_VFLIP:
+               dev->vsettings.vflip = c->value;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+
+static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,
+               void *priv, struct v4l2_fmtdesc *fmtd)
+{
+       switch (fmtd->index) {
+       case 0:
+               fmtd->pixelformat = V4L2_PIX_FMT_RGB565;
+               strcpy(fmtd->description, "r5g6b5");
+               break;
+       case 1:
+               fmtd->pixelformat = V4L2_PIX_FMT_RGB565X;
+               strcpy(fmtd->description, "r5g6b5BE");
+               break;
+       case 2:
+               fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
+               strcpy(fmtd->description, "yuv4:2:2");
+               break;
+       case 3:
+               fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8;
+               strcpy(fmtd->description, "Raw bayer");
+               break;
+       case 4:
+               fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
+               strcpy(fmtd->description, "yuv4:2:2");
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static struct stk_size {
+       unsigned w;
+       unsigned h;
+       enum stk_mode m;
+} stk_sizes[] = {
+       { .w = 1280, .h = 1024, .m = MODE_SXGA, },
+       { .w = 640,  .h = 480,  .m = MODE_VGA,  },
+       { .w = 352,  .h = 288,  .m = MODE_CIF,  },
+       { .w = 320,  .h = 240,  .m = MODE_QVGA, },
+       { .w = 176,  .h = 144,  .m = MODE_QCIF, },
+};
+
+static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
+               void *priv, struct v4l2_format *f)
+{
+       struct v4l2_pix_format *pix_format = &f->fmt.pix;
+       struct stk_camera *dev = priv;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(stk_sizes) &&
+                       stk_sizes[i].m != dev->vsettings.mode; i++)
+               ;
+       if (i == ARRAY_SIZE(stk_sizes)) {
+               STK_ERROR("ERROR: mode invalid\n");
+               return -EINVAL;
+       }
+       pix_format->width = stk_sizes[i].w;
+       pix_format->height = stk_sizes[i].h;
+       pix_format->field = V4L2_FIELD_NONE;
+       pix_format->colorspace = V4L2_COLORSPACE_SRGB;
+       pix_format->pixelformat = dev->vsettings.palette;
+       if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
+               pix_format->bytesperline = pix_format->width;
+       else
+               pix_format->bytesperline = 2 * pix_format->width;
+       pix_format->sizeimage = pix_format->bytesperline
+                               * pix_format->height;
+       return 0;
+}
+
+static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
+               void *priv, struct v4l2_format *fmtd)
+{
+       int i;
+       switch (fmtd->fmt.pix.pixelformat) {
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_RGB565X:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_SBGGR8:
+               break;
+       default:
+               return -EINVAL;
+       }
+       for (i = 1; i < ARRAY_SIZE(stk_sizes); i++) {
+               if (fmtd->fmt.pix.width > stk_sizes[i].w)
+                       break;
+       }
+       if (i == ARRAY_SIZE(stk_sizes)
+               || (abs(fmtd->fmt.pix.width - stk_sizes[i-1].w)
+                       < abs(fmtd->fmt.pix.width - stk_sizes[i].w))) {
+               fmtd->fmt.pix.height = stk_sizes[i-1].h;
+               fmtd->fmt.pix.width = stk_sizes[i-1].w;
+               fmtd->fmt.pix.priv = i - 1;
+       } else {
+               fmtd->fmt.pix.height = stk_sizes[i].h;
+               fmtd->fmt.pix.width = stk_sizes[i].w;
+               fmtd->fmt.pix.priv = i;
+       }
+
+       fmtd->fmt.pix.field = V4L2_FIELD_NONE;
+       fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+       if (fmtd->fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)
+               fmtd->fmt.pix.bytesperline = fmtd->fmt.pix.width;
+       else
+               fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
+       fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
+               * fmtd->fmt.pix.height;
+       return 0;
+}
+
+static int stk_setup_format(struct stk_camera *dev)
+{
+       int i = 0;
+       int depth;
+       if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
+               depth = 1;
+       else
+               depth = 2;
+       while (i < ARRAY_SIZE(stk_sizes) &&
+                       stk_sizes[i].m != dev->vsettings.mode)
+               i++;
+       if (i == ARRAY_SIZE(stk_sizes)) {
+               STK_ERROR("Something is broken in %s\n", __func__);
+               return -EFAULT;
+       }
+       /* This registers controls some timings, not sure of what. */
+       stk_camera_write_reg(dev, 0x001b, 0x0e);
+       if (dev->vsettings.mode == MODE_SXGA)
+               stk_camera_write_reg(dev, 0x001c, 0x0e);
+       else
+               stk_camera_write_reg(dev, 0x001c, 0x46);
+       /*
+        * Registers 0x0115 0x0114 are the size of each line (bytes),
+        * regs 0x0117 0x0116 are the heigth of the image.
+        */
+       stk_camera_write_reg(dev, 0x0115,
+               ((stk_sizes[i].w * depth) >> 8) & 0xff);
+       stk_camera_write_reg(dev, 0x0114,
+               (stk_sizes[i].w * depth) & 0xff);
+       stk_camera_write_reg(dev, 0x0117,
+               (stk_sizes[i].h >> 8) & 0xff);
+       stk_camera_write_reg(dev, 0x0116,
+               stk_sizes[i].h & 0xff);
+       return stk_sensor_configure(dev);
+}
+
+static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
+               void *priv, struct v4l2_format *fmtd)
+{
+       int ret;
+       struct stk_camera *dev = priv;
+
+       if (dev == NULL)
+               return -ENODEV;
+       if (!is_present(dev))
+               return -ENODEV;
+       if (is_streaming(dev))
+               return -EBUSY;
+       if (dev->owner && dev->owner != filp)
+               return -EBUSY;
+       ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd);
+       if (ret)
+               return ret;
+       dev->owner = filp;
+
+       dev->vsettings.palette = fmtd->fmt.pix.pixelformat;
+       stk_free_buffers(dev);
+       dev->frame_size = fmtd->fmt.pix.sizeimage;
+       dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m;
+
+       stk_initialise(dev);
+       return stk_setup_format(dev);
+}
+
+static int stk_vidioc_reqbufs(struct file *filp,
+               void *priv, struct v4l2_requestbuffers *rb)
+{
+       struct stk_camera *dev = priv;
+
+       if (dev == NULL)
+               return -ENODEV;
+       if (rb->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+       if (is_streaming(dev)
+               || (dev->owner && dev->owner != filp))
+               return -EBUSY;
+       dev->owner = filp;
+
+       /*FIXME If they ask for zero, we must stop streaming and free */
+       if (rb->count < 3)
+               rb->count = 3;
+       /* Arbitrary limit */
+       else if (rb->count > 5)
+               rb->count = 5;
+
+       stk_allocate_buffers(dev, rb->count);
+       rb->count = dev->n_sbufs;
+       return 0;
+}
+
+static int stk_vidioc_querybuf(struct file *filp,
+               void *priv, struct v4l2_buffer *buf)
+{
+       struct stk_camera *dev = priv;
+       struct stk_sio_buffer *sbuf;
+
+       if (buf->index >= dev->n_sbufs)
+               return -EINVAL;
+       sbuf = dev->sio_bufs + buf->index;
+       *buf = sbuf->v4lbuf;
+       return 0;
+}
+
+static int stk_vidioc_qbuf(struct file *filp,
+               void *priv, struct v4l2_buffer *buf)
+{
+       struct stk_camera *dev = priv;
+       struct stk_sio_buffer *sbuf;
+       unsigned long flags;
+
+       if (buf->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       if (buf->index >= dev->n_sbufs)
+               return -EINVAL;
+       sbuf = dev->sio_bufs + buf->index;
+       if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED)
+               return 0;
+       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED;
+       sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE;
+       spin_lock_irqsave(&dev->spinlock, flags);
+       list_add_tail(&sbuf->list, &dev->sio_avail);
+       *buf = sbuf->v4lbuf;
+       spin_unlock_irqrestore(&dev->spinlock, flags);
+       return 0;
+}
+
+static int stk_vidioc_dqbuf(struct file *filp,
+               void *priv, struct v4l2_buffer *buf)
+{
+       struct stk_camera *dev = priv;
+       struct stk_sio_buffer *sbuf;
+       unsigned long flags;
+       int ret;
+
+       if (!is_streaming(dev))
+               return -EINVAL;
+
+       if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full))
+               return -EWOULDBLOCK;
+       ret = wait_event_interruptible(dev->wait_frame,
+               !list_empty(&dev->sio_full) || !is_present(dev));
+       if (ret)
+               return ret;
+       if (!is_present(dev))
+               return -EIO;
+
+       spin_lock_irqsave(&dev->spinlock, flags);
+       sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list);
+       list_del_init(&sbuf->list);
+       spin_unlock_irqrestore(&dev->spinlock, flags);
+       sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
+       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;
+       sbuf->v4lbuf.sequence = ++dev->sequence;
+       do_gettimeofday(&sbuf->v4lbuf.timestamp);
+
+       *buf = sbuf->v4lbuf;
+       return 0;
+}
+
+static int stk_vidioc_streamon(struct file *filp,
+               void *priv, enum v4l2_buf_type type)
+{
+       struct stk_camera *dev = priv;
+       if (is_streaming(dev))
+               return 0;
+       if (dev->sio_bufs == NULL)
+               return -EINVAL;
+       dev->sequence = 0;
+       return stk_start_stream(dev);
+}
+
+static int stk_vidioc_streamoff(struct file *filp,
+               void *priv, enum v4l2_buf_type type)
+{
+       struct stk_camera *dev = priv;
+       unsigned long flags;
+       int i;
+       stk_stop_stream(dev);
+       spin_lock_irqsave(&dev->spinlock, flags);
+       INIT_LIST_HEAD(&dev->sio_avail);
+       INIT_LIST_HEAD(&dev->sio_full);
+       for (i = 0; i < dev->n_sbufs; i++) {
+               INIT_LIST_HEAD(&dev->sio_bufs[i].list);
+               dev->sio_bufs[i].v4lbuf.flags = 0;
+       }
+       spin_unlock_irqrestore(&dev->spinlock, flags);
+       return 0;
+}
+
+
+static int stk_vidioc_g_parm(struct file *filp,
+               void *priv, struct v4l2_streamparm *sp)
+{
+       /*FIXME This is not correct */
+       sp->parm.capture.timeperframe.numerator = 1;
+       sp->parm.capture.timeperframe.denominator = 30;
+       sp->parm.capture.readbuffers = 2;
+       return 0;
+}
+
+static int stk_vidioc_enum_framesizes(struct file *filp,
+               void *priv, struct v4l2_frmsizeenum *frms)
+{
+       if (frms->index >= ARRAY_SIZE(stk_sizes))
+               return -EINVAL;
+       switch (frms->pixel_format) {
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_RGB565X:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_SBGGR8:
+               frms->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               frms->discrete.width = stk_sizes[frms->index].w;
+               frms->discrete.height = stk_sizes[frms->index].h;
+               return 0;
+       default: return -EINVAL;
+       }
+}
+
+static struct v4l2_file_operations v4l_stk_fops = {
+       .owner = THIS_MODULE,
+       .open = v4l_stk_open,
+       .release = v4l_stk_release,
+       .read = v4l_stk_read,
+       .poll = v4l_stk_poll,
+       .mmap = v4l_stk_mmap,
+       .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
+       .vidioc_querycap = stk_vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap,
+       .vidioc_enum_input = stk_vidioc_enum_input,
+       .vidioc_s_input = stk_vidioc_s_input,
+       .vidioc_g_input = stk_vidioc_g_input,
+       .vidioc_s_std = stk_vidioc_s_std,
+       .vidioc_reqbufs = stk_vidioc_reqbufs,
+       .vidioc_querybuf = stk_vidioc_querybuf,
+       .vidioc_qbuf = stk_vidioc_qbuf,
+       .vidioc_dqbuf = stk_vidioc_dqbuf,
+       .vidioc_streamon = stk_vidioc_streamon,
+       .vidioc_streamoff = stk_vidioc_streamoff,
+       .vidioc_queryctrl = stk_vidioc_queryctrl,
+       .vidioc_g_ctrl = stk_vidioc_g_ctrl,
+       .vidioc_s_ctrl = stk_vidioc_s_ctrl,
+       .vidioc_g_parm = stk_vidioc_g_parm,
+       .vidioc_enum_framesizes = stk_vidioc_enum_framesizes,
+};
+
+static void stk_v4l_dev_release(struct video_device *vd)
+{
+       struct stk_camera *dev = vdev_to_camera(vd);
+
+       if (dev->sio_bufs != NULL || dev->isobufs != NULL)
+               STK_ERROR("We are leaking memory\n");
+       usb_put_intf(dev->interface);
+       kfree(dev);
+}
+
+static struct video_device stk_v4l_data = {
+       .name = "stkwebcam",
+       .tvnorms = V4L2_STD_UNKNOWN,
+       .current_norm = V4L2_STD_UNKNOWN,
+       .fops = &v4l_stk_fops,
+       .ioctl_ops = &v4l_stk_ioctl_ops,
+       .release = stk_v4l_dev_release,
+};
+
+
+static int stk_register_video_device(struct stk_camera *dev)
+{
+       int err;
+
+       dev->vdev = stk_v4l_data;
+       dev->vdev.debug = debug;
+       dev->vdev.parent = &dev->interface->dev;
+       err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
+       if (err)
+               STK_ERROR("v4l registration failed\n");
+       else
+               STK_INFO("Syntek USB2.0 Camera is now controlling device %s\n",
+                        video_device_node_name(&dev->vdev));
+       return err;
+}
+
+
+/* USB Stuff */
+
+static int stk_camera_probe(struct usb_interface *interface,
+               const struct usb_device_id *id)
+{
+       int i;
+       int err = 0;
+
+       struct stk_camera *dev = NULL;
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+
+       dev = kzalloc(sizeof(struct stk_camera), GFP_KERNEL);
+       if (dev == NULL) {
+               STK_ERROR("Out of memory !\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&dev->spinlock);
+       init_waitqueue_head(&dev->wait_frame);
+
+       dev->udev = udev;
+       dev->interface = interface;
+       usb_get_intf(interface);
+
+       dev->vsettings.vflip = vflip;
+       dev->vsettings.hflip = hflip;
+       dev->n_sbufs = 0;
+       set_present(dev);
+
+       /* Set up the endpoint information
+        * use only the first isoc-in endpoint
+        * for the current alternate setting */
+       iface_desc = interface->cur_altsetting;
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (!dev->isoc_ep
+                       && usb_endpoint_is_isoc_in(endpoint)) {
+                       /* we found an isoc in endpoint */
+                       dev->isoc_ep = usb_endpoint_num(endpoint);
+                       break;
+               }
+       }
+       if (!dev->isoc_ep) {
+               STK_ERROR("Could not find isoc-in endpoint");
+               err = -ENODEV;
+               goto error;
+       }
+       dev->vsettings.brightness = 0x7fff;
+       dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
+       dev->vsettings.mode = MODE_VGA;
+       dev->frame_size = 640 * 480 * 2;
+
+       INIT_LIST_HEAD(&dev->sio_avail);
+       INIT_LIST_HEAD(&dev->sio_full);
+
+       usb_set_intfdata(interface, dev);
+
+       err = stk_register_video_device(dev);
+       if (err)
+               goto error;
+
+       return 0;
+
+error:
+       kfree(dev);
+       return err;
+}
+
+static void stk_camera_disconnect(struct usb_interface *interface)
+{
+       struct stk_camera *dev = usb_get_intfdata(interface);
+
+       usb_set_intfdata(interface, NULL);
+       unset_present(dev);
+
+       wake_up_interruptible(&dev->wait_frame);
+
+       STK_INFO("Syntek USB2.0 Camera release resources device %s\n",
+                video_device_node_name(&dev->vdev));
+
+       video_unregister_device(&dev->vdev);
+}
+
+#ifdef CONFIG_PM
+static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct stk_camera *dev = usb_get_intfdata(intf);
+       if (is_streaming(dev)) {
+               stk_stop_stream(dev);
+               /* yes, this is ugly */
+               set_streaming(dev);
+       }
+       return 0;
+}
+
+static int stk_camera_resume(struct usb_interface *intf)
+{
+       struct stk_camera *dev = usb_get_intfdata(intf);
+       if (!is_initialised(dev))
+               return 0;
+       unset_initialised(dev);
+       stk_initialise(dev);
+       stk_camera_write_reg(dev, 0x0, 0x49);
+       stk_setup_format(dev);
+       if (is_streaming(dev))
+               stk_start_stream(dev);
+       return 0;
+}
+#endif
+
+static struct usb_driver stk_camera_driver = {
+       .name = "stkwebcam",
+       .probe = stk_camera_probe,
+       .disconnect = stk_camera_disconnect,
+       .id_table = stkwebcam_table,
+#ifdef CONFIG_PM
+       .suspend = stk_camera_suspend,
+       .resume = stk_camera_resume,
+#endif
+};
+
+module_usb_driver(stk_camera_driver);
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.h b/drivers/media/usb/stkwebcam/stk-webcam.h
new file mode 100644 (file)
index 0000000..9f67366
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * stk-webcam.h : Driver for Syntek 1125 USB webcam controller
+ *
+ * Copyright (C) 2006 Nicolas VIVIEN
+ * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef STKWEBCAM_H
+#define STKWEBCAM_H
+
+#include <linux/usb.h>
+#include <media/v4l2-common.h>
+
+#define DRIVER_VERSION         "v0.0.1"
+#define DRIVER_VERSION_NUM     0x000001
+
+#define MAX_ISO_BUFS           3
+#define ISO_FRAMES_PER_DESC    16
+#define ISO_MAX_FRAME_SIZE     3 * 1024
+#define ISO_BUFFER_SIZE                (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+
+#define PREFIX                         "stkwebcam: "
+#define STK_INFO(str, args...)         printk(KERN_INFO PREFIX str, ##args)
+#define STK_ERROR(str, args...)                printk(KERN_ERR PREFIX str, ##args)
+#define STK_WARNING(str, args...)      printk(KERN_WARNING PREFIX str, ##args)
+
+struct stk_iso_buf {
+       void *data;
+       int length;
+       int read;
+       struct urb *urb;
+};
+
+/* Streaming IO buffers */
+struct stk_sio_buffer {
+       struct v4l2_buffer v4lbuf;
+       char *buffer;
+       int mapcount;
+       struct stk_camera *dev;
+       struct list_head list;
+};
+
+enum stk_mode {MODE_VGA, MODE_SXGA, MODE_CIF, MODE_QVGA, MODE_QCIF};
+
+struct stk_video {
+       enum stk_mode mode;
+       int brightness;
+       __u32 palette;
+       int hflip;
+       int vflip;
+};
+
+enum stk_status {
+       S_PRESENT = 1,
+       S_INITIALISED = 2,
+       S_MEMALLOCD = 4,
+       S_STREAMING = 8,
+};
+#define is_present(dev)                ((dev)->status & S_PRESENT)
+#define is_initialised(dev)    ((dev)->status & S_INITIALISED)
+#define is_streaming(dev)      ((dev)->status & S_STREAMING)
+#define is_memallocd(dev)      ((dev)->status & S_MEMALLOCD)
+#define set_present(dev)       ((dev)->status = S_PRESENT)
+#define unset_present(dev)     ((dev)->status &= \
+                                       ~(S_PRESENT|S_INITIALISED|S_STREAMING))
+#define set_initialised(dev)   ((dev)->status |= S_INITIALISED)
+#define unset_initialised(dev) ((dev)->status &= ~S_INITIALISED)
+#define set_memallocd(dev)     ((dev)->status |= S_MEMALLOCD)
+#define unset_memallocd(dev)   ((dev)->status &= ~S_MEMALLOCD)
+#define set_streaming(dev)     ((dev)->status |= S_STREAMING)
+#define unset_streaming(dev)   ((dev)->status &= ~S_STREAMING)
+
+struct regval {
+       unsigned reg;
+       unsigned val;
+};
+
+struct stk_camera {
+       struct video_device vdev;
+       struct usb_device *udev;
+       struct usb_interface *interface;
+       int webcam_model;
+       struct file *owner;
+
+       u8 isoc_ep;
+
+       /* Not sure if this is right */
+       atomic_t urbs_used;
+
+       struct stk_video vsettings;
+
+       enum stk_status status;
+
+       spinlock_t spinlock;
+       wait_queue_head_t wait_frame;
+
+       struct stk_iso_buf *isobufs;
+
+       int frame_size;
+       /* Streaming buffers */
+       unsigned int n_sbufs;
+       struct stk_sio_buffer *sio_bufs;
+       struct list_head sio_avail;
+       struct list_head sio_full;
+       unsigned sequence;
+};
+
+#define vdev_to_camera(d) container_of(d, struct stk_camera, vdev)
+
+int stk_camera_write_reg(struct stk_camera *, u16, u8);
+int stk_camera_read_reg(struct stk_camera *, u16, int *);
+
+int stk_sensor_init(struct stk_camera *);
+int stk_sensor_configure(struct stk_camera *);
+int stk_sensor_sleep(struct stk_camera *dev);
+int stk_sensor_wakeup(struct stk_camera *dev);
+int stk_sensor_set_brightness(struct stk_camera *dev, int br);
+
+#endif
diff --git a/drivers/media/usb/zr364xx/Kconfig b/drivers/media/usb/zr364xx/Kconfig
new file mode 100644 (file)
index 0000000..0f58566
--- /dev/null
@@ -0,0 +1,14 @@
+config USB_ZR364XX
+       tristate "USB ZR364XX Camera support"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_GEN
+       select VIDEOBUF_VMALLOC
+       ---help---
+         Say Y here if you want to connect this type of camera to your
+         computer's USB port.
+         See <file:Documentation/video4linux/zr364xx.txt> for more info
+         and list of supported cameras.
+
+         To compile this driver as a module, choose M here: the
+         module will be called zr364xx.
+
diff --git a/drivers/media/usb/zr364xx/Makefile b/drivers/media/usb/zr364xx/Makefile
new file mode 100644 (file)
index 0000000..a577788
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
+
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
new file mode 100644 (file)
index 0000000..9afab35
--- /dev/null
@@ -0,0 +1,1643 @@
+/*
+ * Zoran 364xx based USB webcam module version 0.73
+ *
+ * Allows you to use your USB webcam with V4L2 applications
+ * This is still in heavy developpement !
+ *
+ * Copyright (C) 2004  Antoine Jacquet <royale@zerezo.com>
+ * http://royale.zerezo.com/zr364xx/
+ *
+ * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers
+ * V4L2 version inspired by meye.c driver
+ *
+ * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/highmem.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf-vmalloc.h>
+
+
+/* Version Information */
+#define DRIVER_VERSION "0.7.4"
+#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
+#define DRIVER_DESC "Zoran 364xx"
+
+
+/* Camera */
+#define FRAMES 1
+#define MAX_FRAME_SIZE 200000
+#define BUFFER_SIZE 0x1000
+#define CTRL_TIMEOUT 500
+
+#define ZR364XX_DEF_BUFS       4
+#define ZR364XX_READ_IDLE      0
+#define ZR364XX_READ_FRAME     1
+
+/* Debug macro */
+#define DBG(fmt, args...) \
+       do { \
+               if (debug) { \
+                       printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
+               } \
+       } while (0)
+
+/*#define FULL_DEBUG 1*/
+#ifdef FULL_DEBUG
+#define _DBG DBG
+#else
+#define _DBG(fmt, args...)
+#endif
+
+/* Init methods, need to find nicer names for these
+ * the exact names of the chipsets would be the best if someone finds it */
+#define METHOD0 0
+#define METHOD1 1
+#define METHOD2 2
+#define METHOD3 3
+
+
+/* Module parameters */
+static int debug;
+static int mode;
+
+
+/* Module parameters interface */
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level");
+module_param(mode, int, 0644);
+MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
+
+
+/* Devices supported by this driver
+ * .driver_info contains the init method used by the camera */
+static struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
+       {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
+       {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
+       {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
+       {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
+       {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
+       {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
+       {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
+       {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
+       {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
+       {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
+       {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 },
+       {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
+       {}                      /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* frame structure */
+struct zr364xx_framei {
+       unsigned long ulState;  /* ulState:ZR364XX_READ_IDLE,
+                                          ZR364XX_READ_FRAME */
+       void *lpvbits;          /* image data */
+       unsigned long cur_size; /* current data copied to it */
+};
+
+/* image buffer structure */
+struct zr364xx_bufferi {
+       unsigned long dwFrames;                 /* number of frames in buffer */
+       struct zr364xx_framei frame[FRAMES];    /* array of FRAME structures */
+};
+
+struct zr364xx_dmaqueue {
+       struct list_head        active;
+       struct zr364xx_camera   *cam;
+};
+
+struct zr364xx_pipeinfo {
+       u32 transfer_size;
+       u8 *transfer_buffer;
+       u32 state;
+       void *stream_urb;
+       void *cam;      /* back pointer to zr364xx_camera struct */
+       u32 err_count;
+       u32 idx;
+};
+
+struct zr364xx_fmt {
+       char *name;
+       u32 fourcc;
+       int depth;
+};
+
+/* image formats.  */
+static const struct zr364xx_fmt formats[] = {
+       {
+               .name = "JPG",
+               .fourcc = V4L2_PIX_FMT_JPEG,
+               .depth = 24
+       }
+};
+
+/* Camera stuff */
+struct zr364xx_camera {
+       struct usb_device *udev;        /* save off the usb device pointer */
+       struct usb_interface *interface;/* the interface for this device */
+       struct v4l2_device v4l2_dev;
+       struct v4l2_ctrl_handler ctrl_handler;
+       struct video_device vdev;       /* v4l video device */
+       struct v4l2_fh *owner;          /* owns the streaming */
+       int nb;
+       struct zr364xx_bufferi          buffer;
+       int skip;
+       int width;
+       int height;
+       int method;
+       struct mutex lock;
+
+       spinlock_t              slock;
+       struct zr364xx_dmaqueue vidq;
+       int                     last_frame;
+       int                     cur_frame;
+       unsigned long           frame_count;
+       int                     b_acquire;
+       struct zr364xx_pipeinfo pipe[1];
+
+       u8                      read_endpoint;
+
+       const struct zr364xx_fmt *fmt;
+       struct videobuf_queue   vb_vidq;
+       bool was_streaming;
+};
+
+/* buffer for one video frame */
+struct zr364xx_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+       const struct zr364xx_fmt *fmt;
+};
+
+/* function used to send initialisation commands to the camera */
+static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
+                           u16 index, unsigned char *cp, u16 size)
+{
+       int status;
+
+       unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
+       if (!transfer_buffer) {
+               dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
+               return -ENOMEM;
+       }
+
+       memcpy(transfer_buffer, cp, size);
+
+       status = usb_control_msg(udev,
+                                usb_sndctrlpipe(udev, 0),
+                                request,
+                                USB_DIR_OUT | USB_TYPE_VENDOR |
+                                USB_RECIP_DEVICE, value, index,
+                                transfer_buffer, size, CTRL_TIMEOUT);
+
+       kfree(transfer_buffer);
+       return status;
+}
+
+
+/* Control messages sent to the camera to initialize it
+ * and launch the capture */
+typedef struct {
+       unsigned int value;
+       unsigned int size;
+       unsigned char *bytes;
+} message;
+
+/* method 0 */
+static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
+static unsigned char m0d3[] = { 0, 0 };
+static message m0[] = {
+       {0x1f30, 0, NULL},
+       {0xd000, 0, NULL},
+       {0x3370, sizeof(m0d1), m0d1},
+       {0x2000, 0, NULL},
+       {0x2f0f, 0, NULL},
+       {0x2610, sizeof(m0d2), m0d2},
+       {0xe107, 0, NULL},
+       {0x2502, 0, NULL},
+       {0x1f70, 0, NULL},
+       {0xd000, 0, NULL},
+       {0x9a01, sizeof(m0d3), m0d3},
+       {-1, -1, NULL}
+};
+
+/* method 1 */
+static unsigned char m1d1[] = { 0xff, 0xff };
+static unsigned char m1d2[] = { 0x00, 0x00 };
+static message m1[] = {
+       {0x1f30, 0, NULL},
+       {0xd000, 0, NULL},
+       {0xf000, 0, NULL},
+       {0x2000, 0, NULL},
+       {0x2f0f, 0, NULL},
+       {0x2650, 0, NULL},
+       {0xe107, 0, NULL},
+       {0x2502, sizeof(m1d1), m1d1},
+       {0x1f70, 0, NULL},
+       {0xd000, 0, NULL},
+       {0xd000, 0, NULL},
+       {0xd000, 0, NULL},
+       {0x9a01, sizeof(m1d2), m1d2},
+       {-1, -1, NULL}
+};
+
+/* method 2 */
+static unsigned char m2d1[] = { 0xff, 0xff };
+static message m2[] = {
+       {0x1f30, 0, NULL},
+       {0xf000, 0, NULL},
+       {0x2000, 0, NULL},
+       {0x2f0f, 0, NULL},
+       {0x2650, 0, NULL},
+       {0xe107, 0, NULL},
+       {0x2502, sizeof(m2d1), m2d1},
+       {0x1f70, 0, NULL},
+       {-1, -1, NULL}
+};
+
+/* init table */
+static message *init[4] = { m0, m1, m2, m2 };
+
+
+/* JPEG static data in header (Huffman table, etc) */
+static unsigned char header1[] = {
+       0xFF, 0xD8,
+       /*
+       0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
+       0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
+       */
+       0xFF, 0xDB, 0x00, 0x84
+};
+static unsigned char header2[] = {
+       0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
+       0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
+       0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
+       0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
+       0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
+       0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+       0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
+       0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
+       0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+       0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
+       0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+       0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
+       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
+       0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
+       0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
+       0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
+       0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
+       0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
+       0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
+       0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
+       0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
+       0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
+       0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
+       0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
+       0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
+       0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
+       0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
+       0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
+       0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
+       0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
+       0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+       0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
+       0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
+       0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
+       0x00, 0x3F, 0x00
+};
+static unsigned char header3;
+
+/* ------------------------------------------------------------------
+   Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+                       unsigned int *size)
+{
+       struct zr364xx_camera *cam = vq->priv_data;
+
+       *size = cam->width * cam->height * (cam->fmt->depth >> 3);
+
+       if (*count == 0)
+               *count = ZR364XX_DEF_BUFS;
+
+       if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024)
+               *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size;
+
+       return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
+{
+       _DBG("%s\n", __func__);
+
+       if (in_interrupt())
+               BUG();
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                         enum v4l2_field field)
+{
+       struct zr364xx_camera *cam = vq->priv_data;
+       struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
+                                                 vb);
+       int rc;
+
+       DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
+           cam->fmt->name : "");
+       if (cam->fmt == NULL)
+               return -EINVAL;
+
+       buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
+
+       if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
+               DBG("invalid buffer prepare\n");
+               return -EINVAL;
+       }
+
+       buf->fmt = cam->fmt;
+       buf->vb.width = cam->width;
+       buf->vb.height = cam->height;
+       buf->vb.field = field;
+
+       if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
+                                                 vb);
+       struct zr364xx_camera *cam = vq->priv_data;
+
+       _DBG("%s\n", __func__);
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &cam->vidq.active);
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+                          struct videobuf_buffer *vb)
+{
+       struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
+                                                 vb);
+
+       _DBG("%s\n", __func__);
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops zr364xx_video_qops = {
+       .buf_setup = buffer_setup,
+       .buf_prepare = buffer_prepare,
+       .buf_queue = buffer_queue,
+       .buf_release = buffer_release,
+};
+
+/********************/
+/* V4L2 integration */
+/********************/
+static int zr364xx_vidioc_streamon(struct file *file, void *priv,
+                                  enum v4l2_buf_type type);
+
+static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
+                           loff_t * ppos)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+       int err = 0;
+
+       _DBG("%s\n", __func__);
+
+       if (!buf)
+               return -EINVAL;
+
+       if (!count)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&cam->lock))
+               return -ERESTARTSYS;
+
+       err = zr364xx_vidioc_streamon(file, file->private_data,
+                               V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       if (err == 0) {
+               DBG("%s: reading %d bytes at pos %d.\n", __func__,
+                               (int) count, (int) *ppos);
+
+               /* NoMan Sux ! */
+               err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
+                                       file->f_flags & O_NONBLOCK);
+       }
+       mutex_unlock(&cam->lock);
+       return err;
+}
+
+/* video buffer vmalloc implementation based partly on VIVI driver which is
+ *          Copyright (c) 2006 by
+ *                  Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
+ *                  Ted Walther <ted--a.t--enumera.com>
+ *                  John Sokol <sokol--a.t--videotechnology.com>
+ *                  http://v4l.videotechnology.com/
+ *
+ */
+static void zr364xx_fillbuff(struct zr364xx_camera *cam,
+                            struct zr364xx_buffer *buf,
+                            int jpgsize)
+{
+       int pos = 0;
+       struct timeval ts;
+       const char *tmpbuf;
+       char *vbuf = videobuf_to_vmalloc(&buf->vb);
+       unsigned long last_frame;
+
+       if (!vbuf)
+               return;
+
+       last_frame = cam->last_frame;
+       if (last_frame != -1) {
+               tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
+               switch (buf->fmt->fourcc) {
+               case V4L2_PIX_FMT_JPEG:
+                       buf->vb.size = jpgsize;
+                       memcpy(vbuf, tmpbuf, buf->vb.size);
+                       break;
+               default:
+                       printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
+               }
+               cam->last_frame = -1;
+       } else {
+               printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
+               return;
+       }
+       DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
+               (unsigned long)vbuf, pos);
+       /* tell v4l buffer was filled */
+
+       buf->vb.field_count = cam->frame_count * 2;
+       do_gettimeofday(&ts);
+       buf->vb.ts = ts;
+       buf->vb.state = VIDEOBUF_DONE;
+}
+
+static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
+{
+       struct zr364xx_dmaqueue *dma_q = &cam->vidq;
+       struct zr364xx_buffer *buf;
+       unsigned long flags = 0;
+       int rc = 0;
+
+       DBG("wakeup: %p\n", &dma_q);
+       spin_lock_irqsave(&cam->slock, flags);
+
+       if (list_empty(&dma_q->active)) {
+               DBG("No active queue to serve\n");
+               rc = -1;
+               goto unlock;
+       }
+       buf = list_entry(dma_q->active.next,
+                        struct zr364xx_buffer, vb.queue);
+
+       if (!waitqueue_active(&buf->vb.done)) {
+               /* no one active */
+               rc = -1;
+               goto unlock;
+       }
+       list_del(&buf->vb.queue);
+       do_gettimeofday(&buf->vb.ts);
+       DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
+       zr364xx_fillbuff(cam, buf, jpgsize);
+       wake_up(&buf->vb.done);
+       DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
+unlock:
+       spin_unlock_irqrestore(&cam->slock, flags);
+       return rc;
+}
+
+/* this function moves the usb stream read pipe data
+ * into the system buffers.
+ * returns 0 on success, EAGAIN if more data to process (call this
+ * function again).
+ */
+static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
+                                       struct zr364xx_pipeinfo *pipe_info,
+                                       struct urb *purb)
+{
+       unsigned char *pdest;
+       unsigned char *psrc;
+       s32 idx = -1;
+       struct zr364xx_framei *frm;
+       int i = 0;
+       unsigned char *ptr = NULL;
+
+       _DBG("buffer to user\n");
+       idx = cam->cur_frame;
+       frm = &cam->buffer.frame[idx];
+
+       /* swap bytes if camera needs it */
+       if (cam->method == METHOD0) {
+               u16 *buf = (u16 *)pipe_info->transfer_buffer;
+               for (i = 0; i < purb->actual_length/2; i++)
+                       swab16s(buf + i);
+       }
+
+       /* search done.  now find out if should be acquiring */
+       if (!cam->b_acquire) {
+               /* we found a frame, but this channel is turned off */
+               frm->ulState = ZR364XX_READ_IDLE;
+               return -EINVAL;
+       }
+
+       psrc = (u8 *)pipe_info->transfer_buffer;
+       ptr = pdest = frm->lpvbits;
+
+       if (frm->ulState == ZR364XX_READ_IDLE) {
+               frm->ulState = ZR364XX_READ_FRAME;
+               frm->cur_size = 0;
+
+               _DBG("jpeg header, ");
+               memcpy(ptr, header1, sizeof(header1));
+               ptr += sizeof(header1);
+               header3 = 0;
+               memcpy(ptr, &header3, 1);
+               ptr++;
+               memcpy(ptr, psrc, 64);
+               ptr += 64;
+               header3 = 1;
+               memcpy(ptr, &header3, 1);
+               ptr++;
+               memcpy(ptr, psrc + 64, 64);
+               ptr += 64;
+               memcpy(ptr, header2, sizeof(header2));
+               ptr += sizeof(header2);
+               memcpy(ptr, psrc + 128,
+                      purb->actual_length - 128);
+               ptr += purb->actual_length - 128;
+               _DBG("header : %d %d %d %d %d %d %d %d %d\n",
+                   psrc[0], psrc[1], psrc[2],
+                   psrc[3], psrc[4], psrc[5],
+                   psrc[6], psrc[7], psrc[8]);
+               frm->cur_size = ptr - pdest;
+       } else {
+               if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
+                       dev_info(&cam->udev->dev,
+                                "%s: buffer (%d bytes) too small to hold "
+                                "frame data. Discarding frame data.\n",
+                                __func__, MAX_FRAME_SIZE);
+               } else {
+                       pdest += frm->cur_size;
+                       memcpy(pdest, psrc, purb->actual_length);
+                       frm->cur_size += purb->actual_length;
+               }
+       }
+       /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
+               purb->actual_length);*/
+
+       if (purb->actual_length < pipe_info->transfer_size) {
+               _DBG("****************Buffer[%d]full*************\n", idx);
+               cam->last_frame = cam->cur_frame;
+               cam->cur_frame++;
+               /* end of system frame ring buffer, start at zero */
+               if (cam->cur_frame == cam->buffer.dwFrames)
+                       cam->cur_frame = 0;
+
+               /* frame ready */
+               /* go back to find the JPEG EOI marker */
+               ptr = pdest = frm->lpvbits;
+               ptr += frm->cur_size - 2;
+               while (ptr > pdest) {
+                       if (*ptr == 0xFF && *(ptr + 1) == 0xD9
+                           && *(ptr + 2) == 0xFF)
+                               break;
+                       ptr--;
+               }
+               if (ptr == pdest)
+                       DBG("No EOI marker\n");
+
+               /* Sometimes there is junk data in the middle of the picture,
+                * we want to skip this bogus frames */
+               while (ptr > pdest) {
+                       if (*ptr == 0xFF && *(ptr + 1) == 0xFF
+                           && *(ptr + 2) == 0xFF)
+                               break;
+                       ptr--;
+               }
+               if (ptr != pdest) {
+                       DBG("Bogus frame ? %d\n", ++(cam->nb));
+               } else if (cam->b_acquire) {
+                       /* we skip the 2 first frames which are usually buggy */
+                       if (cam->skip)
+                               cam->skip--;
+                       else {
+                               _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
+                                   frm->cur_size,
+                                   pdest[0], pdest[1], pdest[2], pdest[3],
+                                   pdest[4], pdest[5], pdest[6], pdest[7]);
+
+                               zr364xx_got_frame(cam, frm->cur_size);
+                       }
+               }
+               cam->frame_count++;
+               frm->ulState = ZR364XX_READ_IDLE;
+               frm->cur_size = 0;
+       }
+       /* done successfully */
+       return 0;
+}
+
+static int zr364xx_vidioc_querycap(struct file *file, void *priv,
+                                  struct v4l2_capability *cap)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+
+       strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
+       strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
+       strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
+               sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+                           V4L2_CAP_READWRITE |
+                           V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
+                                    struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+       strcpy(i->name, DRIVER_DESC " Camera");
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       return 0;
+}
+
+static int zr364xx_vidioc_g_input(struct file *file, void *priv,
+                                 unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int zr364xx_vidioc_s_input(struct file *file, void *priv,
+                                 unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct zr364xx_camera *cam =
+               container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
+       int temp;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               /* hardware brightness */
+               send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
+               temp = (0x60 << 8) + 127 - ctrl->val;
+               send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
+                                      void *priv, struct v4l2_fmtdesc *f)
+{
+       if (f->index > 0)
+               return -EINVAL;
+       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+       strcpy(f->description, formats[0].name);
+       f->pixelformat = formats[0].fourcc;
+       return 0;
+}
+
+static char *decode_fourcc(__u32 pixelformat, char *buf)
+{
+       buf[0] = pixelformat & 0xff;
+       buf[1] = (pixelformat >> 8) & 0xff;
+       buf[2] = (pixelformat >> 16) & 0xff;
+       buf[3] = (pixelformat >> 24) & 0xff;
+       buf[4] = '\0';
+       return buf;
+}
+
+static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                     struct v4l2_format *f)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+       char pixelformat_name[5];
+
+       if (cam == NULL)
+               return -ENODEV;
+
+       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
+               DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
+                   decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
+               return -EINVAL;
+       }
+
+       if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
+           !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
+               f->fmt.pix.width = 320;
+               f->fmt.pix.height = 240;
+       }
+
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+       f->fmt.pix.priv = 0;
+       DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
+           decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
+           f->fmt.pix.field);
+       return 0;
+}
+
+static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                   struct v4l2_format *f)
+{
+       struct zr364xx_camera *cam;
+
+       if (file == NULL)
+               return -ENODEV;
+       cam = video_drvdata(file);
+
+       f->fmt.pix.pixelformat = formats[0].fourcc;
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.width = cam->width;
+       f->fmt.pix.height = cam->height;
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+       f->fmt.pix.priv = 0;
+       return 0;
+}
+
+static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                                   struct v4l2_format *f)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+       struct videobuf_queue *q = &cam->vb_vidq;
+       char pixelformat_name[5];
+       int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
+       int i;
+
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&q->vb_lock);
+
+       if (videobuf_queue_is_busy(&cam->vb_vidq)) {
+               DBG("%s queue busy\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (cam->owner) {
+               DBG("%s can't change format after started\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+
+       cam->width = f->fmt.pix.width;
+       cam->height = f->fmt.pix.height;
+       DBG("%s: %dx%d mode selected\n", __func__,
+                cam->width, cam->height);
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+       f->fmt.pix.priv = 0;
+       cam->vb_vidq.field = f->fmt.pix.field;
+
+       if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
+               mode = 1;
+       else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
+               mode = 2;
+       else
+               mode = 0;
+
+       m0d1[0] = mode;
+       m1[2].value = 0xf000 + mode;
+       m2[1].value = 0xf000 + mode;
+
+       /* special case for METHOD3, the modes are different */
+       if (cam->method == METHOD3) {
+               switch (mode) {
+               case 1:
+                       m2[1].value = 0xf000 + 4;
+                       break;
+               case 2:
+                       m2[1].value = 0xf000 + 0;
+                       break;
+               default:
+                       m2[1].value = 0xf000 + 1;
+                       break;
+               }
+       }
+
+       header2[437] = cam->height / 256;
+       header2[438] = cam->height % 256;
+       header2[439] = cam->width / 256;
+       header2[440] = cam->width % 256;
+
+       for (i = 0; init[cam->method][i].size != -1; i++) {
+               ret =
+                   send_control_msg(cam->udev, 1, init[cam->method][i].value,
+                                    0, init[cam->method][i].bytes,
+                                    init[cam->method][i].size);
+               if (ret < 0) {
+                       dev_err(&cam->udev->dev,
+                          "error during resolution change sequence: %d\n", i);
+                       goto out;
+               }
+       }
+
+       /* Added some delay here, since opening/closing the camera quickly,
+        * like Ekiga does during its startup, can crash the webcam
+        */
+       mdelay(100);
+       cam->skip = 2;
+       ret = 0;
+
+out:
+       mutex_unlock(&q->vb_lock);
+
+       DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
+           decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
+           f->fmt.pix.field);
+       return ret;
+}
+
+static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *p)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+
+       if (cam->owner && cam->owner != priv)
+               return -EBUSY;
+       return videobuf_reqbufs(&cam->vb_vidq, p);
+}
+
+static int zr364xx_vidioc_querybuf(struct file *file,
+                               void *priv,
+                               struct v4l2_buffer *p)
+{
+       int rc;
+       struct zr364xx_camera *cam = video_drvdata(file);
+       rc = videobuf_querybuf(&cam->vb_vidq, p);
+       return rc;
+}
+
+static int zr364xx_vidioc_qbuf(struct file *file,
+                               void *priv,
+                               struct v4l2_buffer *p)
+{
+       int rc;
+       struct zr364xx_camera *cam = video_drvdata(file);
+       _DBG("%s\n", __func__);
+       if (cam->owner && cam->owner != priv)
+               return -EBUSY;
+       rc = videobuf_qbuf(&cam->vb_vidq, p);
+       return rc;
+}
+
+static int zr364xx_vidioc_dqbuf(struct file *file,
+                               void *priv,
+                               struct v4l2_buffer *p)
+{
+       int rc;
+       struct zr364xx_camera *cam = video_drvdata(file);
+       _DBG("%s\n", __func__);
+       if (cam->owner && cam->owner != priv)
+               return -EBUSY;
+       rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
+       return rc;
+}
+
+static void read_pipe_completion(struct urb *purb)
+{
+       struct zr364xx_pipeinfo *pipe_info;
+       struct zr364xx_camera *cam;
+       int pipe;
+
+       pipe_info = purb->context;
+       _DBG("%s %p, status %d\n", __func__, purb, purb->status);
+       if (pipe_info == NULL) {
+               printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
+               return;
+       }
+
+       cam = pipe_info->cam;
+       if (cam == NULL) {
+               printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
+               return;
+       }
+
+       /* if shutting down, do not resubmit, exit immediately */
+       if (purb->status == -ESHUTDOWN) {
+               DBG("%s, err shutdown\n", __func__);
+               pipe_info->err_count++;
+               return;
+       }
+
+       if (pipe_info->state == 0) {
+               DBG("exiting USB pipe\n");
+               return;
+       }
+
+       if (purb->actual_length < 0 ||
+           purb->actual_length > pipe_info->transfer_size) {
+               dev_err(&cam->udev->dev, "wrong number of bytes\n");
+               return;
+       }
+
+       if (purb->status == 0)
+               zr364xx_read_video_callback(cam, pipe_info, purb);
+       else {
+               pipe_info->err_count++;
+               DBG("%s: failed URB %d\n", __func__, purb->status);
+       }
+
+       pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
+
+       /* reuse urb */
+       usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
+                         pipe,
+                         pipe_info->transfer_buffer,
+                         pipe_info->transfer_size,
+                         read_pipe_completion, pipe_info);
+
+       if (pipe_info->state != 0) {
+               purb->status = usb_submit_urb(pipe_info->stream_urb,
+                                             GFP_ATOMIC);
+
+               if (purb->status)
+                       dev_err(&cam->udev->dev,
+                               "error submitting urb (error=%i)\n",
+                               purb->status);
+       } else
+               DBG("read pipe complete state 0\n");
+}
+
+static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
+{
+       int pipe;
+       int retval;
+       struct zr364xx_pipeinfo *pipe_info = cam->pipe;
+       pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
+       DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
+
+       pipe_info->state = 1;
+       pipe_info->err_count = 0;
+       pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!pipe_info->stream_urb) {
+               dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
+               return -ENOMEM;
+       }
+       /* transfer buffer allocated in board_init */
+       usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
+                         pipe,
+                         pipe_info->transfer_buffer,
+                         pipe_info->transfer_size,
+                         read_pipe_completion, pipe_info);
+
+       DBG("submitting URB %p\n", pipe_info->stream_urb);
+       retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
+       if (retval) {
+               printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
+               return retval;
+       }
+
+       return 0;
+}
+
+static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
+{
+       struct zr364xx_pipeinfo *pipe_info;
+
+       if (cam == NULL) {
+               printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
+               return;
+       }
+       DBG("stop read pipe\n");
+       pipe_info = cam->pipe;
+       if (pipe_info) {
+               if (pipe_info->state != 0)
+                       pipe_info->state = 0;
+
+               if (pipe_info->stream_urb) {
+                       /* cancel urb */
+                       usb_kill_urb(pipe_info->stream_urb);
+                       usb_free_urb(pipe_info->stream_urb);
+                       pipe_info->stream_urb = NULL;
+               }
+       }
+       return;
+}
+
+/* starts acquisition process */
+static int zr364xx_start_acquire(struct zr364xx_camera *cam)
+{
+       int j;
+
+       DBG("start acquire\n");
+
+       cam->last_frame = -1;
+       cam->cur_frame = 0;
+       for (j = 0; j < FRAMES; j++) {
+               cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
+               cam->buffer.frame[j].cur_size = 0;
+       }
+       cam->b_acquire = 1;
+       return 0;
+}
+
+static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
+{
+       cam->b_acquire = 0;
+       return 0;
+}
+
+static int zr364xx_prepare(struct zr364xx_camera *cam)
+{
+       int res;
+       int i, j;
+
+       for (i = 0; init[cam->method][i].size != -1; i++) {
+               res = send_control_msg(cam->udev, 1, init[cam->method][i].value,
+                                    0, init[cam->method][i].bytes,
+                                    init[cam->method][i].size);
+               if (res < 0) {
+                       dev_err(&cam->udev->dev,
+                               "error during open sequence: %d\n", i);
+                       return res;
+               }
+       }
+
+       cam->skip = 2;
+       cam->last_frame = -1;
+       cam->cur_frame = 0;
+       cam->frame_count = 0;
+       for (j = 0; j < FRAMES; j++) {
+               cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
+               cam->buffer.frame[j].cur_size = 0;
+       }
+       v4l2_ctrl_handler_setup(&cam->ctrl_handler);
+       return 0;
+}
+
+static int zr364xx_vidioc_streamon(struct file *file, void *priv,
+                                  enum v4l2_buf_type type)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+       int res;
+
+       DBG("%s\n", __func__);
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (cam->owner && cam->owner != priv)
+               return -EBUSY;
+
+       res = zr364xx_prepare(cam);
+       if (res)
+               return res;
+       res = videobuf_streamon(&cam->vb_vidq);
+       if (res == 0) {
+               zr364xx_start_acquire(cam);
+               cam->owner = file->private_data;
+       }
+       return res;
+}
+
+static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
+                                   enum v4l2_buf_type type)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+
+       DBG("%s\n", __func__);
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (cam->owner && cam->owner != priv)
+               return -EBUSY;
+       zr364xx_stop_acquire(cam);
+       return videobuf_streamoff(&cam->vb_vidq);
+}
+
+
+/* open the camera */
+static int zr364xx_open(struct file *file)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+       int err;
+
+       DBG("%s\n", __func__);
+
+       if (mutex_lock_interruptible(&cam->lock))
+               return -ERESTARTSYS;
+
+       err = v4l2_fh_open(file);
+       if (err)
+               goto out;
+
+       /* Added some delay here, since opening/closing the camera quickly,
+        * like Ekiga does during its startup, can crash the webcam
+        */
+       mdelay(100);
+       err = 0;
+
+out:
+       mutex_unlock(&cam->lock);
+       DBG("%s: %d\n", __func__, err);
+       return err;
+}
+
+static void zr364xx_release(struct v4l2_device *v4l2_dev)
+{
+       struct zr364xx_camera *cam =
+               container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
+       unsigned long i;
+
+       v4l2_device_unregister(&cam->v4l2_dev);
+
+       videobuf_mmap_free(&cam->vb_vidq);
+
+       /* release sys buffers */
+       for (i = 0; i < FRAMES; i++) {
+               if (cam->buffer.frame[i].lpvbits) {
+                       DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
+                       vfree(cam->buffer.frame[i].lpvbits);
+               }
+               cam->buffer.frame[i].lpvbits = NULL;
+       }
+
+       v4l2_ctrl_handler_free(&cam->ctrl_handler);
+       /* release transfer buffer */
+       kfree(cam->pipe->transfer_buffer);
+       kfree(cam);
+}
+
+/* release the camera */
+static int zr364xx_close(struct file *file)
+{
+       struct zr364xx_camera *cam;
+       struct usb_device *udev;
+       int i;
+
+       DBG("%s\n", __func__);
+       cam = video_drvdata(file);
+
+       mutex_lock(&cam->lock);
+       udev = cam->udev;
+
+       if (file->private_data == cam->owner) {
+               /* turn off stream */
+               if (cam->b_acquire)
+                       zr364xx_stop_acquire(cam);
+               videobuf_streamoff(&cam->vb_vidq);
+
+               for (i = 0; i < 2; i++) {
+                       send_control_msg(udev, 1, init[cam->method][i].value,
+                                       0, init[cam->method][i].bytes,
+                                       init[cam->method][i].size);
+               }
+               cam->owner = NULL;
+       }
+
+       /* Added some delay here, since opening/closing the camera quickly,
+        * like Ekiga does during its startup, can crash the webcam
+        */
+       mdelay(100);
+       mutex_unlock(&cam->lock);
+       return v4l2_fh_release(file);
+}
+
+
+static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+       int ret;
+
+       if (cam == NULL) {
+               DBG("%s: cam == NULL\n", __func__);
+               return -ENODEV;
+       }
+       DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
+
+       ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
+
+       DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
+       return ret;
+}
+
+static unsigned int zr364xx_poll(struct file *file,
+                              struct poll_table_struct *wait)
+{
+       struct zr364xx_camera *cam = video_drvdata(file);
+       struct videobuf_queue *q = &cam->vb_vidq;
+       unsigned res = v4l2_ctrl_poll(file, wait);
+
+       _DBG("%s\n", __func__);
+
+       return res | videobuf_poll_stream(file, q, wait);
+}
+
+static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
+       .s_ctrl = zr364xx_s_ctrl,
+};
+
+static const struct v4l2_file_operations zr364xx_fops = {
+       .owner = THIS_MODULE,
+       .open = zr364xx_open,
+       .release = zr364xx_close,
+       .read = zr364xx_read,
+       .mmap = zr364xx_mmap,
+       .unlocked_ioctl = video_ioctl2,
+       .poll = zr364xx_poll,
+};
+
+static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
+       .vidioc_querycap        = zr364xx_vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = zr364xx_vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = zr364xx_vidioc_g_fmt_vid_cap,
+       .vidioc_enum_input      = zr364xx_vidioc_enum_input,
+       .vidioc_g_input         = zr364xx_vidioc_g_input,
+       .vidioc_s_input         = zr364xx_vidioc_s_input,
+       .vidioc_streamon        = zr364xx_vidioc_streamon,
+       .vidioc_streamoff       = zr364xx_vidioc_streamoff,
+       .vidioc_reqbufs         = zr364xx_vidioc_reqbufs,
+       .vidioc_querybuf        = zr364xx_vidioc_querybuf,
+       .vidioc_qbuf            = zr364xx_vidioc_qbuf,
+       .vidioc_dqbuf           = zr364xx_vidioc_dqbuf,
+       .vidioc_log_status      = v4l2_ctrl_log_status,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static struct video_device zr364xx_template = {
+       .name = DRIVER_DESC,
+       .fops = &zr364xx_fops,
+       .ioctl_ops = &zr364xx_ioctl_ops,
+       .release = video_device_release_empty,
+};
+
+
+
+/*******************/
+/* USB integration */
+/*******************/
+static int zr364xx_board_init(struct zr364xx_camera *cam)
+{
+       struct zr364xx_pipeinfo *pipe = cam->pipe;
+       unsigned long i;
+
+       DBG("board init: %p\n", cam);
+       memset(pipe, 0, sizeof(*pipe));
+       pipe->cam = cam;
+       pipe->transfer_size = BUFFER_SIZE;
+
+       pipe->transfer_buffer = kzalloc(pipe->transfer_size,
+                                       GFP_KERNEL);
+       if (pipe->transfer_buffer == NULL) {
+               DBG("out of memory!\n");
+               return -ENOMEM;
+       }
+
+       cam->b_acquire = 0;
+       cam->frame_count = 0;
+
+       /*** start create system buffers ***/
+       for (i = 0; i < FRAMES; i++) {
+               /* always allocate maximum size for system buffers */
+               cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
+
+               DBG("valloc %p, idx %lu, pdata %p\n",
+                       &cam->buffer.frame[i], i,
+                       cam->buffer.frame[i].lpvbits);
+               if (cam->buffer.frame[i].lpvbits == NULL) {
+                       printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
+                              "Using less frames\n");
+                       break;
+               }
+       }
+
+       if (i == 0) {
+               printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
+               kfree(cam->pipe->transfer_buffer);
+               cam->pipe->transfer_buffer = NULL;
+               return -ENOMEM;
+       } else
+               cam->buffer.dwFrames = i;
+
+       /* make sure internal states are set */
+       for (i = 0; i < FRAMES; i++) {
+               cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
+               cam->buffer.frame[i].cur_size = 0;
+       }
+
+       cam->cur_frame = 0;
+       cam->last_frame = -1;
+       /*** end create system buffers ***/
+
+       /* start read pipe */
+       zr364xx_start_readpipe(cam);
+       DBG(": board initialized\n");
+       return 0;
+}
+
+static int zr364xx_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct zr364xx_camera *cam = NULL;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       struct v4l2_ctrl_handler *hdl;
+       int err;
+       int i;
+
+       DBG("probing...\n");
+
+       dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
+       dev_info(&intf->dev, "model %04x:%04x detected\n",
+                le16_to_cpu(udev->descriptor.idVendor),
+                le16_to_cpu(udev->descriptor.idProduct));
+
+       cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
+       if (cam == NULL) {
+               dev_err(&udev->dev, "cam: out of memory !\n");
+               return -ENOMEM;
+       }
+
+       cam->v4l2_dev.release = zr364xx_release;
+       err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
+       if (err < 0) {
+               dev_err(&udev->dev, "couldn't register v4l2_device\n");
+               kfree(cam);
+               return err;
+       }
+       hdl = &cam->ctrl_handler;
+       v4l2_ctrl_handler_init(hdl, 1);
+       v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
+                         V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
+       if (hdl->error) {
+               err = hdl->error;
+               dev_err(&udev->dev, "couldn't register control\n");
+               goto fail;
+       }
+       /* save the init method used by this camera */
+       cam->method = id->driver_info;
+       mutex_init(&cam->lock);
+       cam->vdev = zr364xx_template;
+       cam->vdev.lock = &cam->lock;
+       cam->vdev.v4l2_dev = &cam->v4l2_dev;
+       cam->vdev.ctrl_handler = &cam->ctrl_handler;
+       set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
+       video_set_drvdata(&cam->vdev, cam);
+       if (debug)
+               cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
+
+       cam->udev = udev;
+
+       switch (mode) {
+       case 1:
+               dev_info(&udev->dev, "160x120 mode selected\n");
+               cam->width = 160;
+               cam->height = 120;
+               break;
+       case 2:
+               dev_info(&udev->dev, "640x480 mode selected\n");
+               cam->width = 640;
+               cam->height = 480;
+               break;
+       default:
+               dev_info(&udev->dev, "320x240 mode selected\n");
+               cam->width = 320;
+               cam->height = 240;
+               break;
+       }
+
+       m0d1[0] = mode;
+       m1[2].value = 0xf000 + mode;
+       m2[1].value = 0xf000 + mode;
+
+       /* special case for METHOD3, the modes are different */
+       if (cam->method == METHOD3) {
+               switch (mode) {
+               case 1:
+                       m2[1].value = 0xf000 + 4;
+                       break;
+               case 2:
+                       m2[1].value = 0xf000 + 0;
+                       break;
+               default:
+                       m2[1].value = 0xf000 + 1;
+                       break;
+               }
+       }
+
+       header2[437] = cam->height / 256;
+       header2[438] = cam->height % 256;
+       header2[439] = cam->width / 256;
+       header2[440] = cam->width % 256;
+
+       cam->nb = 0;
+
+       DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
+
+       /* set up the endpoint information  */
+       iface_desc = intf->cur_altsetting;
+       DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
+                       /* we found the bulk in endpoint */
+                       cam->read_endpoint = endpoint->bEndpointAddress;
+               }
+       }
+
+       if (!cam->read_endpoint) {
+               err = -ENOMEM;
+               dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
+               goto fail;
+       }
+
+       /* v4l */
+       INIT_LIST_HEAD(&cam->vidq.active);
+       cam->vidq.cam = cam;
+
+       usb_set_intfdata(intf, cam);
+
+       /* load zr364xx board specific */
+       err = zr364xx_board_init(cam);
+       if (!err)
+               err = v4l2_ctrl_handler_setup(hdl);
+       if (err)
+               goto fail;
+
+       spin_lock_init(&cam->slock);
+
+       cam->fmt = formats;
+
+       videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
+                                   NULL, &cam->slock,
+                                   V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                                   V4L2_FIELD_NONE,
+                                   sizeof(struct zr364xx_buffer), cam, &cam->lock);
+
+       err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
+       if (err) {
+               dev_err(&udev->dev, "video_register_device failed\n");
+               goto fail;
+       }
+
+       dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
+                video_device_node_name(&cam->vdev));
+       return 0;
+
+fail:
+       v4l2_ctrl_handler_free(hdl);
+       v4l2_device_unregister(&cam->v4l2_dev);
+       kfree(cam);
+       return err;
+}
+
+
+static void zr364xx_disconnect(struct usb_interface *intf)
+{
+       struct zr364xx_camera *cam = usb_get_intfdata(intf);
+
+       mutex_lock(&cam->lock);
+       usb_set_intfdata(intf, NULL);
+       dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
+       video_unregister_device(&cam->vdev);
+       v4l2_device_disconnect(&cam->v4l2_dev);
+
+       /* stops the read pipe if it is running */
+       if (cam->b_acquire)
+               zr364xx_stop_acquire(cam);
+
+       zr364xx_stop_readpipe(cam);
+       mutex_unlock(&cam->lock);
+       v4l2_device_put(&cam->v4l2_dev);
+}
+
+
+#ifdef CONFIG_PM
+static int zr364xx_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct zr364xx_camera *cam = usb_get_intfdata(intf);
+
+       cam->was_streaming = cam->b_acquire;
+       if (!cam->was_streaming)
+               return 0;
+       zr364xx_stop_acquire(cam);
+       zr364xx_stop_readpipe(cam);
+       return 0;
+}
+
+static int zr364xx_resume(struct usb_interface *intf)
+{
+       struct zr364xx_camera *cam = usb_get_intfdata(intf);
+       int res;
+
+       if (!cam->was_streaming)
+               return 0;
+
+       zr364xx_start_readpipe(cam);
+       res = zr364xx_prepare(cam);
+       if (!res)
+               zr364xx_start_acquire(cam);
+       return res;
+}
+#endif
+
+/**********************/
+/* Module integration */
+/**********************/
+
+static struct usb_driver zr364xx_driver = {
+       .name = "zr364xx",
+       .probe = zr364xx_probe,
+       .disconnect = zr364xx_disconnect,
+#ifdef CONFIG_PM
+       .suspend = zr364xx_suspend,
+       .resume = zr364xx_resume,
+       .reset_resume = zr364xx_resume,
+#endif
+       .id_table = device_table
+};
+
+module_usb_driver(zr364xx_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
index 097b17ced172ee360de02cc28845163900c2ccc6..f52799232029074809ac1329405afecdf55cf112 100644 (file)
@@ -605,56 +605,6 @@ config VIDEO_VIVI
          Say Y here if you want to test video apps or debug V4L devices.
          In doubt, say N.
 
-#
-# USB Multimedia device configuration
-#
-
-menuconfig V4L_USB_DRIVERS
-       bool "V4L USB devices"
-       depends on USB
-       default y
-
-if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
-
-config USB_ZR364XX
-       tristate "USB ZR364XX Camera support"
-       depends on VIDEO_V4L2
-       select VIDEOBUF_GEN
-       select VIDEOBUF_VMALLOC
-       ---help---
-         Say Y here if you want to connect this type of camera to your
-         computer's USB port.
-         See <file:Documentation/video4linux/zr364xx.txt> for more info
-         and list of supported cameras.
-
-         To compile this driver as a module, choose M here: the
-         module will be called zr364xx.
-
-config USB_STKWEBCAM
-       tristate "USB Syntek DC1125 Camera support"
-       depends on VIDEO_V4L2 && EXPERIMENTAL
-       ---help---
-         Say Y here if you want to use this type of camera.
-         Supported devices are typically found in some Asus laptops,
-         with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
-         may be supported by the stk11xx driver, from which this is
-         derived, see <http://sourceforge.net/projects/syntekdriver/>
-
-         To compile this driver as a module, choose M here: the
-         module will be called stkwebcam.
-
-config USB_S2255
-       tristate "USB Sensoray 2255 video capture device"
-       depends on VIDEO_V4L2
-       select VIDEOBUF_VMALLOC
-       default n
-       help
-         Say Y here if you want support for the Sensoray 2255 USB device.
-         This driver can be compiled as a module, called s2255drv.
-
-
-endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
-
 #
 # PCI drivers configuration - No devices here are for webcams
 #
index a22a2580ce3043b27ef360b1e7aff391cfff03f0..4ad5bd9246bf13ccaa8ac544de3ed6e117355b48 100644 (file)
@@ -4,8 +4,6 @@
 
 msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
 
-stkwebcam-objs :=      stk-webcam.o stk-sensor.o
-
 omap2cam-objs  :=      omap24xxcam.o omap24xxcam-dma.o
 
 # Helper modules
@@ -119,12 +117,6 @@ obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 
 obj-$(CONFIG_VIDEO_OMAP3)      += omap3isp/
 
-obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
-obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
-
-
-obj-$(CONFIG_USB_S2255)                += s2255drv.o
-
 obj-$(CONFIG_VIDEO_IVTV) += ivtv/
 obj-$(CONFIG_VIDEO_CX18) += cx18/
 
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
deleted file mode 100644 (file)
index 6c7960c..0000000
+++ /dev/null
@@ -1,2689 +0,0 @@
-/*
- *  s2255drv.c - a driver for the Sensoray 2255 USB video capture device
- *
- *   Copyright (C) 2007-2010 by Sensoray Company Inc.
- *                              Dean Anderson
- *
- * Some video buffer code based on vivi driver:
- *
- * Sensoray 2255 device supports 4 simultaneous channels.
- * The channels are not "crossbar" inputs, they are physically
- * attached to separate video decoders.
- *
- * Because of USB2.0 bandwidth limitations. There is only a
- * certain amount of data which may be transferred at one time.
- *
- * Example maximum bandwidth utilization:
- *
- * -full size, color mode YUYV or YUV422P: 2 channels at once
- * -full or half size Grey scale: all 4 channels at once
- * -half size, color mode YUYV or YUV422P: all 4 channels at once
- * -full size, color mode YUYV or YUV422P 1/2 frame rate: all 4 channels
- *  at once.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <linux/mm.h>
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/vmalloc.h>
-#include <linux/usb.h>
-
-#define S2255_VERSION          "1.22.1"
-#define FIRMWARE_FILE_NAME "f2255usb.bin"
-
-/* default JPEG quality */
-#define S2255_DEF_JPEG_QUAL     50
-/* vendor request in */
-#define S2255_VR_IN            0
-/* vendor request out */
-#define S2255_VR_OUT           1
-/* firmware query */
-#define S2255_VR_FW            0x30
-/* USB endpoint number for configuring the device */
-#define S2255_CONFIG_EP         2
-/* maximum time for DSP to start responding after last FW word loaded(ms) */
-#define S2255_DSP_BOOTTIME      800
-/* maximum time to wait for firmware to load (ms) */
-#define S2255_LOAD_TIMEOUT      (5000 + S2255_DSP_BOOTTIME)
-#define S2255_DEF_BUFS          16
-#define S2255_SETMODE_TIMEOUT   500
-#define S2255_VIDSTATUS_TIMEOUT 350
-#define S2255_MARKER_FRAME     cpu_to_le32(0x2255DA4AL)
-#define S2255_MARKER_RESPONSE  cpu_to_le32(0x2255ACACL)
-#define S2255_RESPONSE_SETMODE  cpu_to_le32(0x01)
-#define S2255_RESPONSE_FW       cpu_to_le32(0x10)
-#define S2255_RESPONSE_STATUS   cpu_to_le32(0x20)
-#define S2255_USB_XFER_SIZE    (16 * 1024)
-#define MAX_CHANNELS           4
-#define SYS_FRAMES             4
-/* maximum size is PAL full size plus room for the marker header(s) */
-#define SYS_FRAMES_MAXSIZE     (720*288*2*2 + 4096)
-#define DEF_USB_BLOCK          S2255_USB_XFER_SIZE
-#define LINE_SZ_4CIFS_NTSC     640
-#define LINE_SZ_2CIFS_NTSC     640
-#define LINE_SZ_1CIFS_NTSC     320
-#define LINE_SZ_4CIFS_PAL      704
-#define LINE_SZ_2CIFS_PAL      704
-#define LINE_SZ_1CIFS_PAL      352
-#define NUM_LINES_4CIFS_NTSC   240
-#define NUM_LINES_2CIFS_NTSC   240
-#define NUM_LINES_1CIFS_NTSC   240
-#define NUM_LINES_4CIFS_PAL    288
-#define NUM_LINES_2CIFS_PAL    288
-#define NUM_LINES_1CIFS_PAL    288
-#define LINE_SZ_DEF            640
-#define NUM_LINES_DEF          240
-
-
-/* predefined settings */
-#define FORMAT_NTSC    1
-#define FORMAT_PAL     2
-
-#define SCALE_4CIFS    1       /* 640x480(NTSC) or 704x576(PAL) */
-#define SCALE_2CIFS    2       /* 640x240(NTSC) or 704x288(PAL) */
-#define SCALE_1CIFS    3       /* 320x240(NTSC) or 352x288(PAL) */
-/* SCALE_4CIFSI is the 2 fields interpolated into one */
-#define SCALE_4CIFSI   4       /* 640x480(NTSC) or 704x576(PAL) high quality */
-
-#define COLOR_YUVPL    1       /* YUV planar */
-#define COLOR_YUVPK    2       /* YUV packed */
-#define COLOR_Y8       4       /* monochrome */
-#define COLOR_JPG       5       /* JPEG */
-
-#define MASK_COLOR       0x000000ff
-#define MASK_JPG_QUALITY 0x0000ff00
-#define MASK_INPUT_TYPE  0x000f0000
-/* frame decimation. */
-#define FDEC_1         1       /* capture every frame. default */
-#define FDEC_2         2       /* capture every 2nd frame */
-#define FDEC_3         3       /* capture every 3rd frame */
-#define FDEC_5         5       /* capture every 5th frame */
-
-/*-------------------------------------------------------
- * Default mode parameters.
- *-------------------------------------------------------*/
-#define DEF_SCALE      SCALE_4CIFS
-#define DEF_COLOR      COLOR_YUVPL
-#define DEF_FDEC       FDEC_1
-#define DEF_BRIGHT     0
-#define DEF_CONTRAST   0x5c
-#define DEF_SATURATION 0x80
-#define DEF_HUE                0
-
-/* usb config commands */
-#define IN_DATA_TOKEN  cpu_to_le32(0x2255c0de)
-#define CMD_2255       0xc2255000
-#define CMD_SET_MODE   cpu_to_le32((CMD_2255 | 0x10))
-#define CMD_START      cpu_to_le32((CMD_2255 | 0x20))
-#define CMD_STOP       cpu_to_le32((CMD_2255 | 0x30))
-#define CMD_STATUS     cpu_to_le32((CMD_2255 | 0x40))
-
-struct s2255_mode {
-       u32 format;     /* input video format (NTSC, PAL) */
-       u32 scale;      /* output video scale */
-       u32 color;      /* output video color format */
-       u32 fdec;       /* frame decimation */
-       u32 bright;     /* brightness */
-       u32 contrast;   /* contrast */
-       u32 saturation; /* saturation */
-       u32 hue;        /* hue (NTSC only)*/
-       u32 single;     /* capture 1 frame at a time (!=0), continuously (==0)*/
-       u32 usb_block;  /* block size. should be 4096 of DEF_USB_BLOCK */
-       u32 restart;    /* if DSP requires restart */
-};
-
-
-#define S2255_READ_IDLE                0
-#define S2255_READ_FRAME       1
-
-/* frame structure */
-struct s2255_framei {
-       unsigned long size;
-       unsigned long ulState;  /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/
-       void *lpvbits;          /* image data */
-       unsigned long cur_size; /* current data copied to it */
-};
-
-/* image buffer structure */
-struct s2255_bufferi {
-       unsigned long dwFrames;                 /* number of frames in buffer */
-       struct s2255_framei frame[SYS_FRAMES];  /* array of FRAME structures */
-};
-
-#define DEF_MODEI_NTSC_CONT    {FORMAT_NTSC, DEF_SCALE, DEF_COLOR,     \
-                       DEF_FDEC, DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, \
-                       DEF_HUE, 0, DEF_USB_BLOCK, 0}
-
-struct s2255_dmaqueue {
-       struct list_head        active;
-       struct s2255_dev        *dev;
-};
-
-/* for firmware loading, fw_state */
-#define S2255_FW_NOTLOADED     0
-#define S2255_FW_LOADED_DSPWAIT        1
-#define S2255_FW_SUCCESS       2
-#define S2255_FW_FAILED                3
-#define S2255_FW_DISCONNECTING  4
-#define S2255_FW_MARKER                cpu_to_le32(0x22552f2f)
-/* 2255 read states */
-#define S2255_READ_IDLE         0
-#define S2255_READ_FRAME        1
-struct s2255_fw {
-       int                   fw_loaded;
-       int                   fw_size;
-       struct urb            *fw_urb;
-       atomic_t              fw_state;
-       void                  *pfw_data;
-       wait_queue_head_t     wait_fw;
-       const struct firmware *fw;
-};
-
-struct s2255_pipeinfo {
-       u32 max_transfer_size;
-       u32 cur_transfer_size;
-       u8 *transfer_buffer;
-       u32 state;
-       void *stream_urb;
-       void *dev;      /* back pointer to s2255_dev struct*/
-       u32 err_count;
-       u32 idx;
-};
-
-struct s2255_fmt; /*forward declaration */
-struct s2255_dev;
-
-struct s2255_channel {
-       struct video_device     vdev;
-       int                     resources;
-       struct s2255_dmaqueue   vidq;
-       struct s2255_bufferi    buffer;
-       struct s2255_mode       mode;
-       /* jpeg compression */
-       struct v4l2_jpegcompression jc;
-       /* capture parameters (for high quality mode full size) */
-       struct v4l2_captureparm cap_parm;
-       int                     cur_frame;
-       int                     last_frame;
-
-       int                     b_acquire;
-       /* allocated image size */
-       unsigned long           req_image_size;
-       /* received packet size */
-       unsigned long           pkt_size;
-       int                     bad_payload;
-       unsigned long           frame_count;
-       /* if JPEG image */
-       int                     jpg_size;
-       /* if channel configured to default state */
-       int                     configured;
-       wait_queue_head_t       wait_setmode;
-       int                     setmode_ready;
-       /* video status items */
-       int                     vidstatus;
-       wait_queue_head_t       wait_vidstatus;
-       int                     vidstatus_ready;
-       unsigned int            width;
-       unsigned int            height;
-       const struct s2255_fmt  *fmt;
-       int idx; /* channel number on device, 0-3 */
-};
-
-
-struct s2255_dev {
-       struct s2255_channel    channel[MAX_CHANNELS];
-       struct v4l2_device      v4l2_dev;
-       atomic_t                num_channels;
-       int                     frames;
-       struct mutex            lock;   /* channels[].vdev.lock */
-       struct usb_device       *udev;
-       struct usb_interface    *interface;
-       u8                      read_endpoint;
-       struct timer_list       timer;
-       struct s2255_fw *fw_data;
-       struct s2255_pipeinfo   pipe;
-       u32                     cc;     /* current channel */
-       int                     frame_ready;
-       int                     chn_ready;
-       spinlock_t              slock;
-       /* dsp firmware version (f2255usb.bin) */
-       int                     dsp_fw_ver;
-       u16                     pid; /* product id */
-};
-
-static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct s2255_dev, v4l2_dev);
-}
-
-struct s2255_fmt {
-       char *name;
-       u32 fourcc;
-       int depth;
-};
-
-/* buffer for one video frame */
-struct s2255_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-       const struct s2255_fmt *fmt;
-};
-
-struct s2255_fh {
-       struct s2255_dev        *dev;
-       struct videobuf_queue   vb_vidq;
-       enum v4l2_buf_type      type;
-       struct s2255_channel    *channel;
-       int                     resources;
-};
-
-/* current cypress EEPROM firmware version */
-#define S2255_CUR_USB_FWVER    ((3 << 8) | 12)
-/* current DSP FW version */
-#define S2255_CUR_DSP_FWVER     10104
-/* Need DSP version 5+ for video status feature */
-#define S2255_MIN_DSP_STATUS      5
-#define S2255_MIN_DSP_COLORFILTER 8
-#define S2255_NORMS            (V4L2_STD_PAL | V4L2_STD_NTSC)
-
-/* private V4L2 controls */
-
-/*
- * The following chart displays how COLORFILTER should be set
- *  =========================================================
- *  =     fourcc              =     COLORFILTER             =
- *  =                         ===============================
- *  =                         =   0             =    1      =
- *  =========================================================
- *  =  V4L2_PIX_FMT_GREY(Y8)  = monochrome from = monochrome=
- *  =                         = s-video or      = composite =
- *  =                         = B/W camera      = input     =
- *  =========================================================
- *  =    other                = color, svideo   = color,    =
- *  =                         =                 = composite =
- *  =========================================================
- *
- * Notes:
- *   channels 0-3 on 2255 are composite
- *   channels 0-1 on 2257 are composite, 2-3 are s-video
- * If COLORFILTER is 0 with a composite color camera connected,
- * the output will appear monochrome but hatching
- * will occur.
- * COLORFILTER is different from "color killer" and "color effects"
- * for reasons above.
- */
-#define S2255_V4L2_YC_ON  1
-#define S2255_V4L2_YC_OFF 0
-#define V4L2_CID_PRIVATE_COLORFILTER (V4L2_CID_PRIVATE_BASE + 0)
-
-/* frame prefix size (sent once every frame) */
-#define PREFIX_SIZE            512
-
-/* Channels on box are in reverse order */
-static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0};
-
-static int debug;
-static int *s2255_debug = &debug;
-
-static int s2255_start_readpipe(struct s2255_dev *dev);
-static void s2255_stop_readpipe(struct s2255_dev *dev);
-static int s2255_start_acquire(struct s2255_channel *channel);
-static int s2255_stop_acquire(struct s2255_channel *channel);
-static void s2255_fillbuff(struct s2255_channel *chn, struct s2255_buffer *buf,
-                          int jpgsize);
-static int s2255_set_mode(struct s2255_channel *chan, struct s2255_mode *mode);
-static int s2255_board_shutdown(struct s2255_dev *dev);
-static void s2255_fwload_start(struct s2255_dev *dev, int reset);
-static void s2255_destroy(struct s2255_dev *dev);
-static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
-                            u16 index, u16 value, void *buf,
-                            s32 buf_len, int bOut);
-
-/* dev_err macro with driver name */
-#define S2255_DRIVER_NAME "s2255"
-#define s2255_dev_err(dev, fmt, arg...)                                        \
-               dev_err(dev, S2255_DRIVER_NAME " - " fmt, ##arg)
-
-#define dprintk(level, fmt, arg...)                                    \
-       do {                                                            \
-               if (*s2255_debug >= (level)) {                          \
-                       printk(KERN_DEBUG S2255_DRIVER_NAME             \
-                               ": " fmt, ##arg);                       \
-               }                                                       \
-       } while (0)
-
-static struct usb_driver s2255_driver;
-
-/* Declare static vars that will be used as parameters */
-static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
-
-/* start video number */
-static int video_nr = -1;      /* /dev/videoN, -1 for autodetect */
-
-/* Enable jpeg capture. */
-static int jpeg_enable = 1;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level(0-100) default 0");
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "video memory limit(Mb)");
-module_param(video_nr, int, 0644);
-MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)");
-module_param(jpeg_enable, int, 0644);
-MODULE_PARM_DESC(jpeg_enable, "Jpeg enable(1-on 0-off) default 1");
-
-/* USB device table */
-#define USB_SENSORAY_VID       0x1943
-static struct usb_device_id s2255_table[] = {
-       {USB_DEVICE(USB_SENSORAY_VID, 0x2255)},
-       {USB_DEVICE(USB_SENSORAY_VID, 0x2257)}, /*same family as 2255*/
-       { }                     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, s2255_table);
-
-#define BUFFER_TIMEOUT msecs_to_jiffies(400)
-
-/* image formats.  */
-/* JPEG formats must be defined last to support jpeg_enable parameter */
-static const struct s2255_fmt formats[] = {
-       {
-               .name = "4:2:2, planar, YUV422P",
-               .fourcc = V4L2_PIX_FMT_YUV422P,
-               .depth = 16
-
-       }, {
-               .name = "4:2:2, packed, YUYV",
-               .fourcc = V4L2_PIX_FMT_YUYV,
-               .depth = 16
-
-       }, {
-               .name = "4:2:2, packed, UYVY",
-               .fourcc = V4L2_PIX_FMT_UYVY,
-               .depth = 16
-       }, {
-               .name = "8bpp GREY",
-               .fourcc = V4L2_PIX_FMT_GREY,
-               .depth = 8
-       }, {
-               .name = "JPG",
-               .fourcc = V4L2_PIX_FMT_JPEG,
-               .depth = 24
-       }, {
-               .name = "MJPG",
-               .fourcc = V4L2_PIX_FMT_MJPEG,
-               .depth = 24
-       }
-};
-
-static int norm_maxw(struct video_device *vdev)
-{
-       return (vdev->current_norm & V4L2_STD_NTSC) ?
-           LINE_SZ_4CIFS_NTSC : LINE_SZ_4CIFS_PAL;
-}
-
-static int norm_maxh(struct video_device *vdev)
-{
-       return (vdev->current_norm & V4L2_STD_NTSC) ?
-           (NUM_LINES_1CIFS_NTSC * 2) : (NUM_LINES_1CIFS_PAL * 2);
-}
-
-static int norm_minw(struct video_device *vdev)
-{
-       return (vdev->current_norm & V4L2_STD_NTSC) ?
-           LINE_SZ_1CIFS_NTSC : LINE_SZ_1CIFS_PAL;
-}
-
-static int norm_minh(struct video_device *vdev)
-{
-       return (vdev->current_norm & V4L2_STD_NTSC) ?
-           (NUM_LINES_1CIFS_NTSC) : (NUM_LINES_1CIFS_PAL);
-}
-
-
-/*
- * TODO: fixme: move YUV reordering to hardware
- * converts 2255 planar format to yuyv or uyvy
- */
-static void planar422p_to_yuv_packed(const unsigned char *in,
-                                    unsigned char *out,
-                                    int width, int height,
-                                    int fmt)
-{
-       unsigned char *pY;
-       unsigned char *pCb;
-       unsigned char *pCr;
-       unsigned long size = height * width;
-       unsigned int i;
-       pY = (unsigned char *)in;
-       pCr = (unsigned char *)in + height * width;
-       pCb = (unsigned char *)in + height * width + (height * width / 2);
-       for (i = 0; i < size * 2; i += 4) {
-               out[i] = (fmt == V4L2_PIX_FMT_YUYV) ? *pY++ : *pCr++;
-               out[i + 1] = (fmt == V4L2_PIX_FMT_YUYV) ? *pCr++ : *pY++;
-               out[i + 2] = (fmt == V4L2_PIX_FMT_YUYV) ? *pY++ : *pCb++;
-               out[i + 3] = (fmt == V4L2_PIX_FMT_YUYV) ? *pCb++ : *pY++;
-       }
-       return;
-}
-
-static void s2255_reset_dsppower(struct s2255_dev *dev)
-{
-       s2255_vendor_req(dev, 0x40, 0x0000, 0x0001, NULL, 0, 1);
-       msleep(10);
-       s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1);
-       msleep(600);
-       s2255_vendor_req(dev, 0x10, 0x0000, 0x0000, NULL, 0, 1);
-       return;
-}
-
-/* kickstarts the firmware loading. from probe
- */
-static void s2255_timer(unsigned long user_data)
-{
-       struct s2255_fw *data = (struct s2255_fw *)user_data;
-       dprintk(100, "%s\n", __func__);
-       if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
-               printk(KERN_ERR "s2255: can't submit urb\n");
-               atomic_set(&data->fw_state, S2255_FW_FAILED);
-               /* wake up anything waiting for the firmware */
-               wake_up(&data->wait_fw);
-               return;
-       }
-}
-
-
-/* this loads the firmware asynchronously.
-   Originally this was done synchroously in probe.
-   But it is better to load it asynchronously here than block
-   inside the probe function. Blocking inside probe affects boot time.
-   FW loading is triggered by the timer in the probe function
-*/
-static void s2255_fwchunk_complete(struct urb *urb)
-{
-       struct s2255_fw *data = urb->context;
-       struct usb_device *udev = urb->dev;
-       int len;
-       dprintk(100, "%s: udev %p urb %p", __func__, udev, urb);
-       if (urb->status) {
-               dev_err(&udev->dev, "URB failed with status %d\n", urb->status);
-               atomic_set(&data->fw_state, S2255_FW_FAILED);
-               /* wake up anything waiting for the firmware */
-               wake_up(&data->wait_fw);
-               return;
-       }
-       if (data->fw_urb == NULL) {
-               s2255_dev_err(&udev->dev, "disconnected\n");
-               atomic_set(&data->fw_state, S2255_FW_FAILED);
-               /* wake up anything waiting for the firmware */
-               wake_up(&data->wait_fw);
-               return;
-       }
-#define CHUNK_SIZE 512
-       /* all USB transfers must be done with continuous kernel memory.
-          can't allocate more than 128k in current linux kernel, so
-          upload the firmware in chunks
-        */
-       if (data->fw_loaded < data->fw_size) {
-               len = (data->fw_loaded + CHUNK_SIZE) > data->fw_size ?
-                   data->fw_size % CHUNK_SIZE : CHUNK_SIZE;
-
-               if (len < CHUNK_SIZE)
-                       memset(data->pfw_data, 0, CHUNK_SIZE);
-
-               dprintk(100, "completed len %d, loaded %d \n", len,
-                       data->fw_loaded);
-
-               memcpy(data->pfw_data,
-                      (char *) data->fw->data + data->fw_loaded, len);
-
-               usb_fill_bulk_urb(data->fw_urb, udev, usb_sndbulkpipe(udev, 2),
-                                 data->pfw_data, CHUNK_SIZE,
-                                 s2255_fwchunk_complete, data);
-               if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
-                       dev_err(&udev->dev, "failed submit URB\n");
-                       atomic_set(&data->fw_state, S2255_FW_FAILED);
-                       /* wake up anything waiting for the firmware */
-                       wake_up(&data->wait_fw);
-                       return;
-               }
-               data->fw_loaded += len;
-       } else {
-               atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT);
-               dprintk(100, "%s: firmware upload complete\n", __func__);
-       }
-       return;
-
-}
-
-static int s2255_got_frame(struct s2255_channel *channel, int jpgsize)
-{
-       struct s2255_dmaqueue *dma_q = &channel->vidq;
-       struct s2255_buffer *buf;
-       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-       unsigned long flags = 0;
-       int rc = 0;
-       spin_lock_irqsave(&dev->slock, flags);
-       if (list_empty(&dma_q->active)) {
-               dprintk(1, "No active queue to serve\n");
-               rc = -1;
-               goto unlock;
-       }
-       buf = list_entry(dma_q->active.next,
-                        struct s2255_buffer, vb.queue);
-       list_del(&buf->vb.queue);
-       do_gettimeofday(&buf->vb.ts);
-       s2255_fillbuff(channel, buf, jpgsize);
-       wake_up(&buf->vb.done);
-       dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i);
-unlock:
-       spin_unlock_irqrestore(&dev->slock, flags);
-       return rc;
-}
-
-static const struct s2255_fmt *format_by_fourcc(int fourcc)
-{
-       unsigned int i;
-       for (i = 0; i < ARRAY_SIZE(formats); i++) {
-               if (-1 == formats[i].fourcc)
-                       continue;
-       if (!jpeg_enable && ((formats[i].fourcc == V4L2_PIX_FMT_JPEG) ||
-                            (formats[i].fourcc == V4L2_PIX_FMT_MJPEG)))
-           continue;
-               if (formats[i].fourcc == fourcc)
-                       return formats + i;
-       }
-       return NULL;
-}
-
-/* video buffer vmalloc implementation based partly on VIVI driver which is
- *          Copyright (c) 2006 by
- *                  Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
- *                  Ted Walther <ted--a.t--enumera.com>
- *                  John Sokol <sokol--a.t--videotechnology.com>
- *                  http://v4l.videotechnology.com/
- *
- */
-static void s2255_fillbuff(struct s2255_channel *channel,
-                          struct s2255_buffer *buf, int jpgsize)
-{
-       int pos = 0;
-       struct timeval ts;
-       const char *tmpbuf;
-       char *vbuf = videobuf_to_vmalloc(&buf->vb);
-       unsigned long last_frame;
-
-       if (!vbuf)
-               return;
-       last_frame = channel->last_frame;
-       if (last_frame != -1) {
-               tmpbuf =
-                   (const char *)channel->buffer.frame[last_frame].lpvbits;
-               switch (buf->fmt->fourcc) {
-               case V4L2_PIX_FMT_YUYV:
-               case V4L2_PIX_FMT_UYVY:
-                       planar422p_to_yuv_packed((const unsigned char *)tmpbuf,
-                                                vbuf, buf->vb.width,
-                                                buf->vb.height,
-                                                buf->fmt->fourcc);
-                       break;
-               case V4L2_PIX_FMT_GREY:
-                       memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height);
-                       break;
-               case V4L2_PIX_FMT_JPEG:
-               case V4L2_PIX_FMT_MJPEG:
-                       buf->vb.size = jpgsize;
-                       memcpy(vbuf, tmpbuf, buf->vb.size);
-                       break;
-               case V4L2_PIX_FMT_YUV422P:
-                       memcpy(vbuf, tmpbuf,
-                              buf->vb.width * buf->vb.height * 2);
-                       break;
-               default:
-                       printk(KERN_DEBUG "s2255: unknown format?\n");
-               }
-               channel->last_frame = -1;
-       } else {
-               printk(KERN_ERR "s2255: =======no frame\n");
-               return;
-
-       }
-       dprintk(2, "s2255fill at : Buffer 0x%08lx size= %d\n",
-               (unsigned long)vbuf, pos);
-       /* tell v4l buffer was filled */
-
-       buf->vb.field_count = channel->frame_count * 2;
-       do_gettimeofday(&ts);
-       buf->vb.ts = ts;
-       buf->vb.state = VIDEOBUF_DONE;
-}
-
-
-/* ------------------------------------------------------------------
-   Videobuf operations
-   ------------------------------------------------------------------*/
-
-static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-                       unsigned int *size)
-{
-       struct s2255_fh *fh = vq->priv_data;
-       struct s2255_channel *channel = fh->channel;
-       *size = channel->width * channel->height * (channel->fmt->depth >> 3);
-
-       if (0 == *count)
-               *count = S2255_DEF_BUFS;
-
-       if (*size * *count > vid_limit * 1024 * 1024)
-               *count = (vid_limit * 1024 * 1024) / *size;
-
-       return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct s2255_buffer *buf)
-{
-       dprintk(4, "%s\n", __func__);
-
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                         enum v4l2_field field)
-{
-       struct s2255_fh *fh = vq->priv_data;
-       struct s2255_channel *channel = fh->channel;
-       struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
-       int rc;
-       int w = channel->width;
-       int h = channel->height;
-       dprintk(4, "%s, field=%d\n", __func__, field);
-       if (channel->fmt == NULL)
-               return -EINVAL;
-
-       if ((w < norm_minw(&channel->vdev)) ||
-           (w > norm_maxw(&channel->vdev)) ||
-           (h < norm_minh(&channel->vdev)) ||
-           (h > norm_maxh(&channel->vdev))) {
-               dprintk(4, "invalid buffer prepare\n");
-               return -EINVAL;
-       }
-       buf->vb.size = w * h * (channel->fmt->depth >> 3);
-       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) {
-               dprintk(4, "invalid buffer prepare\n");
-               return -EINVAL;
-       }
-
-       buf->fmt = channel->fmt;
-       buf->vb.width = w;
-       buf->vb.height = h;
-       buf->vb.field = field;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
-       struct s2255_fh *fh = vq->priv_data;
-       struct s2255_channel *channel = fh->channel;
-       struct s2255_dmaqueue *vidq = &channel->vidq;
-       dprintk(1, "%s\n", __func__);
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &vidq->active);
-}
-
-static void buffer_release(struct videobuf_queue *vq,
-                          struct videobuf_buffer *vb)
-{
-       struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
-       struct s2255_fh *fh = vq->priv_data;
-       dprintk(4, "%s %d\n", __func__, fh->channel->idx);
-       free_buffer(vq, buf);
-}
-
-static struct videobuf_queue_ops s2255_video_qops = {
-       .buf_setup = buffer_setup,
-       .buf_prepare = buffer_prepare,
-       .buf_queue = buffer_queue,
-       .buf_release = buffer_release,
-};
-
-
-static int res_get(struct s2255_fh *fh)
-{
-       struct s2255_channel *channel = fh->channel;
-       /* is it free? */
-       if (channel->resources)
-               return 0; /* no, someone else uses it */
-       /* it's free, grab it */
-       channel->resources = 1;
-       fh->resources = 1;
-       dprintk(1, "s2255: res: get\n");
-       return 1;
-}
-
-static int res_locked(struct s2255_fh *fh)
-{
-       return fh->channel->resources;
-}
-
-static int res_check(struct s2255_fh *fh)
-{
-       return fh->resources;
-}
-
-
-static void res_free(struct s2255_fh *fh)
-{
-       struct s2255_channel *channel = fh->channel;
-       channel->resources = 0;
-       fh->resources = 0;
-       dprintk(1, "res: put\n");
-}
-
-static int vidioc_querymenu(struct file *file, void *priv,
-                           struct v4l2_querymenu *qmenu)
-{
-       static const char *colorfilter[] = {
-               "Off",
-               "On",
-               NULL
-       };
-       if (qmenu->id == V4L2_CID_PRIVATE_COLORFILTER) {
-               int i;
-               const char **menu_items = colorfilter;
-               for (i = 0; i < qmenu->index && menu_items[i]; i++)
-                       ; /* do nothing (from v4l2-common.c) */
-               if (menu_items[i] == NULL || menu_items[i][0] == '\0')
-                       return -EINVAL;
-               strlcpy(qmenu->name, menu_items[qmenu->index],
-                       sizeof(qmenu->name));
-               return 0;
-       }
-       return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       struct s2255_fh *fh = file->private_data;
-       struct s2255_dev *dev = fh->dev;
-       strlcpy(cap->driver, "s2255", sizeof(cap->driver));
-       strlcpy(cap->card, "s2255", sizeof(cap->card));
-       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-                              struct v4l2_fmtdesc *f)
-{
-       int index = f->index;
-
-       if (index >= ARRAY_SIZE(formats))
-               return -EINVAL;
-       if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) ||
-                       (formats[index].fourcc == V4L2_PIX_FMT_MJPEG)))
-               return -EINVAL;
-       dprintk(4, "name %s\n", formats[index].name);
-       strlcpy(f->description, formats[index].name, sizeof(f->description));
-       f->pixelformat = formats[index].fourcc;
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                           struct v4l2_format *f)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-
-       f->fmt.pix.width = channel->width;
-       f->fmt.pix.height = channel->height;
-       f->fmt.pix.field = fh->vb_vidq.field;
-       f->fmt.pix.pixelformat = channel->fmt->fourcc;
-       f->fmt.pix.bytesperline = f->fmt.pix.width * (channel->fmt->depth >> 3);
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                             struct v4l2_format *f)
-{
-       const struct s2255_fmt *fmt;
-       enum v4l2_field field;
-       int  b_any_field = 0;
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-       int is_ntsc;
-       is_ntsc =
-               (channel->vdev.current_norm & V4L2_STD_NTSC) ? 1 : 0;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-
-       if (fmt == NULL)
-               return -EINVAL;
-
-       field = f->fmt.pix.field;
-       if (field == V4L2_FIELD_ANY)
-               b_any_field = 1;
-
-       dprintk(50, "%s NTSC: %d suggested width: %d, height: %d\n",
-               __func__, is_ntsc, f->fmt.pix.width, f->fmt.pix.height);
-       if (is_ntsc) {
-               /* NTSC */
-               if (f->fmt.pix.height >= NUM_LINES_1CIFS_NTSC * 2) {
-                       f->fmt.pix.height = NUM_LINES_1CIFS_NTSC * 2;
-                       if (b_any_field) {
-                               field = V4L2_FIELD_SEQ_TB;
-                       } else if (!((field == V4L2_FIELD_INTERLACED) ||
-                                     (field == V4L2_FIELD_SEQ_TB) ||
-                                     (field == V4L2_FIELD_INTERLACED_TB))) {
-                               dprintk(1, "unsupported field setting\n");
-                               return -EINVAL;
-                       }
-               } else {
-                       f->fmt.pix.height = NUM_LINES_1CIFS_NTSC;
-                       if (b_any_field) {
-                               field = V4L2_FIELD_TOP;
-                       } else if (!((field == V4L2_FIELD_TOP) ||
-                                     (field == V4L2_FIELD_BOTTOM))) {
-                               dprintk(1, "unsupported field setting\n");
-                               return -EINVAL;
-                       }
-
-               }
-               if (f->fmt.pix.width >= LINE_SZ_4CIFS_NTSC)
-                       f->fmt.pix.width = LINE_SZ_4CIFS_NTSC;
-               else if (f->fmt.pix.width >= LINE_SZ_2CIFS_NTSC)
-                       f->fmt.pix.width = LINE_SZ_2CIFS_NTSC;
-               else if (f->fmt.pix.width >= LINE_SZ_1CIFS_NTSC)
-                       f->fmt.pix.width = LINE_SZ_1CIFS_NTSC;
-               else
-                       f->fmt.pix.width = LINE_SZ_1CIFS_NTSC;
-       } else {
-               /* PAL */
-               if (f->fmt.pix.height >= NUM_LINES_1CIFS_PAL * 2) {
-                       f->fmt.pix.height = NUM_LINES_1CIFS_PAL * 2;
-                       if (b_any_field) {
-                               field = V4L2_FIELD_SEQ_TB;
-                       } else if (!((field == V4L2_FIELD_INTERLACED) ||
-                                     (field == V4L2_FIELD_SEQ_TB) ||
-                                     (field == V4L2_FIELD_INTERLACED_TB))) {
-                               dprintk(1, "unsupported field setting\n");
-                               return -EINVAL;
-                       }
-               } else {
-                       f->fmt.pix.height = NUM_LINES_1CIFS_PAL;
-                       if (b_any_field) {
-                               field = V4L2_FIELD_TOP;
-                       } else if (!((field == V4L2_FIELD_TOP) ||
-                                    (field == V4L2_FIELD_BOTTOM))) {
-                               dprintk(1, "unsupported field setting\n");
-                               return -EINVAL;
-                       }
-               }
-               if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL) {
-                       f->fmt.pix.width = LINE_SZ_4CIFS_PAL;
-                       field = V4L2_FIELD_SEQ_TB;
-               } else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL) {
-                       f->fmt.pix.width = LINE_SZ_2CIFS_PAL;
-                       field = V4L2_FIELD_TOP;
-               } else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL) {
-                       f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
-                       field = V4L2_FIELD_TOP;
-               } else {
-                       f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
-                       field = V4L2_FIELD_TOP;
-               }
-       }
-       f->fmt.pix.field = field;
-       f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-       dprintk(50, "%s: set width %d height %d field %d\n", __func__,
-               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                           struct v4l2_format *f)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-       const struct s2255_fmt *fmt;
-       struct videobuf_queue *q = &fh->vb_vidq;
-       struct s2255_mode mode;
-       int ret;
-
-       ret = vidioc_try_fmt_vid_cap(file, fh, f);
-
-       if (ret < 0)
-               return ret;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-
-       if (fmt == NULL)
-               return -EINVAL;
-
-       mutex_lock(&q->vb_lock);
-
-       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
-               dprintk(1, "queue busy\n");
-               ret = -EBUSY;
-               goto out_s_fmt;
-       }
-
-       if (res_locked(fh)) {
-               dprintk(1, "%s: channel busy\n", __func__);
-               ret = -EBUSY;
-               goto out_s_fmt;
-       }
-       mode = channel->mode;
-       channel->fmt = fmt;
-       channel->width = f->fmt.pix.width;
-       channel->height = f->fmt.pix.height;
-       fh->vb_vidq.field = f->fmt.pix.field;
-       fh->type = f->type;
-       if (channel->width > norm_minw(&channel->vdev)) {
-               if (channel->height > norm_minh(&channel->vdev)) {
-                       if (channel->cap_parm.capturemode &
-                           V4L2_MODE_HIGHQUALITY)
-                               mode.scale = SCALE_4CIFSI;
-                       else
-                               mode.scale = SCALE_4CIFS;
-               } else
-                       mode.scale = SCALE_2CIFS;
-
-       } else {
-               mode.scale = SCALE_1CIFS;
-       }
-       /* color mode */
-       switch (channel->fmt->fourcc) {
-       case V4L2_PIX_FMT_GREY:
-               mode.color &= ~MASK_COLOR;
-               mode.color |= COLOR_Y8;
-               break;
-       case V4L2_PIX_FMT_JPEG:
-       case V4L2_PIX_FMT_MJPEG:
-               mode.color &= ~MASK_COLOR;
-               mode.color |= COLOR_JPG;
-               mode.color |= (channel->jc.quality << 8);
-               break;
-       case V4L2_PIX_FMT_YUV422P:
-               mode.color &= ~MASK_COLOR;
-               mode.color |= COLOR_YUVPL;
-               break;
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_UYVY:
-       default:
-               mode.color &= ~MASK_COLOR;
-               mode.color |= COLOR_YUVPK;
-               break;
-       }
-       if ((mode.color & MASK_COLOR) != (channel->mode.color & MASK_COLOR))
-               mode.restart = 1;
-       else if (mode.scale != channel->mode.scale)
-               mode.restart = 1;
-       else if (mode.format != channel->mode.format)
-               mode.restart = 1;
-       channel->mode = mode;
-       (void) s2255_set_mode(channel, &mode);
-       ret = 0;
-out_s_fmt:
-       mutex_unlock(&q->vb_lock);
-       return ret;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *p)
-{
-       int rc;
-       struct s2255_fh *fh = priv;
-       rc = videobuf_reqbufs(&fh->vb_vidq, p);
-       return rc;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       int rc;
-       struct s2255_fh *fh = priv;
-       rc = videobuf_querybuf(&fh->vb_vidq, p);
-       return rc;
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       int rc;
-       struct s2255_fh *fh = priv;
-       rc = videobuf_qbuf(&fh->vb_vidq, p);
-       return rc;
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       int rc;
-       struct s2255_fh *fh = priv;
-       rc = videobuf_dqbuf(&fh->vb_vidq, p, file->f_flags & O_NONBLOCK);
-       return rc;
-}
-
-/* write to the configuration pipe, synchronously */
-static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
-                             int size)
-{
-       int pipe;
-       int done;
-       long retval = -1;
-       if (udev) {
-               pipe = usb_sndbulkpipe(udev, S2255_CONFIG_EP);
-               retval = usb_bulk_msg(udev, pipe, pbuf, size, &done, 500);
-       }
-       return retval;
-}
-
-static u32 get_transfer_size(struct s2255_mode *mode)
-{
-       int linesPerFrame = LINE_SZ_DEF;
-       int pixelsPerLine = NUM_LINES_DEF;
-       u32 outImageSize;
-       u32 usbInSize;
-       unsigned int mask_mult;
-
-       if (mode == NULL)
-               return 0;
-
-       if (mode->format == FORMAT_NTSC) {
-               switch (mode->scale) {
-               case SCALE_4CIFS:
-               case SCALE_4CIFSI:
-                       linesPerFrame = NUM_LINES_4CIFS_NTSC * 2;
-                       pixelsPerLine = LINE_SZ_4CIFS_NTSC;
-                       break;
-               case SCALE_2CIFS:
-                       linesPerFrame = NUM_LINES_2CIFS_NTSC;
-                       pixelsPerLine = LINE_SZ_2CIFS_NTSC;
-                       break;
-               case SCALE_1CIFS:
-                       linesPerFrame = NUM_LINES_1CIFS_NTSC;
-                       pixelsPerLine = LINE_SZ_1CIFS_NTSC;
-                       break;
-               default:
-                       break;
-               }
-       } else if (mode->format == FORMAT_PAL) {
-               switch (mode->scale) {
-               case SCALE_4CIFS:
-               case SCALE_4CIFSI:
-                       linesPerFrame = NUM_LINES_4CIFS_PAL * 2;
-                       pixelsPerLine = LINE_SZ_4CIFS_PAL;
-                       break;
-               case SCALE_2CIFS:
-                       linesPerFrame = NUM_LINES_2CIFS_PAL;
-                       pixelsPerLine = LINE_SZ_2CIFS_PAL;
-                       break;
-               case SCALE_1CIFS:
-                       linesPerFrame = NUM_LINES_1CIFS_PAL;
-                       pixelsPerLine = LINE_SZ_1CIFS_PAL;
-                       break;
-               default:
-                       break;
-               }
-       }
-       outImageSize = linesPerFrame * pixelsPerLine;
-       if ((mode->color & MASK_COLOR) != COLOR_Y8) {
-               /* 2 bytes/pixel if not monochrome */
-               outImageSize *= 2;
-       }
-
-       /* total bytes to send including prefix and 4K padding;
-          must be a multiple of USB_READ_SIZE */
-       usbInSize = outImageSize + PREFIX_SIZE; /* always send prefix */
-       mask_mult = 0xffffffffUL - DEF_USB_BLOCK + 1;
-       /* if size not a multiple of USB_READ_SIZE */
-       if (usbInSize & ~mask_mult)
-               usbInSize = (usbInSize & mask_mult) + (DEF_USB_BLOCK);
-       return usbInSize;
-}
-
-static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode)
-{
-       struct device *dev = &sdev->udev->dev;
-       dev_info(dev, "------------------------------------------------\n");
-       dev_info(dev, "format: %d\nscale %d\n", mode->format, mode->scale);
-       dev_info(dev, "fdec: %d\ncolor %d\n", mode->fdec, mode->color);
-       dev_info(dev, "bright: 0x%x\n", mode->bright);
-       dev_info(dev, "------------------------------------------------\n");
-}
-
-/*
- * set mode is the function which controls the DSP.
- * the restart parameter in struct s2255_mode should be set whenever
- * the image size could change via color format, video system or image
- * size.
- * When the restart parameter is set, we sleep for ONE frame to allow the
- * DSP time to get the new frame
- */
-static int s2255_set_mode(struct s2255_channel *channel,
-                         struct s2255_mode *mode)
-{
-       int res;
-       __le32 *buffer;
-       unsigned long chn_rev;
-       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-       chn_rev = G_chnmap[channel->idx];
-       dprintk(3, "%s channel: %d\n", __func__, channel->idx);
-       /* if JPEG, set the quality */
-       if ((mode->color & MASK_COLOR) == COLOR_JPG) {
-               mode->color &= ~MASK_COLOR;
-               mode->color |= COLOR_JPG;
-               mode->color &= ~MASK_JPG_QUALITY;
-               mode->color |= (channel->jc.quality << 8);
-       }
-       /* save the mode */
-       channel->mode = *mode;
-       channel->req_image_size = get_transfer_size(mode);
-       dprintk(1, "%s: reqsize %ld\n", __func__, channel->req_image_size);
-       buffer = kzalloc(512, GFP_KERNEL);
-       if (buffer == NULL) {
-               dev_err(&dev->udev->dev, "out of mem\n");
-               return -ENOMEM;
-       }
-       /* set the mode */
-       buffer[0] = IN_DATA_TOKEN;
-       buffer[1] = (__le32) cpu_to_le32(chn_rev);
-       buffer[2] = CMD_SET_MODE;
-       memcpy(&buffer[3], &channel->mode, sizeof(struct s2255_mode));
-       channel->setmode_ready = 0;
-       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
-       if (debug)
-               s2255_print_cfg(dev, mode);
-       kfree(buffer);
-       /* wait at least 3 frames before continuing */
-       if (mode->restart) {
-               wait_event_timeout(channel->wait_setmode,
-                                  (channel->setmode_ready != 0),
-                                  msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
-               if (channel->setmode_ready != 1) {
-                       printk(KERN_DEBUG "s2255: no set mode response\n");
-                       res = -EFAULT;
-               }
-       }
-       /* clear the restart flag */
-       channel->mode.restart = 0;
-       dprintk(1, "%s chn %d, result: %d\n", __func__, channel->idx, res);
-       return res;
-}
-
-static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus)
-{
-       int res;
-       __le32 *buffer;
-       u32 chn_rev;
-       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-       chn_rev = G_chnmap[channel->idx];
-       dprintk(4, "%s chan %d\n", __func__, channel->idx);
-       buffer = kzalloc(512, GFP_KERNEL);
-       if (buffer == NULL) {
-               dev_err(&dev->udev->dev, "out of mem\n");
-               return -ENOMEM;
-       }
-       /* form the get vid status command */
-       buffer[0] = IN_DATA_TOKEN;
-       buffer[1] = (__le32) cpu_to_le32(chn_rev);
-       buffer[2] = CMD_STATUS;
-       *pstatus = 0;
-       channel->vidstatus_ready = 0;
-       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
-       kfree(buffer);
-       wait_event_timeout(channel->wait_vidstatus,
-                          (channel->vidstatus_ready != 0),
-                          msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT));
-       if (channel->vidstatus_ready != 1) {
-               printk(KERN_DEBUG "s2255: no vidstatus response\n");
-               res = -EFAULT;
-       }
-       *pstatus = channel->vidstatus;
-       dprintk(4, "%s, vid status %d\n", __func__, *pstatus);
-       return res;
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       int res;
-       struct s2255_fh *fh = priv;
-       struct s2255_dev *dev = fh->dev;
-       struct s2255_channel *channel = fh->channel;
-       int j;
-       dprintk(4, "%s\n", __func__);
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               dev_err(&dev->udev->dev, "invalid fh type0\n");
-               return -EINVAL;
-       }
-       if (i != fh->type) {
-               dev_err(&dev->udev->dev, "invalid fh type1\n");
-               return -EINVAL;
-       }
-
-       if (!res_get(fh)) {
-               s2255_dev_err(&dev->udev->dev, "stream busy\n");
-               return -EBUSY;
-       }
-       channel->last_frame = -1;
-       channel->bad_payload = 0;
-       channel->cur_frame = 0;
-       channel->frame_count = 0;
-       for (j = 0; j < SYS_FRAMES; j++) {
-               channel->buffer.frame[j].ulState = S2255_READ_IDLE;
-               channel->buffer.frame[j].cur_size = 0;
-       }
-       res = videobuf_streamon(&fh->vb_vidq);
-       if (res == 0) {
-               s2255_start_acquire(channel);
-               channel->b_acquire = 1;
-       } else
-               res_free(fh);
-
-       return res;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct s2255_fh *fh = priv;
-       dprintk(4, "%s\n, channel: %d", __func__, fh->channel->idx);
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               printk(KERN_ERR "invalid fh type0\n");
-               return -EINVAL;
-       }
-       if (i != fh->type) {
-               printk(KERN_ERR "invalid type i\n");
-               return -EINVAL;
-       }
-       s2255_stop_acquire(fh->channel);
-       videobuf_streamoff(&fh->vb_vidq);
-       res_free(fh);
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_mode mode;
-       struct videobuf_queue *q = &fh->vb_vidq;
-       int ret = 0;
-       mutex_lock(&q->vb_lock);
-       if (videobuf_queue_is_busy(q)) {
-               dprintk(1, "queue busy\n");
-               ret = -EBUSY;
-               goto out_s_std;
-       }
-       if (res_locked(fh)) {
-               dprintk(1, "can't change standard after started\n");
-               ret = -EBUSY;
-               goto out_s_std;
-       }
-       mode = fh->channel->mode;
-       if (*i & V4L2_STD_NTSC) {
-               dprintk(4, "%s NTSC\n", __func__);
-               /* if changing format, reset frame decimation/intervals */
-               if (mode.format != FORMAT_NTSC) {
-                       mode.restart = 1;
-                       mode.format = FORMAT_NTSC;
-                       mode.fdec = FDEC_1;
-               }
-       } else if (*i & V4L2_STD_PAL) {
-               dprintk(4, "%s PAL\n", __func__);
-               if (mode.format != FORMAT_PAL) {
-                       mode.restart = 1;
-                       mode.format = FORMAT_PAL;
-                       mode.fdec = FDEC_1;
-               }
-       } else {
-               ret = -EINVAL;
-       }
-       if (mode.restart)
-               s2255_set_mode(fh->channel, &mode);
-out_s_std:
-       mutex_unlock(&q->vb_lock);
-       return ret;
-}
-
-/* Sensoray 2255 is a multiple channel capture device.
-   It does not have a "crossbar" of inputs.
-   We use one V4L device per channel. The user must
-   be aware that certain combinations are not allowed.
-   For instance, you cannot do full FPS on more than 2 channels(2 videodevs)
-   at once in color(you can do full fps on 4 channels with greyscale.
-*/
-static int vidioc_enum_input(struct file *file, void *priv,
-                            struct v4l2_input *inp)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_dev *dev = fh->dev;
-       struct s2255_channel *channel = fh->channel;
-       u32 status = 0;
-       if (inp->index != 0)
-               return -EINVAL;
-       inp->type = V4L2_INPUT_TYPE_CAMERA;
-       inp->std = S2255_NORMS;
-       inp->status = 0;
-       if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) {
-               int rc;
-               rc = s2255_cmd_status(fh->channel, &status);
-               dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status);
-               if (rc == 0)
-                       inp->status =  (status & 0x01) ? 0
-                               : V4L2_IN_ST_NO_SIGNAL;
-       }
-       switch (dev->pid) {
-       case 0x2255:
-       default:
-               strlcpy(inp->name, "Composite", sizeof(inp->name));
-               break;
-       case 0x2257:
-               strlcpy(inp->name, (channel->idx < 2) ? "Composite" : "S-Video",
-                       sizeof(inp->name));
-               break;
-       }
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       if (i > 0)
-               return -EINVAL;
-       return 0;
-}
-
-/* --- controls ---------------------------------------------- */
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *qc)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-       struct s2255_dev *dev = fh->dev;
-       switch (qc->id) {
-       case V4L2_CID_BRIGHTNESS:
-               v4l2_ctrl_query_fill(qc, -127, 127, 1, DEF_BRIGHT);
-               break;
-       case V4L2_CID_CONTRAST:
-               v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_CONTRAST);
-               break;
-       case V4L2_CID_SATURATION:
-               v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_SATURATION);
-               break;
-       case V4L2_CID_HUE:
-               v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_HUE);
-               break;
-       case V4L2_CID_PRIVATE_COLORFILTER:
-               if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
-                       return -EINVAL;
-               if ((dev->pid == 0x2257) && (channel->idx > 1))
-                       return -EINVAL;
-               strlcpy(qc->name, "Color Filter", sizeof(qc->name));
-               qc->type = V4L2_CTRL_TYPE_MENU;
-               qc->minimum = 0;
-               qc->maximum = 1;
-               qc->step = 1;
-               qc->default_value = 1;
-               qc->flags = 0;
-               break;
-       default:
-               return -EINVAL;
-       }
-       dprintk(4, "%s, id %d\n", __func__, qc->id);
-       return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_dev *dev = fh->dev;
-       struct s2255_channel *channel = fh->channel;
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               ctrl->value = channel->mode.bright;
-               break;
-       case V4L2_CID_CONTRAST:
-               ctrl->value = channel->mode.contrast;
-               break;
-       case V4L2_CID_SATURATION:
-               ctrl->value = channel->mode.saturation;
-               break;
-       case V4L2_CID_HUE:
-               ctrl->value = channel->mode.hue;
-               break;
-       case V4L2_CID_PRIVATE_COLORFILTER:
-               if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
-                       return -EINVAL;
-               if ((dev->pid == 0x2257) && (channel->idx > 1))
-                       return -EINVAL;
-               ctrl->value = !((channel->mode.color & MASK_INPUT_TYPE) >> 16);
-               break;
-       default:
-               return -EINVAL;
-       }
-       dprintk(4, "%s, id %d val %d\n", __func__, ctrl->id, ctrl->value);
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-       struct s2255_mode mode;
-       mode = channel->mode;
-       dprintk(4, "%s\n", __func__);
-       /* update the mode to the corresponding value */
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               mode.bright = ctrl->value;
-               break;
-       case V4L2_CID_CONTRAST:
-               mode.contrast = ctrl->value;
-               break;
-       case V4L2_CID_HUE:
-               mode.hue = ctrl->value;
-               break;
-       case V4L2_CID_SATURATION:
-               mode.saturation = ctrl->value;
-               break;
-       case V4L2_CID_PRIVATE_COLORFILTER:
-               if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
-                       return -EINVAL;
-               if ((dev->pid == 0x2257) && (channel->idx > 1))
-                       return -EINVAL;
-               mode.color &= ~MASK_INPUT_TYPE;
-               mode.color |= ((ctrl->value ? 0 : 1) << 16);
-               break;
-       default:
-               return -EINVAL;
-       }
-       mode.restart = 0;
-       /* set mode here.  Note: stream does not need restarted.
-          some V4L programs restart stream unnecessarily
-          after a s_crtl.
-       */
-       s2255_set_mode(fh->channel, &mode);
-       return 0;
-}
-
-static int vidioc_g_jpegcomp(struct file *file, void *priv,
-                        struct v4l2_jpegcompression *jc)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-       *jc = channel->jc;
-       dprintk(2, "%s: quality %d\n", __func__, jc->quality);
-       return 0;
-}
-
-static int vidioc_s_jpegcomp(struct file *file, void *priv,
-                        struct v4l2_jpegcompression *jc)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-       if (jc->quality < 0 || jc->quality > 100)
-               return -EINVAL;
-       channel->jc.quality = jc->quality;
-       dprintk(2, "%s: quality %d\n", __func__, jc->quality);
-       return 0;
-}
-
-static int vidioc_g_parm(struct file *file, void *priv,
-                        struct v4l2_streamparm *sp)
-{
-       struct s2255_fh *fh = priv;
-       __u32 def_num, def_dem;
-       struct s2255_channel *channel = fh->channel;
-       if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       memset(sp, 0, sizeof(struct v4l2_streamparm));
-       sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
-       sp->parm.capture.capturemode = channel->cap_parm.capturemode;
-       def_num = (channel->mode.format == FORMAT_NTSC) ? 1001 : 1000;
-       def_dem = (channel->mode.format == FORMAT_NTSC) ? 30000 : 25000;
-       sp->parm.capture.timeperframe.denominator = def_dem;
-       switch (channel->mode.fdec) {
-       default:
-       case FDEC_1:
-               sp->parm.capture.timeperframe.numerator = def_num;
-               break;
-       case FDEC_2:
-               sp->parm.capture.timeperframe.numerator = def_num * 2;
-               break;
-       case FDEC_3:
-               sp->parm.capture.timeperframe.numerator = def_num * 3;
-               break;
-       case FDEC_5:
-               sp->parm.capture.timeperframe.numerator = def_num * 5;
-               break;
-       }
-       dprintk(4, "%s capture mode, %d timeperframe %d/%d\n", __func__,
-               sp->parm.capture.capturemode,
-               sp->parm.capture.timeperframe.numerator,
-               sp->parm.capture.timeperframe.denominator);
-       return 0;
-}
-
-static int vidioc_s_parm(struct file *file, void *priv,
-                        struct v4l2_streamparm *sp)
-{
-       struct s2255_fh *fh = priv;
-       struct s2255_channel *channel = fh->channel;
-       struct s2255_mode mode;
-       int fdec = FDEC_1;
-       __u32 def_num, def_dem;
-       if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       mode = channel->mode;
-       /* high quality capture mode requires a stream restart */
-       if (channel->cap_parm.capturemode
-           != sp->parm.capture.capturemode && res_locked(fh))
-               return -EBUSY;
-       def_num = (mode.format == FORMAT_NTSC) ? 1001 : 1000;
-       def_dem = (mode.format == FORMAT_NTSC) ? 30000 : 25000;
-       if (def_dem != sp->parm.capture.timeperframe.denominator)
-               sp->parm.capture.timeperframe.numerator = def_num;
-       else if (sp->parm.capture.timeperframe.numerator <= def_num)
-               sp->parm.capture.timeperframe.numerator = def_num;
-       else if (sp->parm.capture.timeperframe.numerator <= (def_num * 2)) {
-               sp->parm.capture.timeperframe.numerator = def_num * 2;
-               fdec = FDEC_2;
-       } else if (sp->parm.capture.timeperframe.numerator <= (def_num * 3)) {
-               sp->parm.capture.timeperframe.numerator = def_num * 3;
-               fdec = FDEC_3;
-       } else {
-               sp->parm.capture.timeperframe.numerator = def_num * 5;
-               fdec = FDEC_5;
-       }
-       mode.fdec = fdec;
-       sp->parm.capture.timeperframe.denominator = def_dem;
-       s2255_set_mode(channel, &mode);
-       dprintk(4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n",
-               __func__,
-               sp->parm.capture.capturemode,
-               sp->parm.capture.timeperframe.numerator,
-               sp->parm.capture.timeperframe.denominator, fdec);
-       return 0;
-}
-
-static int vidioc_enum_frameintervals(struct file *file, void *priv,
-                           struct v4l2_frmivalenum *fe)
-{
-       int is_ntsc = 0;
-#define NUM_FRAME_ENUMS 4
-       int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5};
-       if (fe->index < 0 || fe->index >= NUM_FRAME_ENUMS)
-               return -EINVAL;
-       switch (fe->width) {
-       case 640:
-               if (fe->height != 240 && fe->height != 480)
-                       return -EINVAL;
-               is_ntsc = 1;
-               break;
-       case 320:
-               if (fe->height != 240)
-                       return -EINVAL;
-               is_ntsc = 1;
-               break;
-       case 704:
-               if (fe->height != 288 && fe->height != 576)
-                       return -EINVAL;
-               break;
-       case 352:
-               if (fe->height != 288)
-                       return -EINVAL;
-               break;
-       default:
-               return -EINVAL;
-       }
-       fe->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-       fe->discrete.denominator = is_ntsc ? 30000 : 25000;
-       fe->discrete.numerator = (is_ntsc ? 1001 : 1000) * frm_dec[fe->index];
-       dprintk(4, "%s discrete %d/%d\n", __func__, fe->discrete.numerator,
-               fe->discrete.denominator);
-       return 0;
-}
-
-static int __s2255_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct s2255_channel *channel = video_drvdata(file);
-       struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
-       struct s2255_fh *fh;
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       int state;
-       dprintk(1, "s2255: open called (dev=%s)\n",
-               video_device_node_name(vdev));
-       state = atomic_read(&dev->fw_data->fw_state);
-       switch (state) {
-       case S2255_FW_DISCONNECTING:
-               return -ENODEV;
-       case S2255_FW_FAILED:
-               s2255_dev_err(&dev->udev->dev,
-                       "firmware load failed. retrying.\n");
-               s2255_fwload_start(dev, 1);
-               wait_event_timeout(dev->fw_data->wait_fw,
-                                  ((atomic_read(&dev->fw_data->fw_state)
-                                    == S2255_FW_SUCCESS) ||
-                                   (atomic_read(&dev->fw_data->fw_state)
-                                    == S2255_FW_DISCONNECTING)),
-                                  msecs_to_jiffies(S2255_LOAD_TIMEOUT));
-               /* state may have changed, re-read */
-               state = atomic_read(&dev->fw_data->fw_state);
-               break;
-       case S2255_FW_NOTLOADED:
-       case S2255_FW_LOADED_DSPWAIT:
-               /* give S2255_LOAD_TIMEOUT time for firmware to load in case
-                  driver loaded and then device immediately opened */
-               printk(KERN_INFO "%s waiting for firmware load\n", __func__);
-               wait_event_timeout(dev->fw_data->wait_fw,
-                                  ((atomic_read(&dev->fw_data->fw_state)
-                                    == S2255_FW_SUCCESS) ||
-                                   (atomic_read(&dev->fw_data->fw_state)
-                                    == S2255_FW_DISCONNECTING)),
-                                  msecs_to_jiffies(S2255_LOAD_TIMEOUT));
-               /* state may have changed, re-read */
-               state = atomic_read(&dev->fw_data->fw_state);
-               break;
-       case S2255_FW_SUCCESS:
-       default:
-               break;
-       }
-       /* state may have changed in above switch statement */
-       switch (state) {
-       case S2255_FW_SUCCESS:
-               break;
-       case S2255_FW_FAILED:
-               printk(KERN_INFO "2255 firmware load failed.\n");
-               return -ENODEV;
-       case S2255_FW_DISCONNECTING:
-               printk(KERN_INFO "%s: disconnecting\n", __func__);
-               return -ENODEV;
-       case S2255_FW_LOADED_DSPWAIT:
-       case S2255_FW_NOTLOADED:
-               printk(KERN_INFO "%s: firmware not loaded yet"
-                      "please try again later\n",
-                      __func__);
-               /*
-                * Timeout on firmware load means device unusable.
-                * Set firmware failure state.
-                * On next s2255_open the firmware will be reloaded.
-                */
-               atomic_set(&dev->fw_data->fw_state,
-                          S2255_FW_FAILED);
-               return -EAGAIN;
-       default:
-               printk(KERN_INFO "%s: unknown state\n", __func__);
-               return -EFAULT;
-       }
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
-               return -ENOMEM;
-       file->private_data = fh;
-       fh->dev = dev;
-       fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       fh->channel = channel;
-       if (!channel->configured) {
-               /* configure channel to default state */
-               channel->fmt = &formats[0];
-               s2255_set_mode(channel, &channel->mode);
-               channel->configured = 1;
-       }
-       dprintk(1, "%s: dev=%s type=%s\n", __func__,
-               video_device_node_name(vdev), v4l2_type_names[type]);
-       dprintk(2, "%s: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", __func__,
-               (unsigned long)fh, (unsigned long)dev,
-               (unsigned long)&channel->vidq);
-       dprintk(4, "%s: list_empty active=%d\n", __func__,
-               list_empty(&channel->vidq.active));
-       videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops,
-                                   NULL, &dev->slock,
-                                   fh->type,
-                                   V4L2_FIELD_INTERLACED,
-                                   sizeof(struct s2255_buffer),
-                                   fh, vdev->lock);
-       return 0;
-}
-
-static int s2255_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       int ret;
-
-       if (mutex_lock_interruptible(vdev->lock))
-               return -ERESTARTSYS;
-       ret = __s2255_open(file);
-       mutex_unlock(vdev->lock);
-       return ret;
-}
-
-static unsigned int s2255_poll(struct file *file,
-                              struct poll_table_struct *wait)
-{
-       struct s2255_fh *fh = file->private_data;
-       struct s2255_dev *dev = fh->dev;
-       int rc;
-       dprintk(100, "%s\n", __func__);
-       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
-               return POLLERR;
-       mutex_lock(&dev->lock);
-       rc = videobuf_poll_stream(file, &fh->vb_vidq, wait);
-       mutex_unlock(&dev->lock);
-       return rc;
-}
-
-static void s2255_destroy(struct s2255_dev *dev)
-{
-       /* board shutdown stops the read pipe if it is running */
-       s2255_board_shutdown(dev);
-       /* make sure firmware still not trying to load */
-       del_timer(&dev->timer);  /* only started in .probe and .open */
-       if (dev->fw_data->fw_urb) {
-               usb_kill_urb(dev->fw_data->fw_urb);
-               usb_free_urb(dev->fw_data->fw_urb);
-               dev->fw_data->fw_urb = NULL;
-       }
-       release_firmware(dev->fw_data->fw);
-       kfree(dev->fw_data->pfw_data);
-       kfree(dev->fw_data);
-       /* reset the DSP so firmware can be reloaded next time */
-       s2255_reset_dsppower(dev);
-       mutex_destroy(&dev->lock);
-       usb_put_dev(dev->udev);
-       v4l2_device_unregister(&dev->v4l2_dev);
-       dprintk(1, "%s", __func__);
-       kfree(dev);
-}
-
-static int s2255_release(struct file *file)
-{
-       struct s2255_fh *fh = file->private_data;
-       struct s2255_dev *dev = fh->dev;
-       struct video_device *vdev = video_devdata(file);
-       struct s2255_channel *channel = fh->channel;
-       if (!dev)
-               return -ENODEV;
-       mutex_lock(&dev->lock);
-       /* turn off stream */
-       if (res_check(fh)) {
-               if (channel->b_acquire)
-                       s2255_stop_acquire(fh->channel);
-               videobuf_streamoff(&fh->vb_vidq);
-               res_free(fh);
-       }
-       videobuf_mmap_free(&fh->vb_vidq);
-       mutex_unlock(&dev->lock);
-       dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev));
-       kfree(fh);
-       return 0;
-}
-
-static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma)
-{
-       struct s2255_fh *fh = file->private_data;
-       struct s2255_dev *dev = fh->dev;
-       int ret;
-
-       if (!fh)
-               return -ENODEV;
-       dprintk(4, "%s, vma=0x%08lx\n", __func__, (unsigned long)vma);
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
-       mutex_unlock(&dev->lock);
-       dprintk(4, "%s vma start=0x%08lx, size=%ld, ret=%d\n", __func__,
-               (unsigned long)vma->vm_start,
-               (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
-       return ret;
-}
-
-static const struct v4l2_file_operations s2255_fops_v4l = {
-       .owner = THIS_MODULE,
-       .open = s2255_open,
-       .release = s2255_release,
-       .poll = s2255_poll,
-       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-       .mmap = s2255_mmap_v4l,
-};
-
-static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
-       .vidioc_querymenu = vidioc_querymenu,
-       .vidioc_querycap = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
-       .vidioc_reqbufs = vidioc_reqbufs,
-       .vidioc_querybuf = vidioc_querybuf,
-       .vidioc_qbuf = vidioc_qbuf,
-       .vidioc_dqbuf = vidioc_dqbuf,
-       .vidioc_s_std = vidioc_s_std,
-       .vidioc_enum_input = vidioc_enum_input,
-       .vidioc_g_input = vidioc_g_input,
-       .vidioc_s_input = vidioc_s_input,
-       .vidioc_queryctrl = vidioc_queryctrl,
-       .vidioc_g_ctrl = vidioc_g_ctrl,
-       .vidioc_s_ctrl = vidioc_s_ctrl,
-       .vidioc_streamon = vidioc_streamon,
-       .vidioc_streamoff = vidioc_streamoff,
-       .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
-       .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
-       .vidioc_s_parm = vidioc_s_parm,
-       .vidioc_g_parm = vidioc_g_parm,
-       .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
-};
-
-static void s2255_video_device_release(struct video_device *vdev)
-{
-       struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
-       dprintk(4, "%s, chnls: %d \n", __func__,
-               atomic_read(&dev->num_channels));
-       if (atomic_dec_and_test(&dev->num_channels))
-               s2255_destroy(dev);
-       return;
-}
-
-static struct video_device template = {
-       .name = "s2255v",
-       .fops = &s2255_fops_v4l,
-       .ioctl_ops = &s2255_ioctl_ops,
-       .release = s2255_video_device_release,
-       .tvnorms = S2255_NORMS,
-       .current_norm = V4L2_STD_NTSC_M,
-};
-
-static int s2255_probe_v4l(struct s2255_dev *dev)
-{
-       int ret;
-       int i;
-       int cur_nr = video_nr;
-       struct s2255_channel *channel;
-       ret = v4l2_device_register(&dev->interface->dev, &dev->v4l2_dev);
-       if (ret)
-               return ret;
-       /* initialize all video 4 linux */
-       /* register 4 video devices */
-       for (i = 0; i < MAX_CHANNELS; i++) {
-               channel = &dev->channel[i];
-               INIT_LIST_HEAD(&channel->vidq.active);
-               channel->vidq.dev = dev;
-               /* register 4 video devices */
-               channel->vdev = template;
-               channel->vdev.lock = &dev->lock;
-               channel->vdev.v4l2_dev = &dev->v4l2_dev;
-               video_set_drvdata(&channel->vdev, channel);
-               if (video_nr == -1)
-                       ret = video_register_device(&channel->vdev,
-                                                   VFL_TYPE_GRABBER,
-                                                   video_nr);
-               else
-                       ret = video_register_device(&channel->vdev,
-                                                   VFL_TYPE_GRABBER,
-                                                   cur_nr + i);
-
-               if (ret) {
-                       dev_err(&dev->udev->dev,
-                               "failed to register video device!\n");
-                       break;
-               }
-               atomic_inc(&dev->num_channels);
-               v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
-                         video_device_node_name(&channel->vdev));
-
-       }
-       printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %s\n",
-              S2255_VERSION);
-       /* if no channels registered, return error and probe will fail*/
-       if (atomic_read(&dev->num_channels) == 0) {
-               v4l2_device_unregister(&dev->v4l2_dev);
-               return ret;
-       }
-       if (atomic_read(&dev->num_channels) != MAX_CHANNELS)
-               printk(KERN_WARNING "s2255: Not all channels available.\n");
-       return 0;
-}
-
-/* this function moves the usb stream read pipe data
- * into the system buffers.
- * returns 0 on success, EAGAIN if more data to process( call this
- * function again).
- *
- * Received frame structure:
- * bytes 0-3:  marker : 0x2255DA4AL (S2255_MARKER_FRAME)
- * bytes 4-7:  channel: 0-3
- * bytes 8-11: payload size:  size of the frame
- * bytes 12-payloadsize+12:  frame data
- */
-static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
-{
-       char *pdest;
-       u32 offset = 0;
-       int bframe = 0;
-       char *psrc;
-       unsigned long copy_size;
-       unsigned long size;
-       s32 idx = -1;
-       struct s2255_framei *frm;
-       unsigned char *pdata;
-       struct s2255_channel *channel;
-       dprintk(100, "buffer to user\n");
-       channel = &dev->channel[dev->cc];
-       idx = channel->cur_frame;
-       frm = &channel->buffer.frame[idx];
-       if (frm->ulState == S2255_READ_IDLE) {
-               int jj;
-               unsigned int cc;
-               __le32 *pdword; /*data from dsp is little endian */
-               int payload;
-               /* search for marker codes */
-               pdata = (unsigned char *)pipe_info->transfer_buffer;
-               pdword = (__le32 *)pdata;
-               for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) {
-                       switch (*pdword) {
-                       case S2255_MARKER_FRAME:
-                               dprintk(4, "found frame marker at offset:"
-                                       " %d [%x %x]\n", jj, pdata[0],
-                                       pdata[1]);
-                               offset = jj + PREFIX_SIZE;
-                               bframe = 1;
-                               cc = le32_to_cpu(pdword[1]);
-                               if (cc >= MAX_CHANNELS) {
-                                       printk(KERN_ERR
-                                              "bad channel\n");
-                                       return -EINVAL;
-                               }
-                               /* reverse it */
-                               dev->cc = G_chnmap[cc];
-                               channel = &dev->channel[dev->cc];
-                               payload =  le32_to_cpu(pdword[3]);
-                               if (payload > channel->req_image_size) {
-                                       channel->bad_payload++;
-                                       /* discard the bad frame */
-                                       return -EINVAL;
-                               }
-                               channel->pkt_size = payload;
-                               channel->jpg_size = le32_to_cpu(pdword[4]);
-                               break;
-                       case S2255_MARKER_RESPONSE:
-
-                               pdata += DEF_USB_BLOCK;
-                               jj += DEF_USB_BLOCK;
-                               if (le32_to_cpu(pdword[1]) >= MAX_CHANNELS)
-                                       break;
-                               cc = G_chnmap[le32_to_cpu(pdword[1])];
-                               if (cc >= MAX_CHANNELS)
-                                       break;
-                               channel = &dev->channel[cc];
-                               switch (pdword[2]) {
-                               case S2255_RESPONSE_SETMODE:
-                                       /* check if channel valid */
-                                       /* set mode ready */
-                                       channel->setmode_ready = 1;
-                                       wake_up(&channel->wait_setmode);
-                                       dprintk(5, "setmode ready %d\n", cc);
-                                       break;
-                               case S2255_RESPONSE_FW:
-                                       dev->chn_ready |= (1 << cc);
-                                       if ((dev->chn_ready & 0x0f) != 0x0f)
-                                               break;
-                                       /* all channels ready */
-                                       printk(KERN_INFO "s2255: fw loaded\n");
-                                       atomic_set(&dev->fw_data->fw_state,
-                                                  S2255_FW_SUCCESS);
-                                       wake_up(&dev->fw_data->wait_fw);
-                                       break;
-                               case S2255_RESPONSE_STATUS:
-                                       channel->vidstatus = le32_to_cpu(pdword[3]);
-                                       channel->vidstatus_ready = 1;
-                                       wake_up(&channel->wait_vidstatus);
-                                       dprintk(5, "got vidstatus %x chan %d\n",
-                                               le32_to_cpu(pdword[3]), cc);
-                                       break;
-                               default:
-                                       printk(KERN_INFO "s2255 unknown resp\n");
-                               }
-                       default:
-                               pdata++;
-                               break;
-                       }
-                       if (bframe)
-                               break;
-               } /* for */
-               if (!bframe)
-                       return -EINVAL;
-       }
-       channel = &dev->channel[dev->cc];
-       idx = channel->cur_frame;
-       frm = &channel->buffer.frame[idx];
-       /* search done.  now find out if should be acquiring on this channel */
-       if (!channel->b_acquire) {
-               /* we found a frame, but this channel is turned off */
-               frm->ulState = S2255_READ_IDLE;
-               return -EINVAL;
-       }
-
-       if (frm->ulState == S2255_READ_IDLE) {
-               frm->ulState = S2255_READ_FRAME;
-               frm->cur_size = 0;
-       }
-
-       /* skip the marker 512 bytes (and offset if out of sync) */
-       psrc = (u8 *)pipe_info->transfer_buffer + offset;
-
-
-       if (frm->lpvbits == NULL) {
-               dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d",
-                       frm, dev, dev->cc, idx);
-               return -ENOMEM;
-       }
-
-       pdest = frm->lpvbits + frm->cur_size;
-
-       copy_size = (pipe_info->cur_transfer_size - offset);
-
-       size = channel->pkt_size - PREFIX_SIZE;
-
-       /* sanity check on pdest */
-       if ((copy_size + frm->cur_size) < channel->req_image_size)
-               memcpy(pdest, psrc, copy_size);
-
-       frm->cur_size += copy_size;
-       dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size);
-
-       if (frm->cur_size >= size) {
-               dprintk(2, "****************[%d]Buffer[%d]full*************\n",
-                       dev->cc, idx);
-               channel->last_frame = channel->cur_frame;
-               channel->cur_frame++;
-               /* end of system frame ring buffer, start at zero */
-               if ((channel->cur_frame == SYS_FRAMES) ||
-                   (channel->cur_frame == channel->buffer.dwFrames))
-                       channel->cur_frame = 0;
-               /* frame ready */
-               if (channel->b_acquire)
-                       s2255_got_frame(channel, channel->jpg_size);
-               channel->frame_count++;
-               frm->ulState = S2255_READ_IDLE;
-               frm->cur_size = 0;
-
-       }
-       /* done successfully */
-       return 0;
-}
-
-static void s2255_read_video_callback(struct s2255_dev *dev,
-                                     struct s2255_pipeinfo *pipe_info)
-{
-       int res;
-       dprintk(50, "callback read video \n");
-
-       if (dev->cc >= MAX_CHANNELS) {
-               dev->cc = 0;
-               dev_err(&dev->udev->dev, "invalid channel\n");
-               return;
-       }
-       /* otherwise copy to the system buffers */
-       res = save_frame(dev, pipe_info);
-       if (res != 0)
-               dprintk(4, "s2255: read callback failed\n");
-
-       dprintk(50, "callback read video done\n");
-       return;
-}
-
-static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
-                            u16 Index, u16 Value, void *TransferBuffer,
-                            s32 TransferBufferLength, int bOut)
-{
-       int r;
-       if (!bOut) {
-               r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-                                   Request,
-                                   USB_TYPE_VENDOR | USB_RECIP_DEVICE |
-                                   USB_DIR_IN,
-                                   Value, Index, TransferBuffer,
-                                   TransferBufferLength, HZ * 5);
-       } else {
-               r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-                                   Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                                   Value, Index, TransferBuffer,
-                                   TransferBufferLength, HZ * 5);
-       }
-       return r;
-}
-
-/*
- * retrieve FX2 firmware version. future use.
- * @param dev pointer to device extension
- * @return -1 for fail, else returns firmware version as an int(16 bits)
- */
-static int s2255_get_fx2fw(struct s2255_dev *dev)
-{
-       int fw;
-       int ret;
-       unsigned char transBuffer[64];
-       ret = s2255_vendor_req(dev, S2255_VR_FW, 0, 0, transBuffer, 2,
-                              S2255_VR_IN);
-       if (ret < 0)
-               dprintk(2, "get fw error: %x\n", ret);
-       fw = transBuffer[0] + (transBuffer[1] << 8);
-       dprintk(2, "Get FW %x %x\n", transBuffer[0], transBuffer[1]);
-       return fw;
-}
-
-/*
- * Create the system ring buffer to copy frames into from the
- * usb read pipe.
- */
-static int s2255_create_sys_buffers(struct s2255_channel *channel)
-{
-       unsigned long i;
-       unsigned long reqsize;
-       dprintk(1, "create sys buffers\n");
-       channel->buffer.dwFrames = SYS_FRAMES;
-       /* always allocate maximum size(PAL) for system buffers */
-       reqsize = SYS_FRAMES_MAXSIZE;
-
-       if (reqsize > SYS_FRAMES_MAXSIZE)
-               reqsize = SYS_FRAMES_MAXSIZE;
-
-       for (i = 0; i < SYS_FRAMES; i++) {
-               /* allocate the frames */
-               channel->buffer.frame[i].lpvbits = vmalloc(reqsize);
-               dprintk(1, "valloc %p chan %d, idx %lu, pdata %p\n",
-                       &channel->buffer.frame[i], channel->idx, i,
-                       channel->buffer.frame[i].lpvbits);
-               channel->buffer.frame[i].size = reqsize;
-               if (channel->buffer.frame[i].lpvbits == NULL) {
-                       printk(KERN_INFO "out of memory.  using less frames\n");
-                       channel->buffer.dwFrames = i;
-                       break;
-               }
-       }
-
-       /* make sure internal states are set */
-       for (i = 0; i < SYS_FRAMES; i++) {
-               channel->buffer.frame[i].ulState = 0;
-               channel->buffer.frame[i].cur_size = 0;
-       }
-
-       channel->cur_frame = 0;
-       channel->last_frame = -1;
-       return 0;
-}
-
-static int s2255_release_sys_buffers(struct s2255_channel *channel)
-{
-       unsigned long i;
-       dprintk(1, "release sys buffers\n");
-       for (i = 0; i < SYS_FRAMES; i++) {
-               if (channel->buffer.frame[i].lpvbits) {
-                       dprintk(1, "vfree %p\n",
-                               channel->buffer.frame[i].lpvbits);
-                       vfree(channel->buffer.frame[i].lpvbits);
-               }
-               channel->buffer.frame[i].lpvbits = NULL;
-       }
-       return 0;
-}
-
-static int s2255_board_init(struct s2255_dev *dev)
-{
-       struct s2255_mode mode_def = DEF_MODEI_NTSC_CONT;
-       int fw_ver;
-       int j;
-       struct s2255_pipeinfo *pipe = &dev->pipe;
-       dprintk(4, "board init: %p", dev);
-       memset(pipe, 0, sizeof(*pipe));
-       pipe->dev = dev;
-       pipe->cur_transfer_size = S2255_USB_XFER_SIZE;
-       pipe->max_transfer_size = S2255_USB_XFER_SIZE;
-
-       pipe->transfer_buffer = kzalloc(pipe->max_transfer_size,
-                                       GFP_KERNEL);
-       if (pipe->transfer_buffer == NULL) {
-               dprintk(1, "out of memory!\n");
-               return -ENOMEM;
-       }
-       /* query the firmware */
-       fw_ver = s2255_get_fx2fw(dev);
-
-       printk(KERN_INFO "s2255: usb firmware version %d.%d\n",
-              (fw_ver >> 8) & 0xff,
-              fw_ver & 0xff);
-
-       if (fw_ver < S2255_CUR_USB_FWVER)
-               printk(KERN_INFO "s2255: newer USB firmware available\n");
-
-       for (j = 0; j < MAX_CHANNELS; j++) {
-               struct s2255_channel *channel = &dev->channel[j];
-               channel->b_acquire = 0;
-               channel->mode = mode_def;
-               if (dev->pid == 0x2257 && j > 1)
-                       channel->mode.color |= (1 << 16);
-               channel->jc.quality = S2255_DEF_JPEG_QUAL;
-               channel->width = LINE_SZ_4CIFS_NTSC;
-               channel->height = NUM_LINES_4CIFS_NTSC * 2;
-               channel->fmt = &formats[0];
-               channel->mode.restart = 1;
-               channel->req_image_size = get_transfer_size(&mode_def);
-               channel->frame_count = 0;
-               /* create the system buffers */
-               s2255_create_sys_buffers(channel);
-       }
-       /* start read pipe */
-       s2255_start_readpipe(dev);
-       dprintk(1, "%s: success\n", __func__);
-       return 0;
-}
-
-static int s2255_board_shutdown(struct s2255_dev *dev)
-{
-       u32 i;
-       dprintk(1, "%s: dev: %p", __func__,  dev);
-
-       for (i = 0; i < MAX_CHANNELS; i++) {
-               if (dev->channel[i].b_acquire)
-                       s2255_stop_acquire(&dev->channel[i]);
-       }
-       s2255_stop_readpipe(dev);
-       for (i = 0; i < MAX_CHANNELS; i++)
-               s2255_release_sys_buffers(&dev->channel[i]);
-       /* release transfer buffer */
-       kfree(dev->pipe.transfer_buffer);
-       return 0;
-}
-
-static void read_pipe_completion(struct urb *purb)
-{
-       struct s2255_pipeinfo *pipe_info;
-       struct s2255_dev *dev;
-       int status;
-       int pipe;
-       pipe_info = purb->context;
-       dprintk(100, "%s: urb:%p, status %d\n", __func__, purb,
-               purb->status);
-       if (pipe_info == NULL) {
-               dev_err(&purb->dev->dev, "no context!\n");
-               return;
-       }
-
-       dev = pipe_info->dev;
-       if (dev == NULL) {
-               dev_err(&purb->dev->dev, "no context!\n");
-               return;
-       }
-       status = purb->status;
-       /* if shutting down, do not resubmit, exit immediately */
-       if (status == -ESHUTDOWN) {
-               dprintk(2, "%s: err shutdown\n", __func__);
-               pipe_info->err_count++;
-               return;
-       }
-
-       if (pipe_info->state == 0) {
-               dprintk(2, "%s: exiting USB pipe", __func__);
-               return;
-       }
-
-       if (status == 0)
-               s2255_read_video_callback(dev, pipe_info);
-       else {
-               pipe_info->err_count++;
-               dprintk(1, "%s: failed URB %d\n", __func__, status);
-       }
-
-       pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
-       /* reuse urb */
-       usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
-                         pipe,
-                         pipe_info->transfer_buffer,
-                         pipe_info->cur_transfer_size,
-                         read_pipe_completion, pipe_info);
-
-       if (pipe_info->state != 0) {
-               if (usb_submit_urb(pipe_info->stream_urb, GFP_ATOMIC)) {
-                       dev_err(&dev->udev->dev, "error submitting urb\n");
-               }
-       } else {
-               dprintk(2, "%s :complete state 0\n", __func__);
-       }
-       return;
-}
-
-static int s2255_start_readpipe(struct s2255_dev *dev)
-{
-       int pipe;
-       int retval;
-       struct s2255_pipeinfo *pipe_info = &dev->pipe;
-       pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
-       dprintk(2, "%s: IN %d\n", __func__, dev->read_endpoint);
-       pipe_info->state = 1;
-       pipe_info->err_count = 0;
-       pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!pipe_info->stream_urb) {
-               dev_err(&dev->udev->dev,
-                       "ReadStream: Unable to alloc URB\n");
-               return -ENOMEM;
-       }
-       /* transfer buffer allocated in board_init */
-       usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
-                         pipe,
-                         pipe_info->transfer_buffer,
-                         pipe_info->cur_transfer_size,
-                         read_pipe_completion, pipe_info);
-       retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
-       if (retval) {
-               printk(KERN_ERR "s2255: start read pipe failed\n");
-               return retval;
-       }
-       return 0;
-}
-
-/* starts acquisition process */
-static int s2255_start_acquire(struct s2255_channel *channel)
-{
-       unsigned char *buffer;
-       int res;
-       unsigned long chn_rev;
-       int j;
-       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-       chn_rev = G_chnmap[channel->idx];
-       buffer = kzalloc(512, GFP_KERNEL);
-       if (buffer == NULL) {
-               dev_err(&dev->udev->dev, "out of mem\n");
-               return -ENOMEM;
-       }
-
-       channel->last_frame = -1;
-       channel->bad_payload = 0;
-       channel->cur_frame = 0;
-       for (j = 0; j < SYS_FRAMES; j++) {
-               channel->buffer.frame[j].ulState = 0;
-               channel->buffer.frame[j].cur_size = 0;
-       }
-
-       /* send the start command */
-       *(__le32 *) buffer = IN_DATA_TOKEN;
-       *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev);
-       *((__le32 *) buffer + 2) = CMD_START;
-       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
-       if (res != 0)
-               dev_err(&dev->udev->dev, "CMD_START error\n");
-
-       dprintk(2, "start acquire exit[%d] %d \n", channel->idx, res);
-       kfree(buffer);
-       return 0;
-}
-
-static int s2255_stop_acquire(struct s2255_channel *channel)
-{
-       unsigned char *buffer;
-       int res;
-       unsigned long chn_rev;
-       struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-       chn_rev = G_chnmap[channel->idx];
-       buffer = kzalloc(512, GFP_KERNEL);
-       if (buffer == NULL) {
-               dev_err(&dev->udev->dev, "out of mem\n");
-               return -ENOMEM;
-       }
-       /* send the stop command */
-       *(__le32 *) buffer = IN_DATA_TOKEN;
-       *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev);
-       *((__le32 *) buffer + 2) = CMD_STOP;
-       res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
-       if (res != 0)
-               dev_err(&dev->udev->dev, "CMD_STOP error\n");
-       kfree(buffer);
-       channel->b_acquire = 0;
-       dprintk(4, "%s: chn %d, res %d\n", __func__, channel->idx, res);
-       return res;
-}
-
-static void s2255_stop_readpipe(struct s2255_dev *dev)
-{
-       struct s2255_pipeinfo *pipe = &dev->pipe;
-
-       pipe->state = 0;
-       if (pipe->stream_urb) {
-               /* cancel urb */
-               usb_kill_urb(pipe->stream_urb);
-               usb_free_urb(pipe->stream_urb);
-               pipe->stream_urb = NULL;
-       }
-       dprintk(4, "%s", __func__);
-       return;
-}
-
-static void s2255_fwload_start(struct s2255_dev *dev, int reset)
-{
-       if (reset)
-               s2255_reset_dsppower(dev);
-       dev->fw_data->fw_size = dev->fw_data->fw->size;
-       atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED);
-       memcpy(dev->fw_data->pfw_data,
-              dev->fw_data->fw->data, CHUNK_SIZE);
-       dev->fw_data->fw_loaded = CHUNK_SIZE;
-       usb_fill_bulk_urb(dev->fw_data->fw_urb, dev->udev,
-                         usb_sndbulkpipe(dev->udev, 2),
-                         dev->fw_data->pfw_data,
-                         CHUNK_SIZE, s2255_fwchunk_complete,
-                         dev->fw_data);
-       mod_timer(&dev->timer, jiffies + HZ);
-}
-
-/* standard usb probe function */
-static int s2255_probe(struct usb_interface *interface,
-                      const struct usb_device_id *id)
-{
-       struct s2255_dev *dev = NULL;
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-       int i;
-       int retval = -ENOMEM;
-       __le32 *pdata;
-       int fw_size;
-       dprintk(2, "%s\n", __func__);
-       /* allocate memory for our device state and initialize it to zero */
-       dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
-       if (dev == NULL) {
-               s2255_dev_err(&interface->dev, "out of memory\n");
-               return -ENOMEM;
-       }
-       atomic_set(&dev->num_channels, 0);
-       dev->pid = id->idProduct;
-       dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
-       if (!dev->fw_data)
-               goto errorFWDATA1;
-       mutex_init(&dev->lock);
-       /* grab usb_device and save it */
-       dev->udev = usb_get_dev(interface_to_usbdev(interface));
-       if (dev->udev == NULL) {
-               dev_err(&interface->dev, "null usb device\n");
-               retval = -ENODEV;
-               goto errorUDEV;
-       }
-       dprintk(1, "dev: %p, udev %p interface %p\n", dev,
-               dev->udev, interface);
-       dev->interface = interface;
-       /* set up the endpoint information  */
-       iface_desc = interface->cur_altsetting;
-       dprintk(1, "num endpoints %d\n", iface_desc->desc.bNumEndpoints);
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-               endpoint = &iface_desc->endpoint[i].desc;
-               if (!dev->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
-                       /* we found the bulk in endpoint */
-                       dev->read_endpoint = endpoint->bEndpointAddress;
-               }
-       }
-
-       if (!dev->read_endpoint) {
-               dev_err(&interface->dev, "Could not find bulk-in endpoint\n");
-               goto errorEP;
-       }
-       init_timer(&dev->timer);
-       dev->timer.function = s2255_timer;
-       dev->timer.data = (unsigned long)dev->fw_data;
-       init_waitqueue_head(&dev->fw_data->wait_fw);
-       for (i = 0; i < MAX_CHANNELS; i++) {
-               struct s2255_channel *channel = &dev->channel[i];
-               dev->channel[i].idx = i;
-               init_waitqueue_head(&channel->wait_setmode);
-               init_waitqueue_head(&channel->wait_vidstatus);
-       }
-
-       dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!dev->fw_data->fw_urb) {
-               dev_err(&interface->dev, "out of memory!\n");
-               goto errorFWURB;
-       }
-
-       dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL);
-       if (!dev->fw_data->pfw_data) {
-               dev_err(&interface->dev, "out of memory!\n");
-               goto errorFWDATA2;
-       }
-       /* load the first chunk */
-       if (request_firmware(&dev->fw_data->fw,
-                            FIRMWARE_FILE_NAME, &dev->udev->dev)) {
-               printk(KERN_ERR "sensoray 2255 failed to get firmware\n");
-               goto errorREQFW;
-       }
-       /* check the firmware is valid */
-       fw_size = dev->fw_data->fw->size;
-       pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
-
-       if (*pdata != S2255_FW_MARKER) {
-               printk(KERN_INFO "Firmware invalid.\n");
-               retval = -ENODEV;
-               goto errorFWMARKER;
-       } else {
-               /* make sure firmware is the latest */
-               __le32 *pRel;
-               pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
-               printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
-               dev->dsp_fw_ver = le32_to_cpu(*pRel);
-               if (dev->dsp_fw_ver < S2255_CUR_DSP_FWVER)
-                       printk(KERN_INFO "s2255: f2255usb.bin out of date.\n");
-               if (dev->pid == 0x2257 &&
-                               dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
-                       printk(KERN_WARNING "s2255: 2257 requires firmware %d"
-                              " or above.\n", S2255_MIN_DSP_COLORFILTER);
-       }
-       usb_reset_device(dev->udev);
-       /* load 2255 board specific */
-       retval = s2255_board_init(dev);
-       if (retval)
-               goto errorBOARDINIT;
-       spin_lock_init(&dev->slock);
-       s2255_fwload_start(dev, 0);
-       /* loads v4l specific */
-       retval = s2255_probe_v4l(dev);
-       if (retval)
-               goto errorBOARDINIT;
-       dev_info(&interface->dev, "Sensoray 2255 detected\n");
-       return 0;
-errorBOARDINIT:
-       s2255_board_shutdown(dev);
-errorFWMARKER:
-       release_firmware(dev->fw_data->fw);
-errorREQFW:
-       kfree(dev->fw_data->pfw_data);
-errorFWDATA2:
-       usb_free_urb(dev->fw_data->fw_urb);
-errorFWURB:
-       del_timer(&dev->timer);
-errorEP:
-       usb_put_dev(dev->udev);
-errorUDEV:
-       kfree(dev->fw_data);
-       mutex_destroy(&dev->lock);
-errorFWDATA1:
-       kfree(dev);
-       printk(KERN_WARNING "Sensoray 2255 driver load failed: 0x%x\n", retval);
-       return retval;
-}
-
-/* disconnect routine. when board is removed physically or with rmmod */
-static void s2255_disconnect(struct usb_interface *interface)
-{
-       struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface));
-       int i;
-       int channels = atomic_read(&dev->num_channels);
-       mutex_lock(&dev->lock);
-       v4l2_device_disconnect(&dev->v4l2_dev);
-       mutex_unlock(&dev->lock);
-       /*see comments in the uvc_driver.c usb disconnect function */
-       atomic_inc(&dev->num_channels);
-       /* unregister each video device. */
-       for (i = 0; i < channels; i++)
-               video_unregister_device(&dev->channel[i].vdev);
-       /* wake up any of our timers */
-       atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
-       wake_up(&dev->fw_data->wait_fw);
-       for (i = 0; i < MAX_CHANNELS; i++) {
-               dev->channel[i].setmode_ready = 1;
-               wake_up(&dev->channel[i].wait_setmode);
-               dev->channel[i].vidstatus_ready = 1;
-               wake_up(&dev->channel[i].wait_vidstatus);
-       }
-       if (atomic_dec_and_test(&dev->num_channels))
-               s2255_destroy(dev);
-       dev_info(&interface->dev, "%s\n", __func__);
-}
-
-static struct usb_driver s2255_driver = {
-       .name = S2255_DRIVER_NAME,
-       .probe = s2255_probe,
-       .disconnect = s2255_disconnect,
-       .id_table = s2255_table,
-};
-
-module_usb_driver(s2255_driver);
-
-MODULE_DESCRIPTION("Sensoray 2255 Video for Linux driver");
-MODULE_AUTHOR("Dean Anderson (Sensoray Company Inc.)");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(S2255_VERSION);
-MODULE_FIRMWARE(FIRMWARE_FILE_NAME);
diff --git a/drivers/media/video/stk-sensor.c b/drivers/media/video/stk-sensor.c
deleted file mode 100644 (file)
index e546b01..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-/* stk-sensor.c: Driver for ov96xx sensor (used in some Syntek webcams)
- *
- * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com>
- *
- * Some parts derived from ov7670.c:
- * Copyright 2006 One Laptop Per Child Association, Inc.  Written
- * by Jonathan Corbet with substantial inspiration from Mark
- * McClelland's ovcamchip code.
- *
- * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
- *
- * This file may be distributed under the terms of the GNU General
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Controlling the sensor via the STK1125 vendor specific control interface:
- * The camera uses an OmniVision sensor and the stk1125 provides an
- * SCCB(i2c)-USB bridge which let us program the sensor.
- * In my case the sensor id is 0x9652, it can be read from sensor's register
- * 0x0A and 0x0B as follows:
- * - read register #R:
- *   output #R to index 0x0208
- *   output 0x0070 to index 0x0200
- *   input 1 byte from index 0x0201 (some kind of status register)
- *     until its value is 0x01
- *   input 1 byte from index 0x0209. This is the value of #R
- * - write value V to register #R
- *   output #R to index 0x0204
- *   output V to index 0x0205
- *   output 0x0005 to index 0x0200
- *   input 1 byte from index 0x0201 until its value becomes 0x04
- */
-
-/* It seems the i2c bus is controlled with these registers */
-
-#include "stk-webcam.h"
-
-#define STK_IIC_BASE           (0x0200)
-#  define STK_IIC_OP           (STK_IIC_BASE)
-#    define STK_IIC_OP_TX      (0x05)
-#    define STK_IIC_OP_RX      (0x70)
-#  define STK_IIC_STAT         (STK_IIC_BASE+1)
-#    define STK_IIC_STAT_TX_OK (0x04)
-#    define STK_IIC_STAT_RX_OK (0x01)
-/* I don't know what does this register.
- * when it is 0x00 or 0x01, we cannot talk to the sensor,
- * other values work */
-#  define STK_IIC_ENABLE       (STK_IIC_BASE+2)
-#    define STK_IIC_ENABLE_NO  (0x00)
-/* This is what the driver writes in windows */
-#    define STK_IIC_ENABLE_YES (0x1e)
-/*
- * Address of the slave. Seems like the binary driver look for the
- * sensor in multiple places, attempting a reset sequence.
- * We only know about the ov9650
- */
-#  define STK_IIC_ADDR         (STK_IIC_BASE+3)
-#  define STK_IIC_TX_INDEX     (STK_IIC_BASE+4)
-#  define STK_IIC_TX_VALUE     (STK_IIC_BASE+5)
-#  define STK_IIC_RX_INDEX     (STK_IIC_BASE+8)
-#  define STK_IIC_RX_VALUE     (STK_IIC_BASE+9)
-
-#define MAX_RETRIES            (50)
-
-#define SENSOR_ADDRESS         (0x60)
-
-/* From ov7670.c (These registers aren't fully accurate) */
-
-/* Registers */
-#define REG_GAIN       0x00    /* Gain lower 8 bits (rest in vref) */
-#define REG_BLUE       0x01    /* blue gain */
-#define REG_RED                0x02    /* red gain */
-#define REG_VREF       0x03    /* Pieces of GAIN, VSTART, VSTOP */
-#define REG_COM1       0x04    /* Control 1 */
-#define  COM1_CCIR656    0x40  /* CCIR656 enable */
-#define  COM1_QFMT       0x20  /* QVGA/QCIF format */
-#define  COM1_SKIP_0     0x00  /* Do not skip any row */
-#define  COM1_SKIP_2     0x04  /* Skip 2 rows of 4 */
-#define  COM1_SKIP_3     0x08  /* Skip 3 rows of 4 */
-#define REG_BAVE       0x05    /* U/B Average level */
-#define REG_GbAVE      0x06    /* Y/Gb Average level */
-#define REG_AECHH      0x07    /* AEC MS 5 bits */
-#define REG_RAVE       0x08    /* V/R Average level */
-#define REG_COM2       0x09    /* Control 2 */
-#define  COM2_SSLEEP     0x10  /* Soft sleep mode */
-#define REG_PID                0x0a    /* Product ID MSB */
-#define REG_VER                0x0b    /* Product ID LSB */
-#define REG_COM3       0x0c    /* Control 3 */
-#define  COM3_SWAP       0x40    /* Byte swap */
-#define  COM3_SCALEEN    0x08    /* Enable scaling */
-#define  COM3_DCWEN      0x04    /* Enable downsamp/crop/window */
-#define REG_COM4       0x0d    /* Control 4 */
-#define REG_COM5       0x0e    /* All "reserved" */
-#define REG_COM6       0x0f    /* Control 6 */
-#define REG_AECH       0x10    /* More bits of AEC value */
-#define REG_CLKRC      0x11    /* Clock control */
-#define   CLK_PLL        0x80    /* Enable internal PLL */
-#define   CLK_EXT        0x40    /* Use external clock directly */
-#define   CLK_SCALE      0x3f    /* Mask for internal clock scale */
-#define REG_COM7       0x12    /* Control 7 */
-#define   COM7_RESET     0x80    /* Register reset */
-#define   COM7_FMT_MASK          0x38
-#define   COM7_FMT_SXGA          0x00
-#define   COM7_FMT_VGA   0x40
-#define          COM7_FMT_CIF    0x20    /* CIF format */
-#define   COM7_FMT_QVGA          0x10    /* QVGA format */
-#define   COM7_FMT_QCIF          0x08    /* QCIF format */
-#define          COM7_RGB        0x04    /* bits 0 and 2 - RGB format */
-#define          COM7_YUV        0x00    /* YUV */
-#define          COM7_BAYER      0x01    /* Bayer format */
-#define          COM7_PBAYER     0x05    /* "Processed bayer" */
-#define REG_COM8       0x13    /* Control 8 */
-#define   COM8_FASTAEC   0x80    /* Enable fast AGC/AEC */
-#define   COM8_AECSTEP   0x40    /* Unlimited AEC step size */
-#define   COM8_BFILT     0x20    /* Band filter enable */
-#define   COM8_AGC       0x04    /* Auto gain enable */
-#define   COM8_AWB       0x02    /* White balance enable */
-#define   COM8_AEC       0x01    /* Auto exposure enable */
-#define REG_COM9       0x14    /* Control 9  - gain ceiling */
-#define REG_COM10      0x15    /* Control 10 */
-#define   COM10_HSYNC    0x40    /* HSYNC instead of HREF */
-#define   COM10_PCLK_HB          0x20    /* Suppress PCLK on horiz blank */
-#define   COM10_HREF_REV  0x08   /* Reverse HREF */
-#define   COM10_VS_LEAD          0x04    /* VSYNC on clock leading edge */
-#define   COM10_VS_NEG   0x02    /* VSYNC negative */
-#define   COM10_HS_NEG   0x01    /* HSYNC negative */
-#define REG_HSTART     0x17    /* Horiz start high bits */
-#define REG_HSTOP      0x18    /* Horiz stop high bits */
-#define REG_VSTART     0x19    /* Vert start high bits */
-#define REG_VSTOP      0x1a    /* Vert stop high bits */
-#define REG_PSHFT      0x1b    /* Pixel delay after HREF */
-#define REG_MIDH       0x1c    /* Manuf. ID high */
-#define REG_MIDL       0x1d    /* Manuf. ID low */
-#define REG_MVFP       0x1e    /* Mirror / vflip */
-#define   MVFP_MIRROR    0x20    /* Mirror image */
-#define   MVFP_FLIP      0x10    /* Vertical flip */
-
-#define REG_AEW                0x24    /* AGC upper limit */
-#define REG_AEB                0x25    /* AGC lower limit */
-#define REG_VPT                0x26    /* AGC/AEC fast mode op region */
-#define REG_ADVFL      0x2d    /* Insert dummy lines (LSB) */
-#define REG_ADVFH      0x2e    /* Insert dummy lines (MSB) */
-#define REG_HSYST      0x30    /* HSYNC rising edge delay */
-#define REG_HSYEN      0x31    /* HSYNC falling edge delay */
-#define REG_HREF       0x32    /* HREF pieces */
-#define REG_TSLB       0x3a    /* lots of stuff */
-#define   TSLB_YLAST     0x04    /* UYVY or VYUY - see com13 */
-#define   TSLB_BYTEORD   0x08    /* swap bytes in 16bit mode? */
-#define REG_COM11      0x3b    /* Control 11 */
-#define   COM11_NIGHT    0x80    /* NIght mode enable */
-#define   COM11_NMFR     0x60    /* Two bit NM frame rate */
-#define   COM11_HZAUTO   0x10    /* Auto detect 50/60 Hz */
-#define          COM11_50HZ      0x08    /* Manual 50Hz select */
-#define   COM11_EXP      0x02
-#define REG_COM12      0x3c    /* Control 12 */
-#define   COM12_HREF     0x80    /* HREF always */
-#define REG_COM13      0x3d    /* Control 13 */
-#define   COM13_GAMMA    0x80    /* Gamma enable */
-#define          COM13_UVSAT     0x40    /* UV saturation auto adjustment */
-#define          COM13_CMATRIX   0x10    /* Enable color matrix for RGB or YUV */
-#define   COM13_UVSWAP   0x01    /* V before U - w/TSLB */
-#define REG_COM14      0x3e    /* Control 14 */
-#define   COM14_DCWEN    0x10    /* DCW/PCLK-scale enable */
-#define REG_EDGE       0x3f    /* Edge enhancement factor */
-#define REG_COM15      0x40    /* Control 15 */
-#define   COM15_R10F0    0x00    /* Data range 10 to F0 */
-#define          COM15_R01FE     0x80    /*            01 to FE */
-#define   COM15_R00FF    0xc0    /*            00 to FF */
-#define   COM15_RGB565   0x10    /* RGB565 output */
-#define   COM15_RGBFIXME         0x20    /* FIXME  */
-#define   COM15_RGB555   0x30    /* RGB555 output */
-#define REG_COM16      0x41    /* Control 16 */
-#define   COM16_AWBGAIN   0x08   /* AWB gain enable */
-#define REG_COM17      0x42    /* Control 17 */
-#define   COM17_AECWIN   0xc0    /* AEC window - must match COM4 */
-#define   COM17_CBAR     0x08    /* DSP Color bar */
-
-/*
- * This matrix defines how the colors are generated, must be
- * tweaked to adjust hue and saturation.
- *
- * Order: v-red, v-green, v-blue, u-red, u-green, u-blue
- *
- * They are nine-bit signed quantities, with the sign bit
- * stored in 0x58.  Sign for v-red is bit 0, and up from there.
- */
-#define        REG_CMATRIX_BASE 0x4f
-#define   CMATRIX_LEN 6
-#define REG_CMATRIX_SIGN 0x58
-
-
-#define REG_BRIGHT     0x55    /* Brightness */
-#define REG_CONTRAS    0x56    /* Contrast control */
-
-#define REG_GFIX       0x69    /* Fix gain control */
-
-#define REG_RGB444     0x8c    /* RGB 444 control */
-#define   R444_ENABLE    0x02    /* Turn on RGB444, overrides 5x5 */
-#define   R444_RGBX      0x01    /* Empty nibble at end */
-
-#define REG_HAECC1     0x9f    /* Hist AEC/AGC control 1 */
-#define REG_HAECC2     0xa0    /* Hist AEC/AGC control 2 */
-
-#define REG_BD50MAX    0xa5    /* 50hz banding step limit */
-#define REG_HAECC3     0xa6    /* Hist AEC/AGC control 3 */
-#define REG_HAECC4     0xa7    /* Hist AEC/AGC control 4 */
-#define REG_HAECC5     0xa8    /* Hist AEC/AGC control 5 */
-#define REG_HAECC6     0xa9    /* Hist AEC/AGC control 6 */
-#define REG_HAECC7     0xaa    /* Hist AEC/AGC control 7 */
-#define REG_BD60MAX    0xab    /* 60hz banding step limit */
-
-
-
-
-/* Returns 0 if OK */
-static int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val)
-{
-       int i = 0;
-       int tmpval = 0;
-
-       if (stk_camera_write_reg(dev, STK_IIC_TX_INDEX, reg))
-               return 1;
-       if (stk_camera_write_reg(dev, STK_IIC_TX_VALUE, val))
-               return 1;
-       if (stk_camera_write_reg(dev, STK_IIC_OP, STK_IIC_OP_TX))
-               return 1;
-       do {
-               if (stk_camera_read_reg(dev, STK_IIC_STAT, &tmpval))
-                       return 1;
-               i++;
-       } while (tmpval == 0 && i < MAX_RETRIES);
-       if (tmpval != STK_IIC_STAT_TX_OK) {
-               if (tmpval)
-                       STK_ERROR("stk_sensor_outb failed, status=0x%02x\n",
-                               tmpval);
-               return 1;
-       } else
-               return 0;
-}
-
-static int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val)
-{
-       int i = 0;
-       int tmpval = 0;
-
-       if (stk_camera_write_reg(dev, STK_IIC_RX_INDEX, reg))
-               return 1;
-       if (stk_camera_write_reg(dev, STK_IIC_OP, STK_IIC_OP_RX))
-               return 1;
-       do {
-               if (stk_camera_read_reg(dev, STK_IIC_STAT, &tmpval))
-                       return 1;
-               i++;
-       } while (tmpval == 0 && i < MAX_RETRIES);
-       if (tmpval != STK_IIC_STAT_RX_OK) {
-               if (tmpval)
-                       STK_ERROR("stk_sensor_inb failed, status=0x%02x\n",
-                               tmpval);
-               return 1;
-       }
-
-       if (stk_camera_read_reg(dev, STK_IIC_RX_VALUE, &tmpval))
-               return 1;
-
-       *val = (u8) tmpval;
-       return 0;
-}
-
-static int stk_sensor_write_regvals(struct stk_camera *dev,
-               struct regval *rv)
-{
-       int ret;
-       if (rv == NULL)
-               return 0;
-       while (rv->reg != 0xff || rv->val != 0xff) {
-               ret = stk_sensor_outb(dev, rv->reg, rv->val);
-               if (ret != 0)
-                       return ret;
-               rv++;
-       }
-       return 0;
-}
-
-int stk_sensor_sleep(struct stk_camera *dev)
-{
-       u8 tmp;
-       return stk_sensor_inb(dev, REG_COM2, &tmp)
-               || stk_sensor_outb(dev, REG_COM2, tmp|COM2_SSLEEP);
-}
-
-int stk_sensor_wakeup(struct stk_camera *dev)
-{
-       u8 tmp;
-       return stk_sensor_inb(dev, REG_COM2, &tmp)
-               || stk_sensor_outb(dev, REG_COM2, tmp&~COM2_SSLEEP);
-}
-
-static struct regval ov_initvals[] = {
-       {REG_CLKRC, CLK_PLL},
-       {REG_COM11, 0x01},
-       {0x6a, 0x7d},
-       {REG_AECH, 0x40},
-       {REG_GAIN, 0x00},
-       {REG_BLUE, 0x80},
-       {REG_RED, 0x80},
-       /* Do not enable fast AEC for now */
-       /*{REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC},*/
-       {REG_COM8, COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC},
-       {0x39, 0x50}, {0x38, 0x93},
-       {0x37, 0x00}, {0x35, 0x81},
-       {REG_COM5, 0x20},
-       {REG_COM1, 0x00},
-       {REG_COM3, 0x00},
-       {REG_COM4, 0x00},
-       {REG_PSHFT, 0x00},
-       {0x16, 0x07},
-       {0x33, 0xe2}, {0x34, 0xbf},
-       {REG_COM16, 0x00},
-       {0x96, 0x04},
-       /* Gamma curve values */
-/*     { 0x7a, 0x20 },         { 0x7b, 0x10 },
-       { 0x7c, 0x1e },         { 0x7d, 0x35 },
-       { 0x7e, 0x5a },         { 0x7f, 0x69 },
-       { 0x80, 0x76 },         { 0x81, 0x80 },
-       { 0x82, 0x88 },         { 0x83, 0x8f },
-       { 0x84, 0x96 },         { 0x85, 0xa3 },
-       { 0x86, 0xaf },         { 0x87, 0xc4 },
-       { 0x88, 0xd7 },         { 0x89, 0xe8 },
-*/
-       {REG_GFIX, 0x40},
-       {0x8e, 0x00},
-       {REG_COM12, 0x73},
-       {0x8f, 0xdf}, {0x8b, 0x06},
-       {0x8c, 0x20},
-       {0x94, 0x88}, {0x95, 0x88},
-/*     {REG_COM15, 0xc1}, TODO */
-       {0x29, 0x3f},
-       {REG_COM6, 0x42},
-       {REG_BD50MAX, 0x80},
-       {REG_HAECC6, 0xb8}, {REG_HAECC7, 0x92},
-       {REG_BD60MAX, 0x0a},
-       {0x90, 0x00}, {0x91, 0x00},
-       {REG_HAECC1, 0x00}, {REG_HAECC2, 0x00},
-       {REG_AEW, 0x68}, {REG_AEB, 0x5c},
-       {REG_VPT, 0xc3},
-       {REG_COM9, 0x2e},
-       {0x2a, 0x00}, {0x2b, 0x00},
-
-       {0xff, 0xff}, /* END MARKER */
-};
-
-/* Probe the I2C bus and initialise the sensor chip */
-int stk_sensor_init(struct stk_camera *dev)
-{
-       u8 idl = 0;
-       u8 idh = 0;
-
-       if (stk_camera_write_reg(dev, STK_IIC_ENABLE, STK_IIC_ENABLE_YES)
-               || stk_camera_write_reg(dev, STK_IIC_ADDR, SENSOR_ADDRESS)
-               || stk_sensor_outb(dev, REG_COM7, COM7_RESET)) {
-               STK_ERROR("Sensor resetting failed\n");
-               return -ENODEV;
-       }
-       msleep(10);
-       /* Read the manufacturer ID: ov = 0x7FA2 */
-       if (stk_sensor_inb(dev, REG_MIDH, &idh)
-           || stk_sensor_inb(dev, REG_MIDL, &idl)) {
-               STK_ERROR("Strange error reading sensor ID\n");
-               return -ENODEV;
-       }
-       if (idh != 0x7f || idl != 0xa2) {
-               STK_ERROR("Huh? you don't have a sensor from ovt\n");
-               return -ENODEV;
-       }
-       if (stk_sensor_inb(dev, REG_PID, &idh)
-           || stk_sensor_inb(dev, REG_VER, &idl)) {
-               STK_ERROR("Could not read sensor model\n");
-               return -ENODEV;
-       }
-       stk_sensor_write_regvals(dev, ov_initvals);
-       msleep(10);
-       STK_INFO("OmniVision sensor detected, id %02X%02X"
-               " at address %x\n", idh, idl, SENSOR_ADDRESS);
-       return 0;
-}
-
-/* V4L2_PIX_FMT_UYVY */
-static struct regval ov_fmt_uyvy[] = {
-       {REG_TSLB, TSLB_YLAST|0x08 },
-       { 0x4f, 0x80 },         /* "matrix coefficient 1" */
-       { 0x50, 0x80 },         /* "matrix coefficient 2" */
-       { 0x51, 0    },         /* vb */
-       { 0x52, 0x22 },         /* "matrix coefficient 4" */
-       { 0x53, 0x5e },         /* "matrix coefficient 5" */
-       { 0x54, 0x80 },         /* "matrix coefficient 6" */
-       {REG_COM13, COM13_UVSAT|COM13_CMATRIX},
-       {REG_COM15, COM15_R00FF },
-       {0xff, 0xff}, /* END MARKER */
-};
-/* V4L2_PIX_FMT_YUYV */
-static struct regval ov_fmt_yuyv[] = {
-       {REG_TSLB, 0 },
-       { 0x4f, 0x80 },         /* "matrix coefficient 1" */
-       { 0x50, 0x80 },         /* "matrix coefficient 2" */
-       { 0x51, 0    },         /* vb */
-       { 0x52, 0x22 },         /* "matrix coefficient 4" */
-       { 0x53, 0x5e },         /* "matrix coefficient 5" */
-       { 0x54, 0x80 },         /* "matrix coefficient 6" */
-       {REG_COM13, COM13_UVSAT|COM13_CMATRIX},
-       {REG_COM15, COM15_R00FF },
-       {0xff, 0xff}, /* END MARKER */
-};
-
-/* V4L2_PIX_FMT_RGB565X rrrrrggg gggbbbbb */
-static struct regval ov_fmt_rgbr[] = {
-       { REG_RGB444, 0 },      /* No RGB444 please */
-       {REG_TSLB, 0x00},
-       { REG_COM1, 0x0 },
-       { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
-       { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
-       { 0x50, 0xb3 },         /* "matrix coefficient 2" */
-       { 0x51, 0    },         /* vb */
-       { 0x52, 0x3d },         /* "matrix coefficient 4" */
-       { 0x53, 0xa7 },         /* "matrix coefficient 5" */
-       { 0x54, 0xe4 },         /* "matrix coefficient 6" */
-       { REG_COM13, COM13_GAMMA },
-       { REG_COM15, COM15_RGB565|COM15_R00FF },
-       { 0xff, 0xff },
-};
-
-/* V4L2_PIX_FMT_RGB565 gggbbbbb rrrrrggg */
-static struct regval ov_fmt_rgbp[] = {
-       { REG_RGB444, 0 },      /* No RGB444 please */
-       {REG_TSLB, TSLB_BYTEORD },
-       { REG_COM1, 0x0 },
-       { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
-       { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
-       { 0x50, 0xb3 },         /* "matrix coefficient 2" */
-       { 0x51, 0    },         /* vb */
-       { 0x52, 0x3d },         /* "matrix coefficient 4" */
-       { 0x53, 0xa7 },         /* "matrix coefficient 5" */
-       { 0x54, 0xe4 },         /* "matrix coefficient 6" */
-       { REG_COM13, COM13_GAMMA },
-       { REG_COM15, COM15_RGB565|COM15_R00FF },
-       { 0xff, 0xff },
-};
-
-/* V4L2_PIX_FMT_SRGGB8 */
-static struct regval ov_fmt_bayer[] = {
-       /* This changes color order */
-       {REG_TSLB, 0x40}, /* BGGR */
-       /* {REG_TSLB, 0x08}, */ /* BGGR with vertical image flipping */
-       {REG_COM15, COM15_R00FF },
-       {0xff, 0xff}, /* END MARKER */
-};
-/*
- * Store a set of start/stop values into the camera.
- */
-static int stk_sensor_set_hw(struct stk_camera *dev,
-               int hstart, int hstop, int vstart, int vstop)
-{
-       int ret;
-       unsigned char v;
-/*
- * Horizontal: 11 bits, top 8 live in hstart and hstop.  Bottom 3 of
- * hstart are in href[2:0], bottom 3 of hstop in href[5:3].  There is
- * a mystery "edge offset" value in the top two bits of href.
- */
-       ret =  stk_sensor_outb(dev, REG_HSTART, (hstart >> 3) & 0xff);
-       ret += stk_sensor_outb(dev, REG_HSTOP, (hstop >> 3) & 0xff);
-       ret += stk_sensor_inb(dev, REG_HREF, &v);
-       v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
-       msleep(10);
-       ret += stk_sensor_outb(dev, REG_HREF, v);
-/*
- * Vertical: similar arrangement (note: this is different from ov7670.c)
- */
-       ret += stk_sensor_outb(dev, REG_VSTART, (vstart >> 3) & 0xff);
-       ret += stk_sensor_outb(dev, REG_VSTOP, (vstop >> 3) & 0xff);
-       ret += stk_sensor_inb(dev, REG_VREF, &v);
-       v = (v & 0xc0) | ((vstop & 0x7) << 3) | (vstart & 0x7);
-       msleep(10);
-       ret += stk_sensor_outb(dev, REG_VREF, v);
-       return ret;
-}
-
-
-int stk_sensor_configure(struct stk_camera *dev)
-{
-       int com7;
-       /*
-        * We setup the sensor to output dummy lines in low-res modes,
-        * so we don't get absurdly hight framerates.
-        */
-       unsigned dummylines;
-       int flip;
-       struct regval *rv;
-
-       switch (dev->vsettings.mode) {
-       case MODE_QCIF: com7 = COM7_FMT_QCIF;
-               dummylines = 604;
-               break;
-       case MODE_QVGA: com7 = COM7_FMT_QVGA;
-               dummylines = 267;
-               break;
-       case MODE_CIF: com7 = COM7_FMT_CIF;
-               dummylines = 412;
-               break;
-       case MODE_VGA: com7 = COM7_FMT_VGA;
-               dummylines = 11;
-               break;
-       case MODE_SXGA: com7 = COM7_FMT_SXGA;
-               dummylines = 0;
-               break;
-       default: STK_ERROR("Unsupported mode %d\n", dev->vsettings.mode);
-               return -EFAULT;
-       }
-       switch (dev->vsettings.palette) {
-       case V4L2_PIX_FMT_UYVY:
-               com7 |= COM7_YUV;
-               rv = ov_fmt_uyvy;
-               break;
-       case V4L2_PIX_FMT_YUYV:
-               com7 |= COM7_YUV;
-               rv = ov_fmt_yuyv;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-               com7 |= COM7_RGB;
-               rv = ov_fmt_rgbp;
-               break;
-       case V4L2_PIX_FMT_RGB565X:
-               com7 |= COM7_RGB;
-               rv = ov_fmt_rgbr;
-               break;
-       case V4L2_PIX_FMT_SBGGR8:
-               com7 |= COM7_PBAYER;
-               rv = ov_fmt_bayer;
-               break;
-       default: STK_ERROR("Unsupported colorspace\n");
-               return -EFAULT;
-       }
-       /*FIXME sometimes the sensor go to a bad state
-       stk_sensor_write_regvals(dev, ov_initvals); */
-       stk_sensor_outb(dev, REG_COM7, com7);
-       msleep(50);
-       stk_sensor_write_regvals(dev, rv);
-       flip = (dev->vsettings.vflip?MVFP_FLIP:0)
-               | (dev->vsettings.hflip?MVFP_MIRROR:0);
-       stk_sensor_outb(dev, REG_MVFP, flip);
-       if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8
-                       && !dev->vsettings.vflip)
-               stk_sensor_outb(dev, REG_TSLB, 0x08);
-       stk_sensor_outb(dev, REG_ADVFH, dummylines >> 8);
-       stk_sensor_outb(dev, REG_ADVFL, dummylines & 0xff);
-       msleep(50);
-       switch (dev->vsettings.mode) {
-       case MODE_VGA:
-               if (stk_sensor_set_hw(dev, 302, 1582, 6, 486))
-                       STK_ERROR("stk_sensor_set_hw failed (VGA)\n");
-               break;
-       case MODE_SXGA:
-       case MODE_CIF:
-       case MODE_QVGA:
-       case MODE_QCIF:
-               /*FIXME These settings seem ignored by the sensor
-               if (stk_sensor_set_hw(dev, 220, 1500, 10, 1034))
-                       STK_ERROR("stk_sensor_set_hw failed (SXGA)\n");
-               */
-               break;
-       }
-       msleep(10);
-       return 0;
-}
-
-int stk_sensor_set_brightness(struct stk_camera *dev, int br)
-{
-       if (br < 0 || br > 0xff)
-               return -EINVAL;
-       stk_sensor_outb(dev, REG_AEB, max(0x00, br - 6));
-       stk_sensor_outb(dev, REG_AEW, min(0xff, br + 6));
-       return 0;
-}
-
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
deleted file mode 100644 (file)
index 86a0fc5..0000000
+++ /dev/null
@@ -1,1380 +0,0 @@
-/*
- * stk-webcam.c : Driver for Syntek 1125 USB webcam controller
- *
- * Copyright (C) 2006 Nicolas VIVIEN
- * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com>
- *
- * Some parts are inspired from cafe_ccic.c
- * Copyright 2006-2007 Jonathan Corbet
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <linux/usb.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-#include "stk-webcam.h"
-
-
-static bool hflip;
-module_param(hflip, bool, 0444);
-MODULE_PARM_DESC(hflip, "Horizontal image flip (mirror). Defaults to 0");
-
-static bool vflip;
-module_param(vflip, bool, 0444);
-MODULE_PARM_DESC(vflip, "Vertical image flip. Defaults to 0");
-
-static int debug;
-module_param(debug, int, 0444);
-MODULE_PARM_DESC(debug, "Debug v4l ioctls. Defaults to 0");
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN");
-MODULE_DESCRIPTION("Syntek DC1125 webcam driver");
-
-
-/* bool for webcam LED management */
-int first_init = 1;
-
-/* Some cameras have audio interfaces, we aren't interested in those */
-static struct usb_device_id stkwebcam_table[] = {
-       { USB_DEVICE_AND_INTERFACE_INFO(0x174f, 0xa311, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(0x05e1, 0x0501, 0xff, 0xff, 0xff) },
-       { }
-};
-MODULE_DEVICE_TABLE(usb, stkwebcam_table);
-
-/*
- * Basic stuff
- */
-int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value)
-{
-       struct usb_device *udev = dev->udev;
-       int ret;
-
-       ret =  usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                       0x01,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value,
-                       index,
-                       NULL,
-                       0,
-                       500);
-       if (ret < 0)
-               return ret;
-       else
-               return 0;
-}
-
-int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value)
-{
-       struct usb_device *udev = dev->udev;
-       int ret;
-
-       ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                       0x00,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x00,
-                       index,
-                       (u8 *) value,
-                       sizeof(u8),
-                       500);
-       if (ret < 0)
-               return ret;
-       else
-               return 0;
-}
-
-static int stk_start_stream(struct stk_camera *dev)
-{
-       int value;
-       int i, ret;
-       int value_116, value_117;
-
-       if (!is_present(dev))
-               return -ENODEV;
-       if (!is_memallocd(dev) || !is_initialised(dev)) {
-               STK_ERROR("FIXME: Buffers are not allocated\n");
-               return -EFAULT;
-       }
-       ret = usb_set_interface(dev->udev, 0, 5);
-
-       if (ret < 0)
-               STK_ERROR("usb_set_interface failed !\n");
-       if (stk_sensor_wakeup(dev))
-               STK_ERROR("error awaking the sensor\n");
-
-       stk_camera_read_reg(dev, 0x0116, &value_116);
-       stk_camera_read_reg(dev, 0x0117, &value_117);
-
-       stk_camera_write_reg(dev, 0x0116, 0x0000);
-       stk_camera_write_reg(dev, 0x0117, 0x0000);
-
-       stk_camera_read_reg(dev, 0x0100, &value);
-       stk_camera_write_reg(dev, 0x0100, value | 0x80);
-
-       stk_camera_write_reg(dev, 0x0116, value_116);
-       stk_camera_write_reg(dev, 0x0117, value_117);
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               if (dev->isobufs[i].urb) {
-                       ret = usb_submit_urb(dev->isobufs[i].urb, GFP_KERNEL);
-                       atomic_inc(&dev->urbs_used);
-                       if (ret)
-                               return ret;
-               }
-       }
-       set_streaming(dev);
-       return 0;
-}
-
-static int stk_stop_stream(struct stk_camera *dev)
-{
-       int value;
-       int i;
-       if (is_present(dev)) {
-               stk_camera_read_reg(dev, 0x0100, &value);
-               stk_camera_write_reg(dev, 0x0100, value & ~0x80);
-               if (dev->isobufs != NULL) {
-                       for (i = 0; i < MAX_ISO_BUFS; i++) {
-                               if (dev->isobufs[i].urb)
-                                       usb_kill_urb(dev->isobufs[i].urb);
-                       }
-               }
-               unset_streaming(dev);
-
-               if (usb_set_interface(dev->udev, 0, 0))
-                       STK_ERROR("usb_set_interface failed !\n");
-               if (stk_sensor_sleep(dev))
-                       STK_ERROR("error suspending the sensor\n");
-       }
-       return 0;
-}
-
-/*
- * This seems to be the shortest init sequence we
- * must do in order to find the sensor
- * Bit 5 of reg. 0x0000 here is important, when reset to 0 the sensor
- * is also reset. Maybe powers down it?
- * Rest of values don't make a difference
- */
-
-static struct regval stk1125_initvals[] = {
-       /*TODO: What means this sequence? */
-       {0x0000, 0x24},
-       {0x0100, 0x21},
-       {0x0002, 0x68},
-       {0x0003, 0x80},
-       {0x0005, 0x00},
-       {0x0007, 0x03},
-       {0x000d, 0x00},
-       {0x000f, 0x02},
-       {0x0300, 0x12},
-       {0x0350, 0x41},
-       {0x0351, 0x00},
-       {0x0352, 0x00},
-       {0x0353, 0x00},
-       {0x0018, 0x10},
-       {0x0019, 0x00},
-       {0x001b, 0x0e},
-       {0x001c, 0x46},
-       {0x0300, 0x80},
-       {0x001a, 0x04},
-       {0x0110, 0x00},
-       {0x0111, 0x00},
-       {0x0112, 0x00},
-       {0x0113, 0x00},
-
-       {0xffff, 0xff},
-};
-
-
-static int stk_initialise(struct stk_camera *dev)
-{
-       struct regval *rv;
-       int ret;
-       if (!is_present(dev))
-               return -ENODEV;
-       if (is_initialised(dev))
-               return 0;
-       rv = stk1125_initvals;
-       while (rv->reg != 0xffff) {
-               ret = stk_camera_write_reg(dev, rv->reg, rv->val);
-               if (ret)
-                       return ret;
-               rv++;
-       }
-       if (stk_sensor_init(dev) == 0) {
-               set_initialised(dev);
-               return 0;
-       } else
-               return -1;
-}
-
-/* *********************************************** */
-/*
- * This function is called as an URB transfert is complete (Isochronous pipe).
- * So, the traitement is done in interrupt time, so it has be fast, not crash,
- * and not stall. Neat.
- */
-static void stk_isoc_handler(struct urb *urb)
-{
-       int i;
-       int ret;
-       int framelen;
-       unsigned long flags;
-
-       unsigned char *fill = NULL;
-       unsigned char *iso_buf = NULL;
-
-       struct stk_camera *dev;
-       struct stk_sio_buffer *fb;
-
-       dev = (struct stk_camera *) urb->context;
-
-       if (dev == NULL) {
-               STK_ERROR("isoc_handler called with NULL device !\n");
-               return;
-       }
-
-       if (urb->status == -ENOENT || urb->status == -ECONNRESET
-               || urb->status == -ESHUTDOWN) {
-               atomic_dec(&dev->urbs_used);
-               return;
-       }
-
-       spin_lock_irqsave(&dev->spinlock, flags);
-
-       if (urb->status != -EINPROGRESS && urb->status != 0) {
-               STK_ERROR("isoc_handler: urb->status == %d\n", urb->status);
-               goto resubmit;
-       }
-
-       if (list_empty(&dev->sio_avail)) {
-               /*FIXME Stop streaming after a while */
-               (void) (printk_ratelimit() &&
-               STK_ERROR("isoc_handler without available buffer!\n"));
-               goto resubmit;
-       }
-       fb = list_first_entry(&dev->sio_avail,
-                       struct stk_sio_buffer, list);
-       fill = fb->buffer + fb->v4lbuf.bytesused;
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               if (urb->iso_frame_desc[i].status != 0) {
-                       if (urb->iso_frame_desc[i].status != -EXDEV)
-                               STK_ERROR("Frame %d has error %d\n", i,
-                                       urb->iso_frame_desc[i].status);
-                       continue;
-               }
-               framelen = urb->iso_frame_desc[i].actual_length;
-               iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-               if (framelen <= 4)
-                       continue; /* no data */
-
-               /*
-                * we found something informational from there
-                * the isoc frames have to type of headers
-                * type1: 00 xx 00 00 or 20 xx 00 00
-                * type2: 80 xx 00 00 00 00 00 00 or a0 xx 00 00 00 00 00 00
-                * xx is a sequencer which has never been seen over 0x3f
-                * imho data written down looks like bayer, i see similarities
-                * after every 640 bytes
-                */
-               if (*iso_buf & 0x80) {
-                       framelen -= 8;
-                       iso_buf += 8;
-                       /* This marks a new frame */
-                       if (fb->v4lbuf.bytesused != 0
-                               && fb->v4lbuf.bytesused != dev->frame_size) {
-                               (void) (printk_ratelimit() &&
-                               STK_ERROR("frame %d, "
-                                       "bytesused=%d, skipping\n",
-                                       i, fb->v4lbuf.bytesused));
-                               fb->v4lbuf.bytesused = 0;
-                               fill = fb->buffer;
-                       } else if (fb->v4lbuf.bytesused == dev->frame_size) {
-                               if (list_is_singular(&dev->sio_avail)) {
-                                       /* Always reuse the last buffer */
-                                       fb->v4lbuf.bytesused = 0;
-                                       fill = fb->buffer;
-                               } else {
-                                       list_move_tail(dev->sio_avail.next,
-                                               &dev->sio_full);
-                                       wake_up(&dev->wait_frame);
-                                       fb = list_first_entry(&dev->sio_avail,
-                                               struct stk_sio_buffer, list);
-                                       fb->v4lbuf.bytesused = 0;
-                                       fill = fb->buffer;
-                               }
-                       }
-               } else {
-                       framelen -= 4;
-                       iso_buf += 4;
-               }
-
-               /* Our buffer is full !!! */
-               if (framelen + fb->v4lbuf.bytesused > dev->frame_size) {
-                       (void) (printk_ratelimit() &&
-                       STK_ERROR("Frame buffer overflow, lost sync\n"));
-                       /*FIXME Do something here? */
-                       continue;
-               }
-               spin_unlock_irqrestore(&dev->spinlock, flags);
-               memcpy(fill, iso_buf, framelen);
-               spin_lock_irqsave(&dev->spinlock, flags);
-               fill += framelen;
-
-               /* New size of our buffer */
-               fb->v4lbuf.bytesused += framelen;
-       }
-
-resubmit:
-       spin_unlock_irqrestore(&dev->spinlock, flags);
-       urb->dev = dev->udev;
-       ret = usb_submit_urb(urb, GFP_ATOMIC);
-       if (ret != 0) {
-               STK_ERROR("Error (%d) re-submitting urb in stk_isoc_handler.\n",
-                       ret);
-       }
-}
-
-/* -------------------------------------------- */
-
-static int stk_prepare_iso(struct stk_camera *dev)
-{
-       void *kbuf;
-       int i, j;
-       struct urb *urb;
-       struct usb_device *udev;
-
-       if (dev == NULL)
-               return -ENXIO;
-       udev = dev->udev;
-
-       if (dev->isobufs)
-               STK_ERROR("isobufs already allocated. Bad\n");
-       else
-               dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs),
-                                      GFP_KERNEL);
-       if (dev->isobufs == NULL) {
-               STK_ERROR("Unable to allocate iso buffers\n");
-               return -ENOMEM;
-       }
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               if (dev->isobufs[i].data == NULL) {
-                       kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
-                       if (kbuf == NULL) {
-                               STK_ERROR("Failed to allocate iso buffer %d\n",
-                                       i);
-                               goto isobufs_out;
-                       }
-                       dev->isobufs[i].data = kbuf;
-               } else
-                       STK_ERROR("isobuf data already allocated\n");
-               if (dev->isobufs[i].urb == NULL) {
-                       urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
-                       if (urb == NULL) {
-                               STK_ERROR("Failed to allocate URB %d\n", i);
-                               goto isobufs_out;
-                       }
-                       dev->isobufs[i].urb = urb;
-               } else {
-                       STK_ERROR("Killing URB\n");
-                       usb_kill_urb(dev->isobufs[i].urb);
-                       urb = dev->isobufs[i].urb;
-               }
-               urb->interval = 1;
-               urb->dev = udev;
-               urb->pipe = usb_rcvisocpipe(udev, dev->isoc_ep);
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->transfer_buffer = dev->isobufs[i].data;
-               urb->transfer_buffer_length = ISO_BUFFER_SIZE;
-               urb->complete = stk_isoc_handler;
-               urb->context = dev;
-               urb->start_frame = 0;
-               urb->number_of_packets = ISO_FRAMES_PER_DESC;
-
-               for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
-                       urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
-                       urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
-               }
-       }
-       set_memallocd(dev);
-       return 0;
-
-isobufs_out:
-       for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].data; i++)
-               kfree(dev->isobufs[i].data);
-       for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].urb; i++)
-               usb_free_urb(dev->isobufs[i].urb);
-       kfree(dev->isobufs);
-       dev->isobufs = NULL;
-       return -ENOMEM;
-}
-
-static void stk_clean_iso(struct stk_camera *dev)
-{
-       int i;
-
-       if (dev == NULL || dev->isobufs == NULL)
-               return;
-
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               struct urb *urb;
-
-               urb = dev->isobufs[i].urb;
-               if (urb) {
-                       if (atomic_read(&dev->urbs_used) && is_present(dev))
-                               usb_kill_urb(urb);
-                       usb_free_urb(urb);
-               }
-               kfree(dev->isobufs[i].data);
-       }
-       kfree(dev->isobufs);
-       dev->isobufs = NULL;
-       unset_memallocd(dev);
-}
-
-static int stk_setup_siobuf(struct stk_camera *dev, int index)
-{
-       struct stk_sio_buffer *buf = dev->sio_bufs + index;
-       INIT_LIST_HEAD(&buf->list);
-       buf->v4lbuf.length = PAGE_ALIGN(dev->frame_size);
-       buf->buffer = vmalloc_user(buf->v4lbuf.length);
-       if (buf->buffer == NULL)
-               return -ENOMEM;
-       buf->mapcount = 0;
-       buf->dev = dev;
-       buf->v4lbuf.index = index;
-       buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       buf->v4lbuf.field = V4L2_FIELD_NONE;
-       buf->v4lbuf.memory = V4L2_MEMORY_MMAP;
-       buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length;
-       return 0;
-}
-
-static int stk_free_sio_buffers(struct stk_camera *dev)
-{
-       int i;
-       int nbufs;
-       unsigned long flags;
-       if (dev->n_sbufs == 0 || dev->sio_bufs == NULL)
-               return 0;
-       /*
-       * If any buffers are mapped, we cannot free them at all.
-       */
-       for (i = 0; i < dev->n_sbufs; i++) {
-               if (dev->sio_bufs[i].mapcount > 0)
-                       return -EBUSY;
-       }
-       /*
-       * OK, let's do it.
-       */
-       spin_lock_irqsave(&dev->spinlock, flags);
-       INIT_LIST_HEAD(&dev->sio_avail);
-       INIT_LIST_HEAD(&dev->sio_full);
-       nbufs = dev->n_sbufs;
-       dev->n_sbufs = 0;
-       spin_unlock_irqrestore(&dev->spinlock, flags);
-       for (i = 0; i < nbufs; i++) {
-               if (dev->sio_bufs[i].buffer != NULL)
-                       vfree(dev->sio_bufs[i].buffer);
-       }
-       kfree(dev->sio_bufs);
-       dev->sio_bufs = NULL;
-       return 0;
-}
-
-static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs)
-{
-       int i;
-       if (dev->sio_bufs != NULL)
-               STK_ERROR("sio_bufs already allocated\n");
-       else {
-               dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer),
-                               GFP_KERNEL);
-               if (dev->sio_bufs == NULL)
-                       return -ENOMEM;
-               for (i = 0; i < n_sbufs; i++) {
-                       if (stk_setup_siobuf(dev, i))
-                               return (dev->n_sbufs > 1 ? 0 : -ENOMEM);
-                       dev->n_sbufs = i+1;
-               }
-       }
-       return 0;
-}
-
-static int stk_allocate_buffers(struct stk_camera *dev, unsigned n_sbufs)
-{
-       int err;
-       err = stk_prepare_iso(dev);
-       if (err) {
-               stk_clean_iso(dev);
-               return err;
-       }
-       err = stk_prepare_sio_buffers(dev, n_sbufs);
-       if (err) {
-               stk_free_sio_buffers(dev);
-               return err;
-       }
-       return 0;
-}
-
-static void stk_free_buffers(struct stk_camera *dev)
-{
-       stk_clean_iso(dev);
-       stk_free_sio_buffers(dev);
-}
-/* -------------------------------------------- */
-
-/* v4l file operations */
-
-static int v4l_stk_open(struct file *fp)
-{
-       struct stk_camera *dev;
-       struct video_device *vdev;
-
-       vdev = video_devdata(fp);
-       dev = vdev_to_camera(vdev);
-
-       if (dev == NULL || !is_present(dev))
-               return -ENXIO;
-
-       if (!first_init)
-               stk_camera_write_reg(dev, 0x0, 0x24);
-       else
-               first_init = 0;
-
-       fp->private_data = dev;
-       usb_autopm_get_interface(dev->interface);
-
-       return 0;
-}
-
-static int v4l_stk_release(struct file *fp)
-{
-       struct stk_camera *dev = fp->private_data;
-
-       if (dev->owner == fp) {
-               stk_stop_stream(dev);
-               stk_free_buffers(dev);
-               stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */
-               unset_initialised(dev);
-               dev->owner = NULL;
-       }
-
-       if (is_present(dev))
-               usb_autopm_put_interface(dev->interface);
-
-       return 0;
-}
-
-static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
-               size_t count, loff_t *f_pos)
-{
-       int i;
-       int ret;
-       unsigned long flags;
-       struct stk_sio_buffer *sbuf;
-       struct stk_camera *dev = fp->private_data;
-
-       if (!is_present(dev))
-               return -EIO;
-       if (dev->owner && dev->owner != fp)
-               return -EBUSY;
-       dev->owner = fp;
-       if (!is_streaming(dev)) {
-               if (stk_initialise(dev)
-                       || stk_allocate_buffers(dev, 3)
-                       || stk_start_stream(dev))
-                       return -ENOMEM;
-               spin_lock_irqsave(&dev->spinlock, flags);
-               for (i = 0; i < dev->n_sbufs; i++) {
-                       list_add_tail(&dev->sio_bufs[i].list, &dev->sio_avail);
-                       dev->sio_bufs[i].v4lbuf.flags = V4L2_BUF_FLAG_QUEUED;
-               }
-               spin_unlock_irqrestore(&dev->spinlock, flags);
-       }
-       if (*f_pos == 0) {
-               if (fp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full))
-                       return -EWOULDBLOCK;
-               ret = wait_event_interruptible(dev->wait_frame,
-                       !list_empty(&dev->sio_full) || !is_present(dev));
-               if (ret)
-                       return ret;
-               if (!is_present(dev))
-                       return -EIO;
-       }
-       if (count + *f_pos > dev->frame_size)
-               count = dev->frame_size - *f_pos;
-       spin_lock_irqsave(&dev->spinlock, flags);
-       if (list_empty(&dev->sio_full)) {
-               spin_unlock_irqrestore(&dev->spinlock, flags);
-               STK_ERROR("BUG: No siobufs ready\n");
-               return 0;
-       }
-       sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list);
-       spin_unlock_irqrestore(&dev->spinlock, flags);
-
-       if (copy_to_user(buf, sbuf->buffer + *f_pos, count))
-               return -EFAULT;
-
-       *f_pos += count;
-
-       if (*f_pos >= dev->frame_size) {
-               *f_pos = 0;
-               spin_lock_irqsave(&dev->spinlock, flags);
-               list_move_tail(&sbuf->list, &dev->sio_avail);
-               spin_unlock_irqrestore(&dev->spinlock, flags);
-       }
-       return count;
-}
-
-static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
-{
-       struct stk_camera *dev = fp->private_data;
-
-       poll_wait(fp, &dev->wait_frame, wait);
-
-       if (!is_present(dev))
-               return POLLERR;
-
-       if (!list_empty(&dev->sio_full))
-               return POLLIN | POLLRDNORM;
-
-       return 0;
-}
-
-
-static void stk_v4l_vm_open(struct vm_area_struct *vma)
-{
-       struct stk_sio_buffer *sbuf = vma->vm_private_data;
-       sbuf->mapcount++;
-}
-static void stk_v4l_vm_close(struct vm_area_struct *vma)
-{
-       struct stk_sio_buffer *sbuf = vma->vm_private_data;
-       sbuf->mapcount--;
-       if (sbuf->mapcount == 0)
-               sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED;
-}
-static const struct vm_operations_struct stk_v4l_vm_ops = {
-       .open = stk_v4l_vm_open,
-       .close = stk_v4l_vm_close
-};
-
-static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma)
-{
-       unsigned int i;
-       int ret;
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       struct stk_camera *dev = fp->private_data;
-       struct stk_sio_buffer *sbuf = NULL;
-
-       if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
-               return -EINVAL;
-
-       for (i = 0; i < dev->n_sbufs; i++) {
-               if (dev->sio_bufs[i].v4lbuf.m.offset == offset) {
-                       sbuf = dev->sio_bufs + i;
-                       break;
-               }
-       }
-       if (sbuf == NULL)
-               return -EINVAL;
-       ret = remap_vmalloc_range(vma, sbuf->buffer, 0);
-       if (ret)
-               return ret;
-       vma->vm_flags |= VM_DONTEXPAND;
-       vma->vm_private_data = sbuf;
-       vma->vm_ops = &stk_v4l_vm_ops;
-       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED;
-       stk_v4l_vm_open(vma);
-       return 0;
-}
-
-/* v4l ioctl handlers */
-
-static int stk_vidioc_querycap(struct file *filp,
-               void *priv, struct v4l2_capability *cap)
-{
-       strcpy(cap->driver, "stk");
-       strcpy(cap->card, "stk");
-       cap->version = DRIVER_VERSION_NUM;
-
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
-               | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-       return 0;
-}
-
-static int stk_vidioc_enum_input(struct file *filp,
-               void *priv, struct v4l2_input *input)
-{
-       if (input->index != 0)
-               return -EINVAL;
-
-       strcpy(input->name, "Syntek USB Camera");
-       input->type = V4L2_INPUT_TYPE_CAMERA;
-       return 0;
-}
-
-
-static int stk_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int stk_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       if (i != 0)
-               return -EINVAL;
-       else
-               return 0;
-}
-
-/* from vivi.c */
-static int stk_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
-{
-       return 0;
-}
-
-/* List of all V4Lv2 controls supported by the driver */
-static struct v4l2_queryctrl stk_controls[] = {
-       {
-               .id      = V4L2_CID_BRIGHTNESS,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Brightness",
-               .minimum = 0,
-               .maximum = 0xffff,
-               .step    = 0x0100,
-               .default_value = 0x6000,
-       },
-       {
-               .id      = V4L2_CID_HFLIP,
-               .type    = V4L2_CTRL_TYPE_BOOLEAN,
-               .name    = "Horizontal Flip",
-               .minimum = 0,
-               .maximum = 1,
-               .step    = 1,
-               .default_value = 1,
-       },
-       {
-               .id      = V4L2_CID_VFLIP,
-               .type    = V4L2_CTRL_TYPE_BOOLEAN,
-               .name    = "Vertical Flip",
-               .minimum = 0,
-               .maximum = 1,
-               .step    = 1,
-               .default_value = 1,
-       },
-};
-
-static int stk_vidioc_queryctrl(struct file *filp,
-               void *priv, struct v4l2_queryctrl *c)
-{
-       int i;
-       int nbr;
-       nbr = ARRAY_SIZE(stk_controls);
-
-       for (i = 0; i < nbr; i++) {
-               if (stk_controls[i].id == c->id) {
-                       memcpy(c, &stk_controls[i],
-                               sizeof(struct v4l2_queryctrl));
-                       return 0;
-               }
-       }
-       return -EINVAL;
-}
-
-static int stk_vidioc_g_ctrl(struct file *filp,
-               void *priv, struct v4l2_control *c)
-{
-       struct stk_camera *dev = priv;
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               c->value = dev->vsettings.brightness;
-               break;
-       case V4L2_CID_HFLIP:
-               c->value = dev->vsettings.hflip;
-               break;
-       case V4L2_CID_VFLIP:
-               c->value = dev->vsettings.vflip;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int stk_vidioc_s_ctrl(struct file *filp,
-               void *priv, struct v4l2_control *c)
-{
-       struct stk_camera *dev = priv;
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               dev->vsettings.brightness = c->value;
-               return stk_sensor_set_brightness(dev, c->value >> 8);
-       case V4L2_CID_HFLIP:
-               dev->vsettings.hflip = c->value;
-               return 0;
-       case V4L2_CID_VFLIP:
-               dev->vsettings.vflip = c->value;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-
-static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,
-               void *priv, struct v4l2_fmtdesc *fmtd)
-{
-       switch (fmtd->index) {
-       case 0:
-               fmtd->pixelformat = V4L2_PIX_FMT_RGB565;
-               strcpy(fmtd->description, "r5g6b5");
-               break;
-       case 1:
-               fmtd->pixelformat = V4L2_PIX_FMT_RGB565X;
-               strcpy(fmtd->description, "r5g6b5BE");
-               break;
-       case 2:
-               fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
-               strcpy(fmtd->description, "yuv4:2:2");
-               break;
-       case 3:
-               fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8;
-               strcpy(fmtd->description, "Raw bayer");
-               break;
-       case 4:
-               fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
-               strcpy(fmtd->description, "yuv4:2:2");
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static struct stk_size {
-       unsigned w;
-       unsigned h;
-       enum stk_mode m;
-} stk_sizes[] = {
-       { .w = 1280, .h = 1024, .m = MODE_SXGA, },
-       { .w = 640,  .h = 480,  .m = MODE_VGA,  },
-       { .w = 352,  .h = 288,  .m = MODE_CIF,  },
-       { .w = 320,  .h = 240,  .m = MODE_QVGA, },
-       { .w = 176,  .h = 144,  .m = MODE_QCIF, },
-};
-
-static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
-               void *priv, struct v4l2_format *f)
-{
-       struct v4l2_pix_format *pix_format = &f->fmt.pix;
-       struct stk_camera *dev = priv;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(stk_sizes) &&
-                       stk_sizes[i].m != dev->vsettings.mode; i++)
-               ;
-       if (i == ARRAY_SIZE(stk_sizes)) {
-               STK_ERROR("ERROR: mode invalid\n");
-               return -EINVAL;
-       }
-       pix_format->width = stk_sizes[i].w;
-       pix_format->height = stk_sizes[i].h;
-       pix_format->field = V4L2_FIELD_NONE;
-       pix_format->colorspace = V4L2_COLORSPACE_SRGB;
-       pix_format->pixelformat = dev->vsettings.palette;
-       if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
-               pix_format->bytesperline = pix_format->width;
-       else
-               pix_format->bytesperline = 2 * pix_format->width;
-       pix_format->sizeimage = pix_format->bytesperline
-                               * pix_format->height;
-       return 0;
-}
-
-static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
-               void *priv, struct v4l2_format *fmtd)
-{
-       int i;
-       switch (fmtd->fmt.pix.pixelformat) {
-       case V4L2_PIX_FMT_RGB565:
-       case V4L2_PIX_FMT_RGB565X:
-       case V4L2_PIX_FMT_UYVY:
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_SBGGR8:
-               break;
-       default:
-               return -EINVAL;
-       }
-       for (i = 1; i < ARRAY_SIZE(stk_sizes); i++) {
-               if (fmtd->fmt.pix.width > stk_sizes[i].w)
-                       break;
-       }
-       if (i == ARRAY_SIZE(stk_sizes)
-               || (abs(fmtd->fmt.pix.width - stk_sizes[i-1].w)
-                       < abs(fmtd->fmt.pix.width - stk_sizes[i].w))) {
-               fmtd->fmt.pix.height = stk_sizes[i-1].h;
-               fmtd->fmt.pix.width = stk_sizes[i-1].w;
-               fmtd->fmt.pix.priv = i - 1;
-       } else {
-               fmtd->fmt.pix.height = stk_sizes[i].h;
-               fmtd->fmt.pix.width = stk_sizes[i].w;
-               fmtd->fmt.pix.priv = i;
-       }
-
-       fmtd->fmt.pix.field = V4L2_FIELD_NONE;
-       fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
-       if (fmtd->fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)
-               fmtd->fmt.pix.bytesperline = fmtd->fmt.pix.width;
-       else
-               fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
-       fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
-               * fmtd->fmt.pix.height;
-       return 0;
-}
-
-static int stk_setup_format(struct stk_camera *dev)
-{
-       int i = 0;
-       int depth;
-       if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
-               depth = 1;
-       else
-               depth = 2;
-       while (i < ARRAY_SIZE(stk_sizes) &&
-                       stk_sizes[i].m != dev->vsettings.mode)
-               i++;
-       if (i == ARRAY_SIZE(stk_sizes)) {
-               STK_ERROR("Something is broken in %s\n", __func__);
-               return -EFAULT;
-       }
-       /* This registers controls some timings, not sure of what. */
-       stk_camera_write_reg(dev, 0x001b, 0x0e);
-       if (dev->vsettings.mode == MODE_SXGA)
-               stk_camera_write_reg(dev, 0x001c, 0x0e);
-       else
-               stk_camera_write_reg(dev, 0x001c, 0x46);
-       /*
-        * Registers 0x0115 0x0114 are the size of each line (bytes),
-        * regs 0x0117 0x0116 are the heigth of the image.
-        */
-       stk_camera_write_reg(dev, 0x0115,
-               ((stk_sizes[i].w * depth) >> 8) & 0xff);
-       stk_camera_write_reg(dev, 0x0114,
-               (stk_sizes[i].w * depth) & 0xff);
-       stk_camera_write_reg(dev, 0x0117,
-               (stk_sizes[i].h >> 8) & 0xff);
-       stk_camera_write_reg(dev, 0x0116,
-               stk_sizes[i].h & 0xff);
-       return stk_sensor_configure(dev);
-}
-
-static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
-               void *priv, struct v4l2_format *fmtd)
-{
-       int ret;
-       struct stk_camera *dev = priv;
-
-       if (dev == NULL)
-               return -ENODEV;
-       if (!is_present(dev))
-               return -ENODEV;
-       if (is_streaming(dev))
-               return -EBUSY;
-       if (dev->owner && dev->owner != filp)
-               return -EBUSY;
-       ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd);
-       if (ret)
-               return ret;
-       dev->owner = filp;
-
-       dev->vsettings.palette = fmtd->fmt.pix.pixelformat;
-       stk_free_buffers(dev);
-       dev->frame_size = fmtd->fmt.pix.sizeimage;
-       dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m;
-
-       stk_initialise(dev);
-       return stk_setup_format(dev);
-}
-
-static int stk_vidioc_reqbufs(struct file *filp,
-               void *priv, struct v4l2_requestbuffers *rb)
-{
-       struct stk_camera *dev = priv;
-
-       if (dev == NULL)
-               return -ENODEV;
-       if (rb->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-       if (is_streaming(dev)
-               || (dev->owner && dev->owner != filp))
-               return -EBUSY;
-       dev->owner = filp;
-
-       /*FIXME If they ask for zero, we must stop streaming and free */
-       if (rb->count < 3)
-               rb->count = 3;
-       /* Arbitrary limit */
-       else if (rb->count > 5)
-               rb->count = 5;
-
-       stk_allocate_buffers(dev, rb->count);
-       rb->count = dev->n_sbufs;
-       return 0;
-}
-
-static int stk_vidioc_querybuf(struct file *filp,
-               void *priv, struct v4l2_buffer *buf)
-{
-       struct stk_camera *dev = priv;
-       struct stk_sio_buffer *sbuf;
-
-       if (buf->index >= dev->n_sbufs)
-               return -EINVAL;
-       sbuf = dev->sio_bufs + buf->index;
-       *buf = sbuf->v4lbuf;
-       return 0;
-}
-
-static int stk_vidioc_qbuf(struct file *filp,
-               void *priv, struct v4l2_buffer *buf)
-{
-       struct stk_camera *dev = priv;
-       struct stk_sio_buffer *sbuf;
-       unsigned long flags;
-
-       if (buf->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-
-       if (buf->index >= dev->n_sbufs)
-               return -EINVAL;
-       sbuf = dev->sio_bufs + buf->index;
-       if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED)
-               return 0;
-       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED;
-       sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE;
-       spin_lock_irqsave(&dev->spinlock, flags);
-       list_add_tail(&sbuf->list, &dev->sio_avail);
-       *buf = sbuf->v4lbuf;
-       spin_unlock_irqrestore(&dev->spinlock, flags);
-       return 0;
-}
-
-static int stk_vidioc_dqbuf(struct file *filp,
-               void *priv, struct v4l2_buffer *buf)
-{
-       struct stk_camera *dev = priv;
-       struct stk_sio_buffer *sbuf;
-       unsigned long flags;
-       int ret;
-
-       if (!is_streaming(dev))
-               return -EINVAL;
-
-       if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full))
-               return -EWOULDBLOCK;
-       ret = wait_event_interruptible(dev->wait_frame,
-               !list_empty(&dev->sio_full) || !is_present(dev));
-       if (ret)
-               return ret;
-       if (!is_present(dev))
-               return -EIO;
-
-       spin_lock_irqsave(&dev->spinlock, flags);
-       sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list);
-       list_del_init(&sbuf->list);
-       spin_unlock_irqrestore(&dev->spinlock, flags);
-       sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
-       sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;
-       sbuf->v4lbuf.sequence = ++dev->sequence;
-       do_gettimeofday(&sbuf->v4lbuf.timestamp);
-
-       *buf = sbuf->v4lbuf;
-       return 0;
-}
-
-static int stk_vidioc_streamon(struct file *filp,
-               void *priv, enum v4l2_buf_type type)
-{
-       struct stk_camera *dev = priv;
-       if (is_streaming(dev))
-               return 0;
-       if (dev->sio_bufs == NULL)
-               return -EINVAL;
-       dev->sequence = 0;
-       return stk_start_stream(dev);
-}
-
-static int stk_vidioc_streamoff(struct file *filp,
-               void *priv, enum v4l2_buf_type type)
-{
-       struct stk_camera *dev = priv;
-       unsigned long flags;
-       int i;
-       stk_stop_stream(dev);
-       spin_lock_irqsave(&dev->spinlock, flags);
-       INIT_LIST_HEAD(&dev->sio_avail);
-       INIT_LIST_HEAD(&dev->sio_full);
-       for (i = 0; i < dev->n_sbufs; i++) {
-               INIT_LIST_HEAD(&dev->sio_bufs[i].list);
-               dev->sio_bufs[i].v4lbuf.flags = 0;
-       }
-       spin_unlock_irqrestore(&dev->spinlock, flags);
-       return 0;
-}
-
-
-static int stk_vidioc_g_parm(struct file *filp,
-               void *priv, struct v4l2_streamparm *sp)
-{
-       /*FIXME This is not correct */
-       sp->parm.capture.timeperframe.numerator = 1;
-       sp->parm.capture.timeperframe.denominator = 30;
-       sp->parm.capture.readbuffers = 2;
-       return 0;
-}
-
-static int stk_vidioc_enum_framesizes(struct file *filp,
-               void *priv, struct v4l2_frmsizeenum *frms)
-{
-       if (frms->index >= ARRAY_SIZE(stk_sizes))
-               return -EINVAL;
-       switch (frms->pixel_format) {
-       case V4L2_PIX_FMT_RGB565:
-       case V4L2_PIX_FMT_RGB565X:
-       case V4L2_PIX_FMT_UYVY:
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_SBGGR8:
-               frms->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-               frms->discrete.width = stk_sizes[frms->index].w;
-               frms->discrete.height = stk_sizes[frms->index].h;
-               return 0;
-       default: return -EINVAL;
-       }
-}
-
-static struct v4l2_file_operations v4l_stk_fops = {
-       .owner = THIS_MODULE,
-       .open = v4l_stk_open,
-       .release = v4l_stk_release,
-       .read = v4l_stk_read,
-       .poll = v4l_stk_poll,
-       .mmap = v4l_stk_mmap,
-       .ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
-       .vidioc_querycap = stk_vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap,
-       .vidioc_enum_input = stk_vidioc_enum_input,
-       .vidioc_s_input = stk_vidioc_s_input,
-       .vidioc_g_input = stk_vidioc_g_input,
-       .vidioc_s_std = stk_vidioc_s_std,
-       .vidioc_reqbufs = stk_vidioc_reqbufs,
-       .vidioc_querybuf = stk_vidioc_querybuf,
-       .vidioc_qbuf = stk_vidioc_qbuf,
-       .vidioc_dqbuf = stk_vidioc_dqbuf,
-       .vidioc_streamon = stk_vidioc_streamon,
-       .vidioc_streamoff = stk_vidioc_streamoff,
-       .vidioc_queryctrl = stk_vidioc_queryctrl,
-       .vidioc_g_ctrl = stk_vidioc_g_ctrl,
-       .vidioc_s_ctrl = stk_vidioc_s_ctrl,
-       .vidioc_g_parm = stk_vidioc_g_parm,
-       .vidioc_enum_framesizes = stk_vidioc_enum_framesizes,
-};
-
-static void stk_v4l_dev_release(struct video_device *vd)
-{
-       struct stk_camera *dev = vdev_to_camera(vd);
-
-       if (dev->sio_bufs != NULL || dev->isobufs != NULL)
-               STK_ERROR("We are leaking memory\n");
-       usb_put_intf(dev->interface);
-       kfree(dev);
-}
-
-static struct video_device stk_v4l_data = {
-       .name = "stkwebcam",
-       .tvnorms = V4L2_STD_UNKNOWN,
-       .current_norm = V4L2_STD_UNKNOWN,
-       .fops = &v4l_stk_fops,
-       .ioctl_ops = &v4l_stk_ioctl_ops,
-       .release = stk_v4l_dev_release,
-};
-
-
-static int stk_register_video_device(struct stk_camera *dev)
-{
-       int err;
-
-       dev->vdev = stk_v4l_data;
-       dev->vdev.debug = debug;
-       dev->vdev.parent = &dev->interface->dev;
-       err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
-       if (err)
-               STK_ERROR("v4l registration failed\n");
-       else
-               STK_INFO("Syntek USB2.0 Camera is now controlling device %s\n",
-                        video_device_node_name(&dev->vdev));
-       return err;
-}
-
-
-/* USB Stuff */
-
-static int stk_camera_probe(struct usb_interface *interface,
-               const struct usb_device_id *id)
-{
-       int i;
-       int err = 0;
-
-       struct stk_camera *dev = NULL;
-       struct usb_device *udev = interface_to_usbdev(interface);
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-
-       dev = kzalloc(sizeof(struct stk_camera), GFP_KERNEL);
-       if (dev == NULL) {
-               STK_ERROR("Out of memory !\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_init(&dev->spinlock);
-       init_waitqueue_head(&dev->wait_frame);
-
-       dev->udev = udev;
-       dev->interface = interface;
-       usb_get_intf(interface);
-
-       dev->vsettings.vflip = vflip;
-       dev->vsettings.hflip = hflip;
-       dev->n_sbufs = 0;
-       set_present(dev);
-
-       /* Set up the endpoint information
-        * use only the first isoc-in endpoint
-        * for the current alternate setting */
-       iface_desc = interface->cur_altsetting;
-
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-               endpoint = &iface_desc->endpoint[i].desc;
-
-               if (!dev->isoc_ep
-                       && usb_endpoint_is_isoc_in(endpoint)) {
-                       /* we found an isoc in endpoint */
-                       dev->isoc_ep = usb_endpoint_num(endpoint);
-                       break;
-               }
-       }
-       if (!dev->isoc_ep) {
-               STK_ERROR("Could not find isoc-in endpoint");
-               err = -ENODEV;
-               goto error;
-       }
-       dev->vsettings.brightness = 0x7fff;
-       dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
-       dev->vsettings.mode = MODE_VGA;
-       dev->frame_size = 640 * 480 * 2;
-
-       INIT_LIST_HEAD(&dev->sio_avail);
-       INIT_LIST_HEAD(&dev->sio_full);
-
-       usb_set_intfdata(interface, dev);
-
-       err = stk_register_video_device(dev);
-       if (err)
-               goto error;
-
-       return 0;
-
-error:
-       kfree(dev);
-       return err;
-}
-
-static void stk_camera_disconnect(struct usb_interface *interface)
-{
-       struct stk_camera *dev = usb_get_intfdata(interface);
-
-       usb_set_intfdata(interface, NULL);
-       unset_present(dev);
-
-       wake_up_interruptible(&dev->wait_frame);
-
-       STK_INFO("Syntek USB2.0 Camera release resources device %s\n",
-                video_device_node_name(&dev->vdev));
-
-       video_unregister_device(&dev->vdev);
-}
-
-#ifdef CONFIG_PM
-static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
-{
-       struct stk_camera *dev = usb_get_intfdata(intf);
-       if (is_streaming(dev)) {
-               stk_stop_stream(dev);
-               /* yes, this is ugly */
-               set_streaming(dev);
-       }
-       return 0;
-}
-
-static int stk_camera_resume(struct usb_interface *intf)
-{
-       struct stk_camera *dev = usb_get_intfdata(intf);
-       if (!is_initialised(dev))
-               return 0;
-       unset_initialised(dev);
-       stk_initialise(dev);
-       stk_camera_write_reg(dev, 0x0, 0x49);
-       stk_setup_format(dev);
-       if (is_streaming(dev))
-               stk_start_stream(dev);
-       return 0;
-}
-#endif
-
-static struct usb_driver stk_camera_driver = {
-       .name = "stkwebcam",
-       .probe = stk_camera_probe,
-       .disconnect = stk_camera_disconnect,
-       .id_table = stkwebcam_table,
-#ifdef CONFIG_PM
-       .suspend = stk_camera_suspend,
-       .resume = stk_camera_resume,
-#endif
-};
-
-module_usb_driver(stk_camera_driver);
diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h
deleted file mode 100644 (file)
index 9f67366..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * stk-webcam.h : Driver for Syntek 1125 USB webcam controller
- *
- * Copyright (C) 2006 Nicolas VIVIEN
- * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef STKWEBCAM_H
-#define STKWEBCAM_H
-
-#include <linux/usb.h>
-#include <media/v4l2-common.h>
-
-#define DRIVER_VERSION         "v0.0.1"
-#define DRIVER_VERSION_NUM     0x000001
-
-#define MAX_ISO_BUFS           3
-#define ISO_FRAMES_PER_DESC    16
-#define ISO_MAX_FRAME_SIZE     3 * 1024
-#define ISO_BUFFER_SIZE                (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
-
-
-#define PREFIX                         "stkwebcam: "
-#define STK_INFO(str, args...)         printk(KERN_INFO PREFIX str, ##args)
-#define STK_ERROR(str, args...)                printk(KERN_ERR PREFIX str, ##args)
-#define STK_WARNING(str, args...)      printk(KERN_WARNING PREFIX str, ##args)
-
-struct stk_iso_buf {
-       void *data;
-       int length;
-       int read;
-       struct urb *urb;
-};
-
-/* Streaming IO buffers */
-struct stk_sio_buffer {
-       struct v4l2_buffer v4lbuf;
-       char *buffer;
-       int mapcount;
-       struct stk_camera *dev;
-       struct list_head list;
-};
-
-enum stk_mode {MODE_VGA, MODE_SXGA, MODE_CIF, MODE_QVGA, MODE_QCIF};
-
-struct stk_video {
-       enum stk_mode mode;
-       int brightness;
-       __u32 palette;
-       int hflip;
-       int vflip;
-};
-
-enum stk_status {
-       S_PRESENT = 1,
-       S_INITIALISED = 2,
-       S_MEMALLOCD = 4,
-       S_STREAMING = 8,
-};
-#define is_present(dev)                ((dev)->status & S_PRESENT)
-#define is_initialised(dev)    ((dev)->status & S_INITIALISED)
-#define is_streaming(dev)      ((dev)->status & S_STREAMING)
-#define is_memallocd(dev)      ((dev)->status & S_MEMALLOCD)
-#define set_present(dev)       ((dev)->status = S_PRESENT)
-#define unset_present(dev)     ((dev)->status &= \
-                                       ~(S_PRESENT|S_INITIALISED|S_STREAMING))
-#define set_initialised(dev)   ((dev)->status |= S_INITIALISED)
-#define unset_initialised(dev) ((dev)->status &= ~S_INITIALISED)
-#define set_memallocd(dev)     ((dev)->status |= S_MEMALLOCD)
-#define unset_memallocd(dev)   ((dev)->status &= ~S_MEMALLOCD)
-#define set_streaming(dev)     ((dev)->status |= S_STREAMING)
-#define unset_streaming(dev)   ((dev)->status &= ~S_STREAMING)
-
-struct regval {
-       unsigned reg;
-       unsigned val;
-};
-
-struct stk_camera {
-       struct video_device vdev;
-       struct usb_device *udev;
-       struct usb_interface *interface;
-       int webcam_model;
-       struct file *owner;
-
-       u8 isoc_ep;
-
-       /* Not sure if this is right */
-       atomic_t urbs_used;
-
-       struct stk_video vsettings;
-
-       enum stk_status status;
-
-       spinlock_t spinlock;
-       wait_queue_head_t wait_frame;
-
-       struct stk_iso_buf *isobufs;
-
-       int frame_size;
-       /* Streaming buffers */
-       unsigned int n_sbufs;
-       struct stk_sio_buffer *sio_bufs;
-       struct list_head sio_avail;
-       struct list_head sio_full;
-       unsigned sequence;
-};
-
-#define vdev_to_camera(d) container_of(d, struct stk_camera, vdev)
-
-int stk_camera_write_reg(struct stk_camera *, u16, u8);
-int stk_camera_read_reg(struct stk_camera *, u16, int *);
-
-int stk_sensor_init(struct stk_camera *);
-int stk_sensor_configure(struct stk_camera *);
-int stk_sensor_sleep(struct stk_camera *dev);
-int stk_sensor_wakeup(struct stk_camera *dev);
-int stk_sensor_set_brightness(struct stk_camera *dev, int br);
-
-#endif
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
deleted file mode 100644 (file)
index 9afab35..0000000
+++ /dev/null
@@ -1,1643 +0,0 @@
-/*
- * Zoran 364xx based USB webcam module version 0.73
- *
- * Allows you to use your USB webcam with V4L2 applications
- * This is still in heavy developpement !
- *
- * Copyright (C) 2004  Antoine Jacquet <royale@zerezo.com>
- * http://royale.zerezo.com/zr364xx/
- *
- * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers
- * V4L2 version inspired by meye.c driver
- *
- * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/highmem.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf-vmalloc.h>
-
-
-/* Version Information */
-#define DRIVER_VERSION "0.7.4"
-#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
-#define DRIVER_DESC "Zoran 364xx"
-
-
-/* Camera */
-#define FRAMES 1
-#define MAX_FRAME_SIZE 200000
-#define BUFFER_SIZE 0x1000
-#define CTRL_TIMEOUT 500
-
-#define ZR364XX_DEF_BUFS       4
-#define ZR364XX_READ_IDLE      0
-#define ZR364XX_READ_FRAME     1
-
-/* Debug macro */
-#define DBG(fmt, args...) \
-       do { \
-               if (debug) { \
-                       printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
-               } \
-       } while (0)
-
-/*#define FULL_DEBUG 1*/
-#ifdef FULL_DEBUG
-#define _DBG DBG
-#else
-#define _DBG(fmt, args...)
-#endif
-
-/* Init methods, need to find nicer names for these
- * the exact names of the chipsets would be the best if someone finds it */
-#define METHOD0 0
-#define METHOD1 1
-#define METHOD2 2
-#define METHOD3 3
-
-
-/* Module parameters */
-static int debug;
-static int mode;
-
-
-/* Module parameters interface */
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level");
-module_param(mode, int, 0644);
-MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
-
-
-/* Devices supported by this driver
- * .driver_info contains the init method used by the camera */
-static struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
-       {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
-       {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
-       {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
-       {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
-       {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
-       {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
-       {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
-       {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
-       {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
-       {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
-       {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 },
-       {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
-       {}                      /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* frame structure */
-struct zr364xx_framei {
-       unsigned long ulState;  /* ulState:ZR364XX_READ_IDLE,
-                                          ZR364XX_READ_FRAME */
-       void *lpvbits;          /* image data */
-       unsigned long cur_size; /* current data copied to it */
-};
-
-/* image buffer structure */
-struct zr364xx_bufferi {
-       unsigned long dwFrames;                 /* number of frames in buffer */
-       struct zr364xx_framei frame[FRAMES];    /* array of FRAME structures */
-};
-
-struct zr364xx_dmaqueue {
-       struct list_head        active;
-       struct zr364xx_camera   *cam;
-};
-
-struct zr364xx_pipeinfo {
-       u32 transfer_size;
-       u8 *transfer_buffer;
-       u32 state;
-       void *stream_urb;
-       void *cam;      /* back pointer to zr364xx_camera struct */
-       u32 err_count;
-       u32 idx;
-};
-
-struct zr364xx_fmt {
-       char *name;
-       u32 fourcc;
-       int depth;
-};
-
-/* image formats.  */
-static const struct zr364xx_fmt formats[] = {
-       {
-               .name = "JPG",
-               .fourcc = V4L2_PIX_FMT_JPEG,
-               .depth = 24
-       }
-};
-
-/* Camera stuff */
-struct zr364xx_camera {
-       struct usb_device *udev;        /* save off the usb device pointer */
-       struct usb_interface *interface;/* the interface for this device */
-       struct v4l2_device v4l2_dev;
-       struct v4l2_ctrl_handler ctrl_handler;
-       struct video_device vdev;       /* v4l video device */
-       struct v4l2_fh *owner;          /* owns the streaming */
-       int nb;
-       struct zr364xx_bufferi          buffer;
-       int skip;
-       int width;
-       int height;
-       int method;
-       struct mutex lock;
-
-       spinlock_t              slock;
-       struct zr364xx_dmaqueue vidq;
-       int                     last_frame;
-       int                     cur_frame;
-       unsigned long           frame_count;
-       int                     b_acquire;
-       struct zr364xx_pipeinfo pipe[1];
-
-       u8                      read_endpoint;
-
-       const struct zr364xx_fmt *fmt;
-       struct videobuf_queue   vb_vidq;
-       bool was_streaming;
-};
-
-/* buffer for one video frame */
-struct zr364xx_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-       const struct zr364xx_fmt *fmt;
-};
-
-/* function used to send initialisation commands to the camera */
-static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
-                           u16 index, unsigned char *cp, u16 size)
-{
-       int status;
-
-       unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
-       if (!transfer_buffer) {
-               dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
-               return -ENOMEM;
-       }
-
-       memcpy(transfer_buffer, cp, size);
-
-       status = usb_control_msg(udev,
-                                usb_sndctrlpipe(udev, 0),
-                                request,
-                                USB_DIR_OUT | USB_TYPE_VENDOR |
-                                USB_RECIP_DEVICE, value, index,
-                                transfer_buffer, size, CTRL_TIMEOUT);
-
-       kfree(transfer_buffer);
-       return status;
-}
-
-
-/* Control messages sent to the camera to initialize it
- * and launch the capture */
-typedef struct {
-       unsigned int value;
-       unsigned int size;
-       unsigned char *bytes;
-} message;
-
-/* method 0 */
-static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
-static unsigned char m0d3[] = { 0, 0 };
-static message m0[] = {
-       {0x1f30, 0, NULL},
-       {0xd000, 0, NULL},
-       {0x3370, sizeof(m0d1), m0d1},
-       {0x2000, 0, NULL},
-       {0x2f0f, 0, NULL},
-       {0x2610, sizeof(m0d2), m0d2},
-       {0xe107, 0, NULL},
-       {0x2502, 0, NULL},
-       {0x1f70, 0, NULL},
-       {0xd000, 0, NULL},
-       {0x9a01, sizeof(m0d3), m0d3},
-       {-1, -1, NULL}
-};
-
-/* method 1 */
-static unsigned char m1d1[] = { 0xff, 0xff };
-static unsigned char m1d2[] = { 0x00, 0x00 };
-static message m1[] = {
-       {0x1f30, 0, NULL},
-       {0xd000, 0, NULL},
-       {0xf000, 0, NULL},
-       {0x2000, 0, NULL},
-       {0x2f0f, 0, NULL},
-       {0x2650, 0, NULL},
-       {0xe107, 0, NULL},
-       {0x2502, sizeof(m1d1), m1d1},
-       {0x1f70, 0, NULL},
-       {0xd000, 0, NULL},
-       {0xd000, 0, NULL},
-       {0xd000, 0, NULL},
-       {0x9a01, sizeof(m1d2), m1d2},
-       {-1, -1, NULL}
-};
-
-/* method 2 */
-static unsigned char m2d1[] = { 0xff, 0xff };
-static message m2[] = {
-       {0x1f30, 0, NULL},
-       {0xf000, 0, NULL},
-       {0x2000, 0, NULL},
-       {0x2f0f, 0, NULL},
-       {0x2650, 0, NULL},
-       {0xe107, 0, NULL},
-       {0x2502, sizeof(m2d1), m2d1},
-       {0x1f70, 0, NULL},
-       {-1, -1, NULL}
-};
-
-/* init table */
-static message *init[4] = { m0, m1, m2, m2 };
-
-
-/* JPEG static data in header (Huffman table, etc) */
-static unsigned char header1[] = {
-       0xFF, 0xD8,
-       /*
-       0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
-       0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
-       */
-       0xFF, 0xDB, 0x00, 0x84
-};
-static unsigned char header2[] = {
-       0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
-       0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
-       0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
-       0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
-       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
-       0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
-       0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-       0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
-       0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
-       0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
-       0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
-       0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
-       0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
-       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
-       0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
-       0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
-       0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
-       0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
-       0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
-       0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
-       0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
-       0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
-       0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
-       0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
-       0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
-       0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
-       0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
-       0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
-       0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
-       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
-       0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
-       0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
-       0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-       0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
-       0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
-       0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
-       0x00, 0x3F, 0x00
-};
-static unsigned char header3;
-
-/* ------------------------------------------------------------------
-   Videobuf operations
-   ------------------------------------------------------------------*/
-
-static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-                       unsigned int *size)
-{
-       struct zr364xx_camera *cam = vq->priv_data;
-
-       *size = cam->width * cam->height * (cam->fmt->depth >> 3);
-
-       if (*count == 0)
-               *count = ZR364XX_DEF_BUFS;
-
-       if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024)
-               *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size;
-
-       return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
-{
-       _DBG("%s\n", __func__);
-
-       if (in_interrupt())
-               BUG();
-
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                         enum v4l2_field field)
-{
-       struct zr364xx_camera *cam = vq->priv_data;
-       struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
-                                                 vb);
-       int rc;
-
-       DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
-           cam->fmt->name : "");
-       if (cam->fmt == NULL)
-               return -EINVAL;
-
-       buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
-
-       if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
-               DBG("invalid buffer prepare\n");
-               return -EINVAL;
-       }
-
-       buf->fmt = cam->fmt;
-       buf->vb.width = cam->width;
-       buf->vb.height = cam->height;
-       buf->vb.field = field;
-
-       if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
-                                                 vb);
-       struct zr364xx_camera *cam = vq->priv_data;
-
-       _DBG("%s\n", __func__);
-
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &cam->vidq.active);
-}
-
-static void buffer_release(struct videobuf_queue *vq,
-                          struct videobuf_buffer *vb)
-{
-       struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
-                                                 vb);
-
-       _DBG("%s\n", __func__);
-       free_buffer(vq, buf);
-}
-
-static struct videobuf_queue_ops zr364xx_video_qops = {
-       .buf_setup = buffer_setup,
-       .buf_prepare = buffer_prepare,
-       .buf_queue = buffer_queue,
-       .buf_release = buffer_release,
-};
-
-/********************/
-/* V4L2 integration */
-/********************/
-static int zr364xx_vidioc_streamon(struct file *file, void *priv,
-                                  enum v4l2_buf_type type);
-
-static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
-                           loff_t * ppos)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-       int err = 0;
-
-       _DBG("%s\n", __func__);
-
-       if (!buf)
-               return -EINVAL;
-
-       if (!count)
-               return -EINVAL;
-
-       if (mutex_lock_interruptible(&cam->lock))
-               return -ERESTARTSYS;
-
-       err = zr364xx_vidioc_streamon(file, file->private_data,
-                               V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       if (err == 0) {
-               DBG("%s: reading %d bytes at pos %d.\n", __func__,
-                               (int) count, (int) *ppos);
-
-               /* NoMan Sux ! */
-               err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
-                                       file->f_flags & O_NONBLOCK);
-       }
-       mutex_unlock(&cam->lock);
-       return err;
-}
-
-/* video buffer vmalloc implementation based partly on VIVI driver which is
- *          Copyright (c) 2006 by
- *                  Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
- *                  Ted Walther <ted--a.t--enumera.com>
- *                  John Sokol <sokol--a.t--videotechnology.com>
- *                  http://v4l.videotechnology.com/
- *
- */
-static void zr364xx_fillbuff(struct zr364xx_camera *cam,
-                            struct zr364xx_buffer *buf,
-                            int jpgsize)
-{
-       int pos = 0;
-       struct timeval ts;
-       const char *tmpbuf;
-       char *vbuf = videobuf_to_vmalloc(&buf->vb);
-       unsigned long last_frame;
-
-       if (!vbuf)
-               return;
-
-       last_frame = cam->last_frame;
-       if (last_frame != -1) {
-               tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
-               switch (buf->fmt->fourcc) {
-               case V4L2_PIX_FMT_JPEG:
-                       buf->vb.size = jpgsize;
-                       memcpy(vbuf, tmpbuf, buf->vb.size);
-                       break;
-               default:
-                       printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
-               }
-               cam->last_frame = -1;
-       } else {
-               printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
-               return;
-       }
-       DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
-               (unsigned long)vbuf, pos);
-       /* tell v4l buffer was filled */
-
-       buf->vb.field_count = cam->frame_count * 2;
-       do_gettimeofday(&ts);
-       buf->vb.ts = ts;
-       buf->vb.state = VIDEOBUF_DONE;
-}
-
-static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
-{
-       struct zr364xx_dmaqueue *dma_q = &cam->vidq;
-       struct zr364xx_buffer *buf;
-       unsigned long flags = 0;
-       int rc = 0;
-
-       DBG("wakeup: %p\n", &dma_q);
-       spin_lock_irqsave(&cam->slock, flags);
-
-       if (list_empty(&dma_q->active)) {
-               DBG("No active queue to serve\n");
-               rc = -1;
-               goto unlock;
-       }
-       buf = list_entry(dma_q->active.next,
-                        struct zr364xx_buffer, vb.queue);
-
-       if (!waitqueue_active(&buf->vb.done)) {
-               /* no one active */
-               rc = -1;
-               goto unlock;
-       }
-       list_del(&buf->vb.queue);
-       do_gettimeofday(&buf->vb.ts);
-       DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
-       zr364xx_fillbuff(cam, buf, jpgsize);
-       wake_up(&buf->vb.done);
-       DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
-unlock:
-       spin_unlock_irqrestore(&cam->slock, flags);
-       return rc;
-}
-
-/* this function moves the usb stream read pipe data
- * into the system buffers.
- * returns 0 on success, EAGAIN if more data to process (call this
- * function again).
- */
-static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
-                                       struct zr364xx_pipeinfo *pipe_info,
-                                       struct urb *purb)
-{
-       unsigned char *pdest;
-       unsigned char *psrc;
-       s32 idx = -1;
-       struct zr364xx_framei *frm;
-       int i = 0;
-       unsigned char *ptr = NULL;
-
-       _DBG("buffer to user\n");
-       idx = cam->cur_frame;
-       frm = &cam->buffer.frame[idx];
-
-       /* swap bytes if camera needs it */
-       if (cam->method == METHOD0) {
-               u16 *buf = (u16 *)pipe_info->transfer_buffer;
-               for (i = 0; i < purb->actual_length/2; i++)
-                       swab16s(buf + i);
-       }
-
-       /* search done.  now find out if should be acquiring */
-       if (!cam->b_acquire) {
-               /* we found a frame, but this channel is turned off */
-               frm->ulState = ZR364XX_READ_IDLE;
-               return -EINVAL;
-       }
-
-       psrc = (u8 *)pipe_info->transfer_buffer;
-       ptr = pdest = frm->lpvbits;
-
-       if (frm->ulState == ZR364XX_READ_IDLE) {
-               frm->ulState = ZR364XX_READ_FRAME;
-               frm->cur_size = 0;
-
-               _DBG("jpeg header, ");
-               memcpy(ptr, header1, sizeof(header1));
-               ptr += sizeof(header1);
-               header3 = 0;
-               memcpy(ptr, &header3, 1);
-               ptr++;
-               memcpy(ptr, psrc, 64);
-               ptr += 64;
-               header3 = 1;
-               memcpy(ptr, &header3, 1);
-               ptr++;
-               memcpy(ptr, psrc + 64, 64);
-               ptr += 64;
-               memcpy(ptr, header2, sizeof(header2));
-               ptr += sizeof(header2);
-               memcpy(ptr, psrc + 128,
-                      purb->actual_length - 128);
-               ptr += purb->actual_length - 128;
-               _DBG("header : %d %d %d %d %d %d %d %d %d\n",
-                   psrc[0], psrc[1], psrc[2],
-                   psrc[3], psrc[4], psrc[5],
-                   psrc[6], psrc[7], psrc[8]);
-               frm->cur_size = ptr - pdest;
-       } else {
-               if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
-                       dev_info(&cam->udev->dev,
-                                "%s: buffer (%d bytes) too small to hold "
-                                "frame data. Discarding frame data.\n",
-                                __func__, MAX_FRAME_SIZE);
-               } else {
-                       pdest += frm->cur_size;
-                       memcpy(pdest, psrc, purb->actual_length);
-                       frm->cur_size += purb->actual_length;
-               }
-       }
-       /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
-               purb->actual_length);*/
-
-       if (purb->actual_length < pipe_info->transfer_size) {
-               _DBG("****************Buffer[%d]full*************\n", idx);
-               cam->last_frame = cam->cur_frame;
-               cam->cur_frame++;
-               /* end of system frame ring buffer, start at zero */
-               if (cam->cur_frame == cam->buffer.dwFrames)
-                       cam->cur_frame = 0;
-
-               /* frame ready */
-               /* go back to find the JPEG EOI marker */
-               ptr = pdest = frm->lpvbits;
-               ptr += frm->cur_size - 2;
-               while (ptr > pdest) {
-                       if (*ptr == 0xFF && *(ptr + 1) == 0xD9
-                           && *(ptr + 2) == 0xFF)
-                               break;
-                       ptr--;
-               }
-               if (ptr == pdest)
-                       DBG("No EOI marker\n");
-
-               /* Sometimes there is junk data in the middle of the picture,
-                * we want to skip this bogus frames */
-               while (ptr > pdest) {
-                       if (*ptr == 0xFF && *(ptr + 1) == 0xFF
-                           && *(ptr + 2) == 0xFF)
-                               break;
-                       ptr--;
-               }
-               if (ptr != pdest) {
-                       DBG("Bogus frame ? %d\n", ++(cam->nb));
-               } else if (cam->b_acquire) {
-                       /* we skip the 2 first frames which are usually buggy */
-                       if (cam->skip)
-                               cam->skip--;
-                       else {
-                               _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
-                                   frm->cur_size,
-                                   pdest[0], pdest[1], pdest[2], pdest[3],
-                                   pdest[4], pdest[5], pdest[6], pdest[7]);
-
-                               zr364xx_got_frame(cam, frm->cur_size);
-                       }
-               }
-               cam->frame_count++;
-               frm->ulState = ZR364XX_READ_IDLE;
-               frm->cur_size = 0;
-       }
-       /* done successfully */
-       return 0;
-}
-
-static int zr364xx_vidioc_querycap(struct file *file, void *priv,
-                                  struct v4l2_capability *cap)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-
-       strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
-       strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
-       strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
-               sizeof(cap->bus_info));
-       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
-                           V4L2_CAP_READWRITE |
-                           V4L2_CAP_STREAMING;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
-       return 0;
-}
-
-static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
-                                    struct v4l2_input *i)
-{
-       if (i->index != 0)
-               return -EINVAL;
-       strcpy(i->name, DRIVER_DESC " Camera");
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-       return 0;
-}
-
-static int zr364xx_vidioc_g_input(struct file *file, void *priv,
-                                 unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int zr364xx_vidioc_s_input(struct file *file, void *priv,
-                                 unsigned int i)
-{
-       if (i != 0)
-               return -EINVAL;
-       return 0;
-}
-
-static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct zr364xx_camera *cam =
-               container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
-       int temp;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               /* hardware brightness */
-               send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
-               temp = (0x60 << 8) + 127 - ctrl->val;
-               send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
-                                      void *priv, struct v4l2_fmtdesc *f)
-{
-       if (f->index > 0)
-               return -EINVAL;
-       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-       strcpy(f->description, formats[0].name);
-       f->pixelformat = formats[0].fourcc;
-       return 0;
-}
-
-static char *decode_fourcc(__u32 pixelformat, char *buf)
-{
-       buf[0] = pixelformat & 0xff;
-       buf[1] = (pixelformat >> 8) & 0xff;
-       buf[2] = (pixelformat >> 16) & 0xff;
-       buf[3] = (pixelformat >> 24) & 0xff;
-       buf[4] = '\0';
-       return buf;
-}
-
-static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                                     struct v4l2_format *f)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-       char pixelformat_name[5];
-
-       if (cam == NULL)
-               return -ENODEV;
-
-       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
-               DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
-                   decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
-               return -EINVAL;
-       }
-
-       if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
-           !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
-               f->fmt.pix.width = 320;
-               f->fmt.pix.height = 240;
-       }
-
-       f->fmt.pix.field = V4L2_FIELD_NONE;
-       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
-       DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
-           decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
-           f->fmt.pix.field);
-       return 0;
-}
-
-static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                   struct v4l2_format *f)
-{
-       struct zr364xx_camera *cam;
-
-       if (file == NULL)
-               return -ENODEV;
-       cam = video_drvdata(file);
-
-       f->fmt.pix.pixelformat = formats[0].fourcc;
-       f->fmt.pix.field = V4L2_FIELD_NONE;
-       f->fmt.pix.width = cam->width;
-       f->fmt.pix.height = cam->height;
-       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
-       return 0;
-}
-
-static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                                   struct v4l2_format *f)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-       struct videobuf_queue *q = &cam->vb_vidq;
-       char pixelformat_name[5];
-       int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
-       int i;
-
-       if (ret < 0)
-               return ret;
-
-       mutex_lock(&q->vb_lock);
-
-       if (videobuf_queue_is_busy(&cam->vb_vidq)) {
-               DBG("%s queue busy\n", __func__);
-               ret = -EBUSY;
-               goto out;
-       }
-
-       if (cam->owner) {
-               DBG("%s can't change format after started\n", __func__);
-               ret = -EBUSY;
-               goto out;
-       }
-
-       cam->width = f->fmt.pix.width;
-       cam->height = f->fmt.pix.height;
-       DBG("%s: %dx%d mode selected\n", __func__,
-                cam->width, cam->height);
-       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
-       cam->vb_vidq.field = f->fmt.pix.field;
-
-       if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
-               mode = 1;
-       else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
-               mode = 2;
-       else
-               mode = 0;
-
-       m0d1[0] = mode;
-       m1[2].value = 0xf000 + mode;
-       m2[1].value = 0xf000 + mode;
-
-       /* special case for METHOD3, the modes are different */
-       if (cam->method == METHOD3) {
-               switch (mode) {
-               case 1:
-                       m2[1].value = 0xf000 + 4;
-                       break;
-               case 2:
-                       m2[1].value = 0xf000 + 0;
-                       break;
-               default:
-                       m2[1].value = 0xf000 + 1;
-                       break;
-               }
-       }
-
-       header2[437] = cam->height / 256;
-       header2[438] = cam->height % 256;
-       header2[439] = cam->width / 256;
-       header2[440] = cam->width % 256;
-
-       for (i = 0; init[cam->method][i].size != -1; i++) {
-               ret =
-                   send_control_msg(cam->udev, 1, init[cam->method][i].value,
-                                    0, init[cam->method][i].bytes,
-                                    init[cam->method][i].size);
-               if (ret < 0) {
-                       dev_err(&cam->udev->dev,
-                          "error during resolution change sequence: %d\n", i);
-                       goto out;
-               }
-       }
-
-       /* Added some delay here, since opening/closing the camera quickly,
-        * like Ekiga does during its startup, can crash the webcam
-        */
-       mdelay(100);
-       cam->skip = 2;
-       ret = 0;
-
-out:
-       mutex_unlock(&q->vb_lock);
-
-       DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
-           decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
-           f->fmt.pix.field);
-       return ret;
-}
-
-static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *p)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-
-       if (cam->owner && cam->owner != priv)
-               return -EBUSY;
-       return videobuf_reqbufs(&cam->vb_vidq, p);
-}
-
-static int zr364xx_vidioc_querybuf(struct file *file,
-                               void *priv,
-                               struct v4l2_buffer *p)
-{
-       int rc;
-       struct zr364xx_camera *cam = video_drvdata(file);
-       rc = videobuf_querybuf(&cam->vb_vidq, p);
-       return rc;
-}
-
-static int zr364xx_vidioc_qbuf(struct file *file,
-                               void *priv,
-                               struct v4l2_buffer *p)
-{
-       int rc;
-       struct zr364xx_camera *cam = video_drvdata(file);
-       _DBG("%s\n", __func__);
-       if (cam->owner && cam->owner != priv)
-               return -EBUSY;
-       rc = videobuf_qbuf(&cam->vb_vidq, p);
-       return rc;
-}
-
-static int zr364xx_vidioc_dqbuf(struct file *file,
-                               void *priv,
-                               struct v4l2_buffer *p)
-{
-       int rc;
-       struct zr364xx_camera *cam = video_drvdata(file);
-       _DBG("%s\n", __func__);
-       if (cam->owner && cam->owner != priv)
-               return -EBUSY;
-       rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
-       return rc;
-}
-
-static void read_pipe_completion(struct urb *purb)
-{
-       struct zr364xx_pipeinfo *pipe_info;
-       struct zr364xx_camera *cam;
-       int pipe;
-
-       pipe_info = purb->context;
-       _DBG("%s %p, status %d\n", __func__, purb, purb->status);
-       if (pipe_info == NULL) {
-               printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
-               return;
-       }
-
-       cam = pipe_info->cam;
-       if (cam == NULL) {
-               printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
-               return;
-       }
-
-       /* if shutting down, do not resubmit, exit immediately */
-       if (purb->status == -ESHUTDOWN) {
-               DBG("%s, err shutdown\n", __func__);
-               pipe_info->err_count++;
-               return;
-       }
-
-       if (pipe_info->state == 0) {
-               DBG("exiting USB pipe\n");
-               return;
-       }
-
-       if (purb->actual_length < 0 ||
-           purb->actual_length > pipe_info->transfer_size) {
-               dev_err(&cam->udev->dev, "wrong number of bytes\n");
-               return;
-       }
-
-       if (purb->status == 0)
-               zr364xx_read_video_callback(cam, pipe_info, purb);
-       else {
-               pipe_info->err_count++;
-               DBG("%s: failed URB %d\n", __func__, purb->status);
-       }
-
-       pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
-
-       /* reuse urb */
-       usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
-                         pipe,
-                         pipe_info->transfer_buffer,
-                         pipe_info->transfer_size,
-                         read_pipe_completion, pipe_info);
-
-       if (pipe_info->state != 0) {
-               purb->status = usb_submit_urb(pipe_info->stream_urb,
-                                             GFP_ATOMIC);
-
-               if (purb->status)
-                       dev_err(&cam->udev->dev,
-                               "error submitting urb (error=%i)\n",
-                               purb->status);
-       } else
-               DBG("read pipe complete state 0\n");
-}
-
-static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
-{
-       int pipe;
-       int retval;
-       struct zr364xx_pipeinfo *pipe_info = cam->pipe;
-       pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
-       DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
-
-       pipe_info->state = 1;
-       pipe_info->err_count = 0;
-       pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!pipe_info->stream_urb) {
-               dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
-               return -ENOMEM;
-       }
-       /* transfer buffer allocated in board_init */
-       usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
-                         pipe,
-                         pipe_info->transfer_buffer,
-                         pipe_info->transfer_size,
-                         read_pipe_completion, pipe_info);
-
-       DBG("submitting URB %p\n", pipe_info->stream_urb);
-       retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
-       if (retval) {
-               printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
-               return retval;
-       }
-
-       return 0;
-}
-
-static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
-{
-       struct zr364xx_pipeinfo *pipe_info;
-
-       if (cam == NULL) {
-               printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
-               return;
-       }
-       DBG("stop read pipe\n");
-       pipe_info = cam->pipe;
-       if (pipe_info) {
-               if (pipe_info->state != 0)
-                       pipe_info->state = 0;
-
-               if (pipe_info->stream_urb) {
-                       /* cancel urb */
-                       usb_kill_urb(pipe_info->stream_urb);
-                       usb_free_urb(pipe_info->stream_urb);
-                       pipe_info->stream_urb = NULL;
-               }
-       }
-       return;
-}
-
-/* starts acquisition process */
-static int zr364xx_start_acquire(struct zr364xx_camera *cam)
-{
-       int j;
-
-       DBG("start acquire\n");
-
-       cam->last_frame = -1;
-       cam->cur_frame = 0;
-       for (j = 0; j < FRAMES; j++) {
-               cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
-               cam->buffer.frame[j].cur_size = 0;
-       }
-       cam->b_acquire = 1;
-       return 0;
-}
-
-static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
-{
-       cam->b_acquire = 0;
-       return 0;
-}
-
-static int zr364xx_prepare(struct zr364xx_camera *cam)
-{
-       int res;
-       int i, j;
-
-       for (i = 0; init[cam->method][i].size != -1; i++) {
-               res = send_control_msg(cam->udev, 1, init[cam->method][i].value,
-                                    0, init[cam->method][i].bytes,
-                                    init[cam->method][i].size);
-               if (res < 0) {
-                       dev_err(&cam->udev->dev,
-                               "error during open sequence: %d\n", i);
-                       return res;
-               }
-       }
-
-       cam->skip = 2;
-       cam->last_frame = -1;
-       cam->cur_frame = 0;
-       cam->frame_count = 0;
-       for (j = 0; j < FRAMES; j++) {
-               cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
-               cam->buffer.frame[j].cur_size = 0;
-       }
-       v4l2_ctrl_handler_setup(&cam->ctrl_handler);
-       return 0;
-}
-
-static int zr364xx_vidioc_streamon(struct file *file, void *priv,
-                                  enum v4l2_buf_type type)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-       int res;
-
-       DBG("%s\n", __func__);
-
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (cam->owner && cam->owner != priv)
-               return -EBUSY;
-
-       res = zr364xx_prepare(cam);
-       if (res)
-               return res;
-       res = videobuf_streamon(&cam->vb_vidq);
-       if (res == 0) {
-               zr364xx_start_acquire(cam);
-               cam->owner = file->private_data;
-       }
-       return res;
-}
-
-static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
-                                   enum v4l2_buf_type type)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-
-       DBG("%s\n", __func__);
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (cam->owner && cam->owner != priv)
-               return -EBUSY;
-       zr364xx_stop_acquire(cam);
-       return videobuf_streamoff(&cam->vb_vidq);
-}
-
-
-/* open the camera */
-static int zr364xx_open(struct file *file)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-       int err;
-
-       DBG("%s\n", __func__);
-
-       if (mutex_lock_interruptible(&cam->lock))
-               return -ERESTARTSYS;
-
-       err = v4l2_fh_open(file);
-       if (err)
-               goto out;
-
-       /* Added some delay here, since opening/closing the camera quickly,
-        * like Ekiga does during its startup, can crash the webcam
-        */
-       mdelay(100);
-       err = 0;
-
-out:
-       mutex_unlock(&cam->lock);
-       DBG("%s: %d\n", __func__, err);
-       return err;
-}
-
-static void zr364xx_release(struct v4l2_device *v4l2_dev)
-{
-       struct zr364xx_camera *cam =
-               container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
-       unsigned long i;
-
-       v4l2_device_unregister(&cam->v4l2_dev);
-
-       videobuf_mmap_free(&cam->vb_vidq);
-
-       /* release sys buffers */
-       for (i = 0; i < FRAMES; i++) {
-               if (cam->buffer.frame[i].lpvbits) {
-                       DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
-                       vfree(cam->buffer.frame[i].lpvbits);
-               }
-               cam->buffer.frame[i].lpvbits = NULL;
-       }
-
-       v4l2_ctrl_handler_free(&cam->ctrl_handler);
-       /* release transfer buffer */
-       kfree(cam->pipe->transfer_buffer);
-       kfree(cam);
-}
-
-/* release the camera */
-static int zr364xx_close(struct file *file)
-{
-       struct zr364xx_camera *cam;
-       struct usb_device *udev;
-       int i;
-
-       DBG("%s\n", __func__);
-       cam = video_drvdata(file);
-
-       mutex_lock(&cam->lock);
-       udev = cam->udev;
-
-       if (file->private_data == cam->owner) {
-               /* turn off stream */
-               if (cam->b_acquire)
-                       zr364xx_stop_acquire(cam);
-               videobuf_streamoff(&cam->vb_vidq);
-
-               for (i = 0; i < 2; i++) {
-                       send_control_msg(udev, 1, init[cam->method][i].value,
-                                       0, init[cam->method][i].bytes,
-                                       init[cam->method][i].size);
-               }
-               cam->owner = NULL;
-       }
-
-       /* Added some delay here, since opening/closing the camera quickly,
-        * like Ekiga does during its startup, can crash the webcam
-        */
-       mdelay(100);
-       mutex_unlock(&cam->lock);
-       return v4l2_fh_release(file);
-}
-
-
-static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-       int ret;
-
-       if (cam == NULL) {
-               DBG("%s: cam == NULL\n", __func__);
-               return -ENODEV;
-       }
-       DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
-
-       ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
-
-       DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
-               (unsigned long)vma->vm_start,
-               (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
-       return ret;
-}
-
-static unsigned int zr364xx_poll(struct file *file,
-                              struct poll_table_struct *wait)
-{
-       struct zr364xx_camera *cam = video_drvdata(file);
-       struct videobuf_queue *q = &cam->vb_vidq;
-       unsigned res = v4l2_ctrl_poll(file, wait);
-
-       _DBG("%s\n", __func__);
-
-       return res | videobuf_poll_stream(file, q, wait);
-}
-
-static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
-       .s_ctrl = zr364xx_s_ctrl,
-};
-
-static const struct v4l2_file_operations zr364xx_fops = {
-       .owner = THIS_MODULE,
-       .open = zr364xx_open,
-       .release = zr364xx_close,
-       .read = zr364xx_read,
-       .mmap = zr364xx_mmap,
-       .unlocked_ioctl = video_ioctl2,
-       .poll = zr364xx_poll,
-};
-
-static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
-       .vidioc_querycap        = zr364xx_vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap   = zr364xx_vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap   = zr364xx_vidioc_g_fmt_vid_cap,
-       .vidioc_enum_input      = zr364xx_vidioc_enum_input,
-       .vidioc_g_input         = zr364xx_vidioc_g_input,
-       .vidioc_s_input         = zr364xx_vidioc_s_input,
-       .vidioc_streamon        = zr364xx_vidioc_streamon,
-       .vidioc_streamoff       = zr364xx_vidioc_streamoff,
-       .vidioc_reqbufs         = zr364xx_vidioc_reqbufs,
-       .vidioc_querybuf        = zr364xx_vidioc_querybuf,
-       .vidioc_qbuf            = zr364xx_vidioc_qbuf,
-       .vidioc_dqbuf           = zr364xx_vidioc_dqbuf,
-       .vidioc_log_status      = v4l2_ctrl_log_status,
-       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static struct video_device zr364xx_template = {
-       .name = DRIVER_DESC,
-       .fops = &zr364xx_fops,
-       .ioctl_ops = &zr364xx_ioctl_ops,
-       .release = video_device_release_empty,
-};
-
-
-
-/*******************/
-/* USB integration */
-/*******************/
-static int zr364xx_board_init(struct zr364xx_camera *cam)
-{
-       struct zr364xx_pipeinfo *pipe = cam->pipe;
-       unsigned long i;
-
-       DBG("board init: %p\n", cam);
-       memset(pipe, 0, sizeof(*pipe));
-       pipe->cam = cam;
-       pipe->transfer_size = BUFFER_SIZE;
-
-       pipe->transfer_buffer = kzalloc(pipe->transfer_size,
-                                       GFP_KERNEL);
-       if (pipe->transfer_buffer == NULL) {
-               DBG("out of memory!\n");
-               return -ENOMEM;
-       }
-
-       cam->b_acquire = 0;
-       cam->frame_count = 0;
-
-       /*** start create system buffers ***/
-       for (i = 0; i < FRAMES; i++) {
-               /* always allocate maximum size for system buffers */
-               cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
-
-               DBG("valloc %p, idx %lu, pdata %p\n",
-                       &cam->buffer.frame[i], i,
-                       cam->buffer.frame[i].lpvbits);
-               if (cam->buffer.frame[i].lpvbits == NULL) {
-                       printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
-                              "Using less frames\n");
-                       break;
-               }
-       }
-
-       if (i == 0) {
-               printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
-               kfree(cam->pipe->transfer_buffer);
-               cam->pipe->transfer_buffer = NULL;
-               return -ENOMEM;
-       } else
-               cam->buffer.dwFrames = i;
-
-       /* make sure internal states are set */
-       for (i = 0; i < FRAMES; i++) {
-               cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
-               cam->buffer.frame[i].cur_size = 0;
-       }
-
-       cam->cur_frame = 0;
-       cam->last_frame = -1;
-       /*** end create system buffers ***/
-
-       /* start read pipe */
-       zr364xx_start_readpipe(cam);
-       DBG(": board initialized\n");
-       return 0;
-}
-
-static int zr364xx_probe(struct usb_interface *intf,
-                        const struct usb_device_id *id)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct zr364xx_camera *cam = NULL;
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-       struct v4l2_ctrl_handler *hdl;
-       int err;
-       int i;
-
-       DBG("probing...\n");
-
-       dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
-       dev_info(&intf->dev, "model %04x:%04x detected\n",
-                le16_to_cpu(udev->descriptor.idVendor),
-                le16_to_cpu(udev->descriptor.idProduct));
-
-       cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
-       if (cam == NULL) {
-               dev_err(&udev->dev, "cam: out of memory !\n");
-               return -ENOMEM;
-       }
-
-       cam->v4l2_dev.release = zr364xx_release;
-       err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
-       if (err < 0) {
-               dev_err(&udev->dev, "couldn't register v4l2_device\n");
-               kfree(cam);
-               return err;
-       }
-       hdl = &cam->ctrl_handler;
-       v4l2_ctrl_handler_init(hdl, 1);
-       v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
-                         V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
-       if (hdl->error) {
-               err = hdl->error;
-               dev_err(&udev->dev, "couldn't register control\n");
-               goto fail;
-       }
-       /* save the init method used by this camera */
-       cam->method = id->driver_info;
-       mutex_init(&cam->lock);
-       cam->vdev = zr364xx_template;
-       cam->vdev.lock = &cam->lock;
-       cam->vdev.v4l2_dev = &cam->v4l2_dev;
-       cam->vdev.ctrl_handler = &cam->ctrl_handler;
-       set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
-       video_set_drvdata(&cam->vdev, cam);
-       if (debug)
-               cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
-
-       cam->udev = udev;
-
-       switch (mode) {
-       case 1:
-               dev_info(&udev->dev, "160x120 mode selected\n");
-               cam->width = 160;
-               cam->height = 120;
-               break;
-       case 2:
-               dev_info(&udev->dev, "640x480 mode selected\n");
-               cam->width = 640;
-               cam->height = 480;
-               break;
-       default:
-               dev_info(&udev->dev, "320x240 mode selected\n");
-               cam->width = 320;
-               cam->height = 240;
-               break;
-       }
-
-       m0d1[0] = mode;
-       m1[2].value = 0xf000 + mode;
-       m2[1].value = 0xf000 + mode;
-
-       /* special case for METHOD3, the modes are different */
-       if (cam->method == METHOD3) {
-               switch (mode) {
-               case 1:
-                       m2[1].value = 0xf000 + 4;
-                       break;
-               case 2:
-                       m2[1].value = 0xf000 + 0;
-                       break;
-               default:
-                       m2[1].value = 0xf000 + 1;
-                       break;
-               }
-       }
-
-       header2[437] = cam->height / 256;
-       header2[438] = cam->height % 256;
-       header2[439] = cam->width / 256;
-       header2[440] = cam->width % 256;
-
-       cam->nb = 0;
-
-       DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
-
-       /* set up the endpoint information  */
-       iface_desc = intf->cur_altsetting;
-       DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-               endpoint = &iface_desc->endpoint[i].desc;
-               if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
-                       /* we found the bulk in endpoint */
-                       cam->read_endpoint = endpoint->bEndpointAddress;
-               }
-       }
-
-       if (!cam->read_endpoint) {
-               err = -ENOMEM;
-               dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
-               goto fail;
-       }
-
-       /* v4l */
-       INIT_LIST_HEAD(&cam->vidq.active);
-       cam->vidq.cam = cam;
-
-       usb_set_intfdata(intf, cam);
-
-       /* load zr364xx board specific */
-       err = zr364xx_board_init(cam);
-       if (!err)
-               err = v4l2_ctrl_handler_setup(hdl);
-       if (err)
-               goto fail;
-
-       spin_lock_init(&cam->slock);
-
-       cam->fmt = formats;
-
-       videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
-                                   NULL, &cam->slock,
-                                   V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                                   V4L2_FIELD_NONE,
-                                   sizeof(struct zr364xx_buffer), cam, &cam->lock);
-
-       err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
-       if (err) {
-               dev_err(&udev->dev, "video_register_device failed\n");
-               goto fail;
-       }
-
-       dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
-                video_device_node_name(&cam->vdev));
-       return 0;
-
-fail:
-       v4l2_ctrl_handler_free(hdl);
-       v4l2_device_unregister(&cam->v4l2_dev);
-       kfree(cam);
-       return err;
-}
-
-
-static void zr364xx_disconnect(struct usb_interface *intf)
-{
-       struct zr364xx_camera *cam = usb_get_intfdata(intf);
-
-       mutex_lock(&cam->lock);
-       usb_set_intfdata(intf, NULL);
-       dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
-       video_unregister_device(&cam->vdev);
-       v4l2_device_disconnect(&cam->v4l2_dev);
-
-       /* stops the read pipe if it is running */
-       if (cam->b_acquire)
-               zr364xx_stop_acquire(cam);
-
-       zr364xx_stop_readpipe(cam);
-       mutex_unlock(&cam->lock);
-       v4l2_device_put(&cam->v4l2_dev);
-}
-
-
-#ifdef CONFIG_PM
-static int zr364xx_suspend(struct usb_interface *intf, pm_message_t message)
-{
-       struct zr364xx_camera *cam = usb_get_intfdata(intf);
-
-       cam->was_streaming = cam->b_acquire;
-       if (!cam->was_streaming)
-               return 0;
-       zr364xx_stop_acquire(cam);
-       zr364xx_stop_readpipe(cam);
-       return 0;
-}
-
-static int zr364xx_resume(struct usb_interface *intf)
-{
-       struct zr364xx_camera *cam = usb_get_intfdata(intf);
-       int res;
-
-       if (!cam->was_streaming)
-               return 0;
-
-       zr364xx_start_readpipe(cam);
-       res = zr364xx_prepare(cam);
-       if (!res)
-               zr364xx_start_acquire(cam);
-       return res;
-}
-#endif
-
-/**********************/
-/* Module integration */
-/**********************/
-
-static struct usb_driver zr364xx_driver = {
-       .name = "zr364xx",
-       .probe = zr364xx_probe,
-       .disconnect = zr364xx_disconnect,
-#ifdef CONFIG_PM
-       .suspend = zr364xx_suspend,
-       .resume = zr364xx_resume,
-       .reset_resume = zr364xx_resume,
-#endif
-       .id_table = device_table
-};
-
-module_usb_driver(zr364xx_driver);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);