/*
- em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+ em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
+ video capture devices
Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
Markus Rechberger <mrechberger@gmail.com>
dev->name, __func__ , ##arg); } while (0)
static unsigned int isoc_debug;
-module_param(isoc_debug,int,0644);
-MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
-#define em28xx_isocdbg(fmt, arg...) do {\
- if (isoc_debug) \
+#define em28xx_isocdbg(fmt, arg...) \
+do {\
+ if (isoc_debug) { \
printk(KERN_INFO "%s %s :"fmt, \
- dev->name, __FUNCTION__ , ##arg); } while (0)
-
-#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
-
-/* Limits minimum and default number of buffers */
-#define EM28XX_MIN_BUF 4
-#define EM28XX_DEF_BUF 8
+ dev->name, __func__ , ##arg); \
+ } \
+ } while (0)
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_PARM_DESC(radio_nr, "radio device numbers");
static unsigned int video_debug;
-module_param(video_debug,int,0644);
-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
static unsigned long em28xx_devused;
.step = 0x1,
.default_value = 0x1f,
.flags = 0,
- },{
+ }, {
.id = V4L2_CID_AUDIO_MUTE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Mute",
/*
* Announces that a buffer were filled and request the next
*/
-static void inline buffer_filled (struct em28xx *dev,
+static inline void buffer_filled(struct em28xx *dev,
struct em28xx_dmaqueue *dma_q,
struct em28xx_buffer *buf)
{
- mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-
- /* Nobody is waiting something to be done, just return */
- if (!waitqueue_active(&buf->vb.done)) {
- printk(KERN_ERR "em28xx: buffer underrun at %ld\n",
- jiffies);
-
- return;
- }
-
/* Advice that buffer was filled */
em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
buf->vb.state = VIDEOBUF_DONE;
buf->vb.field_count++;
do_gettimeofday(&buf->vb.ts);
+ dev->isoc_ctl.buf = NULL;
+
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
}
unsigned char *outp, unsigned long len)
{
void *fieldstart, *startwrite, *startread;
- int linesdone, currlinedone, offset, lencopy,remain;
-
- if(dev->frame_size != buf->vb.size){
- em28xx_errdev("size %i and buf.length %lu are different!\n",
- dev->frame_size, buf->vb.size);
- return;
- }
+ int linesdone, currlinedone, offset, lencopy, remain;
+ int bytesperline = dev->width << 1;
if (dma_q->pos + len > buf->vb.size)
len = buf->vb.size - dma_q->pos;
em28xx_isocdbg("frame is not complete\n");
len += 4;
} else
- p +=4;
+ p += 4;
startread = p;
remain = len;
if (buf->top_field)
fieldstart = outp;
else
- fieldstart = outp + dev->bytesperline;
+ fieldstart = outp + bytesperline;
- linesdone = dma_q->pos / dev->bytesperline;
- currlinedone = dma_q->pos % dev->bytesperline;
- offset = linesdone * dev->bytesperline * 2 + currlinedone;
+ linesdone = dma_q->pos / bytesperline;
+ currlinedone = dma_q->pos % bytesperline;
+ offset = linesdone * bytesperline * 2 + currlinedone;
startwrite = fieldstart + offset;
- lencopy = dev->bytesperline - currlinedone;
+ lencopy = bytesperline - currlinedone;
lencopy = lencopy > remain ? remain : lencopy;
- if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) {
+ if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
- ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size));
- lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite;
+ ((char *)startwrite + lencopy) -
+ ((char *)outp + buf->vb.size));
+ lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite;
}
- BUG_ON(lencopy <= 0);
+ if (lencopy <= 0)
+ return;
memcpy(startwrite, startread, lencopy);
remain -= lencopy;
while (remain > 0) {
- startwrite += lencopy + dev->bytesperline;
+ startwrite += lencopy + bytesperline;
startread += lencopy;
- if (dev->bytesperline > remain)
+ if (bytesperline > remain)
lencopy = remain;
else
- lencopy = dev->bytesperline;
-
- BUG_ON(lencopy <= 0);
+ lencopy = bytesperline;
- if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) {
+ if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
- ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size));
- lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite;
+ ((char *)startwrite + lencopy) -
+ ((char *)outp + buf->vb.size));
+ lencopy = remain = (char *)outp + buf->vb.size -
+ (char *)startwrite;
}
- if(lencopy <= 0) break;
+ if (lencopy <= 0)
+ break;
memcpy(startwrite, startread, lencopy);
dma_q->pos += len;
}
-static void inline print_err_status (struct em28xx *dev,
+static inline void print_err_status(struct em28xx *dev,
int packet, int status)
{
char *errmsg = "Unknown";
- switch(status) {
+ switch (status) {
case -ENOENT:
errmsg = "unlinked synchronuously";
break;
errmsg = "Device does not respond";
break;
}
- if (packet<0) {
+ if (packet < 0) {
em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
} else {
em28xx_isocdbg("URB packet %d, status %d [%s].\n",
/*
* video-buf generic routine to get the next available buffer
*/
-static int inline get_next_buf (struct em28xx_dmaqueue *dma_q,
+static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
struct em28xx_buffer **buf)
{
struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+ char *outp;
if (list_empty(&dma_q->active)) {
em28xx_isocdbg("No active queue to serve\n");
- return 0;
+ dev->isoc_ctl.buf = NULL;
+ *buf = NULL;
+ return;
}
+ /* Get the next buffer */
*buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
- return 1;
+ /* Cleans up buffer - Usefull for testing for frame/URB loss */
+ outp = videobuf_to_vmalloc(&(*buf)->vb);
+ memset(outp, 0, (*buf)->vb.size);
+
+ dev->isoc_ctl.buf = *buf;
+
+ return;
}
/*
* Controls the isoc copy of each urb packet
*/
-static inline int em28xx_isoc_copy(struct urb *urb)
+static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
{
struct em28xx_buffer *buf;
struct em28xx_dmaqueue *dma_q = urb->context;
- struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
- unsigned char *outp;
+ unsigned char *outp = NULL;
int i, len = 0, rc = 1;
unsigned char *p;
if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
return 0;
- if (urb->status<0) {
- print_err_status (dev,-1,urb->status);
+ if (urb->status < 0) {
+ print_err_status(dev, -1, urb->status);
if (urb->status == -ENOENT)
return 0;
}
- buf=dev->isoc_ctl.buf;
-
- if (!buf) {
- rc=get_next_buf (dma_q, &buf);
- if (rc<=0)
- return rc;
- }
-
- outp = videobuf_to_vmalloc (&buf->vb);
-
+ buf = dev->isoc_ctl.buf;
+ if (buf != NULL)
+ outp = videobuf_to_vmalloc(&buf->vb);
for (i = 0; i < urb->number_of_packets; i++) {
int status = urb->iso_frame_desc[i].status;
- if (status<0) {
- print_err_status (dev,i,status);
+ if (status < 0) {
+ print_err_status(dev, i, status);
if (urb->iso_frame_desc[i].status != -EPROTO)
continue;
}
- len=urb->iso_frame_desc[i].actual_length - 4;
+ len = urb->iso_frame_desc[i].actual_length - 4;
if (urb->iso_frame_desc[i].actual_length <= 0) {
/* em28xx_isocdbg("packet %d is empty",i); - spammy */
/* FIXME: incomplete buffer checks where removed to make
logic simpler. Impacts of those changes should be evaluated
*/
- if (p[0] == 0x22 && p[1] == 0x5a) {
- /* FIXME - are the fields the right way around? */
- em28xx_isocdbg("Video frame, length=%i, %s\n", len,
- (p[2] & 1)? "top" : "bottom");
- em28xx_isocdbg("Current buffer is: outp = 0x%p, len = %i\n", outp, (int)buf->vb.size);
-
- if (p[2] & 1) {
- if (buf->receiving) {
- buffer_filled (dev, dma_q, buf);
- rc=get_next_buf (dma_q, &buf);
- if (rc<=0)
- return rc;
-
- outp = videobuf_to_vmalloc (&buf->vb);
- }
-
- buf->top_field = 1;
- } else {
- buf->top_field = 0;
- }
- buf->receiving = 1;
- dma_q->pos = 0;
- } else if (p[0]==0x33 && p[1]==0x95 && p[2]==0x00) {
+ if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
em28xx_isocdbg("VBI HEADER!!!\n");
+ /* FIXME: Should add vbi copy */
+ continue;
}
-
- em28xx_copy_video(dev, dma_q, buf, p, outp, len);
-
- /* FIXME: Should add vbi copy */
- }
- return rc;
-}
-
-/* ------------------------------------------------------------------
- URB control
- ------------------------------------------------------------------*/
-
-/*
- * IRQ callback, called by URB callback
- */
-static void em28xx_irq_callback(struct urb *urb)
-{
- struct em28xx_dmaqueue *dma_q = urb->context;
- struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
- int rc,i;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->slock,flags);
-
- /* Copy data from URB */
- rc=em28xx_isoc_copy(urb);
-
- /* Reset urb buffers */
- for (i = 0; i < urb->number_of_packets; i++) {
- urb->iso_frame_desc[i].status = 0;
- urb->iso_frame_desc[i].actual_length = 0;
- }
- urb->status = 0;
-
- if ((urb->status = usb_submit_urb(urb, GFP_ATOMIC))) {
- em28xx_err("urb resubmit failed (error=%i)\n",
- urb->status);
- }
-
-#if 0 /* Bad idea. There are problems that cause a load of valid, but
- empty, data packets. Don't reset the timeout unless we've actually
- got a frame. I've had xawtv hang in free_buffer due to this! */
- if (rc >= 0)
- mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-#endif
- spin_unlock_irqrestore(&dev->slock,flags);
-}
-
-/*
- * Stop and Deallocate URBs
- */
-static void em28xx_uninit_isoc(struct em28xx *dev)
-{
- struct urb *urb;
- int i;
-
- em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n");
-
- dev->isoc_ctl.nfields=-1;
- dev->isoc_ctl.buf=NULL;
- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
- urb=dev->isoc_ctl.urb[i];
- if (urb) {
- usb_kill_urb(urb);
- usb_unlink_urb(urb);
- if (dev->isoc_ctl.transfer_buffer[i]) {
- usb_buffer_free(dev->udev,
- urb->transfer_buffer_length,
- dev->isoc_ctl.transfer_buffer[i],
- urb->transfer_dma);
+ if (p[0] == 0x22 && p[1] == 0x5a) {
+ em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
+ len, (p[2] & 1)? "odd" : "even");
+
+ if (!(p[2] & 1)) {
+ if (buf != NULL)
+ buffer_filled(dev, dma_q, buf);
+ get_next_buf(dma_q, &buf);
+ if (buf == NULL)
+ outp = NULL;
+ else
+ outp = videobuf_to_vmalloc(&buf->vb);
}
- usb_free_urb(urb);
- dev->isoc_ctl.urb[i] = NULL;
- }
- dev->isoc_ctl.transfer_buffer[i] = NULL;
- }
-
- kfree (dev->isoc_ctl.urb);
- kfree (dev->isoc_ctl.transfer_buffer);
- dev->isoc_ctl.urb=NULL;
- dev->isoc_ctl.transfer_buffer=NULL;
-
- dev->isoc_ctl.num_bufs=0;
-
- // em28xx_capture_start(dev, 0); - FIXME - how could I restart it?
-}
-
-
-/*
- * Allocate URBs and start IRQ
- */
-static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets,
- int num_bufs)
-{
- struct em28xx_dmaqueue *dma_q = &dev->vidq;
- int i;
- int sb_size, pipe;
- struct urb *urb;
- int j, k;
-
- em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n");
-
- /* De-allocates all pending stuff */
- em28xx_uninit_isoc(dev);
-
- dev->isoc_ctl.num_bufs = num_bufs;
-
- dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
- if (!dev->isoc_ctl.urb) {
- em28xx_errdev("cannot alloc memory for usb buffers\n");
- return -ENOMEM;
- }
- dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
- GFP_KERNEL);
- if (!dev->isoc_ctl.urb) {
- em28xx_errdev("cannot allocate memory for usbtransfer\n");
- kfree(dev->isoc_ctl.urb);
- return -ENOMEM;
- }
-
- dev->isoc_ctl.max_pkt_size = dev->max_pkt_size;
-
- sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
-
- /* allocate urbs and transfer buffers */
- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
- urb = usb_alloc_urb(max_packets, GFP_KERNEL);
- if (!urb) {
- em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
- em28xx_uninit_isoc(dev);
- return -ENOMEM;
- }
- dev->isoc_ctl.urb[i] = urb;
-
- dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
- sb_size, GFP_KERNEL, &urb->transfer_dma);
- if (!dev->isoc_ctl.transfer_buffer[i]) {
- em28xx_err ("unable to allocate %i bytes for transfer"
- " buffer %i%s\n",
- sb_size, i,
- in_interrupt()?" while in int":"");
- em28xx_uninit_isoc(dev);
- return -ENOMEM;
- }
- memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
-
- /* FIXME: this is a hack - should be
- 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
- should also be using 'desc.bInterval'
- */
- pipe=usb_rcvisocpipe(dev->udev, 0x82);
- usb_fill_int_urb(urb, dev->udev, pipe,
- dev->isoc_ctl.transfer_buffer[i], sb_size,
- em28xx_irq_callback, dma_q, 1);
-
- urb->number_of_packets = max_packets;
- urb->transfer_flags = URB_ISO_ASAP;
-
- k = 0;
- for (j = 0; j < max_packets; j++) {
- urb->iso_frame_desc[j].offset = k;
- urb->iso_frame_desc[j].length =
- dev->isoc_ctl.max_pkt_size;
- k += dev->isoc_ctl.max_pkt_size;
- }
- }
-
- return 0;
-}
-
-static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q)
-{
- struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
- int i,rc = 0;
-
- em28xx_videodbg("Called em28xx_start_thread\n");
-
- init_waitqueue_head(&dma_q->wq);
+ if (buf != NULL) {
+ if (p[2] & 1)
+ buf->top_field = 0;
+ else
+ buf->top_field = 1;
+ }
- /* submit urbs and enables IRQ */
- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
- rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
- if (rc) {
- em28xx_err("submit of urb %i failed (error=%i)\n", i,
- rc);
- em28xx_uninit_isoc(dev);
- return rc;
+ dma_q->pos = 0;
}
+ if (buf != NULL)
+ em28xx_copy_video(dev, dma_q, buf, p, outp, len);
}
-
- if (rc<0)
- return rc;
-
- return 0;
-}
-
-
-static void em28xx_vid_timeout(unsigned long data)
-{
- struct em28xx *dev = (struct em28xx*)data;
- struct em28xx_dmaqueue *vidq = &dev->vidq;
- struct em28xx_buffer *buf;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->slock,flags);
- while (!list_empty(&vidq->active)) {
- buf = list_entry(vidq->active.next, struct em28xx_buffer,
- vb.queue);
- list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
- wake_up(&buf->vb.done);
- em28xx_videodbg("em28xx/0: [%p/%d] timeout\n",
- buf, buf->vb.i);
- }
-
- /* restart_video_queue(vidq); */
- spin_unlock_irqrestore(&dev->slock,flags);
+ return rc;
}
/* ------------------------------------------------------------------
buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
{
struct em28xx_fh *fh = vq->priv_data;
+ struct em28xx *dev = fh->dev;
+ struct v4l2_frequency f;
*size = 16 * fh->dev->width * fh->dev->height >> 3;
if (0 == *count)
*count = EM28XX_DEF_BUF;
- if (*count < EM28XX_MIN_BUF) {
- *count=EM28XX_MIN_BUF;
- }
+ if (*count < EM28XX_MIN_BUF)
+ *count = EM28XX_MIN_BUF;
+
+ /* Ask tuner to go to analog mode */
+ memset(&f, 0, sizeof(f));
+ f.frequency = dev->ctl_freq;
+
+ em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
return 0;
}
+/* This is called *without* dev->slock held; please keep it that way */
static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
{
+ struct em28xx_fh *fh = vq->priv_data;
+ struct em28xx *dev = fh->dev;
+ unsigned long flags = 0;
if (in_interrupt())
BUG();
- videobuf_waiton(&buf->vb, 0, 0);
+ /* We used to wait for the buffer to finish here, but this didn't work
+ because, as we were keeping the state as VIDEOBUF_QUEUED,
+ videobuf_queue_cancel marked it as finished for us.
+ (Also, it could wedge forever if the hardware was misconfigured.)
+
+ This should be safe; by the time we get here, the buffer isn't
+ queued anymore. If we ever start marking the buffers as
+ VIDEOBUF_ACTIVE, it won't be, though.
+ */
+ spin_lock_irqsave(&dev->slock, flags);
+ if (dev->isoc_ctl.buf == buf)
+ dev->isoc_ctl.buf = NULL;
+ spin_unlock_irqrestore(&dev->slock, flags);
+
videobuf_vmalloc_free(&buf->vb);
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}
enum v4l2_field field)
{
struct em28xx_fh *fh = vq->priv_data;
- struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb);
+ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
struct em28xx *dev = fh->dev;
- struct em28xx_dmaqueue *vidq = &dev->vidq;
int rc = 0, urb_init = 0;
- /* BUG_ON(NULL == fh->fmt); */
-
/* FIXME: It assumes depth = 16 */
/* The only currently supported format is 16 bits/pixel */
buf->vb.size = 16 * dev->width * dev->height >> 3;
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
return -EINVAL;
- if (buf->fmt != fh->fmt ||
- buf->vb.width != dev->width ||
- buf->vb.height != dev->height ||
- buf->vb.field != field) {
- buf->fmt = fh->fmt;
- buf->vb.width = dev->width;
- buf->vb.height = dev->height;
- buf->vb.field = field;
- buf->vb.state = VIDEOBUF_NEEDS_INIT;
- }
+ buf->vb.width = dev->width;
+ buf->vb.height = dev->height;
+ buf->vb.field = field;
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
rc = videobuf_iolock(vq, &buf->vb, NULL);
}
if (!dev->isoc_ctl.num_bufs)
- urb_init=1;
+ urb_init = 1;
if (urb_init) {
- rc = em28xx_prepare_isoc(dev, EM28XX_NUM_PACKETS, EM28XX_NUM_BUFS);
- if (rc<0)
- goto fail;
-
- /* FIXME - should probably be done in response to STREAMON */
- rc = em28xx_start_thread(vidq);
- if (rc<0)
+ rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
+ EM28XX_NUM_BUFS, dev->max_pkt_size,
+ em28xx_isoc_copy);
+ if (rc < 0)
goto fail;
}
return 0;
fail:
- free_buffer(vq,buf);
+ free_buffer(vq, buf);
return rc;
}
{
struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
struct em28xx_fh *fh = vq->priv_data;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = fh->dev;
struct em28xx_dmaqueue *vidq = &dev->vidq;
buf->vb.state = VIDEOBUF_QUEUED;
}
-static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static void buffer_release(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
{
- struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb);
+ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
struct em28xx_fh *fh = vq->priv_data;
- struct em28xx *dev = (struct em28xx*)fh->dev;
+ struct em28xx *dev = (struct em28xx *)fh->dev;
em28xx_isocdbg("em28xx: called buffer_release\n");
- free_buffer(vq,buf);
+ free_buffer(vq, buf);
}
static struct videobuf_queue_ops em28xx_video_qops = {
.buf_release = buffer_release,
};
-/********************* v4l2 interface ******************************************/
+/********************* v4l2 interface **************************************/
/*
* em28xx_config()
/* enable vbi capturing */
-/* em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */
-/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
- em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
+/* em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */
+/* em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */
+ em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1);
dev->mute = 1; /* maybe not the right place... */
dev->volume = 0x1f;
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
if (dev->has_msp34xx) {
- if (dev->i2s_speed)
- em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
+ if (dev->i2s_speed) {
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ,
+ &dev->i2s_speed);
+ }
route.input = dev->ctl_ainput;
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
/* Note: this is msp3400 specific */
- em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
+ &route);
}
em28xx_audio_analog_set(dev);
if (fh->stream_on)
return rc;
- mutex_lock(&dev->lock);
-
if (dev->stream_on)
- rc = -EINVAL;
- else {
- dev->stream_on = 1;
- fh->stream_on = 1;
- }
+ return -EINVAL;
+ mutex_lock(&dev->lock);
+ dev->stream_on = 1;
+ fh->stream_on = 1;
mutex_unlock(&dev->lock);
return rc;
}
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- f->fmt.pix.bytesperline = dev->bytesperline;
- f->fmt.pix.sizeimage = dev->frame_size;
+ f->fmt.pix.bytesperline = dev->width * 2;
+ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
/* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
mutex_lock(&dev->lock);
+ if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+ em28xx_errdev("%s queue busy\n", __func__);
+ rc = -EBUSY;
+ goto out;
+ }
+
+ if (dev->stream_on && !fh->stream_on) {
+ em28xx_errdev("%s device in use by another fh\n", __func__);
+ rc = -EBUSY;
+ goto out;
+ }
+
/* set new image size */
dev->width = f->fmt.pix.width;
dev->height = f->fmt.pix.height;
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1;
- dev->bytesperline = dev->width * 2;
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
em28xx_set_alternate(dev);
- em28xx_capture_start(dev, 1); /* ??? */
em28xx_resolution_set(dev);
+ rc = 0;
+
+out:
mutex_unlock(&dev->lock);
- return 0;
+ return rc;
}
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
/* set new image size */
dev->width = f.fmt.pix.width;
dev->height = f.fmt.pix.height;
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1;
- dev->bytesperline = dev->width * 2;
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
em28xx_resolution_set(dev);
index = dev->ctl_ainput;
- if (index == 0) {
+ if (index == 0)
strcpy(a->name, "Television");
- } else {
+ else
strcpy(a->name, "Line In");
- }
+
a->capability = V4L2_AUDCAP_STEREO;
a->index = index;
static int em28xx_reg_len(int reg)
{
switch (reg) {
- case AC97LSB_REG:
- case HSCALELOW_REG:
- case VSCALELOW_REG:
+ case EM28XX_R40_AC97LSB:
+ case EM28XX_R30_HSCALELOW:
+ case EM28XX_R32_VSCALELOW:
return 2;
default:
return 1;
if (unlikely(res_get(fh) < 0))
return -EBUSY;
- /* We can't do this from buffer_queue or anything called from
- there, since it's called with IRQs disabled and the spinlock held,
- and this uses USB functions that may sleep
-
- FIXME FIXME FIXME - putting this here means it may not always
- be called when it needs to be */
- em28xx_capture_start(dev, 1);
-
return (videobuf_streamon(&fh->vb_vidq));
}
}
#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
{
- struct em28xx_fh *fh=priv;
+ struct em28xx_fh *fh = priv;
- return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8);
+ return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
}
#endif
{
int minor = iminor(inode);
int errCode = 0, radio = 0;
- struct em28xx *h,*dev = NULL;
+ struct em28xx *h, *dev = NULL;
struct em28xx_fh *fh;
enum v4l2_buf_type fh_type = 0;
em28xx_videodbg("open minor=%d type=%s users=%d\n",
minor, v4l2_type_names[fh_type], dev->users);
- fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+ fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
if (!fh) {
em28xx_errdev("em28xx-video.c: Out of memory?!\n");
return -ENOMEM;
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
dev->width = norm_maxw(dev);
dev->height = norm_maxh(dev);
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
- dev->bytesperline = dev->width * 2;
dev->hscale = 0;
dev->vscale = 0;
+ em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
em28xx_set_alternate(dev);
em28xx_resolution_set(dev);
+ /* Needed, since GPIO might have disabled power of
+ some i2c device
+ */
+ em28xx_config_i2c(dev);
+
}
if (fh->radio) {
em28xx_videodbg("video_open: setting radio device\n");
sizeof(struct em28xx_buffer), fh);
mutex_unlock(&dev->lock);
+
return errCode;
}
usb_put_dev(dev->udev);
/* Mark device as unused */
- em28xx_devused&=~(1<<dev->devno);
+ em28xx_devused &= ~(1<<dev->devno);
}
/*
* em28xx_v4l2_close()
- * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
+ * stops streaming and deallocates all resources allocated by the v4l2
+ * calls and ioctls
*/
static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
{
/* do this before setting alternate! */
em28xx_uninit_isoc(dev);
+ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
/* set alternate 0 */
dev->alt = 0;
* will allocate buffers when called for the first time
*/
static ssize_t
-em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
- loff_t * pos)
+em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *pos)
{
struct em28xx_fh *fh = filp->private_data;
struct em28xx *dev = fh->dev;
#endif
};
-/******************************** usb interface *****************************************/
+/******************************** usb interface ******************************/
static LIST_HEAD(em28xx_extension_devlist);
vfd->dev = &dev->udev->dev;
vfd->release = video_device_release;
vfd->type = type;
+ vfd->debug = video_debug;
snprintf(vfd->name, sizeof(vfd->name), "%s %s",
dev->name, type_name);
dev->em28xx_read_reg_req = em28xx_read_reg_req;
dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
- errCode = em28xx_read_reg(dev, CHIPID_REG);
- if (errCode >= 0)
- em28xx_info("em28xx chip ID = %d\n", errCode);
-
em28xx_pre_card_setup(dev);
errCode = em28xx_config(dev);
dev->width = maxw;
dev->height = maxh;
dev->interlaced = EM28XX_INTERLACED_DEFAULT;
- dev->field_size = dev->width * dev->height;
- dev->frame_size =
- dev->interlaced ? dev->field_size << 1 : dev->field_size;
- dev->bytesperline = dev->width * 2;
dev->hscale = 0;
dev->vscale = 0;
dev->ctl_input = 2;
INIT_LIST_HEAD(&dev->vidq.active);
INIT_LIST_HEAD(&dev->vidq.queued);
- dev->vidq.timeout.function = em28xx_vid_timeout;
- dev->vidq.timeout.data = (unsigned long)dev;
- init_timer(&dev->vidq.timeout);
-
if (dev->has_msp34xx) {
/* Send a reset to other chips via gpio */
request_module("snd-usb-audio");
else
request_module("em28xx-alsa");
+
+ if (dev->has_dvb)
+ request_module("em28xx-dvb");
}
static void request_modules(struct em28xx *dev)
ifnum = interface->altsetting[0].desc.bInterfaceNumber;
/* Check to see next free device and mark as used */
- nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS);
- em28xx_devused|=1<<nr;
+ nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+ em28xx_devused |= 1<<nr;
/* Don't register audio interfaces */
if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",
- udev->descriptor.idVendor,udev->descriptor.idProduct,
+ udev->descriptor.idVendor,
+ udev->descriptor.idProduct,
ifnum,
interface->altsetting[0].desc.bInterfaceClass);
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENODEV;
}
em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",
- udev->descriptor.idVendor,udev->descriptor.idProduct,
+ udev->descriptor.idVendor,
+ udev->descriptor.idProduct,
ifnum,
interface->altsetting[0].desc.bInterfaceClass);
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
USB_ENDPOINT_XFER_ISOC) {
em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENODEV;
}
if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENODEV;
}
if (nr >= EM28XX_MAXBOARDS) {
- printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);
- em28xx_devused&=~(1<<nr);
+ printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+ EM28XX_MAXBOARDS);
+ em28xx_devused &= ~(1<<nr);
return -ENOMEM;
}
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em28xx_err(DRIVER_NAME ": out of memory!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENOMEM;
}
/* compute alternate max packet sizes */
uif = udev->actconfig->interface[0];
- dev->num_alt=uif->num_altsetting;
- em28xx_info("Alternate settings: %i\n",dev->num_alt);
-// dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)*
- dev->alt_max_pkt_size = kmalloc(32*
- dev->num_alt,GFP_KERNEL);
+ dev->num_alt = uif->num_altsetting;
+ em28xx_info("Alternate settings: %i\n", dev->num_alt);
+/* dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */
+ dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
+
if (dev->alt_max_pkt_size == NULL) {
em28xx_errdev("out of memory!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
kfree(dev);
return -ENOMEM;
}
wMaxPacketSize);
dev->alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- em28xx_info("Alternate setting %i, max size= %i\n",i,
- dev->alt_max_pkt_size[i]);
+ em28xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->alt_max_pkt_size[i]);
}
- if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))
+ if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
dev->model = card[nr];
/* allocate device struct */
em28xx_info("disconnecting %s\n", dev->vdev->name);
- /* wait until all current v4l2 io is finished then deallocate resources */
+ /* wait until all current v4l2 io is finished then deallocate
+ resources */
mutex_lock(&dev->lock);
wake_up_interruptible_all(&dev->open);