diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-10-12 09:07:57 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:40:33 -0500 |
commit | b46aaa02648cd8c1ebc20191304e2f6a2382d04c (patch) | |
tree | c53b3ec8ac438c218fc741c04bc3ca4aa23b00df /drivers/media/video/gspca/ov519.c | |
parent | 635118d5b19c4ad562d425a3f3491c721d6a8293 (diff) |
V4L/DVB (13145): gscpa_ov519: add support for the ovfx2 bridge
gscpa_ov519: add support for the ovfx2 bridge
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 | 206 |
1 files changed, 181 insertions, 25 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index bfc88360132d..30e91c365ea4 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -2,14 +2,19 @@ | |||
2 | * OV519 driver | 2 | * OV519 driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) | 4 | * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) |
5 | * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> | ||
5 | * | 6 | * |
6 | * This module is adapted from the ov51x-jpeg package, which itself | 7 | * This module is adapted from the ov51x-jpeg package, which itself |
7 | * was adapted from the ov511 driver. | 8 | * was adapted from the ov511 driver. |
8 | * | 9 | * |
9 | * Original copyright for the ov511 driver is: | 10 | * Original copyright for the ov511 driver is: |
10 | * | 11 | * |
11 | * Copyright (c) 1999-2004 Mark W. McClelland | 12 | * Copyright (c) 1999-2006 Mark W. McClelland |
12 | * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach | 13 | * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach |
14 | * Many improvements by Bret Wallach <bwallac1@san.rr.com> | ||
15 | * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) | ||
16 | * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> | ||
17 | * Changes by Claudio Matsuoka <claudio@conectiva.com> | ||
13 | * | 18 | * |
14 | * ov51x-jpeg original copyright is: | 19 | * ov51x-jpeg original copyright is: |
15 | * | 20 | * |
@@ -389,26 +394,31 @@ static const struct v4l2_pix_format ovfx2_ov2610_mode[] = { | |||
389 | .colorspace = V4L2_COLORSPACE_SRGB}, | 394 | .colorspace = V4L2_COLORSPACE_SRGB}, |
390 | }; | 395 | }; |
391 | static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { | 396 | static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { |
392 | {2080, 1544, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
393 | .bytesperline = 2080, | ||
394 | .sizeimage = 2080 * 1544, | ||
395 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
396 | {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
397 | .bytesperline = 1600, | ||
398 | .sizeimage = 1600 * 1200, | ||
399 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
400 | {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
401 | .bytesperline = 1024, | ||
402 | .sizeimage = 1024 * 768, | ||
403 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
404 | {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
405 | .bytesperline = 800, | ||
406 | .sizeimage = 800 * 600, | ||
407 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
408 | {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | 397 | {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, |
409 | .bytesperline = 640, | 398 | .bytesperline = 640, |
410 | .sizeimage = 640 * 480, | 399 | .sizeimage = 640 * 480, |
411 | .colorspace = V4L2_COLORSPACE_SRGB}, | 400 | .colorspace = V4L2_COLORSPACE_SRGB, |
401 | .priv = 1}, | ||
402 | {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
403 | .bytesperline = 800, | ||
404 | .sizeimage = 800 * 600, | ||
405 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
406 | .priv = 1}, | ||
407 | {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
408 | .bytesperline = 1024, | ||
409 | .sizeimage = 1024 * 768, | ||
410 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
411 | .priv = 1}, | ||
412 | {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
413 | .bytesperline = 1600, | ||
414 | .sizeimage = 1600 * 1200, | ||
415 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
416 | .priv = 0}, | ||
417 | {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
418 | .bytesperline = 2048, | ||
419 | .sizeimage = 2048 * 1536, | ||
420 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
421 | .priv = 0}, | ||
412 | }; | 422 | }; |
413 | 423 | ||
414 | 424 | ||
@@ -473,6 +483,30 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { | |||
473 | 483 | ||
474 | #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ | 484 | #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ |
475 | 485 | ||
486 | /* | ||
487 | * The FX2 chip does not give us a zero length read at end of frame. | ||
488 | * It does, however, give a short read at the end of a frame, if | ||
489 | * neccessary, rather than run two frames together. | ||
490 | * | ||
491 | * By choosing the right bulk transfer size, we are guaranteed to always | ||
492 | * get a short read for the last read of each frame. Frame sizes are | ||
493 | * always a composite number (width * height, or a multiple) so if we | ||
494 | * choose a prime number, we are guaranteed that the last read of a | ||
495 | * frame will be short. | ||
496 | * | ||
497 | * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB, | ||
498 | * otherwise EOVERFLOW "babbling" errors occur. I have not been able | ||
499 | * to figure out why. [PMiller] | ||
500 | * | ||
501 | * The constant (13 * 4096) is the largest "prime enough" number less than 64KB. | ||
502 | * | ||
503 | * It isn't enough to know the number of bytes per frame, in case we | ||
504 | * have data dropouts or buffer overruns (even though the FX2 double | ||
505 | * buffers, there are some pretty strict real time constraints for | ||
506 | * isochronous transfer for larger frame sizes). | ||
507 | */ | ||
508 | #define OVFX2_BULK_SIZE (13 * 4096) | ||
509 | |||
476 | /* I2C registers */ | 510 | /* I2C registers */ |
477 | #define R51x_I2C_W_SID 0x41 | 511 | #define R51x_I2C_W_SID 0x41 |
478 | #define R51x_I2C_SADDR_3 0x42 | 512 | #define R51x_I2C_SADDR_3 0x42 |
@@ -480,6 +514,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { | |||
480 | #define R51x_I2C_R_SID 0x44 | 514 | #define R51x_I2C_R_SID 0x44 |
481 | #define R51x_I2C_DATA 0x45 | 515 | #define R51x_I2C_DATA 0x45 |
482 | #define R518_I2C_CTL 0x47 /* OV518(+) only */ | 516 | #define R518_I2C_CTL 0x47 /* OV518(+) only */ |
517 | #define OVFX2_I2C_ADDR 0x00 | ||
483 | 518 | ||
484 | /* I2C ADDRESSES */ | 519 | /* I2C ADDRESSES */ |
485 | #define OV7xx0_SID 0x42 | 520 | #define OV7xx0_SID 0x42 |
@@ -579,7 +614,7 @@ struct ov_i2c_regvals { | |||
579 | /* Settings for OV2610 camera chip */ | 614 | /* Settings for OV2610 camera chip */ |
580 | static const struct ov_i2c_regvals norm_2610[] = | 615 | static const struct ov_i2c_regvals norm_2610[] = |
581 | { | 616 | { |
582 | { 0x10, 0x80 }, /* reset */ | 617 | { 0x12, 0x80 }, /* reset */ |
583 | }; | 618 | }; |
584 | 619 | ||
585 | static const struct ov_i2c_regvals norm_3620b[] = | 620 | static const struct ov_i2c_regvals norm_3620b[] = |
@@ -1803,7 +1838,23 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) | |||
1803 | static int reg_w(struct sd *sd, __u16 index, __u8 value) | 1838 | static int reg_w(struct sd *sd, __u16 index, __u8 value) |
1804 | { | 1839 | { |
1805 | int ret; | 1840 | int ret; |
1806 | int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1; | 1841 | int req; |
1842 | |||
1843 | switch (sd->bridge) { | ||
1844 | case BRIDGE_OV511: | ||
1845 | case BRIDGE_OV511PLUS: | ||
1846 | req = 2; | ||
1847 | break; | ||
1848 | case BRIDGE_OVFX2: | ||
1849 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
1850 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | ||
1851 | 0x0a, | ||
1852 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
1853 | (__u16)value, index, NULL, 0, 500); | ||
1854 | goto leave; | ||
1855 | default: | ||
1856 | req = 1; | ||
1857 | } | ||
1807 | 1858 | ||
1808 | sd->gspca_dev.usb_buf[0] = value; | 1859 | sd->gspca_dev.usb_buf[0] = value; |
1809 | ret = usb_control_msg(sd->gspca_dev.dev, | 1860 | ret = usb_control_msg(sd->gspca_dev.dev, |
@@ -1812,6 +1863,7 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) | |||
1812 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1863 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
1813 | 0, index, | 1864 | 0, index, |
1814 | sd->gspca_dev.usb_buf, 1, 500); | 1865 | sd->gspca_dev.usb_buf, 1, 500); |
1866 | leave: | ||
1815 | if (ret < 0) | 1867 | if (ret < 0) |
1816 | PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); | 1868 | PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); |
1817 | return ret; | 1869 | return ret; |
@@ -1822,7 +1874,19 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) | |||
1822 | static int reg_r(struct sd *sd, __u16 index) | 1874 | static int reg_r(struct sd *sd, __u16 index) |
1823 | { | 1875 | { |
1824 | int ret; | 1876 | int ret; |
1825 | int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1; | 1877 | int req; |
1878 | |||
1879 | switch (sd->bridge) { | ||
1880 | case BRIDGE_OV511: | ||
1881 | case BRIDGE_OV511PLUS: | ||
1882 | req = 3; | ||
1883 | break; | ||
1884 | case BRIDGE_OVFX2: | ||
1885 | req = 0x0b; | ||
1886 | break; | ||
1887 | default: | ||
1888 | req = 1; | ||
1889 | } | ||
1826 | 1890 | ||
1827 | ret = usb_control_msg(sd->gspca_dev.dev, | 1891 | ret = usb_control_msg(sd->gspca_dev.dev, |
1828 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | 1892 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), |
@@ -2082,6 +2146,43 @@ static int ov518_i2c_r(struct sd *sd, __u8 reg) | |||
2082 | return value; | 2146 | return value; |
2083 | } | 2147 | } |
2084 | 2148 | ||
2149 | static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) | ||
2150 | { | ||
2151 | int ret; | ||
2152 | |||
2153 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
2154 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | ||
2155 | 0x02, | ||
2156 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
2157 | (__u16)value, (__u16)reg, NULL, 0, 500); | ||
2158 | |||
2159 | 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); | ||
2163 | |||
2164 | return ret; | ||
2165 | } | ||
2166 | |||
2167 | static int ovfx2_i2c_r(struct sd *sd, __u8 reg) | ||
2168 | { | ||
2169 | int ret; | ||
2170 | |||
2171 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
2172 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | ||
2173 | 0x03, | ||
2174 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
2175 | 0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500); | ||
2176 | |||
2177 | if (ret >= 0) { | ||
2178 | ret = sd->gspca_dev.usb_buf[0]; | ||
2179 | PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); | ||
2180 | } else | ||
2181 | PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); | ||
2182 | |||
2183 | return ret; | ||
2184 | } | ||
2185 | |||
2085 | static int i2c_w(struct sd *sd, __u8 reg, __u8 value) | 2186 | static int i2c_w(struct sd *sd, __u8 reg, __u8 value) |
2086 | { | 2187 | { |
2087 | switch (sd->bridge) { | 2188 | switch (sd->bridge) { |
@@ -2092,6 +2193,8 @@ static int i2c_w(struct sd *sd, __u8 reg, __u8 value) | |||
2092 | case BRIDGE_OV518PLUS: | 2193 | case BRIDGE_OV518PLUS: |
2093 | case BRIDGE_OV519: | 2194 | case BRIDGE_OV519: |
2094 | return ov518_i2c_w(sd, reg, value); | 2195 | return ov518_i2c_w(sd, reg, value); |
2196 | case BRIDGE_OVFX2: | ||
2197 | return ovfx2_i2c_w(sd, reg, value); | ||
2095 | } | 2198 | } |
2096 | return -1; /* Should never happen */ | 2199 | return -1; /* Should never happen */ |
2097 | } | 2200 | } |
@@ -2106,6 +2209,8 @@ static int i2c_r(struct sd *sd, __u8 reg) | |||
2106 | case BRIDGE_OV518PLUS: | 2209 | case BRIDGE_OV518PLUS: |
2107 | case BRIDGE_OV519: | 2210 | case BRIDGE_OV519: |
2108 | return ov518_i2c_r(sd, reg); | 2211 | return ov518_i2c_r(sd, reg); |
2212 | case BRIDGE_OVFX2: | ||
2213 | return ovfx2_i2c_r(sd, reg); | ||
2109 | } | 2214 | } |
2110 | return -1; /* Should never happen */ | 2215 | return -1; /* Should never happen */ |
2111 | } | 2216 | } |
@@ -2147,6 +2252,8 @@ static inline int ov51x_stop(struct sd *sd) | |||
2147 | return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); | 2252 | return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); |
2148 | case BRIDGE_OV519: | 2253 | case BRIDGE_OV519: |
2149 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); | 2254 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); |
2255 | case BRIDGE_OVFX2: | ||
2256 | return reg_w_mask(sd, 0x0f, 0x00, 0x02); | ||
2150 | } | 2257 | } |
2151 | 2258 | ||
2152 | return 0; | 2259 | return 0; |
@@ -2176,6 +2283,8 @@ static inline int ov51x_restart(struct sd *sd) | |||
2176 | return reg_w(sd, R51x_SYS_RESET, 0x00); | 2283 | return reg_w(sd, R51x_SYS_RESET, 0x00); |
2177 | case BRIDGE_OV519: | 2284 | case BRIDGE_OV519: |
2178 | return reg_w(sd, OV519_SYS_RESET1, 0x00); | 2285 | return reg_w(sd, OV519_SYS_RESET1, 0x00); |
2286 | case BRIDGE_OVFX2: | ||
2287 | return reg_w_mask(sd, 0x0f, 0x02, 0x02); | ||
2179 | } | 2288 | } |
2180 | 2289 | ||
2181 | return 0; | 2290 | return 0; |
@@ -2229,6 +2338,9 @@ static int ov51x_set_slave_ids(struct sd *sd, | |||
2229 | { | 2338 | { |
2230 | int rc; | 2339 | int rc; |
2231 | 2340 | ||
2341 | if (sd->bridge == BRIDGE_OVFX2) | ||
2342 | return reg_w(sd, OVFX2_I2C_ADDR, slave); | ||
2343 | |||
2232 | rc = reg_w(sd, R51x_I2C_W_SID, slave); | 2344 | rc = reg_w(sd, R51x_I2C_W_SID, slave); |
2233 | if (rc < 0) | 2345 | if (rc < 0) |
2234 | return rc; | 2346 | return rc; |
@@ -2762,12 +2874,29 @@ static int ov519_configure(struct sd *sd) | |||
2762 | return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); | 2874 | return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); |
2763 | } | 2875 | } |
2764 | 2876 | ||
2877 | static int ovfx2_configure(struct sd *sd) | ||
2878 | { | ||
2879 | static const struct ov_regvals init_fx2[] = { | ||
2880 | { 0x00, 0x60 }, | ||
2881 | { 0x02, 0x01 }, | ||
2882 | { 0x0f, 0x1d }, | ||
2883 | { 0xe9, 0x82 }, | ||
2884 | { 0xea, 0xc7 }, | ||
2885 | { 0xeb, 0x10 }, | ||
2886 | { 0xec, 0xf6 }, | ||
2887 | }; | ||
2888 | |||
2889 | sd->stopped = 1; | ||
2890 | |||
2891 | return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); | ||
2892 | } | ||
2893 | |||
2765 | /* this function is called at probe time */ | 2894 | /* this function is called at probe time */ |
2766 | static int sd_config(struct gspca_dev *gspca_dev, | 2895 | static int sd_config(struct gspca_dev *gspca_dev, |
2767 | const struct usb_device_id *id) | 2896 | const struct usb_device_id *id) |
2768 | { | 2897 | { |
2769 | struct sd *sd = (struct sd *) gspca_dev; | 2898 | struct sd *sd = (struct sd *) gspca_dev; |
2770 | struct cam *cam; | 2899 | struct cam *cam = &gspca_dev->cam; |
2771 | int ret = 0; | 2900 | int ret = 0; |
2772 | 2901 | ||
2773 | sd->bridge = id->driver_info & BRIDGE_MASK; | 2902 | sd->bridge = id->driver_info & BRIDGE_MASK; |
@@ -2785,6 +2914,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2785 | case BRIDGE_OV519: | 2914 | case BRIDGE_OV519: |
2786 | ret = ov519_configure(sd); | 2915 | ret = ov519_configure(sd); |
2787 | break; | 2916 | break; |
2917 | case BRIDGE_OVFX2: | ||
2918 | ret = ovfx2_configure(sd); | ||
2919 | cam->bulk_size = OVFX2_BULK_SIZE; | ||
2920 | cam->bulk_nurbs = MAX_NURBS; | ||
2921 | cam->bulk = 1; | ||
2922 | break; | ||
2788 | } | 2923 | } |
2789 | 2924 | ||
2790 | if (ret) | 2925 | if (ret) |
@@ -2825,7 +2960,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2825 | goto error; | 2960 | goto error; |
2826 | } | 2961 | } |
2827 | 2962 | ||
2828 | cam = &gspca_dev->cam; | ||
2829 | switch (sd->bridge) { | 2963 | switch (sd->bridge) { |
2830 | case BRIDGE_OV511: | 2964 | case BRIDGE_OV511: |
2831 | case BRIDGE_OV511PLUS: | 2965 | case BRIDGE_OV511PLUS: |
@@ -3388,9 +3522,9 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3388 | 3522 | ||
3389 | if (qvga) { | 3523 | if (qvga) { |
3390 | xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); | 3524 | xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); |
3391 | ystart = (772 - gspca_dev->height) / 2; | 3525 | ystart = (776 - gspca_dev->height) / 2; |
3392 | } else { | 3526 | } else { |
3393 | xstart = (2080 - gspca_dev->width) / 2 + (0x10 << 4); | 3527 | xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4); |
3394 | ystart = (1544 - gspca_dev->height) / 2; | 3528 | ystart = (1544 - gspca_dev->height) / 2; |
3395 | } | 3529 | } |
3396 | xend = xstart + gspca_dev->width; | 3530 | xend = xstart + gspca_dev->width; |
@@ -3685,6 +3819,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3685 | case BRIDGE_OV519: | 3819 | case BRIDGE_OV519: |
3686 | ret = ov519_mode_init_regs(sd); | 3820 | ret = ov519_mode_init_regs(sd); |
3687 | break; | 3821 | break; |
3822 | /* case BRIDGE_OVFX2: nothing to do */ | ||
3688 | } | 3823 | } |
3689 | if (ret < 0) | 3824 | if (ret < 0) |
3690 | goto out; | 3825 | goto out; |
@@ -3850,6 +3985,20 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | |||
3850 | data, len); | 3985 | data, len); |
3851 | } | 3986 | } |
3852 | 3987 | ||
3988 | static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, | ||
3989 | struct gspca_frame *frame, /* target */ | ||
3990 | __u8 *data, /* isoc packet */ | ||
3991 | int len) /* iso packet length */ | ||
3992 | { | ||
3993 | /* A short read signals EOF */ | ||
3994 | if (len < OVFX2_BULK_SIZE) { | ||
3995 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, len); | ||
3996 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); | ||
3997 | return; | ||
3998 | } | ||
3999 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
4000 | } | ||
4001 | |||
3853 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 4002 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
3854 | struct gspca_frame *frame, /* target */ | 4003 | struct gspca_frame *frame, /* target */ |
3855 | __u8 *data, /* isoc packet */ | 4004 | __u8 *data, /* isoc packet */ |
@@ -3869,6 +4018,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
3869 | case BRIDGE_OV519: | 4018 | case BRIDGE_OV519: |
3870 | ov519_pkt_scan(gspca_dev, frame, data, len); | 4019 | ov519_pkt_scan(gspca_dev, frame, data, len); |
3871 | break; | 4020 | break; |
4021 | case BRIDGE_OVFX2: | ||
4022 | ovfx2_pkt_scan(gspca_dev, frame, data, len); | ||
4023 | break; | ||
3872 | } | 4024 | } |
3873 | } | 4025 | } |
3874 | 4026 | ||
@@ -4237,11 +4389,15 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
4237 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, | 4389 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, |
4238 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, | 4390 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, |
4239 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, | 4391 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, |
4392 | {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 }, | ||
4240 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, | 4393 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, |
4241 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, | 4394 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, |
4242 | {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, | 4395 | {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, |
4243 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, | 4396 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, |
4244 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, | 4397 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, |
4398 | {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, | ||
4399 | {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, | ||
4400 | {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, | ||
4245 | {} | 4401 | {} |
4246 | }; | 4402 | }; |
4247 | 4403 | ||