Commit fe85ce90 authored by Dean Anderson's avatar Dean Anderson Committed by Mauro Carvalho Chehab

V4L/DVB: s2255drv: cleanup of device structure

s2255drv: cleanup of device structure

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