diff mbox

s2255drv: cleanup of device structure

Message ID tkrat.82060c9b3088ee14@sensoray.com (mailing list archive)
State Accepted
Headers show

Commit Message

sensoray-dev June 1, 2010, 10:12 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 3c7a79f..8ec7c9a 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -191,7 +191,6 @@  struct s2255_bufferi {
 struct s2255_dmaqueue {
 	struct list_head	active;
 	struct s2255_dev	*dev;
-	int			channel;
 };
 
 /* for firmware loading, fw_state */
@@ -226,51 +225,60 @@  struct s2255_pipeinfo {
 };
 
 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 video_device	vdev[MAX_CHANNELS];
+	struct s2255_channel    channel[MAX_CHANNELS];
 	struct v4l2_device 	v4l2_dev;
-	atomic_t                channels; /* number of channels registered */
+	atomic_t                num_channels;
 	int			frames;
 	struct mutex		lock;
 	struct mutex		open_lock;
-	int			resources[MAX_CHANNELS];
 	struct usb_device	*udev;
 	struct usb_interface	*interface;
 	u8			read_endpoint;
-
-	struct s2255_dmaqueue	vidq[MAX_CHANNELS];
 	struct timer_list	timer;
 	struct s2255_fw	*fw_data;
 	struct s2255_pipeinfo	pipe;
-	struct s2255_bufferi	buffer[MAX_CHANNELS];
-	struct s2255_mode	mode[MAX_CHANNELS];
-	/* jpeg compression */
-	struct v4l2_jpegcompression jc[MAX_CHANNELS];
-	/* capture parameters (for high quality mode full size) */
-	struct v4l2_captureparm cap_parm[MAX_CHANNELS];
-	const struct s2255_fmt	*cur_fmt[MAX_CHANNELS];
-	int			cur_frame[MAX_CHANNELS];
-	int			last_frame[MAX_CHANNELS];
 	u32			cc;	/* current channel */
-	int			b_acquire[MAX_CHANNELS];
-	/* allocated image size */
-	unsigned long		req_image_size[MAX_CHANNELS];
-	/* received packet size */
-	unsigned long		pkt_size[MAX_CHANNELS];
-	int			bad_payload[MAX_CHANNELS];
-	unsigned long		frame_count[MAX_CHANNELS];
 	int			frame_ready;
-	/* if JPEG image */
-	int                     jpg_size[MAX_CHANNELS];
-	/* if channel configured to default state */
-	int                     chn_configured[MAX_CHANNELS];
-	wait_queue_head_t       wait_setmode[MAX_CHANNELS];
-	int                     setmode_ready[MAX_CHANNELS];
-	/* video status items */
-	int                     vidstatus[MAX_CHANNELS];
-	wait_queue_head_t       wait_vidstatus[MAX_CHANNELS];
-	int                     vidstatus_ready[MAX_CHANNELS];
 	int                     chn_ready;
 	spinlock_t              slock;
 	/* dsp firmware version (f2255usb.bin) */
@@ -298,16 +306,10 @@  struct s2255_buffer {
 
 struct s2255_fh {
 	struct s2255_dev	*dev;
-	const struct s2255_fmt	*fmt;
-	unsigned int		width;
-	unsigned int		height;
 	struct videobuf_queue	vb_vidq;
 	enum v4l2_buf_type	type;
-	int			channel;
-	/* mode below is the desired mode.
-	   mode in s2255_dev is the current mode that was last set */
-	struct s2255_mode	mode;
-	int			resources[MAX_CHANNELS];
+	struct s2255_channel	*channel;
+	int			resources;
 };
 
 /* current cypress EEPROM firmware version */
@@ -360,12 +362,11 @@  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_dev *dev, unsigned long chn);
-static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn);
-static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
-			   int chn, int jpgsize);
-static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
-			  struct s2255_mode *mode);
+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);
@@ -577,10 +578,11 @@  static void s2255_fwchunk_complete(struct urb *urb)
 
 }
 
-static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize)
+static int s2255_got_frame(struct s2255_channel *channel, int jpgsize)
 {
-	struct s2255_dmaqueue *dma_q = &dev->vidq[chn];
+	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);
@@ -593,7 +595,7 @@  static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize)
 			 struct s2255_buffer, vb.queue);
 	list_del(&buf->vb.queue);
 	do_gettimeofday(&buf->vb.ts);
-	s2255_fillbuff(dev, buf, dma_q->channel, jpgsize);
+	s2255_fillbuff(channel, buf, jpgsize);
 	wake_up(&buf->vb.done);
 	dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i);
 unlock:
@@ -621,8 +623,8 @@  static const struct s2255_fmt *format_by_fourcc(int fourcc)
  *                  http://v4l.videotechnology.com/
  *
  */
