diff options
author | Devin Heitmueller <dheitmueller@linuxtv.org> | 2009-03-11 02:01:00 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:26 -0400 |
commit | fc4ce6cd9855dcd1151a9afc067ea354179089f9 (patch) | |
tree | ab463988eb634e6bae258a57e55e9c72b22c7025 /drivers/media/video/au0828 | |
parent | d9109bef4b4f501eee94ae68bf876f765d5c6941 (diff) |
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>
Diffstat (limited to 'drivers/media/video/au0828')
-rw-r--r-- | drivers/media/video/au0828/au0828-core.c | 30 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-video.c | 33 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828.h | 3 |
3 files changed, 36 insertions, 30 deletions
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index f47fd9d78fa0..2b5ade626e57 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c | |||
@@ -165,11 +165,9 @@ static void au0828_usb_disconnect(struct usb_interface *interface) | |||
165 | static int au0828_usb_probe(struct usb_interface *interface, | 165 | static int au0828_usb_probe(struct usb_interface *interface, |
166 | const struct usb_device_id *id) | 166 | const struct usb_device_id *id) |
167 | { | 167 | { |
168 | int ifnum, i; | 168 | int ifnum; |
169 | struct au0828_dev *dev; | 169 | struct au0828_dev *dev; |
170 | struct usb_device *usbdev = interface_to_usbdev(interface); | 170 | struct usb_device *usbdev = interface_to_usbdev(interface); |
171 | struct usb_host_interface *iface_desc; | ||
172 | struct usb_endpoint_descriptor *endpoint; | ||
173 | 171 | ||
174 | ifnum = interface->altsetting->desc.bInterfaceNumber; | 172 | ifnum = interface->altsetting->desc.bInterfaceNumber; |
175 | 173 | ||
@@ -194,30 +192,6 @@ static int au0828_usb_probe(struct usb_interface *interface, | |||
194 | 192 | ||
195 | usb_set_intfdata(interface, dev); | 193 | usb_set_intfdata(interface, dev); |
196 | 194 | ||
197 | /* set au0828 usb interface0 to as5 */ | ||
198 | usb_set_interface(usbdev, | ||
199 | interface->cur_altsetting->desc.bInterfaceNumber, 5); | ||
200 | |||
201 | /* Figure out which endpoint has the isoc interface */ | ||
202 | iface_desc = interface->cur_altsetting; | ||
203 | for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ | ||
204 | endpoint = &iface_desc->endpoint[i].desc; | ||
205 | if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && | ||
206 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ | ||
207 | |||
208 | /* we find our isoc in endpoint */ | ||
209 | u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); | ||
210 | dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
211 | dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; | ||
212 | } | ||
213 | } | ||
214 | if(!(dev->isoc_in_endpointaddr)) { | ||
215 | printk("Could not locate isoc endpoint\n"); | ||
216 | kfree(dev); | ||
217 | return -ENODEV; | ||
218 | } | ||
219 | |||
220 | |||
221 | /* Power Up the bridge */ | 195 | /* Power Up the bridge */ |
222 | au0828_write(dev, REG_600, 1 << 4); | 196 | au0828_write(dev, REG_600, 1 << 4); |
223 | 197 | ||
@@ -232,7 +206,7 @@ static int au0828_usb_probe(struct usb_interface *interface, | |||
232 | 206 | ||
233 | /* Analog TV */ | 207 | /* Analog TV */ |
234 | if (dev->board.input != NULL) | 208 | if (dev->board.input != NULL) |
235 | au0828_analog_register(dev); | 209 | au0828_analog_register(dev, interface); |
236 | 210 | ||
237 | /* Digital TV */ | 211 | /* Digital TV */ |
238 | au0828_dvb_register(dev); | 212 | au0828_dvb_register(dev); |
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index ce80882d45e2..4c77aebfe6ee 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c | |||
@@ -1618,12 +1618,43 @@ static const struct video_device au0828_video_template = { | |||
1618 | 1618 | ||
1619 | /**************************************************************************/ | 1619 | /**************************************************************************/ |
1620 | 1620 | ||
1621 | int au0828_analog_register(struct au0828_dev *dev) | 1621 | int au0828_analog_register(struct au0828_dev *dev, |
1622 | struct usb_interface *interface) | ||
1622 | { | 1623 | { |
1623 | int retval = -ENOMEM; | 1624 | int retval = -ENOMEM; |
1625 | struct usb_host_interface *iface_desc; | ||
1626 | struct usb_endpoint_descriptor *endpoint; | ||
1627 | int i; | ||
1624 | 1628 | ||
1625 | dprintk(1, "au0828_analog_register called!\n"); | 1629 | dprintk(1, "au0828_analog_register called!\n"); |
1626 | 1630 | ||
1631 | /* set au0828 usb interface0 to as5 */ | ||
1632 | retval = usb_set_interface(dev->usbdev, | ||
1633 | interface->cur_altsetting->desc.bInterfaceNumber, 5); | ||
1634 | if (retval != 0) { | ||
1635 | printk("Failure setting usb interface0 to as5\n"); | ||
1636 | return retval; | ||
1637 | } | ||
1638 | |||
1639 | /* Figure out which endpoint has the isoc interface */ | ||
1640 | iface_desc = interface->cur_altsetting; | ||
1641 | for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ | ||
1642 | endpoint = &iface_desc->endpoint[i].desc; | ||
1643 | if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && | ||
1644 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ | ||
1645 | |||
1646 | /* we find our isoc in endpoint */ | ||
1647 | u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); | ||
1648 | dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
1649 | dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; | ||
1650 | } | ||
1651 | } | ||
1652 | if(!(dev->isoc_in_endpointaddr)) { | ||
1653 | printk("Could not locate isoc endpoint\n"); | ||
1654 | kfree(dev); | ||
1655 | return -ENODEV; | ||
1656 | } | ||
1657 | |||
1627 | init_waitqueue_head(&dev->open); | 1658 | init_waitqueue_head(&dev->open); |
1628 | spin_lock_init(&dev->slock); | 1659 | spin_lock_init(&dev->slock); |
1629 | mutex_init(&dev->lock); | 1660 | mutex_init(&dev->lock); |
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 2f48ec2136bf..d2e54c8e18c4 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h | |||
@@ -273,7 +273,8 @@ extern void au0828_call_i2c_clients(struct au0828_dev *dev, | |||
273 | 273 | ||
274 | /* ----------------------------------------------------------- */ | 274 | /* ----------------------------------------------------------- */ |
275 | /* au0828-video.c */ | 275 | /* au0828-video.c */ |
276 | int au0828_analog_register(struct au0828_dev *dev); | 276 | int au0828_analog_register(struct au0828_dev *dev, |
277 | struct usb_interface *interface); | ||
277 | int au0828_analog_stream_disable(struct au0828_dev *d); | 278 | int au0828_analog_stream_disable(struct au0828_dev *d); |
278 | void au0828_analog_unregister(struct au0828_dev *dev); | 279 | void au0828_analog_unregister(struct au0828_dev *dev); |
279 | 280 | ||