Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3687e1e67e4920a202d53cc24678fb34fcda8fc5
Commit:     3687e1e67e4920a202d53cc24678fb34fcda8fc5
Parent:     92ea42f442c4895e38f525a097d7d8ce2a55b9b9
Author:     Mauro Carvalho Chehab <[EMAIL PROTECTED]>
AuthorDate: Fri Feb 8 15:44:25 2008 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Mon Feb 18 11:15:17 2008 -0300

    V4L/DVB (7179): Allow more than one em28xx board
    
    em28xx driver is capable of handling more than one usb device. However, isoc
    transfers require a large amount of data to be transfered.
    
    Before this patch, just one em28xx board were enough to allocate more than 
50%
    URBs:
    
    T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480 MxCh= 8
    B:  Alloc=480/800 us (60%), #Int=  0, #Iso=  2
    D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=01 MxPS=64 #Cfgs=  1
    
    So, only one board could use an USB host at the same time. After the patch, 
it
    is possible to use more than one em28xx at the same time, on the same usb 
host,
    if the image size is slower or equal to 345600, since those images will
    require about 30% of the URBs:
    
    T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480 MxCh= 8
    B:  Alloc=232/800 us (29%), #Int=  0, #Iso=  2
    D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=01 MxPS=64 #Cfgs=  1
    
    So, in thesis, after the patch, it would be possible to use up to 3 boards 
by
    each usb host, if the devices are generating small images.
    
    Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]>
---
 drivers/media/video/em28xx/em28xx-core.c  |   62 ++++++++++++++++++----------
 drivers/media/video/em28xx/em28xx-video.c |    4 +-
 drivers/media/video/em28xx/em28xx.h       |    2 +-
 3 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/drivers/media/video/em28xx/em28xx-core.c 
b/drivers/media/video/em28xx/em28xx-core.c
index 275f1e9..0966017 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -72,7 +72,8 @@ 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", count, imagesize);
+       em28xx_coredbg("requested %i buffers with size %zi\n",
+                       count, imagesize);
        if (count > EM28XX_NUM_FRAMES)
                count = EM28XX_NUM_FRAMES;
 
@@ -676,7 +677,7 @@ static void em28xx_isocIrq(struct urb *urb)
                                continue;
                        }
                        if (urb->iso_frame_desc[i].actual_length >
-                                                dev->max_pkt_size) {
+                           urb->iso_frame_desc[i].length) {
                                em28xx_isocdbg("packet bigger than packet 
size");
                                continue;
                        }
@@ -722,8 +723,11 @@ void em28xx_uninit_isoc(struct em28xx *dev)
        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,(EM28XX_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma);
+                       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]);
                }
@@ -741,7 +745,10 @@ int em28xx_init_isoc(struct em28xx *dev)
 {
        /* change interface to 3 which allows the biggest packet sizes */
        int i, errCode;
-       const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
+       int sb_size;
+
+       em28xx_set_alternate(dev);
+       sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
 
        /* reset streaming vars */
        dev->frame_current = NULL;
@@ -750,7 +757,7 @@ int em28xx_init_isoc(struct em28xx *dev)
        /* allocate urbs */
        for (i = 0; i < EM28XX_NUM_BUFS; i++) {
                struct urb *urb;
-               int j, k;
+               int j;
                /* allocate transfer buffer */
                urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
                if (!urb){
@@ -758,7 +765,9 @@ int em28xx_init_isoc(struct em28xx *dev)
                        em28xx_uninit_isoc(dev);
                        return -ENOMEM;
                }
-               dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, 
GFP_KERNEL,&urb->transfer_dma);
+               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",
@@ -777,16 +786,16 @@ int em28xx_init_isoc(struct em28xx *dev)
                urb->complete = em28xx_isocIrq;
                urb->number_of_packets = EM28XX_NUM_PACKETS;
                urb->transfer_buffer_length = sb_size;
-               for (j = k = 0; j < EM28XX_NUM_PACKETS;
-                               j++, k += dev->max_pkt_size) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                               dev->max_pkt_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) {
@@ -803,22 +812,31 @@ int em28xx_init_isoc(struct em28xx *dev)
 int em28xx_set_alternate(struct em28xx *dev)
 {
        int errCode, prev_alt = dev->alt;
-       dev->alt = alt;
-       if (dev->alt == 0) {
-               int i;
-               for(i=0;i< dev->num_alt; i++)
-                       
if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt])
-                               dev->alt=i;
-       }
+       int i;
+       unsigned int min_pkt_size = dev->bytesperline+4;
+
+       /* When image size is bigger than a ceirtain value,
+          the frame size should be increased, otherwise, only
+          green screen will be received.
+        */
+       if (dev->frame_size > 720*240*2)
+               min_pkt_size *= 2;
+
+       for (i = 0; i < dev->num_alt; i++)
+               if (dev->alt_max_pkt_size[i] >= min_pkt_size)
+                       break;
+       dev->alt = i;
 
        if (dev->alt != prev_alt) {
+               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->alt);
                dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
-               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", 
dev->alt,
-                      dev->max_pkt_size);
+               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+                              dev->alt, dev->max_pkt_size);
                errCode = usb_set_interface(dev->udev, 0, dev->alt);
                if (errCode < 0) {
                        em28xx_errdev ("cannot change alternate number to %d 
(error=%i)\n",
-                                                       dev->alt, errCode);
+                                       dev->alt, errCode);
                        return errCode;
                }
        }
diff --git a/drivers/media/video/em28xx/em28xx-video.c 
b/drivers/media/video/em28xx/em28xx-video.c
index eeda3b2..4abe670 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1352,8 +1352,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct 
file *filp)
        filp->private_data = fh;
 
        if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
-               em28xx_set_alternate(dev);
-
                dev->width = norm_maxw(dev);
                dev->height = norm_maxh(dev);
                dev->frame_size = dev->width * dev->height * 2;
@@ -1362,6 +1360,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct 
file *filp)
                dev->hscale = 0;
                dev->vscale = 0;
 
+               em28xx_set_alternate(dev);
                em28xx_capture_start(dev, 1);
                em28xx_resolution_set(dev);
 
@@ -2129,6 +2128,7 @@ static int em28xx_usb_probe(struct usb_interface 
*interface,
        snprintf(dev->name, 29, "em28xx #%d", nr);
        dev->devno = nr;
        dev->model = id->driver_info;
+       dev->alt   = -1;
 
        /* Checks if audio is provided by some interface */
        for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
diff --git a/drivers/media/video/em28xx/em28xx.h 
b/drivers/media/video/em28xx/em28xx.h
index 813c0af..04e0e48 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -33,7 +33,7 @@
 #define UNSET -1
 
 /* maximum number of em28xx boards */
-#define EM28XX_MAXBOARDS 1 /*FIXME: should be bigger */
+#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
 
 /* maximum number of frames that can be queued */
 #define EM28XX_NUM_FRAMES 5
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to