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 | |
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')
-rw-r--r-- | drivers/media/video/Kconfig | 11 | ||||
-rw-r--r-- | drivers/media/video/gspca/Kconfig | 5 | ||||
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 22 | ||||
-rw-r--r-- | drivers/media/video/gspca/gspca.h | 1 | ||||
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 115 | ||||
-rw-r--r-- | drivers/media/video/gspca/w996Xcf.c | 589 |
6 files changed, 713 insertions, 30 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 0ab7ccd8729b..c69f858c9278 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -951,9 +951,13 @@ source "drivers/media/video/usbvideo/Kconfig" | |||
951 | source "drivers/media/video/et61x251/Kconfig" | 951 | source "drivers/media/video/et61x251/Kconfig" |
952 | 952 | ||
953 | config VIDEO_OVCAMCHIP | 953 | config VIDEO_OVCAMCHIP |
954 | tristate "OmniVision Camera Chip support" | 954 | tristate "OmniVision Camera Chip support (DEPRECATED)" |
955 | depends on I2C && VIDEO_V4L1 | 955 | depends on I2C && VIDEO_V4L1 |
956 | ---help--- | 956 | ---help--- |
957 | This driver is DEPRECATED please use the gspca ov519 module | ||
958 | instead. Note that for the ov511 / ov518 support of the gspca module | ||
959 | you need atleast version 0.6.0 of libv4l. | ||
960 | |||
957 | Support for the OmniVision OV6xxx and OV7xxx series of camera chips. | 961 | Support for the OmniVision OV6xxx and OV7xxx series of camera chips. |
958 | This driver is intended to be used with the ov511 and w9968cf USB | 962 | This driver is intended to be used with the ov511 and w9968cf USB |
959 | camera drivers. | 963 | camera drivers. |
@@ -962,9 +966,12 @@ config VIDEO_OVCAMCHIP | |||
962 | module will be called ovcamchip. | 966 | module will be called ovcamchip. |
963 | 967 | ||
964 | config USB_W9968CF | 968 | config USB_W9968CF |
965 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" | 969 | tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" |
966 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP | 970 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP |
967 | ---help--- | 971 | ---help--- |
972 | This driver is DEPRECATED please use the gspca ov519 module | ||
973 | instead. | ||
974 | |||
968 | Say Y here if you want support for cameras based on OV681 or | 975 | Say Y here if you want support for cameras based on OV681 or |
969 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. | 976 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. |
970 | 977 | ||
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index fe2e490ebc52..cbc2367719f0 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -76,10 +76,11 @@ config USB_GSPCA_MR97310A | |||
76 | module will be called gspca_mr97310a. | 76 | module will be called gspca_mr97310a. |
77 | 77 | ||
78 | config USB_GSPCA_OV519 | 78 | config USB_GSPCA_OV519 |
79 | tristate "OV519 USB Camera Driver" | 79 | tristate "OV51x / OVFX2 / W996xCF USB Camera Driver" |
80 | depends on VIDEO_V4L2 && USB_GSPCA | 80 | depends on VIDEO_V4L2 && USB_GSPCA |
81 | help | 81 | help |
82 | Say Y here if you want support for cameras based on the OV519 chip. | 82 | Say Y here if you want support for cameras based on one of these: |
83 | OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF | ||
83 | 84 | ||
84 | To compile this driver as a module, choose M here: the | 85 | To compile this driver as a module, choose M here: the |
85 | module will be called gspca_ov519. | 86 | module will be called gspca_ov519. |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 179cbc14ee51..ebaa2425fb50 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -475,10 +475,18 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) | |||
475 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK | 475 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK |
476 | : USB_ENDPOINT_XFER_ISOC; | 476 | : USB_ENDPOINT_XFER_ISOC; |
477 | i = gspca_dev->alt; /* previous alt setting */ | 477 | i = gspca_dev->alt; /* previous alt setting */ |
478 | while (--i >= 0) { | 478 | if (gspca_dev->cam.reverse_alts) { |
479 | ep = alt_xfer(&intf->altsetting[i], xfer); | 479 | while (++i < gspca_dev->nbalt) { |
480 | if (ep) | 480 | ep = alt_xfer(&intf->altsetting[i], xfer); |
481 | break; | 481 | if (ep) |
482 | break; | ||
483 | } | ||
484 | } else { | ||
485 | while (--i >= 0) { | ||
486 | ep = alt_xfer(&intf->altsetting[i], xfer); | ||
487 | if (ep) | ||
488 | break; | ||
489 | } | ||
482 | } | 490 | } |
483 | if (ep == NULL) { | 491 | if (ep == NULL) { |
484 | err("no transfer endpoint found"); | 492 | err("no transfer endpoint found"); |
@@ -599,7 +607,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
599 | 607 | ||
600 | /* set the higher alternate setting and | 608 | /* set the higher alternate setting and |
601 | * loop until urb submit succeeds */ | 609 | * loop until urb submit succeeds */ |
602 | gspca_dev->alt = gspca_dev->nbalt; | 610 | if (gspca_dev->cam.reverse_alts) |
611 | gspca_dev->alt = 0; | ||
612 | else | ||
613 | gspca_dev->alt = gspca_dev->nbalt; | ||
614 | |||
603 | if (gspca_dev->sd_desc->isoc_init) { | 615 | if (gspca_dev->sd_desc->isoc_init) { |
604 | ret = gspca_dev->sd_desc->isoc_init(gspca_dev); | 616 | ret = gspca_dev->sd_desc->isoc_init(gspca_dev); |
605 | if (ret < 0) | 617 | if (ret < 0) |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 70b1fd830876..1d761d7cefc6 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -58,6 +58,7 @@ struct cam { | |||
58 | u8 npkt; /* number of packets in an ISOC message | 58 | u8 npkt; /* number of packets in an ISOC message |
59 | * 0 is the default value: 32 packets */ | 59 | * 0 is the default value: 32 packets */ |
60 | u32 input_flags; /* value for ENUM_INPUT status flags */ | 60 | u32 input_flags; /* value for ENUM_INPUT status flags */ |
61 | char reverse_alts; /* Alt settings are in high to low order */ | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | struct gspca_dev; | 64 | struct gspca_dev; |
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 | }; |
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c new file mode 100644 index 000000000000..ba3a28d4f87f --- /dev/null +++ b/drivers/media/video/gspca/w996Xcf.c | |||
@@ -0,0 +1,589 @@ | |||
1 | /** | ||
2 | * | ||
3 | * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip. | ||
4 | * | ||
5 | * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> | ||
6 | * | ||
7 | * This module is adapted from the in kernel v4l1 w9968cf driver: | ||
8 | * | ||
9 | * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* Note this is not a stand alone driver, it gets included in ov519.c, this | ||
28 | is a bit of a hack, but it needs the driver code for a lot of different | ||
29 | ov sensors which is already present in ov519.c (the old v4l1 driver used | ||
30 | the ovchipcam framework). When we have the time we really should move | ||
31 | the sensor drivers to v4l2 sub drivers, and properly split of this | ||
32 | driver from ov519.c */ | ||
33 | |||
34 | #define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ | ||
35 | |||
36 | /* FIXME make this runtime configurable */ | ||
37 | /* Comment/uncomment this for high/low quality of compressed video */ | ||
38 | #define W9968CF_DEC_FAST_LOWQUALITY_VIDEO | ||
39 | |||
40 | #ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO | ||
41 | static const unsigned char Y_QUANTABLE[64] = { | ||
42 | 16, 11, 10, 16, 24, 40, 51, 61, | ||
43 | 12, 12, 14, 19, 26, 58, 60, 55, | ||
44 | 14, 13, 16, 24, 40, 57, 69, 56, | ||
45 | 14, 17, 22, 29, 51, 87, 80, 62, | ||
46 | 18, 22, 37, 56, 68, 109, 103, 77, | ||
47 | 24, 35, 55, 64, 81, 104, 113, 92, | ||
48 | 49, 64, 78, 87, 103, 121, 120, 101, | ||
49 | 72, 92, 95, 98, 112, 100, 103, 99 | ||
50 | }; | ||
51 | |||
52 | static const unsigned char UV_QUANTABLE[64] = { | ||
53 | 17, 18, 24, 47, 99, 99, 99, 99, | ||
54 | 18, 21, 26, 66, 99, 99, 99, 99, | ||
55 | 24, 26, 56, 99, 99, 99, 99, 99, | ||
56 | 47, 66, 99, 99, 99, 99, 99, 99, | ||
57 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
58 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
59 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
60 | 99, 99, 99, 99, 99, 99, 99, 99 | ||
61 | }; | ||
62 | #else | ||
63 | static const unsigned char Y_QUANTABLE[64] = { | ||
64 | 8, 5, 5, 8, 12, 20, 25, 30, | ||
65 | 6, 6, 7, 9, 13, 29, 30, 27, | ||
66 | 7, 6, 8, 12, 20, 28, 34, 28, | ||
67 | 7, 8, 11, 14, 25, 43, 40, 31, | ||
68 | 9, 11, 18, 28, 34, 54, 51, 38, | ||
69 | 12, 17, 27, 32, 40, 52, 56, 46, | ||
70 | 24, 32, 39, 43, 51, 60, 60, 50, | ||
71 | 36, 46, 47, 49, 56, 50, 51, 49 | ||
72 | }; | ||
73 | |||
74 | static const unsigned char UV_QUANTABLE[64] = { | ||
75 | 8, 9, 12, 23, 49, 49, 49, 49, | ||
76 | 9, 10, 13, 33, 49, 49, 49, 49, | ||
77 | 12, 13, 28, 49, 49, 49, 49, 49, | ||
78 | 23, 33, 49, 49, 49, 49, 49, 49, | ||
79 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
80 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
81 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
82 | 49, 49, 49, 49, 49, 49, 49, 49 | ||
83 | }; | ||
84 | #endif | ||
85 | |||
86 | static const struct v4l2_pix_format w9968cf_vga_mode[] = { | ||
87 | {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
88 | .bytesperline = 160 * 2, | ||
89 | .sizeimage = 160 * 120 * 2, | ||
90 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
91 | {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
92 | .bytesperline = 176 * 2, | ||
93 | .sizeimage = 176 * 144 * 2, | ||
94 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
95 | {320, 240, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
96 | .bytesperline = 320 * 2, | ||
97 | .sizeimage = 320 * 240 * 2, | ||
98 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
99 | {352, 288, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
100 | .bytesperline = 352 * 2, | ||
101 | .sizeimage = 352 * 288 * 2, | ||
102 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
103 | /* {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
104 | .bytesperline = 640 * 2, | ||
105 | .sizeimage = 640 * 480 * 2, | ||
106 | .colorspace = V4L2_COLORSPACE_JPEG}, */ | ||
107 | }; | ||
108 | |||
109 | static int reg_w(struct sd *sd, __u16 index, __u16 value); | ||
110 | |||
111 | /*-------------------------------------------------------------------------- | ||
112 | Write 64-bit data to the fast serial bus registers. | ||
113 | Return 0 on success, -1 otherwise. | ||
114 | --------------------------------------------------------------------------*/ | ||
115 | static int w9968cf_write_fsb(struct sd *sd, u16* data) | ||
116 | { | ||
117 | struct usb_device* udev = sd->gspca_dev.dev; | ||
118 | u16 value; | ||
119 | int ret; | ||
120 | |||
121 | value = *data++; | ||
122 | memcpy(sd->gspca_dev.usb_buf, data, 6); | ||
123 | |||
124 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, | ||
125 | USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
126 | value, 0x06, sd->gspca_dev.usb_buf, 6, 500); | ||
127 | if (ret < 0) { | ||
128 | PDEBUG(D_ERR, "Write FSB registers failed (%d)", ret); | ||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /*-------------------------------------------------------------------------- | ||
136 | Write data to the serial bus control register. | ||
137 | Return 0 on success, a negative number otherwise. | ||
138 | --------------------------------------------------------------------------*/ | ||
139 | static int w9968cf_write_sb(struct sd *sd, u16 value) | ||
140 | { | ||
141 | int ret; | ||
142 | |||
143 | /* We don't use reg_w here, as that would cause all writes when | ||
144 | bitbanging i2c to be logged, making the logs impossible to read */ | ||
145 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
146 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | ||
147 | 0, | ||
148 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
149 | value, 0x01, NULL, 0, 500); | ||
150 | |||
151 | udelay(W9968CF_I2C_BUS_DELAY); | ||
152 | |||
153 | if (ret < 0) { | ||
154 | PDEBUG(D_ERR, "Write SB reg [01] %04x failed", value); | ||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | /*-------------------------------------------------------------------------- | ||
162 | Read data from the serial bus control register. | ||
163 | Return 0 on success, a negative number otherwise. | ||
164 | --------------------------------------------------------------------------*/ | ||
165 | static int w9968cf_read_sb(struct sd *sd) | ||
166 | { | ||
167 | int ret; | ||
168 | |||
169 | /* We don't use reg_r here, as the w9968cf is special and has 16 | ||
170 | bit registers instead of 8 bit */ | ||
171 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
172 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | ||
173 | 1, | ||
174 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
175 | 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); | ||
176 | if (ret >= 0) | ||
177 | ret = sd->gspca_dev.usb_buf[0] | | ||
178 | (sd->gspca_dev.usb_buf[1] << 8); | ||
179 | else | ||
180 | PDEBUG(D_ERR, "Read SB reg [01] failed"); | ||
181 | |||
182 | udelay(W9968CF_I2C_BUS_DELAY); | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | /*-------------------------------------------------------------------------- | ||
188 | Upload quantization tables for the JPEG compression. | ||
189 | This function is called by w9968cf_start_transfer(). | ||
190 | Return 0 on success, a negative number otherwise. | ||
191 | --------------------------------------------------------------------------*/ | ||
192 | static int w9968cf_upload_quantizationtables(struct sd *sd) | ||
193 | { | ||
194 | u16 a, b; | ||
195 | int ret = 0, i, j; | ||
196 | |||
197 | ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ | ||
198 | |||
199 | for (i = 0, j = 0; i < 32; i++, j += 2) { | ||
200 | a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); | ||
201 | b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); | ||
202 | ret += reg_w(sd, 0x40+i, a); | ||
203 | ret += reg_w(sd, 0x60+i, b); | ||
204 | } | ||
205 | ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ | ||
206 | |||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | /**************************************************************************** | ||
211 | * Low-level I2C I/O functions. * | ||
212 | * The adapter supports the following I2C transfer functions: * | ||
213 | * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * | ||
214 | * i2c_adap_read_byte_data() * | ||
215 | * i2c_adap_read_byte() * | ||
216 | ****************************************************************************/ | ||
217 | |||
218 | static int w9968cf_smbus_start(struct sd *sd) | ||
219 | { | ||
220 | int ret = 0; | ||
221 | |||
222 | ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | ||
223 | ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | ||
224 | |||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int w9968cf_smbus_stop(struct sd *sd) | ||
229 | { | ||
230 | int ret = 0; | ||
231 | |||
232 | ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | ||
233 | ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | ||
234 | ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static int w9968cf_smbus_write_byte(struct sd *sd, u8 v) | ||
240 | { | ||
241 | u8 bit; | ||
242 | int ret = 0, sda; | ||
243 | |||
244 | for (bit = 0 ; bit < 8 ; bit++) { | ||
245 | sda = (v & 0x80) ? 2 : 0; | ||
246 | v <<= 1; | ||
247 | /* SDE=1, SDA=sda, SCL=0 */ | ||
248 | ret += w9968cf_write_sb(sd, 0x10 | sda); | ||
249 | /* SDE=1, SDA=sda, SCL=1 */ | ||
250 | ret += w9968cf_write_sb(sd, 0x11 | sda); | ||
251 | /* SDE=1, SDA=sda, SCL=0 */ | ||
252 | ret += w9968cf_write_sb(sd, 0x10 | sda); | ||
253 | } | ||
254 | |||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) | ||
259 | { | ||
260 | u8 bit; | ||
261 | int ret = 0; | ||
262 | |||
263 | /* No need to ensure SDA is high as we are always called after | ||
264 | read_ack which ends with SDA high */ | ||
265 | *v = 0; | ||
266 | for (bit = 0 ; bit < 8 ; bit++) { | ||
267 | *v <<= 1; | ||
268 | /* SDE=1, SDA=1, SCL=1 */ | ||
269 | ret += w9968cf_write_sb(sd, 0x0013); | ||
270 | *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; | ||
271 | /* SDE=1, SDA=1, SCL=0 */ | ||
272 | ret += w9968cf_write_sb(sd, 0x0012); | ||
273 | } | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static int w9968cf_smbus_write_nack(struct sd *sd) | ||
279 | { | ||
280 | int ret = 0; | ||
281 | |||
282 | /* No need to ensure SDA is high as we are always called after | ||
283 | read_byte which ends with SDA high */ | ||
284 | ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
285 | ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | static int w9968cf_smbus_read_ack(struct sd *sd) | ||
291 | { | ||
292 | int ret = 0, sda; | ||
293 | |||
294 | /* Ensure SDA is high before raising clock to avoid a spurious stop */ | ||
295 | ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | ||
296 | ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
297 | sda = w9968cf_read_sb(sd); | ||
298 | ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | ||
299 | if (sda < 0) | ||
300 | ret += sda; | ||
301 | else if (sda & 0x08) { | ||
302 | PDEBUG(D_USBI, "Did not receive i2c ACK"); | ||
303 | ret += -1; | ||
304 | } | ||
305 | |||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ | ||
310 | static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) | ||
311 | { | ||
312 | u16* data = (u16 *)sd->gspca_dev.usb_buf; | ||
313 | int ret = 0; | ||
314 | |||
315 | data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); | ||
316 | data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; | ||
317 | data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0); | ||
318 | data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0; | ||
319 | data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0; | ||
320 | data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0); | ||
321 | data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0; | ||
322 | data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0; | ||
323 | data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); | ||
324 | data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; | ||
325 | |||
326 | ret += w9968cf_write_fsb(sd, data); | ||
327 | |||
328 | data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); | ||
329 | data[0] |= (reg & 0x40) ? 0x0540 : 0x0; | ||
330 | data[0] |= (reg & 0x20) ? 0x5000 : 0x0; | ||
331 | data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0); | ||
332 | data[1] |= (reg & 0x10) ? 0x0054 : 0x0; | ||
333 | data[1] |= (reg & 0x08) ? 0x1500 : 0x0; | ||
334 | data[1] |= (reg & 0x04) ? 0x4000 : 0x0; | ||
335 | data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0); | ||
336 | data[2] |= (reg & 0x02) ? 0x0150 : 0x0; | ||
337 | data[2] |= (reg & 0x01) ? 0x5400 : 0x0; | ||
338 | data[3] = 0x001d; | ||
339 | |||
340 | ret += w9968cf_write_fsb(sd, data); | ||
341 | |||
342 | data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); | ||
343 | data[0] |= (value & 0x40) ? 0x0540 : 0x0; | ||
344 | data[0] |= (value & 0x20) ? 0x5000 : 0x0; | ||
345 | data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); | ||
346 | data[1] |= (value & 0x10) ? 0x0054 : 0x0; | ||
347 | data[1] |= (value & 0x08) ? 0x1500 : 0x0; | ||
348 | data[1] |= (value & 0x04) ? 0x4000 : 0x0; | ||
349 | data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); | ||
350 | data[2] |= (value & 0x02) ? 0x0150 : 0x0; | ||
351 | data[2] |= (value & 0x01) ? 0x5400 : 0x0; | ||
352 | data[3] = 0xfe1d; | ||
353 | |||
354 | ret += w9968cf_write_fsb(sd, data); | ||
355 | |||
356 | if (!ret) | ||
357 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); | ||
358 | else | ||
359 | PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); | ||
360 | |||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ | ||
365 | static int w9968cf_i2c_r(struct sd *sd, u8 reg) | ||
366 | { | ||
367 | int ret = 0; | ||
368 | u8 value; | ||
369 | |||
370 | /* Fast serial bus data control disable */ | ||
371 | ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */ | ||
372 | |||
373 | ret += w9968cf_smbus_start(sd); | ||
374 | ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr); | ||
375 | ret += w9968cf_smbus_read_ack(sd); | ||
376 | ret += w9968cf_smbus_write_byte(sd, reg); | ||
377 | ret += w9968cf_smbus_read_ack(sd); | ||
378 | ret += w9968cf_smbus_stop(sd); | ||
379 | ret += w9968cf_smbus_start(sd); | ||
380 | ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); | ||
381 | ret += w9968cf_smbus_read_ack(sd); | ||
382 | ret += w9968cf_smbus_read_byte(sd, &value); | ||
383 | /* signal we don't want to read anymore, the v4l1 driver used to | ||
384 | send an ack here which is very wrong! (and then fixed | ||
385 | the issues this gave by retrying reads) */ | ||
386 | ret += w9968cf_smbus_write_nack(sd); | ||
387 | ret += w9968cf_smbus_stop(sd); | ||
388 | |||
389 | /* Fast serial bus data control re-enable */ | ||
390 | ret += w9968cf_write_sb(sd, 0x0030); | ||
391 | |||
392 | if (!ret) { | ||
393 | ret = value; | ||
394 | PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); | ||
395 | } else | ||
396 | PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); | ||
397 | |||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | |||
402 | /*-------------------------------------------------------------------------- | ||
403 | Turn on the LED on some webcams. A beep should be heard too. | ||
404 | Return 0 on success, a negative number otherwise. | ||
405 | --------------------------------------------------------------------------*/ | ||
406 | static int w9968cf_configure(struct sd *sd) | ||
407 | { | ||
408 | int ret = 0; | ||
409 | |||
410 | ret += reg_w(sd, 0x00, 0xff00); /* power-down */ | ||
411 | ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ | ||
412 | ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ | ||
413 | ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ | ||
414 | ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ | ||
415 | ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ | ||
416 | ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ | ||
417 | |||
418 | if (ret) | ||
419 | PDEBUG(D_ERR, "Couldn't turn on the LED"); | ||
420 | |||
421 | sd->stopped = 1; | ||
422 | |||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | static int w9968cf_init(struct sd *sd) | ||
427 | { | ||
428 | int ret = 0; | ||
429 | unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), | ||
430 | y0 = 0x0000, | ||
431 | u0 = y0 + hw_bufsize/2, | ||
432 | v0 = u0 + hw_bufsize/4, | ||
433 | y1 = v0 + hw_bufsize/4, | ||
434 | u1 = y1 + hw_bufsize/2, | ||
435 | v1 = u1 + hw_bufsize/4; | ||
436 | |||
437 | ret += reg_w(sd, 0x00, 0xff00); /* power off */ | ||
438 | ret += reg_w(sd, 0x00, 0xbf10); /* power on */ | ||
439 | |||
440 | ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */ | ||
441 | ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ | ||
442 | |||
443 | ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ | ||
444 | ret += reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ | ||
445 | ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ | ||
446 | ret += reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ | ||
447 | ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ | ||
448 | ret += reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ | ||
449 | |||
450 | ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ | ||
451 | ret += reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ | ||
452 | ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ | ||
453 | ret += reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ | ||
454 | ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ | ||
455 | ret += reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ | ||
456 | |||
457 | ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ | ||
458 | ret += reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ | ||
459 | |||
460 | ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ | ||
461 | ret += reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ | ||
462 | |||
463 | ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ | ||
464 | ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ | ||
465 | ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ | ||
466 | ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ | ||
467 | |||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | static int w9968cf_set_crop_window(struct sd *sd) | ||
472 | { | ||
473 | int ret = 0, start_cropx, start_cropy, x, y, fw, fh, cw, ch, | ||
474 | max_width, max_height; | ||
475 | |||
476 | if (sd->sif) { | ||
477 | max_width = 352; | ||
478 | max_height = 288; | ||
479 | } else { | ||
480 | max_width = 640; | ||
481 | max_height = 480; | ||
482 | } | ||
483 | |||
484 | if (sd->sensor == SEN_OV7620) { | ||
485 | /* Sigh, this is dependend on the clock / framerate changes | ||
486 | made by the frequency control, sick. */ | ||
487 | if (sd->freq == 1) { | ||
488 | start_cropx = 279; | ||
489 | start_cropy = 35; | ||
490 | } else { | ||
491 | start_cropx = 103; | ||
492 | start_cropy = 35; | ||
493 | } | ||
494 | } else { | ||
495 | start_cropx = 320; | ||
496 | start_cropy = 35; | ||
497 | } | ||
498 | |||
499 | /* Work around to avoid FP arithmetics */ | ||
500 | #define SC(x) ((x) << 10) | ||
501 | |||
502 | /* Scaling factors */ | ||
503 | fw = SC(sd->gspca_dev.width) / max_width; | ||
504 | fh = SC(sd->gspca_dev.height) / max_height; | ||
505 | |||
506 | cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width)/fh; | ||
507 | ch = (fw >= fh) ? SC(sd->gspca_dev.height)/fw : max_height; | ||
508 | |||
509 | sd->sensor_width = max_width; | ||
510 | sd->sensor_height = max_height; | ||
511 | |||
512 | x = (max_width - cw) / 2; | ||
513 | y = (max_height - ch) / 2; | ||
514 | |||
515 | ret += reg_w(sd, 0x10, start_cropx + x); | ||
516 | ret += reg_w(sd, 0x11, start_cropy + y); | ||
517 | ret += reg_w(sd, 0x12, start_cropx + x + cw); | ||
518 | ret += reg_w(sd, 0x13, start_cropy + y + ch); | ||
519 | |||
520 | return ret; | ||
521 | } | ||
522 | |||
523 | static int w9968cf_mode_init_regs(struct sd *sd) | ||
524 | { | ||
525 | int ret = 0, val, vs_polarity, hs_polarity; | ||
526 | |||
527 | ret += w9968cf_set_crop_window(sd); | ||
528 | |||
529 | ret += reg_w(sd, 0x14, sd->gspca_dev.width); | ||
530 | ret += reg_w(sd, 0x15, sd->gspca_dev.height); | ||
531 | |||
532 | /* JPEG width & height */ | ||
533 | ret += reg_w(sd, 0x30, sd->gspca_dev.width); | ||
534 | ret += reg_w(sd, 0x31, sd->gspca_dev.height); | ||
535 | |||
536 | /* Y & UV frame buffer strides (in WORD) */ | ||
537 | ret += reg_w(sd, 0x2c, sd->gspca_dev.width); | ||
538 | |||
539 | ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ | ||
540 | ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ | ||
541 | |||
542 | /* Transfer size */ | ||
543 | /* FIXME JPEG * 4 ?? */ | ||
544 | val = sd->gspca_dev.width * sd->gspca_dev.height; | ||
545 | ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ | ||
546 | ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ | ||
547 | |||
548 | /* Video Capture Control Register */ | ||
549 | if (sd->sensor == SEN_OV7620) { | ||
550 | /* Seems to work around a bug in the image sensor */ | ||
551 | vs_polarity = 1; | ||
552 | hs_polarity = 1; | ||
553 | } else { | ||
554 | vs_polarity = 1; | ||
555 | hs_polarity = 0; | ||
556 | } | ||
557 | |||
558 | val = (vs_polarity << 12) | (hs_polarity << 11); | ||
559 | |||
560 | val |= 0x0080; /* Enable HW double buffering */ | ||
561 | |||
562 | /* val |= 0x0020; enable clamping */ | ||
563 | /* val |= 0x0008; enable (1-2-1) filter */ | ||
564 | /* val |= 0x000c; enable (2-3-6-3-2) filter */ | ||
565 | |||
566 | val |= 0x8000; /* capt. enable */ | ||
567 | |||
568 | ret += reg_w(sd, 0x16, val); | ||
569 | |||
570 | sd->gspca_dev.empty_packet = 0; | ||
571 | |||
572 | return ret; | ||
573 | } | ||
574 | |||
575 | static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, | ||
576 | struct gspca_frame *frame, /* target */ | ||
577 | __u8 *data, /* isoc packet */ | ||
578 | int len) /* iso packet length */ | ||
579 | { | ||
580 | /* An empty packet signals EOF */ | ||
581 | if (gspca_dev->empty_packet) { | ||
582 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
583 | data, len); | ||
584 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | ||
585 | NULL, 0); | ||
586 | gspca_dev->empty_packet = 0; | ||
587 | } | ||
588 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
589 | } | ||