diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-28 20:18:14 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:39:37 -0500 |
commit | 1a23f81b7dc3115b29cff0e4f58b5dd04a6242ad (patch) | |
tree | 643b900aae78870a53fec3fdf1e15b400ae960c0 /drivers/media/video | |
parent | 126be90f720d9b23e89c68519022fb806882f42d (diff) |
V4L/DVB (9979): em28xx: move usb probe code to a proper place
em28xx-video were holding several code that are not specific to V4L2
interface.
This patch moves the core code for em28xx-core, and usb probing code
into em28xx-cards.
This opens the possibility of breaking em28xx into a core module and a
V4L2 module, loaded only on devices that have analog interfaces.
Some cleanup may be done at em28xx-cards to optimize the config code.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 430 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 143 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 619 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 16 |
4 files changed, 633 insertions, 575 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index e5d9424d03f9..42978f9592b7 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -37,6 +37,8 @@ | |||
37 | 37 | ||
38 | #include "em28xx.h" | 38 | #include "em28xx.h" |
39 | 39 | ||
40 | #define DRIVER_NAME "em28xx" | ||
41 | |||
40 | static int tuner = -1; | 42 | static int tuner = -1; |
41 | module_param(tuner, int, 0444); | 43 | module_param(tuner, int, 0444); |
42 | MODULE_PARM_DESC(tuner, "tuner type"); | 44 | MODULE_PARM_DESC(tuner, "tuner type"); |
@@ -45,6 +47,13 @@ static unsigned int disable_ir; | |||
45 | module_param(disable_ir, int, 0444); | 47 | module_param(disable_ir, int, 0444); |
46 | MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); | 48 | MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); |
47 | 49 | ||
50 | static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | ||
51 | module_param_array(card, int, NULL, 0444); | ||
52 | MODULE_PARM_DESC(card, "card type"); | ||
53 | |||
54 | /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ | ||
55 | static unsigned long em28xx_devused; | ||
56 | |||
48 | struct em28xx_hash_table { | 57 | struct em28xx_hash_table { |
49 | unsigned long hash; | 58 | unsigned long hash; |
50 | unsigned int model; | 59 | unsigned int model; |
@@ -1801,3 +1810,424 @@ void em28xx_card_setup(struct em28xx *dev) | |||
1801 | em28xx_ir_init(dev); | 1810 | em28xx_ir_init(dev); |
1802 | } | 1811 | } |
1803 | 1812 | ||
1813 | |||
1814 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
1815 | static void request_module_async(struct work_struct *work) | ||
1816 | { | ||
1817 | struct em28xx *dev = container_of(work, | ||
1818 | struct em28xx, request_module_wk); | ||
1819 | |||
1820 | if (dev->has_audio_class) | ||
1821 | request_module("snd-usb-audio"); | ||
1822 | else if (dev->has_alsa_audio) | ||
1823 | request_module("em28xx-alsa"); | ||
1824 | |||
1825 | if (dev->board.has_dvb) | ||
1826 | request_module("em28xx-dvb"); | ||
1827 | } | ||
1828 | |||
1829 | static void request_modules(struct em28xx *dev) | ||
1830 | { | ||
1831 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
1832 | schedule_work(&dev->request_module_wk); | ||
1833 | } | ||
1834 | #else | ||
1835 | #define request_modules(dev) | ||
1836 | #endif /* CONFIG_MODULES */ | ||
1837 | |||
1838 | /* | ||
1839 | * em28xx_realease_resources() | ||
1840 | * unregisters the v4l2,i2c and usb devices | ||
1841 | * called when the device gets disconected or at module unload | ||
1842 | */ | ||
1843 | void em28xx_release_resources(struct em28xx *dev) | ||
1844 | { | ||
1845 | if (dev->sbutton_input_dev) | ||
1846 | em28xx_deregister_snapshot_button(dev); | ||
1847 | |||
1848 | if (dev->ir) | ||
1849 | em28xx_ir_fini(dev); | ||
1850 | |||
1851 | /*FIXME: I2C IR should be disconnected */ | ||
1852 | |||
1853 | em28xx_release_analog_resources(dev); | ||
1854 | |||
1855 | em28xx_remove_from_devlist(dev); | ||
1856 | |||
1857 | em28xx_i2c_unregister(dev); | ||
1858 | usb_put_dev(dev->udev); | ||
1859 | |||
1860 | /* Mark device as unused */ | ||
1861 | em28xx_devused &= ~(1 << dev->devno); | ||
1862 | }; | ||
1863 | |||
1864 | /* | ||
1865 | * em28xx_init_dev() | ||
1866 | * allocates and inits the device structs, registers i2c bus and v4l device | ||
1867 | */ | ||
1868 | int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | ||
1869 | int minor) | ||
1870 | { | ||
1871 | struct em28xx *dev = *devhandle; | ||
1872 | int retval = -ENOMEM; | ||
1873 | int errCode; | ||
1874 | |||
1875 | dev->udev = udev; | ||
1876 | mutex_init(&dev->ctrl_urb_lock); | ||
1877 | spin_lock_init(&dev->slock); | ||
1878 | init_waitqueue_head(&dev->open); | ||
1879 | init_waitqueue_head(&dev->wait_frame); | ||
1880 | init_waitqueue_head(&dev->wait_stream); | ||
1881 | |||
1882 | dev->em28xx_write_regs = em28xx_write_regs; | ||
1883 | dev->em28xx_read_reg = em28xx_read_reg; | ||
1884 | dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; | ||
1885 | dev->em28xx_write_regs_req = em28xx_write_regs_req; | ||
1886 | dev->em28xx_read_reg_req = em28xx_read_reg_req; | ||
1887 | dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; | ||
1888 | |||
1889 | em28xx_pre_card_setup(dev); | ||
1890 | |||
1891 | if (!dev->board.is_em2800) { | ||
1892 | /* Sets I2C speed to 100 KHz */ | ||
1893 | retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); | ||
1894 | if (retval < 0) { | ||
1895 | em28xx_errdev("%s: em28xx_write_regs_req failed!" | ||
1896 | " retval [%d]\n", | ||
1897 | __func__, retval); | ||
1898 | return retval; | ||
1899 | } | ||
1900 | } | ||
1901 | |||
1902 | /* register i2c bus */ | ||
1903 | errCode = em28xx_i2c_register(dev); | ||
1904 | if (errCode < 0) { | ||
1905 | em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", | ||
1906 | __func__, errCode); | ||
1907 | return errCode; | ||
1908 | } | ||
1909 | |||
1910 | /* Do board specific init and eeprom reading */ | ||
1911 | em28xx_card_setup(dev); | ||
1912 | |||
1913 | /* Configure audio */ | ||
1914 | errCode = em28xx_audio_setup(dev); | ||
1915 | if (errCode < 0) { | ||
1916 | em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", | ||
1917 | __func__, errCode); | ||
1918 | } | ||
1919 | |||
1920 | /* wake i2c devices */ | ||
1921 | em28xx_wake_i2c(dev); | ||
1922 | |||
1923 | /* init video dma queues */ | ||
1924 | INIT_LIST_HEAD(&dev->vidq.active); | ||
1925 | INIT_LIST_HEAD(&dev->vidq.queued); | ||
1926 | |||
1927 | |||
1928 | if (dev->board.has_msp34xx) { | ||
1929 | /* Send a reset to other chips via gpio */ | ||
1930 | errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); | ||
1931 | if (errCode < 0) { | ||
1932 | em28xx_errdev("%s: em28xx_write_regs_req - " | ||
1933 | "msp34xx(1) failed! errCode [%d]\n", | ||
1934 | __func__, errCode); | ||
1935 | return errCode; | ||
1936 | } | ||
1937 | msleep(3); | ||
1938 | |||
1939 | errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); | ||
1940 | if (errCode < 0) { | ||
1941 | em28xx_errdev("%s: em28xx_write_regs_req - " | ||
1942 | "msp34xx(2) failed! errCode [%d]\n", | ||
1943 | __func__, errCode); | ||
1944 | return errCode; | ||
1945 | } | ||
1946 | msleep(3); | ||
1947 | } | ||
1948 | |||
1949 | em28xx_add_into_devlist(dev); | ||
1950 | |||
1951 | errCode = em28xx_analog_config(dev); | ||
1952 | if (errCode) { | ||
1953 | em28xx_errdev("error configuring device\n"); | ||
1954 | return -ENOMEM; | ||
1955 | } | ||
1956 | |||
1957 | retval = em28xx_register_analog_devices(dev); | ||
1958 | if (retval < 0) { | ||
1959 | em28xx_release_resources(dev); | ||
1960 | goto fail_reg_devices; | ||
1961 | } | ||
1962 | |||
1963 | em28xx_init_extension(dev); | ||
1964 | |||
1965 | /* Save some power by putting tuner to sleep */ | ||
1966 | em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); | ||
1967 | |||
1968 | return 0; | ||
1969 | |||
1970 | fail_reg_devices: | ||
1971 | return retval; | ||
1972 | } | ||
1973 | |||
1974 | /* | ||
1975 | * em28xx_usb_probe() | ||
1976 | * checks for supported devices | ||
1977 | */ | ||
1978 | static int em28xx_usb_probe(struct usb_interface *interface, | ||
1979 | const struct usb_device_id *id) | ||
1980 | { | ||
1981 | const struct usb_endpoint_descriptor *endpoint; | ||
1982 | struct usb_device *udev; | ||
1983 | struct usb_interface *uif; | ||
1984 | struct em28xx *dev = NULL; | ||
1985 | int retval = -ENODEV; | ||
1986 | int i, nr, ifnum, isoc_pipe; | ||
1987 | char *speed; | ||
1988 | char descr[255] = ""; | ||
1989 | |||
1990 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
1991 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | ||
1992 | |||
1993 | /* Check to see next free device and mark as used */ | ||
1994 | nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); | ||
1995 | em28xx_devused |= 1<<nr; | ||
1996 | |||
1997 | /* Don't register audio interfaces */ | ||
1998 | if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { | ||
1999 | em28xx_err(DRIVER_NAME " audio device (%04x:%04x): " | ||
2000 | "interface %i, class %i\n", | ||
2001 | le16_to_cpu(udev->descriptor.idVendor), | ||
2002 | le16_to_cpu(udev->descriptor.idProduct), | ||
2003 | ifnum, | ||
2004 | interface->altsetting[0].desc.bInterfaceClass); | ||
2005 | |||
2006 | em28xx_devused &= ~(1<<nr); | ||
2007 | return -ENODEV; | ||
2008 | } | ||
2009 | |||
2010 | endpoint = &interface->cur_altsetting->endpoint[0].desc; | ||
2011 | |||
2012 | /* check if the device has the iso in endpoint at the correct place */ | ||
2013 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
2014 | USB_ENDPOINT_XFER_ISOC && | ||
2015 | (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { | ||
2016 | /* It's a newer em2874/em2875 device */ | ||
2017 | isoc_pipe = 0; | ||
2018 | } else { | ||
2019 | int check_interface = 1; | ||
2020 | isoc_pipe = 1; | ||
2021 | endpoint = &interface->cur_altsetting->endpoint[1].desc; | ||
2022 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != | ||
2023 | USB_ENDPOINT_XFER_ISOC) | ||
2024 | check_interface = 0; | ||
2025 | |||
2026 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) | ||
2027 | check_interface = 0; | ||
2028 | |||
2029 | if (!check_interface) { | ||
2030 | em28xx_err(DRIVER_NAME " video device (%04x:%04x): " | ||
2031 | "interface %i, class %i found.\n", | ||
2032 | le16_to_cpu(udev->descriptor.idVendor), | ||
2033 | le16_to_cpu(udev->descriptor.idProduct), | ||
2034 | ifnum, | ||
2035 | interface->altsetting[0].desc.bInterfaceClass); | ||
2036 | |||
2037 | em28xx_err(DRIVER_NAME " This is an anciliary " | ||
2038 | "interface not used by the driver\n"); | ||
2039 | |||
2040 | em28xx_devused &= ~(1<<nr); | ||
2041 | return -ENODEV; | ||
2042 | } | ||
2043 | } | ||
2044 | |||
2045 | switch (udev->speed) { | ||
2046 | case USB_SPEED_LOW: | ||
2047 | speed = "1.5"; | ||
2048 | break; | ||
2049 | case USB_SPEED_UNKNOWN: | ||
2050 | case USB_SPEED_FULL: | ||
2051 | speed = "12"; | ||
2052 | break; | ||
2053 | case USB_SPEED_HIGH: | ||
2054 | speed = "480"; | ||
2055 | break; | ||
2056 | default: | ||
2057 | speed = "unknown"; | ||
2058 | } | ||
2059 | |||
2060 | if (udev->manufacturer) | ||
2061 | strlcpy(descr, udev->manufacturer, sizeof(descr)); | ||
2062 | |||
2063 | if (udev->product) { | ||
2064 | if (*descr) | ||
2065 | strlcat(descr, " ", sizeof(descr)); | ||
2066 | strlcat(descr, udev->product, sizeof(descr)); | ||
2067 | } | ||
2068 | if (*descr) | ||
2069 | strlcat(descr, " ", sizeof(descr)); | ||
2070 | |||
2071 | printk(DRIVER_NAME ": New device %s@ %s Mbps " | ||
2072 | "(%04x:%04x, interface %d, class %d)\n", | ||
2073 | descr, | ||
2074 | speed, | ||
2075 | le16_to_cpu(udev->descriptor.idVendor), | ||
2076 | le16_to_cpu(udev->descriptor.idProduct), | ||
2077 | ifnum, | ||
2078 | interface->altsetting->desc.bInterfaceNumber); | ||
2079 | |||
2080 | if (nr >= EM28XX_MAXBOARDS) { | ||
2081 | printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", | ||
2082 | EM28XX_MAXBOARDS); | ||
2083 | em28xx_devused &= ~(1<<nr); | ||
2084 | return -ENOMEM; | ||
2085 | } | ||
2086 | |||
2087 | /* allocate memory for our device state and initialize it */ | ||
2088 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
2089 | if (dev == NULL) { | ||
2090 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | ||
2091 | em28xx_devused &= ~(1<<nr); | ||
2092 | return -ENOMEM; | ||
2093 | } | ||
2094 | |||
2095 | snprintf(dev->name, 29, "em28xx #%d", nr); | ||
2096 | dev->devno = nr; | ||
2097 | dev->model = id->driver_info; | ||
2098 | dev->alt = -1; | ||
2099 | |||
2100 | /* Checks if audio is provided by some interface */ | ||
2101 | for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { | ||
2102 | uif = udev->config->interface[i]; | ||
2103 | if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { | ||
2104 | dev->has_audio_class = 1; | ||
2105 | break; | ||
2106 | } | ||
2107 | } | ||
2108 | |||
2109 | /* compute alternate max packet sizes */ | ||
2110 | uif = udev->actconfig->interface[0]; | ||
2111 | |||
2112 | dev->num_alt = uif->num_altsetting; | ||
2113 | dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); | ||
2114 | |||
2115 | if (dev->alt_max_pkt_size == NULL) { | ||
2116 | em28xx_errdev("out of memory!\n"); | ||
2117 | em28xx_devused &= ~(1<<nr); | ||
2118 | kfree(dev); | ||
2119 | return -ENOMEM; | ||
2120 | } | ||
2121 | |||
2122 | for (i = 0; i < dev->num_alt ; i++) { | ||
2123 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); | ||
2124 | dev->alt_max_pkt_size[i] = | ||
2125 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
2126 | } | ||
2127 | |||
2128 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) | ||
2129 | dev->model = card[nr]; | ||
2130 | |||
2131 | /* allocate device struct */ | ||
2132 | mutex_init(&dev->lock); | ||
2133 | mutex_lock(&dev->lock); | ||
2134 | retval = em28xx_init_dev(&dev, udev, nr); | ||
2135 | if (retval) { | ||
2136 | em28xx_devused &= ~(1<<dev->devno); | ||
2137 | kfree(dev); | ||
2138 | |||
2139 | return retval; | ||
2140 | } | ||
2141 | |||
2142 | /* save our data pointer in this interface device */ | ||
2143 | usb_set_intfdata(interface, dev); | ||
2144 | |||
2145 | request_modules(dev); | ||
2146 | |||
2147 | /* Should be the last thing to do, to avoid newer udev's to | ||
2148 | open the device before fully initializing it | ||
2149 | */ | ||
2150 | mutex_unlock(&dev->lock); | ||
2151 | |||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2155 | /* | ||
2156 | * em28xx_usb_disconnect() | ||
2157 | * called when the device gets diconencted | ||
2158 | * video device will be unregistered on v4l2_close in case it is still open | ||
2159 | */ | ||
2160 | static void em28xx_usb_disconnect(struct usb_interface *interface) | ||
2161 | { | ||
2162 | struct em28xx *dev; | ||
2163 | |||
2164 | dev = usb_get_intfdata(interface); | ||
2165 | usb_set_intfdata(interface, NULL); | ||
2166 | |||
2167 | if (!dev) | ||
2168 | return; | ||
2169 | |||
2170 | em28xx_info("disconnecting %s\n", dev->vdev->name); | ||
2171 | |||
2172 | /* wait until all current v4l2 io is finished then deallocate | ||
2173 | resources */ | ||
2174 | mutex_lock(&dev->lock); | ||
2175 | |||
2176 | wake_up_interruptible_all(&dev->open); | ||
2177 | |||
2178 | if (dev->users) { | ||
2179 | em28xx_warn | ||
2180 | ("device /dev/video%d is open! Deregistration and memory " | ||
2181 | "deallocation are deferred on close.\n", | ||
2182 | dev->vdev->num); | ||
2183 | |||
2184 | dev->state |= DEV_MISCONFIGURED; | ||
2185 | em28xx_uninit_isoc(dev); | ||
2186 | dev->state |= DEV_DISCONNECTED; | ||
2187 | wake_up_interruptible(&dev->wait_frame); | ||
2188 | wake_up_interruptible(&dev->wait_stream); | ||
2189 | } else { | ||
2190 | dev->state |= DEV_DISCONNECTED; | ||
2191 | em28xx_release_resources(dev); | ||
2192 | } | ||
2193 | |||
2194 | em28xx_close_extension(dev); | ||
2195 | |||
2196 | mutex_unlock(&dev->lock); | ||
2197 | |||
2198 | if (!dev->users) { | ||
2199 | kfree(dev->alt_max_pkt_size); | ||
2200 | kfree(dev); | ||
2201 | } | ||
2202 | } | ||
2203 | |||
2204 | static struct usb_driver em28xx_usb_driver = { | ||
2205 | .name = "em28xx", | ||
2206 | .probe = em28xx_usb_probe, | ||
2207 | .disconnect = em28xx_usb_disconnect, | ||
2208 | .id_table = em28xx_id_table, | ||
2209 | }; | ||
2210 | |||
2211 | static int __init em28xx_module_init(void) | ||
2212 | { | ||
2213 | int result; | ||
2214 | |||
2215 | /* register this driver with the USB subsystem */ | ||
2216 | result = usb_register(&em28xx_usb_driver); | ||
2217 | if (result) | ||
2218 | em28xx_err(DRIVER_NAME | ||
2219 | " usb_register failed. Error number %d.\n", result); | ||
2220 | |||
2221 | printk(KERN_INFO DRIVER_NAME " driver loaded\n"); | ||
2222 | |||
2223 | return result; | ||
2224 | } | ||
2225 | |||
2226 | static void __exit em28xx_module_exit(void) | ||
2227 | { | ||
2228 | /* deregister this driver with the USB subsystem */ | ||
2229 | usb_deregister(&em28xx_usb_driver); | ||
2230 | } | ||
2231 | |||
2232 | module_init(em28xx_module_init); | ||
2233 | module_exit(em28xx_module_exit); | ||
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 5964998daf2e..ac735f25283c 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/usb.h> | 27 | #include <linux/usb.h> |
28 | #include <linux/vmalloc.h> | 28 | #include <linux/vmalloc.h> |
29 | #include <media/v4l2-common.h> | ||
29 | 30 | ||
30 | #include "em28xx.h" | 31 | #include "em28xx.h" |
31 | 32 | ||
@@ -974,3 +975,145 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, | |||
974 | return 0; | 975 | return 0; |
975 | } | 976 | } |
976 | EXPORT_SYMBOL_GPL(em28xx_init_isoc); | 977 | EXPORT_SYMBOL_GPL(em28xx_init_isoc); |
978 | |||
979 | /* | ||
980 | * em28xx_wake_i2c() | ||
981 | * configure i2c attached devices | ||
982 | */ | ||
983 | void em28xx_wake_i2c(struct em28xx *dev) | ||
984 | { | ||
985 | struct v4l2_routing route; | ||
986 | int zero = 0; | ||
987 | |||
988 | route.input = INPUT(dev->ctl_input)->vmux; | ||
989 | route.output = 0; | ||
990 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); | ||
991 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
992 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); | ||
993 | } | ||
994 | |||
995 | /* | ||
996 | * Device control list | ||
997 | */ | ||
998 | |||
999 | static LIST_HEAD(em28xx_devlist); | ||
1000 | static DEFINE_MUTEX(em28xx_devlist_mutex); | ||
1001 | |||
1002 | struct em28xx *em28xx_get_device(struct inode *inode, | ||
1003 | enum v4l2_buf_type *fh_type, | ||
1004 | int *has_radio) | ||
1005 | { | ||
1006 | struct em28xx *h, *dev = NULL; | ||
1007 | int minor = iminor(inode); | ||
1008 | |||
1009 | *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1010 | *has_radio = 0; | ||
1011 | |||
1012 | mutex_lock(&em28xx_devlist_mutex); | ||
1013 | list_for_each_entry(h, &em28xx_devlist, devlist) { | ||
1014 | if (h->vdev->minor == minor) | ||
1015 | dev = h; | ||
1016 | if (h->vbi_dev->minor == minor) { | ||
1017 | dev = h; | ||
1018 | *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1019 | } | ||
1020 | if (h->radio_dev && | ||
1021 | h->radio_dev->minor == minor) { | ||
1022 | dev = h; | ||
1023 | *has_radio = 1; | ||
1024 | } | ||
1025 | } | ||
1026 | mutex_unlock(&em28xx_devlist_mutex); | ||
1027 | |||
1028 | return dev; | ||
1029 | } | ||
1030 | |||
1031 | /* | ||
1032 | * em28xx_realease_resources() | ||
1033 | * unregisters the v4l2,i2c and usb devices | ||
1034 | * called when the device gets disconected or at module unload | ||
1035 | */ | ||
1036 | void em28xx_remove_from_devlist(struct em28xx *dev) | ||
1037 | { | ||
1038 | mutex_lock(&em28xx_devlist_mutex); | ||
1039 | list_del(&dev->devlist); | ||
1040 | mutex_unlock(&em28xx_devlist_mutex); | ||
1041 | }; | ||
1042 | |||
1043 | void em28xx_add_into_devlist(struct em28xx *dev) | ||
1044 | { | ||
1045 | mutex_lock(&em28xx_devlist_mutex); | ||
1046 | list_add_tail(&dev->devlist, &em28xx_devlist); | ||
1047 | mutex_unlock(&em28xx_devlist_mutex); | ||
1048 | }; | ||
1049 | |||
1050 | /* | ||
1051 | * Extension interface | ||
1052 | */ | ||
1053 | |||
1054 | static LIST_HEAD(em28xx_extension_devlist); | ||
1055 | static DEFINE_MUTEX(em28xx_extension_devlist_lock); | ||
1056 | |||
1057 | int em28xx_register_extension(struct em28xx_ops *ops) | ||
1058 | { | ||
1059 | struct em28xx *dev = NULL; | ||
1060 | |||
1061 | mutex_lock(&em28xx_devlist_mutex); | ||
1062 | mutex_lock(&em28xx_extension_devlist_lock); | ||
1063 | list_add_tail(&ops->next, &em28xx_extension_devlist); | ||
1064 | list_for_each_entry(dev, &em28xx_devlist, devlist) { | ||
1065 | if (dev) | ||
1066 | ops->init(dev); | ||
1067 | } | ||
1068 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); | ||
1069 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
1070 | mutex_unlock(&em28xx_devlist_mutex); | ||
1071 | return 0; | ||
1072 | } | ||
1073 | EXPORT_SYMBOL(em28xx_register_extension); | ||
1074 | |||
1075 | void em28xx_unregister_extension(struct em28xx_ops *ops) | ||
1076 | { | ||
1077 | struct em28xx *dev = NULL; | ||
1078 | |||
1079 | mutex_lock(&em28xx_devlist_mutex); | ||
1080 | list_for_each_entry(dev, &em28xx_devlist, devlist) { | ||
1081 | if (dev) | ||
1082 | ops->fini(dev); | ||
1083 | } | ||
1084 | |||
1085 | mutex_lock(&em28xx_extension_devlist_lock); | ||
1086 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); | ||
1087 | list_del(&ops->next); | ||
1088 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
1089 | mutex_unlock(&em28xx_devlist_mutex); | ||
1090 | } | ||
1091 | EXPORT_SYMBOL(em28xx_unregister_extension); | ||
1092 | |||
1093 | void em28xx_init_extension(struct em28xx *dev) | ||
1094 | { | ||
1095 | struct em28xx_ops *ops = NULL; | ||
1096 | |||
1097 | mutex_lock(&em28xx_extension_devlist_lock); | ||
1098 | if (!list_empty(&em28xx_extension_devlist)) { | ||
1099 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||
1100 | if (ops->init) | ||
1101 | ops->init(dev); | ||
1102 | } | ||
1103 | } | ||
1104 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
1105 | } | ||
1106 | |||
1107 | void em28xx_close_extension(struct em28xx *dev) | ||
1108 | { | ||
1109 | struct em28xx_ops *ops = NULL; | ||
1110 | |||
1111 | mutex_lock(&em28xx_extension_devlist_lock); | ||
1112 | if (!list_empty(&em28xx_extension_devlist)) { | ||
1113 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||
1114 | if (ops->fini) | ||
1115 | ops->fini(dev); | ||
1116 | } | ||
1117 | } | ||
1118 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
1119 | } | ||
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index b5ea18e12290..4c0986920970 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -48,9 +48,8 @@ | |||
48 | "Mauro Carvalho Chehab <mchehab@infradead.org>, " \ | 48 | "Mauro Carvalho Chehab <mchehab@infradead.org>, " \ |
49 | "Sascha Sommer <saschasommer@freenet.de>" | 49 | "Sascha Sommer <saschasommer@freenet.de>" |
50 | 50 | ||
51 | #define DRIVER_NAME "em28xx" | ||
52 | #define DRIVER_DESC "Empia em28xx based USB video device driver" | 51 | #define DRIVER_DESC "Empia em28xx based USB video device driver" |
53 | #define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 0) | 52 | #define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 1) |
54 | 53 | ||
55 | #define em28xx_videodbg(fmt, arg...) do {\ | 54 | #define em28xx_videodbg(fmt, arg...) do {\ |
56 | if (video_debug) \ | 55 | if (video_debug) \ |
@@ -73,19 +72,13 @@ MODULE_AUTHOR(DRIVER_AUTHOR); | |||
73 | MODULE_DESCRIPTION(DRIVER_DESC); | 72 | MODULE_DESCRIPTION(DRIVER_DESC); |
74 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
75 | 74 | ||
76 | static LIST_HEAD(em28xx_devlist); | ||
77 | static DEFINE_MUTEX(em28xx_devlist_mutex); | ||
78 | |||
79 | static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | ||
80 | static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | 75 | static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; |
81 | static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | 76 | static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; |
82 | static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | 77 | static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; |
83 | 78 | ||
84 | module_param_array(card, int, NULL, 0444); | ||
85 | module_param_array(video_nr, int, NULL, 0444); | 79 | module_param_array(video_nr, int, NULL, 0444); |
86 | module_param_array(vbi_nr, int, NULL, 0444); | 80 | module_param_array(vbi_nr, int, NULL, 0444); |
87 | module_param_array(radio_nr, int, NULL, 0444); | 81 | module_param_array(radio_nr, int, NULL, 0444); |
88 | MODULE_PARM_DESC(card, "card type"); | ||
89 | MODULE_PARM_DESC(video_nr, "video device numbers"); | 82 | MODULE_PARM_DESC(video_nr, "video device numbers"); |
90 | MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); | 83 | MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); |
91 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); | 84 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); |
@@ -94,9 +87,6 @@ static unsigned int video_debug; | |||
94 | module_param(video_debug, int, 0644); | 87 | module_param(video_debug, int, 0644); |
95 | MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); | 88 | MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); |
96 | 89 | ||
97 | /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ | ||
98 | static unsigned long em28xx_devused; | ||
99 | |||
100 | /* supported video standards */ | 90 | /* supported video standards */ |
101 | static struct em28xx_fmt format[] = { | 91 | static struct em28xx_fmt format[] = { |
102 | { | 92 | { |
@@ -131,8 +121,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { | |||
131 | } | 121 | } |
132 | }; | 122 | }; |
133 | 123 | ||
134 | static struct usb_driver em28xx_usb_driver; | ||
135 | |||
136 | /* ------------------------------------------------------------------ | 124 | /* ------------------------------------------------------------------ |
137 | DMA and thread functions | 125 | DMA and thread functions |
138 | ------------------------------------------------------------------*/ | 126 | ------------------------------------------------------------------*/ |
@@ -519,56 +507,6 @@ static struct videobuf_queue_ops em28xx_video_qops = { | |||
519 | 507 | ||
520 | /********************* v4l2 interface **************************************/ | 508 | /********************* v4l2 interface **************************************/ |
521 | 509 | ||
522 | /* | ||
523 | * em28xx_config() | ||
524 | * inits registers with sane defaults | ||
525 | */ | ||
526 | static int em28xx_config(struct em28xx *dev) | ||
527 | { | ||
528 | int retval; | ||
529 | |||
530 | /* Sets I2C speed to 100 KHz */ | ||
531 | if (!dev->board.is_em2800) { | ||
532 | retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); | ||
533 | if (retval < 0) { | ||
534 | em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n", | ||
535 | __func__, retval); | ||
536 | return retval; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | /* enable vbi capturing */ | ||
541 | |||
542 | /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ | ||
543 | /* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ | ||
544 | em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); | ||
545 | |||
546 | dev->mute = 1; /* maybe not the right place... */ | ||
547 | dev->volume = 0x1f; | ||
548 | |||
549 | em28xx_set_outfmt(dev); | ||
550 | em28xx_colorlevels_set_default(dev); | ||
551 | em28xx_compression_disable(dev); | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * em28xx_config_i2c() | ||
558 | * configure i2c attached devices | ||
559 | */ | ||
560 | static void em28xx_config_i2c(struct em28xx *dev) | ||
561 | { | ||
562 | struct v4l2_routing route; | ||
563 | int zero = 0; | ||
564 | |||
565 | route.input = INPUT(dev->ctl_input)->vmux; | ||
566 | route.output = 0; | ||
567 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); | ||
568 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
569 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); | ||
570 | } | ||
571 | |||
572 | static void video_mux(struct em28xx *dev, int index) | 510 | static void video_mux(struct em28xx *dev, int index) |
573 | { | 511 | { |
574 | struct v4l2_routing route; | 512 | struct v4l2_routing route; |
@@ -1647,28 +1585,12 @@ static int radio_queryctrl(struct file *file, void *priv, | |||
1647 | static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | 1585 | static int em28xx_v4l2_open(struct inode *inode, struct file *filp) |
1648 | { | 1586 | { |
1649 | int minor = iminor(inode); | 1587 | int minor = iminor(inode); |
1650 | int errCode = 0, radio = 0; | 1588 | int errCode = 0, radio; |
1651 | struct em28xx *h, *dev = NULL; | 1589 | struct em28xx *dev; |
1590 | enum v4l2_buf_type fh_type; | ||
1652 | struct em28xx_fh *fh; | 1591 | struct em28xx_fh *fh; |
1653 | enum v4l2_buf_type fh_type = 0; | ||
1654 | 1592 | ||
1655 | mutex_lock(&em28xx_devlist_mutex); | 1593 | dev = em28xx_get_device(inode, &fh_type, &radio); |
1656 | list_for_each_entry(h, &em28xx_devlist, devlist) { | ||
1657 | if (h->vdev->minor == minor) { | ||
1658 | dev = h; | ||
1659 | fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1660 | } | ||
1661 | if (h->vbi_dev->minor == minor) { | ||
1662 | dev = h; | ||
1663 | fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1664 | } | ||
1665 | if (h->radio_dev && | ||
1666 | h->radio_dev->minor == minor) { | ||
1667 | radio = 1; | ||
1668 | dev = h; | ||
1669 | } | ||
1670 | } | ||
1671 | mutex_unlock(&em28xx_devlist_mutex); | ||
1672 | 1594 | ||
1673 | if (NULL == dev) | 1595 | if (NULL == dev) |
1674 | return -ENODEV; | 1596 | return -ENODEV; |
@@ -1703,7 +1625,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
1703 | /* Needed, since GPIO might have disabled power of | 1625 | /* Needed, since GPIO might have disabled power of |
1704 | some i2c device | 1626 | some i2c device |
1705 | */ | 1627 | */ |
1706 | em28xx_config_i2c(dev); | 1628 | em28xx_wake_i2c(dev); |
1707 | 1629 | ||
1708 | } | 1630 | } |
1709 | if (fh->radio) { | 1631 | if (fh->radio) { |
@@ -1727,18 +1649,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
1727 | * unregisters the v4l2,i2c and usb devices | 1649 | * unregisters the v4l2,i2c and usb devices |
1728 | * called when the device gets disconected or at module unload | 1650 | * called when the device gets disconected or at module unload |
1729 | */ | 1651 | */ |
1730 | static void em28xx_release_resources(struct em28xx *dev) | 1652 | void em28xx_release_analog_resources(struct em28xx *dev) |
1731 | { | 1653 | { |
1732 | 1654 | ||
1733 | /*FIXME: I2C IR should be disconnected */ | 1655 | /*FIXME: I2C IR should be disconnected */ |
1734 | 1656 | ||
1735 | list_del(&dev->devlist); | ||
1736 | if (dev->sbutton_input_dev) | ||
1737 | em28xx_deregister_snapshot_button(dev); | ||
1738 | |||
1739 | if (dev->ir) | ||
1740 | em28xx_ir_fini(dev); | ||
1741 | |||
1742 | if (dev->radio_dev) { | 1657 | if (dev->radio_dev) { |
1743 | if (-1 != dev->radio_dev->minor) | 1658 | if (-1 != dev->radio_dev->minor) |
1744 | video_unregister_device(dev->radio_dev); | 1659 | video_unregister_device(dev->radio_dev); |
@@ -1764,11 +1679,6 @@ static void em28xx_release_resources(struct em28xx *dev) | |||
1764 | video_device_release(dev->vdev); | 1679 | video_device_release(dev->vdev); |
1765 | dev->vdev = NULL; | 1680 | dev->vdev = NULL; |
1766 | } | 1681 | } |
1767 | em28xx_i2c_unregister(dev); | ||
1768 | usb_put_dev(dev->udev); | ||
1769 | |||
1770 | /* Mark device as unused */ | ||
1771 | em28xx_devused &= ~(1<<dev->devno); | ||
1772 | } | 1682 | } |
1773 | 1683 | ||
1774 | /* | 1684 | /* |
@@ -2018,44 +1928,6 @@ static struct video_device em28xx_radio_template = { | |||
2018 | /******************************** usb interface ******************************/ | 1928 | /******************************** usb interface ******************************/ |
2019 | 1929 | ||
2020 | 1930 | ||
2021 | static LIST_HEAD(em28xx_extension_devlist); | ||
2022 | static DEFINE_MUTEX(em28xx_extension_devlist_lock); | ||
2023 | |||
2024 | int em28xx_register_extension(struct em28xx_ops *ops) | ||
2025 | { | ||
2026 | struct em28xx *dev = NULL; | ||
2027 | |||
2028 | mutex_lock(&em28xx_devlist_mutex); | ||
2029 | mutex_lock(&em28xx_extension_devlist_lock); | ||
2030 | list_add_tail(&ops->next, &em28xx_extension_devlist); | ||
2031 | list_for_each_entry(dev, &em28xx_devlist, devlist) { | ||
2032 | if (dev) | ||
2033 | ops->init(dev); | ||
2034 | } | ||
2035 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); | ||
2036 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
2037 | mutex_unlock(&em28xx_devlist_mutex); | ||
2038 | return 0; | ||
2039 | } | ||
2040 | EXPORT_SYMBOL(em28xx_register_extension); | ||
2041 | |||
2042 | void em28xx_unregister_extension(struct em28xx_ops *ops) | ||
2043 | { | ||
2044 | struct em28xx *dev = NULL; | ||
2045 | |||
2046 | mutex_lock(&em28xx_devlist_mutex); | ||
2047 | list_for_each_entry(dev, &em28xx_devlist, devlist) { | ||
2048 | if (dev) | ||
2049 | ops->fini(dev); | ||
2050 | } | ||
2051 | |||
2052 | mutex_lock(&em28xx_extension_devlist_lock); | ||
2053 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); | ||
2054 | list_del(&ops->next); | ||
2055 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
2056 | mutex_unlock(&em28xx_devlist_mutex); | ||
2057 | } | ||
2058 | EXPORT_SYMBOL(em28xx_unregister_extension); | ||
2059 | 1931 | ||
2060 | static struct video_device *em28xx_vdev_init(struct em28xx *dev, | 1932 | static struct video_device *em28xx_vdev_init(struct em28xx *dev, |
2061 | const struct video_device *template, | 1933 | const struct video_device *template, |
@@ -2078,7 +1950,45 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, | |||
2078 | return vfd; | 1950 | return vfd; |
2079 | } | 1951 | } |
2080 | 1952 | ||
2081 | static int register_analog_devices(struct em28xx *dev) | 1953 | int em28xx_analog_config(struct em28xx *dev) |
1954 | { | ||
1955 | printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n", | ||
1956 | dev->name, | ||
1957 | (EM28XX_VERSION_CODE >> 16) & 0xff, | ||
1958 | (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); | ||
1959 | |||
1960 | /* Analog specific initialization */ | ||
1961 | dev->format = &format[0]; | ||
1962 | video_mux(dev, 0); | ||
1963 | |||
1964 | /* enable vbi capturing */ | ||
1965 | |||
1966 | /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ | ||
1967 | /* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ | ||
1968 | em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); | ||
1969 | |||
1970 | dev->mute = 1; /* maybe not the right place... */ | ||
1971 | dev->volume = 0x1f; | ||
1972 | |||
1973 | em28xx_set_outfmt(dev); | ||
1974 | em28xx_colorlevels_set_default(dev); | ||
1975 | em28xx_compression_disable(dev); | ||
1976 | |||
1977 | /* set default norm */ | ||
1978 | dev->norm = em28xx_video_template.current_norm; | ||
1979 | dev->width = norm_maxw(dev); | ||
1980 | dev->height = norm_maxh(dev); | ||
1981 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | ||
1982 | dev->hscale = 0; | ||
1983 | dev->vscale = 0; | ||
1984 | |||
1985 | /* FIXME: This is a very bad hack! Not all devices have TV on input 2 */ | ||
1986 | dev->ctl_input = 2; | ||
1987 | |||
1988 | return 0; | ||
1989 | } | ||
1990 | |||
1991 | int em28xx_register_analog_devices(struct em28xx *dev) | ||
2082 | { | 1992 | { |
2083 | int ret; | 1993 | int ret; |
2084 | 1994 | ||
@@ -2130,440 +2040,3 @@ static int register_analog_devices(struct em28xx *dev) | |||
2130 | 2040 | ||
2131 | return 0; | 2041 | return 0; |
2132 | } | 2042 | } |
2133 | |||
2134 | |||
2135 | /* | ||
2136 | * em28xx_init_dev() | ||
2137 | * allocates and inits the device structs, registers i2c bus and v4l device | ||
2138 | */ | ||
2139 | static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | ||
2140 | int minor) | ||
2141 | { | ||
2142 | struct em28xx_ops *ops = NULL; | ||
2143 | struct em28xx *dev = *devhandle; | ||
2144 | int retval = -ENOMEM; | ||
2145 | int errCode; | ||
2146 | unsigned int maxh, maxw; | ||
2147 | |||
2148 | dev->udev = udev; | ||
2149 | mutex_init(&dev->ctrl_urb_lock); | ||
2150 | spin_lock_init(&dev->slock); | ||
2151 | init_waitqueue_head(&dev->open); | ||
2152 | init_waitqueue_head(&dev->wait_frame); | ||
2153 | init_waitqueue_head(&dev->wait_stream); | ||
2154 | |||
2155 | dev->em28xx_write_regs = em28xx_write_regs; | ||
2156 | dev->em28xx_read_reg = em28xx_read_reg; | ||
2157 | dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; | ||
2158 | dev->em28xx_write_regs_req = em28xx_write_regs_req; | ||
2159 | dev->em28xx_read_reg_req = em28xx_read_reg_req; | ||
2160 | dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; | ||
2161 | dev->format = &format[0]; | ||
2162 | |||
2163 | em28xx_pre_card_setup(dev); | ||
2164 | |||
2165 | errCode = em28xx_config(dev); | ||
2166 | if (errCode) { | ||
2167 | em28xx_errdev("error configuring device\n"); | ||
2168 | return -ENOMEM; | ||
2169 | } | ||
2170 | |||
2171 | /* register i2c bus */ | ||
2172 | errCode = em28xx_i2c_register(dev); | ||
2173 | if (errCode < 0) { | ||
2174 | em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", | ||
2175 | __func__, errCode); | ||
2176 | return errCode; | ||
2177 | } | ||
2178 | |||
2179 | /* Do board specific init and eeprom reading */ | ||
2180 | em28xx_card_setup(dev); | ||
2181 | |||
2182 | /* Configure audio */ | ||
2183 | errCode = em28xx_audio_setup(dev); | ||
2184 | if (errCode < 0) { | ||
2185 | em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", | ||
2186 | __func__, errCode); | ||
2187 | } | ||
2188 | |||
2189 | /* configure the device */ | ||
2190 | em28xx_config_i2c(dev); | ||
2191 | |||
2192 | /* set default norm */ | ||
2193 | dev->norm = em28xx_video_template.current_norm; | ||
2194 | |||
2195 | maxw = norm_maxw(dev); | ||
2196 | maxh = norm_maxh(dev); | ||
2197 | |||
2198 | /* set default image size */ | ||
2199 | dev->width = maxw; | ||
2200 | dev->height = maxh; | ||
2201 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | ||
2202 | dev->hscale = 0; | ||
2203 | dev->vscale = 0; | ||
2204 | dev->ctl_input = 2; | ||
2205 | |||
2206 | errCode = em28xx_config(dev); | ||
2207 | if (errCode < 0) { | ||
2208 | em28xx_errdev("%s: em28xx_config - errCode [%d]!\n", | ||
2209 | __func__, errCode); | ||
2210 | return errCode; | ||
2211 | } | ||
2212 | |||
2213 | /* init video dma queues */ | ||
2214 | INIT_LIST_HEAD(&dev->vidq.active); | ||
2215 | INIT_LIST_HEAD(&dev->vidq.queued); | ||
2216 | |||
2217 | |||
2218 | if (dev->board.has_msp34xx) { | ||
2219 | /* Send a reset to other chips via gpio */ | ||
2220 | errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); | ||
2221 | if (errCode < 0) { | ||
2222 | em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n", | ||
2223 | __func__, errCode); | ||
2224 | return errCode; | ||
2225 | } | ||
2226 | msleep(3); | ||
2227 | |||
2228 | errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); | ||
2229 | if (errCode < 0) { | ||
2230 | em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n", | ||
2231 | __func__, errCode); | ||
2232 | return errCode; | ||
2233 | } | ||
2234 | msleep(3); | ||
2235 | } | ||
2236 | |||
2237 | video_mux(dev, 0); | ||
2238 | |||
2239 | mutex_lock(&em28xx_devlist_mutex); | ||
2240 | list_add_tail(&dev->devlist, &em28xx_devlist); | ||
2241 | retval = register_analog_devices(dev); | ||
2242 | if (retval < 0) { | ||
2243 | em28xx_release_resources(dev); | ||
2244 | mutex_unlock(&em28xx_devlist_mutex); | ||
2245 | goto fail_reg_devices; | ||
2246 | } | ||
2247 | |||
2248 | mutex_lock(&em28xx_extension_devlist_lock); | ||
2249 | if (!list_empty(&em28xx_extension_devlist)) { | ||
2250 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||
2251 | if (ops->id) | ||
2252 | ops->init(dev); | ||
2253 | } | ||
2254 | } | ||
2255 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
2256 | mutex_unlock(&em28xx_devlist_mutex); | ||
2257 | |||
2258 | /* Save some power by putting tuner to sleep */ | ||
2259 | em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); | ||
2260 | |||
2261 | return 0; | ||
2262 | |||
2263 | fail_reg_devices: | ||
2264 | return retval; | ||
2265 | } | ||
2266 | |||
2267 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
2268 | static void request_module_async(struct work_struct *work) | ||
2269 | { | ||
2270 | struct em28xx *dev = container_of(work, | ||
2271 | struct em28xx, request_module_wk); | ||
2272 | |||
2273 | if (dev->has_audio_class) | ||
2274 | request_module("snd-usb-audio"); | ||
2275 | else if (dev->has_alsa_audio) | ||
2276 | request_module("em28xx-alsa"); | ||
2277 | |||
2278 | if (dev->board.has_dvb) | ||
2279 | request_module("em28xx-dvb"); | ||
2280 | } | ||
2281 | |||
2282 | static void request_modules(struct em28xx *dev) | ||
2283 | { | ||
2284 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
2285 | schedule_work(&dev->request_module_wk); | ||
2286 | } | ||
2287 | #else | ||
2288 | #define request_modules(dev) | ||
2289 | #endif /* CONFIG_MODULES */ | ||
2290 | |||
2291 | /* | ||
2292 | * em28xx_usb_probe() | ||
2293 | * checks for supported devices | ||
2294 | */ | ||
2295 | static int em28xx_usb_probe(struct usb_interface *interface, | ||
2296 | const struct usb_device_id *id) | ||
2297 | { | ||
2298 | const struct usb_endpoint_descriptor *endpoint; | ||
2299 | struct usb_device *udev; | ||
2300 | struct usb_interface *uif; | ||
2301 | struct em28xx *dev = NULL; | ||
2302 | int retval = -ENODEV; | ||
2303 | int i, nr, ifnum, isoc_pipe; | ||
2304 | char *speed; | ||
2305 | char descr[255] = ""; | ||
2306 | |||
2307 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
2308 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | ||
2309 | |||
2310 | /* Check to see next free device and mark as used */ | ||
2311 | nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); | ||
2312 | em28xx_devused |= 1<<nr; | ||
2313 | |||
2314 | /* Don't register audio interfaces */ | ||
2315 | if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { | ||
2316 | em28xx_err(DRIVER_NAME " audio device (%04x:%04x): " | ||
2317 | "interface %i, class %i\n", | ||
2318 | le16_to_cpu(udev->descriptor.idVendor), | ||
2319 | le16_to_cpu(udev->descriptor.idProduct), | ||
2320 | ifnum, | ||
2321 | interface->altsetting[0].desc.bInterfaceClass); | ||
2322 | |||
2323 | em28xx_devused &= ~(1<<nr); | ||
2324 | return -ENODEV; | ||
2325 | } | ||
2326 | |||
2327 | endpoint = &interface->cur_altsetting->endpoint[0].desc; | ||
2328 | |||
2329 | /* check if the device has the iso in endpoint at the correct place */ | ||
2330 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
2331 | USB_ENDPOINT_XFER_ISOC && | ||
2332 | (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) | ||
2333 | { | ||
2334 | /* It's a newer em2874/em2875 device */ | ||
2335 | isoc_pipe = 0; | ||
2336 | } else { | ||
2337 | int check_interface = 1; | ||
2338 | isoc_pipe = 1; | ||
2339 | endpoint = &interface->cur_altsetting->endpoint[1].desc; | ||
2340 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != | ||
2341 | USB_ENDPOINT_XFER_ISOC) | ||
2342 | check_interface = 0; | ||
2343 | |||
2344 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) | ||
2345 | check_interface = 0; | ||
2346 | |||
2347 | if (!check_interface) { | ||
2348 | em28xx_err(DRIVER_NAME " video device (%04x:%04x): " | ||
2349 | "interface %i, class %i found.\n", | ||
2350 | le16_to_cpu(udev->descriptor.idVendor), | ||
2351 | le16_to_cpu(udev->descriptor.idProduct), | ||
2352 | ifnum, | ||
2353 | interface->altsetting[0].desc.bInterfaceClass); | ||
2354 | |||
2355 | em28xx_err(DRIVER_NAME " This is an anciliary " | ||
2356 | "interface not used by the driver\n"); | ||
2357 | |||
2358 | em28xx_devused &= ~(1<<nr); | ||
2359 | return -ENODEV; | ||
2360 | } | ||
2361 | } | ||
2362 | |||
2363 | switch (udev->speed) { | ||
2364 | case USB_SPEED_LOW: | ||
2365 | speed = "1.5"; | ||
2366 | break; | ||
2367 | case USB_SPEED_UNKNOWN: | ||
2368 | case USB_SPEED_FULL: | ||
2369 | speed = "12"; | ||
2370 | break; | ||
2371 | case USB_SPEED_HIGH: | ||
2372 | speed = "480"; | ||
2373 | break; | ||
2374 | default: | ||
2375 | speed = "unknown"; | ||
2376 | } | ||
2377 | |||
2378 | if (udev->manufacturer) | ||
2379 | strlcpy(descr, udev->manufacturer, sizeof(descr)); | ||
2380 | |||
2381 | if (udev->product) { | ||
2382 | if (*descr) | ||
2383 | strlcat(descr, " ", sizeof(descr)); | ||
2384 | strlcat(descr, udev->product, sizeof(descr)); | ||
2385 | } | ||
2386 | if (*descr) | ||
2387 | strlcat(descr, " ", sizeof(descr)); | ||
2388 | |||
2389 | printk(DRIVER_NAME ": New device %s@ %s Mbps " | ||
2390 | "(%04x:%04x, interface %d, class %d)\n", | ||
2391 | descr, | ||
2392 | speed, | ||
2393 | le16_to_cpu(udev->descriptor.idVendor), | ||
2394 | le16_to_cpu(udev->descriptor.idProduct), | ||
2395 | ifnum, | ||
2396 | interface->altsetting->desc.bInterfaceNumber); | ||
2397 | |||
2398 | if (nr >= EM28XX_MAXBOARDS) { | ||
2399 | printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", | ||
2400 | EM28XX_MAXBOARDS); | ||
2401 | em28xx_devused &= ~(1<<nr); | ||
2402 | return -ENOMEM; | ||
2403 | } | ||
2404 | |||
2405 | /* allocate memory for our device state and initialize it */ | ||
2406 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
2407 | if (dev == NULL) { | ||
2408 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | ||
2409 | em28xx_devused &= ~(1<<nr); | ||
2410 | return -ENOMEM; | ||
2411 | } | ||
2412 | |||
2413 | snprintf(dev->name, 29, "em28xx #%d", nr); | ||
2414 | dev->devno = nr; | ||
2415 | dev->model = id->driver_info; | ||
2416 | dev->alt = -1; | ||
2417 | |||
2418 | /* Checks if audio is provided by some interface */ | ||
2419 | for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { | ||
2420 | uif = udev->config->interface[i]; | ||
2421 | if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { | ||
2422 | dev->has_audio_class = 1; | ||
2423 | break; | ||
2424 | } | ||
2425 | } | ||
2426 | |||
2427 | /* compute alternate max packet sizes */ | ||
2428 | uif = udev->actconfig->interface[0]; | ||
2429 | |||
2430 | dev->num_alt = uif->num_altsetting; | ||
2431 | em28xx_videodbg("Alternate settings: %i\n", dev->num_alt); | ||
2432 | /* dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */ | ||
2433 | dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); | ||
2434 | |||
2435 | if (dev->alt_max_pkt_size == NULL) { | ||
2436 | em28xx_errdev("out of memory!\n"); | ||
2437 | em28xx_devused &= ~(1<<nr); | ||
2438 | kfree(dev); | ||
2439 | return -ENOMEM; | ||
2440 | } | ||
2441 | |||
2442 | for (i = 0; i < dev->num_alt ; i++) { | ||
2443 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. | ||
2444 | wMaxPacketSize); | ||
2445 | dev->alt_max_pkt_size[i] = | ||
2446 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
2447 | em28xx_videodbg("Alternate setting %i, max size= %i\n", i, | ||
2448 | dev->alt_max_pkt_size[i]); | ||
2449 | } | ||
2450 | |||
2451 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) | ||
2452 | dev->model = card[nr]; | ||
2453 | |||
2454 | /* allocate device struct */ | ||
2455 | mutex_init(&dev->lock); | ||
2456 | mutex_lock(&dev->lock); | ||
2457 | retval = em28xx_init_dev(&dev, udev, nr); | ||
2458 | if (retval) { | ||
2459 | em28xx_devused &= ~(1<<dev->devno); | ||
2460 | kfree(dev); | ||
2461 | |||
2462 | return retval; | ||
2463 | } | ||
2464 | |||
2465 | /* save our data pointer in this interface device */ | ||
2466 | usb_set_intfdata(interface, dev); | ||
2467 | |||
2468 | request_modules(dev); | ||
2469 | |||
2470 | /* Should be the last thing to do, to avoid newer udev's to | ||
2471 | open the device before fully initializing it | ||
2472 | */ | ||
2473 | mutex_unlock(&dev->lock); | ||
2474 | |||
2475 | return 0; | ||
2476 | } | ||
2477 | |||
2478 | /* | ||
2479 | * em28xx_usb_disconnect() | ||
2480 | * called when the device gets diconencted | ||
2481 | * video device will be unregistered on v4l2_close in case it is still open | ||
2482 | */ | ||
2483 | static void em28xx_usb_disconnect(struct usb_interface *interface) | ||
2484 | { | ||
2485 | struct em28xx *dev; | ||
2486 | struct em28xx_ops *ops = NULL; | ||
2487 | |||
2488 | dev = usb_get_intfdata(interface); | ||
2489 | usb_set_intfdata(interface, NULL); | ||
2490 | |||
2491 | if (!dev) | ||
2492 | return; | ||
2493 | |||
2494 | em28xx_info("disconnecting %s\n", dev->vdev->name); | ||
2495 | |||
2496 | /* wait until all current v4l2 io is finished then deallocate | ||
2497 | resources */ | ||
2498 | mutex_lock(&dev->lock); | ||
2499 | |||
2500 | wake_up_interruptible_all(&dev->open); | ||
2501 | |||
2502 | if (dev->users) { | ||
2503 | em28xx_warn | ||
2504 | ("device /dev/video%d is open! Deregistration and memory " | ||
2505 | "deallocation are deferred on close.\n", | ||
2506 | dev->vdev->num); | ||
2507 | |||
2508 | dev->state |= DEV_MISCONFIGURED; | ||
2509 | em28xx_uninit_isoc(dev); | ||
2510 | dev->state |= DEV_DISCONNECTED; | ||
2511 | wake_up_interruptible(&dev->wait_frame); | ||
2512 | wake_up_interruptible(&dev->wait_stream); | ||
2513 | } else { | ||
2514 | dev->state |= DEV_DISCONNECTED; | ||
2515 | em28xx_release_resources(dev); | ||
2516 | } | ||
2517 | mutex_unlock(&dev->lock); | ||
2518 | |||
2519 | mutex_lock(&em28xx_extension_devlist_lock); | ||
2520 | if (!list_empty(&em28xx_extension_devlist)) { | ||
2521 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||
2522 | ops->fini(dev); | ||
2523 | } | ||
2524 | } | ||
2525 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
2526 | |||
2527 | if (!dev->users) { | ||
2528 | kfree(dev->alt_max_pkt_size); | ||
2529 | kfree(dev); | ||
2530 | } | ||
2531 | } | ||
2532 | |||
2533 | static struct usb_driver em28xx_usb_driver = { | ||
2534 | .name = "em28xx", | ||
2535 | .probe = em28xx_usb_probe, | ||
2536 | .disconnect = em28xx_usb_disconnect, | ||
2537 | .id_table = em28xx_id_table, | ||
2538 | }; | ||
2539 | |||
2540 | static int __init em28xx_module_init(void) | ||
2541 | { | ||
2542 | int result; | ||
2543 | |||
2544 | printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n", | ||
2545 | (EM28XX_VERSION_CODE >> 16) & 0xff, | ||
2546 | (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); | ||
2547 | #ifdef SNAPSHOT | ||
2548 | printk(KERN_INFO DRIVER_NAME " snapshot date %04d-%02d-%02d\n", | ||
2549 | SNAPSHOT / 10000, (SNAPSHOT / 100) % 100, SNAPSHOT % 100); | ||
2550 | #endif | ||
2551 | |||
2552 | /* register this driver with the USB subsystem */ | ||
2553 | result = usb_register(&em28xx_usb_driver); | ||
2554 | if (result) | ||
2555 | em28xx_err(DRIVER_NAME | ||
2556 | " usb_register failed. Error number %d.\n", result); | ||
2557 | |||
2558 | return result; | ||
2559 | } | ||
2560 | |||
2561 | static void __exit em28xx_module_exit(void) | ||
2562 | { | ||
2563 | /* deregister this driver with the USB subsystem */ | ||
2564 | usb_deregister(&em28xx_usb_driver); | ||
2565 | } | ||
2566 | |||
2567 | module_init(em28xx_module_init); | ||
2568 | module_exit(em28xx_module_exit); | ||
2569 | |||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 100f27819cdc..c8e71edbfea7 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -581,10 +581,21 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, | |||
581 | void em28xx_uninit_isoc(struct em28xx *dev); | 581 | void em28xx_uninit_isoc(struct em28xx *dev); |
582 | int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); | 582 | int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); |
583 | int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); | 583 | int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); |
584 | 584 | void em28xx_wake_i2c(struct em28xx *dev); | |
585 | /* Provided by em28xx-video.c */ | 585 | void em28xx_remove_from_devlist(struct em28xx *dev); |
586 | void em28xx_add_into_devlist(struct em28xx *dev); | ||
587 | struct em28xx *em28xx_get_device(struct inode *inode, | ||
588 | enum v4l2_buf_type *fh_type, | ||
589 | int *has_radio); | ||
586 | int em28xx_register_extension(struct em28xx_ops *dev); | 590 | int em28xx_register_extension(struct em28xx_ops *dev); |
587 | void em28xx_unregister_extension(struct em28xx_ops *dev); | 591 | void em28xx_unregister_extension(struct em28xx_ops *dev); |
592 | void em28xx_init_extension(struct em28xx *dev); | ||
593 | void em28xx_close_extension(struct em28xx *dev); | ||
594 | |||
595 | /* Provided by em28xx-video.c */ | ||
596 | int em28xx_analog_config(struct em28xx *dev); | ||
597 | int em28xx_register_analog_devices(struct em28xx *dev); | ||
598 | void em28xx_release_analog_resources(struct em28xx *dev); | ||
588 | 599 | ||
589 | /* Provided by em28xx-cards.c */ | 600 | /* Provided by em28xx-cards.c */ |
590 | extern int em2800_variant_detect(struct usb_device *udev, int model); | 601 | extern int em2800_variant_detect(struct usb_device *udev, int model); |
@@ -595,6 +606,7 @@ extern struct usb_device_id em28xx_id_table[]; | |||
595 | extern const unsigned int em28xx_bcount; | 606 | extern const unsigned int em28xx_bcount; |
596 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); | 607 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); |
597 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg); | 608 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg); |
609 | void em28xx_release_resources(struct em28xx *dev); | ||
598 | 610 | ||
599 | /* Provided by em28xx-input.c */ | 611 | /* Provided by em28xx-input.c */ |
600 | int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); | 612 | int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); |