-static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
-			   int chn, int jpgsize)
+static void s2255_fillbuff(struct s2255_channel *channel,
+			   struct s2255_buffer *buf, int jpgsize)
 {
 	int pos = 0;
 	struct timeval ts;
@@ -633,12 +635,11 @@  static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
 
 	if (!vbuf)
 		return;
-
-	last_frame = dev->last_frame[chn];
+	last_frame = channel->last_frame;
 	if (last_frame != -1) {
-		frm = &dev->buffer[chn].frame[last_frame];
+		frm = &channel->buffer.frame[last_frame];
 		tmpbuf =
-		    (const char *)dev->buffer[chn].frame[last_frame].lpvbits;
+		    (const char *)channel->buffer.frame[last_frame].lpvbits;
 		switch (buf->fmt->fourcc) {
 		case V4L2_PIX_FMT_YUYV:
 		case V4L2_PIX_FMT_UYVY:
@@ -661,7 +662,7 @@  static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
 		default:
 			printk(KERN_DEBUG "s2255: unknown format?\n");
 		}
-		dev->last_frame[chn] = -1;
+		channel->last_frame = -1;
 	} else {
 		printk(KERN_ERR "s2255: =======no frame\n");
 		return;
@@ -671,7 +672,7 @@  static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
 		(unsigned long)vbuf, pos);
 	/* tell v4l buffer was filled */
 
-	buf->vb.field_count = dev->frame_count[chn] * 2;
+	buf->vb.field_count = channel->frame_count * 2;
 	do_gettimeofday(&ts);
 	buf->vb.ts = ts;
 	buf->vb.state = VIDEOBUF_DONE;
@@ -686,8 +687,8 @@  static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
 			unsigned int *size)
 {
 	struct s2255_fh *fh = vq->priv_data;
-
-	*size = fh->width * fh->height * (fh->fmt->depth >> 3);
+	struct s2255_channel *channel = fh->channel;
+	*size = channel->width * channel->height * (channel->fmt->depth >> 3);
 
 	if (0 == *count)
 		*count = S2255_DEF_BUFS;
@@ -710,30 +711,31 @@  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 (fh->fmt == NULL)
+	if (channel->fmt == NULL)
 		return -EINVAL;
 
-	if ((fh->width < norm_minw(&fh->dev->vdev[fh->channel])) ||
-	    (fh->width > norm_maxw(&fh->dev->vdev[fh->channel])) ||
-	    (fh->height < norm_minh(&fh->dev->vdev[fh->channel])) ||
-	    (fh->height > norm_maxh(&fh->dev->vdev[fh->channel]))) {
+	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 = fh->width * fh->height * (fh->fmt->depth >> 3);
-
+	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 = fh->fmt;
-	buf->vb.width = fh->width;
-	buf->vb.height = fh->height;
+	buf->fmt = channel->fmt;
+	buf->vb.width = w;
+	buf->vb.height = h;
 	buf->vb.field = field;
 
 	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
@@ -753,8 +755,8 @@  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_dev *dev = fh->dev;
-	struct s2255_dmaqueue *vidq = &dev->vidq[fh->channel];
+	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);
@@ -765,7 +767,7 @@  static void buffer_release(struct videobuf_queue *vq,
 {
 	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);
+	dprintk(4, "%s %d\n", __func__, fh->channel->idx);
 	free_buffer(vq, buf);
 }
 
@@ -777,39 +779,43 @@  static struct videobuf_queue_ops s2255_video_qops = {
 };
 
 
-static int res_get(struct s2255_dev *dev, struct s2255_fh *fh)
+static int res_get(struct s2255_fh *fh)
 {
+	struct s2255_dev *dev = fh->dev;
 	/* is it free? */
+	struct s2255_channel *channel = fh->channel;
 	mutex_lock(&dev->lock);
-	if (dev->resources[fh->channel]) {
+	if (channel->resources) {
 		/* no, someone else uses it */
 		mutex_unlock(&dev->lock);
 		return 0;
 	}
 	/* it's free, grab it */
-	dev->resources[fh->channel] = 1;
-	fh->resources[fh->channel] = 1;
+	channel->resources = 1;
+	fh->resources = 1;
 	dprintk(1, "s2255: res: get\n");
 	mutex_unlock(&dev->lock);
 	return 1;
 }
 
-static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh)
+static int res_locked(struct s2255_fh *fh)
 {
-	return dev->resources[fh->channel];
+	return fh->channel->resources;
 }
 
 static int res_check(struct s2255_fh *fh)
 {
-	return fh->resources[fh->channel];
+	return fh->resources;
 }
 
 
-static void res_free(struct s2255_dev *dev, struct s2255_fh *fh)
+static void res_free(struct s2255_fh *fh)
 {
+	struct s2255_channel *channel = fh->channel;
+	struct s2255_dev *dev = fh->dev;
 	mutex_lock(&dev->lock);
-	dev->resources[fh->channel] = 0;
-	fh->resources[fh->channel] = 0;
+	channel->resources = 0;
+	fh->resources = 0;
 	mutex_unlock(&dev->lock);
 	dprintk(1, "res: put\n");
 }
@@ -869,12 +875,13 @@  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 = fh->width;
-	f->fmt.pix.height = fh->height;
+	f->fmt.pix.width = channel->width;
+	f->fmt.pix.height = channel->height;
 	f->fmt.pix.field = fh->vb_vidq.field;
-	f->fmt.pix.pixelformat = fh->fmt->fourcc;
-	f->fmt.pix.bytesperline = f->fmt.pix.width * (fh->fmt->depth >> 3);
+	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;
 }
@@ -886,11 +893,10 @@  static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 	enum v4l2_field field;
 	int  b_any_field = 0;
 	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
+	struct s2255_channel *channel = fh->channel;
 	int is_ntsc;
-
 	is_ntsc =
-	    (dev->vdev[fh->channel].current_norm & V4L2_STD_NTSC) ? 1 : 0;
+		(channel->vdev.current_norm & V4L2_STD_NTSC) ? 1 : 0;
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
@@ -982,8 +988,10 @@  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;
 	int norm;
 
@@ -1005,54 +1013,61 @@  static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 		goto out_s_fmt;
 	}
 
