Commit a511ba94 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent eea85b0a
...@@ -951,9 +951,13 @@ source "drivers/media/video/usbvideo/Kconfig" ...@@ -951,9 +951,13 @@ source "drivers/media/video/usbvideo/Kconfig"
source "drivers/media/video/et61x251/Kconfig" source "drivers/media/video/et61x251/Kconfig"
config VIDEO_OVCAMCHIP config VIDEO_OVCAMCHIP
tristate "OmniVision Camera Chip support" tristate "OmniVision Camera Chip support (DEPRECATED)"
depends on I2C && VIDEO_V4L1 depends on I2C && VIDEO_V4L1
---help--- ---help---
This driver is DEPRECATED please use the gspca ov519 module
instead. Note that for the ov511 / ov518 support of the gspca module
you need atleast version 0.6.0 of libv4l.
Support for the OmniVision OV6xxx and OV7xxx series of camera chips. Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
This driver is intended to be used with the ov511 and w9968cf USB This driver is intended to be used with the ov511 and w9968cf USB
camera drivers. camera drivers.
...@@ -962,9 +966,12 @@ config VIDEO_OVCAMCHIP ...@@ -962,9 +966,12 @@ config VIDEO_OVCAMCHIP
module will be called ovcamchip. module will be called ovcamchip.
config USB_W9968CF config USB_W9968CF
tristate "USB W996[87]CF JPEG Dual Mode Camera support" tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)"
depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
---help--- ---help---
This driver is DEPRECATED please use the gspca ov519 module
instead.
Say Y here if you want support for cameras based on OV681 or Say Y here if you want support for cameras based on OV681 or
Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
......
...@@ -76,10 +76,11 @@ config USB_GSPCA_MR97310A ...@@ -76,10 +76,11 @@ config USB_GSPCA_MR97310A
module will be called gspca_mr97310a. module will be called gspca_mr97310a.
config USB_GSPCA_OV519 config USB_GSPCA_OV519
tristate "OV519 USB Camera Driver" tristate "OV51x / OVFX2 / W996xCF USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA depends on VIDEO_V4L2 && USB_GSPCA
help help
Say Y here if you want support for cameras based on the OV519 chip. Say Y here if you want support for cameras based on one of these:
OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called gspca_ov519. module will be called gspca_ov519.
......
...@@ -475,10 +475,18 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) ...@@ -475,10 +475,18 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
: USB_ENDPOINT_XFER_ISOC; : USB_ENDPOINT_XFER_ISOC;
i = gspca_dev->alt; /* previous alt setting */ i = gspca_dev->alt; /* previous alt setting */
while (--i >= 0) { if (gspca_dev->cam.reverse_alts) {
ep = alt_xfer(&intf->altsetting[i], xfer); while (++i < gspca_dev->nbalt) {
if (ep) ep = alt_xfer(&intf->altsetting[i], xfer);
break; if (ep)
break;
}
} else {
while (--i >= 0) {
ep = alt_xfer(&intf->altsetting[i], xfer);
if (ep)
break;
}
} }
if (ep == NULL) { if (ep == NULL) {
err("no transfer endpoint found"); err("no transfer endpoint found");
...@@ -599,7 +607,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) ...@@ -599,7 +607,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
/* set the higher alternate setting and /* set the higher alternate setting and
* loop until urb submit succeeds */ * loop until urb submit succeeds */
gspca_dev->alt = gspca_dev->nbalt; if (gspca_dev->cam.reverse_alts)
gspca_dev->alt = 0;
else
gspca_dev->alt = gspca_dev->nbalt;
if (gspca_dev->sd_desc->isoc_init) { if (gspca_dev->sd_desc->isoc_init) {
ret = gspca_dev->sd_desc->isoc_init(gspca_dev); ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
if (ret < 0) if (ret < 0)
......
...@@ -58,6 +58,7 @@ struct cam { ...@@ -58,6 +58,7 @@ struct cam {
u8 npkt; /* number of packets in an ISOC message u8 npkt; /* number of packets in an ISOC message
* 0 is the default value: 32 packets */ * 0 is the default value: 32 packets */
u32 input_flags; /* value for ENUM_INPUT status flags */ u32 input_flags; /* value for ENUM_INPUT status flags */
char reverse_alts; /* Alt settings are in high to low order */
}; };
struct gspca_dev; struct gspca_dev;
......
...@@ -64,6 +64,7 @@ struct sd { ...@@ -64,6 +64,7 @@ struct sd {
#define BRIDGE_OV518PLUS 3 #define BRIDGE_OV518PLUS 3
#define BRIDGE_OV519 4 #define BRIDGE_OV519 4
#define BRIDGE_OVFX2 5 #define BRIDGE_OVFX2 5
#define BRIDGE_W9968CF 6
#define BRIDGE_MASK 7 #define BRIDGE_MASK 7
char invert_led; char invert_led;
...@@ -98,8 +99,17 @@ struct sd { ...@@ -98,8 +99,17 @@ struct sd {
#define SEN_OV7670 9 #define SEN_OV7670 9
#define SEN_OV76BE 10 #define SEN_OV76BE 10
#define SEN_OV8610 11 #define SEN_OV8610 11
u8 sensor_addr;
int sensor_width;
int sensor_height;
}; };
/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
the ov sensors which is already present here. When we have the time we
really should move the sensor drivers to v4l2 sub drivers. */
#include "w996Xcf.c"
/* V4L2 controls supported by the driver */ /* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
...@@ -1471,6 +1481,7 @@ static const struct ov_i2c_regvals norm_7610[] = { ...@@ -1471,6 +1481,7 @@ static const struct ov_i2c_regvals norm_7610[] = {
}; };
static const struct ov_i2c_regvals norm_7620[] = { static const struct ov_i2c_regvals norm_7620[] = {
{ 0x12, 0x80 }, /* reset */
{ 0x00, 0x00 }, /* gain */ { 0x00, 0x00 }, /* gain */
{ 0x01, 0x80 }, /* blue gain */ { 0x01, 0x80 }, /* blue gain */
{ 0x02, 0x80 }, /* red gain */ { 0x02, 0x80 }, /* red gain */
...@@ -1835,10 +1846,9 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) ...@@ -1835,10 +1846,9 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
} }
/* Write a OV519 register */ /* Write a OV519 register */
static int reg_w(struct sd *sd, __u16 index, __u8 value) static int reg_w(struct sd *sd, __u16 index, __u16 value)
{ {
int ret; int ret, req = 0;
int req;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
...@@ -1846,11 +1856,14 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) ...@@ -1846,11 +1856,14 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value)
req = 2; req = 2;
break; break;
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
req = 0x0a;
/* fall through */
case BRIDGE_W9968CF:
ret = usb_control_msg(sd->gspca_dev.dev, ret = usb_control_msg(sd->gspca_dev.dev,
usb_sndctrlpipe(sd->gspca_dev.dev, 0), usb_sndctrlpipe(sd->gspca_dev.dev, 0),
0x0a, req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
(__u16)value, index, NULL, 0, 500); value, index, NULL, 0, 500);
goto leave; goto leave;
default: default:
req = 1; req = 1;
...@@ -1864,12 +1877,17 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) ...@@ -1864,12 +1877,17 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value)
0, index, 0, index,
sd->gspca_dev.usb_buf, 1, 500); sd->gspca_dev.usb_buf, 1, 500);
leave: leave:
if (ret < 0) if (ret < 0) {
PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); PDEBUG(D_ERR, "Write reg 0x%04x -> [0x%02x] failed",
return ret; value, index);
return ret;
}
PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index);
return 0;
} }
/* Read from a OV519 register */ /* Read from a OV519 register, note not valid for the w9968cf!! */
/* returns: negative is error, pos or zero is data */ /* returns: negative is error, pos or zero is data */
static int reg_r(struct sd *sd, __u16 index) static int reg_r(struct sd *sd, __u16 index)
{ {
...@@ -1894,10 +1912,12 @@ static int reg_r(struct sd *sd, __u16 index) ...@@ -1894,10 +1912,12 @@ static int reg_r(struct sd *sd, __u16 index)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, sd->gspca_dev.usb_buf, 1, 500); 0, index, sd->gspca_dev.usb_buf, 1, 500);
if (ret >= 0) if (ret >= 0) {
ret = sd->gspca_dev.usb_buf[0]; ret = sd->gspca_dev.usb_buf[0];
else PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret);
} else
PDEBUG(D_ERR, "Read reg [0x%02x] failed", index); PDEBUG(D_ERR, "Read reg [0x%02x] failed", index);
return ret; return ret;
} }
...@@ -1917,6 +1937,7 @@ static int reg_r8(struct sd *sd, ...@@ -1917,6 +1937,7 @@ static int reg_r8(struct sd *sd,
ret = sd->gspca_dev.usb_buf[0]; ret = sd->gspca_dev.usb_buf[0];
else else
PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index); PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index);
return ret; return ret;
} }
...@@ -1962,9 +1983,12 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) ...@@ -1962,9 +1983,12 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, 0, index,
sd->gspca_dev.usb_buf, n, 500); sd->gspca_dev.usb_buf, n, 500);
if (ret < 0) if (ret < 0) {
PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value);
return ret; return ret;
}
return 0;
} }
static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) 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,12 +2180,13 @@ static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
(__u16)value, (__u16)reg, NULL, 0, 500); (__u16)value, (__u16)reg, NULL, 0, 500);
if (ret >= 0) if (ret < 0) {
PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
else
PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg);
return ret;
}
return ret; PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
return 0;
} }
static int ovfx2_i2c_r(struct sd *sd, __u8 reg) 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,6 +2220,8 @@ static int i2c_w(struct sd *sd, __u8 reg, __u8 value)
return ov518_i2c_w(sd, reg, value); return ov518_i2c_w(sd, reg, value);
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
return ovfx2_i2c_w(sd, reg, value); return ovfx2_i2c_w(sd, reg, value);
case BRIDGE_W9968CF:
return w9968cf_i2c_w(sd, reg, value);
} }
return -1; /* Should never happen */ return -1; /* Should never happen */
} }
...@@ -2211,6 +2238,8 @@ static int i2c_r(struct sd *sd, __u8 reg) ...@@ -2211,6 +2238,8 @@ static int i2c_r(struct sd *sd, __u8 reg)
return ov518_i2c_r(sd, reg); return ov518_i2c_r(sd, reg);
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
return ovfx2_i2c_r(sd, reg); return ovfx2_i2c_r(sd, reg);
case BRIDGE_W9968CF:
return w9968cf_i2c_r(sd, reg);
} }
return -1; /* Should never happen */ return -1; /* Should never happen */
} }
...@@ -2241,6 +2270,8 @@ static int i2c_w_mask(struct sd *sd, ...@@ -2241,6 +2270,8 @@ static int i2c_w_mask(struct sd *sd,
* registers while the camera is streaming */ * registers while the camera is streaming */
static inline int ov51x_stop(struct sd *sd) static inline int ov51x_stop(struct sd *sd)
{ {
int ret;
PDEBUG(D_STREAM, "stopping"); PDEBUG(D_STREAM, "stopping");
sd->stopped = 1; sd->stopped = 1;
switch (sd->bridge) { switch (sd->bridge) {
...@@ -2254,6 +2285,11 @@ static inline int ov51x_stop(struct sd *sd) ...@@ -2254,6 +2285,11 @@ static inline int ov51x_stop(struct sd *sd)
return reg_w(sd, OV519_SYS_RESET1, 0x0f); return reg_w(sd, OV519_SYS_RESET1, 0x0f);
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
return reg_w_mask(sd, 0x0f, 0x00, 0x02); return reg_w_mask(sd, 0x0f, 0x00, 0x02);
case BRIDGE_W9968CF:
ret = reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
ret += reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
ret += reg_w(sd, 0x16, 0x0000); /* stop video capture */
return ret;
} }
return 0; return 0;
...@@ -2285,6 +2321,8 @@ static inline int ov51x_restart(struct sd *sd) ...@@ -2285,6 +2321,8 @@ static inline int ov51x_restart(struct sd *sd)
return reg_w(sd, OV519_SYS_RESET1, 0x00); return reg_w(sd, OV519_SYS_RESET1, 0x00);
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
return reg_w_mask(sd, 0x0f, 0x02, 0x02); return reg_w_mask(sd, 0x0f, 0x02, 0x02);
case BRIDGE_W9968CF:
return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
} }
return 0; return 0;
...@@ -2338,8 +2376,13 @@ static int ov51x_set_slave_ids(struct sd *sd, ...@@ -2338,8 +2376,13 @@ static int ov51x_set_slave_ids(struct sd *sd,
{ {
int rc; int rc;
if (sd->bridge == BRIDGE_OVFX2) switch (sd->bridge) {
case BRIDGE_OVFX2:
return reg_w(sd, OVFX2_I2C_ADDR, slave); return reg_w(sd, OVFX2_I2C_ADDR, slave);
case BRIDGE_W9968CF:
sd->sensor_addr = slave;
return 0;
}
rc = reg_w(sd, R51x_I2C_W_SID, slave); rc = reg_w(sd, R51x_I2C_W_SID, slave);
if (rc < 0) if (rc < 0)
...@@ -2920,6 +2963,10 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -2920,6 +2963,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->bulk_nurbs = MAX_NURBS; cam->bulk_nurbs = MAX_NURBS;
cam->bulk = 1; cam->bulk = 1;
break; break;
case BRIDGE_W9968CF:
ret = w9968cf_configure(sd);
cam->reverse_alts = 1;
break;
} }
if (ret) if (ret)
...@@ -3005,6 +3052,16 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -3005,6 +3052,16 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->nmodes = ARRAY_SIZE(ov519_sif_mode); cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
} }
break; break;
case BRIDGE_W9968CF:
cam->cam_mode = w9968cf_vga_mode;
cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
/* if (sd->sif)
cam->nmodes--; */
/* w9968cf needs initialisation once the sensor is known */
if (w9968cf_init(sd) < 0)
goto error;
break;
} }
sd->brightness = BRIGHTNESS_DEF; sd->brightness = BRIGHTNESS_DEF;
if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF)
...@@ -3753,9 +3810,9 @@ static int set_ov_sensor_window(struct sd *sd) ...@@ -3753,9 +3810,9 @@ static int set_ov_sensor_window(struct sd *sd)
return ret; return ret;
i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x17, hwsbase);
i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
i2c_w(sd, 0x19, vwsbase); i2c_w(sd, 0x19, vwsbase);
i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
return 0; return 0;
} }
...@@ -3766,6 +3823,10 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -3766,6 +3823,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int ret = 0; int ret = 0;
/* Default for most bridges, allow bridge_mode_init_regs to override */
sd->sensor_width = sd->gspca_dev.width;
sd->sensor_height = sd->gspca_dev.height;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
...@@ -3779,6 +3840,9 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -3779,6 +3840,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
ret = ov519_mode_init_regs(sd); ret = ov519_mode_init_regs(sd);
break; break;
/* case BRIDGE_OVFX2: nothing to do */ /* case BRIDGE_OVFX2: nothing to do */
case BRIDGE_W9968CF:
ret = w9968cf_mode_init_regs(sd);
break;
} }
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -3980,6 +4044,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ...@@ -3980,6 +4044,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
ovfx2_pkt_scan(gspca_dev, frame, data, len); ovfx2_pkt_scan(gspca_dev, frame, data, len);
break; break;
case BRIDGE_W9968CF:
w9968cf_pkt_scan(gspca_dev, frame, data, len);
break;
} }
} }
...@@ -4275,8 +4342,12 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) ...@@ -4275,8 +4342,12 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
sd->freq = val; sd->freq = val;
if (gspca_dev->streaming) if (gspca_dev->streaming) {
setfreq(sd); setfreq(sd);
/* Ugly but necessary */
if (sd->bridge == BRIDGE_W9968CF)
w9968cf_set_crop_window(sd);
}
return 0; return 0;
} }
...@@ -4332,6 +4403,7 @@ static const struct sd_desc sd_desc = { ...@@ -4332,6 +4403,7 @@ static const struct sd_desc sd_desc = {
/* -- module initialisation -- */ /* -- module initialisation -- */
static const __devinitdata struct usb_device_id device_table[] = { static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
{USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
{USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
...@@ -4356,6 +4428,7 @@ static const __devinitdata struct usb_device_id device_table[] = { ...@@ -4356,6 +4428,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
{USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
{USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
{USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
{USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 },
{} {}
}; };
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment