mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
V4L/DVB (7540): em28xx: convert to use videobuf-vmalloc
The usage of videobuf-vmalloc allows to cleanup em28xx logic. Also, it reduced its size by about 5.42% on i386 arch (and about 7.5% on x86_64): 39113 4876 40 44029 abfd old/em28xx.ko 36731 4868 40 41639 a2a7 /home/v4l/master/v4l/em28xx.ko Also, the preliminary tests, made on a single core 1.5 MHz Centrino showed that CPU usage reduced from 42%-75% to 28%-33% (reports from "top") command. A test with time command presented an even better result: This is the performance tests I did, running code_example to get 1,000 frames @29.995 Hz (about 35 seconds of stream), tested on a i386 machine, running at 1,5GHz: The old driver: $ time -f "%E: %Us User time, %Ss Kernel time, %P CPU used" ./capture_example 0:34.21: 8.22s User time, 25.16s Kernel time, 97% CPU used The videobuf-based driver: $ time -f "%E: %Us User time, %Ss Kernel time, %P CPU used" ./capture_example 0:35.36: 0.01s User time, 0.05s Kernel time, 0% CPU used Conclusion: The time consumption to receive the stream where reduced from about 33.38 seconds to 0.05 seconds. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
78e92006f4
commit
ad0ebb96c2
3 changed files with 813 additions and 900 deletions
|
@ -49,87 +49,10 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
|
|||
printk(KERN_INFO "%s %s :"fmt, \
|
||||
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]");
|
||||
|
||||
#define em28xx_isocdbg(fmt, arg...) do {\
|
||||
if (isoc_debug) \
|
||||
printk(KERN_INFO "%s %s :"fmt, \
|
||||
dev->name, __func__ , ##arg); } while (0)
|
||||
|
||||
static int alt = EM28XX_PINOUT;
|
||||
module_param(alt, int, 0644);
|
||||
MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
|
||||
|
||||
|
||||
/*
|
||||
* em28xx_request_buffers()
|
||||
* allocate a number of buffers
|
||||
*/
|
||||
u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
|
||||
{
|
||||
const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */
|
||||
void *buff = NULL;
|
||||
u32 i;
|
||||
em28xx_coredbg("requested %i buffers with size %zi\n",
|
||||
count, imagesize);
|
||||
if (count > EM28XX_NUM_FRAMES)
|
||||
count = EM28XX_NUM_FRAMES;
|
||||
|
||||
dev->num_frames = count;
|
||||
while (dev->num_frames > 0) {
|
||||
if ((buff = vmalloc_32(dev->num_frames * imagesize))) {
|
||||
memset(buff, 0, dev->num_frames * imagesize);
|
||||
break;
|
||||
}
|
||||
dev->num_frames--;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->num_frames; i++) {
|
||||
dev->frame[i].bufmem = buff + i * imagesize;
|
||||
dev->frame[i].buf.index = i;
|
||||
dev->frame[i].buf.m.offset = i * imagesize;
|
||||
dev->frame[i].buf.length = dev->frame_size;
|
||||
dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
dev->frame[i].buf.sequence = 0;
|
||||
dev->frame[i].buf.field = V4L2_FIELD_NONE;
|
||||
dev->frame[i].buf.memory = V4L2_MEMORY_MMAP;
|
||||
dev->frame[i].buf.flags = 0;
|
||||
}
|
||||
return dev->num_frames;
|
||||
}
|
||||
|
||||
/*
|
||||
* em28xx_queue_unusedframes()
|
||||
* add all frames that are not currently in use to the inbuffer queue
|
||||
*/
|
||||
void em28xx_queue_unusedframes(struct em28xx *dev)
|
||||
{
|
||||
unsigned long lock_flags;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < dev->num_frames; i++)
|
||||
if (dev->frame[i].state == F_UNUSED) {
|
||||
dev->frame[i].state = F_QUEUED;
|
||||
spin_lock_irqsave(&dev->queue_lock, lock_flags);
|
||||
list_add_tail(&dev->frame[i].frame, &dev->inqueue);
|
||||
spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* em28xx_release_buffers()
|
||||
* free frame buffers
|
||||
*/
|
||||
void em28xx_release_buffers(struct em28xx *dev)
|
||||
{
|
||||
if (dev->num_frames) {
|
||||
vfree(dev->frame[0].bufmem);
|
||||
dev->num_frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* em28xx_read_reg_req()
|
||||
* reads data from the usb device specifying bRequest
|
||||
|
@ -469,346 +392,6 @@ int em28xx_resolution_set(struct em28xx *dev)
|
|||
return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
|
||||
}
|
||||
|
||||
|
||||
/******************* isoc transfer handling ****************************/
|
||||
|
||||
#ifdef ENABLE_DEBUG_ISOC_FRAMES
|
||||
static void em28xx_isoc_dump(struct urb *urb)
|
||||
{
|
||||
int len = 0;
|
||||
int ntrans = 0;
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n",
|
||||
urb->start_frame, urb->number_of_packets,
|
||||
urb->error_count);
|
||||
for (i = 0; i < urb->number_of_packets; i++) {
|
||||
unsigned char *buf =
|
||||
urb->transfer_buffer +
|
||||
urb->iso_frame_desc[i].offset;
|
||||
int alen = urb->iso_frame_desc[i].actual_length;
|
||||
if (alen > 0) {
|
||||
if (buf[0] == 0x88) {
|
||||
ntrans++;
|
||||
len += alen;
|
||||
} else if (buf[0] == 0x22) {
|
||||
printk(KERN_DEBUG
|
||||
"= l=%d nt=%d bpp=%d\n",
|
||||
len - 4 * ntrans, ntrans,
|
||||
ntrans == 0 ? 0 : len / ntrans);
|
||||
ntrans = 1;
|
||||
len = alen;
|
||||
} else
|
||||
printk(KERN_DEBUG "!\n");
|
||||
}
|
||||
printk(KERN_DEBUG " n=%d s=%d al=%d %x\n", i,
|
||||
urb->iso_frame_desc[i].status,
|
||||
urb->iso_frame_desc[i].actual_length,
|
||||
(unsigned int)
|
||||
*((unsigned char *)(urb->transfer_buffer +
|
||||
urb->iso_frame_desc[i].
|
||||
offset)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f,
|
||||
unsigned long *lock_flags, unsigned char buf)
|
||||
{
|
||||
if (!(buf & 0x01)) {
|
||||
if ((*f)->state == F_GRABBING) {
|
||||
/*previous frame is incomplete */
|
||||
if ((*f)->fieldbytesused < dev->field_size) {
|
||||
(*f)->state = F_ERROR;
|
||||
em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)",
|
||||
dev->field_size-(*f)->fieldbytesused);
|
||||
} else {
|
||||
(*f)->state = F_DONE;
|
||||
(*f)->buf.bytesused = dev->frame_size;
|
||||
}
|
||||
}
|
||||
if ((*f)->state == F_DONE || (*f)->state == F_ERROR) {
|
||||
/* move current frame to outqueue and get next free buffer from inqueue */
|
||||
spin_lock_irqsave(&dev-> queue_lock, *lock_flags);
|
||||
list_move_tail(&(*f)->frame, &dev->outqueue);
|
||||
if (!list_empty(&dev->inqueue))
|
||||
(*f) = list_entry(dev-> inqueue.next,
|
||||
struct em28xx_frame_t,frame);
|
||||
else
|
||||
(*f) = NULL;
|
||||
spin_unlock_irqrestore(&dev->queue_lock,*lock_flags);
|
||||
}
|
||||
if (!(*f)) {
|
||||
em28xx_isocdbg ("new frame but no buffer is free");
|
||||
return -1;
|
||||
}
|
||||
do_gettimeofday(&(*f)->buf.timestamp);
|
||||
(*f)->buf.sequence = ++dev->frame_count;
|
||||
(*f)->buf.field = V4L2_FIELD_INTERLACED;
|
||||
(*f)->state = F_GRABBING;
|
||||
(*f)->buf.bytesused = 0;
|
||||
(*f)->top_field = 1;
|
||||
(*f)->fieldbytesused = 0;
|
||||
} else {
|
||||
/* acquiring bottom field */
|
||||
if ((*f)->state == F_GRABBING) {
|
||||
if (!(*f)->top_field) {
|
||||
(*f)->state = F_ERROR;
|
||||
em28xx_isocdbg ("unexpected begin of bottom field; discarding it");
|
||||
} else if ((*f)-> fieldbytesused < dev->field_size - 172) {
|
||||
(*f)->state = F_ERROR;
|
||||
em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)",
|
||||
dev->field_size-(*f)->fieldbytesused);
|
||||
} else {
|
||||
(*f)->top_field = 0;
|
||||
(*f)->fieldbytesused = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static inline void em28xx_isoc_video_copy(struct em28xx *dev,
|
||||
struct em28xx_frame_t **f, unsigned char *buf, int len)
|
||||
{
|
||||
void *fieldstart, *startwrite, *startread;
|
||||
int linesdone, currlinedone, offset, lencopy,remain;
|
||||
|
||||
if(dev->frame_size != (*f)->buf.length){
|
||||
em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((*f)->fieldbytesused + len > dev->field_size)
|
||||
len =dev->field_size - (*f)->fieldbytesused;
|
||||
|
||||
if (buf[0] != 0x88 && buf[0] != 0x22) {
|
||||
em28xx_isocdbg("frame is not complete\n");
|
||||
startread = buf;
|
||||
len+=4;
|
||||
} else
|
||||
startread = buf + 4;
|
||||
|
||||
remain = len;
|
||||
|
||||
if ((*f)->top_field)
|
||||
fieldstart = (*f)->bufmem;
|
||||
else
|
||||
fieldstart = (*f)->bufmem + dev->bytesperline;
|
||||
|
||||
linesdone = (*f)->fieldbytesused / dev->bytesperline;
|
||||
currlinedone = (*f)->fieldbytesused % dev->bytesperline;
|
||||
offset = linesdone * dev->bytesperline * 2 + currlinedone;
|
||||
startwrite = fieldstart + offset;
|
||||
lencopy = dev->bytesperline - currlinedone;
|
||||
lencopy = lencopy > remain ? remain : lencopy;
|
||||
|
||||
memcpy(startwrite, startread, lencopy);
|
||||
remain -= lencopy;
|
||||
|
||||
while (remain > 0) {
|
||||
startwrite += lencopy + dev->bytesperline;
|
||||
startread += lencopy;
|
||||
if (dev->bytesperline > remain)
|
||||
lencopy = remain;
|
||||
else
|
||||
lencopy = dev->bytesperline;
|
||||
|
||||
memcpy(startwrite, startread, lencopy);
|
||||
remain -= lencopy;
|
||||
}
|
||||
|
||||
(*f)->fieldbytesused += len;
|
||||
}
|
||||
|
||||
/*
|
||||
* em28xx_isoIrq()
|
||||
* handles the incoming isoc urbs and fills the frames from our inqueue
|
||||
*/
|
||||
static void em28xx_isocIrq(struct urb *urb)
|
||||
{
|
||||
struct em28xx *dev = urb->context;
|
||||
int i, status;
|
||||
struct em28xx_frame_t **f;
|
||||
unsigned long lock_flags;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
#ifdef ENABLE_DEBUG_ISOC_FRAMES
|
||||
if (isoc_debug>1)
|
||||
em28xx_isoc_dump(urb);
|
||||
#endif
|
||||
|
||||
if (urb->status == -ENOENT)
|
||||
return;
|
||||
|
||||
f = &dev->frame_current;
|
||||
|
||||
if (dev->stream == STREAM_INTERRUPT) {
|
||||
dev->stream = STREAM_OFF;
|
||||
if ((*f))
|
||||
(*f)->state = F_QUEUED;
|
||||
em28xx_isocdbg("stream interrupted");
|
||||
wake_up_interruptible(&dev->wait_stream);
|
||||
}
|
||||
|
||||
if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
|
||||
return;
|
||||
|
||||
if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) {
|
||||
if (!(*f))
|
||||
(*f) = list_entry(dev->inqueue.next,
|
||||
struct em28xx_frame_t, frame);
|
||||
|
||||
for (i = 0; i < urb->number_of_packets; i++) {
|
||||
unsigned char *buf = urb->transfer_buffer +
|
||||
urb->iso_frame_desc[i].offset;
|
||||
int len = urb->iso_frame_desc[i].actual_length - 4;
|
||||
|
||||
if (urb->iso_frame_desc[i].status) {
|
||||
em28xx_isocdbg("data error: [%d] len=%d, status=%d", i,
|
||||
urb->iso_frame_desc[i].actual_length,
|
||||
urb->iso_frame_desc[i].status);
|
||||
if (urb->iso_frame_desc[i].status != -EPROTO)
|
||||
continue;
|
||||
}
|
||||
if (urb->iso_frame_desc[i].actual_length <= 0) {
|
||||
em28xx_isocdbg("packet %d is empty",i);
|
||||
continue;
|
||||
}
|
||||
if (urb->iso_frame_desc[i].actual_length >
|
||||
urb->iso_frame_desc[i].length) {
|
||||
em28xx_isocdbg("packet bigger than packet size");
|
||||
continue;
|
||||
}
|
||||
/*new frame */
|
||||
if (buf[0] == 0x22 && buf[1] == 0x5a) {
|
||||
em28xx_isocdbg("Video frame, length=%i!",len);
|
||||
|
||||
if (em28xx_isoc_video(dev,f,&lock_flags,buf[2]))
|
||||
break;
|
||||
} else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) {
|
||||
em28xx_isocdbg("VBI HEADER!!!");
|
||||
}
|
||||
|
||||
/* actual copying */
|
||||
if ((*f)->state == F_GRABBING) {
|
||||
em28xx_isoc_video_copy(dev,f,buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 ((status = usb_submit_urb(urb, GFP_ATOMIC))) {
|
||||
em28xx_errdev("resubmit of urb failed (error=%i)\n", status);
|
||||
dev->state |= DEV_MISCONFIGURED;
|
||||
}
|
||||
wake_up_interruptible(&dev->wait_frame);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* em28xx_uninit_isoc()
|
||||
* deallocates the buffers and urbs allocated during em28xx_init_iosc()
|
||||
*/
|
||||
void em28xx_uninit_isoc(struct em28xx *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EM28XX_NUM_BUFS; i++) {
|
||||
if (dev->urb[i]) {
|
||||
usb_kill_urb(dev->urb[i]);
|
||||
if (dev->transfer_buffer[i]) {
|
||||
usb_buffer_free(dev->udev,
|
||||
dev->urb[i]->transfer_buffer_length,
|
||||
dev->transfer_buffer[i],
|
||||
dev->urb[i]->transfer_dma);
|
||||
}
|
||||
usb_free_urb(dev->urb[i]);
|
||||
}
|
||||
dev->urb[i] = NULL;
|
||||
dev->transfer_buffer[i] = NULL;
|
||||
}
|
||||
em28xx_capture_start(dev, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* em28xx_init_isoc()
|
||||
* allocates transfer buffers and submits the urbs for isoc transfer
|
||||
*/
|
||||
int em28xx_init_isoc(struct em28xx *dev)
|
||||
{
|
||||
/* change interface to 3 which allows the biggest packet sizes */
|
||||
int i, errCode;
|
||||
int sb_size;
|
||||
|
||||
em28xx_set_alternate(dev);
|
||||
sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
|
||||
|
||||
/* reset streaming vars */
|
||||
dev->frame_current = NULL;
|
||||
dev->frame_count = 0;
|
||||
|
||||
/* allocate urbs */
|
||||
for (i = 0; i < EM28XX_NUM_BUFS; i++) {
|
||||
struct urb *urb;
|
||||
int j;
|
||||
/* allocate transfer buffer */
|
||||
urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
|
||||
if (!urb){
|
||||
em28xx_errdev("cannot alloc urb %i\n", i);
|
||||
em28xx_uninit_isoc(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
|
||||
GFP_KERNEL,
|
||||
&urb->transfer_dma);
|
||||
if (!dev->transfer_buffer[i]) {
|
||||
em28xx_errdev
|
||||
("unable to allocate %i bytes for transfer buffer %i\n",
|
||||
sb_size, i);
|
||||
em28xx_uninit_isoc(dev);
|
||||
usb_free_urb(urb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(dev->transfer_buffer[i], 0, sb_size);
|
||||
urb->dev = dev->udev;
|
||||
urb->context = dev;
|
||||
urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);
|
||||
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
|
||||
urb->interval = 1;
|
||||
urb->transfer_buffer = dev->transfer_buffer[i];
|
||||
urb->complete = em28xx_isocIrq;
|
||||
urb->number_of_packets = EM28XX_NUM_PACKETS;
|
||||
urb->transfer_buffer_length = sb_size;
|
||||
for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
|
||||
urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
|
||||
urb->iso_frame_desc[j].length = dev->max_pkt_size;
|
||||
}
|
||||
dev->urb[i] = urb;
|
||||
}
|
||||
|
||||
/* submit urbs */
|
||||
em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
|
||||
EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
|
||||
for (i = 0; i < EM28XX_NUM_BUFS; i++) {
|
||||
errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
|
||||
if (errCode) {
|
||||
em28xx_errdev("submit of urb %i failed (error=%i)\n", i,
|
||||
errCode);
|
||||
em28xx_uninit_isoc(dev);
|
||||
return errCode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int em28xx_set_alternate(struct em28xx *dev)
|
||||
{
|
||||
int errCode, prev_alt = dev->alt;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,12 +26,12 @@
|
|||
#define _EM28XX_H
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/videobuf-vmalloc.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <media/ir-kbd-i2c.h>
|
||||
|
||||
#define UNSET -1
|
||||
|
||||
/* maximum number of em28xx boards */
|
||||
#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
|
||||
|
||||
|
@ -81,31 +81,69 @@
|
|||
/* time in msecs to wait for i2c writes to finish */
|
||||
#define EM2800_I2C_WRITE_TIMEOUT 20
|
||||
|
||||
/* the various frame states */
|
||||
enum em28xx_frame_state {
|
||||
F_UNUSED = 0,
|
||||
F_QUEUED,
|
||||
F_GRABBING,
|
||||
F_DONE,
|
||||
F_ERROR,
|
||||
};
|
||||
|
||||
/* stream states */
|
||||
enum em28xx_stream_state {
|
||||
STREAM_OFF,
|
||||
STREAM_INTERRUPT,
|
||||
STREAM_ON,
|
||||
};
|
||||
|
||||
/* frames */
|
||||
struct em28xx_frame_t {
|
||||
void *bufmem;
|
||||
struct v4l2_buffer buf;
|
||||
enum em28xx_frame_state state;
|
||||
struct em28xx_usb_isoc_ctl {
|
||||
/* max packet size of isoc transaction */
|
||||
int max_pkt_size;
|
||||
|
||||
/* number of allocated urbs */
|
||||
int num_bufs;
|
||||
|
||||
/* urb for isoc transfers */
|
||||
struct urb **urb;
|
||||
|
||||
/* transfer buffers for isoc transfer */
|
||||
char **transfer_buffer;
|
||||
|
||||
/* Last buffer command and region */
|
||||
u8 cmd;
|
||||
int pos, size, pktsize;
|
||||
|
||||
/* Last field: ODD or EVEN? */
|
||||
int field;
|
||||
|
||||
/* Stores incomplete commands */
|
||||
u32 tmp_buf;
|
||||
int tmp_buf_len;
|
||||
|
||||
/* Stores already requested buffers */
|
||||
struct em28xx_buffer *buf;
|
||||
|
||||
/* Stores the number of received fields */
|
||||
int nfields;
|
||||
};
|
||||
|
||||
struct em28xx_fmt {
|
||||
char *name;
|
||||
u32 fourcc; /* v4l2 format id */
|
||||
};
|
||||
|
||||
/* buffer for one video frame */
|
||||
struct em28xx_buffer {
|
||||
/* common v4l buffer stuff -- must be first */
|
||||
struct videobuf_buffer vb;
|
||||
|
||||
struct em28xx_fmt *fmt;
|
||||
|
||||
struct list_head frame;
|
||||
unsigned long vma_use_count;
|
||||
int top_field;
|
||||
int fieldbytesused;
|
||||
int receiving;
|
||||
};
|
||||
|
||||
struct em28xx_dmaqueue {
|
||||
struct list_head active;
|
||||
struct list_head queued;
|
||||
struct timer_list timeout;
|
||||
|
||||
wait_queue_head_t wq;
|
||||
|
||||
/* Counters to control buffer fill */
|
||||
int pos;
|
||||
};
|
||||
|
||||
/* io methods */
|
||||
|
@ -255,10 +293,6 @@ struct em28xx {
|
|||
int mute;
|
||||
int volume;
|
||||
/* frame properties */
|
||||
struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */
|
||||
int num_frames; /* number of frames currently in use */
|
||||
unsigned int frame_count; /* total number of transfered frames */
|
||||
struct em28xx_frame_t *frame_current; /* the frame that is being filled */
|
||||
int width; /* current frame width */
|
||||
int height; /* current frame height */
|
||||
int frame_size; /* current frame size */
|
||||
|
@ -277,7 +311,6 @@ struct em28xx {
|
|||
|
||||
/* states */
|
||||
enum em28xx_dev_state state;
|
||||
enum em28xx_stream_state stream;
|
||||
enum em28xx_io_method io;
|
||||
|
||||
struct work_struct request_module_wk;
|
||||
|
@ -292,6 +325,11 @@ struct em28xx {
|
|||
|
||||
unsigned char eedata[256];
|
||||
|
||||
/* Isoc control struct */
|
||||
struct em28xx_dmaqueue vidq;
|
||||
struct em28xx_usb_isoc_ctl isoc_ctl;
|
||||
spinlock_t slock;
|
||||
|
||||
/* usb transfer */
|
||||
struct usb_device *udev; /* the usb device */
|
||||
int alt; /* alternate */
|
||||
|
@ -315,6 +353,12 @@ struct em28xx_fh {
|
|||
struct em28xx *dev;
|
||||
unsigned int stream_on:1; /* Locks streams */
|
||||
int radio;
|
||||
|
||||
unsigned int width, height;
|
||||
struct videobuf_queue vb_vidq;
|
||||
struct em28xx_fmt *fmt;
|
||||
|
||||
enum v4l2_buf_type type;
|
||||
};
|
||||
|
||||
struct em28xx_ops {
|
||||
|
@ -351,8 +395,6 @@ int em28xx_colorlevels_set_default(struct em28xx *dev);
|
|||
int em28xx_capture_start(struct em28xx *dev, int start);
|
||||
int em28xx_outfmt_set_yuv422(struct em28xx *dev);
|
||||
int em28xx_resolution_set(struct em28xx *dev);
|
||||
int em28xx_init_isoc(struct em28xx *dev);
|
||||
void em28xx_uninit_isoc(struct em28xx *dev);
|
||||
int em28xx_set_alternate(struct em28xx *dev);
|
||||
|
||||
/* Provided by em28xx-video.c */
|
||||
|
|
Loading…
Reference in a new issue