-	if (res_locked(fh->dev, fh)) {
+	if (res_locked(fh)) {
 		dprintk(1, "%s: channel busy\n", __func__);
 		ret = -EBUSY;
 		goto out_s_fmt;
 	}
-
-	fh->fmt = fmt;
-	fh->width = f->fmt.pix.width;
-	fh->height = f->fmt.pix.height;
+	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;
-	norm = norm_minw(&fh->dev->vdev[fh->channel]);
-	if (fh->width > norm_minw(&fh->dev->vdev[fh->channel])) {
-		if (fh->height > norm_minh(&fh->dev->vdev[fh->channel])) {
-			if (fh->dev->cap_parm[fh->channel].capturemode &
+	norm = norm_minw(&channel->vdev);
+	if (channel->width > norm_minw(&channel->vdev)) {
+		if (channel->height > norm_minh(&channel->vdev)) {
+			if (channel->cap_parm.capturemode &
 			    V4L2_MODE_HIGHQUALITY)
-				fh->mode.scale = SCALE_4CIFSI;
+				mode.scale = SCALE_4CIFSI;
 			else
-				fh->mode.scale = SCALE_4CIFS;
+				mode.scale = SCALE_4CIFS;
 		} else
-			fh->mode.scale = SCALE_2CIFS;
+			mode.scale = SCALE_2CIFS;
 
 	} else {
-		fh->mode.scale = SCALE_1CIFS;
+		mode.scale = SCALE_1CIFS;
 	}
-
 	/* color mode */
-	switch (fh->fmt->fourcc) {
+	switch (channel->fmt->fourcc) {
 	case V4L2_PIX_FMT_GREY:
-		fh->mode.color &= ~MASK_COLOR;
-		fh->mode.color |= COLOR_Y8;
+		mode.color &= ~MASK_COLOR;
+		mode.color |= COLOR_Y8;
 		break;
 	case V4L2_PIX_FMT_JPEG:
-		fh->mode.color &= ~MASK_COLOR;
-		fh->mode.color |= COLOR_JPG;
-		fh->mode.color |= (fh->dev->jc[fh->channel].quality << 8);
+		mode.color &= ~MASK_COLOR;
+		mode.color |= COLOR_JPG;
+		mode.color |= (channel->jc.quality << 8);
 		break;
 	case V4L2_PIX_FMT_YUV422P:
-		fh->mode.color &= ~MASK_COLOR;
-		fh->mode.color |= COLOR_YUVPL;
+		mode.color &= ~MASK_COLOR;
+		mode.color |= COLOR_YUVPL;
 		break;
 	case V4L2_PIX_FMT_YUYV:
 	case V4L2_PIX_FMT_UYVY:
 	default:
-		fh->mode.color &= ~MASK_COLOR;
-		fh->mode.color |= COLOR_YUVPK;
+		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);
@@ -1197,26 +1212,27 @@  static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode)
  * 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_dev *dev, unsigned long chn,
+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);
 	mutex_lock(&dev->lock);
-	chn_rev = G_chnmap[chn];
-	dprintk(3, "%s channel %lu\n", __func__, chn);
+	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 |= (dev->jc[chn].quality << 8);
+		mode->color |= (channel->jc.quality << 8);
 	}
 	/* save the mode */
-	dev->mode[chn] = *mode;
-	dev->req_image_size[chn] = get_transfer_size(mode);
-	dprintk(1, "%s: reqsize %ld\n", __func__, dev->req_image_size[chn]);
+	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");
@@ -1227,38 +1243,38 @@  static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
 	buffer[0] = IN_DATA_TOKEN;
 	buffer[1] = (__le32) cpu_to_le32(chn_rev);
 	buffer[2] = CMD_SET_MODE;
-	memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode));
-	dev->setmode_ready[chn] = 0;
+	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(dev->wait_setmode[chn],
-				   (dev->setmode_ready[chn] != 0),
+		wait_event_timeout(channel->wait_setmode,
+				   (channel->setmode_ready != 0),
 				   msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
-		if (dev->setmode_ready[chn] != 1) {
+		if (channel->setmode_ready != 1) {
 			printk(KERN_DEBUG "s2255: no set mode response\n");
 			res = -EFAULT;
 		}
 	}
 	/* clear the restart flag */
-	dev->mode[chn].restart = 0;
+	channel->mode.restart = 0;
 	mutex_unlock(&dev->lock);
-	dprintk(1, "%s chn %lu, result: %d\n", __func__, chn, res);
+	dprintk(1, "%s chn %d, result: %d\n", __func__, channel->idx, res);
 	return res;
 }
 
-static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn,
-			    u32 *pstatus)
+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);
 	mutex_lock(&dev->lock);
-	chn_rev = G_chnmap[chn];
-	dprintk(4, "%s chan %lu\n", __func__, chn);
+	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");
@@ -1270,17 +1286,17 @@  static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn,
 	buffer[1] = (__le32) cpu_to_le32(chn_rev);
 	buffer[2] = CMD_STATUS;
 	*pstatus = 0;
-	dev->vidstatus_ready[chn] = 0;
+	channel->vidstatus_ready = 0;
 	res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
 	kfree(buffer);
-	wait_event_timeout(dev->wait_vidstatus[chn],
-			   (dev->vidstatus_ready[chn] != 0),
+	wait_event_timeout(channel->wait_vidstatus,
+			   (channel->vidstatus_ready != 0),
 			   msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT));
