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 | /* |