diff --git a/packages/linux/patches/linux-3.2.28-214-hdtv-hvr930c.patch b/packages/linux/patches/linux-3.2.28-214-hdtv-hvr930c.patch new file mode 100644 index 0000000000..e84c2495ee --- /dev/null +++ b/packages/linux/patches/linux-3.2.28-214-hdtv-hvr930c.patch @@ -0,0 +1,389 @@ +From 8ab3362665a699bd54fc489ff7fb6372678b94c1 Mon Sep 17 00:00:00 2001 +From: Holger Nelson +Date: Wed, 28 Dec 2011 18:55:41 -0300 +Subject: [PATCH] [media] em28xx: Reworked probe code to get rid of some hacks + +Reworked device probing to get rid of hacks to guess the maximum size of +dvb iso transfer packets. The new code also selects the first alternate +config which supports the largest possible iso transfers for dvb. + +[mchehab@redhat.com: Fix a few checkpatch.pl CodingStyle compliants] +Signed-off-by: Holger Nelson +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/video/em28xx/em28xx-audio.c | 2 +- + drivers/media/video/em28xx/em28xx-cards.c | 148 ++++++++++++++--------------- + drivers/media/video/em28xx/em28xx-core.c | 59 +----------- + drivers/media/video/em28xx/em28xx-dvb.c | 4 +- + drivers/media/video/em28xx/em28xx-reg.h | 5 + + drivers/media/video/em28xx/em28xx.h | 2 + + 6 files changed, 84 insertions(+), 136 deletions(-) + +diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c +index cff0768..e2a7b77 100644 +--- a/drivers/media/video/em28xx/em28xx-audio.c ++++ b/drivers/media/video/em28xx/em28xx-audio.c +@@ -193,7 +193,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) + + urb->dev = dev->udev; + urb->context = dev; +- urb->pipe = usb_rcvisocpipe(dev->udev, 0x83); ++ urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = dev->adev.transfer_buffer[i]; + urb->interval = 1; +diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c +index b95e661..0adaf84 100644 +--- a/drivers/media/video/em28xx/em28xx-cards.c ++++ b/drivers/media/video/em28xx/em28xx-cards.c +@@ -3111,12 +3111,11 @@ unregister_dev: + static int em28xx_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) + { +- const struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev; + struct em28xx *dev = NULL; + int retval; +- bool is_audio_only = false, has_audio = false; +- int i, nr, isoc_pipe; ++ bool has_audio = false, has_video = false, has_dvb = false; ++ int i, nr; + const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; + char *speed; + char descr[255] = ""; +@@ -3148,54 +3147,65 @@ static int em28xx_usb_probe(struct usb_interface *interface, + goto err; + } + ++ /* allocate memory for our device state and initialize it */ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ if (dev == NULL) { ++ em28xx_err(DRIVER_NAME ": out of memory!\n"); ++ retval = -ENOMEM; ++ goto err; ++ } ++ ++ /* compute alternate max packet sizes */ ++ dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) * ++ interface->num_altsetting, GFP_KERNEL); ++ if (dev->alt_max_pkt_size == NULL) { ++ em28xx_errdev("out of memory!\n"); ++ kfree(dev); ++ retval = -ENOMEM; ++ goto err; ++ } ++ + /* Get endpoints */ + for (i = 0; i < interface->num_altsetting; i++) { + int ep; + + for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { +- struct usb_host_endpoint *e; +- e = &interface->altsetting[i].endpoint[ep]; +- +- if (e->desc.bEndpointAddress == 0x83) +- has_audio = true; ++ const struct usb_endpoint_descriptor *e; ++ int sizedescr, size; ++ ++ e = &interface->altsetting[i].endpoint[ep].desc; ++ ++ sizedescr = le16_to_cpu(e->wMaxPacketSize); ++ size = sizedescr & 0x7ff; ++ ++ if (udev->speed == USB_SPEED_HIGH) ++ size = size * hb_mult(sizedescr); ++ ++ if (usb_endpoint_xfer_isoc(e) && ++ usb_endpoint_dir_in(e)) { ++ switch (e->bEndpointAddress) { ++ case EM28XX_EP_AUDIO: ++ has_audio = true; ++ break; ++ case EM28XX_EP_ANALOG: ++ has_video = true; ++ dev->alt_max_pkt_size[i] = size; ++ break; ++ case EM28XX_EP_DIGITAL: ++ has_dvb = true; ++ if (size > dev->dvb_max_pkt_size) { ++ dev->dvb_max_pkt_size = size; ++ dev->dvb_alt = i; ++ } ++ break; ++ } ++ } + } + } + +- endpoint = &interface->cur_altsetting->endpoint[0].desc; +- +- /* check if the device has the iso in endpoint at the correct place */ +- if (usb_endpoint_xfer_isoc(endpoint) +- && +- (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { +- /* It's a newer em2874/em2875 device */ +- isoc_pipe = 0; +- } else { +- int check_interface = 1; +- isoc_pipe = 1; +- endpoint = &interface->cur_altsetting->endpoint[1].desc; +- if (!usb_endpoint_xfer_isoc(endpoint)) +- check_interface = 0; +- +- if (usb_endpoint_dir_out(endpoint)) +- check_interface = 0; +- +- if (!check_interface) { +- if (has_audio) { +- is_audio_only = true; +- } else { +- em28xx_err(DRIVER_NAME " video device (%04x:%04x): " +- "interface %i, class %i found.\n", +- le16_to_cpu(udev->descriptor.idVendor), +- le16_to_cpu(udev->descriptor.idProduct), +- ifnum, +- interface->altsetting[0].desc.bInterfaceClass); +- em28xx_err(DRIVER_NAME " This is an anciliary " +- "interface not used by the driver\n"); +- +- retval = -ENODEV; +- goto err; +- } +- } ++ if (!(has_audio || has_video || has_dvb)) { ++ retval = -ENODEV; ++ goto err_free; + } + + switch (udev->speed) { +@@ -3221,6 +3231,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, + strlcat(descr, " ", sizeof(descr)); + strlcat(descr, udev->product, sizeof(descr)); + } ++ + if (*descr) + strlcat(descr, " ", sizeof(descr)); + +@@ -3237,6 +3248,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, + printk(KERN_INFO DRIVER_NAME + ": Audio Vendor Class interface %i found\n", + ifnum); ++ if (has_video) ++ printk(KERN_INFO DRIVER_NAME ++ ": Video interface %i found\n", ++ ifnum); ++ if (has_dvb) ++ printk(KERN_INFO DRIVER_NAME ++ ": DVB interface %i found\n", ++ ifnum); + + /* + * Make sure we have 480 Mbps of bandwidth, otherwise things like +@@ -3248,22 +3267,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, + printk(DRIVER_NAME ": Device must be connected to a high-speed" + " USB 2.0 port.\n"); + retval = -ENODEV; +- goto err; +- } +- +- /* allocate memory for our device state and initialize it */ +- dev = kzalloc(sizeof(*dev), GFP_KERNEL); +- if (dev == NULL) { +- em28xx_err(DRIVER_NAME ": out of memory!\n"); +- retval = -ENOMEM; +- goto err; ++ goto err_free; + } + + snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); + dev->devno = nr; + dev->model = id->driver_info; + dev->alt = -1; +- dev->is_audio_only = is_audio_only; ++ dev->is_audio_only = has_audio && !(has_video || has_dvb); + dev->has_alsa_audio = has_audio; + dev->audio_ifnum = ifnum; + +@@ -3276,26 +3287,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, + } + } + +- /* compute alternate max packet sizes */ + dev->num_alt = interface->num_altsetting; +- 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"); +- kfree(dev); +- retval = -ENOMEM; +- goto err; +- } +- +- for (i = 0; i < dev->num_alt ; i++) { +- u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); +- unsigned int size = tmp & 0x7ff; +- +- if (udev->speed == USB_SPEED_HIGH) +- size = size * hb_mult(tmp); +- +- dev->alt_max_pkt_size[i] = size; +- } + + if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) + dev->model = card[nr]; +@@ -3308,10 +3300,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, + mutex_lock(&dev->lock); + retval = em28xx_init_dev(&dev, udev, interface, nr); + if (retval) { +- mutex_unlock(&dev->lock); +- kfree(dev->alt_max_pkt_size); +- kfree(dev); +- goto err; ++ goto unlock_and_free; + } + + request_modules(dev); +@@ -3330,6 +3319,13 @@ static int em28xx_usb_probe(struct usb_interface *interface, + + return 0; + ++unlock_and_free: ++ mutex_unlock(&dev->lock); ++ ++err_free: ++ kfree(dev->alt_max_pkt_size); ++ kfree(dev); ++ + err: + clear_bit(nr, &em28xx_devused); + +diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c +index 2982a06..0aacc96 100644 +--- a/drivers/media/video/em28xx/em28xx-core.c ++++ b/drivers/media/video/em28xx/em28xx-core.c +@@ -1070,7 +1070,8 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, + should also be using 'desc.bInterval' + */ + pipe = usb_rcvisocpipe(dev->udev, +- dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84); ++ dev->mode == EM28XX_ANALOG_MODE ? ++ EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); + + usb_fill_int_urb(urb, dev->udev, pipe, + dev->isoc_ctl.transfer_buffer[i], sb_size, +@@ -1108,62 +1109,6 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, + } + EXPORT_SYMBOL_GPL(em28xx_init_isoc); + +-/* Determine the packet size for the DVB stream for the given device +- (underlying value programmed into the eeprom) */ +-int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev) +-{ +- unsigned int chip_cfg2; +- unsigned int packet_size; +- +- switch (dev->chip_id) { +- case CHIP_ID_EM2710: +- case CHIP_ID_EM2750: +- case CHIP_ID_EM2800: +- case CHIP_ID_EM2820: +- case CHIP_ID_EM2840: +- case CHIP_ID_EM2860: +- /* No DVB support */ +- return -EINVAL; +- case CHIP_ID_EM2870: +- case CHIP_ID_EM2883: +- /* TS max packet size stored in bits 1-0 of R01 */ +- chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); +- switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) { +- case EM28XX_CHIPCFG2_TS_PACKETSIZE_188: +- packet_size = 188; +- break; +- case EM28XX_CHIPCFG2_TS_PACKETSIZE_376: +- packet_size = 376; +- break; +- case EM28XX_CHIPCFG2_TS_PACKETSIZE_564: +- packet_size = 564; +- break; +- case EM28XX_CHIPCFG2_TS_PACKETSIZE_752: +- packet_size = 752; +- break; +- } +- break; +- case CHIP_ID_EM2874: +- /* +- * FIXME: for now assumes 564 like it was before, but the +- * em2874 code should be added to return the proper value +- */ +- packet_size = 564; +- break; +- case CHIP_ID_EM2884: +- case CHIP_ID_EM28174: +- default: +- /* +- * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T +- * but not enough for 44 Mbit DVB-C. +- */ +- packet_size = 752; +- } +- +- return packet_size; +-} +-EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize); +- + /* + * em28xx_wake_i2c() + * configure i2c attached devices +diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c +index ac55de9..9449423 100644 +--- a/drivers/media/video/em28xx/em28xx-dvb.c ++++ b/drivers/media/video/em28xx/em28xx-dvb.c +@@ -164,12 +164,12 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) + struct em28xx *dev = dvb->adapter.priv; + int max_dvb_packet_size; + +- usb_set_interface(dev->udev, 0, 1); ++ usb_set_interface(dev->udev, 0, dev->dvb_alt); + rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); + if (rc < 0) + return rc; + +- max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); ++ max_dvb_packet_size = dev->dvb_max_pkt_size; + if (max_dvb_packet_size < 0) + return max_dvb_packet_size; + dprintk(1, "Using %d buffers each with %d bytes\n", +diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h +index 66f7923..2f62685 100644 +--- a/drivers/media/video/em28xx/em28xx-reg.h ++++ b/drivers/media/video/em28xx/em28xx-reg.h +@@ -12,6 +12,11 @@ + #define EM_GPO_2 (1 << 2) + #define EM_GPO_3 (1 << 3) + ++/* em28xx endpoints */ ++#define EM28XX_EP_ANALOG 0x82 ++#define EM28XX_EP_AUDIO 0x83 ++#define EM28XX_EP_DIGITAL 0x84 ++ + /* em2800 registers */ + #define EM2800_R08_AUDIOSRC 0x08 + +diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h +index 2dbb12c..7c3ebe2 100644 +--- a/drivers/media/video/em28xx/em28xx.h ++++ b/drivers/media/video/em28xx/em28xx.h +@@ -598,6 +598,8 @@ struct em28xx { + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ ++ int dvb_alt; /* alternate for DVB */ ++ unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ + struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ + char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc + transfer */ +-- +1.7.6.5 + +