-	if (dev->vidstatus_ready[chn] != 1) {
+	if (channel->vidstatus_ready != 1) {
 		printk(KERN_DEBUG "s2255: no vidstatus response\n");
 		res = -EFAULT;
 	}
-	*pstatus = dev->vidstatus[chn];
+	*pstatus = channel->vidstatus;
 	dprintk(4, "%s, vid status %d\n", __func__, *pstatus);
 	mutex_unlock(&dev->lock);
 	return res;
@@ -1291,9 +1307,7 @@  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_mode *new_mode;
-	struct s2255_mode *old_mode;
-	int chn;
+	struct s2255_channel *channel = fh->channel;
 	int j;
 	dprintk(4, "%s\n", __func__);
 	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
@@ -1305,51 +1319,32 @@  static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 		return -EINVAL;
 	}
 
-	if (!res_get(dev, fh)) {
+	if (!res_get(fh)) {
 		s2255_dev_err(&dev->udev->dev, "stream busy\n");
 		return -EBUSY;
 	}
-
-	/* send a set mode command everytime with restart.
-	   in case we switch resolutions or other parameters */
-	chn = fh->channel;
-	new_mode = &fh->mode;
-	old_mode = &fh->dev->mode[chn];
-
-	if ((new_mode->color & MASK_COLOR) != (old_mode->color & MASK_COLOR))
-		new_mode->restart = 1;
-	else if (new_mode->scale != old_mode->scale)
-		new_mode->restart = 1;
-	else if (new_mode->format != old_mode->format)
-		new_mode->restart = 1;
-
-	s2255_set_mode(dev, chn, new_mode);
-	new_mode->restart = 0;
-	*old_mode = *new_mode;
-	dev->cur_fmt[chn] = fh->fmt;
-	dev->last_frame[chn] = -1;
-	dev->bad_payload[chn] = 0;
-	dev->cur_frame[chn] = 0;
-	dev->frame_count[chn] = 0;
+	channel->last_frame = -1;
+	channel->bad_payload = 0;
+	channel->cur_frame = 0;
+	channel->frame_count = 0;
 	for (j = 0; j < SYS_FRAMES; j++) {
-		dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE;
-		dev->buffer[chn].frame[j].cur_size = 0;
+		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(dev, chn);
-		dev->b_acquire[chn] = 1;
-	} else {
-		res_free(dev, fh);
-	}
+		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;
-	struct s2255_dev *dev = fh->dev;
-	dprintk(4, "%s\n, channel: %d", __func__, fh->channel);
+	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;
@@ -1358,16 +1353,16 @@  static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 		printk(KERN_ERR "invalid type i\n");
 		return -EINVAL;
 	}
-	s2255_stop_acquire(dev, fh->channel);
+	s2255_stop_acquire(fh->channel);
 	videobuf_streamoff(&fh->vb_vidq);
-	res_free(dev, fh);
+	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 s2255_mode mode;
 	struct videobuf_queue *q = &fh->vb_vidq;
 	int ret = 0;
 	mutex_lock(&q->vb_lock);
@@ -1376,29 +1371,32 @@  static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
 		ret = -EBUSY;
 		goto out_s_std;
 	}
