diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-10-16 06:13:07 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:40:44 -0500 |
commit | a511ba947600ae263f8c29c86020ba66a901d3e5 (patch) | |
tree | d27d646a98aa45f92a2df78eb66d7cfe0f446ff6 /drivers/media/video/gspca/ov519.c | |
parent | eea85b0a629970d462481a80e1d45f4d71fe797f (diff) |
V4L/DVB (13178): gspca: Add support for Winbond W9967CF and W9968CF camera's
This patch adds support to gspca for the Winbond W9967CF and W9968CF
camera's. This is mostly a port of the existing v4l1 driver to gspca
(making it v4l2). But this also features fixes to the bitbanging i2c code
(send a nack not an ack after reading the last byte of a transfer), which
gets rid of the weird errors which were being seen there, and of
the smbus_refresh() hack to get around these errors.
Also the vstart settings have been tweaked to work with different
frequency filter settings.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/ov519.c')
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 115 |
1 files changed, 94 insertions, 21 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 4d6a762a6f3d..994a5e927d2d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -64,6 +64,7 @@ struct sd { | |||
64 | #define BRIDGE_OV518PLUS 3 | 64 | #define BRIDGE_OV518PLUS 3 |
65 | #define BRIDGE_OV519 4 | 65 | #define BRIDGE_OV519 4 |
66 | #define BRIDGE_OVFX2 5 | 66 | #define BRIDGE_OVFX2 5 |
67 | #define BRIDGE_W9968CF 6 | ||
67 | #define BRIDGE_MASK 7 | 68 | #define BRIDGE_MASK 7 |
68 | 69 | ||
69 | char invert_led; | 70 | char invert_led; |
@@ -98,8 +99,17 @@ struct sd { | |||
98 | #define SEN_OV7670 9 | 99 | #define SEN_OV7670 9 |
99 | #define SEN_OV76BE 10 | 100 | #define SEN_OV76BE 10 |
100 | #define SEN_OV8610 11 | 101 | #define SEN_OV8610 11 |
102 | |||
103 | u8 sensor_addr; | ||
104 | int sensor_width; | ||
105 | int sensor_height; | ||
101 | }; | 106 | }; |
102 | 107 | ||
108 | /* Note this is a bit of a hack, but the w9968cf driver needs the code for all | ||
109 | the ov sensors which is already present here. When we have the time we | ||
110 | really should move the sensor drivers to v4l2 sub drivers. */ | ||
111 | #include "w996Xcf.c" | ||
112 | |||
103 | /* V4L2 controls supported by the driver */ | 113 | /* V4L2 controls supported by the driver */ |
104 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 114 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
105 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 115 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
@@ -1471,6 +1481,7 @@ static const struct ov_i2c_regvals norm_7610[] = { | |||
1471 | }; | 1481 | }; |
1472 | 1482 | ||
1473 | static const struct ov_i2c_regvals norm_7620[] = { | 1483 | static const struct ov_i2c_regvals norm_7620[] = { |
1484 | { 0x12, 0x80 }, /* reset */ | ||
1474 | { 0x00, 0x00 }, /* gain */ | 1485 | { 0x00, 0x00 }, /* gain */ |
1475 | { 0x01, 0x80 }, /* blue gain */ | 1486 | { 0x01, 0x80 }, /* blue gain */ |
1476 | { 0x02, 0x80 }, /* red gain */ | 1487 | { 0x02, 0x80 }, /* red gain */ |
@@ -1835,10 +1846,9 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) | |||
1835 | } | 1846 | } |
1836 | 1847 | ||
1837 | /* Write a OV519 register */ | 1848 | /* Write a OV519 register */ |
1838 | static int reg_w(struct sd *sd, __u16 index, __u8 value) | 1849 | static int reg_w(struct sd *sd, __u16 index, __u16 value) |
1839 | { | 1850 | { |
1840 | int ret; | 1851 | int ret, req = 0; |
1841 | int req; | ||
1842 | 1852 | ||
1843 | switch (sd->bridge) { | 1853 | switch (sd->bridge) { |
1844 | case BRIDGE_OV511: | 1854 | case BRIDGE_OV511: |
@@ -1846,11 +1856,14 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) | |||
1846 | req = 2; | 1856 | req = 2; |
1847 | break; | 1857 | break; |
1848 | case BRIDGE_OVFX2: | 1858 | case BRIDGE_OVFX2: |
1859 | req = 0x0a; | ||
1860 | /* fall through */ | ||
1861 | case BRIDGE_W9968CF: | ||
1849 | ret = usb_control_msg(sd->gspca_dev.dev, | 1862 | ret = usb_control_msg(sd->gspca_dev.dev, |
1850 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | 1863 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), |
1851 | 0x0a, | 1864 | req, |
1852 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1865 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
1853 | (__u16)value, index, NULL, 0, 500); | 1866 | value, index, NULL, 0, 500); |
1854 | goto leave; | 1867 | goto leave; |
1855 | default: | 1868 | default: |
1856 | req = 1; | 1869 | req = 1; |
@@ -1864,12 +1877,17 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) | |||
1864 | 0, index, | 1877 | 0, index, |
1865 | sd->gspca_dev.usb_buf, 1, 500); | 1878 | sd->gspca_dev.usb_buf, 1, 500); |
1866 | leave: | 1879 | leave: |
1867 | if (ret < 0) | 1880 | if (ret < 0) { |
1868 | PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); | 1881 | PDEBUG(D_ERR, "Write reg 0x%04x -> [0x%02x] failed", |
1869 | return ret; | 1882 | value, index); |
1883 | return ret; | ||
1884 | } | ||
1885 | |||
1886 | PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); | ||
1887 | return 0; | ||
1870 | } | 1888 | } |
1871 | 1889 | ||
1872 | /* Read from a OV519 register */ | 1890 | /* Read from a OV519 register, note not valid for the w9968cf!! */ |
1873 | /* returns: negative is error, pos or zero is data */ | 1891 | /* returns: negative is error, pos or zero is data */ |
1874 | static int reg_r(struct sd *sd, __u16 index) | 1892 | static int reg_r(struct sd *sd, __u16 index) |
1875 | { | 1893 | { |
@@ -1894,10 +1912,12 @@ static int reg_r(struct sd *sd, __u16 index) | |||
1894 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1912 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
1895 | 0, index, sd->gspca_dev.usb_buf, 1, 500); | 1913 | 0, index, sd->gspca_dev.usb_buf, 1, 500); |
1896 | 1914 | ||
1897 | if (ret >= 0) | 1915 | if (ret >= 0) { |
1898 | ret = sd->gspca_dev.usb_buf[0]; | 1916 | ret = sd->gspca_dev.usb_buf[0]; |
1899 | else | 1917 | PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); |
1918 | } else | ||
1900 | PDEBUG(D_ERR, "Read reg [0x%02x] failed", index); | 1919 | PDEBUG(D_ERR, "Read reg [0x%02x] failed", index); |
1920 | |||
1901 | return ret; | 1921 | return ret; |
1902 | } | 1922 | } |
1903 | 1923 | ||
@@ -1917,6 +1937,7 @@ static int reg_r8(struct sd *sd, | |||
1917 | ret = sd->gspca_dev.usb_buf[0]; | 1937 | ret = sd->gspca_dev.usb_buf[0]; |
1918 | else | 1938 | else |
1919 | PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index); | 1939 | PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index); |
1940 | |||
1920 | return ret; | 1941 | return ret; |
1921 | } | 1942 | } |
1922 | 1943 | ||
@@ -1962,9 +1983,12 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) | |||
1962 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1983 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
1963 | 0, index, | 1984 | 0, index, |
1964 | sd->gspca_dev.usb_buf, n, 500); | 1985 | sd->gspca_dev.usb_buf, n, 500); |
1965 | if (ret < 0) | 1986 | if (ret < 0) { |
1966 | PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); | 1987 | PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); |
1967 | return ret; | 1988 | return ret; |
1989 | } | ||
1990 | |||
1991 | return 0; | ||
1968 | } | 1992 | } |
1969 | 1993 | ||
1970 | static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) | 1994 | static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) |
@@ -2156,12 +2180,13 @@ static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) | |||
2156 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 2180 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
2157 | (__u16)value, (__u16)reg, NULL, 0, 500); | 2181 | (__u16)value, (__u16)reg, NULL, 0, 500); |
2158 | 2182 | ||
2159 | if (ret >= 0) | 2183 | if (ret < 0) { |
2160 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); | ||
2161 | else | ||
2162 | PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); | 2184 | PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); |
2185 | return ret; | ||
2186 | } | ||
2163 | 2187 | ||
2164 | return ret; | 2188 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); |
2189 | return 0; | ||
2165 | } | 2190 | } |
2166 | 2191 | ||
2167 | static int ovfx2_i2c_r(struct sd *sd, __u8 reg) | 2192 | static int ovfx2_i2c_r(struct sd *sd, __u8 reg) |
@@ -2195,6 +2220,8 @@ static int i2c_w(struct sd *sd, __u8 reg, __u8 value) | |||
2195 | return ov518_i2c_w(sd, reg, value); | 2220 | return ov518_i2c_w(sd, reg, value); |
2196 | case BRIDGE_OVFX2: | 2221 | case BRIDGE_OVFX2: |
2197 | return ovfx2_i2c_w(sd, reg, value); | 2222 | return ovfx2_i2c_w(sd, reg, value); |
2223 | case BRIDGE_W9968CF: | ||
2224 | return w9968cf_i2c_w(sd, reg, value); | ||
2198 | } | 2225 | } |
2199 | return -1; /* Should never happen */ | 2226 | return -1; /* Should never happen */ |
2200 | } | 2227 | } |
@@ -2211,6 +2238,8 @@ static int i2c_r(struct sd *sd, __u8 reg) | |||
2211 | return ov518_i2c_r(sd, reg); | 2238 | return ov518_i2c_r(sd, reg); |
2212 | case BRIDGE_OVFX2: | 2239 | case BRIDGE_OVFX2: |
2213 | return ovfx2_i2c_r(sd, reg); | 2240 | return ovfx2_i2c_r(sd, reg); |
2241 | case BRIDGE_W9968CF: | ||
2242 | return w9968cf_i2c_r(sd, reg); | ||
2214 | } | 2243 | } |
2215 | return -1; /* Should never happen */ | 2244 | return -1; /* Should never happen */ |
2216 | } | 2245 | } |
@@ -2241,6 +2270,8 @@ static int i2c_w_mask(struct sd *sd, | |||
2241 | * registers while the camera is streaming */ | 2270 | * registers while the camera is streaming */ |
2242 | static inline int ov51x_stop(struct sd *sd) | 2271 | static inline int ov51x_stop(struct sd *sd) |
2243 | { | 2272 | { |
2273 | int ret; | ||
2274 | |||
2244 | PDEBUG(D_STREAM, "stopping"); | 2275 | PDEBUG(D_STREAM, "stopping"); |
2245 | sd->stopped = 1; | 2276 | sd->stopped = 1; |
2246 | switch (sd->bridge) { | 2277 | switch (sd->bridge) { |
@@ -2254,6 +2285,11 @@ static inline int ov51x_stop(struct sd *sd) | |||
2254 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); | 2285 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); |
2255 | case BRIDGE_OVFX2: | 2286 | case BRIDGE_OVFX2: |
2256 | return reg_w_mask(sd, 0x0f, 0x00, 0x02); | 2287 | return reg_w_mask(sd, 0x0f, 0x00, 0x02); |
2288 | case BRIDGE_W9968CF: | ||
2289 | ret = reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ | ||
2290 | ret += reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ | ||
2291 | ret += reg_w(sd, 0x16, 0x0000); /* stop video capture */ | ||
2292 | return ret; | ||
2257 | } | 2293 | } |
2258 | 2294 | ||
2259 | return 0; | 2295 | return 0; |
@@ -2285,6 +2321,8 @@ static inline int ov51x_restart(struct sd *sd) | |||
2285 | return reg_w(sd, OV519_SYS_RESET1, 0x00); | 2321 | return reg_w(sd, OV519_SYS_RESET1, 0x00); |
2286 | case BRIDGE_OVFX2: | 2322 | case BRIDGE_OVFX2: |
2287 | return reg_w_mask(sd, 0x0f, 0x02, 0x02); | 2323 | return reg_w_mask(sd, 0x0f, 0x02, 0x02); |
2324 | case BRIDGE_W9968CF: | ||
2325 | return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ | ||
2288 | } | 2326 | } |
2289 | 2327 | ||
2290 | return 0; | 2328 | return 0; |
@@ -2338,8 +2376,13 @@ static int ov51x_set_slave_ids(struct sd *sd, | |||
2338 | { | 2376 | { |
2339 | int rc; | 2377 | int rc; |
2340 | 2378 | ||
2341 | if (sd->bridge == BRIDGE_OVFX2) | 2379 | switch (sd->bridge) { |
2380 | case BRIDGE_OVFX2: | ||
2342 | return reg_w(sd, OVFX2_I2C_ADDR, slave); | 2381 | return reg_w(sd, OVFX2_I2C_ADDR, slave); |
2382 | case BRIDGE_W9968CF: | ||
2383 | sd->sensor_addr = slave; | ||
2384 | return 0; | ||
2385 | } | ||
2343 | 2386 | ||
2344 | rc = reg_w(sd, R51x_I2C_W_SID, slave); | 2387 | rc = reg_w(sd, R51x_I2C_W_SID, slave); |
2345 | if (rc < 0) | 2388 | if (rc < 0) |
@@ -2920,6 +2963,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2920 | cam->bulk_nurbs = MAX_NURBS; | 2963 | cam->bulk_nurbs = MAX_NURBS; |
2921 | cam->bulk = 1; | 2964 | cam->bulk = 1; |
2922 | break; | 2965 | break; |
2966 | case BRIDGE_W9968CF: | ||
2967 | ret = w9968cf_configure(sd); | ||
2968 | cam->reverse_alts = 1; | ||
2969 | break; | ||
2923 | } | 2970 | } |
2924 | 2971 | ||
2925 | if (ret) | 2972 | if (ret) |
@@ -3005,6 +3052,16 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3005 | cam->nmodes = ARRAY_SIZE(ov519_sif_mode); | 3052 | cam->nmodes = ARRAY_SIZE(ov519_sif_mode); |
3006 | } | 3053 | } |
3007 | break; | 3054 | break; |
3055 | case BRIDGE_W9968CF: | ||
3056 | cam->cam_mode = w9968cf_vga_mode; | ||
3057 | cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); | ||
3058 | /* if (sd->sif) | ||
3059 | cam->nmodes--; */ | ||
3060 | |||
3061 | /* w9968cf needs initialisation once the sensor is known */ | ||
3062 | if (w9968cf_init(sd) < 0) | ||
3063 | goto error; | ||
3064 | break; | ||
3008 | } | 3065 | } |
3009 | sd->brightness = BRIGHTNESS_DEF; | 3066 | sd->brightness = BRIGHTNESS_DEF; |
3010 | if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) | 3067 | if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) |
@@ -3753,9 +3810,9 @@ static int set_ov_sensor_window(struct sd *sd) | |||
3753 | return ret; | 3810 | return ret; |
3754 | 3811 | ||
3755 | i2c_w(sd, 0x17, hwsbase); | 3812 | i2c_w(sd, 0x17, hwsbase); |
3756 | i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); | 3813 | i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); |
3757 | i2c_w(sd, 0x19, vwsbase); | 3814 | i2c_w(sd, 0x19, vwsbase); |
3758 | i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); | 3815 | i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); |
3759 | 3816 | ||
3760 | return 0; | 3817 | return 0; |
3761 | } | 3818 | } |
@@ -3766,6 +3823,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3766 | struct sd *sd = (struct sd *) gspca_dev; | 3823 | struct sd *sd = (struct sd *) gspca_dev; |
3767 | int ret = 0; | 3824 | int ret = 0; |
3768 | 3825 | ||
3826 | /* Default for most bridges, allow bridge_mode_init_regs to override */ | ||
3827 | sd->sensor_width = sd->gspca_dev.width; | ||
3828 | sd->sensor_height = sd->gspca_dev.height; | ||
3829 | |||
3769 | switch (sd->bridge) { | 3830 | switch (sd->bridge) { |
3770 | case BRIDGE_OV511: | 3831 | case BRIDGE_OV511: |
3771 | case BRIDGE_OV511PLUS: | 3832 | case BRIDGE_OV511PLUS: |
@@ -3779,6 +3840,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3779 | ret = ov519_mode_init_regs(sd); | 3840 | ret = ov519_mode_init_regs(sd); |
3780 | break; | 3841 | break; |
3781 | /* case BRIDGE_OVFX2: nothing to do */ | 3842 | /* case BRIDGE_OVFX2: nothing to do */ |
3843 | case BRIDGE_W9968CF: | ||
3844 | ret = w9968cf_mode_init_regs(sd); | ||
3845 | break; | ||
3782 | } | 3846 | } |
3783 | if (ret < 0) | 3847 | if (ret < 0) |
3784 | goto out; | 3848 | goto out; |
@@ -3980,6 +4044,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
3980 | case BRIDGE_OVFX2: | 4044 | case BRIDGE_OVFX2: |
3981 | ovfx2_pkt_scan(gspca_dev, frame, data, len); | 4045 | ovfx2_pkt_scan(gspca_dev, frame, data, len); |
3982 | break; | 4046 | break; |
4047 | case BRIDGE_W9968CF: | ||
4048 | w9968cf_pkt_scan(gspca_dev, frame, data, len); | ||
4049 | break; | ||
3983 | } | 4050 | } |
3984 | } | 4051 | } |
3985 | 4052 | ||
@@ -4275,8 +4342,12 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | |||
4275 | struct sd *sd = (struct sd *) gspca_dev; | 4342 | struct sd *sd = (struct sd *) gspca_dev; |
4276 | 4343 | ||
4277 | sd->freq = val; | 4344 | sd->freq = val; |
4278 | if (gspca_dev->streaming) | 4345 | if (gspca_dev->streaming) { |
4279 | setfreq(sd); | 4346 | setfreq(sd); |
4347 | /* Ugly but necessary */ | ||
4348 | if (sd->bridge == BRIDGE_W9968CF) | ||
4349 | w9968cf_set_crop_window(sd); | ||
4350 | } | ||
4280 | return 0; | 4351 | return 0; |
4281 | } | 4352 | } |
4282 | 4353 | ||
@@ -4332,6 +4403,7 @@ static const struct sd_desc sd_desc = { | |||
4332 | 4403 | ||
4333 | /* -- module initialisation -- */ | 4404 | /* -- module initialisation -- */ |
4334 | static const __devinitdata struct usb_device_id device_table[] = { | 4405 | static const __devinitdata struct usb_device_id device_table[] = { |
4406 | {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF }, | ||
4335 | {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, | 4407 | {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, |
4336 | {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, | 4408 | {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, |
4337 | {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, | 4409 | {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, |
@@ -4356,6 +4428,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
4356 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, | 4428 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, |
4357 | {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, | 4429 | {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, |
4358 | {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, | 4430 | {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, |
4431 | {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, | ||
4359 | {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, | 4432 | {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, |
4360 | {} | 4433 | {} |
4361 | }; | 4434 | }; |