Skip to content

Commit

Permalink
[media] em28xx: prefer bulk mode on webcams
Browse files Browse the repository at this point in the history
Using bulk mode allows more than one webcam, as the maximum fps
is low at 640x480 resolution. So, prefer it, if the device is
a webcam.

Tested with Silvercrest 1.3 Mpixel webcam (em2710) on both bulk and isoc
modes.

Tested analog with HVR-950 model 65201/A1C0 (em2883), where only ISOC
endpoints are available for both DVB and Analog.

Tested on Hauppauge WinTV USB 2 (em2840) on both bulk and isoc modes.

It should be noticed that enabling bulk mode by default with TV boards
is a bad idea; what happens is that, while with ISOC the USB logic will
prevent the concurrent usage of two devices that spends more than 100%
of the USB2 traffic, it doesn't care with bulk transfers.

On my tests, I started two streams, one with a WinTV at 640x480x30fps
and the other one with a Silvercrest webcam at 640x480, on a lower fps)
both on bulk mode. One of the streams always silently failed.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Mauro Carvalho Chehab committed Dec 23, 2012
1 parent a3efa1c commit 8b2aea7
Showing 1 changed file with 25 additions and 11 deletions.
36 changes: 25 additions & 11 deletions drivers/media/usb/em28xx/em28xx-cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "card type");

static unsigned int prefer_bulk;
static int prefer_bulk = -1;
module_param(prefer_bulk, int, 0444);
MODULE_PARM_DESC(prefer_bulk, "prefer USB bulk transfers");
MODULE_PARM_DESC(prefer_bulk, "prefer USB bulk transfers (-1 = auto, 0 = isoc, 1 = bulk)");


/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
Expand Down Expand Up @@ -3170,7 +3170,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
struct em28xx *dev = NULL;
int retval;
bool has_audio = false, has_video = false, has_dvb = false;
int i, nr;
int i, nr, try_bulk;
const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
char *speed;

Expand Down Expand Up @@ -3344,14 +3344,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
goto err_free;
}

/* Select USB transfer types to use */
if (has_video &&
(!dev->analog_ep_isoc || (prefer_bulk && dev->analog_ep_bulk)))
dev->analog_xfer_bulk = 1;
if (has_dvb &&
(!dev->dvb_ep_isoc || (prefer_bulk && dev->dvb_ep_bulk)))
dev->dvb_xfer_bulk = 1;

dev->devno = nr;
dev->model = id->driver_info;
dev->alt = -1;
Expand Down Expand Up @@ -3402,7 +3394,29 @@ static int em28xx_usb_probe(struct usb_interface *interface,
goto unlock_and_free;
}

if (prefer_bulk < 0) {
if (dev->board.is_webcam)
try_bulk = 1;
else
try_bulk = 0;
} else {
try_bulk = prefer_bulk > 0;
}

/* Select USB transfer types to use */
if (has_video) {
if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk))
dev->analog_xfer_bulk = 1;
em28xx_info("analog set to %s mode.\n",
dev->analog_xfer_bulk ? "bulk" : "isoc");
}
if (has_dvb) {
if (!dev->dvb_ep_isoc || (try_bulk && dev->dvb_ep_bulk))
dev->dvb_xfer_bulk = 1;

em28xx_info("dvb set to %s mode.\n",
dev->dvb_xfer_bulk ? "bulk" : "isoc");

/* pre-allocate DVB usb transfer buffers */
if (dev->dvb_xfer_bulk) {
retval = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE,
Expand Down

0 comments on commit 8b2aea7

Please sign in to comment.