-	if (res_locked(fh->dev, fh)) {
+	if (res_locked(fh)) {
 		dprintk(1, "can't change standard after started\n");
 		ret = -EBUSY;
 		goto out_s_std;
 	}
-	mode = &fh->mode;
+	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->format = FORMAT_NTSC;
-			mode->fdec = FDEC_1;
+		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__);
-		mode->format = FORMAT_PAL;
-		if (mode->format != FORMAT_PAL) {
-			mode->format = FORMAT_PAL;
-			mode->fdec = FDEC_1;
+		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;
@@ -1416,6 +1414,7 @@  static int vidioc_enum_input(struct file *file, void *priv,
 {
 	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;
@@ -1424,7 +1423,7 @@  static int vidioc_enum_input(struct file *file, void *priv,
 	inp->status = 0;
 	if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) {
 		int rc;
-		rc = s2255_cmd_status(dev, fh->channel, &status);
+		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
@@ -1436,7 +1435,7 @@  static int vidioc_enum_input(struct file *file, void *priv,
 		strlcpy(inp->name, "Composite", sizeof(inp->name));
 		break;
 	case 0x2257:
-		strlcpy(inp->name, (fh->channel < 2) ? "Composite" : "S-Video",
+		strlcpy(inp->name, (channel->idx < 2) ? "Composite" : "S-Video",
 			sizeof(inp->name));
 		break;
 	}
@@ -1460,6 +1459,7 @@  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:
@@ -1477,7 +1477,7 @@  static int vidioc_queryctrl(struct file *file, void *priv,
 	case V4L2_CID_PRIVATE_COLORFILTER:
 		if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
 			return -EINVAL;
-		if ((dev->pid == 0x2257) && (fh->channel > 1))
+		if ((dev->pid == 0x2257) && (channel->idx > 1))
 			return -EINVAL;
 		strlcpy(qc->name, "Color Filter", sizeof(qc->name));
 		qc->type = V4L2_CTRL_TYPE_MENU;
@@ -1499,25 +1499,26 @@  static int vidioc_g_ctrl(struct file *file, void *priv,
 {
 	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 = fh->mode.bright;
+		ctrl->value = channel->mode.bright;
 		break;
 	case V4L2_CID_CONTRAST:
-		ctrl->value = fh->mode.contrast;
+		ctrl->value = channel->mode.contrast;
 		break;
 	case V4L2_CID_SATURATION:
-		ctrl->value = fh->mode.saturation;
+		ctrl->value = channel->mode.saturation;
 		break;
 	case V4L2_CID_HUE:
-		ctrl->value = fh->mode.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) && (fh->channel > 1))
+		if ((dev->pid == 0x2257) && (channel->idx > 1))
 			return -EINVAL;
-		ctrl->value = !((fh->mode.color & MASK_INPUT_TYPE) >> 16);
+		ctrl->value = !((channel->mode.color & MASK_INPUT_TYPE) >> 16);
 		break;
 	default:
 		return -EINVAL;
@@ -1530,41 +1531,42 @@  static int vidioc_s_ctrl(struct file *file, void *priv,
 			 struct v4l2_control *ctrl)
 {
 	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
-	struct s2255_mode *mode;
-	mode = &fh->mode;
+	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;
+		mode.bright = ctrl->value;
 		break;
 	case V4L2_CID_CONTRAST:
-		mode->contrast = ctrl->value;
+		mode.contrast = ctrl->value;
 		break;
 	case V4L2_CID_HUE:
-		mode->hue = ctrl->value;
+		mode.hue = ctrl->value;
 		break;
 	case V4L2_CID_SATURATION:
-		mode->saturation = ctrl->value;
+		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) && (fh->channel > 1))
+		if ((dev->pid == 0x2257) && (channel->idx > 1))
 			return -EINVAL;
-		mode->color &= ~MASK_INPUT_TYPE;
-		mode->color |= ((ctrl->value ? 0 : 1) << 16);
+		mode.color &= ~MASK_INPUT_TYPE;
+		mode.color |= ((ctrl->value ? 0 : 1) << 16);
 		break;
 	default:
 		return -EINVAL;
 	}
-	mode->restart = 0;
+	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(dev, fh->channel, mode);
+	s2255_set_mode(fh->channel, &mode);
 	return 0;
 }
 
@@ -1572,8 +1574,8 @@  static int vidioc_g_jpegcomp(struct file *file, void *priv,
 			 struct v4l2_jpegcompression *jc)
 {
 	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
-	*jc = dev->jc[fh->channel];
+	struct s2255_channel *channel = fh->channel;
+	*jc = channel->jc;
 	dprintk(2, "%s: quality %d\n", __func__, jc->quality);
 	return 0;
 }
@@ -1582,10 +1584,10 @@  static int vidioc_s_jpegcomp(struct file *file, void *priv,
 			 struct v4l2_jpegcompression *jc)
 {
 	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
+	struct s2255_channel *channel = fh->channel;
 	if (jc->quality < 0 || jc->quality > 100)
 		return -EINVAL;
-	dev->jc[fh->channel].quality = jc->quality;
+	channel->jc.quality = jc->quality;
 	dprintk(2, "%s: quality %d\n", __func__, jc->quality);
 	return 0;
 }
@@ -1594,17 +1596,17 @@  static int vidioc_g_parm(struct file *file, void *priv,
 			 struct v4l2_streamparm *sp)
 {
 	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
 	__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 = dev->cap_parm[fh->channel].capturemode;
-	def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000;
-	def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000;
+	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 (fh->mode.fdec) {
+	switch (channel->mode.fdec) {
 	default:
 	case FDEC_1:
 		sp->parm.capture.timeperframe.numerator = def_num;
@@ -1630,17 +1632,19 @@  static int vidioc_s_parm(struct file *file, void *priv,
 			 struct v4l2_streamparm *sp)
 {
 	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
+	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 (dev->cap_parm[fh->channel].capturemode
-	    != sp->parm.capture.capturemode && res_locked(fh->dev, fh))
+	if (channel->cap_parm.capturemode
+	    != sp->parm.capture.capturemode && res_locked(fh))
 		return -EBUSY;
-	def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000;
-	def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000;
+	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)
@@ -1655,9 +1659,9 @@  static int vidioc_s_parm(struct file *file, void *priv,
 		sp->parm.capture.timeperframe.numerator = def_num * 5;
 		fdec = FDEC_5;
 	}
-	fh->mode.fdec = fdec;
+	mode.fdec = fdec;
 	sp->parm.capture.timeperframe.denominator = def_dem;
-	s2255_set_mode(dev, fh->channel, &fh->mode);
+	s2255_set_mode(channel, &mode);
 	dprintk(4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n",
 		__func__,
 		sp->parm.capture.capturemode,
@@ -1707,24 +1711,13 @@  static int vidioc_enum_frameintervals(struct file *file, void *priv,
 static int s2255_open(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
-	struct s2255_dev *dev = video_drvdata(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 i = 0;
-	int cur_channel = -1;
 	int state;
 	dprintk(1, "s2255: open called (dev=%s)\n",
 		video_device_node_name(vdev));
-
-	for (i = 0; i < MAX_CHANNELS; i++) {
-		if (&dev->vdev[i] == vdev) {
-			cur_channel = i;
-			break;
-		}
-	}
-	if (i == MAX_CHANNELS)
-		return -ENODEV;
-
 	/*
 	 * open lock necessary to prevent multiple instances
 	 * of v4l-conf (or other programs) from simultaneously
@@ -1806,24 +1799,20 @@  static int s2255_open(struct file *file)
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	fh->mode = dev->mode[cur_channel];
-	fh->fmt = dev->cur_fmt[cur_channel];
-	/* default 4CIF NTSC */
-	fh->width = LINE_SZ_4CIFS_NTSC;
-	fh->height = NUM_LINES_4CIFS_NTSC * 2;
-	fh->channel = cur_channel;
-	/* configure channel to default state */
-	if (!dev->chn_configured[cur_channel]) {
-		s2255_set_mode(dev, cur_channel, &fh->mode);
-		dev->chn_configured[cur_channel] = 1;
+	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)&dev->vidq[cur_channel]);
+		(unsigned long)&channel->vidq);
 	dprintk(4, "%s: list_empty active=%d\n", __func__,
-		list_empty(&dev->vidq[cur_channel].active));
+		list_empty(&channel->vidq.active));
 	videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops,
 				    NULL, &dev->slock,
 				    fh->type,
@@ -1865,6 +1854,7 @@  static void s2255_destroy(struct s2255_dev *dev)
 	mutex_destroy(&dev->open_lock);
 	mutex_destroy(&dev->lock);
 	usb_put_dev(dev->udev);
+	v4l2_device_unregister(&dev->v4l2_dev);
 	dprintk(1, "%s", __func__);
 	kfree(dev);
 }
@@ -1874,14 +1864,15 @@  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;
 	/* turn off stream */
 	if (res_check(fh)) {
-		if (dev->b_acquire[fh->channel])
-			s2255_stop_acquire(dev, fh->channel);
+		if (channel->b_acquire)
+			s2255_stop_acquire(fh->channel);
 		videobuf_streamoff(&fh->vb_vidq);
-		res_free(dev, fh);
+		res_free(fh);
 	}
 	videobuf_mmap_free(&fh->vb_vidq);
 	dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev));
@@ -1945,9 +1936,10 @@  static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
 
 static void s2255_video_device_release(struct video_device *vdev)
 {
-	struct s2255_dev *dev = video_get_drvdata(vdev);
-	dprintk(4, "%s, chnls: %d \n", __func__, atomic_read(&dev->channels));
-	if (atomic_dec_and_test(&dev->channels))
+	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;
 }
@@ -1966,47 +1958,48 @@  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++) {
-		INIT_LIST_HEAD(&dev->vidq[i].active);
-		dev->vidq[i].dev = dev;
-		dev->vidq[i].channel = i;
+		channel = &dev->channel[i];
+		INIT_LIST_HEAD(&channel->vidq.active);
+		channel->vidq.dev = dev;
 		/* register 4 video devices */
-		memcpy(&dev->vdev[i], &template, sizeof(struct video_device));
-		dev->vdev[i].v4l2_dev = &dev->v4l2_dev;
-		video_set_drvdata(&dev->vdev[i], dev);
+		channel->vdev = template;
+		channel->vdev.v4l2_dev = &dev->v4l2_dev;
+		video_set_drvdata(&channel->vdev, channel);
 		if (video_nr == -1)
-			ret = video_register_device(&dev->vdev[i],
+			ret = video_register_device(&channel->vdev,
 						    VFL_TYPE_GRABBER,
 						    video_nr);
 		else
-			ret = video_register_device(&dev->vdev[i],
+			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->channels);
+		atomic_inc(&dev->num_channels);
 		v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
-			  video_device_node_name(&dev->vdev[i]));
+			  video_device_node_name(&channel->vdev));
 
 	}
-
 	printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n",
 	       S2255_MAJOR_VERSION,
 	       S2255_MINOR_VERSION);
 	/* if no channels registered, return error and probe will fail*/
-	if (atomic_read(&dev->channels) == 0) {
+	if (atomic_read(&dev->num_channels) == 0) {
 		v4l2_device_unregister(&dev->v4l2_dev);
 		return ret;
 	}
-	if (atomic_read(&dev->channels) != MAX_CHANNELS)
+	if (atomic_read(&dev->num_channels) != MAX_CHANNELS)
 		printk(KERN_WARNING "s2255: Not all channels available.\n");
 	return 0;
 }
@@ -2033,12 +2026,11 @@  static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 	s32 idx = -1;
 	struct s2255_framei *frm;
 	unsigned char *pdata;
-
+	struct s2255_channel *channel;
 	dprintk(100, "buffer to user\n");
-
-	idx = dev->cur_frame[dev->cc];
-	frm = &dev->buffer[dev->cc].frame[idx];
-
+	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;
@@ -2063,16 +2055,18 @@  static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 				}
 				/* reverse it */
 				dev->cc = G_chnmap[cc];
