aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-02-08 13:44:25 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-02-18 09:15:17 -0500
commit3687e1e67e4920a202d53cc24678fb34fcda8fc5 (patch)
tree690923e60041a813ffbe4c03a9c0822ecb0402b8
parent92ea42f442c4895e38f525a097d7d8ce2a55b9b9 (diff)
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 <mchehab@infradead.org>
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c62
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c4
-rw-r--r--drivers/media/video/em28xx/em28xx.h2
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 275f1e936304..0966017ca745 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)
72 const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ 72 const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */
73 void *buff = NULL; 73 void *buff = NULL;
74 u32 i; 74 u32 i;
75 em28xx_coredbg("requested %i buffers with size %zi", count, imagesize); 75 em28xx_coredbg("requested %i buffers with size %zi\n",
76 count, imagesize);
76 if (count > EM28XX_NUM_FRAMES) 77 if (count > EM28XX_NUM_FRAMES)
77 count = EM28XX_NUM_FRAMES; 78 count = EM28XX_NUM_FRAMES;
78 79
@@ -676,7 +677,7 @@ static void em28xx_isocIrq(struct urb *urb)
676 continue; 677 continue;
677 } 678 }
678 if (urb->iso_frame_desc[i].actual_length > 679 if (urb->iso_frame_desc[i].actual_length >
679 dev->max_pkt_size) { 680 urb->iso_frame_desc[i].length) {
680 em28xx_isocdbg("packet bigger than packet size"); 681 em28xx_isocdbg("packet bigger than packet size");
681 continue; 682 continue;
682 } 683 }
@@ -722,8 +723,11 @@ void em28xx_uninit_isoc(struct em28xx *dev)
722 for (i = 0; i < EM28XX_NUM_BUFS; i++) { 723 for (i = 0; i < EM28XX_NUM_BUFS; i++) {
723 if (dev->urb[i]) { 724 if (dev->urb[i]) {
724 usb_kill_urb(dev->urb[i]); 725 usb_kill_urb(dev->urb[i]);
725 if (dev->transfer_buffer[i]){ 726 if (dev->transfer_buffer[i]) {
726 usb_buffer_free(dev->udev,(EM28XX_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma); 727 usb_buffer_free(dev->udev,
728 dev->urb[i]->transfer_buffer_length,
729 dev->transfer_buffer[i],
730 dev->urb[i]->transfer_dma);
727 } 731 }
728 usb_free_urb(dev->urb[i]); 732 usb_free_urb(dev->urb[i]);
729 } 733 }
@@ -741,7 +745,10 @@ int em28xx_init_isoc(struct em28xx *dev)
741{ 745{
742 /* change interface to 3 which allows the biggest packet sizes */ 746 /* change interface to 3 which allows the biggest packet sizes */
743 int i, errCode; 747 int i, errCode;
744 const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; 748 int sb_size;
749
750 em28xx_set_alternate(dev);
751 sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
745 752
746 /* reset streaming vars */ 753 /* reset streaming vars */
747 dev->frame_current = NULL; 754 dev->frame_current = NULL;
@@ -750,7 +757,7 @@ int em28xx_init_isoc(struct em28xx *dev)
750 /* allocate urbs */ 757 /* allocate urbs */
751 for (i = 0; i < EM28XX_NUM_BUFS; i++) { 758 for (i = 0; i < EM28XX_NUM_BUFS; i++) {
752 struct urb *urb; 759 struct urb *urb;
753 int j, k; 760 int j;
754 /* allocate transfer buffer */ 761 /* allocate transfer buffer */
755 urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL); 762 urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
756 if (!urb){ 763 if (!urb){
@@ -758,7 +765,9 @@ int em28xx_init_isoc(struct em28xx *dev)
758 em28xx_uninit_isoc(dev); 765 em28xx_uninit_isoc(dev);
759 return -ENOMEM; 766 return -ENOMEM;
760 } 767 }
761 dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,&urb->transfer_dma); 768 dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
769 GFP_KERNEL,
770 &urb->transfer_dma);
762 if (!dev->transfer_buffer[i]) { 771 if (!dev->transfer_buffer[i]) {
763 em28xx_errdev 772 em28xx_errdev
764 ("unable to allocate %i bytes for transfer buffer %i\n", 773 ("unable to allocate %i bytes for transfer buffer %i\n",
@@ -777,16 +786,16 @@ int em28xx_init_isoc(struct em28xx *dev)
777 urb->complete = em28xx_isocIrq; 786 urb->complete = em28xx_isocIrq;
778 urb->number_of_packets = EM28XX_NUM_PACKETS; 787 urb->number_of_packets = EM28XX_NUM_PACKETS;
779 urb->transfer_buffer_length = sb_size; 788 urb->transfer_buffer_length = sb_size;
780 for (j = k = 0; j < EM28XX_NUM_PACKETS; 789 for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
781 j++, k += dev->max_pkt_size) { 790 urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
782 urb->iso_frame_desc[j].offset = k; 791 urb->iso_frame_desc[j].length = dev->max_pkt_size;
783 urb->iso_frame_desc[j].length =
784 dev->max_pkt_size;
785 } 792 }
786 dev->urb[i] = urb; 793 dev->urb[i] = urb;
787 } 794 }
788 795
789 /* submit urbs */ 796 /* submit urbs */
797 em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
798 EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
790 for (i = 0; i < EM28XX_NUM_BUFS; i++) { 799 for (i = 0; i < EM28XX_NUM_BUFS; i++) {
791 errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL); 800 errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
792 if (errCode) { 801 if (errCode) {
@@ -803,22 +812,31 @@ int em28xx_init_isoc(struct em28xx *dev)
803int em28xx_set_alternate(struct em28xx *dev) 812int em28xx_set_alternate(struct em28xx *dev)
804{ 813{
805 int errCode, prev_alt = dev->alt; 814 int errCode, prev_alt = dev->alt;
806 dev->alt = alt; 815 int i;
807 if (dev->alt == 0) { 816 unsigned int min_pkt_size = dev->bytesperline+4;
808 int i; 817
809 for(i=0;i< dev->num_alt; i++) 818 /* When image size is bigger than a ceirtain value,
810 if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) 819 the frame size should be increased, otherwise, only
811 dev->alt=i; 820 green screen will be received.
812 } 821 */
822 if (dev->frame_size > 720*240*2)
823 min_pkt_size *= 2;
824
825 for (i = 0; i < dev->num_alt; i++)
826 if (dev->alt_max_pkt_size[i] >= min_pkt_size)
827 break;
828 dev->alt = i;
813 829
814 if (dev->alt != prev_alt) { 830 if (dev->alt != prev_alt) {
831 em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
832 min_pkt_size, dev->alt);
815 dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; 833 dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
816 em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", dev->alt, 834 em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
817 dev->max_pkt_size); 835 dev->alt, dev->max_pkt_size);
818 errCode = usb_set_interface(dev->udev, 0, dev->alt); 836 errCode = usb_set_interface(dev->udev, 0, dev->alt);
819 if (errCode < 0) { 837 if (errCode < 0) {
820 em28xx_errdev ("cannot change alternate number to %d (error=%i)\n", 838 em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",
821 dev->alt, errCode); 839 dev->alt, errCode);
822 return errCode; 840 return errCode;
823 } 841 }
824 } 842 }
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index eeda3b2faec8..4abe6701a770 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)
1352 filp->private_data = fh; 1352 filp->private_data = fh;
1353 1353
1354 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { 1354 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
1355 em28xx_set_alternate(dev);
1356
1357 dev->width = norm_maxw(dev); 1355 dev->width = norm_maxw(dev);
1358 dev->height = norm_maxh(dev); 1356 dev->height = norm_maxh(dev);
1359 dev->frame_size = dev->width * dev->height * 2; 1357 dev->frame_size = dev->width * dev->height * 2;
@@ -1362,6 +1360,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
1362 dev->hscale = 0; 1360 dev->hscale = 0;
1363 dev->vscale = 0; 1361 dev->vscale = 0;
1364 1362
1363 em28xx_set_alternate(dev);
1365 em28xx_capture_start(dev, 1); 1364 em28xx_capture_start(dev, 1);
1366 em28xx_resolution_set(dev); 1365 em28xx_resolution_set(dev);
1367 1366
@@ -2129,6 +2128,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
2129 snprintf(dev->name, 29, "em28xx #%d", nr); 2128 snprintf(dev->name, 29, "em28xx #%d", nr);
2130 dev->devno = nr; 2129 dev->devno = nr;
2131 dev->model = id->driver_info; 2130 dev->model = id->driver_info;
2131 dev->alt = -1;
2132 2132
2133 /* Checks if audio is provided by some interface */ 2133 /* Checks if audio is provided by some interface */
2134 for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { 2134 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 813c0af458d3..04e0e48ecabe 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -33,7 +33,7 @@
33#define UNSET -1 33#define UNSET -1
34 34
35/* maximum number of em28xx boards */ 35/* maximum number of em28xx boards */
36#define EM28XX_MAXBOARDS 1 /*FIXME: should be bigger */ 36#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
37 37
38/* maximum number of frames that can be queued */ 38/* maximum number of frames that can be queued */
39#define EM28XX_NUM_FRAMES 5 39#define EM28XX_NUM_FRAMES 5