diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-06 21:08:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-06 21:11:41 -0400 |
commit | 4ef4327b30957a16619ac7d47c749465e62de8c3 (patch) | |
tree | 5c80e853f0d9eadd01b2019d03d2432334393c5e /drivers/media/video/em28xx/em28xx-cards.c | |
parent | 3989203290fba6fdf6bc4825fbf6526e1bf17977 (diff) | |
parent | a938b8c5be8fe5c28800c9cef4aa43d569aa57a8 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (120 commits)
cx231xx: Convert to snd_card_create()
V4L/DVB (11440): PWC: fix build error when CONFIG_INPUT=m
V4L/DVB (11439): UVC: uvc_status_cleanup(): undefined reference to `input_unregister_device'
V4L/DVB (11438): au0828: fix Kconfig dependance
V4L/DVB (11437): pvrusb2: Drop client_register/unregister stubs
V4L/DVB (11436): radio-mr800: convert to to v4l2_device
V4L/DVB (11435): dsbr100 radio: convert to to v4l2_device
V4L/DVB: zr364xx: remove unused #include <version.h>
V4L/DVB: usbvision: remove unused #include <version.h>
V4L/DVB (11427): gspca - m5602: Minor cleanups
V4L/DVB (11426): gspca - m5602: Don't touch hflip/vflip register on Read/Modify/Write
V4L/DVB (11425): gspca - m5602: Move the vflip quirk to probe stage.
V4L/DVB (11424): gspca - m5602-ov9650: Use the local ctrl cache. Adjust image on vflip.
V4L/DVB (11423): gspca - m5602-ov9650: Add a disconnect hook, setup a ctrl cache ctrl.
V4L/DVB (11422): gspca - m5602-ov9650: Replace a magic constant with a define
V4L/DVB (11421): gspca - m5602-ov9650: Synthesize modesetting.
V4L/DVB (11420): gspca - m5602: Improve error handling in the ov9650 driver
V4L/DVB (11419): gspca - m5602-ov9650: Don't read exposure data from COM1.
V4L/DVB (11418): gspca - m5602-ov9650: Auto white balancing is on by default
V4L/DVB (11417): gspca - m5602-ov9650: Autogain is on by default
...
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-cards.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 150 |
1 files changed, 123 insertions, 27 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 0f48c0ff5ac3..7c70738479dd 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <media/msp3400.h> | 31 | #include <media/msp3400.h> |
32 | #include <media/saa7115.h> | 32 | #include <media/saa7115.h> |
33 | #include <media/tvp5150.h> | 33 | #include <media/tvp5150.h> |
34 | #include <media/tvaudio.h> | ||
35 | #include <media/i2c-addr.h> | ||
34 | #include <media/tveeprom.h> | 36 | #include <media/tveeprom.h> |
35 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
36 | #include <media/v4l2-chip-ident.h> | 38 | #include <media/v4l2-chip-ident.h> |
@@ -1240,6 +1242,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1240 | [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { | 1242 | [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { |
1241 | .name = "Compro VideoMate ForYou/Stereo", | 1243 | .name = "Compro VideoMate ForYou/Stereo", |
1242 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | 1244 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
1245 | .tvaudio_addr = 0xb0, | ||
1243 | .tda9887_conf = TDA9887_PRESENT, | 1246 | .tda9887_conf = TDA9887_PRESENT, |
1244 | .decoder = EM28XX_TVP5150, | 1247 | .decoder = EM28XX_TVP5150, |
1245 | .adecoder = EM28XX_TVAUDIO, | 1248 | .adecoder = EM28XX_TVAUDIO, |
@@ -1444,6 +1447,24 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { | |||
1444 | {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, | 1447 | {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, |
1445 | }; | 1448 | }; |
1446 | 1449 | ||
1450 | /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ | ||
1451 | static unsigned short saa711x_addrs[] = { | ||
1452 | 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ | ||
1453 | 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ | ||
1454 | I2C_CLIENT_END }; | ||
1455 | |||
1456 | static unsigned short tvp5150_addrs[] = { | ||
1457 | 0xb8 >> 1, | ||
1458 | 0xba >> 1, | ||
1459 | I2C_CLIENT_END | ||
1460 | }; | ||
1461 | |||
1462 | static unsigned short msp3400_addrs[] = { | ||
1463 | 0x80 >> 1, | ||
1464 | 0x88 >> 1, | ||
1465 | I2C_CLIENT_END | ||
1466 | }; | ||
1467 | |||
1447 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg) | 1468 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg) |
1448 | { | 1469 | { |
1449 | int rc = 0; | 1470 | int rc = 0; |
@@ -1672,31 +1693,55 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
1672 | } | 1693 | } |
1673 | } | 1694 | } |
1674 | 1695 | ||
1675 | static void em28xx_config_tuner(struct em28xx *dev) | 1696 | static void em28xx_tuner_setup(struct em28xx *dev) |
1676 | { | 1697 | { |
1677 | struct v4l2_priv_tun_config xc2028_cfg; | ||
1678 | struct tuner_setup tun_setup; | 1698 | struct tuner_setup tun_setup; |
1679 | struct v4l2_frequency f; | 1699 | struct v4l2_frequency f; |
1680 | 1700 | ||
1681 | if (dev->tuner_type == TUNER_ABSENT) | 1701 | if (dev->tuner_type == TUNER_ABSENT) |
1682 | return; | 1702 | return; |
1683 | 1703 | ||
1704 | memset(&tun_setup, 0, sizeof(tun_setup)); | ||
1705 | |||
1684 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | 1706 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; |
1685 | tun_setup.type = dev->tuner_type; | ||
1686 | tun_setup.addr = dev->tuner_addr; | ||
1687 | tun_setup.tuner_callback = em28xx_tuner_callback; | 1707 | tun_setup.tuner_callback = em28xx_tuner_callback; |
1688 | 1708 | ||
1689 | em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); | 1709 | if (dev->board.radio.type) { |
1710 | tun_setup.type = dev->board.radio.type; | ||
1711 | tun_setup.addr = dev->board.radio_addr; | ||
1712 | |||
1713 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); | ||
1714 | } | ||
1715 | |||
1716 | if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) { | ||
1717 | tun_setup.type = dev->tuner_type; | ||
1718 | tun_setup.addr = dev->tuner_addr; | ||
1719 | |||
1720 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); | ||
1721 | } | ||
1722 | |||
1723 | if (dev->tda9887_conf) { | ||
1724 | struct v4l2_priv_tun_config tda9887_cfg; | ||
1725 | |||
1726 | tda9887_cfg.tuner = TUNER_TDA9887; | ||
1727 | tda9887_cfg.priv = &dev->tda9887_conf; | ||
1728 | |||
1729 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg); | ||
1730 | } | ||
1690 | 1731 | ||
1691 | if (dev->tuner_type == TUNER_XC2028) { | 1732 | if (dev->tuner_type == TUNER_XC2028) { |
1733 | struct v4l2_priv_tun_config xc2028_cfg; | ||
1692 | struct xc2028_ctrl ctl; | 1734 | struct xc2028_ctrl ctl; |
1693 | 1735 | ||
1736 | memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); | ||
1737 | memset(&ctl, 0, sizeof(ctl)); | ||
1738 | |||
1694 | em28xx_setup_xc3028(dev, &ctl); | 1739 | em28xx_setup_xc3028(dev, &ctl); |
1695 | 1740 | ||
1696 | xc2028_cfg.tuner = TUNER_XC2028; | 1741 | xc2028_cfg.tuner = TUNER_XC2028; |
1697 | xc2028_cfg.priv = &ctl; | 1742 | xc2028_cfg.priv = &ctl; |
1698 | 1743 | ||
1699 | em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); | 1744 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg); |
1700 | } | 1745 | } |
1701 | 1746 | ||
1702 | /* configure tuner */ | 1747 | /* configure tuner */ |
@@ -1704,7 +1749,7 @@ static void em28xx_config_tuner(struct em28xx *dev) | |||
1704 | f.type = V4L2_TUNER_ANALOG_TV; | 1749 | f.type = V4L2_TUNER_ANALOG_TV; |
1705 | f.frequency = 9076; /* just a magic number */ | 1750 | f.frequency = 9076; /* just a magic number */ |
1706 | dev->ctl_freq = f.frequency; | 1751 | dev->ctl_freq = f.frequency; |
1707 | em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); | 1752 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); |
1708 | } | 1753 | } |
1709 | 1754 | ||
1710 | static int em28xx_hint_board(struct em28xx *dev) | 1755 | static int em28xx_hint_board(struct em28xx *dev) |
@@ -1911,22 +1956,52 @@ void em28xx_card_setup(struct em28xx *dev) | |||
1911 | if (tuner >= 0) | 1956 | if (tuner >= 0) |
1912 | dev->tuner_type = tuner; | 1957 | dev->tuner_type = tuner; |
1913 | 1958 | ||
1914 | #ifdef CONFIG_MODULES | ||
1915 | /* request some modules */ | 1959 | /* request some modules */ |
1916 | if (dev->board.has_msp34xx) | 1960 | if (dev->board.has_msp34xx) |
1917 | request_module("msp3400"); | 1961 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
1962 | "msp3400", "msp3400", msp3400_addrs); | ||
1963 | |||
1918 | if (dev->board.decoder == EM28XX_SAA711X) | 1964 | if (dev->board.decoder == EM28XX_SAA711X) |
1919 | request_module("saa7115"); | 1965 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
1966 | "saa7115", "saa7115_auto", saa711x_addrs); | ||
1967 | |||
1920 | if (dev->board.decoder == EM28XX_TVP5150) | 1968 | if (dev->board.decoder == EM28XX_TVP5150) |
1921 | request_module("tvp5150"); | 1969 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
1922 | if (dev->board.tuner_type != TUNER_ABSENT) | 1970 | "tvp5150", "tvp5150", tvp5150_addrs); |
1923 | request_module("tuner"); | ||
1924 | if (dev->board.adecoder == EM28XX_TVAUDIO) | ||
1925 | request_module("tvaudio"); | ||
1926 | #endif | ||
1927 | 1971 | ||
1928 | em28xx_config_tuner(dev); | 1972 | if (dev->board.adecoder == EM28XX_TVAUDIO) |
1973 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
1974 | "tvaudio", "tvaudio", dev->board.tvaudio_addr); | ||
1975 | |||
1976 | if (dev->board.tuner_type != TUNER_ABSENT) { | ||
1977 | int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); | ||
1978 | |||
1979 | if (dev->board.radio.type) | ||
1980 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
1981 | "tuner", "tuner", dev->board.radio_addr); | ||
1982 | |||
1983 | if (has_demod) | ||
1984 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, | ||
1985 | &dev->i2c_adap, "tuner", "tuner", | ||
1986 | v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); | ||
1987 | if (dev->tuner_addr == 0) { | ||
1988 | enum v4l2_i2c_tuner_type type = | ||
1989 | has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; | ||
1990 | struct v4l2_subdev *sd; | ||
1991 | |||
1992 | sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, | ||
1993 | &dev->i2c_adap, "tuner", "tuner", | ||
1994 | v4l2_i2c_tuner_addrs(type)); | ||
1995 | |||
1996 | if (sd) | ||
1997 | dev->tuner_addr = v4l2_i2c_subdev_addr(sd); | ||
1998 | } else { | ||
1999 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
2000 | "tuner", "tuner", dev->tuner_addr); | ||
2001 | } | ||
2002 | } | ||
1929 | 2003 | ||
2004 | em28xx_tuner_setup(dev); | ||
1930 | em28xx_ir_init(dev); | 2005 | em28xx_ir_init(dev); |
1931 | } | 2006 | } |
1932 | 2007 | ||
@@ -1975,6 +2050,9 @@ void em28xx_release_resources(struct em28xx *dev) | |||
1975 | em28xx_remove_from_devlist(dev); | 2050 | em28xx_remove_from_devlist(dev); |
1976 | 2051 | ||
1977 | em28xx_i2c_unregister(dev); | 2052 | em28xx_i2c_unregister(dev); |
2053 | |||
2054 | v4l2_device_unregister(&dev->v4l2_dev); | ||
2055 | |||
1978 | usb_put_dev(dev->udev); | 2056 | usb_put_dev(dev->udev); |
1979 | 2057 | ||
1980 | /* Mark device as unused */ | 2058 | /* Mark device as unused */ |
@@ -1986,6 +2064,7 @@ void em28xx_release_resources(struct em28xx *dev) | |||
1986 | * allocates and inits the device structs, registers i2c bus and v4l device | 2064 | * allocates and inits the device structs, registers i2c bus and v4l device |
1987 | */ | 2065 | */ |
1988 | static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | 2066 | static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, |
2067 | struct usb_interface *interface, | ||
1989 | int minor) | 2068 | int minor) |
1990 | { | 2069 | { |
1991 | struct em28xx *dev = *devhandle; | 2070 | struct em28xx *dev = *devhandle; |
@@ -2019,9 +2098,16 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2019 | } | 2098 | } |
2020 | } | 2099 | } |
2021 | 2100 | ||
2101 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | ||
2102 | if (retval < 0) { | ||
2103 | em28xx_errdev("Call to v4l2_device_register() failed!\n"); | ||
2104 | return retval; | ||
2105 | } | ||
2106 | |||
2022 | /* register i2c bus */ | 2107 | /* register i2c bus */ |
2023 | errCode = em28xx_i2c_register(dev); | 2108 | errCode = em28xx_i2c_register(dev); |
2024 | if (errCode < 0) { | 2109 | if (errCode < 0) { |
2110 | v4l2_device_unregister(&dev->v4l2_dev); | ||
2025 | em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", | 2111 | em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", |
2026 | __func__, errCode); | 2112 | __func__, errCode); |
2027 | return errCode; | 2113 | return errCode; |
@@ -2033,6 +2119,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2033 | /* Configure audio */ | 2119 | /* Configure audio */ |
2034 | errCode = em28xx_audio_setup(dev); | 2120 | errCode = em28xx_audio_setup(dev); |
2035 | if (errCode < 0) { | 2121 | if (errCode < 0) { |
2122 | v4l2_device_unregister(&dev->v4l2_dev); | ||
2036 | em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", | 2123 | em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", |
2037 | __func__, errCode); | 2124 | __func__, errCode); |
2038 | } | 2125 | } |
@@ -2077,7 +2164,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2077 | em28xx_init_extension(dev); | 2164 | em28xx_init_extension(dev); |
2078 | 2165 | ||
2079 | /* Save some power by putting tuner to sleep */ | 2166 | /* Save some power by putting tuner to sleep */ |
2080 | em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); | 2167 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); |
2081 | 2168 | ||
2082 | return 0; | 2169 | return 0; |
2083 | 2170 | ||
@@ -2096,7 +2183,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2096 | struct usb_device *udev; | 2183 | struct usb_device *udev; |
2097 | struct usb_interface *uif; | 2184 | struct usb_interface *uif; |
2098 | struct em28xx *dev = NULL; | 2185 | struct em28xx *dev = NULL; |
2099 | int retval = -ENODEV; | 2186 | int retval; |
2100 | int i, nr, ifnum, isoc_pipe; | 2187 | int i, nr, ifnum, isoc_pipe; |
2101 | char *speed; | 2188 | char *speed; |
2102 | char descr[255] = ""; | 2189 | char descr[255] = ""; |
@@ -2118,7 +2205,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2118 | interface->altsetting[0].desc.bInterfaceClass); | 2205 | interface->altsetting[0].desc.bInterfaceClass); |
2119 | 2206 | ||
2120 | em28xx_devused &= ~(1<<nr); | 2207 | em28xx_devused &= ~(1<<nr); |
2121 | return -ENODEV; | 2208 | retval = -ENODEV; |
2209 | goto err; | ||
2122 | } | 2210 | } |
2123 | 2211 | ||
2124 | endpoint = &interface->cur_altsetting->endpoint[0].desc; | 2212 | endpoint = &interface->cur_altsetting->endpoint[0].desc; |
@@ -2151,7 +2239,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2151 | "interface not used by the driver\n"); | 2239 | "interface not used by the driver\n"); |
2152 | 2240 | ||
2153 | em28xx_devused &= ~(1<<nr); | 2241 | em28xx_devused &= ~(1<<nr); |
2154 | return -ENODEV; | 2242 | retval = -ENODEV; |
2243 | goto err; | ||
2155 | } | 2244 | } |
2156 | } | 2245 | } |
2157 | 2246 | ||
@@ -2194,7 +2283,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2194 | printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", | 2283 | printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", |
2195 | EM28XX_MAXBOARDS); | 2284 | EM28XX_MAXBOARDS); |
2196 | em28xx_devused &= ~(1<<nr); | 2285 | em28xx_devused &= ~(1<<nr); |
2197 | return -ENOMEM; | 2286 | retval = -ENOMEM; |
2287 | goto err; | ||
2198 | } | 2288 | } |
2199 | 2289 | ||
2200 | /* allocate memory for our device state and initialize it */ | 2290 | /* allocate memory for our device state and initialize it */ |
@@ -2202,7 +2292,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2202 | if (dev == NULL) { | 2292 | if (dev == NULL) { |
2203 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | 2293 | em28xx_err(DRIVER_NAME ": out of memory!\n"); |
2204 | em28xx_devused &= ~(1<<nr); | 2294 | em28xx_devused &= ~(1<<nr); |
2205 | return -ENOMEM; | 2295 | retval = -ENOMEM; |
2296 | goto err; | ||
2206 | } | 2297 | } |
2207 | 2298 | ||
2208 | snprintf(dev->name, 29, "em28xx #%d", nr); | 2299 | snprintf(dev->name, 29, "em28xx #%d", nr); |
@@ -2229,7 +2320,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2229 | em28xx_errdev("out of memory!\n"); | 2320 | em28xx_errdev("out of memory!\n"); |
2230 | em28xx_devused &= ~(1<<nr); | 2321 | em28xx_devused &= ~(1<<nr); |
2231 | kfree(dev); | 2322 | kfree(dev); |
2232 | return -ENOMEM; | 2323 | retval = -ENOMEM; |
2324 | goto err; | ||
2233 | } | 2325 | } |
2234 | 2326 | ||
2235 | for (i = 0; i < dev->num_alt ; i++) { | 2327 | for (i = 0; i < dev->num_alt ; i++) { |
@@ -2244,12 +2336,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2244 | /* allocate device struct */ | 2336 | /* allocate device struct */ |
2245 | mutex_init(&dev->lock); | 2337 | mutex_init(&dev->lock); |
2246 | mutex_lock(&dev->lock); | 2338 | mutex_lock(&dev->lock); |
2247 | retval = em28xx_init_dev(&dev, udev, nr); | 2339 | retval = em28xx_init_dev(&dev, udev, interface, nr); |
2248 | if (retval) { | 2340 | if (retval) { |
2249 | em28xx_devused &= ~(1<<dev->devno); | 2341 | em28xx_devused &= ~(1<<dev->devno); |
2250 | kfree(dev); | 2342 | kfree(dev); |
2251 | 2343 | goto err; | |
2252 | return retval; | ||
2253 | } | 2344 | } |
2254 | 2345 | ||
2255 | /* save our data pointer in this interface device */ | 2346 | /* save our data pointer in this interface device */ |
@@ -2263,6 +2354,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2263 | mutex_unlock(&dev->lock); | 2354 | mutex_unlock(&dev->lock); |
2264 | 2355 | ||
2265 | return 0; | 2356 | return 0; |
2357 | |||
2358 | err: | ||
2359 | return retval; | ||
2266 | } | 2360 | } |
2267 | 2361 | ||
2268 | /* | 2362 | /* |
@@ -2288,6 +2382,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
2288 | 2382 | ||
2289 | wake_up_interruptible_all(&dev->open); | 2383 | wake_up_interruptible_all(&dev->open); |
2290 | 2384 | ||
2385 | v4l2_device_disconnect(&dev->v4l2_dev); | ||
2386 | |||
2291 | if (dev->users) { | 2387 | if (dev->users) { |
2292 | em28xx_warn | 2388 | em28xx_warn |
2293 | ("device /dev/video%d is open! Deregistration and memory " | 2389 | ("device /dev/video%d is open! Deregistration and memory " |