+				channel = &dev->channel[dev->cc];
 				payload =  pdword[3];
-				if (payload > dev->req_image_size[dev->cc]) {
-					dev->bad_payload[dev->cc]++;
+				if (payload > channel->req_image_size) {
+					channel->bad_payload++;
 					/* discard the bad frame */
 					return -EINVAL;
 				}
-				dev->pkt_size[dev->cc] = payload;
-				dev->jpg_size[dev->cc] = pdword[4];
+				channel->pkt_size = payload;
+				channel->jpg_size = pdword[4];
 				break;
 			case S2255_MARKER_RESPONSE:
+
 				pdata += DEF_USB_BLOCK;
 				jj += DEF_USB_BLOCK;
 				if (pdword[1] >= MAX_CHANNELS)
@@ -2080,12 +2074,13 @@  static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 				cc = G_chnmap[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 */
-					dev->setmode_ready[cc] = 1;
-					wake_up(&dev->wait_setmode[cc]);
+					channel->setmode_ready = 1;
+					wake_up(&channel->wait_setmode);
 					dprintk(5, "setmode ready %d\n", cc);
 					break;
 				case S2255_RESPONSE_FW:
@@ -2099,9 +2094,9 @@  static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 					wake_up(&dev->fw_data->wait_fw);
 					break;
 				case S2255_RESPONSE_STATUS:
-					dev->vidstatus[cc] = pdword[3];
-					dev->vidstatus_ready[cc] = 1;
-					wake_up(&dev->wait_vidstatus[cc]);
+					channel->vidstatus = pdword[3];
+					channel->vidstatus_ready = 1;
+					wake_up(&channel->wait_vidstatus);
 					dprintk(5, "got vidstatus %x chan %d\n",
 						pdword[3], cc);
 					break;
@@ -2118,13 +2113,11 @@  static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 		if (!bframe)
 			return -EINVAL;
 	}
-
-
-	idx = dev->cur_frame[dev->cc];
-	frm = &dev->buffer[dev->cc].frame[idx];
-
+	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 (!dev->b_acquire[dev->cc]) {
+	if (!channel->b_acquire) {
 		/* we found a frame, but this channel is turned off */
 		frm->ulState = S2255_READ_IDLE;
 		return -EINVAL;
@@ -2149,30 +2142,28 @@  static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 
 	copy_size = (pipe_info->cur_transfer_size - offset);
 
-	size = dev->pkt_size[dev->cc] - PREFIX_SIZE;
+	size = channel->pkt_size - PREFIX_SIZE;
 
 	/* sanity check on pdest */
-	if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc])
+	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) {
-
-		u32 cc = dev->cc;
 		dprintk(2, "****************[%d]Buffer[%d]full*************\n",
-			cc, idx);
-		dev->last_frame[cc] = dev->cur_frame[cc];
-		dev->cur_frame[cc]++;
+			dev->cc, idx);
+		channel->last_frame = channel->cur_frame;
+		channel->cur_frame++;
 		/* end of system frame ring buffer, start at zero */
