diff options
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 256 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 1 |
2 files changed, 181 insertions, 76 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 94a14a2bb6d6..e4e82ae716bf 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/bitmap.h> | ||
31 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
32 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
33 | #include <linux/version.h> | 34 | #include <linux/version.h> |
@@ -59,8 +60,14 @@ MODULE_LICENSE("GPL"); | |||
59 | static LIST_HEAD(em28xx_devlist); | 60 | static LIST_HEAD(em28xx_devlist); |
60 | 61 | ||
61 | static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | 62 | static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; |
63 | static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | ||
64 | static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | ||
62 | module_param_array(card, int, NULL, 0444); | 65 | module_param_array(card, int, NULL, 0444); |
66 | module_param_array(video_nr, int, NULL, 0444); | ||
67 | module_param_array(vbi_nr, int, NULL, 0444); | ||
63 | MODULE_PARM_DESC(card,"card type"); | 68 | MODULE_PARM_DESC(card,"card type"); |
69 | MODULE_PARM_DESC(video_nr,"video device numbers"); | ||
70 | MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); | ||
64 | 71 | ||
65 | static int tuner = -1; | 72 | static int tuner = -1; |
66 | module_param(tuner, int, 0444); | 73 | module_param(tuner, int, 0444); |
@@ -70,6 +77,9 @@ static unsigned int video_debug = 0; | |||
70 | module_param(video_debug,int,0644); | 77 | module_param(video_debug,int,0644); |
71 | MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); | 78 | MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); |
72 | 79 | ||
80 | /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ | ||
81 | static unsigned long em28xx_devused; | ||
82 | |||
73 | /* supported tv norms */ | 83 | /* supported tv norms */ |
74 | static struct em28xx_tvnorm tvnorms[] = { | 84 | static struct em28xx_tvnorm tvnorms[] = { |
75 | { | 85 | { |
@@ -211,6 +221,11 @@ static int em28xx_config(struct em28xx *dev) | |||
211 | em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); | 221 | em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); |
212 | 222 | ||
213 | /* enable vbi capturing */ | 223 | /* enable vbi capturing */ |
224 | |||
225 | em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); | ||
226 | em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); | ||
227 | em28xx_write_regs_req(dev,0x00,0x11,"\x51",1); | ||
228 | |||
214 | em28xx_audio_usb_mute(dev, 1); | 229 | em28xx_audio_usb_mute(dev, 1); |
215 | dev->mute = 1; /* maybe not the right place... */ | 230 | dev->mute = 1; /* maybe not the right place... */ |
216 | dev->volume = 0x1f; | 231 | dev->volume = 0x1f; |
@@ -323,13 +338,20 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
323 | h = list_entry(list, struct em28xx, devlist); | 338 | h = list_entry(list, struct em28xx, devlist); |
324 | if (h->vdev->minor == minor) { | 339 | if (h->vdev->minor == minor) { |
325 | dev = h; | 340 | dev = h; |
341 | dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
342 | } | ||
343 | if (h->vbi_dev->minor == minor) { | ||
344 | dev = h; | ||
345 | dev->type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
326 | } | 346 | } |
327 | } | 347 | } |
348 | if (NULL == dev) | ||
349 | return -ENODEV; | ||
328 | 350 | ||
329 | filp->private_data=dev; | 351 | filp->private_data=dev; |
330 | 352 | ||
331 | 353 | em28xx_videodbg("open minor=%d type=%s users=%d\n", | |
332 | em28xx_videodbg("users=%d\n", dev->users); | 354 | minor,v4l2_type_names[dev->type],dev->users); |
333 | 355 | ||
334 | if (!down_read_trylock(&em28xx_disconnect)) | 356 | if (!down_read_trylock(&em28xx_disconnect)) |
335 | return -ERESTARTSYS; | 357 | return -ERESTARTSYS; |
@@ -340,13 +362,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
340 | return -EBUSY; | 362 | return -EBUSY; |
341 | } | 363 | } |
342 | 364 | ||
343 | /* if(dev->vbi_dev->minor == minor){ | ||
344 | dev->type=V4L2_BUF_TYPE_VBI_CAPTURE; | ||
345 | }*/ | ||
346 | if (dev->vdev->minor == minor) { | ||
347 | dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
348 | } | ||
349 | |||
350 | init_MUTEX(&dev->fileop_lock); /* to 1 == available */ | 365 | init_MUTEX(&dev->fileop_lock); /* to 1 == available */ |
351 | spin_lock_init(&dev->queue_lock); | 366 | spin_lock_init(&dev->queue_lock); |
352 | init_waitqueue_head(&dev->wait_frame); | 367 | init_waitqueue_head(&dev->wait_frame); |
@@ -354,23 +369,27 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
354 | 369 | ||
355 | down(&dev->lock); | 370 | down(&dev->lock); |
356 | 371 | ||
357 | em28xx_set_alternate(dev); | 372 | if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
373 | em28xx_set_alternate(dev); | ||
358 | 374 | ||
359 | dev->width = norm_maxw(dev); | 375 | dev->width = norm_maxw(dev); |
360 | dev->height = norm_maxh(dev); | 376 | dev->height = norm_maxh(dev); |
361 | dev->frame_size = dev->width * dev->height * 2; | 377 | dev->frame_size = dev->width * dev->height * 2; |
362 | dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ | 378 | dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ |
363 | dev->bytesperline = dev->width * 2; | 379 | dev->bytesperline = dev->width * 2; |
364 | dev->hscale = 0; | 380 | dev->hscale = 0; |
365 | dev->vscale = 0; | 381 | dev->vscale = 0; |
366 | 382 | ||
367 | em28xx_capture_start(dev, 1); | 383 | em28xx_capture_start(dev, 1); |
368 | em28xx_resolution_set(dev); | 384 | em28xx_resolution_set(dev); |
369 | 385 | ||
370 | /* start the transfer */ | 386 | /* start the transfer */ |
371 | errCode = em28xx_init_isoc(dev); | 387 | errCode = em28xx_init_isoc(dev); |
372 | if (errCode) | 388 | if (errCode) |
373 | goto err; | 389 | goto err; |
390 | |||
391 | video_mux(dev, 0); | ||
392 | } | ||
374 | 393 | ||
375 | dev->users++; | 394 | dev->users++; |
376 | filp->private_data = dev; | 395 | filp->private_data = dev; |
@@ -383,8 +402,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
383 | 402 | ||
384 | dev->state |= DEV_INITIALIZED; | 403 | dev->state |= DEV_INITIALIZED; |
385 | 404 | ||
386 | video_mux(dev, 0); | ||
387 | |||
388 | err: | 405 | err: |
389 | up(&dev->lock); | 406 | up(&dev->lock); |
390 | up_read(&em28xx_disconnect); | 407 | up_read(&em28xx_disconnect); |
@@ -400,14 +417,21 @@ static void em28xx_release_resources(struct em28xx *dev) | |||
400 | { | 417 | { |
401 | mutex_lock(&em28xx_sysfs_lock); | 418 | mutex_lock(&em28xx_sysfs_lock); |
402 | 419 | ||
403 | em28xx_info("V4L2 device /dev/video%d deregistered\n", | 420 | /*FIXME: I2C IR should be disconnected */ |
404 | dev->vdev->minor); | 421 | |
422 | em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", | ||
423 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, | ||
424 | dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); | ||
405 | list_del(&dev->devlist); | 425 | list_del(&dev->devlist); |
406 | video_unregister_device(dev->vdev); | 426 | video_unregister_device(dev->vdev); |
407 | /* video_unregister_device(dev->vbi_dev); */ | 427 | video_unregister_device(dev->vbi_dev); |
408 | em28xx_i2c_unregister(dev); | 428 | em28xx_i2c_unregister(dev); |
409 | usb_put_dev(dev->udev); | 429 | usb_put_dev(dev->udev); |
410 | mutex_unlock(&em28xx_sysfs_lock); | 430 | mutex_unlock(&em28xx_sysfs_lock); |
431 | |||
432 | |||
433 | /* Mark device as unused */ | ||
434 | em28xx_devused&=~(1<<dev->devno); | ||
411 | } | 435 | } |
412 | 436 | ||
413 | /* | 437 | /* |
@@ -463,6 +487,28 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, | |||
463 | int ret = 0; | 487 | int ret = 0; |
464 | struct em28xx *dev = filp->private_data; | 488 | struct em28xx *dev = filp->private_data; |
465 | 489 | ||
490 | if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
491 | em28xx_videodbg("V4l2_Buf_type_videocapture is set\n"); | ||
492 | } | ||
493 | if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
494 | em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); | ||
495 | em28xx_videodbg("not supported yet! ...\n"); | ||
496 | if (copy_to_user(buf, "", 1)) { | ||
497 | up(&dev->fileop_lock); | ||
498 | return -EFAULT; | ||
499 | } | ||
500 | return (1); | ||
501 | } | ||
502 | if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
503 | em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n"); | ||
504 | em28xx_videodbg("not supported yet! ...\n"); | ||
505 | if (copy_to_user(buf, "", 1)) { | ||
506 | up(&dev->fileop_lock); | ||
507 | return -EFAULT; | ||
508 | } | ||
509 | return (1); | ||
510 | } | ||
511 | |||
466 | if (down_interruptible(&dev->fileop_lock)) | 512 | if (down_interruptible(&dev->fileop_lock)) |
467 | return -ERESTARTSYS; | 513 | return -ERESTARTSYS; |
468 | 514 | ||
@@ -799,7 +845,8 @@ static int em28xx_stream_interrupt(struct em28xx *dev) | |||
799 | else if (ret) { | 845 | else if (ret) { |
800 | dev->state |= DEV_MISCONFIGURED; | 846 | dev->state |= DEV_MISCONFIGURED; |
801 | em28xx_videodbg("device is misconfigured; close and " | 847 | em28xx_videodbg("device is misconfigured; close and " |
802 | "open /dev/video%d again\n", dev->vdev->minor); | 848 | "open /dev/video%d again\n", |
849 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); | ||
803 | return ret; | 850 | return ret; |
804 | } | 851 | } |
805 | 852 | ||
@@ -850,6 +897,36 @@ static int em28xx_set_norm(struct em28xx *dev, int width, int height) | |||
850 | return 0; | 897 | return 0; |
851 | } | 898 | } |
852 | 899 | ||
900 | |||
901 | static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) | ||
902 | { | ||
903 | em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", | ||
904 | (format->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE) ? | ||
905 | "V4L2_BUF_TYPE_VIDEO_CAPTURE" : | ||
906 | (format->type ==V4L2_BUF_TYPE_VBI_CAPTURE) ? | ||
907 | "V4L2_BUF_TYPE_VBI_CAPTURE" : | ||
908 | (format->type ==V4L2_CAP_SLICED_VBI_CAPTURE) ? | ||
909 | "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE " : | ||
910 | "not supported"); | ||
911 | |||
912 | if (format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
913 | format->fmt.pix.width = dev->width; | ||
914 | format->fmt.pix.height = dev->height; | ||
915 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
916 | format->fmt.pix.bytesperline = dev->bytesperline; | ||
917 | format->fmt.pix.sizeimage = dev->frame_size; | ||
918 | format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
919 | format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ | ||
920 | |||
921 | em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, | ||
922 | dev->height); | ||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | return -EINVAL; | ||
927 | } | ||
928 | |||
929 | |||
853 | /* | 930 | /* |
854 | * em28xx_v4l2_do_ioctl() | 931 | * em28xx_v4l2_do_ioctl() |
855 | * This function is _not_ called directly, but from | 932 | * This function is _not_ called directly, but from |
@@ -1290,6 +1367,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, | |||
1290 | sizeof(cap->bus_info)); | 1367 | sizeof(cap->bus_info)); |
1291 | cap->version = EM28XX_VERSION_CODE; | 1368 | cap->version = EM28XX_VERSION_CODE; |
1292 | cap->capabilities = | 1369 | cap->capabilities = |
1370 | V4L2_CAP_SLICED_VBI_CAPTURE | | ||
1293 | V4L2_CAP_VIDEO_CAPTURE | | 1371 | V4L2_CAP_VIDEO_CAPTURE | |
1294 | V4L2_CAP_AUDIO | | 1372 | V4L2_CAP_AUDIO | |
1295 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | 1373 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; |
@@ -1314,32 +1392,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, | |||
1314 | } | 1392 | } |
1315 | 1393 | ||
1316 | case VIDIOC_G_FMT: | 1394 | case VIDIOC_G_FMT: |
1317 | { | 1395 | return em28xx_get_fmt(dev, (struct v4l2_format *) arg); |
1318 | struct v4l2_format *format = arg; | ||
1319 | |||
1320 | em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", | ||
1321 | format->type == | ||
1322 | V4L2_BUF_TYPE_VIDEO_CAPTURE ? | ||
1323 | "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == | ||
1324 | V4L2_BUF_TYPE_VBI_CAPTURE ? | ||
1325 | "V4L2_BUF_TYPE_VBI_CAPTURE " : | ||
1326 | "not supported"); | ||
1327 | |||
1328 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1329 | return -EINVAL; | ||
1330 | |||
1331 | format->fmt.pix.width = dev->width; | ||
1332 | format->fmt.pix.height = dev->height; | ||
1333 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
1334 | format->fmt.pix.bytesperline = dev->bytesperline; | ||
1335 | format->fmt.pix.sizeimage = dev->frame_size; | ||
1336 | format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1337 | format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ | ||
1338 | |||
1339 | em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, | ||
1340 | dev->height); | ||
1341 | return 0; | ||
1342 | } | ||
1343 | 1396 | ||
1344 | case VIDIOC_TRY_FMT: | 1397 | case VIDIOC_TRY_FMT: |
1345 | case VIDIOC_S_FMT: | 1398 | case VIDIOC_S_FMT: |
@@ -1741,6 +1794,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1741 | if (errCode) { | 1794 | if (errCode) { |
1742 | em28xx_errdev("error configuring device\n"); | 1795 | em28xx_errdev("error configuring device\n"); |
1743 | kfree(dev); | 1796 | kfree(dev); |
1797 | em28xx_devused&=~(1<<dev->devno); | ||
1744 | return -ENOMEM; | 1798 | return -ENOMEM; |
1745 | } | 1799 | } |
1746 | 1800 | ||
@@ -1767,9 +1821,30 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1767 | if (NULL == dev->vdev) { | 1821 | if (NULL == dev->vdev) { |
1768 | em28xx_errdev("cannot allocate video_device.\n"); | 1822 | em28xx_errdev("cannot allocate video_device.\n"); |
1769 | kfree(dev); | 1823 | kfree(dev); |
1824 | em28xx_devused&=~(1<<dev->devno); | ||
1825 | return -ENOMEM; | ||
1826 | } | ||
1827 | |||
1828 | dev->vbi_dev = video_device_alloc(); | ||
1829 | if (NULL == dev->vbi_dev) { | ||
1830 | em28xx_errdev("cannot allocate video_device.\n"); | ||
1831 | kfree(dev->vdev); | ||
1832 | kfree(dev); | ||
1833 | em28xx_devused&=~(1<<dev->devno); | ||
1770 | return -ENOMEM; | 1834 | return -ENOMEM; |
1771 | } | 1835 | } |
1772 | 1836 | ||
1837 | /* Fills VBI device info */ | ||
1838 | dev->vbi_dev->type = VFL_TYPE_VBI; | ||
1839 | dev->vbi_dev->hardware = 0; | ||
1840 | dev->vbi_dev->fops = &em28xx_v4l_fops; | ||
1841 | dev->vbi_dev->minor = -1; | ||
1842 | dev->vbi_dev->dev = &dev->udev->dev; | ||
1843 | dev->vbi_dev->release = video_device_release; | ||
1844 | snprintf(dev->vbi_dev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", | ||
1845 | "em28xx",dev->devno,"vbi"); | ||
1846 | |||
1847 | /* Fills CAPTURE device info */ | ||
1773 | dev->vdev->type = VID_TYPE_CAPTURE; | 1848 | dev->vdev->type = VID_TYPE_CAPTURE; |
1774 | if (dev->has_tuner) | 1849 | if (dev->has_tuner) |
1775 | dev->vdev->type |= VID_TYPE_TUNER; | 1850 | dev->vdev->type |= VID_TYPE_TUNER; |
@@ -1778,21 +1853,39 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1778 | dev->vdev->minor = -1; | 1853 | dev->vdev->minor = -1; |
1779 | dev->vdev->dev = &dev->udev->dev; | 1854 | dev->vdev->dev = &dev->udev->dev; |
1780 | dev->vdev->release = video_device_release; | 1855 | dev->vdev->release = video_device_release; |
1781 | snprintf(dev->vdev->name, sizeof(dev->vdev->name), "%s", | 1856 | snprintf(dev->vdev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", |
1782 | "em28xx video"); | 1857 | "em28xx",dev->devno,"video"); |
1858 | |||
1783 | list_add_tail(&dev->devlist,&em28xx_devlist); | 1859 | list_add_tail(&dev->devlist,&em28xx_devlist); |
1784 | 1860 | ||
1785 | /* register v4l2 device */ | 1861 | /* register v4l2 device */ |
1786 | down(&dev->lock); | 1862 | down(&dev->lock); |
1787 | if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1))) { | 1863 | if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, |
1864 | video_nr[dev->devno]))) { | ||
1788 | em28xx_errdev("unable to register video device (error=%i).\n", | 1865 | em28xx_errdev("unable to register video device (error=%i).\n", |
1789 | retval); | 1866 | retval); |
1790 | up(&dev->lock); | 1867 | up(&dev->lock); |
1791 | list_del(&dev->devlist); | 1868 | list_del(&dev->devlist); |
1792 | video_device_release(dev->vdev); | 1869 | video_device_release(dev->vdev); |
1793 | kfree(dev); | 1870 | kfree(dev); |
1871 | em28xx_devused&=~(1<<dev->devno); | ||
1794 | return -ENODEV; | 1872 | return -ENODEV; |
1795 | } | 1873 | } |
1874 | |||
1875 | if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, | ||
1876 | vbi_nr[dev->devno]) < 0) { | ||
1877 | printk("unable to register vbi device\n"); | ||
1878 | up(&dev->lock); | ||
1879 | list_del(&dev->devlist); | ||
1880 | video_device_release(dev->vbi_dev); | ||
1881 | video_device_release(dev->vdev); | ||
1882 | kfree(dev); | ||
1883 | em28xx_devused&=~(1<<dev->devno); | ||
1884 | return -ENODEV; | ||
1885 | } else { | ||
1886 | printk("registered VBI\n"); | ||
1887 | } | ||
1888 | |||
1796 | if (dev->has_msp34xx) { | 1889 | if (dev->has_msp34xx) { |
1797 | /* Send a reset to other chips via gpio */ | 1890 | /* Send a reset to other chips via gpio */ |
1798 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); | 1891 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); |
@@ -1805,8 +1898,9 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1805 | 1898 | ||
1806 | up(&dev->lock); | 1899 | up(&dev->lock); |
1807 | 1900 | ||
1808 | em28xx_info("V4L2 device registered as /dev/video%d\n", | 1901 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", |
1809 | dev->vdev->minor); | 1902 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, |
1903 | dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); | ||
1810 | 1904 | ||
1811 | return 0; | 1905 | return 0; |
1812 | } | 1906 | } |
@@ -1828,6 +1922,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1828 | udev = usb_get_dev(interface_to_usbdev(interface)); | 1922 | udev = usb_get_dev(interface_to_usbdev(interface)); |
1829 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | 1923 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; |
1830 | 1924 | ||
1925 | /* Check to see next free device and mark as used */ | ||
1926 | nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS); | ||
1927 | em28xx_devused|=1<<nr; | ||
1831 | 1928 | ||
1832 | /* Don't register audio interfaces */ | 1929 | /* Don't register audio interfaces */ |
1833 | if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { | 1930 | if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { |
@@ -1835,6 +1932,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1835 | udev->descriptor.idVendor,udev->descriptor.idProduct, | 1932 | udev->descriptor.idVendor,udev->descriptor.idProduct, |
1836 | ifnum, | 1933 | ifnum, |
1837 | interface->altsetting[0].desc.bInterfaceClass); | 1934 | interface->altsetting[0].desc.bInterfaceClass); |
1935 | |||
1936 | em28xx_devused&=~(1<<nr); | ||
1838 | return -ENODEV; | 1937 | return -ENODEV; |
1839 | } | 1938 | } |
1840 | 1939 | ||
@@ -1849,18 +1948,20 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1849 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != | 1948 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != |
1850 | USB_ENDPOINT_XFER_ISOC) { | 1949 | USB_ENDPOINT_XFER_ISOC) { |
1851 | em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); | 1950 | em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); |
1951 | em28xx_devused&=~(1<<nr); | ||
1852 | return -ENODEV; | 1952 | return -ENODEV; |
1853 | } | 1953 | } |
1854 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { | 1954 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { |
1855 | em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); | 1955 | em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); |
1956 | em28xx_devused&=~(1<<nr); | ||
1856 | return -ENODEV; | 1957 | return -ENODEV; |
1857 | } | 1958 | } |
1858 | 1959 | ||
1859 | model=id->driver_info; | 1960 | model=id->driver_info; |
1860 | nr=interface->minor; | ||
1861 | 1961 | ||
1862 | if (nr>EM28XX_MAXBOARDS) { | 1962 | if (nr > EM28XX_MAXBOARDS) { |
1863 | printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); | 1963 | printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); |
1964 | em28xx_devused&=~(1<<nr); | ||
1864 | return -ENOMEM; | 1965 | return -ENOMEM; |
1865 | } | 1966 | } |
1866 | 1967 | ||
@@ -1868,19 +1969,24 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1868 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 1969 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1869 | if (dev == NULL) { | 1970 | if (dev == NULL) { |
1870 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | 1971 | em28xx_err(DRIVER_NAME ": out of memory!\n"); |
1972 | em28xx_devused&=~(1<<nr); | ||
1871 | return -ENOMEM; | 1973 | return -ENOMEM; |
1872 | } | 1974 | } |
1873 | 1975 | ||
1976 | snprintf(dev->name, 29, "em28xx #%d", nr); | ||
1977 | dev->devno=nr; | ||
1978 | |||
1874 | /* compute alternate max packet sizes */ | 1979 | /* compute alternate max packet sizes */ |
1875 | uif = udev->actconfig->interface[0]; | 1980 | uif = udev->actconfig->interface[0]; |
1876 | 1981 | ||
1877 | dev->num_alt=uif->num_altsetting; | 1982 | dev->num_alt=uif->num_altsetting; |
1878 | printk(DRIVER_NAME ": Alternate settings: %i\n",dev->num_alt); | 1983 | em28xx_info("Alternate settings: %i\n",dev->num_alt); |
1879 | // dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* | 1984 | // dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* |
1880 | dev->alt_max_pkt_size = kmalloc(32* | 1985 | dev->alt_max_pkt_size = kmalloc(32* |
1881 | dev->num_alt,GFP_KERNEL); | 1986 | dev->num_alt,GFP_KERNEL); |
1882 | if (dev->alt_max_pkt_size == NULL) { | 1987 | if (dev->alt_max_pkt_size == NULL) { |
1883 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | 1988 | em28xx_errdev("out of memory!\n"); |
1989 | em28xx_devused&=~(1<<nr); | ||
1884 | return -ENOMEM; | 1990 | return -ENOMEM; |
1885 | } | 1991 | } |
1886 | 1992 | ||
@@ -1889,27 +1995,26 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1889 | wMaxPacketSize); | 1995 | wMaxPacketSize); |
1890 | dev->alt_max_pkt_size[i] = | 1996 | dev->alt_max_pkt_size[i] = |
1891 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | 1997 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); |
1892 | printk(DRIVER_NAME ": Alternate setting %i, max size= %i\n",i, | 1998 | em28xx_info("Alternate setting %i, max size= %i\n",i, |
1893 | dev->alt_max_pkt_size[i]); | 1999 | dev->alt_max_pkt_size[i]); |
1894 | } | 2000 | } |
1895 | 2001 | ||
1896 | snprintf(dev->name, 29, "em28xx #%d", nr); | ||
1897 | |||
1898 | if ((card[nr]>=0)&&(card[nr]<em28xx_bcount)) | 2002 | if ((card[nr]>=0)&&(card[nr]<em28xx_bcount)) |
1899 | model=card[nr]; | 2003 | model=card[nr]; |
1900 | 2004 | ||
1901 | if ((model==EM2800_BOARD_UNKNOWN)||(model==EM2820_BOARD_UNKNOWN)) { | 2005 | if ((model==EM2800_BOARD_UNKNOWN)||(model==EM2820_BOARD_UNKNOWN)) { |
1902 | printk( "%s: Your board has no eeprom inside it and thus can't\n" | 2006 | em28xx_errdev( "Your board has no eeprom inside it and thus can't\n" |
1903 | "%s: be autodetected. Please pass card=<n> insmod option to\n" | 2007 | "%s: be autodetected. Please pass card=<n> insmod option to\n" |
1904 | "%s: workaround that. Redirect complaints to the vendor of\n" | 2008 | "%s: workaround that. Redirect complaints to the vendor of\n" |
1905 | "%s: the TV card. Best regards,\n" | 2009 | "%s: the TV card. Generic type will be used." |
2010 | "%s: Best regards,\n" | ||
1906 | "%s: -- tux\n", | 2011 | "%s: -- tux\n", |
1907 | dev->name,dev->name,dev->name,dev->name,dev->name); | 2012 | dev->name,dev->name,dev->name,dev->name,dev->name); |
1908 | printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n", | 2013 | em28xx_errdev("%s: Here is a list of valid choices for the card=<n> insmod option:\n", |
1909 | dev->name); | 2014 | dev->name); |
1910 | for (i = 0; i < em28xx_bcount; i++) { | 2015 | for (i = 0; i < em28xx_bcount; i++) { |
1911 | printk("%s: card=%d -> %s\n", | 2016 | em28xx_errdev(" card=%d -> %s\n", i, |
1912 | dev->name, i, em28xx_boards[i].name); | 2017 | em28xx_boards[i].name); |
1913 | } | 2018 | } |
1914 | } | 2019 | } |
1915 | 2020 | ||
@@ -1935,12 +2040,9 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
1935 | struct em28xx *dev = usb_get_intfdata(interface); | 2040 | struct em28xx *dev = usb_get_intfdata(interface); |
1936 | usb_set_intfdata(interface, NULL); | 2041 | usb_set_intfdata(interface, NULL); |
1937 | 2042 | ||
1938 | /*FIXME: IR should be disconnected */ | ||
1939 | |||
1940 | if (!dev) | 2043 | if (!dev) |
1941 | return; | 2044 | return; |
1942 | 2045 | ||
1943 | |||
1944 | down_write(&em28xx_disconnect); | 2046 | down_write(&em28xx_disconnect); |
1945 | 2047 | ||
1946 | down(&dev->lock); | 2048 | down(&dev->lock); |
@@ -1952,7 +2054,9 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
1952 | if (dev->users) { | 2054 | if (dev->users) { |
1953 | em28xx_warn | 2055 | em28xx_warn |
1954 | ("device /dev/video%d is open! Deregistration and memory " | 2056 | ("device /dev/video%d is open! Deregistration and memory " |
1955 | "deallocation are deferred on close.\n", dev->vdev->minor); | 2057 | "deallocation are deferred on close.\n", |
2058 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); | ||
2059 | |||
1956 | dev->state |= DEV_MISCONFIGURED; | 2060 | dev->state |= DEV_MISCONFIGURED; |
1957 | em28xx_uninit_isoc(dev); | 2061 | em28xx_uninit_isoc(dev); |
1958 | dev->state |= DEV_DISCONNECTED; | 2062 | dev->state |= DEV_DISCONNECTED; |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 33de9d846af5..119fdbedc7bf 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -209,6 +209,7 @@ struct em28xx { | |||
209 | /* generic device properties */ | 209 | /* generic device properties */ |
210 | char name[30]; /* name (including minor) of the device */ | 210 | char name[30]; /* name (including minor) of the device */ |
211 | int model; /* index in the device_data struct */ | 211 | int model; /* index in the device_data struct */ |
212 | int devno; /* marks the number of this device */ | ||
212 | unsigned int is_em2800; | 213 | unsigned int is_em2800; |
213 | int video_inputs; /* number of video inputs */ | 214 | int video_inputs; /* number of video inputs */ |
214 | struct list_head devlist; | 215 | struct list_head devlist; |