aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladik Aranov <earnol@mail.ru>2013-09-20 20:09:44 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-10-15 11:49:51 -0400
commit15807765d81dd71ab4e43517257e5e0ddcc2bc3b (patch)
tree484902972859b27c537113ab6b4cab91cbd5f967
parentde0fc463268eed44ba68ebdddbc472e4f2ccd29e (diff)
[media] gscpa_ov534_9: Add support for ov3610 sensor
Dear Hans de Goede, I have Ubuntu (raring) and recently bought digital microscope eyepiece Lomo MD300. It is the same device as Future Optics MVV3000. Unfortunately it does not work out of box. Moreover drivers refused to work under Windows 7 as well leaving me only with Win Xp working system. I have had no choice but to examine what happened in USB bus and attempt to reproduce the sequence. So, i have download the source(3.8.0-30 kernel) and made required changes to driver to make my hardware work. I submit my changed files to you as maintainer of the driver so you can integrade my changes into main stream. Thanx. Hopefully my Ubuntu will work with my hardware out of box. Sincerely yours Vladik Aranov Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/media/usb/gspca/ov534_9.c334
1 files changed, 333 insertions, 1 deletions
diff --git a/drivers/media/usb/gspca/ov534_9.c b/drivers/media/usb/gspca/ov534_9.c
index c4cd028fe0b4..47085cf2d723 100644
--- a/drivers/media/usb/gspca/ov534_9.c
+++ b/drivers/media/usb/gspca/ov534_9.c
@@ -59,6 +59,7 @@ enum sensors {
59 SENSOR_OV965x, /* ov9657 */ 59 SENSOR_OV965x, /* ov9657 */
60 SENSOR_OV971x, /* ov9712 */ 60 SENSOR_OV971x, /* ov9712 */
61 SENSOR_OV562x, /* ov5621 */ 61 SENSOR_OV562x, /* ov5621 */
62 SENSOR_OV361x, /* ov3610 */
62 NSENSORS 63 NSENSORS
63}; 64};
64 65
@@ -106,6 +107,274 @@ static const struct v4l2_pix_format ov562x_mode[] = {
106 } 107 }
107}; 108};
108 109
110enum ov361x {
111 ov361x_2048 = 0,
112 ov361x_1600,
113 ov361x_1024,
114 ov361x_640,
115 ov361x_320,
116 ov361x_160,
117 ov361x_last
118};
119
120static const struct v4l2_pix_format ov361x_mode[] = {
121 {0x800, 0x600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
122 .bytesperline = 0x800,
123 .sizeimage = 0x800 * 0x600,
124 .colorspace = V4L2_COLORSPACE_SRGB},
125 {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
126 .bytesperline = 1600,
127 .sizeimage = 1600 * 1200,
128 .colorspace = V4L2_COLORSPACE_SRGB},
129 {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
130 .bytesperline = 768,
131 .sizeimage = 1024 * 768,
132 .colorspace = V4L2_COLORSPACE_SRGB},
133 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
134 .bytesperline = 640,
135 .sizeimage = 640 * 480,
136 .colorspace = V4L2_COLORSPACE_SRGB},
137 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
138 .bytesperline = 320,
139 .sizeimage = 320 * 240,
140 .colorspace = V4L2_COLORSPACE_SRGB},
141 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
142 .bytesperline = 160,
143 .sizeimage = 160 * 120,
144 .colorspace = V4L2_COLORSPACE_SRGB}
145};
146
147static const u8 ov361x_start_2048[][2] = {
148 {0x12, 0x80},
149 {0x13, 0xcf},
150 {0x14, 0x40},
151 {0x15, 0x00},
152 {0x01, 0x80},
153 {0x02, 0x80},
154 {0x04, 0x70},
155 {0x0d, 0x40},
156 {0x0f, 0x47},
157 {0x11, 0x81},
158 {0x32, 0x36},
159 {0x33, 0x0c},
160 {0x34, 0x00},
161 {0x35, 0x90},
162 {0x12, 0x00},
163 {0x17, 0x10},
164 {0x18, 0x90},
165 {0x19, 0x00},
166 {0x1a, 0xc0},
167};
168static const u8 ov361x_bridge_start_2048[][2] = {
169 {0xf1, 0x60},
170 {0x88, 0x00},
171 {0x89, 0x08},
172 {0x8a, 0x00},
173 {0x8b, 0x06},
174 {0x8c, 0x01},
175 {0x8d, 0x10},
176 {0x1c, 0x00},
177 {0x1d, 0x48},
178 {0x1d, 0x00},
179 {0x1d, 0xff},
180 {0x1c, 0x0a},
181 {0x1d, 0x2e},
182 {0x1d, 0x1e},
183};
184
185static const u8 ov361x_start_1600[][2] = {
186 {0x12, 0x80},
187 {0x13, 0xcf},
188 {0x14, 0x40},
189 {0x15, 0x00},
190 {0x01, 0x80},
191 {0x02, 0x80},
192 {0x04, 0x70},
193 {0x0d, 0x40},
194 {0x0f, 0x47},
195 {0x11, 0x81},
196 {0x32, 0x36},
197 {0x33, 0x0C},
198 {0x34, 0x00},
199 {0x35, 0x90},
200 {0x12, 0x00},
201 {0x17, 0x10},
202 {0x18, 0x90},
203 {0x19, 0x00},
204 {0x1a, 0xc0},
205};
206static const u8 ov361x_bridge_start_1600[][2] = {
207 {0xf1, 0x60}, /* Hsize[7:0] */
208 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */
209 {0x89, 0x08}, /* Vsize[7:0] */
210 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */
211 {0x8b, 0x06}, /* for Iso */
212 {0x8c, 0x01}, /* RAW input */
213 {0x8d, 0x10},
214 {0x1c, 0x00}, /* RAW output, Iso transfer */
215 {0x1d, 0x48},
216 {0x1d, 0x00},
217 {0x1d, 0xff},
218 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */
219 {0x1d, 0x2e}, /* for Iso */
220 {0x1d, 0x1e},
221};
222
223static const u8 ov361x_start_1024[][2] = {
224 {0x12, 0x80},
225 {0x13, 0xcf},
226 {0x14, 0x40},
227 {0x15, 0x00},
228 {0x01, 0x80},
229 {0x02, 0x80},
230 {0x04, 0x70},
231 {0x0d, 0x40},
232 {0x0f, 0x47},
233 {0x11, 0x81},
234 {0x32, 0x36},
235 {0x33, 0x0C},
236 {0x34, 0x00},
237 {0x35, 0x90},
238 {0x12, 0x40},
239 {0x17, 0x1f},
240 {0x18, 0x5f},
241 {0x19, 0x00},
242 {0x1a, 0x68},
243};
244static const u8 ov361x_bridge_start_1024[][2] = {
245 {0xf1, 0x60}, /* Hsize[7:0] */
246 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */
247 {0x89, 0x04}, /* Vsize[7:0] */
248 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */
249 {0x8b, 0x03}, /* for Iso */
250 {0x8c, 0x01}, /* RAW input */
251 {0x8d, 0x10},
252 {0x1c, 0x00}, /* RAW output, Iso transfer */
253 {0x1d, 0x48},
254 {0x1d, 0x00},
255 {0x1d, 0xff},
256 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */
257 {0x1d, 0x2e}, /* for Iso */
258 {0x1d, 0x1e},
259};
260
261static const u8 ov361x_start_640[][2] = {
262 {0x12, 0x80},
263 {0x13, 0xcf},
264 {0x14, 0x40},
265 {0x15, 0x00},
266 {0x01, 0x80},
267 {0x02, 0x80},
268 {0x04, 0x70},
269 {0x0d, 0x40},
270 {0x0f, 0x47},
271 {0x11, 0x81},
272 {0x32, 0x36},
273 {0x33, 0x0C},
274 {0x34, 0x00},
275 {0x35, 0x90},
276 {0x12, 0x40},
277 {0x17, 0x1f},
278 {0x18, 0x5f},
279 {0x19, 0x00},
280 {0x1a, 0x68},
281};
282
283static const u8 ov361x_bridge_start_640[][2] = {
284 {0xf1, 0x60}, /* Hsize[7:0]*/
285 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */
286 {0x89, 0x04}, /* Vsize[7:0] */
287 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */
288 {0x8b, 0x03}, /* for Iso */
289 {0x8c, 0x01}, /* RAW input */
290 {0x8d, 0x10},
291 {0x1c, 0x00}, /* RAW output, Iso transfer */
292 {0x1d, 0x48},
293 {0x1d, 0x00},
294 {0x1d, 0xff},
295 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */
296 {0x1d, 0x2e}, /* for Iso */
297 {0x1d, 0x1e},
298};
299
300static const u8 ov361x_start_320[][2] = {
301 {0x12, 0x80},
302 {0x13, 0xcf},
303 {0x14, 0x40},
304 {0x15, 0x00},
305 {0x01, 0x80},
306 {0x02, 0x80},
307 {0x04, 0x70},
308 {0x0d, 0x40},
309 {0x0f, 0x47},
310 {0x11, 0x81},
311 {0x32, 0x36},
312 {0x33, 0x0C},
313 {0x34, 0x00},
314 {0x35, 0x90},
315 {0x12, 0x40},
316 {0x17, 0x1f},
317 {0x18, 0x5f},
318 {0x19, 0x00},
319 {0x1a, 0x68},
320};
321
322static const u8 ov361x_bridge_start_320[][2] = {
323 {0xf1, 0x60}, /* Hsize[7:0] */
324 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */
325 {0x89, 0x04}, /* Vsize[7:0] */
326 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */
327 {0x8b, 0x03}, /* for Iso */
328 {0x8c, 0x01}, /* RAW input */
329 {0x8d, 0x10},
330 {0x1c, 0x00}, /* RAW output, Iso transfer; */
331 {0x1d, 0x48},
332 {0x1d, 0x00},
333 {0x1d, 0xff},
334 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */
335 {0x1d, 0x2e}, /* for Iso */
336 {0x1d, 0x1e},
337};
338
339static const u8 ov361x_start_160[][2] = {
340 {0x12, 0x80},
341 {0x13, 0xcf},
342 {0x14, 0x40},
343 {0x15, 0x00},
344 {0x01, 0x80},
345 {0x02, 0x80},
346 {0x04, 0x70},
347 {0x0d, 0x40},
348 {0x0f, 0x47},
349 {0x11, 0x81},
350 {0x32, 0x36},
351 {0x33, 0x0C},
352 {0x34, 0x00},
353 {0x35, 0x90},
354 {0x12, 0x40},
355 {0x17, 0x1f},
356 {0x18, 0x5f},
357 {0x19, 0x00},
358 {0x1a, 0x68},
359};
360
361static const u8 ov361x_bridge_start_160[][2] = {
362 {0xf1, 0x60}, /* Hsize[7:0] */
363 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */
364 {0x89, 0x04}, /* Vsize[7:0] */
365 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */
366 {0x8b, 0x03}, /* for Iso */
367 {0x8c, 0x01}, /* RAW input */
368 {0x8d, 0x10},
369 {0x1c, 0x00}, /* RAW output, Iso transfer */
370 {0x1d, 0x48},
371 {0x1d, 0x00},
372 {0x1d, 0xff},
373 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */
374 {0x1d, 0x2e}, /* for Iso */
375 {0x1d, 0x1e},
376};
377
109static const u8 bridge_init[][2] = { 378static const u8 bridge_init[][2] = {
110 {0x88, 0xf8}, 379 {0x88, 0xf8},
111 {0x89, 0xff}, 380 {0x89, 0xff},
@@ -898,7 +1167,7 @@ static int sccb_check_status(struct gspca_dev *gspca_dev)
898 int i; 1167 int i;
899 1168
900 for (i = 0; i < 5; i++) { 1169 for (i = 0; i < 5; i++) {
901 msleep(10); 1170 msleep(20);
902 data = reg_r(gspca_dev, OV534_REG_STATUS); 1171 data = reg_r(gspca_dev, OV534_REG_STATUS);
903 1172
904 switch (data) { 1173 switch (data) {
@@ -1221,6 +1490,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
1221 sccb_w_array(gspca_dev, ov562x_init_2, 1490 sccb_w_array(gspca_dev, ov562x_init_2,
1222 ARRAY_SIZE(ov562x_init_2)); 1491 ARRAY_SIZE(ov562x_init_2));
1223 reg_w(gspca_dev, 0xe0, 0x00); 1492 reg_w(gspca_dev, 0xe0, 0x00);
1493 } else if ((sensor_id & 0xfff0) == 0x3610) {
1494 sd->sensor = SENSOR_OV361x;
1495 gspca_dev->cam.cam_mode = ov361x_mode;
1496 gspca_dev->cam.nmodes = ARRAY_SIZE(ov361x_mode);
1497 reg_w(gspca_dev, 0xe7, 0x3a);
1498 reg_w(gspca_dev, 0xf1, 0x60);
1499 sccb_write(gspca_dev, 0x12, 0x80);
1224 } else { 1500 } else {
1225 pr_err("Unknown sensor %04x", sensor_id); 1501 pr_err("Unknown sensor %04x", sensor_id);
1226 return -EINVAL; 1502 return -EINVAL;
@@ -1229,6 +1505,53 @@ static int sd_init(struct gspca_dev *gspca_dev)
1229 return gspca_dev->usb_err; 1505 return gspca_dev->usb_err;
1230} 1506}
1231 1507
1508static int sd_start_ov361x(struct gspca_dev *gspca_dev)
1509{
1510 sccb_write(gspca_dev, 0x12, 0x80);
1511 msleep(20);
1512 switch (gspca_dev->curr_mode % (ov361x_last)) {
1513 case ov361x_2048:
1514 reg_w_array(gspca_dev, ov361x_bridge_start_2048,
1515 ARRAY_SIZE(ov361x_bridge_start_2048));
1516 sccb_w_array(gspca_dev, ov361x_start_2048,
1517 ARRAY_SIZE(ov361x_start_2048));
1518 break;
1519 case ov361x_1600:
1520 reg_w_array(gspca_dev, ov361x_bridge_start_1600,
1521 ARRAY_SIZE(ov361x_bridge_start_1600));
1522 sccb_w_array(gspca_dev, ov361x_start_1600,
1523 ARRAY_SIZE(ov361x_start_1600));
1524 break;
1525 case ov361x_1024:
1526 reg_w_array(gspca_dev, ov361x_bridge_start_1024,
1527 ARRAY_SIZE(ov361x_bridge_start_1024));
1528 sccb_w_array(gspca_dev, ov361x_start_1024,
1529 ARRAY_SIZE(ov361x_start_1024));
1530 break;
1531 case ov361x_640:
1532 reg_w_array(gspca_dev, ov361x_bridge_start_640,
1533 ARRAY_SIZE(ov361x_bridge_start_640));
1534 sccb_w_array(gspca_dev, ov361x_start_640,
1535 ARRAY_SIZE(ov361x_start_640));
1536 break;
1537 case ov361x_320:
1538 reg_w_array(gspca_dev, ov361x_bridge_start_320,
1539 ARRAY_SIZE(ov361x_bridge_start_320));
1540 sccb_w_array(gspca_dev, ov361x_start_320,
1541 ARRAY_SIZE(ov361x_start_320));
1542 break;
1543 case ov361x_160:
1544 reg_w_array(gspca_dev, ov361x_bridge_start_160,
1545 ARRAY_SIZE(ov361x_bridge_start_160));
1546 sccb_w_array(gspca_dev, ov361x_start_160,
1547 ARRAY_SIZE(ov361x_start_160));
1548 break;
1549 }
1550 reg_w(gspca_dev, 0xe0, 0x00); /* start transfer */
1551
1552 return gspca_dev->usb_err;
1553}
1554
1232static int sd_start(struct gspca_dev *gspca_dev) 1555static int sd_start(struct gspca_dev *gspca_dev)
1233{ 1556{
1234 struct sd *sd = (struct sd *) gspca_dev; 1557 struct sd *sd = (struct sd *) gspca_dev;
@@ -1237,6 +1560,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
1237 return gspca_dev->usb_err; 1560 return gspca_dev->usb_err;
1238 if (sd->sensor == SENSOR_OV562x) 1561 if (sd->sensor == SENSOR_OV562x)
1239 return gspca_dev->usb_err; 1562 return gspca_dev->usb_err;
1563 if (sd->sensor == SENSOR_OV361x)
1564 return sd_start_ov361x(gspca_dev);
1240 1565
1241 switch (gspca_dev->curr_mode) { 1566 switch (gspca_dev->curr_mode) {
1242 case QVGA_MODE: /* 320x240 */ 1567 case QVGA_MODE: /* 320x240 */
@@ -1290,6 +1615,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
1290 1615
1291static void sd_stopN(struct gspca_dev *gspca_dev) 1616static void sd_stopN(struct gspca_dev *gspca_dev)
1292{ 1617{
1618 if (((struct sd *)gspca_dev)->sensor == SENSOR_OV361x) {
1619 reg_w(gspca_dev, 0xe0, 0x01); /* stop transfer */
1620 /* reg_w(gspca_dev, 0x31, 0x09); */
1621 return;
1622 }
1293 reg_w(gspca_dev, 0xe0, 0x01); 1623 reg_w(gspca_dev, 0xe0, 0x01);
1294 set_led(gspca_dev, 0); 1624 set_led(gspca_dev, 0);
1295 reg_w(gspca_dev, 0xe0, 0x00); 1625 reg_w(gspca_dev, 0xe0, 0x00);
@@ -1425,6 +1755,8 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
1425 1755
1426 if (sd->sensor == SENSOR_OV971x) 1756 if (sd->sensor == SENSOR_OV971x)
1427 return 0; 1757 return 0;
1758 if (sd->sensor == SENSOR_OV361x)
1759 return 0;
1428 gspca_dev->vdev.ctrl_handler = hdl; 1760 gspca_dev->vdev.ctrl_handler = hdl;
1429 v4l2_ctrl_handler_init(hdl, 7); 1761 v4l2_ctrl_handler_init(hdl, 7);
1430 if (sd->sensor == SENSOR_OV562x) { 1762 if (sd->sensor == SENSOR_OV562x) {