-		if ((dev->cur_frame[cc] == SYS_FRAMES) ||
-		    (dev->cur_frame[cc] == dev->buffer[cc].dwFrames))
-			dev->cur_frame[cc] = 0;
+		if ((channel->cur_frame == SYS_FRAMES) ||
+		    (channel->cur_frame == channel->buffer.dwFrames))
+			channel->cur_frame = 0;
 		/* frame ready */
-		if (dev->b_acquire[cc])
-			s2255_got_frame(dev, cc, dev->jpg_size[cc]);
-		dev->frame_count[cc]++;
+		if (channel->b_acquire)
+			s2255_got_frame(channel, channel->jpg_size);
+		channel->frame_count++;
 		frm->ulState = S2255_READ_IDLE;
 		frm->cur_size = 0;
 
@@ -2245,16 +2236,12 @@  static int s2255_get_fx2fw(struct s2255_dev *dev)
  * Create the system ring buffer to copy frames into from the
  * usb read pipe.
  */
-static int s2255_create_sys_buffers(struct s2255_dev *dev, unsigned long chn)
+static int s2255_create_sys_buffers(struct s2255_channel *channel)
 {
 	unsigned long i;
 	unsigned long reqsize;
 	dprintk(1, "create sys buffers\n");
-	if (chn >= MAX_CHANNELS)
-		return -1;
-
-	dev->buffer[chn].dwFrames = SYS_FRAMES;
-
+	channel->buffer.dwFrames = SYS_FRAMES;
 	/* always allocate maximum size(PAL) for system buffers */
 	reqsize = SYS_FRAMES_MAXSIZE;
 
@@ -2263,42 +2250,40 @@  static int s2255_create_sys_buffers(struct s2255_dev *dev, unsigned long chn)
 
 	for (i = 0; i < SYS_FRAMES; i++) {
 		/* allocate the frames */
-		dev->buffer[chn].frame[i].lpvbits = vmalloc(reqsize);
-
-		dprintk(1, "valloc %p chan %lu, idx %lu, pdata %p\n",
-			&dev->buffer[chn].frame[i], chn, i,
-			dev->buffer[chn].frame[i].lpvbits);
-		dev->buffer[chn].frame[i].size = reqsize;
-		if (dev->buffer[chn].frame[i].lpvbits == NULL) {
+		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");
-			dev->buffer[chn].dwFrames = i;
+			channel->buffer.dwFrames = i;
 			break;
 		}
 	}
 
 	/* make sure internal states are set */
 	for (i = 0; i < SYS_FRAMES; i++) {
-		dev->buffer[chn].frame[i].ulState = 0;
-		dev->buffer[chn].frame[i].cur_size = 0;
+		channel->buffer.frame[i].ulState = 0;
+		channel->buffer.frame[i].cur_size = 0;
 	}
 
-	dev->cur_frame[chn] = 0;
-	dev->last_frame[chn] = -1;
+	channel->cur_frame = 0;
+	channel->last_frame = -1;
 	return 0;
 }
 
-static int s2255_release_sys_buffers(struct s2255_dev *dev,
-				     unsigned long channel)
+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 (dev->buffer[channel].frame[i].lpvbits) {
+		if (channel->buffer.frame[i].lpvbits) {
 			dprintk(1, "vfree %p\n",
-				dev->buffer[channel].frame[i].lpvbits);
-			vfree(dev->buffer[channel].frame[i].lpvbits);
+				channel->buffer.frame[i].lpvbits);
+			vfree(channel->buffer.frame[i].lpvbits);
 		}
-		dev->buffer[channel].frame[i].lpvbits = NULL;
+		channel->buffer.frame[i].lpvbits = NULL;
 	}
 	return 0;
 }
@@ -2335,17 +2320,20 @@  static int s2255_board_init(struct s2255_dev *dev)
 			fw_ver & 0xff);
 
 	for (j = 0; j < MAX_CHANNELS; j++) {
-		dev->b_acquire[j] = 0;
-		dev->mode[j] = mode_def;
+		struct s2255_channel *channel = &dev->channel[j];
+		channel->b_acquire = 0;
+		channel->mode = mode_def;
 		if (dev->pid == 0x2257 && j > 1)
-			dev->mode[j].color |= (1 << 16);
-		dev->jc[j].quality = S2255_DEF_JPEG_QUAL;
-		dev->cur_fmt[j] = &formats[0];
-		dev->mode[j].restart = 1;
-		dev->req_image_size[j] = get_transfer_size(&mode_def);
-		dev->frame_count[j] = 0;
+			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(dev, j);
+		s2255_create_sys_buffers(channel);
 	}
 	/* start read pipe */
 	s2255_start_readpipe(dev);
