diff options
| author | Hans de Goede <hdegoede@redhat.com> | 2009-06-14 05:45:50 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-23 02:12:37 -0400 |
| commit | 1876bb923c98c605eca69f0bfe295f7b5f5eba28 (patch) | |
| tree | ddc996e7e15a9ec803e5cfeb8bf341af30fae7fa | |
| parent | f5cee95c2e4c56b50cdb8edd33cf04902946cd25 (diff) | |
V4L/DVB (12079): gspca_ov519: add support for the ov511 bridge
gspca_ov519: add support for the ov511 bridge
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/media/video/gspca/ov519.c | 533 | ||||
| -rw-r--r-- | include/linux/videodev2.h | 1 |
2 files changed, 521 insertions, 13 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 9d4b69dbf966..1f8e2613ecc5 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
| @@ -76,8 +76,8 @@ struct sd { | |||
| 76 | 76 | ||
| 77 | __u8 stopped; /* Streaming is temporarily paused */ | 77 | __u8 stopped; /* Streaming is temporarily paused */ |
| 78 | 78 | ||
| 79 | __u8 frame_rate; /* current Framerate (OV519 only) */ | 79 | __u8 frame_rate; /* current Framerate */ |
| 80 | __u8 clockdiv; /* clockdiv override for OV519 only */ | 80 | __u8 clockdiv; /* clockdiv override */ |
| 81 | 81 | ||
| 82 | char sensor; /* Type of image sensor chip (SEN_*) */ | 82 | char sensor; /* Type of image sensor chip (SEN_*) */ |
| 83 | #define SEN_UNKNOWN 0 | 83 | #define SEN_UNKNOWN 0 |
| @@ -304,17 +304,77 @@ static const struct v4l2_pix_format ov518_sif_mode[] = { | |||
| 304 | .priv = 0}, | 304 | .priv = 0}, |
| 305 | }; | 305 | }; |
| 306 | 306 | ||
| 307 | static const struct v4l2_pix_format ov511_vga_mode[] = { | ||
| 308 | {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
| 309 | .bytesperline = 320, | ||
| 310 | .sizeimage = 320 * 240 * 3, | ||
| 311 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
| 312 | .priv = 1}, | ||
| 313 | {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
| 314 | .bytesperline = 640, | ||
| 315 | .sizeimage = 640 * 480 * 2, | ||
| 316 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
| 317 | .priv = 0}, | ||
| 318 | }; | ||
| 319 | static const struct v4l2_pix_format ov511_sif_mode[] = { | ||
| 320 | {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
| 321 | .bytesperline = 160, | ||
| 322 | .sizeimage = 40000, | ||
| 323 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
| 324 | .priv = 3}, | ||
| 325 | {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
| 326 | .bytesperline = 176, | ||
| 327 | .sizeimage = 40000, | ||
| 328 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
| 329 | .priv = 1}, | ||
| 330 | {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
| 331 | .bytesperline = 320, | ||
| 332 | .sizeimage = 320 * 240 * 3, | ||
| 333 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
| 334 | .priv = 2}, | ||
| 335 | {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
| 336 | .bytesperline = 352, | ||
| 337 | .sizeimage = 352 * 288 * 3, | ||
| 338 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
| 339 | .priv = 0}, | ||
| 340 | }; | ||
| 307 | 341 | ||
| 308 | /* Registers common to OV511 / OV518 */ | 342 | /* Registers common to OV511 / OV518 */ |
| 343 | #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ | ||
| 309 | #define R51x_SYS_RESET 0x50 | 344 | #define R51x_SYS_RESET 0x50 |
| 345 | /* Reset type flags */ | ||
| 346 | #define OV511_RESET_OMNICE 0x08 | ||
| 310 | #define R51x_SYS_INIT 0x53 | 347 | #define R51x_SYS_INIT 0x53 |
| 311 | #define R51x_SYS_SNAP 0x52 | 348 | #define R51x_SYS_SNAP 0x52 |
| 312 | #define R51x_SYS_CUST_ID 0x5F | 349 | #define R51x_SYS_CUST_ID 0x5F |
| 313 | #define R51x_COMP_LUT_BEGIN 0x80 | 350 | #define R51x_COMP_LUT_BEGIN 0x80 |
| 314 | 351 | ||
| 315 | /* OV511 Camera interface register numbers */ | 352 | /* OV511 Camera interface register numbers */ |
| 353 | #define R511_CAM_DELAY 0x10 | ||
| 354 | #define R511_CAM_EDGE 0x11 | ||
| 355 | #define R511_CAM_PXCNT 0x12 | ||
| 356 | #define R511_CAM_LNCNT 0x13 | ||
| 357 | #define R511_CAM_PXDIV 0x14 | ||
| 358 | #define R511_CAM_LNDIV 0x15 | ||
| 359 | #define R511_CAM_UV_EN 0x16 | ||
| 360 | #define R511_CAM_LINE_MODE 0x17 | ||
| 361 | #define R511_CAM_OPTS 0x18 | ||
| 362 | |||
| 363 | #define R511_SNAP_FRAME 0x19 | ||
| 364 | #define R511_SNAP_PXCNT 0x1A | ||
| 365 | #define R511_SNAP_LNCNT 0x1B | ||
| 366 | #define R511_SNAP_PXDIV 0x1C | ||
| 367 | #define R511_SNAP_LNDIV 0x1D | ||
| 368 | #define R511_SNAP_UV_EN 0x1E | ||
| 369 | #define R511_SNAP_UV_EN 0x1E | ||
| 370 | #define R511_SNAP_OPTS 0x1F | ||
| 371 | |||
| 372 | #define R511_DRAM_FLOW_CTL 0x20 | ||
| 373 | #define R511_FIFO_OPTS 0x31 | ||
| 374 | #define R511_I2C_CTL 0x40 | ||
| 316 | #define R511_SYS_LED_CTL 0x55 /* OV511+ only */ | 375 | #define R511_SYS_LED_CTL 0x55 /* OV511+ only */ |
| 317 | #define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ | 376 | #define R511_COMP_EN 0x78 |
| 377 | #define R511_COMP_LUT_EN 0x79 | ||
| 318 | 378 | ||
| 319 | /* OV518 Camera interface register numbers */ | 379 | /* OV518 Camera interface register numbers */ |
| 320 | #define R518_GPIO_OUT 0x56 /* OV518(+) only */ | 380 | #define R518_GPIO_OUT 0x56 /* OV518(+) only */ |
| @@ -1079,13 +1139,128 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) | |||
| 1079 | return ret; | 1139 | return ret; |
| 1080 | } | 1140 | } |
| 1081 | 1141 | ||
| 1142 | static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) | ||
| 1143 | { | ||
| 1144 | int rc, retries; | ||
| 1145 | |||
| 1146 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); | ||
| 1147 | |||
| 1148 | /* Three byte write cycle */ | ||
| 1149 | for (retries = 6; ; ) { | ||
| 1150 | /* Select camera register */ | ||
| 1151 | rc = reg_w(sd, R51x_I2C_SADDR_3, reg); | ||
| 1152 | if (rc < 0) | ||
| 1153 | return rc; | ||
| 1154 | |||
| 1155 | /* Write "value" to I2C data port of OV511 */ | ||
| 1156 | rc = reg_w(sd, R51x_I2C_DATA, value); | ||
| 1157 | if (rc < 0) | ||
| 1158 | return rc; | ||
| 1159 | |||
| 1160 | /* Initiate 3-byte write cycle */ | ||
| 1161 | rc = reg_w(sd, R511_I2C_CTL, 0x01); | ||
| 1162 | if (rc < 0) | ||
| 1163 | return rc; | ||
| 1164 | |||
| 1165 | do | ||
| 1166 | rc = reg_r(sd, R511_I2C_CTL); | ||
| 1167 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | ||
| 1168 | |||
| 1169 | if (rc < 0) | ||
| 1170 | return rc; | ||
| 1171 | |||
| 1172 | if ((rc & 2) == 0) /* Ack? */ | ||
| 1173 | break; | ||
| 1174 | if (--retries < 0) { | ||
| 1175 | PDEBUG(D_USBO, "i2c write retries exhausted"); | ||
| 1176 | return -1; | ||
| 1177 | } | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | return 0; | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | static int ov511_i2c_r(struct sd *sd, __u8 reg) | ||
| 1184 | { | ||
| 1185 | int rc, value, retries; | ||
| 1186 | |||
| 1187 | /* Two byte write cycle */ | ||
| 1188 | for (retries = 6; ; ) { | ||
| 1189 | /* Select camera register */ | ||
| 1190 | rc = reg_w(sd, R51x_I2C_SADDR_2, reg); | ||
| 1191 | if (rc < 0) | ||
| 1192 | return rc; | ||
| 1193 | |||
| 1194 | /* Initiate 2-byte write cycle */ | ||
| 1195 | rc = reg_w(sd, R511_I2C_CTL, 0x03); | ||
| 1196 | if (rc < 0) | ||
| 1197 | return rc; | ||
| 1198 | |||
| 1199 | do | ||
| 1200 | rc = reg_r(sd, R511_I2C_CTL); | ||
| 1201 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | ||
| 1202 | |||
| 1203 | if (rc < 0) | ||
| 1204 | return rc; | ||
| 1205 | |||
| 1206 | if ((rc & 2) == 0) /* Ack? */ | ||
| 1207 | break; | ||
| 1208 | |||
| 1209 | /* I2C abort */ | ||
| 1210 | reg_w(sd, R511_I2C_CTL, 0x10); | ||
| 1211 | |||
| 1212 | if (--retries < 0) { | ||
| 1213 | PDEBUG(D_USBI, "i2c write retries exhausted"); | ||
| 1214 | return -1; | ||
| 1215 | } | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | /* Two byte read cycle */ | ||
| 1219 | for (retries = 6; ; ) { | ||
| 1220 | /* Initiate 2-byte read cycle */ | ||
| 1221 | rc = reg_w(sd, R511_I2C_CTL, 0x05); | ||
| 1222 | if (rc < 0) | ||
| 1223 | return rc; | ||
| 1224 | |||
| 1225 | do | ||
| 1226 | rc = reg_r(sd, R511_I2C_CTL); | ||
| 1227 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | ||
| 1228 | |||
| 1229 | if (rc < 0) | ||
| 1230 | return rc; | ||
| 1231 | |||
| 1232 | if ((rc & 2) == 0) /* Ack? */ | ||
| 1233 | break; | ||
| 1234 | |||
| 1235 | /* I2C abort */ | ||
| 1236 | rc = reg_w(sd, R511_I2C_CTL, 0x10); | ||
| 1237 | if (rc < 0) | ||
| 1238 | return rc; | ||
| 1239 | |||
| 1240 | if (--retries < 0) { | ||
| 1241 | PDEBUG(D_USBI, "i2c read retries exhausted"); | ||
| 1242 | return -1; | ||
| 1243 | } | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | value = reg_r(sd, R51x_I2C_DATA); | ||
| 1247 | |||
| 1248 | PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); | ||
| 1249 | |||
| 1250 | /* This is needed to make i2c_w() work */ | ||
| 1251 | rc = reg_w(sd, R511_I2C_CTL, 0x05); | ||
| 1252 | if (rc < 0) | ||
| 1253 | return rc; | ||
| 1254 | |||
| 1255 | return value; | ||
| 1256 | } | ||
| 1082 | 1257 | ||
| 1083 | /* | 1258 | /* |
| 1084 | * The OV518 I2C I/O procedure is different, hence, this function. | 1259 | * The OV518 I2C I/O procedure is different, hence, this function. |
| 1085 | * This is normally only called from i2c_w(). Note that this function | 1260 | * This is normally only called from i2c_w(). Note that this function |
| 1086 | * always succeeds regardless of whether the sensor is present and working. | 1261 | * always succeeds regardless of whether the sensor is present and working. |
| 1087 | */ | 1262 | */ |
| 1088 | static int i2c_w(struct sd *sd, | 1263 | static int ov518_i2c_w(struct sd *sd, |
| 1089 | __u8 reg, | 1264 | __u8 reg, |
| 1090 | __u8 value) | 1265 | __u8 value) |
| 1091 | { | 1266 | { |
| @@ -1120,7 +1295,7 @@ static int i2c_w(struct sd *sd, | |||
| 1120 | * This is normally only called from i2c_r(). Note that this function | 1295 | * This is normally only called from i2c_r(). Note that this function |
| 1121 | * always succeeds regardless of whether the sensor is present and working. | 1296 | * always succeeds regardless of whether the sensor is present and working. |
| 1122 | */ | 1297 | */ |
| 1123 | static int i2c_r(struct sd *sd, __u8 reg) | 1298 | static int ov518_i2c_r(struct sd *sd, __u8 reg) |
| 1124 | { | 1299 | { |
| 1125 | int rc, value; | 1300 | int rc, value; |
| 1126 | 1301 | ||
| @@ -1143,6 +1318,34 @@ static int i2c_r(struct sd *sd, __u8 reg) | |||
| 1143 | return value; | 1318 | return value; |
| 1144 | } | 1319 | } |
| 1145 | 1320 | ||
| 1321 | static int i2c_w(struct sd *sd, __u8 reg, __u8 value) | ||
| 1322 | { | ||
| 1323 | switch (sd->bridge) { | ||
| 1324 | case BRIDGE_OV511: | ||
| 1325 | case BRIDGE_OV511PLUS: | ||
| 1326 | return ov511_i2c_w(sd, reg, value); | ||
| 1327 | case BRIDGE_OV518: | ||
| 1328 | case BRIDGE_OV518PLUS: | ||
| 1329 | case BRIDGE_OV519: | ||
| 1330 | return ov518_i2c_w(sd, reg, value); | ||
| 1331 | } | ||
| 1332 | return -1; /* Should never happen */ | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | static int i2c_r(struct sd *sd, __u8 reg) | ||
| 1336 | { | ||
| 1337 | switch (sd->bridge) { | ||
| 1338 | case BRIDGE_OV511: | ||
| 1339 | case BRIDGE_OV511PLUS: | ||
| 1340 | return ov511_i2c_r(sd, reg); | ||
| 1341 | case BRIDGE_OV518: | ||
| 1342 | case BRIDGE_OV518PLUS: | ||
| 1343 | case BRIDGE_OV519: | ||
| 1344 | return ov518_i2c_r(sd, reg); | ||
| 1345 | } | ||
| 1346 | return -1; /* Should never happen */ | ||
| 1347 | } | ||
| 1348 | |||
| 1146 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in | 1349 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in |
| 1147 | * the same position as 1's in "mask" are cleared and set to "value". Bits | 1350 | * the same position as 1's in "mask" are cleared and set to "value". Bits |
| 1148 | * that are in the same position as 0's in "mask" are preserved, regardless | 1351 | * that are in the same position as 0's in "mask" are preserved, regardless |
| @@ -1490,9 +1693,31 @@ static void ov51x_led_control(struct sd *sd, int on) | |||
| 1490 | } | 1693 | } |
| 1491 | } | 1694 | } |
| 1492 | 1695 | ||
| 1493 | /* OV518 quantization tables are 8x4 (instead of 8x8) */ | 1696 | static int ov51x_upload_quan_tables(struct sd *sd) |
| 1494 | static int ov518_upload_quan_tables(struct sd *sd) | ||
| 1495 | { | 1697 | { |
| 1698 | const unsigned char yQuanTable511[] = { | ||
| 1699 | 0, 1, 1, 2, 2, 3, 3, 4, | ||
| 1700 | 1, 1, 1, 2, 2, 3, 4, 4, | ||
| 1701 | 1, 1, 2, 2, 3, 4, 4, 4, | ||
| 1702 | 2, 2, 2, 3, 4, 4, 4, 4, | ||
| 1703 | 2, 2, 3, 4, 4, 5, 5, 5, | ||
| 1704 | 3, 3, 4, 4, 5, 5, 5, 5, | ||
| 1705 | 3, 4, 4, 4, 5, 5, 5, 5, | ||
| 1706 | 4, 4, 4, 4, 5, 5, 5, 5 | ||
| 1707 | }; | ||
| 1708 | |||
| 1709 | const unsigned char uvQuanTable511[] = { | ||
| 1710 | 0, 2, 2, 3, 4, 4, 4, 4, | ||
| 1711 | 2, 2, 2, 4, 4, 4, 4, 4, | ||
| 1712 | 2, 2, 3, 4, 4, 4, 4, 4, | ||
| 1713 | 3, 4, 4, 4, 4, 4, 4, 4, | ||
| 1714 | 4, 4, 4, 4, 4, 4, 4, 4, | ||
| 1715 | 4, 4, 4, 4, 4, 4, 4, 4, | ||
| 1716 | 4, 4, 4, 4, 4, 4, 4, 4, | ||
| 1717 | 4, 4, 4, 4, 4, 4, 4, 4 | ||
| 1718 | }; | ||
| 1719 | |||
| 1720 | /* OV518 quantization tables are 8x4 (instead of 8x8) */ | ||
| 1496 | const unsigned char yQuanTable518[] = { | 1721 | const unsigned char yQuanTable518[] = { |
| 1497 | 5, 4, 5, 6, 6, 7, 7, 7, | 1722 | 5, 4, 5, 6, 6, 7, 7, 7, |
| 1498 | 5, 5, 5, 5, 6, 7, 7, 7, | 1723 | 5, 5, 5, 5, 6, 7, 7, 7, |
| @@ -1507,14 +1732,23 @@ static int ov518_upload_quan_tables(struct sd *sd) | |||
| 1507 | 7, 7, 7, 7, 7, 7, 8, 8 | 1732 | 7, 7, 7, 7, 7, 7, 8, 8 |
| 1508 | }; | 1733 | }; |
| 1509 | 1734 | ||
| 1510 | const unsigned char *pYTable = yQuanTable518; | 1735 | const unsigned char *pYTable, *pUVTable; |
| 1511 | const unsigned char *pUVTable = uvQuanTable518; | ||
| 1512 | unsigned char val0, val1; | 1736 | unsigned char val0, val1; |
| 1513 | int i, rc, reg = R51x_COMP_LUT_BEGIN; | 1737 | int i, size, rc, reg = R51x_COMP_LUT_BEGIN; |
| 1514 | 1738 | ||
| 1515 | PDEBUG(D_PROBE, "Uploading quantization tables"); | 1739 | PDEBUG(D_PROBE, "Uploading quantization tables"); |
| 1516 | 1740 | ||
| 1517 | for (i = 0; i < 16; i++) { | 1741 | if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { |
| 1742 | pYTable = yQuanTable511; | ||
| 1743 | pUVTable = uvQuanTable511; | ||
| 1744 | size = 32; | ||
| 1745 | } else { | ||
| 1746 | pYTable = yQuanTable518; | ||
| 1747 | pUVTable = uvQuanTable518; | ||
| 1748 | size = 16; | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | for (i = 0; i < size; i++) { | ||
| 1518 | val0 = *pYTable++; | 1752 | val0 = *pYTable++; |
| 1519 | val1 = *pYTable++; | 1753 | val1 = *pYTable++; |
| 1520 | val0 &= 0x0f; | 1754 | val0 &= 0x0f; |
| @@ -1529,7 +1763,7 @@ static int ov518_upload_quan_tables(struct sd *sd) | |||
| 1529 | val0 &= 0x0f; | 1763 | val0 &= 0x0f; |
| 1530 | val1 &= 0x0f; | 1764 | val1 &= 0x0f; |
| 1531 | val0 |= val1 << 4; | 1765 | val0 |= val1 << 4; |
| 1532 | rc = reg_w(sd, reg + 16, val0); | 1766 | rc = reg_w(sd, reg + size, val0); |
| 1533 | if (rc < 0) | 1767 | if (rc < 0) |
| 1534 | return rc; | 1768 | return rc; |
| 1535 | 1769 | ||
| @@ -1539,6 +1773,87 @@ static int ov518_upload_quan_tables(struct sd *sd) | |||
| 1539 | return 0; | 1773 | return 0; |
| 1540 | } | 1774 | } |
| 1541 | 1775 | ||
| 1776 | /* This initializes the OV511/OV511+ and the sensor */ | ||
| 1777 | static int ov511_configure(struct gspca_dev *gspca_dev) | ||
| 1778 | { | ||
| 1779 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 1780 | int rc; | ||
| 1781 | |||
| 1782 | /* For 511 and 511+ */ | ||
| 1783 | const struct ov_regvals init_511[] = { | ||
| 1784 | { R51x_SYS_RESET, 0x7f }, | ||
| 1785 | { R51x_SYS_INIT, 0x01 }, | ||
| 1786 | { R51x_SYS_RESET, 0x7f }, | ||
| 1787 | { R51x_SYS_INIT, 0x01 }, | ||
| 1788 | { R51x_SYS_RESET, 0x3f }, | ||
| 1789 | { R51x_SYS_INIT, 0x01 }, | ||
| 1790 | { R51x_SYS_RESET, 0x3d }, | ||
| 1791 | }; | ||
| 1792 | |||
| 1793 | const struct ov_regvals norm_511[] = { | ||
| 1794 | { R511_DRAM_FLOW_CTL, 0x01 }, | ||
| 1795 | { R51x_SYS_SNAP, 0x00 }, | ||
| 1796 | { R51x_SYS_SNAP, 0x02 }, | ||
| 1797 | { R51x_SYS_SNAP, 0x00 }, | ||
| 1798 | { R511_FIFO_OPTS, 0x1f }, | ||
| 1799 | { R511_COMP_EN, 0x00 }, | ||
| 1800 | { R511_COMP_LUT_EN, 0x03 }, | ||
| 1801 | }; | ||
| 1802 | |||
| 1803 | const struct ov_regvals norm_511_p[] = { | ||
| 1804 | { R511_DRAM_FLOW_CTL, 0xff }, | ||
| 1805 | { R51x_SYS_SNAP, 0x00 }, | ||
| 1806 | { R51x_SYS_SNAP, 0x02 }, | ||
| 1807 | { R51x_SYS_SNAP, 0x00 }, | ||
| 1808 | { R511_FIFO_OPTS, 0xff }, | ||
| 1809 | { R511_COMP_EN, 0x00 }, | ||
| 1810 | { R511_COMP_LUT_EN, 0x03 }, | ||
| 1811 | }; | ||
| 1812 | |||
| 1813 | const struct ov_regvals compress_511[] = { | ||
| 1814 | { 0x70, 0x1f }, | ||
| 1815 | { 0x71, 0x05 }, | ||
| 1816 | { 0x72, 0x06 }, | ||
| 1817 | { 0x73, 0x06 }, | ||
| 1818 | { 0x74, 0x14 }, | ||
| 1819 | { 0x75, 0x03 }, | ||
| 1820 | { 0x76, 0x04 }, | ||
| 1821 | { 0x77, 0x04 }, | ||
| 1822 | }; | ||
| 1823 | |||
| 1824 | PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); | ||
| 1825 | |||
| 1826 | rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511)); | ||
| 1827 | if (rc < 0) | ||
| 1828 | return rc; | ||
| 1829 | |||
| 1830 | switch (sd->bridge) { | ||
| 1831 | case BRIDGE_OV511: | ||
| 1832 | rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); | ||
| 1833 | if (rc < 0) | ||
| 1834 | return rc; | ||
| 1835 | break; | ||
| 1836 | case BRIDGE_OV511PLUS: | ||
| 1837 | rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); | ||
| 1838 | if (rc < 0) | ||
| 1839 | return rc; | ||
| 1840 | break; | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | /* Init compression */ | ||
| 1844 | rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); | ||
| 1845 | if (rc < 0) | ||
| 1846 | return rc; | ||
| 1847 | |||
| 1848 | rc = ov51x_upload_quan_tables(sd); | ||
| 1849 | if (rc < 0) { | ||
| 1850 | PDEBUG(D_ERR, "Error uploading quantization tables"); | ||
| 1851 | return rc; | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | return 0; | ||
| 1855 | } | ||
| 1856 | |||
| 1542 | /* This initializes the OV518/OV518+ and the sensor */ | 1857 | /* This initializes the OV518/OV518+ and the sensor */ |
| 1543 | static int ov518_configure(struct gspca_dev *gspca_dev) | 1858 | static int ov518_configure(struct gspca_dev *gspca_dev) |
| 1544 | { | 1859 | { |
| @@ -1615,7 +1930,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) | |||
| 1615 | break; | 1930 | break; |
| 1616 | } | 1931 | } |
| 1617 | 1932 | ||
| 1618 | rc = ov518_upload_quan_tables(sd); | 1933 | rc = ov51x_upload_quan_tables(sd); |
| 1619 | if (rc < 0) { | 1934 | if (rc < 0) { |
| 1620 | PDEBUG(D_ERR, "Error uploading quantization tables"); | 1935 | PDEBUG(D_ERR, "Error uploading quantization tables"); |
| 1621 | return rc; | 1936 | return rc; |
| @@ -1661,6 +1976,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 1661 | sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; | 1976 | sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; |
| 1662 | 1977 | ||
| 1663 | switch (sd->bridge) { | 1978 | switch (sd->bridge) { |
| 1979 | case BRIDGE_OV511: | ||
| 1980 | case BRIDGE_OV511PLUS: | ||
| 1981 | ret = ov511_configure(gspca_dev); | ||
| 1982 | break; | ||
| 1664 | case BRIDGE_OV518: | 1983 | case BRIDGE_OV518: |
| 1665 | case BRIDGE_OV518PLUS: | 1984 | case BRIDGE_OV518PLUS: |
| 1666 | ret = ov518_configure(gspca_dev); | 1985 | ret = ov518_configure(gspca_dev); |
| @@ -1719,6 +2038,16 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 1719 | 2038 | ||
| 1720 | cam = &gspca_dev->cam; | 2039 | cam = &gspca_dev->cam; |
| 1721 | switch (sd->bridge) { | 2040 | switch (sd->bridge) { |
| 2041 | case BRIDGE_OV511: | ||
| 2042 | case BRIDGE_OV511PLUS: | ||
| 2043 | if (!sd->sif) { | ||
| 2044 | cam->cam_mode = ov511_vga_mode; | ||
| 2045 | cam->nmodes = ARRAY_SIZE(ov511_vga_mode); | ||
| 2046 | } else { | ||
| 2047 | cam->cam_mode = ov511_sif_mode; | ||
| 2048 | cam->nmodes = ARRAY_SIZE(ov511_sif_mode); | ||
| 2049 | } | ||
| 2050 | break; | ||
| 1722 | case BRIDGE_OV518: | 2051 | case BRIDGE_OV518: |
| 1723 | case BRIDGE_OV518PLUS: | 2052 | case BRIDGE_OV518PLUS: |
| 1724 | if (!sd->sif) { | 2053 | if (!sd->sif) { |
| @@ -1810,6 +2139,126 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 1810 | return 0; | 2139 | return 0; |
| 1811 | } | 2140 | } |
| 1812 | 2141 | ||
| 2142 | /* Set up the OV511/OV511+ with the given image parameters. | ||
| 2143 | * | ||
| 2144 | * Do not put any sensor-specific code in here (including I2C I/O functions) | ||
| 2145 | */ | ||
| 2146 | static int ov511_mode_init_regs(struct sd *sd) | ||
| 2147 | { | ||
| 2148 | int hsegs, vsegs, packet_size, fps, needed; | ||
| 2149 | int interlaced = 0; | ||
| 2150 | struct usb_host_interface *alt; | ||
| 2151 | struct usb_interface *intf; | ||
| 2152 | |||
| 2153 | intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); | ||
| 2154 | alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); | ||
| 2155 | if (!alt) { | ||
| 2156 | PDEBUG(D_ERR, "Couldn't get altsetting"); | ||
| 2157 | return -EIO; | ||
| 2158 | } | ||
| 2159 | |||
| 2160 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | ||
| 2161 | reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); | ||
| 2162 | |||
| 2163 | reg_w(sd, R511_CAM_UV_EN, 0x01); | ||
| 2164 | reg_w(sd, R511_SNAP_UV_EN, 0x01); | ||
| 2165 | reg_w(sd, R511_SNAP_OPTS, 0x03); | ||
| 2166 | |||
| 2167 | /* Here I'm assuming that snapshot size == image size. | ||
| 2168 | * I hope that's always true. --claudio | ||
| 2169 | */ | ||
| 2170 | hsegs = (sd->gspca_dev.width >> 3) - 1; | ||
| 2171 | vsegs = (sd->gspca_dev.height >> 3) - 1; | ||
| 2172 | |||
| 2173 | reg_w(sd, R511_CAM_PXCNT, hsegs); | ||
| 2174 | reg_w(sd, R511_CAM_LNCNT, vsegs); | ||
| 2175 | reg_w(sd, R511_CAM_PXDIV, 0x00); | ||
| 2176 | reg_w(sd, R511_CAM_LNDIV, 0x00); | ||
| 2177 | |||
| 2178 | /* YUV420, low pass filter on */ | ||
| 2179 | reg_w(sd, R511_CAM_OPTS, 0x03); | ||
| 2180 | |||
| 2181 | /* Snapshot additions */ | ||
| 2182 | reg_w(sd, R511_SNAP_PXCNT, hsegs); | ||
| 2183 | reg_w(sd, R511_SNAP_LNCNT, vsegs); | ||
| 2184 | reg_w(sd, R511_SNAP_PXDIV, 0x00); | ||
| 2185 | reg_w(sd, R511_SNAP_LNDIV, 0x00); | ||
| 2186 | |||
| 2187 | /******** Set the framerate ********/ | ||
| 2188 | if (frame_rate > 0) | ||
| 2189 | sd->frame_rate = frame_rate; | ||
| 2190 | |||
| 2191 | switch (sd->sensor) { | ||
| 2192 | case SEN_OV6620: | ||
| 2193 | /* No framerate control, doesn't like higher rates yet */ | ||
| 2194 | sd->clockdiv = 3; | ||
| 2195 | break; | ||
| 2196 | |||
| 2197 | /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed | ||
| 2198 | for more sensors we need to do this for them too */ | ||
| 2199 | case SEN_OV7620: | ||
| 2200 | case SEN_OV7640: | ||
| 2201 | if (sd->gspca_dev.width == 320) | ||
| 2202 | interlaced = 1; | ||
| 2203 | /* Fall through */ | ||
| 2204 | case SEN_OV6630: | ||
| 2205 | case SEN_OV76BE: | ||
| 2206 | case SEN_OV7610: | ||
| 2207 | case SEN_OV7670: | ||
| 2208 | switch (sd->frame_rate) { | ||
| 2209 | case 30: | ||
| 2210 | case 25: | ||
| 2211 | /* Not enough bandwidth to do 640x480 @ 30 fps */ | ||
| 2212 | if (sd->gspca_dev.width != 640) { | ||
| 2213 | sd->clockdiv = 0; | ||
| 2214 | break; | ||
| 2215 | } | ||
| 2216 | /* Fall through for 640x480 case */ | ||
| 2217 | default: | ||
| 2218 | /* case 20: */ | ||
| 2219 | /* case 15: */ | ||
| 2220 | sd->clockdiv = 1; | ||
| 2221 | break; | ||
| 2222 | case 10: | ||
| 2223 | sd->clockdiv = 2; | ||
| 2224 | break; | ||
| 2225 | case 5: | ||
| 2226 | sd->clockdiv = 5; | ||
| 2227 | break; | ||
| 2228 | } | ||
| 2229 | if (interlaced) { | ||
| 2230 | sd->clockdiv = (sd->clockdiv + 1) * 2 - 1; | ||
| 2231 | /* Higher then 10 does not work */ | ||
| 2232 | if (sd->clockdiv > 10) | ||
| 2233 | sd->clockdiv = 10; | ||
| 2234 | } | ||
| 2235 | break; | ||
| 2236 | |||
| 2237 | case SEN_OV8610: | ||
| 2238 | /* No framerate control ?? */ | ||
| 2239 | sd->clockdiv = 0; | ||
| 2240 | break; | ||
| 2241 | } | ||
| 2242 | |||
| 2243 | /* Check if we have enough bandwidth to disable compression */ | ||
| 2244 | fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; | ||
| 2245 | needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2; | ||
| 2246 | /* 1400 is a conservative estimate of the max nr of isoc packets/sec */ | ||
| 2247 | if (needed > 1400 * packet_size) { | ||
| 2248 | /* Enable Y and UV quantization and compression */ | ||
| 2249 | reg_w(sd, R511_COMP_EN, 0x07); | ||
| 2250 | reg_w(sd, R511_COMP_LUT_EN, 0x03); | ||
| 2251 | } else { | ||
| 2252 | reg_w(sd, R511_COMP_EN, 0x06); | ||
| 2253 | reg_w(sd, R511_COMP_LUT_EN, 0x00); | ||
| 2254 | } | ||
| 2255 | |||
| 2256 | reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); | ||
| 2257 | reg_w(sd, R51x_SYS_RESET, 0); | ||
| 2258 | |||
| 2259 | return 0; | ||
| 2260 | } | ||
| 2261 | |||
| 1813 | /* Sets up the OV518/OV518+ with the given image parameters | 2262 | /* Sets up the OV518/OV518+ with the given image parameters |
| 1814 | * | 2263 | * |
| 1815 | * OV518 needs a completely different approach, until we can figure out what | 2264 | * OV518 needs a completely different approach, until we can figure out what |
| @@ -2363,6 +2812,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
| 2363 | int ret = 0; | 2812 | int ret = 0; |
| 2364 | 2813 | ||
| 2365 | switch (sd->bridge) { | 2814 | switch (sd->bridge) { |
| 2815 | case BRIDGE_OV511: | ||
| 2816 | case BRIDGE_OV511PLUS: | ||
| 2817 | ret = ov511_mode_init_regs(sd); | ||
| 2818 | break; | ||
| 2366 | case BRIDGE_OV518: | 2819 | case BRIDGE_OV518: |
| 2367 | case BRIDGE_OV518PLUS: | 2820 | case BRIDGE_OV518PLUS: |
| 2368 | ret = ov518_mode_init_regs(sd); | 2821 | ret = ov518_mode_init_regs(sd); |
| @@ -2403,6 +2856,56 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
| 2403 | ov51x_led_control(sd, 0); | 2856 | ov51x_led_control(sd, 0); |
| 2404 | } | 2857 | } |
| 2405 | 2858 | ||
| 2859 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | ||
| 2860 | struct gspca_frame *frame, /* target */ | ||
| 2861 | __u8 *in, /* isoc packet */ | ||
| 2862 | int len) /* iso packet length */ | ||
| 2863 | { | ||
| 2864 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 2865 | |||
| 2866 | /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th | ||
| 2867 | * byte non-zero. The EOF packet has image width/height in the | ||
| 2868 | * 10th and 11th bytes. The 9th byte is given as follows: | ||
| 2869 | * | ||
| 2870 | * bit 7: EOF | ||
| 2871 | * 6: compression enabled | ||
| 2872 | * 5: 422/420/400 modes | ||
| 2873 | * 4: 422/420/400 modes | ||
| 2874 | * 3: 1 | ||
| 2875 | * 2: snapshot button on | ||
| 2876 | * 1: snapshot frame | ||
| 2877 | * 0: even/odd field | ||
| 2878 | */ | ||
| 2879 | if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && | ||
| 2880 | (in[8] & 0x08)) { | ||
| 2881 | if (in[8] & 0x80) { | ||
| 2882 | /* Frame end */ | ||
| 2883 | if ((in[9] + 1) * 8 != gspca_dev->width || | ||
| 2884 | (in[10] + 1) * 8 != gspca_dev->height) { | ||
| 2885 | PDEBUG(D_ERR, "Invalid frame size, got: %dx%d," | ||
| 2886 | " requested: %dx%d\n", | ||
| 2887 | (in[9] + 1) * 8, (in[10] + 1) * 8, | ||
| 2888 | gspca_dev->width, gspca_dev->height); | ||
| 2889 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
| 2890 | return; | ||
| 2891 | } | ||
| 2892 | /* Add 11 byte footer to frame, might be usefull */ | ||
| 2893 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11); | ||
| 2894 | return; | ||
| 2895 | } else { | ||
| 2896 | /* Frame start */ | ||
| 2897 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0); | ||
| 2898 | sd->packet_nr = 0; | ||
| 2899 | } | ||
| 2900 | } | ||
| 2901 | |||
| 2902 | /* Ignore the packet number */ | ||
| 2903 | len--; | ||
| 2904 | |||
| 2905 | /* intermediate packet */ | ||
| 2906 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len); | ||
| 2907 | } | ||
| 2908 | |||
| 2406 | static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | 2909 | static void ov518_pkt_scan(struct gspca_dev *gspca_dev, |
| 2407 | struct gspca_frame *frame, /* target */ | 2910 | struct gspca_frame *frame, /* target */ |
| 2408 | __u8 *data, /* isoc packet */ | 2911 | __u8 *data, /* isoc packet */ |
| @@ -2495,6 +2998,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
| 2495 | switch (sd->bridge) { | 2998 | switch (sd->bridge) { |
| 2496 | case BRIDGE_OV511: | 2999 | case BRIDGE_OV511: |
| 2497 | case BRIDGE_OV511PLUS: | 3000 | case BRIDGE_OV511PLUS: |
| 3001 | ov511_pkt_scan(gspca_dev, frame, data, len); | ||
| 2498 | break; | 3002 | break; |
| 2499 | case BRIDGE_OV518: | 3003 | case BRIDGE_OV518: |
| 2500 | case BRIDGE_OV518PLUS: | 3004 | case BRIDGE_OV518PLUS: |
| @@ -2862,12 +3366,15 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
| 2862 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, | 3366 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, |
| 2863 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, | 3367 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, |
| 2864 | {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, | 3368 | {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, |
| 3369 | {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, | ||
| 2865 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, | 3370 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, |
| 2866 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, | 3371 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, |
| 2867 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, | 3372 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, |
| 2868 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, | 3373 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, |
| 2869 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, | 3374 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, |
| 3375 | {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, | ||
| 2870 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, | 3376 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, |
| 3377 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, | ||
| 2871 | {} | 3378 | {} |
| 2872 | }; | 3379 | }; |
| 2873 | 3380 | ||
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 772d226cb5ca..8a025d510904 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
| @@ -348,6 +348,7 @@ struct v4l2_pix_format { | |||
| 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_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ | ||
| 351 | #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ | 352 | #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ |
| 352 | 353 | ||
| 353 | /* | 354 | /* |
