mirror of
https://github.com/torvalds/linux.git
synced 2024-12-14 15:13:52 +00:00
V4L/DVB (11077): au0828: properly handle missing analog USB endpoint
Move the setup of the analog isoc handler into au0828-video.c, so it does not occur if there is not an .input section defined for the board. Also fixes a case where if there is an input section but the board does not actually have analog support, the digital support will continue to work as expected. Thanks to Michael Krufky <mkrufky@linuxtv.org> for providing sample hardware of various configurations to test with. Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
d9109bef4b
commit
fc4ce6cd98
@ -165,11 +165,9 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
|
||||
static int au0828_usb_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
int ifnum, i;
|
||||
int ifnum;
|
||||
struct au0828_dev *dev;
|
||||
struct usb_device *usbdev = interface_to_usbdev(interface);
|
||||
struct usb_host_interface *iface_desc;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
|
||||
ifnum = interface->altsetting->desc.bInterfaceNumber;
|
||||
|
||||
@ -194,30 +192,6 @@ static int au0828_usb_probe(struct usb_interface *interface,
|
||||
|
||||
usb_set_intfdata(interface, dev);
|
||||
|
||||
/* set au0828 usb interface0 to as5 */
|
||||
usb_set_interface(usbdev,
|
||||
interface->cur_altsetting->desc.bInterfaceNumber, 5);
|
||||
|
||||
/* Figure out which endpoint has the isoc interface */
|
||||
iface_desc = interface->cur_altsetting;
|
||||
for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
|
||||
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){
|
||||
|
||||
/* we find our isoc in endpoint */
|
||||
u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
|
||||
dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
|
||||
}
|
||||
}
|
||||
if(!(dev->isoc_in_endpointaddr)) {
|
||||
printk("Could not locate isoc endpoint\n");
|
||||
kfree(dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
/* Power Up the bridge */
|
||||
au0828_write(dev, REG_600, 1 << 4);
|
||||
|
||||
@ -232,7 +206,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
|
||||
|
||||
/* Analog TV */
|
||||
if (dev->board.input != NULL)
|
||||
au0828_analog_register(dev);
|
||||
au0828_analog_register(dev, interface);
|
||||
|
||||
/* Digital TV */
|
||||
au0828_dvb_register(dev);
|
||||
|
@ -1618,12 +1618,43 @@ static const struct video_device au0828_video_template = {
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
int au0828_analog_register(struct au0828_dev *dev)
|
||||
int au0828_analog_register(struct au0828_dev *dev,
|
||||
struct usb_interface *interface)
|
||||
{
|
||||
int retval = -ENOMEM;
|
||||
struct usb_host_interface *iface_desc;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
int i;
|
||||
|
||||
dprintk(1, "au0828_analog_register called!\n");
|
||||
|
||||
/* set au0828 usb interface0 to as5 */
|
||||
retval = usb_set_interface(dev->usbdev,
|
||||
interface->cur_altsetting->desc.bInterfaceNumber, 5);
|
||||
if (retval != 0) {
|
||||
printk("Failure setting usb interface0 to as5\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Figure out which endpoint has the isoc interface */
|
||||
iface_desc = interface->cur_altsetting;
|
||||
for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
|
||||
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){
|
||||
|
||||
/* we find our isoc in endpoint */
|
||||
u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
|
||||
dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
|
||||
}
|
||||
}
|
||||
if(!(dev->isoc_in_endpointaddr)) {
|
||||
printk("Could not locate isoc endpoint\n");
|
||||
kfree(dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&dev->open);
|
||||
spin_lock_init(&dev->slock);
|
||||
mutex_init(&dev->lock);
|
||||
|
@ -273,7 +273,8 @@ extern void au0828_call_i2c_clients(struct au0828_dev *dev,
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* au0828-video.c */
|
||||
int au0828_analog_register(struct au0828_dev *dev);
|
||||
int au0828_analog_register(struct au0828_dev *dev,
|
||||
struct usb_interface *interface);
|
||||
int au0828_analog_stream_disable(struct au0828_dev *d);
|
||||
void au0828_analog_unregister(struct au0828_dev *dev);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user