@@ -2359,14 +2347,12 @@  static int s2255_board_shutdown(struct s2255_dev *dev)
 	dprintk(1, "%s: dev: %p", __func__,  dev);
 
 	for (i = 0; i < MAX_CHANNELS; i++) {
-		if (dev->b_acquire[i])
-			s2255_stop_acquire(dev, 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, i);
+		s2255_release_sys_buffers(&dev->channel[i]);
 	/* release transfer buffer */
 	kfree(dev->pipe.transfer_buffer);
 	return 0;
@@ -2459,29 +2445,26 @@  static int s2255_start_readpipe(struct s2255_dev *dev)
 }
 
 /* starts acquisition process */
-static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn)
+static int s2255_start_acquire(struct s2255_channel *channel)
 {
 	unsigned char *buffer;
 	int res;
 	unsigned long chn_rev;
 	int j;
-	if (chn >= MAX_CHANNELS) {
-		dprintk(2, "start acquire failed, bad channel %lu\n", chn);
-		return -1;
-	}
-	chn_rev = G_chnmap[chn];
+	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;
 	}
 
-	dev->last_frame[chn] = -1;
-	dev->bad_payload[chn] = 0;
-	dev->cur_frame[chn] = 0;
+	channel->last_frame = -1;
+	channel->bad_payload = 0;
+	channel->cur_frame = 0;
 	for (j = 0; j < SYS_FRAMES; j++) {
-		dev->buffer[chn].frame[j].ulState = 0;
-		dev->buffer[chn].frame[j].cur_size = 0;
+		channel->buffer.frame[j].ulState = 0;
+		channel->buffer.frame[j].cur_size = 0;
 	}
 
 	/* send the start command */
@@ -2492,21 +2475,18 @@  static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn)
 	if (res != 0)
 		dev_err(&dev->udev->dev, "CMD_START error\n");
 
-	dprintk(2, "start acquire exit[%lu] %d \n", chn, res);
+	dprintk(2, "start acquire exit[%d] %d \n", channel->idx, res);
 	kfree(buffer);
 	return 0;
 }
 
-static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn)
+static int s2255_stop_acquire(struct s2255_channel *channel)
 {
 	unsigned char *buffer;
 	int res;
 	unsigned long chn_rev;
-	if (chn >= MAX_CHANNELS) {
-		dprintk(2, "stop acquire failed, bad channel %lu\n", chn);
-		return -1;
-	}
-	chn_rev = G_chnmap[chn];
+	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");
@@ -2520,8 +2500,8 @@  static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn)
 	if (res != 0)
 		dev_err(&dev->udev->dev, "CMD_STOP error\n");
 	kfree(buffer);
-	dev->b_acquire[chn] = 0;
-	dprintk(4, "%s: chn %lu, res %d\n", __func__, chn, res);
+	channel->b_acquire = 0;
+	dprintk(4, "%s: chn %d, res %d\n", __func__, channel->idx, res);
 	return res;
 }
 
@@ -2575,7 +2555,7 @@  static int s2255_probe(struct usb_interface *interface,
 		s2255_dev_err(&interface->dev, "out of memory\n");
 		return -ENOMEM;
 	}
-	atomic_set(&dev->channels, 0);
+	atomic_set(&dev->num_channels, 0);
 	dev->pid = id->idProduct;
 	dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
 	if (!dev->fw_data)
@@ -2612,8 +2592,10 @@  static int s2255_probe(struct usb_interface *interface,
 	dev->timer.data = (unsigned long)dev->fw_data;
 	init_waitqueue_head(&dev->fw_data->wait_fw);
 	for (i = 0; i < MAX_CHANNELS; i++) {
-		init_waitqueue_head(&dev->wait_setmode[i]);
-		init_waitqueue_head(&dev->wait_vidstatus[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);
@@ -2651,7 +2633,7 @@  static int s2255_probe(struct usb_interface *interface,
 			printk(KERN_INFO "s2255: f2255usb.bin out of date.\n");
 		if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER)
 			printk(KERN_WARNING "s2255: 2257 requires firmware %d"
-			       "or above.\n", S2255_MIN_DSP_COLORFILTER);
+			       " or above.\n", S2255_MIN_DSP_COLORFILTER);
 	}
 	usb_reset_device(dev->udev);
 	/* load 2255 board specific */
@@ -2693,25 +2675,23 @@  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->channels);
-	v4l2_device_unregister(&dev->v4l2_dev);
+	int channels = atomic_read(&dev->num_channels);
+	v4l2_device_disconnect(&dev->v4l2_dev);
 	/*see comments in the uvc_driver.c usb disconnect function */
-	atomic_inc(&dev->channels);
+	atomic_inc(&dev->num_channels);
 	/* unregister each video device. */
-	for (i = 0; i < channels; i++) {
-		if (video_is_registered(&dev->vdev[i]))
-			video_unregister_device(&dev->vdev[i]);
-	}
+	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->setmode_ready[i] = 1;
-		wake_up(&dev->wait_setmode[i]);
-		dev->vidstatus_ready[i] = 1;
-		wake_up(&dev->wait_vidstatus[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->channels))
+	if (atomic_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
 	dev_info(&interface->dev, "%s\n", __func__);
 }