diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-06-07 11:10:39 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-16 18:07:42 -0400 |
commit | 49809d6a511960e5ccfb85b780894f45ac119065 (patch) | |
tree | ef00b16e944adf94774f65e47ddff6787e75b991 | |
parent | 253f13d5cd05204aa3174ffb53490f2b0fad055c (diff) |
V4L/DVB (11970): gspca - ov519: Add support for the ov518 bridge.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 520 | ||||
-rw-r--r-- | include/linux/videodev2.h | 3 |
2 files changed, 488 insertions, 35 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 1fff37b79891..188866ac6cef 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -50,6 +50,13 @@ static int i2c_detect_tries = 10; | |||
50 | struct sd { | 50 | struct sd { |
51 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 51 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
52 | 52 | ||
53 | char bridge; | ||
54 | #define BRIDGE_OV511 0 | ||
55 | #define BRIDGE_OV511PLUS 1 | ||
56 | #define BRIDGE_OV518 2 | ||
57 | #define BRIDGE_OV518PLUS 3 | ||
58 | #define BRIDGE_OV519 4 | ||
59 | |||
53 | /* Determined by sensor type */ | 60 | /* Determined by sensor type */ |
54 | __u8 sif; | 61 | __u8 sif; |
55 | 62 | ||
@@ -87,6 +94,9 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | |||
87 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | 94 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); |
88 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 95 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
89 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | 96 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); |
97 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
98 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
99 | static void setcolors(struct gspca_dev *gspca_dev); | ||
90 | 100 | ||
91 | static struct ctrl sd_ctrls[] = { | 101 | static struct ctrl sd_ctrls[] = { |
92 | { | 102 | { |
@@ -164,7 +174,7 @@ static struct ctrl sd_ctrls[] = { | |||
164 | }, | 174 | }, |
165 | }; | 175 | }; |
166 | 176 | ||
167 | static const struct v4l2_pix_format vga_mode[] = { | 177 | static const struct v4l2_pix_format ov519_vga_mode[] = { |
168 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 178 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
169 | .bytesperline = 320, | 179 | .bytesperline = 320, |
170 | .sizeimage = 320 * 240 * 3 / 8 + 590, | 180 | .sizeimage = 320 * 240 * 3 / 8 + 590, |
@@ -176,7 +186,7 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
176 | .colorspace = V4L2_COLORSPACE_JPEG, | 186 | .colorspace = V4L2_COLORSPACE_JPEG, |
177 | .priv = 0}, | 187 | .priv = 0}, |
178 | }; | 188 | }; |
179 | static const struct v4l2_pix_format sif_mode[] = { | 189 | static const struct v4l2_pix_format ov519_sif_mode[] = { |
180 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 190 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
181 | .bytesperline = 176, | 191 | .bytesperline = 176, |
182 | .sizeimage = 176 * 144 * 3 / 8 + 590, | 192 | .sizeimage = 176 * 144 * 3 / 8 + 590, |
@@ -189,6 +199,47 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
189 | .priv = 0}, | 199 | .priv = 0}, |
190 | }; | 200 | }; |
191 | 201 | ||
202 | static const struct v4l2_pix_format ov518_vga_mode[] = { | ||
203 | {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | ||
204 | .bytesperline = 320, | ||
205 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
206 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
207 | .priv = 1}, | ||
208 | {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | ||
209 | .bytesperline = 640, | ||
210 | .sizeimage = 640 * 480 * 3 / 8 + 590, | ||
211 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
212 | .priv = 0}, | ||
213 | }; | ||
214 | static const struct v4l2_pix_format ov518_sif_mode[] = { | ||
215 | {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | ||
216 | .bytesperline = 176, | ||
217 | .sizeimage = 40000, | ||
218 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
219 | .priv = 1}, | ||
220 | {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | ||
221 | .bytesperline = 352, | ||
222 | .sizeimage = 352 * 288 * 3 / 8 + 590, | ||
223 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
224 | .priv = 0}, | ||
225 | }; | ||
226 | |||
227 | |||
228 | /* Registers common to OV511 / OV518 */ | ||
229 | #define R51x_SYS_RESET 0x50 | ||
230 | #define R51x_SYS_INIT 0x53 | ||
231 | #define R51x_SYS_SNAP 0x52 | ||
232 | #define R51x_SYS_CUST_ID 0x5F | ||
233 | #define R51x_COMP_LUT_BEGIN 0x80 | ||
234 | |||
235 | /* OV511 Camera interface register numbers */ | ||
236 | #define R511_SYS_LED_CTL 0x55 /* OV511+ only */ | ||
237 | #define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ | ||
238 | |||
239 | /* OV518 Camera interface register numbers */ | ||
240 | #define R518_GPIO_OUT 0x56 /* OV518(+) only */ | ||
241 | #define R518_GPIO_CTL 0x57 /* OV518(+) only */ | ||
242 | |||
192 | /* OV519 Camera interface register numbers */ | 243 | /* OV519 Camera interface register numbers */ |
193 | #define OV519_R10_H_SIZE 0x10 | 244 | #define OV519_R10_H_SIZE 0x10 |
194 | #define OV519_R11_V_SIZE 0x11 | 245 | #define OV519_R11_V_SIZE 0x11 |
@@ -224,6 +275,8 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
224 | 275 | ||
225 | /* OV7610 registers */ | 276 | /* OV7610 registers */ |
226 | #define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ | 277 | #define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ |
278 | #define OV7610_REG_BLUE 0x01 /* blue channel balance */ | ||
279 | #define OV7610_REG_RED 0x02 /* red channel balance */ | ||
227 | #define OV7610_REG_SAT 0x03 /* saturation */ | 280 | #define OV7610_REG_SAT 0x03 /* saturation */ |
228 | #define OV8610_REG_HUE 0x04 /* 04 reserved */ | 281 | #define OV8610_REG_HUE 0x04 /* 04 reserved */ |
229 | #define OV7610_REG_CNT 0x05 /* Y contrast */ | 282 | #define OV7610_REG_CNT 0x05 /* Y contrast */ |
@@ -846,11 +899,12 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) | |||
846 | static int reg_w(struct sd *sd, __u16 index, __u8 value) | 899 | static int reg_w(struct sd *sd, __u16 index, __u8 value) |
847 | { | 900 | { |
848 | int ret; | 901 | int ret; |
902 | int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1; | ||
849 | 903 | ||
850 | sd->gspca_dev.usb_buf[0] = value; | 904 | sd->gspca_dev.usb_buf[0] = value; |
851 | ret = usb_control_msg(sd->gspca_dev.dev, | 905 | ret = usb_control_msg(sd->gspca_dev.dev, |
852 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | 906 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), |
853 | 1, /* REQ_IO (ov518/519) */ | 907 | req, |
854 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 908 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
855 | 0, index, | 909 | 0, index, |
856 | sd->gspca_dev.usb_buf, 1, 500); | 910 | sd->gspca_dev.usb_buf, 1, 500); |
@@ -864,10 +918,11 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) | |||
864 | static int reg_r(struct sd *sd, __u16 index) | 918 | static int reg_r(struct sd *sd, __u16 index) |
865 | { | 919 | { |
866 | int ret; | 920 | int ret; |
921 | int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1; | ||
867 | 922 | ||
868 | ret = usb_control_msg(sd->gspca_dev.dev, | 923 | ret = usb_control_msg(sd->gspca_dev.dev, |
869 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | 924 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), |
870 | 1, /* REQ_IO */ | 925 | req, |
871 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 926 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
872 | 0, index, sd->gspca_dev.usb_buf, 1, 500); | 927 | 0, index, sd->gspca_dev.usb_buf, 1, 500); |
873 | 928 | ||
@@ -924,6 +979,28 @@ static int reg_w_mask(struct sd *sd, | |||
924 | } | 979 | } |
925 | 980 | ||
926 | /* | 981 | /* |
982 | * Writes multiple (n) byte value to a single register. Only valid with certain | ||
983 | * registers (0x30 and 0xc4 - 0xce). | ||
984 | */ | ||
985 | static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) | ||
986 | { | ||
987 | int ret; | ||
988 | |||
989 | *((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value); | ||
990 | |||
991 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
992 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | ||
993 | 1 /* REG_IO */, | ||
994 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
995 | 0, index, | ||
996 | sd->gspca_dev.usb_buf, n, 500); | ||
997 | if (ret < 0) | ||
998 | PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); | ||
999 | return ret; | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /* | ||
927 | * The OV518 I2C I/O procedure is different, hence, this function. | 1004 | * The OV518 I2C I/O procedure is different, hence, this function. |
928 | * This is normally only called from i2c_w(). Note that this function | 1005 | * This is normally only called from i2c_w(). Note that this function |
929 | * always succeeds regardless of whether the sensor is present and working. | 1006 | * always succeeds regardless of whether the sensor is present and working. |
@@ -1014,20 +1091,47 @@ static inline int ov51x_stop(struct sd *sd) | |||
1014 | { | 1091 | { |
1015 | PDEBUG(D_STREAM, "stopping"); | 1092 | PDEBUG(D_STREAM, "stopping"); |
1016 | sd->stopped = 1; | 1093 | sd->stopped = 1; |
1017 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); | 1094 | switch (sd->bridge) { |
1095 | case BRIDGE_OV511: | ||
1096 | case BRIDGE_OV511PLUS: | ||
1097 | return reg_w(sd, R51x_SYS_RESET, 0x3d); | ||
1098 | case BRIDGE_OV518: | ||
1099 | case BRIDGE_OV518PLUS: | ||
1100 | return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); | ||
1101 | case BRIDGE_OV519: | ||
1102 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); | ||
1103 | } | ||
1104 | |||
1105 | return 0; | ||
1018 | } | 1106 | } |
1019 | 1107 | ||
1020 | /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not | 1108 | /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not |
1021 | * actually stopped (for performance). */ | 1109 | * actually stopped (for performance). */ |
1022 | static inline int ov51x_restart(struct sd *sd) | 1110 | static inline int ov51x_restart(struct sd *sd) |
1023 | { | 1111 | { |
1112 | int rc; | ||
1113 | |||
1024 | PDEBUG(D_STREAM, "restarting"); | 1114 | PDEBUG(D_STREAM, "restarting"); |
1025 | if (!sd->stopped) | 1115 | if (!sd->stopped) |
1026 | return 0; | 1116 | return 0; |
1027 | sd->stopped = 0; | 1117 | sd->stopped = 0; |
1028 | 1118 | ||
1029 | /* Reinitialize the stream */ | 1119 | /* Reinitialize the stream */ |
1030 | return reg_w(sd, OV519_SYS_RESET1, 0x00); | 1120 | switch (sd->bridge) { |
1121 | case BRIDGE_OV511: | ||
1122 | case BRIDGE_OV511PLUS: | ||
1123 | return reg_w(sd, R51x_SYS_RESET, 0x00); | ||
1124 | case BRIDGE_OV518: | ||
1125 | case BRIDGE_OV518PLUS: | ||
1126 | rc = reg_w(sd, 0x2f, 0x80); | ||
1127 | if (rc < 0) | ||
1128 | return rc; | ||
1129 | return reg_w(sd, R51x_SYS_RESET, 0x00); | ||
1130 | case BRIDGE_OV519: | ||
1131 | return reg_w(sd, OV519_SYS_RESET1, 0x00); | ||
1132 | } | ||
1133 | |||
1134 | return 0; | ||
1031 | } | 1135 | } |
1032 | 1136 | ||
1033 | /* This does an initial reset of an OmniVision sensor and ensures that I2C | 1137 | /* This does an initial reset of an OmniVision sensor and ensures that I2C |
@@ -1287,16 +1391,161 @@ static int ov6xx0_configure(struct sd *sd) | |||
1287 | /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ | 1391 | /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ |
1288 | static void ov51x_led_control(struct sd *sd, int on) | 1392 | static void ov51x_led_control(struct sd *sd, int on) |
1289 | { | 1393 | { |
1290 | reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ | 1394 | switch (sd->bridge) { |
1395 | /* OV511 has no LED control */ | ||
1396 | case BRIDGE_OV511PLUS: | ||
1397 | reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); | ||
1398 | break; | ||
1399 | case BRIDGE_OV518: | ||
1400 | case BRIDGE_OV518PLUS: | ||
1401 | reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); | ||
1402 | break; | ||
1403 | case BRIDGE_OV519: | ||
1404 | reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ | ||
1405 | break; | ||
1406 | } | ||
1291 | } | 1407 | } |
1292 | 1408 | ||
1293 | /* this function is called at probe time */ | 1409 | /* OV518 quantization tables are 8x4 (instead of 8x8) */ |
1294 | static int sd_config(struct gspca_dev *gspca_dev, | 1410 | static int ov518_upload_quan_tables(struct sd *sd) |
1295 | const struct usb_device_id *id) | 1411 | { |
1412 | const unsigned char yQuanTable518[] = { | ||
1413 | 5, 4, 5, 6, 6, 7, 7, 7, | ||
1414 | 5, 5, 5, 5, 6, 7, 7, 7, | ||
1415 | 6, 6, 6, 6, 7, 7, 7, 8, | ||
1416 | 7, 7, 6, 7, 7, 7, 8, 8 | ||
1417 | }; | ||
1418 | |||
1419 | const unsigned char uvQuanTable518[] = { | ||
1420 | 6, 6, 6, 7, 7, 7, 7, 7, | ||
1421 | 6, 6, 6, 7, 7, 7, 7, 7, | ||
1422 | 6, 6, 6, 7, 7, 7, 7, 8, | ||
1423 | 7, 7, 7, 7, 7, 7, 8, 8 | ||
1424 | }; | ||
1425 | |||
1426 | const unsigned char *pYTable = yQuanTable518; | ||
1427 | const unsigned char *pUVTable = uvQuanTable518; | ||
1428 | unsigned char val0, val1; | ||
1429 | int i, rc, reg = R51x_COMP_LUT_BEGIN; | ||
1430 | |||
1431 | PDEBUG(D_PROBE, "Uploading quantization tables"); | ||
1432 | |||
1433 | for (i = 0; i < 16; i++) { | ||
1434 | val0 = *pYTable++; | ||
1435 | val1 = *pYTable++; | ||
1436 | val0 &= 0x0f; | ||
1437 | val1 &= 0x0f; | ||
1438 | val0 |= val1 << 4; | ||
1439 | rc = reg_w(sd, reg, val0); | ||
1440 | if (rc < 0) | ||
1441 | return rc; | ||
1442 | |||
1443 | val0 = *pUVTable++; | ||
1444 | val1 = *pUVTable++; | ||
1445 | val0 &= 0x0f; | ||
1446 | val1 &= 0x0f; | ||
1447 | val0 |= val1 << 4; | ||
1448 | rc = reg_w(sd, reg + 16, val0); | ||
1449 | if (rc < 0) | ||
1450 | return rc; | ||
1451 | |||
1452 | reg++; | ||
1453 | } | ||
1454 | |||
1455 | return 0; | ||
1456 | } | ||
1457 | |||
1458 | /* This initializes the OV518/OV518+ and the sensor */ | ||
1459 | static int ov518_configure(struct gspca_dev *gspca_dev) | ||
1296 | { | 1460 | { |
1297 | struct sd *sd = (struct sd *) gspca_dev; | 1461 | struct sd *sd = (struct sd *) gspca_dev; |
1298 | struct cam *cam; | 1462 | int rc; |
1463 | |||
1464 | /* For 518 and 518+ */ | ||
1465 | static struct ov_regvals init_518[] = { | ||
1466 | { R51x_SYS_RESET, 0x40 }, | ||
1467 | { R51x_SYS_INIT, 0xe1 }, | ||
1468 | { R51x_SYS_RESET, 0x3e }, | ||
1469 | { R51x_SYS_INIT, 0xe1 }, | ||
1470 | { R51x_SYS_RESET, 0x00 }, | ||
1471 | { R51x_SYS_INIT, 0xe1 }, | ||
1472 | { 0x46, 0x00 }, | ||
1473 | { 0x5d, 0x03 }, | ||
1474 | }; | ||
1475 | |||
1476 | static struct ov_regvals norm_518[] = { | ||
1477 | { R51x_SYS_SNAP, 0x02 }, /* Reset */ | ||
1478 | { R51x_SYS_SNAP, 0x01 }, /* Enable */ | ||
1479 | { 0x31, 0x0f }, | ||
1480 | { 0x5d, 0x03 }, | ||
1481 | { 0x24, 0x9f }, | ||
1482 | { 0x25, 0x90 }, | ||
1483 | { 0x20, 0x00 }, | ||
1484 | { 0x51, 0x04 }, | ||
1485 | { 0x71, 0x19 }, | ||
1486 | { 0x2f, 0x80 }, | ||
1487 | }; | ||
1488 | |||
1489 | static struct ov_regvals norm_518_p[] = { | ||
1490 | { R51x_SYS_SNAP, 0x02 }, /* Reset */ | ||
1491 | { R51x_SYS_SNAP, 0x01 }, /* Enable */ | ||
1492 | { 0x31, 0x0f }, | ||
1493 | { 0x5d, 0x03 }, | ||
1494 | { 0x24, 0x9f }, | ||
1495 | { 0x25, 0x90 }, | ||
1496 | { 0x20, 0x60 }, | ||
1497 | { 0x51, 0x02 }, | ||
1498 | { 0x71, 0x19 }, | ||
1499 | { 0x40, 0xff }, | ||
1500 | { 0x41, 0x42 }, | ||
1501 | { 0x46, 0x00 }, | ||
1502 | { 0x33, 0x04 }, | ||
1503 | { 0x21, 0x19 }, | ||
1504 | { 0x3f, 0x10 }, | ||
1505 | { 0x2f, 0x80 }, | ||
1506 | }; | ||
1507 | |||
1508 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ | ||
1509 | PDEBUG(D_PROBE, "Device revision %d", | ||
1510 | 0x1F & reg_r(sd, R51x_SYS_CUST_ID)); | ||
1511 | |||
1512 | rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518)); | ||
1513 | if (rc < 0) | ||
1514 | return rc; | ||
1515 | |||
1516 | /* Set LED GPIO pin to output mode */ | ||
1517 | rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); | ||
1518 | if (rc < 0) | ||
1519 | return rc; | ||
1299 | 1520 | ||
1521 | switch (sd->bridge) { | ||
1522 | case BRIDGE_OV518: | ||
1523 | rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); | ||
1524 | if (rc < 0) | ||
1525 | return rc; | ||
1526 | break; | ||
1527 | case BRIDGE_OV518PLUS: | ||
1528 | rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); | ||
1529 | if (rc < 0) | ||
1530 | return rc; | ||
1531 | break; | ||
1532 | } | ||
1533 | |||
1534 | rc = ov518_upload_quan_tables(sd); | ||
1535 | if (rc < 0) { | ||
1536 | PDEBUG(D_ERR, "Error uploading quantization tables"); | ||
1537 | return rc; | ||
1538 | } | ||
1539 | |||
1540 | rc = reg_w(sd, 0x2f, 0x80); | ||
1541 | if (rc < 0) | ||
1542 | return rc; | ||
1543 | |||
1544 | return 0; | ||
1545 | } | ||
1546 | |||
1547 | static int ov519_configure(struct sd *sd) | ||
1548 | { | ||
1300 | static const struct ov_regvals init_519[] = { | 1549 | static const struct ov_regvals init_519[] = { |
1301 | { 0x5a, 0x6d }, /* EnableSystem */ | 1550 | { 0x5a, 0x6d }, /* EnableSystem */ |
1302 | { 0x53, 0x9b }, | 1551 | { 0x53, 0x9b }, |
@@ -1313,8 +1562,32 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1313 | /* windows reads 0x55 at this point*/ | 1562 | /* windows reads 0x55 at this point*/ |
1314 | }; | 1563 | }; |
1315 | 1564 | ||
1316 | if (write_regvals(sd, init_519, ARRAY_SIZE(init_519))) | 1565 | return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); |
1566 | } | ||
1567 | |||
1568 | /* this function is called at probe time */ | ||
1569 | static int sd_config(struct gspca_dev *gspca_dev, | ||
1570 | const struct usb_device_id *id) | ||
1571 | { | ||
1572 | struct sd *sd = (struct sd *) gspca_dev; | ||
1573 | struct cam *cam; | ||
1574 | int ret = 0; | ||
1575 | |||
1576 | sd->bridge = id->driver_info; | ||
1577 | |||
1578 | switch (sd->bridge) { | ||
1579 | case BRIDGE_OV518: | ||
1580 | case BRIDGE_OV518PLUS: | ||
1581 | ret = ov518_configure(gspca_dev); | ||
1582 | break; | ||
1583 | case BRIDGE_OV519: | ||
1584 | ret = ov519_configure(sd); | ||
1585 | break; | ||
1586 | } | ||
1587 | |||
1588 | if (ret) | ||
1317 | goto error; | 1589 | goto error; |
1590 | |||
1318 | ov51x_led_control(sd, 0); /* turn LED off */ | 1591 | ov51x_led_control(sd, 0); /* turn LED off */ |
1319 | 1592 | ||
1320 | /* Test for 76xx */ | 1593 | /* Test for 76xx */ |
@@ -1360,12 +1633,26 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1360 | } | 1633 | } |
1361 | 1634 | ||
1362 | cam = &gspca_dev->cam; | 1635 | cam = &gspca_dev->cam; |
1363 | if (!sd->sif) { | 1636 | switch (sd->bridge) { |
1364 | cam->cam_mode = vga_mode; | 1637 | case BRIDGE_OV518: |
1365 | cam->nmodes = ARRAY_SIZE(vga_mode); | 1638 | case BRIDGE_OV518PLUS: |
1366 | } else { | 1639 | if (!sd->sif) { |
1367 | cam->cam_mode = sif_mode; | 1640 | cam->cam_mode = ov518_vga_mode; |
1368 | cam->nmodes = ARRAY_SIZE(sif_mode); | 1641 | cam->nmodes = ARRAY_SIZE(ov518_vga_mode); |
1642 | } else { | ||
1643 | cam->cam_mode = ov518_sif_mode; | ||
1644 | cam->nmodes = ARRAY_SIZE(ov518_sif_mode); | ||
1645 | } | ||
1646 | break; | ||
1647 | case BRIDGE_OV519: | ||
1648 | if (!sd->sif) { | ||
1649 | cam->cam_mode = ov519_vga_mode; | ||
1650 | cam->nmodes = ARRAY_SIZE(ov519_vga_mode); | ||
1651 | } else { | ||
1652 | cam->cam_mode = ov519_sif_mode; | ||
1653 | cam->nmodes = ARRAY_SIZE(ov519_sif_mode); | ||
1654 | } | ||
1655 | break; | ||
1369 | } | 1656 | } |
1370 | sd->brightness = BRIGHTNESS_DEF; | 1657 | sd->brightness = BRIGHTNESS_DEF; |
1371 | sd->contrast = CONTRAST_DEF; | 1658 | sd->contrast = CONTRAST_DEF; |
@@ -1422,6 +1709,106 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1422 | return 0; | 1709 | return 0; |
1423 | } | 1710 | } |
1424 | 1711 | ||
1712 | /* Sets up the OV518/OV518+ with the given image parameters | ||
1713 | * | ||
1714 | * OV518 needs a completely different approach, until we can figure out what | ||
1715 | * the individual registers do. Also, only 15 FPS is supported now. | ||
1716 | * | ||
1717 | * Do not put any sensor-specific code in here (including I2C I/O functions) | ||
1718 | */ | ||
1719 | static int ov518_mode_init_regs(struct sd *sd) | ||
1720 | { | ||
1721 | int hsegs, vsegs; | ||
1722 | |||
1723 | /******** Set the mode ********/ | ||
1724 | |||
1725 | reg_w(sd, 0x2b, 0); | ||
1726 | reg_w(sd, 0x2c, 0); | ||
1727 | reg_w(sd, 0x2d, 0); | ||
1728 | reg_w(sd, 0x2e, 0); | ||
1729 | reg_w(sd, 0x3b, 0); | ||
1730 | reg_w(sd, 0x3c, 0); | ||
1731 | reg_w(sd, 0x3d, 0); | ||
1732 | reg_w(sd, 0x3e, 0); | ||
1733 | |||
1734 | if (sd->bridge == BRIDGE_OV518) { | ||
1735 | /* Set 8-bit (YVYU) input format */ | ||
1736 | reg_w_mask(sd, 0x20, 0x08, 0x08); | ||
1737 | |||
1738 | /* Set 12-bit (4:2:0) output format */ | ||
1739 | reg_w_mask(sd, 0x28, 0x80, 0xf0); | ||
1740 | reg_w_mask(sd, 0x38, 0x80, 0xf0); | ||
1741 | } else { | ||
1742 | reg_w(sd, 0x28, 0x80); | ||
1743 | reg_w(sd, 0x38, 0x80); | ||
1744 | } | ||
1745 | |||
1746 | hsegs = sd->gspca_dev.width / 16; | ||
1747 | vsegs = sd->gspca_dev.height / 4; | ||
1748 | |||
1749 | reg_w(sd, 0x29, hsegs); | ||
1750 | reg_w(sd, 0x2a, vsegs); | ||
1751 | |||
1752 | reg_w(sd, 0x39, hsegs); | ||
1753 | reg_w(sd, 0x3a, vsegs); | ||
1754 | |||
1755 | /* Windows driver does this here; who knows why */ | ||
1756 | reg_w(sd, 0x2f, 0x80); | ||
1757 | |||
1758 | /******** Set the framerate (to 30 FPS) ********/ | ||
1759 | if (sd->bridge == BRIDGE_OV518PLUS) | ||
1760 | sd->clockdiv = 1; | ||
1761 | else | ||
1762 | sd->clockdiv = 0; | ||
1763 | |||
1764 | /* Mode independent, but framerate dependent, regs */ | ||
1765 | reg_w(sd, 0x51, 0x04); /* Clock divider; lower==faster */ | ||
1766 | reg_w(sd, 0x22, 0x18); | ||
1767 | reg_w(sd, 0x23, 0xff); | ||
1768 | |||
1769 | if (sd->bridge == BRIDGE_OV518PLUS) | ||
1770 | reg_w(sd, 0x21, 0x19); | ||
1771 | else | ||
1772 | reg_w(sd, 0x71, 0x17); /* Compression-related? */ | ||
1773 | |||
1774 | /* FIXME: Sensor-specific */ | ||
1775 | /* Bit 5 is what matters here. Of course, it is "reserved" */ | ||
1776 | i2c_w(sd, 0x54, 0x23); | ||
1777 | |||
1778 | reg_w(sd, 0x2f, 0x80); | ||
1779 | |||
1780 | if (sd->bridge == BRIDGE_OV518PLUS) { | ||
1781 | reg_w(sd, 0x24, 0x94); | ||
1782 | reg_w(sd, 0x25, 0x90); | ||
1783 | ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ | ||
1784 | ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */ | ||
1785 | ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */ | ||
1786 | ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */ | ||
1787 | ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */ | ||
1788 | ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */ | ||
1789 | ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */ | ||
1790 | ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */ | ||
1791 | ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */ | ||
1792 | } else { | ||
1793 | reg_w(sd, 0x24, 0x9f); | ||
1794 | reg_w(sd, 0x25, 0x90); | ||
1795 | ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ | ||
1796 | ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */ | ||
1797 | ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */ | ||
1798 | ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */ | ||
1799 | ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */ | ||
1800 | ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */ | ||
1801 | ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */ | ||
1802 | ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */ | ||
1803 | ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */ | ||
1804 | } | ||
1805 | |||
1806 | reg_w(sd, 0x2f, 0x80); | ||
1807 | |||
1808 | return 0; | ||
1809 | } | ||
1810 | |||
1811 | |||
1425 | /* Sets up the OV519 with the given image parameters | 1812 | /* Sets up the OV519 with the given image parameters |
1426 | * | 1813 | * |
1427 | * OV519 needs a completely different approach, until we can figure out what | 1814 | * OV519 needs a completely different approach, until we can figure out what |
@@ -1740,6 +2127,11 @@ static int set_ov_sensor_window(struct sd *sd) | |||
1740 | hwebase = 0x3a; | 2127 | hwebase = 0x3a; |
1741 | vwsbase = 0x05; | 2128 | vwsbase = 0x05; |
1742 | vwebase = 0x06; | 2129 | vwebase = 0x06; |
2130 | if (qvga) { | ||
2131 | /* HDG: this fixes U and V getting swapped */ | ||
2132 | hwsbase--; | ||
2133 | vwsbase--; | ||
2134 | } | ||
1743 | break; | 2135 | break; |
1744 | case SEN_OV7620: | 2136 | case SEN_OV7620: |
1745 | hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ | 2137 | hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ |
@@ -1855,15 +2247,28 @@ static int set_ov_sensor_window(struct sd *sd) | |||
1855 | static int sd_start(struct gspca_dev *gspca_dev) | 2247 | static int sd_start(struct gspca_dev *gspca_dev) |
1856 | { | 2248 | { |
1857 | struct sd *sd = (struct sd *) gspca_dev; | 2249 | struct sd *sd = (struct sd *) gspca_dev; |
1858 | int ret; | 2250 | int ret = 0; |
1859 | 2251 | ||
1860 | ret = ov519_mode_init_regs(sd); | 2252 | switch (sd->bridge) { |
2253 | case BRIDGE_OV518: | ||
2254 | case BRIDGE_OV518PLUS: | ||
2255 | ret = ov518_mode_init_regs(sd); | ||
2256 | break; | ||
2257 | case BRIDGE_OV519: | ||
2258 | ret = ov519_mode_init_regs(sd); | ||
2259 | break; | ||
2260 | } | ||
1861 | if (ret < 0) | 2261 | if (ret < 0) |
1862 | goto out; | 2262 | goto out; |
2263 | |||
1863 | ret = set_ov_sensor_window(sd); | 2264 | ret = set_ov_sensor_window(sd); |
1864 | if (ret < 0) | 2265 | if (ret < 0) |
1865 | goto out; | 2266 | goto out; |
1866 | 2267 | ||
2268 | setcontrast(gspca_dev); | ||
2269 | setbrightness(gspca_dev); | ||
2270 | setcolors(gspca_dev); | ||
2271 | |||
1867 | ret = ov51x_restart(sd); | 2272 | ret = ov51x_restart(sd); |
1868 | if (ret < 0) | 2273 | if (ret < 0) |
1869 | goto out; | 2274 | goto out; |
@@ -1882,7 +2287,30 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
1882 | ov51x_led_control(sd, 0); | 2287 | ov51x_led_control(sd, 0); |
1883 | } | 2288 | } |
1884 | 2289 | ||
1885 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2290 | static void ov518_pkt_scan(struct gspca_dev *gspca_dev, |
2291 | struct gspca_frame *frame, /* target */ | ||
2292 | __u8 *data, /* isoc packet */ | ||
2293 | int len) /* iso packet length */ | ||
2294 | { | ||
2295 | PDEBUG(D_STREAM, "ov518_pkt_scan: %d bytes", len); | ||
2296 | |||
2297 | if (len & 7) { | ||
2298 | len--; | ||
2299 | PDEBUG(D_STREAM, "packet number: %d\n", (int)data[len]); | ||
2300 | } | ||
2301 | |||
2302 | /* A false positive here is likely, until OVT gives me | ||
2303 | * the definitive SOF/EOF format */ | ||
2304 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { | ||
2305 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); | ||
2306 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); | ||
2307 | } | ||
2308 | |||
2309 | /* intermediate packet */ | ||
2310 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
2311 | } | ||
2312 | |||
2313 | static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | ||
1886 | struct gspca_frame *frame, /* target */ | 2314 | struct gspca_frame *frame, /* target */ |
1887 | __u8 *data, /* isoc packet */ | 2315 | __u8 *data, /* isoc packet */ |
1888 | int len) /* iso packet length */ | 2316 | int len) /* iso packet length */ |
@@ -1926,6 +2354,27 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1926 | data, len); | 2354 | data, len); |
1927 | } | 2355 | } |
1928 | 2356 | ||
2357 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
2358 | struct gspca_frame *frame, /* target */ | ||
2359 | __u8 *data, /* isoc packet */ | ||
2360 | int len) /* iso packet length */ | ||
2361 | { | ||
2362 | struct sd *sd = (struct sd *) gspca_dev; | ||
2363 | |||
2364 | switch (sd->bridge) { | ||
2365 | case BRIDGE_OV511: | ||
2366 | case BRIDGE_OV511PLUS: | ||
2367 | break; | ||
2368 | case BRIDGE_OV518: | ||
2369 | case BRIDGE_OV518PLUS: | ||
2370 | ov518_pkt_scan(gspca_dev, frame, data, len); | ||
2371 | break; | ||
2372 | case BRIDGE_OV519: | ||
2373 | ov519_pkt_scan(gspca_dev, frame, data, len); | ||
2374 | break; | ||
2375 | } | ||
2376 | } | ||
2377 | |||
1929 | /* -- management routines -- */ | 2378 | /* -- management routines -- */ |
1930 | 2379 | ||
1931 | static void setbrightness(struct gspca_dev *gspca_dev) | 2380 | static void setbrightness(struct gspca_dev *gspca_dev) |
@@ -1970,6 +2419,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
1970 | break; | 2419 | break; |
1971 | case SEN_OV6630: | 2420 | case SEN_OV6630: |
1972 | i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); | 2421 | i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); |
2422 | break; | ||
1973 | case SEN_OV8610: { | 2423 | case SEN_OV8610: { |
1974 | static const __u8 ctab[] = { | 2424 | static const __u8 ctab[] = { |
1975 | 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f | 2425 | 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f |
@@ -2136,19 +2586,21 @@ static const struct sd_desc sd_desc = { | |||
2136 | 2586 | ||
2137 | /* -- module initialisation -- */ | 2587 | /* -- module initialisation -- */ |
2138 | static const __devinitdata struct usb_device_id device_table[] = { | 2588 | static const __devinitdata struct usb_device_id device_table[] = { |
2139 | {USB_DEVICE(0x041e, 0x4052)}, | 2589 | {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, |
2140 | {USB_DEVICE(0x041e, 0x405f)}, | 2590 | {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, |
2141 | {USB_DEVICE(0x041e, 0x4060)}, | 2591 | {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, |
2142 | {USB_DEVICE(0x041e, 0x4061)}, | 2592 | {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, |
2143 | {USB_DEVICE(0x041e, 0x4064)}, | 2593 | {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 }, |
2144 | {USB_DEVICE(0x041e, 0x4068)}, | 2594 | {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 }, |
2145 | {USB_DEVICE(0x045e, 0x028c)}, | 2595 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, |
2146 | {USB_DEVICE(0x054c, 0x0154)}, | 2596 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, |
2147 | {USB_DEVICE(0x054c, 0x0155)}, | 2597 | {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, |
2148 | {USB_DEVICE(0x05a9, 0x0519)}, | 2598 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, |
2149 | {USB_DEVICE(0x05a9, 0x0530)}, | 2599 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, |
2150 | {USB_DEVICE(0x05a9, 0x4519)}, | 2600 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, |
2151 | {USB_DEVICE(0x05a9, 0x8519)}, | 2601 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, |
2602 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, | ||
2603 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, | ||
2152 | {} | 2604 | {} |
2153 | }; | 2605 | }; |
2154 | 2606 | ||
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index ebb2ea6b4995..f24eceecc5a6 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
@@ -347,7 +347,8 @@ struct v4l2_pix_format { | |||
347 | #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ | 347 | #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ |
348 | #define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ | 348 | #define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ |
349 | #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ | 349 | #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ |
350 | #define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */ | 350 | #define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */ |
351 | #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ | ||
351 | 352 | ||
352 | /* | 353 | /* |
353 | * F O R M A T E N U M E R A T I O N | 354 | * F O R M A T E N U M E R A T I O N |