aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/stv06xx
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/video/gspca/stv06xx
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/media/video/gspca/stv06xx')
-rw-r--r--drivers/media/video/gspca/stv06xx/Kconfig9
-rw-r--r--drivers/media/video/gspca/stv06xx/Makefile10
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.c630
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.h115
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c611
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h207
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c573
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h152
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_sensor.h87
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_st6422.c401
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_st6422.h52
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c392
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h259
13 files changed, 3498 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/stv06xx/Kconfig b/drivers/media/video/gspca/stv06xx/Kconfig
new file mode 100644
index 00000000000..634ad38d9fb
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/Kconfig
@@ -0,0 +1,9 @@
1config USB_STV06XX
2 tristate "STV06XX USB Camera Driver"
3 depends on USB_GSPCA
4 help
5 Say Y here if you want support for cameras based on
6 the ST STV06XX chip.
7
8 To compile this driver as a module, choose M here: the
9 module will be called gspca_stv06xx.
diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile
new file mode 100644
index 00000000000..2f3c3a606ce
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/Makefile
@@ -0,0 +1,10 @@
1obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o
2
3gspca_stv06xx-objs := stv06xx.o \
4 stv06xx_vv6410.o \
5 stv06xx_hdcs.o \
6 stv06xx_pb0100.o \
7 stv06xx_st6422.o
8
9EXTRA_CFLAGS += -Idrivers/media/video/gspca
10
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
new file mode 100644
index 00000000000..abf1658fa33
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -0,0 +1,630 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#include <linux/input.h>
31#include "stv06xx_sensor.h"
32
33MODULE_AUTHOR("Erik Andrén");
34MODULE_DESCRIPTION("STV06XX USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37static int dump_bridge;
38static int dump_sensor;
39
40int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
41{
42 int err;
43 struct usb_device *udev = sd->gspca_dev.dev;
44 __u8 *buf = sd->gspca_dev.usb_buf;
45 u8 len = (i2c_data > 0xff) ? 2 : 1;
46
47 buf[0] = i2c_data & 0xff;
48 buf[1] = (i2c_data >> 8) & 0xff;
49
50 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
51 0x04, 0x40, address, 0, buf, len,
52 STV06XX_URB_MSG_TIMEOUT);
53
54 PDEBUG(D_CONF, "Written 0x%x to address 0x%x, status: %d",
55 i2c_data, address, err);
56
57 return (err < 0) ? err : 0;
58}
59
60int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data)
61{
62 int err;
63 struct usb_device *udev = sd->gspca_dev.dev;
64 __u8 *buf = sd->gspca_dev.usb_buf;
65
66 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
67 0x04, 0xc0, address, 0, buf, 1,
68 STV06XX_URB_MSG_TIMEOUT);
69
70 *i2c_data = buf[0];
71
72 PDEBUG(D_CONF, "Reading 0x%x from address 0x%x, status %d",
73 *i2c_data, address, err);
74
75 return (err < 0) ? err : 0;
76}
77
78/* Wraps the normal write sensor bytes / words functions for writing a
79 single value */
80int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value)
81{
82 if (sd->sensor->i2c_len == 2) {
83 u16 data[2] = { address, value };
84 return stv06xx_write_sensor_words(sd, data, 1);
85 } else {
86 u8 data[2] = { address, value };
87 return stv06xx_write_sensor_bytes(sd, data, 1);
88 }
89}
90
91static int stv06xx_write_sensor_finish(struct sd *sd)
92{
93 int err = 0;
94
95 if (sd->bridge == BRIDGE_STV610) {
96 struct usb_device *udev = sd->gspca_dev.dev;
97 __u8 *buf = sd->gspca_dev.usb_buf;
98
99 buf[0] = 0;
100 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
101 0x04, 0x40, 0x1704, 0, buf, 1,
102 STV06XX_URB_MSG_TIMEOUT);
103 }
104
105 return (err < 0) ? err : 0;
106}
107
108int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
109{
110 int err, i, j;
111 struct usb_device *udev = sd->gspca_dev.dev;
112 __u8 *buf = sd->gspca_dev.usb_buf;
113
114 PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
115 for (i = 0; i < len;) {
116 /* Build the command buffer */
117 memset(buf, 0, I2C_BUFFER_LENGTH);
118 for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) {
119 buf[j] = data[2*i];
120 buf[0x10 + j] = data[2*i+1];
121 PDEBUG(D_CONF, "I2C: Writing 0x%02x to reg 0x%02x",
122 data[2*i+1], data[2*i]);
123 }
124 buf[0x20] = sd->sensor->i2c_addr;
125 buf[0x21] = j - 1; /* Number of commands to send - 1 */
126 buf[0x22] = I2C_WRITE_CMD;
127 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
128 0x04, 0x40, 0x0400, 0, buf,
129 I2C_BUFFER_LENGTH,
130 STV06XX_URB_MSG_TIMEOUT);
131 if (err < 0)
132 return err;
133 }
134 return stv06xx_write_sensor_finish(sd);
135}
136
137int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
138{
139 int err, i, j;
140 struct usb_device *udev = sd->gspca_dev.dev;
141 __u8 *buf = sd->gspca_dev.usb_buf;
142
143 PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
144
145 for (i = 0; i < len;) {
146 /* Build the command buffer */
147 memset(buf, 0, I2C_BUFFER_LENGTH);
148 for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) {
149 buf[j] = data[2*i];
150 buf[0x10 + j * 2] = data[2*i+1];
151 buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8;
152 PDEBUG(D_CONF, "I2C: Writing 0x%04x to reg 0x%02x",
153 data[2*i+1], data[2*i]);
154 }
155 buf[0x20] = sd->sensor->i2c_addr;
156 buf[0x21] = j - 1; /* Number of commands to send - 1 */
157 buf[0x22] = I2C_WRITE_CMD;
158 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
159 0x04, 0x40, 0x0400, 0, buf,
160 I2C_BUFFER_LENGTH,
161 STV06XX_URB_MSG_TIMEOUT);
162 if (err < 0)
163 return err;
164 }
165 return stv06xx_write_sensor_finish(sd);
166}
167
168int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
169{
170 int err;
171 struct usb_device *udev = sd->gspca_dev.dev;
172 __u8 *buf = sd->gspca_dev.usb_buf;
173
174 err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush);
175 if (err < 0)
176 return err;
177
178 /* Clear mem */
179 memset(buf, 0, I2C_BUFFER_LENGTH);
180
181 buf[0] = address;
182 buf[0x20] = sd->sensor->i2c_addr;
183 buf[0x21] = 0;
184
185 /* Read I2C register */
186 buf[0x22] = I2C_READ_CMD;
187
188 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
189 0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
190 STV06XX_URB_MSG_TIMEOUT);
191 if (err < 0) {
192 err("I2C: Read error writing address: %d", err);
193 return err;
194 }
195
196 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
197 0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len,
198 STV06XX_URB_MSG_TIMEOUT);
199 if (sd->sensor->i2c_len == 2)
200 *value = buf[0] | (buf[1] << 8);
201 else
202 *value = buf[0];
203
204 PDEBUG(D_CONF, "I2C: Read 0x%x from address 0x%x, status: %d",
205 *value, address, err);
206
207 return (err < 0) ? err : 0;
208}
209
210/* Dumps all bridge registers */
211static void stv06xx_dump_bridge(struct sd *sd)
212{
213 int i;
214 u8 data, buf;
215
216 info("Dumping all stv06xx bridge registers");
217 for (i = 0x1400; i < 0x160f; i++) {
218 stv06xx_read_bridge(sd, i, &data);
219
220 info("Read 0x%x from address 0x%x", data, i);
221 }
222
223 info("Testing stv06xx bridge registers for writability");
224 for (i = 0x1400; i < 0x160f; i++) {
225 stv06xx_read_bridge(sd, i, &data);
226 buf = data;
227
228 stv06xx_write_bridge(sd, i, 0xff);
229 stv06xx_read_bridge(sd, i, &data);
230 if (data == 0xff)
231 info("Register 0x%x is read/write", i);
232 else if (data != buf)
233 info("Register 0x%x is read/write,"
234 " but only partially", i);
235 else
236 info("Register 0x%x is read-only", i);
237
238 stv06xx_write_bridge(sd, i, buf);
239 }
240}
241
242/* this function is called at probe and resume time */
243static int stv06xx_init(struct gspca_dev *gspca_dev)
244{
245 struct sd *sd = (struct sd *) gspca_dev;
246 int err;
247
248 PDEBUG(D_PROBE, "Initializing camera");
249
250 /* Let the usb init settle for a bit
251 before performing the initialization */
252 msleep(250);
253
254 err = sd->sensor->init(sd);
255
256 if (dump_sensor && sd->sensor->dump)
257 sd->sensor->dump(sd);
258
259 return (err < 0) ? err : 0;
260}
261
262/* Start the camera */
263static int stv06xx_start(struct gspca_dev *gspca_dev)
264{
265 struct sd *sd = (struct sd *) gspca_dev;
266 struct usb_host_interface *alt;
267 struct usb_interface *intf;
268 int err, packet_size;
269
270 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
271 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
272 if (!alt) {
273 PDEBUG(D_ERR, "Couldn't get altsetting");
274 return -EIO;
275 }
276
277 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
278 err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
279 if (err < 0)
280 return err;
281
282 /* Prepare the sensor for start */
283 err = sd->sensor->start(sd);
284 if (err < 0)
285 goto out;
286
287 /* Start isochronous streaming */
288 err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1);
289
290out:
291 if (err < 0)
292 PDEBUG(D_STREAM, "Starting stream failed");
293 else
294 PDEBUG(D_STREAM, "Started streaming");
295
296 return (err < 0) ? err : 0;
297}
298
299static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
300{
301 struct usb_host_interface *alt;
302 struct sd *sd = (struct sd *) gspca_dev;
303
304 /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
305 alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
306 alt->endpoint[0].desc.wMaxPacketSize =
307 cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
308
309 return 0;
310}
311
312static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
313{
314 int ret, packet_size, min_packet_size;
315 struct usb_host_interface *alt;
316 struct sd *sd = (struct sd *) gspca_dev;
317
318 alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
319 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
320 min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
321 if (packet_size <= min_packet_size)
322 return -EIO;
323
324 packet_size -= 100;
325 if (packet_size < min_packet_size)
326 packet_size = min_packet_size;
327 alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
328
329 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
330 if (ret < 0)
331 PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
332
333 return ret;
334}
335
336static void stv06xx_stopN(struct gspca_dev *gspca_dev)
337{
338 int err;
339 struct sd *sd = (struct sd *) gspca_dev;
340
341 /* stop ISO-streaming */
342 err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0);
343 if (err < 0)
344 goto out;
345
346 err = sd->sensor->stop(sd);
347
348out:
349 if (err < 0)
350 PDEBUG(D_STREAM, "Failed to stop stream");
351 else
352 PDEBUG(D_STREAM, "Stopped streaming");
353}
354
355/*
356 * Analyse an USB packet of the data stream and store it appropriately.
357 * Each packet contains an integral number of chunks. Each chunk has
358 * 2-bytes identification, followed by 2-bytes that describe the chunk
359 * length. Known/guessed chunk identifications are:
360 * 8001/8005/C001/C005 - Begin new frame
361 * 8002/8006/C002/C006 - End frame
362 * 0200/4200 - Contains actual image data, bayer or compressed
363 * 0005 - 11 bytes of unknown data
364 * 0100 - 2 bytes of unknown data
365 * The 0005 and 0100 chunks seem to appear only in compressed stream.
366 */
367static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
368 u8 *data, /* isoc packet */
369 int len) /* iso packet length */
370{
371 struct sd *sd = (struct sd *) gspca_dev;
372
373 PDEBUG(D_PACK, "Packet of length %d arrived", len);
374
375 /* A packet may contain several frames
376 loop until the whole packet is reached */
377 while (len) {
378 int id, chunk_len;
379
380 if (len < 4) {
381 PDEBUG(D_PACK, "Packet is smaller than 4 bytes");
382 return;
383 }
384
385 /* Capture the id */
386 id = (data[0] << 8) | data[1];
387
388 /* Capture the chunk length */
389 chunk_len = (data[2] << 8) | data[3];
390 PDEBUG(D_PACK, "Chunk id: %x, length: %d", id, chunk_len);
391
392 data += 4;
393 len -= 4;
394
395 if (len < chunk_len) {
396 PDEBUG(D_ERR, "URB packet length is smaller"
397 " than the specified chunk length");
398 gspca_dev->last_packet_type = DISCARD_PACKET;
399 return;
400 }
401
402 /* First byte seem to be 02=data 2nd byte is unknown??? */
403 if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200)
404 goto frame_data;
405
406 switch (id) {
407 case 0x0200:
408 case 0x4200:
409frame_data:
410 PDEBUG(D_PACK, "Frame data packet detected");
411
412 if (sd->to_skip) {
413 int skip = (sd->to_skip < chunk_len) ?
414 sd->to_skip : chunk_len;
415 data += skip;
416 len -= skip;
417 chunk_len -= skip;
418 sd->to_skip -= skip;
419 }
420
421 gspca_frame_add(gspca_dev, INTER_PACKET,
422 data, chunk_len);
423 break;
424
425 case 0x8001:
426 case 0x8005:
427 case 0xc001:
428 case 0xc005:
429 PDEBUG(D_PACK, "Starting new frame");
430
431 /* Create a new frame, chunk length should be zero */
432 gspca_frame_add(gspca_dev, FIRST_PACKET,
433 NULL, 0);
434
435 if (sd->bridge == BRIDGE_ST6422)
436 sd->to_skip = gspca_dev->width * 4;
437
438 if (chunk_len)
439 PDEBUG(D_ERR, "Chunk length is "
440 "non-zero on a SOF");
441 break;
442
443 case 0x8002:
444 case 0x8006:
445 case 0xc002:
446 PDEBUG(D_PACK, "End of frame detected");
447
448 /* Complete the last frame (if any) */
449 gspca_frame_add(gspca_dev, LAST_PACKET,
450 NULL, 0);
451
452 if (chunk_len)
453 PDEBUG(D_ERR, "Chunk length is "
454 "non-zero on a EOF");
455 break;
456
457 case 0x0005:
458 PDEBUG(D_PACK, "Chunk 0x005 detected");
459 /* Unknown chunk with 11 bytes of data,
460 occurs just before end of each frame
461 in compressed mode */
462 break;
463
464 case 0x0100:
465 PDEBUG(D_PACK, "Chunk 0x0100 detected");
466 /* Unknown chunk with 2 bytes of data,
467 occurs 2-3 times per USB interrupt */
468 break;
469 case 0x42ff:
470 PDEBUG(D_PACK, "Chunk 0x42ff detected");
471 /* Special chunk seen sometimes on the ST6422 */
472 break;
473 default:
474 PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
475 /* Unknown chunk */
476 }
477 data += chunk_len;
478 len -= chunk_len;
479 }
480}
481
482#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
483static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
484 u8 *data, /* interrupt packet data */
485 int len) /* interrupt packet length */
486{
487 int ret = -EINVAL;
488
489 if (len == 1 && data[0] == 0x80) {
490 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
491 input_sync(gspca_dev->input_dev);
492 ret = 0;
493 }
494
495 if (len == 1 && data[0] == 0x88) {
496 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
497 input_sync(gspca_dev->input_dev);
498 ret = 0;
499 }
500
501 return ret;
502}
503#endif
504
505static int stv06xx_config(struct gspca_dev *gspca_dev,
506 const struct usb_device_id *id);
507
508/* sub-driver description */
509static const struct sd_desc sd_desc = {
510 .name = MODULE_NAME,
511 .config = stv06xx_config,
512 .init = stv06xx_init,
513 .start = stv06xx_start,
514 .stopN = stv06xx_stopN,
515 .pkt_scan = stv06xx_pkt_scan,
516 .isoc_init = stv06xx_isoc_init,
517 .isoc_nego = stv06xx_isoc_nego,
518#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
519 .int_pkt_scan = sd_int_pkt_scan,
520#endif
521};
522
523/* This function is called at probe time */
524static int stv06xx_config(struct gspca_dev *gspca_dev,
525 const struct usb_device_id *id)
526{
527 struct sd *sd = (struct sd *) gspca_dev;
528
529 PDEBUG(D_PROBE, "Configuring camera");
530
531 sd->desc = sd_desc;
532 sd->bridge = id->driver_info;
533 gspca_dev->sd_desc = &sd->desc;
534
535 if (dump_bridge)
536 stv06xx_dump_bridge(sd);
537
538 sd->sensor = &stv06xx_sensor_st6422;
539 if (!sd->sensor->probe(sd))
540 return 0;
541
542 sd->sensor = &stv06xx_sensor_vv6410;
543 if (!sd->sensor->probe(sd))
544 return 0;
545
546 sd->sensor = &stv06xx_sensor_hdcs1x00;
547 if (!sd->sensor->probe(sd))
548 return 0;
549
550 sd->sensor = &stv06xx_sensor_hdcs1020;
551 if (!sd->sensor->probe(sd))
552 return 0;
553
554 sd->sensor = &stv06xx_sensor_pb0100;
555 if (!sd->sensor->probe(sd))
556 return 0;
557
558 sd->sensor = NULL;
559 return -ENODEV;
560}
561
562
563
564/* -- module initialisation -- */
565static const struct usb_device_id device_table[] = {
566 /* QuickCam Express */
567 {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
568 /* LEGO cam / QuickCam Web */
569 {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
570 /* Dexxa WebCam USB */
571 {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
572 /* QuickCam Messenger */
573 {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
574 /* QuickCam Communicate */
575 {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
576 /* QuickCam Messenger (new) */
577 {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
578 {}
579};
580MODULE_DEVICE_TABLE(usb, device_table);
581
582/* -- device connect -- */
583static int sd_probe(struct usb_interface *intf,
584 const struct usb_device_id *id)
585{
586 PDEBUG(D_PROBE, "Probing for a stv06xx device");
587 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
588 THIS_MODULE);
589}
590
591static void sd_disconnect(struct usb_interface *intf)
592{
593 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
594 struct sd *sd = (struct sd *) gspca_dev;
595 PDEBUG(D_PROBE, "Disconnecting the stv06xx device");
596
597 if (sd->sensor->disconnect)
598 sd->sensor->disconnect(sd);
599 gspca_disconnect(intf);
600}
601
602static struct usb_driver sd_driver = {
603 .name = MODULE_NAME,
604 .id_table = device_table,
605 .probe = sd_probe,
606 .disconnect = sd_disconnect,
607#ifdef CONFIG_PM
608 .suspend = gspca_suspend,
609 .resume = gspca_resume,
610#endif
611};
612
613/* -- module insert / remove -- */
614static int __init sd_mod_init(void)
615{
616 return usb_register(&sd_driver);
617}
618static void __exit sd_mod_exit(void)
619{
620 usb_deregister(&sd_driver);
621}
622
623module_init(sd_mod_init);
624module_exit(sd_mod_exit);
625
626module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
627MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
628
629module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
630MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup");
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h
new file mode 100644
index 00000000000..e0f63c51f40
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.h
@@ -0,0 +1,115 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_H_
31#define STV06XX_H_
32
33#include <linux/slab.h>
34#include "gspca.h"
35
36#define MODULE_NAME "STV06xx"
37
38#define STV_ISOC_ENDPOINT_ADDR 0x81
39
40#define STV_REG23 0x0423
41
42/* Control registers of the STV0600 ASIC */
43#define STV_I2C_PARTNER 0x1420
44#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421
45#define STV_I2C_READ_WRITE_TOGGLE 0x1422
46#define STV_I2C_FLUSH 0x1423
47#define STV_I2C_SUCC_READ_REG_VALS 0x1424
48
49#define STV_ISO_ENABLE 0x1440
50#define STV_SCAN_RATE 0x1443
51#define STV_LED_CTRL 0x1445
52#define STV_STV0600_EMULATION 0x1446
53#define STV_REG00 0x1500
54#define STV_REG01 0x1501
55#define STV_REG02 0x1502
56#define STV_REG03 0x1503
57#define STV_REG04 0x1504
58
59#define STV_ISO_SIZE_L 0x15c1
60#define STV_ISO_SIZE_H 0x15c2
61
62/* Refers to the CIF 352x288 and QCIF 176x144 */
63/* 1: 288 lines, 2: 144 lines */
64#define STV_Y_CTRL 0x15c3
65
66/* 0xa: 352 columns, 0x6: 176 columns */
67#define STV_X_CTRL 0x1680
68
69#define STV06XX_URB_MSG_TIMEOUT 5000
70
71#define I2C_MAX_BYTES 16
72#define I2C_MAX_WORDS 8
73
74#define I2C_BUFFER_LENGTH 0x23
75#define I2C_READ_CMD 3
76#define I2C_WRITE_CMD 1
77
78#define LED_ON 1
79#define LED_OFF 0
80
81/* STV06xx device descriptor */
82struct sd {
83 struct gspca_dev gspca_dev;
84
85 /* A pointer to the currently connected sensor */
86 const struct stv06xx_sensor *sensor;
87
88 /* A pointer to the sd_desc struct */
89 struct sd_desc desc;
90
91 /* Sensor private data */
92 void *sensor_priv;
93
94 /* The first 4 lines produced by the stv6422 are no good, this keeps
95 track of how many bytes we still need to skip during a frame */
96 int to_skip;
97
98 /* Bridge / Camera type */
99 u8 bridge;
100 #define BRIDGE_STV600 0
101 #define BRIDGE_STV602 1
102 #define BRIDGE_STV610 2
103 #define BRIDGE_ST6422 3 /* With integrated sensor */
104};
105
106int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
107int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data);
108
109int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len);
110int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len);
111
112int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value);
113int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value);
114
115#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
new file mode 100644
index 00000000000..b8156855f2b
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
@@ -0,0 +1,611 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 * Copyright (c) 2008 Chia-I Wu
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * P/N 861037: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
24 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
25 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
26 * P/N 861075-0040: Sensor HDCS1000 ASIC
27 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
28 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
29 */
30
31#include "stv06xx_hdcs.h"
32
33static const struct ctrl hdcs1x00_ctrl[] = {
34 {
35 {
36 .id = V4L2_CID_EXPOSURE,
37 .type = V4L2_CTRL_TYPE_INTEGER,
38 .name = "exposure",
39 .minimum = 0x00,
40 .maximum = 0xff,
41 .step = 0x1,
42 .default_value = HDCS_DEFAULT_EXPOSURE,
43 .flags = V4L2_CTRL_FLAG_SLIDER
44 },
45 .set = hdcs_set_exposure,
46 .get = hdcs_get_exposure
47 }, {
48 {
49 .id = V4L2_CID_GAIN,
50 .type = V4L2_CTRL_TYPE_INTEGER,
51 .name = "gain",
52 .minimum = 0x00,
53 .maximum = 0xff,
54 .step = 0x1,
55 .default_value = HDCS_DEFAULT_GAIN,
56 .flags = V4L2_CTRL_FLAG_SLIDER
57 },
58 .set = hdcs_set_gain,
59 .get = hdcs_get_gain
60 }
61};
62
63static struct v4l2_pix_format hdcs1x00_mode[] = {
64 {
65 HDCS_1X00_DEF_WIDTH,
66 HDCS_1X00_DEF_HEIGHT,
67 V4L2_PIX_FMT_SGRBG8,
68 V4L2_FIELD_NONE,
69 .sizeimage =
70 HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
71 .bytesperline = HDCS_1X00_DEF_WIDTH,
72 .colorspace = V4L2_COLORSPACE_SRGB,
73 .priv = 1
74 }
75};
76
77static const struct ctrl hdcs1020_ctrl[] = {
78 {
79 {
80 .id = V4L2_CID_EXPOSURE,
81 .type = V4L2_CTRL_TYPE_INTEGER,
82 .name = "exposure",
83 .minimum = 0x00,
84 .maximum = 0xffff,
85 .step = 0x1,
86 .default_value = HDCS_DEFAULT_EXPOSURE,
87 .flags = V4L2_CTRL_FLAG_SLIDER
88 },
89 .set = hdcs_set_exposure,
90 .get = hdcs_get_exposure
91 }, {
92 {
93 .id = V4L2_CID_GAIN,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "gain",
96 .minimum = 0x00,
97 .maximum = 0xff,
98 .step = 0x1,
99 .default_value = HDCS_DEFAULT_GAIN,
100 .flags = V4L2_CTRL_FLAG_SLIDER
101 },
102 .set = hdcs_set_gain,
103 .get = hdcs_get_gain
104 }
105};
106
107static struct v4l2_pix_format hdcs1020_mode[] = {
108 {
109 HDCS_1020_DEF_WIDTH,
110 HDCS_1020_DEF_HEIGHT,
111 V4L2_PIX_FMT_SGRBG8,
112 V4L2_FIELD_NONE,
113 .sizeimage =
114 HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
115 .bytesperline = HDCS_1020_DEF_WIDTH,
116 .colorspace = V4L2_COLORSPACE_SRGB,
117 .priv = 1
118 }
119};
120
121enum hdcs_power_state {
122 HDCS_STATE_SLEEP,
123 HDCS_STATE_IDLE,
124 HDCS_STATE_RUN
125};
126
127/* no lock? */
128struct hdcs {
129 enum hdcs_power_state state;
130 int w, h;
131
132 /* visible area of the sensor array */
133 struct {
134 int left, top;
135 int width, height;
136 int border;
137 } array;
138
139 struct {
140 /* Column timing overhead */
141 u8 cto;
142 /* Column processing overhead */
143 u8 cpo;
144 /* Row sample period constant */
145 u16 rs;
146 /* Exposure reset duration */
147 u16 er;
148 } exp;
149
150 int psmp;
151 u8 exp_cache, gain_cache;
152};
153
154static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
155{
156 u8 regs[I2C_MAX_BYTES * 2];
157 int i;
158
159 if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) ||
160 (reg + len > 0xff)))
161 return -EINVAL;
162
163 for (i = 0; i < len; i++) {
164 regs[2 * i] = reg;
165 regs[2 * i + 1] = vals[i];
166 /* All addresses are shifted left one bit
167 * as bit 0 toggles r/w */
168 reg += 2;
169 }
170
171 return stv06xx_write_sensor_bytes(sd, regs, len);
172}
173
174static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
175{
176 struct hdcs *hdcs = sd->sensor_priv;
177 u8 val;
178 int ret;
179
180 if (hdcs->state == state)
181 return 0;
182
183 /* we need to go idle before running or sleeping */
184 if (hdcs->state != HDCS_STATE_IDLE) {
185 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
186 if (ret)
187 return ret;
188 }
189
190 hdcs->state = HDCS_STATE_IDLE;
191
192 if (state == HDCS_STATE_IDLE)
193 return 0;
194
195 switch (state) {
196 case HDCS_STATE_SLEEP:
197 val = HDCS_SLEEP_MODE;
198 break;
199
200 case HDCS_STATE_RUN:
201 val = HDCS_RUN_ENABLE;
202 break;
203
204 default:
205 return -EINVAL;
206 }
207
208 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
209
210 /* Update the state if the write succeeded */
211 if (!ret)
212 hdcs->state = state;
213
214 return ret;
215}
216
217static int hdcs_reset(struct sd *sd)
218{
219 struct hdcs *hdcs = sd->sensor_priv;
220 int err;
221
222 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
223 if (err < 0)
224 return err;
225
226 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
227 if (err < 0)
228 hdcs->state = HDCS_STATE_IDLE;
229
230 return err;
231}
232
233static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
234{
235 struct sd *sd = (struct sd *) gspca_dev;
236 struct hdcs *hdcs = sd->sensor_priv;
237
238 *val = hdcs->exp_cache;
239
240 return 0;
241}
242
243static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
244{
245 struct sd *sd = (struct sd *) gspca_dev;
246 struct hdcs *hdcs = sd->sensor_priv;
247 int rowexp, srowexp;
248 int max_srowexp;
249 /* Column time period */
250 int ct;
251 /* Column processing period */
252 int cp;
253 /* Row processing period */
254 int rp;
255 /* Minimum number of column timing periods
256 within the column processing period */
257 int mnct;
258 int cycles, err;
259 u8 exp[14];
260
261 val &= 0xff;
262 hdcs->exp_cache = val;
263
264 cycles = val * HDCS_CLK_FREQ_MHZ * 257;
265
266 ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
267 cp = hdcs->exp.cto + (hdcs->w * ct / 2);
268
269 /* the cycles one row takes */
270 rp = hdcs->exp.rs + cp;
271
272 rowexp = cycles / rp;
273
274 /* the remaining cycles */
275 cycles -= rowexp * rp;
276
277 /* calculate sub-row exposure */
278 if (IS_1020(sd)) {
279 /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
280 srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;
281
282 mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
283 max_srowexp = hdcs->w - mnct;
284 } else {
285 /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
286 srowexp = cp - hdcs->exp.er - 6 - cycles;
287
288 mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
289 max_srowexp = cp - mnct * ct - 1;
290 }
291
292 if (srowexp < 0)
293 srowexp = 0;
294 else if (srowexp > max_srowexp)
295 srowexp = max_srowexp;
296
297 if (IS_1020(sd)) {
298 exp[0] = HDCS20_CONTROL;
299 exp[1] = 0x00; /* Stop streaming */
300 exp[2] = HDCS_ROWEXPL;
301 exp[3] = rowexp & 0xff;
302 exp[4] = HDCS_ROWEXPH;
303 exp[5] = rowexp >> 8;
304 exp[6] = HDCS20_SROWEXP;
305 exp[7] = (srowexp >> 2) & 0xff;
306 exp[8] = HDCS20_ERROR;
307 exp[9] = 0x10; /* Clear exposure error flag*/
308 exp[10] = HDCS20_CONTROL;
309 exp[11] = 0x04; /* Restart streaming */
310 err = stv06xx_write_sensor_bytes(sd, exp, 6);
311 } else {
312 exp[0] = HDCS00_CONTROL;
313 exp[1] = 0x00; /* Stop streaming */
314 exp[2] = HDCS_ROWEXPL;
315 exp[3] = rowexp & 0xff;
316 exp[4] = HDCS_ROWEXPH;
317 exp[5] = rowexp >> 8;
318 exp[6] = HDCS00_SROWEXPL;
319 exp[7] = srowexp & 0xff;
320 exp[8] = HDCS00_SROWEXPH;
321 exp[9] = srowexp >> 8;
322 exp[10] = HDCS_STATUS;
323 exp[11] = 0x10; /* Clear exposure error flag*/
324 exp[12] = HDCS00_CONTROL;
325 exp[13] = 0x04; /* Restart streaming */
326 err = stv06xx_write_sensor_bytes(sd, exp, 7);
327 if (err < 0)
328 return err;
329 }
330 PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
331 val, rowexp, srowexp);
332 return err;
333}
334
335static int hdcs_set_gains(struct sd *sd, u8 g)
336{
337 struct hdcs *hdcs = sd->sensor_priv;
338 int err;
339 u8 gains[4];
340
341 hdcs->gain_cache = g;
342
343 /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
344 if (g > 127)
345 g = 0x80 | (g / 2);
346
347 gains[0] = g;
348 gains[1] = g;
349 gains[2] = g;
350 gains[3] = g;
351
352 err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
353 return err;
354}
355
356static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
357{
358 struct sd *sd = (struct sd *) gspca_dev;
359 struct hdcs *hdcs = sd->sensor_priv;
360
361 *val = hdcs->gain_cache;
362
363 return 0;
364}
365
366static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
367{
368 PDEBUG(D_V4L2, "Writing gain %d", val);
369 return hdcs_set_gains((struct sd *) gspca_dev,
370 val & 0xff);
371}
372
373static int hdcs_set_size(struct sd *sd,
374 unsigned int width, unsigned int height)
375{
376 struct hdcs *hdcs = sd->sensor_priv;
377 u8 win[4];
378 unsigned int x, y;
379 int err;
380
381 /* must be multiple of 4 */
382 width = (width + 3) & ~0x3;
383 height = (height + 3) & ~0x3;
384
385 if (width > hdcs->array.width)
386 width = hdcs->array.width;
387
388 if (IS_1020(sd)) {
389 /* the borders are also invalid */
390 if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
391 > hdcs->array.height)
392 height = hdcs->array.height - 2 * hdcs->array.border -
393 HDCS_1020_BOTTOM_Y_SKIP;
394
395 y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
396 + hdcs->array.top;
397 } else {
398 if (height > hdcs->array.height)
399 height = hdcs->array.height;
400
401 y = hdcs->array.top + (hdcs->array.height - height) / 2;
402 }
403
404 x = hdcs->array.left + (hdcs->array.width - width) / 2;
405
406 win[0] = y / 4;
407 win[1] = x / 4;
408 win[2] = (y + height) / 4 - 1;
409 win[3] = (x + width) / 4 - 1;
410
411 err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
412 if (err < 0)
413 return err;
414
415 /* Update the current width and height */
416 hdcs->w = width;
417 hdcs->h = height;
418 return err;
419}
420
421static int hdcs_probe_1x00(struct sd *sd)
422{
423 struct hdcs *hdcs;
424 u16 sensor;
425 int ret;
426
427 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
428 if (ret < 0 || sensor != 0x08)
429 return -ENODEV;
430
431 info("HDCS-1000/1100 sensor detected");
432
433 sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
434 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
435 sd->desc.ctrls = hdcs1x00_ctrl;
436 sd->desc.nctrls = ARRAY_SIZE(hdcs1x00_ctrl);
437
438 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
439 if (!hdcs)
440 return -ENOMEM;
441
442 hdcs->array.left = 8;
443 hdcs->array.top = 8;
444 hdcs->array.width = HDCS_1X00_DEF_WIDTH;
445 hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
446 hdcs->array.border = 4;
447
448 hdcs->exp.cto = 4;
449 hdcs->exp.cpo = 2;
450 hdcs->exp.rs = 186;
451 hdcs->exp.er = 100;
452
453 /*
454 * Frame rate on HDCS-1000 with STV600 depends on PSMP:
455 * 4 = doesn't work at all
456 * 5 = 7.8 fps,
457 * 6 = 6.9 fps,
458 * 8 = 6.3 fps,
459 * 10 = 5.5 fps,
460 * 15 = 4.4 fps,
461 * 31 = 2.8 fps
462 *
463 * Frame rate on HDCS-1000 with STV602 depends on PSMP:
464 * 15 = doesn't work at all
465 * 18 = doesn't work at all
466 * 19 = 7.3 fps
467 * 20 = 7.4 fps
468 * 21 = 7.4 fps
469 * 22 = 7.4 fps
470 * 24 = 6.3 fps
471 * 30 = 5.4 fps
472 */
473 hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
474
475 sd->sensor_priv = hdcs;
476
477 return 0;
478}
479
480static int hdcs_probe_1020(struct sd *sd)
481{
482 struct hdcs *hdcs;
483 u16 sensor;
484 int ret;
485
486 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
487 if (ret < 0 || sensor != 0x10)
488 return -ENODEV;
489
490 info("HDCS-1020 sensor detected");
491
492 sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
493 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
494 sd->desc.ctrls = hdcs1020_ctrl;
495 sd->desc.nctrls = ARRAY_SIZE(hdcs1020_ctrl);
496
497 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
498 if (!hdcs)
499 return -ENOMEM;
500
501 /*
502 * From Andrey's test image: looks like HDCS-1020 upper-left
503 * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
504 * visible pixel at 375,299 (x maybe even larger?)
505 */
506 hdcs->array.left = 24;
507 hdcs->array.top = 4;
508 hdcs->array.width = HDCS_1020_DEF_WIDTH;
509 hdcs->array.height = 304;
510 hdcs->array.border = 4;
511
512 hdcs->psmp = 6;
513
514 hdcs->exp.cto = 3;
515 hdcs->exp.cpo = 3;
516 hdcs->exp.rs = 155;
517 hdcs->exp.er = 96;
518
519 sd->sensor_priv = hdcs;
520
521 return 0;
522}
523
524static int hdcs_start(struct sd *sd)
525{
526 PDEBUG(D_STREAM, "Starting stream");
527
528 return hdcs_set_state(sd, HDCS_STATE_RUN);
529}
530
531static int hdcs_stop(struct sd *sd)
532{
533 PDEBUG(D_STREAM, "Halting stream");
534
535 return hdcs_set_state(sd, HDCS_STATE_SLEEP);
536}
537
538static void hdcs_disconnect(struct sd *sd)
539{
540 PDEBUG(D_PROBE, "Disconnecting the sensor");
541 kfree(sd->sensor_priv);
542}
543
544static int hdcs_init(struct sd *sd)
545{
546 struct hdcs *hdcs = sd->sensor_priv;
547 int i, err = 0;
548
549 /* Set the STV0602AA in STV0600 emulation mode */
550 if (sd->bridge == BRIDGE_STV602)
551 stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
552
553 /* Execute the bridge init */
554 for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
555 err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
556 stv_bridge_init[i][1]);
557 }
558 if (err < 0)
559 return err;
560
561 /* sensor soft reset */
562 hdcs_reset(sd);
563
564 /* Execute the sensor init */
565 for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
566 err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
567 stv_sensor_init[i][1]);
568 }
569 if (err < 0)
570 return err;
571
572 /* Enable continuous frame capture, bit 2: stop when frame complete */
573 err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
574 if (err < 0)
575 return err;
576
577 /* Set PGA sample duration
578 (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
579 if (IS_1020(sd))
580 err = stv06xx_write_sensor(sd, HDCS_TCTRL,
581 (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
582 else
583 err = stv06xx_write_sensor(sd, HDCS_TCTRL,
584 (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
585 if (err < 0)
586 return err;
587
588 err = hdcs_set_gains(sd, HDCS_DEFAULT_GAIN);
589 if (err < 0)
590 return err;
591
592 err = hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
593 if (err < 0)
594 return err;
595
596 err = hdcs_set_exposure(&sd->gspca_dev, HDCS_DEFAULT_EXPOSURE);
597 return err;
598}
599
600static int hdcs_dump(struct sd *sd)
601{
602 u16 reg, val;
603
604 info("Dumping sensor registers:");
605
606 for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
607 stv06xx_read_sensor(sd, reg, &val);
608 info("reg 0x%02x = 0x%02x", reg, val);
609 }
610 return 0;
611}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
new file mode 100644
index 00000000000..a14a84a5079
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
@@ -0,0 +1,207 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 * Copyright (c) 2008 Chia-I Wu
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * P/N 861037: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
24 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
25 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
26 * P/N 861075-0040: Sensor HDCS1000 ASIC
27 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
28 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
29 */
30
31#ifndef STV06XX_HDCS_H_
32#define STV06XX_HDCS_H_
33
34#include "stv06xx_sensor.h"
35
36#define HDCS_REG_CONFIG(sd) (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG)
37#define HDCS_REG_CONTROL(sd) (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL)
38
39#define HDCS_1X00_DEF_WIDTH 360
40#define HDCS_1X00_DEF_HEIGHT 296
41
42#define HDCS_1020_DEF_WIDTH 352
43#define HDCS_1020_DEF_HEIGHT 292
44
45#define HDCS_1020_BOTTOM_Y_SKIP 4
46
47#define HDCS_CLK_FREQ_MHZ 25
48
49#define HDCS_ADC_START_SIG_DUR 3
50
51/* LSB bit of I2C or register address signifies write (0) or read (1) */
52/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */
53/* Identifications Register */
54#define HDCS_IDENT (0x00 << 1)
55/* Status Register */
56#define HDCS_STATUS (0x01 << 1)
57/* Interrupt Mask Register */
58#define HDCS_IMASK (0x02 << 1)
59/* Pad Control Register */
60#define HDCS_PCTRL (0x03 << 1)
61/* Pad Drive Control Register */
62#define HDCS_PDRV (0x04 << 1)
63/* Interface Control Register */
64#define HDCS_ICTRL (0x05 << 1)
65/* Interface Timing Register */
66#define HDCS_ITMG (0x06 << 1)
67/* Baud Fraction Register */
68#define HDCS_BFRAC (0x07 << 1)
69/* Baud Rate Register */
70#define HDCS_BRATE (0x08 << 1)
71/* ADC Control Register */
72#define HDCS_ADCCTRL (0x09 << 1)
73/* First Window Row Register */
74#define HDCS_FWROW (0x0a << 1)
75/* First Window Column Register */
76#define HDCS_FWCOL (0x0b << 1)
77/* Last Window Row Register */
78#define HDCS_LWROW (0x0c << 1)
79/* Last Window Column Register */
80#define HDCS_LWCOL (0x0d << 1)
81/* Timing Control Register */
82#define HDCS_TCTRL (0x0e << 1)
83/* PGA Gain Register: Even Row, Even Column */
84#define HDCS_ERECPGA (0x0f << 1)
85/* PGA Gain Register: Even Row, Odd Column */
86#define HDCS_EROCPGA (0x10 << 1)
87/* PGA Gain Register: Odd Row, Even Column */
88#define HDCS_ORECPGA (0x11 << 1)
89/* PGA Gain Register: Odd Row, Odd Column */
90#define HDCS_OROCPGA (0x12 << 1)
91/* Row Exposure Low Register */
92#define HDCS_ROWEXPL (0x13 << 1)
93/* Row Exposure High Register */
94#define HDCS_ROWEXPH (0x14 << 1)
95
96/* I2C Registers only for HDCS-1000/1100 */
97/* Sub-Row Exposure Low Register */
98#define HDCS00_SROWEXPL (0x15 << 1)
99/* Sub-Row Exposure High Register */
100#define HDCS00_SROWEXPH (0x16 << 1)
101/* Configuration Register */
102#define HDCS00_CONFIG (0x17 << 1)
103/* Control Register */
104#define HDCS00_CONTROL (0x18 << 1)
105
106/* I2C Registers only for HDCS-1020 */
107/* Sub-Row Exposure Register */
108#define HDCS20_SROWEXP (0x15 << 1)
109/* Error Control Register */
110#define HDCS20_ERROR (0x16 << 1)
111/* Interface Timing 2 Register */
112#define HDCS20_ITMG2 (0x17 << 1)
113/* Interface Control 2 Register */
114#define HDCS20_ICTRL2 (0x18 << 1)
115/* Horizontal Blank Register */
116#define HDCS20_HBLANK (0x19 << 1)
117/* Vertical Blank Register */
118#define HDCS20_VBLANK (0x1a << 1)
119/* Configuration Register */
120#define HDCS20_CONFIG (0x1b << 1)
121/* Control Register */
122#define HDCS20_CONTROL (0x1c << 1)
123
124#define HDCS_RUN_ENABLE (1 << 2)
125#define HDCS_SLEEP_MODE (1 << 1)
126
127#define HDCS_DEFAULT_EXPOSURE 48
128#define HDCS_DEFAULT_GAIN 50
129
130static int hdcs_probe_1x00(struct sd *sd);
131static int hdcs_probe_1020(struct sd *sd);
132static int hdcs_start(struct sd *sd);
133static int hdcs_init(struct sd *sd);
134static int hdcs_stop(struct sd *sd);
135static int hdcs_dump(struct sd *sd);
136static void hdcs_disconnect(struct sd *sd);
137
138static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
139static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
140static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val);
141static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
142
143const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
144 .name = "HP HDCS-1000/1100",
145 .i2c_flush = 0,
146 .i2c_addr = (0x55 << 1),
147 .i2c_len = 1,
148
149 /* FIXME (see if we can lower min_packet_size, needs testing, and also
150 adjusting framerate when the bandwidth gets lower) */
151 .min_packet_size = { 847 },
152 .max_packet_size = { 847 },
153
154 .init = hdcs_init,
155 .probe = hdcs_probe_1x00,
156 .start = hdcs_start,
157 .stop = hdcs_stop,
158 .disconnect = hdcs_disconnect,
159 .dump = hdcs_dump,
160};
161
162const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
163 .name = "HDCS-1020",
164 .i2c_flush = 0,
165 .i2c_addr = (0x55 << 1),
166 .i2c_len = 1,
167
168 /* FIXME (see if we can lower min_packet_size, needs testing, and also
169 adjusting framerate when the bandwidthm gets lower) */
170 .min_packet_size = { 847 },
171 .max_packet_size = { 847 },
172
173 .init = hdcs_init,
174 .probe = hdcs_probe_1020,
175 .start = hdcs_start,
176 .stop = hdcs_stop,
177 .dump = hdcs_dump,
178};
179
180static const u16 stv_bridge_init[][2] = {
181 {STV_ISO_ENABLE, 0},
182 {STV_REG23, 0},
183 {STV_REG00, 0x1d},
184 {STV_REG01, 0xb5},
185 {STV_REG02, 0xa8},
186 {STV_REG03, 0x95},
187 {STV_REG04, 0x07},
188
189 {STV_SCAN_RATE, 0x20},
190 {STV_Y_CTRL, 0x01},
191 {STV_X_CTRL, 0x0a}
192};
193
194static const u8 stv_sensor_init[][2] = {
195 /* Clear status (writing 1 will clear the corresponding status bit) */
196 {HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
197 /* Disable all interrupts */
198 {HDCS_IMASK, 0x00},
199 {HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)},
200 {HDCS_PDRV, 0x00},
201 {HDCS_ICTRL, BIT(5)},
202 {HDCS_ITMG, BIT(4) | BIT(1)},
203 /* ADC output resolution to 10 bits */
204 {HDCS_ADCCTRL, 10}
205};
206
207#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
new file mode 100644
index 00000000000..75a5b9c2f15
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
@@ -0,0 +1,573 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30/*
31 * The spec file for the PB-0100 suggests the following for best quality
32 * images after the sensor has been reset :
33 *
34 * PB_ADCGAINL = R60 = 0x03 (3 dec) : sets low reference of ADC
35 to produce good black level
36 * PB_PREADCTRL = R32 = 0x1400 (5120 dec) : Enables global gain changes
37 through R53
38 * PB_ADCMINGAIN = R52 = 0x10 (16 dec) : Sets the minimum gain for
39 auto-exposure
40 * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec) : Sets the global gain
41 * PB_EXPGAIN = R14 = 0x11 (17 dec) : Sets the auto-exposure value
42 * PB_UPDATEINT = R23 = 0x02 (2 dec) : Sets the speed on
43 auto-exposure routine
44 * PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate
45 */
46
47#include "stv06xx_pb0100.h"
48
49static const struct ctrl pb0100_ctrl[] = {
50#define GAIN_IDX 0
51 {
52 {
53 .id = V4L2_CID_GAIN,
54 .type = V4L2_CTRL_TYPE_INTEGER,
55 .name = "Gain",
56 .minimum = 0,
57 .maximum = 255,
58 .step = 1,
59 .default_value = 128
60 },
61 .set = pb0100_set_gain,
62 .get = pb0100_get_gain
63 },
64#define RED_BALANCE_IDX 1
65 {
66 {
67 .id = V4L2_CID_RED_BALANCE,
68 .type = V4L2_CTRL_TYPE_INTEGER,
69 .name = "Red Balance",
70 .minimum = -255,
71 .maximum = 255,
72 .step = 1,
73 .default_value = 0
74 },
75 .set = pb0100_set_red_balance,
76 .get = pb0100_get_red_balance
77 },
78#define BLUE_BALANCE_IDX 2
79 {
80 {
81 .id = V4L2_CID_BLUE_BALANCE,
82 .type = V4L2_CTRL_TYPE_INTEGER,
83 .name = "Blue Balance",
84 .minimum = -255,
85 .maximum = 255,
86 .step = 1,
87 .default_value = 0
88 },
89 .set = pb0100_set_blue_balance,
90 .get = pb0100_get_blue_balance
91 },
92#define EXPOSURE_IDX 3
93 {
94 {
95 .id = V4L2_CID_EXPOSURE,
96 .type = V4L2_CTRL_TYPE_INTEGER,
97 .name = "Exposure",
98 .minimum = 0,
99 .maximum = 511,
100 .step = 1,
101 .default_value = 12
102 },
103 .set = pb0100_set_exposure,
104 .get = pb0100_get_exposure
105 },
106#define AUTOGAIN_IDX 4
107 {
108 {
109 .id = V4L2_CID_AUTOGAIN,
110 .type = V4L2_CTRL_TYPE_BOOLEAN,
111 .name = "Automatic Gain and Exposure",
112 .minimum = 0,
113 .maximum = 1,
114 .step = 1,
115 .default_value = 1
116 },
117 .set = pb0100_set_autogain,
118 .get = pb0100_get_autogain
119 },
120#define AUTOGAIN_TARGET_IDX 5
121 {
122 {
123 .id = V4L2_CTRL_CLASS_USER + 0x1000,
124 .type = V4L2_CTRL_TYPE_INTEGER,
125 .name = "Automatic Gain Target",
126 .minimum = 0,
127 .maximum = 255,
128 .step = 1,
129 .default_value = 128
130 },
131 .set = pb0100_set_autogain_target,
132 .get = pb0100_get_autogain_target
133 },
134#define NATURAL_IDX 6
135 {
136 {
137 .id = V4L2_CTRL_CLASS_USER + 0x1001,
138 .type = V4L2_CTRL_TYPE_BOOLEAN,
139 .name = "Natural Light Source",
140 .minimum = 0,
141 .maximum = 1,
142 .step = 1,
143 .default_value = 1
144 },
145 .set = pb0100_set_natural,
146 .get = pb0100_get_natural
147 }
148};
149
150static struct v4l2_pix_format pb0100_mode[] = {
151/* low res / subsample modes disabled as they are only half res horizontal,
152 halving the vertical resolution does not seem to work */
153 {
154 320,
155 240,
156 V4L2_PIX_FMT_SGRBG8,
157 V4L2_FIELD_NONE,
158 .sizeimage = 320 * 240,
159 .bytesperline = 320,
160 .colorspace = V4L2_COLORSPACE_SRGB,
161 .priv = PB0100_CROP_TO_VGA
162 },
163 {
164 352,
165 288,
166 V4L2_PIX_FMT_SGRBG8,
167 V4L2_FIELD_NONE,
168 .sizeimage = 352 * 288,
169 .bytesperline = 352,
170 .colorspace = V4L2_COLORSPACE_SRGB,
171 .priv = 0
172 }
173};
174
175static int pb0100_probe(struct sd *sd)
176{
177 u16 sensor;
178 int i, err;
179 s32 *sensor_settings;
180
181 err = stv06xx_read_sensor(sd, PB_IDENT, &sensor);
182
183 if (err < 0)
184 return -ENODEV;
185
186 if ((sensor >> 8) == 0x64) {
187 sensor_settings = kmalloc(
188 ARRAY_SIZE(pb0100_ctrl) * sizeof(s32),
189 GFP_KERNEL);
190 if (!sensor_settings)
191 return -ENOMEM;
192
193 info("Photobit pb0100 sensor detected");
194
195 sd->gspca_dev.cam.cam_mode = pb0100_mode;
196 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
197 sd->desc.ctrls = pb0100_ctrl;
198 sd->desc.nctrls = ARRAY_SIZE(pb0100_ctrl);
199 for (i = 0; i < sd->desc.nctrls; i++)
200 sensor_settings[i] = pb0100_ctrl[i].qctrl.default_value;
201 sd->sensor_priv = sensor_settings;
202
203 return 0;
204 }
205
206 return -ENODEV;
207}
208
209static int pb0100_start(struct sd *sd)
210{
211 int err, packet_size, max_packet_size;
212 struct usb_host_interface *alt;
213 struct usb_interface *intf;
214 struct cam *cam = &sd->gspca_dev.cam;
215 s32 *sensor_settings = sd->sensor_priv;
216 u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
217
218 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
219 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
220 if (!alt)
221 return -ENODEV;
222 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
223
224 /* If we don't have enough bandwidth use a lower framerate */
225 max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
226 if (packet_size < max_packet_size)
227 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
228 else
229 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
230
231 /* Setup sensor window */
232 if (mode & PB0100_CROP_TO_VGA) {
233 stv06xx_write_sensor(sd, PB_RSTART, 30);
234 stv06xx_write_sensor(sd, PB_CSTART, 20);
235 stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1);
236 stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1);
237 } else {
238 stv06xx_write_sensor(sd, PB_RSTART, 8);
239 stv06xx_write_sensor(sd, PB_CSTART, 4);
240 stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1);
241 stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1);
242 }
243
244 if (mode & PB0100_SUBSAMPLE) {
245 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */
246 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
247
248 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
249 } else {
250 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
251 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
252 /* larger -> slower */
253 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
254 }
255
256 /* set_gain also sets red and blue balance */
257 pb0100_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
258 pb0100_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]);
259 pb0100_set_autogain_target(&sd->gspca_dev,
260 sensor_settings[AUTOGAIN_TARGET_IDX]);
261 pb0100_set_autogain(&sd->gspca_dev, sensor_settings[AUTOGAIN_IDX]);
262
263 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1));
264 PDEBUG(D_STREAM, "Started stream, status: %d", err);
265
266 return (err < 0) ? err : 0;
267}
268
269static int pb0100_stop(struct sd *sd)
270{
271 int err;
272
273 err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
274
275 if (err < 0)
276 goto out;
277
278 /* Set bit 1 to zero */
279 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
280
281 PDEBUG(D_STREAM, "Halting stream");
282out:
283 return (err < 0) ? err : 0;
284}
285
286static void pb0100_disconnect(struct sd *sd)
287{
288 sd->sensor = NULL;
289 kfree(sd->sensor_priv);
290}
291
292/* FIXME: Sort the init commands out and put them into tables,
293 this is only for getting the camera to work */
294/* FIXME: No error handling for now,
295 add this once the init has been converted to proper tables */
296static int pb0100_init(struct sd *sd)
297{
298 stv06xx_write_bridge(sd, STV_REG00, 1);
299 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0);
300
301 /* Reset sensor */
302 stv06xx_write_sensor(sd, PB_RESET, 1);
303 stv06xx_write_sensor(sd, PB_RESET, 0);
304
305 /* Disable chip */
306 stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
307
308 /* Gain stuff...*/
309 stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6));
310 stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12);
311
312 /* Set up auto-exposure */
313 /* ADC VREF_HI new setting for a transition
314 from the Expose1 to the Expose2 setting */
315 stv06xx_write_sensor(sd, PB_R28, 12);
316 /* gain max for autoexposure */
317 stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180);
318 /* gain min for autoexposure */
319 stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12);
320 /* Maximum frame integration time (programmed into R8)
321 allowed for auto-exposure routine */
322 stv06xx_write_sensor(sd, PB_R54, 3);
323 /* Minimum frame integration time (programmed into R8)
324 allowed for auto-exposure routine */
325 stv06xx_write_sensor(sd, PB_R55, 0);
326 stv06xx_write_sensor(sd, PB_UPDATEINT, 1);
327 /* R15 Expose0 (maximum that auto-exposure may use) */
328 stv06xx_write_sensor(sd, PB_R15, 800);
329 /* R17 Expose2 (minimum that auto-exposure may use) */
330 stv06xx_write_sensor(sd, PB_R17, 10);
331
332 stv06xx_write_sensor(sd, PB_EXPGAIN, 0);
333
334 /* 0x14 */
335 stv06xx_write_sensor(sd, PB_VOFFSET, 0);
336 /* 0x0D */
337 stv06xx_write_sensor(sd, PB_ADCGAINH, 11);
338 /* Set black level (important!) */
339 stv06xx_write_sensor(sd, PB_ADCGAINL, 0);
340
341 /* ??? */
342 stv06xx_write_bridge(sd, STV_REG00, 0x11);
343 stv06xx_write_bridge(sd, STV_REG03, 0x45);
344 stv06xx_write_bridge(sd, STV_REG04, 0x07);
345
346 /* Scan/timing for the sensor */
347 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
348 stv06xx_write_sensor(sd, PB_CFILLIN, 14);
349 stv06xx_write_sensor(sd, PB_VBL, 0);
350 stv06xx_write_sensor(sd, PB_FINTTIME, 0);
351 stv06xx_write_sensor(sd, PB_RINTTIME, 123);
352
353 stv06xx_write_bridge(sd, STV_REG01, 0xc2);
354 stv06xx_write_bridge(sd, STV_REG02, 0xb0);
355 return 0;
356}
357
358static int pb0100_dump(struct sd *sd)
359{
360 return 0;
361}
362
363static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
364{
365 struct sd *sd = (struct sd *) gspca_dev;
366 s32 *sensor_settings = sd->sensor_priv;
367
368 *val = sensor_settings[GAIN_IDX];
369
370 return 0;
371}
372
373static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
374{
375 int err;
376 struct sd *sd = (struct sd *) gspca_dev;
377 s32 *sensor_settings = sd->sensor_priv;
378
379 if (sensor_settings[AUTOGAIN_IDX])
380 return -EBUSY;
381
382 sensor_settings[GAIN_IDX] = val;
383 err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
384 if (!err)
385 err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
386 PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
387
388 if (!err)
389 err = pb0100_set_red_balance(gspca_dev,
390 sensor_settings[RED_BALANCE_IDX]);
391 if (!err)
392 err = pb0100_set_blue_balance(gspca_dev,
393 sensor_settings[BLUE_BALANCE_IDX]);
394
395 return err;
396}
397
398static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
399{
400 struct sd *sd = (struct sd *) gspca_dev;
401 s32 *sensor_settings = sd->sensor_priv;
402
403 *val = sensor_settings[RED_BALANCE_IDX];
404
405 return 0;
406}
407
408static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
409{
410 int err;
411 struct sd *sd = (struct sd *) gspca_dev;
412 s32 *sensor_settings = sd->sensor_priv;
413
414 if (sensor_settings[AUTOGAIN_IDX])
415 return -EBUSY;
416
417 sensor_settings[RED_BALANCE_IDX] = val;
418 val += sensor_settings[GAIN_IDX];
419 if (val < 0)
420 val = 0;
421 else if (val > 255)
422 val = 255;
423
424 err = stv06xx_write_sensor(sd, PB_RGAIN, val);
425 PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
426
427 return err;
428}
429
430static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
431{
432 struct sd *sd = (struct sd *) gspca_dev;
433 s32 *sensor_settings = sd->sensor_priv;
434
435 *val = sensor_settings[BLUE_BALANCE_IDX];
436
437 return 0;
438}
439
440static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
441{
442 int err;
443 struct sd *sd = (struct sd *) gspca_dev;
444 s32 *sensor_settings = sd->sensor_priv;
445
446 if (sensor_settings[AUTOGAIN_IDX])
447 return -EBUSY;
448
449 sensor_settings[BLUE_BALANCE_IDX] = val;
450 val += sensor_settings[GAIN_IDX];
451 if (val < 0)
452 val = 0;
453 else if (val > 255)
454 val = 255;
455
456 err = stv06xx_write_sensor(sd, PB_BGAIN, val);
457 PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
458
459 return err;
460}
461
462static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
463{
464 struct sd *sd = (struct sd *) gspca_dev;
465 s32 *sensor_settings = sd->sensor_priv;
466
467 *val = sensor_settings[EXPOSURE_IDX];
468
469 return 0;
470}
471
472static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
473{
474 int err;
475 struct sd *sd = (struct sd *) gspca_dev;
476 s32 *sensor_settings = sd->sensor_priv;
477
478 if (sensor_settings[AUTOGAIN_IDX])
479 return -EBUSY;
480
481 sensor_settings[EXPOSURE_IDX] = val;
482 err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
483 PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
484
485 return err;
486}
487
488static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val)
489{
490 struct sd *sd = (struct sd *) gspca_dev;
491 s32 *sensor_settings = sd->sensor_priv;
492
493 *val = sensor_settings[AUTOGAIN_IDX];
494
495 return 0;
496}
497
498static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
499{
500 int err;
501 struct sd *sd = (struct sd *) gspca_dev;
502 s32 *sensor_settings = sd->sensor_priv;
503
504 sensor_settings[AUTOGAIN_IDX] = val;
505 if (sensor_settings[AUTOGAIN_IDX]) {
506 if (sensor_settings[NATURAL_IDX])
507 val = BIT(6)|BIT(4)|BIT(0);
508 else
509 val = BIT(4)|BIT(0);
510 } else
511 val = 0;
512
513 err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
514 PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
515 sensor_settings[AUTOGAIN_IDX], sensor_settings[NATURAL_IDX],
516 err);
517
518 return err;
519}
520
521static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val)
522{
523 struct sd *sd = (struct sd *) gspca_dev;
524 s32 *sensor_settings = sd->sensor_priv;
525
526 *val = sensor_settings[AUTOGAIN_TARGET_IDX];
527
528 return 0;
529}
530
531static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
532{
533 int err, totalpixels, brightpixels, darkpixels;
534 struct sd *sd = (struct sd *) gspca_dev;
535 s32 *sensor_settings = sd->sensor_priv;
536
537 sensor_settings[AUTOGAIN_TARGET_IDX] = val;
538
539 /* Number of pixels counted by the sensor when subsampling the pixels.
540 * Slightly larger than the real value to avoid oscillation */
541 totalpixels = gspca_dev->width * gspca_dev->height;
542 totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
543
544 brightpixels = (totalpixels * val) >> 8;
545 darkpixels = totalpixels - brightpixels;
546 err = stv06xx_write_sensor(sd, PB_R21, brightpixels);
547 if (!err)
548 err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
549
550 PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
551
552 return err;
553}
554
555static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val)
556{
557 struct sd *sd = (struct sd *) gspca_dev;
558 s32 *sensor_settings = sd->sensor_priv;
559
560 *val = sensor_settings[NATURAL_IDX];
561
562 return 0;
563}
564
565static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val)
566{
567 struct sd *sd = (struct sd *) gspca_dev;
568 s32 *sensor_settings = sd->sensor_priv;
569
570 sensor_settings[NATURAL_IDX] = val;
571
572 return pb0100_set_autogain(gspca_dev, sensor_settings[AUTOGAIN_IDX]);
573}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
new file mode 100644
index 00000000000..757de246dc7
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
@@ -0,0 +1,152 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_PB0100_H_
31#define STV06XX_PB0100_H_
32
33#include "stv06xx_sensor.h"
34
35/* mode priv field flags */
36#define PB0100_CROP_TO_VGA 0x01
37#define PB0100_SUBSAMPLE 0x02
38
39/* I2C Registers */
40#define PB_IDENT 0x00 /* Chip Version */
41#define PB_RSTART 0x01 /* Row Window Start */
42#define PB_CSTART 0x02 /* Column Window Start */
43#define PB_RWSIZE 0x03 /* Row Window Size */
44#define PB_CWSIZE 0x04 /* Column Window Size */
45#define PB_CFILLIN 0x05 /* Column Fill-In */
46#define PB_VBL 0x06 /* Vertical Blank Count */
47#define PB_CONTROL 0x07 /* Control Mode */
48#define PB_FINTTIME 0x08 /* Integration Time/Frame Unit Count */
49#define PB_RINTTIME 0x09 /* Integration Time/Row Unit Count */
50#define PB_ROWSPEED 0x0a /* Row Speed Control */
51#define PB_ABORTFRAME 0x0b /* Abort Frame */
52#define PB_R12 0x0c /* Reserved */
53#define PB_RESET 0x0d /* Reset */
54#define PB_EXPGAIN 0x0e /* Exposure Gain Command */
55#define PB_R15 0x0f /* Expose0 */
56#define PB_R16 0x10 /* Expose1 */
57#define PB_R17 0x11 /* Expose2 */
58#define PB_R18 0x12 /* Low0_DAC */
59#define PB_R19 0x13 /* Low1_DAC */
60#define PB_R20 0x14 /* Low2_DAC */
61#define PB_R21 0x15 /* Threshold11 */
62#define PB_R22 0x16 /* Threshold0x */
63#define PB_UPDATEINT 0x17 /* Update Interval */
64#define PB_R24 0x18 /* High_DAC */
65#define PB_R25 0x19 /* Trans0H */
66#define PB_R26 0x1a /* Trans1L */
67#define PB_R27 0x1b /* Trans1H */
68#define PB_R28 0x1c /* Trans2L */
69#define PB_R29 0x1d /* Reserved */
70#define PB_R30 0x1e /* Reserved */
71#define PB_R31 0x1f /* Wait to Read */
72#define PB_PREADCTRL 0x20 /* Pixel Read Control Mode */
73#define PB_R33 0x21 /* IREF_VLN */
74#define PB_R34 0x22 /* IREF_VLP */
75#define PB_R35 0x23 /* IREF_VLN_INTEG */
76#define PB_R36 0x24 /* IREF_MASTER */
77#define PB_R37 0x25 /* IDACP */
78#define PB_R38 0x26 /* IDACN */
79#define PB_R39 0x27 /* DAC_Control_Reg */
80#define PB_R40 0x28 /* VCL */
81#define PB_R41 0x29 /* IREF_VLN_ADCIN */
82#define PB_R42 0x2a /* Reserved */
83#define PB_G1GAIN 0x2b /* Green 1 Gain */
84#define PB_BGAIN 0x2c /* Blue Gain */
85#define PB_RGAIN 0x2d /* Red Gain */
86#define PB_G2GAIN 0x2e /* Green 2 Gain */
87#define PB_R47 0x2f /* Dark Row Address */
88#define PB_R48 0x30 /* Dark Row Options */
89#define PB_R49 0x31 /* Reserved */
90#define PB_R50 0x32 /* Image Test Data */
91#define PB_ADCMAXGAIN 0x33 /* Maximum Gain */
92#define PB_ADCMINGAIN 0x34 /* Minimum Gain */
93#define PB_ADCGLOBALGAIN 0x35 /* Global Gain */
94#define PB_R54 0x36 /* Maximum Frame */
95#define PB_R55 0x37 /* Minimum Frame */
96#define PB_R56 0x38 /* Reserved */
97#define PB_VOFFSET 0x39 /* VOFFSET */
98#define PB_R58 0x3a /* Snap-Shot Sequence Trigger */
99#define PB_ADCGAINH 0x3b /* VREF_HI */
100#define PB_ADCGAINL 0x3c /* VREF_LO */
101#define PB_R61 0x3d /* Reserved */
102#define PB_R62 0x3e /* Reserved */
103#define PB_R63 0x3f /* Reserved */
104#define PB_R64 0x40 /* Red/Blue Gain */
105#define PB_R65 0x41 /* Green 2/Green 1 Gain */
106#define PB_R66 0x42 /* VREF_HI/LO */
107#define PB_R67 0x43 /* Integration Time/Row Unit Count */
108#define PB_R240 0xf0 /* ADC Test */
109#define PB_R241 0xf1 /* Chip Enable */
110#define PB_R242 0xf2 /* Reserved */
111
112static int pb0100_probe(struct sd *sd);
113static int pb0100_start(struct sd *sd);
114static int pb0100_init(struct sd *sd);
115static int pb0100_stop(struct sd *sd);
116static int pb0100_dump(struct sd *sd);
117static void pb0100_disconnect(struct sd *sd);
118
119/* V4L2 controls supported by the driver */
120static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
121static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val);
122static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
123static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
124static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
125static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
126static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
127static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
128static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val);
129static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val);
130static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val);
131static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val);
132static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val);
133static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val);
134
135const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
136 .name = "PB-0100",
137 .i2c_flush = 1,
138 .i2c_addr = 0xba,
139 .i2c_len = 2,
140
141 .min_packet_size = { 635, 847 },
142 .max_packet_size = { 847, 923 },
143
144 .init = pb0100_init,
145 .probe = pb0100_probe,
146 .start = pb0100_start,
147 .stop = pb0100_stop,
148 .dump = pb0100_dump,
149 .disconnect = pb0100_disconnect,
150};
151
152#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
new file mode 100644
index 00000000000..fb229d8ded5
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_SENSOR_H_
31#define STV06XX_SENSOR_H_
32
33#include "stv06xx.h"
34
35#define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020)
36
37extern const struct stv06xx_sensor stv06xx_sensor_vv6410;
38extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00;
39extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
40extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
41extern const struct stv06xx_sensor stv06xx_sensor_st6422;
42
43struct stv06xx_sensor {
44 /* Defines the name of a sensor */
45 char name[32];
46
47 /* Sensor i2c address */
48 u8 i2c_addr;
49
50 /* Flush value*/
51 u8 i2c_flush;
52
53 /* length of an i2c word */
54 u8 i2c_len;
55
56 /* Isoc packet size (per mode) */
57 int min_packet_size[4];
58 int max_packet_size[4];
59
60 /* Probes if the sensor is connected */
61 int (*probe)(struct sd *sd);
62
63 /* Performs a initialization sequence */
64 int (*init)(struct sd *sd);
65
66 /* Executed at device disconnect */
67 void (*disconnect)(struct sd *sd);
68
69 /* Reads a sensor register */
70 int (*read_sensor)(struct sd *sd, const u8 address,
71 u8 *i2c_data, const u8 len);
72
73 /* Writes to a sensor register */
74 int (*write_sensor)(struct sd *sd, const u8 address,
75 u8 *i2c_data, const u8 len);
76
77 /* Instructs the sensor to start streaming */
78 int (*start)(struct sd *sd);
79
80 /* Instructs the sensor to stop streaming */
81 int (*stop)(struct sd *sd);
82
83 /* Instructs the sensor to dump all its contents */
84 int (*dump)(struct sd *sd);
85};
86
87#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
new file mode 100644
index 00000000000..8a456de4970
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -0,0 +1,401 @@
1/*
2 * Support for the sensor part which is integrated (I think) into the
3 * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
4 * but instead direct bridge writes.
5 *
6 * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
7 *
8 * Strongly based on qc-usb-messenger, which is:
9 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
10 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
11 * Copyright (c) 2002, 2003 Tuukka Toivonen
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29#include "stv06xx_st6422.h"
30
31/* controls */
32enum e_ctrl {
33 BRIGHTNESS,
34 CONTRAST,
35 GAIN,
36 EXPOSURE,
37 NCTRLS /* number of controls */
38};
39
40/* sensor settings */
41struct st6422_settings {
42 struct gspca_ctrl ctrls[NCTRLS];
43};
44
45static struct v4l2_pix_format st6422_mode[] = {
46 /* Note we actually get 124 lines of data, of which we skip the 4st
47 4 as they are garbage */
48 {
49 162,
50 120,
51 V4L2_PIX_FMT_SGRBG8,
52 V4L2_FIELD_NONE,
53 .sizeimage = 162 * 120,
54 .bytesperline = 162,
55 .colorspace = V4L2_COLORSPACE_SRGB,
56 .priv = 1
57 },
58 /* Note we actually get 248 lines of data, of which we skip the 4st
59 4 as they are garbage, and we tell the app it only gets the
60 first 240 of the 244 lines it actually gets, so that it ignores
61 the last 4. */
62 {
63 324,
64 240,
65 V4L2_PIX_FMT_SGRBG8,
66 V4L2_FIELD_NONE,
67 .sizeimage = 324 * 244,
68 .bytesperline = 324,
69 .colorspace = V4L2_COLORSPACE_SRGB,
70 .priv = 0
71 },
72};
73
74/* V4L2 controls supported by the driver */
75static void st6422_set_brightness(struct gspca_dev *gspca_dev);
76static void st6422_set_contrast(struct gspca_dev *gspca_dev);
77static void st6422_set_gain(struct gspca_dev *gspca_dev);
78static void st6422_set_exposure(struct gspca_dev *gspca_dev);
79
80static const struct ctrl st6422_ctrl[NCTRLS] = {
81[BRIGHTNESS] = {
82 {
83 .id = V4L2_CID_BRIGHTNESS,
84 .type = V4L2_CTRL_TYPE_INTEGER,
85 .name = "Brightness",
86 .minimum = 0,
87 .maximum = 31,
88 .step = 1,
89 .default_value = 3
90 },
91 .set_control = st6422_set_brightness
92 },
93[CONTRAST] = {
94 {
95 .id = V4L2_CID_CONTRAST,
96 .type = V4L2_CTRL_TYPE_INTEGER,
97 .name = "Contrast",
98 .minimum = 0,
99 .maximum = 15,
100 .step = 1,
101 .default_value = 11
102 },
103 .set_control = st6422_set_contrast
104 },
105[GAIN] = {
106 {
107 .id = V4L2_CID_GAIN,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Gain",
110 .minimum = 0,
111 .maximum = 255,
112 .step = 1,
113 .default_value = 64
114 },
115 .set_control = st6422_set_gain
116 },
117[EXPOSURE] = {
118 {
119 .id = V4L2_CID_EXPOSURE,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .name = "Exposure",
122 .minimum = 0,
123#define EXPOSURE_MAX 1023
124 .maximum = EXPOSURE_MAX,
125 .step = 1,
126 .default_value = 256
127 },
128 .set_control = st6422_set_exposure
129 },
130};
131
132static int st6422_probe(struct sd *sd)
133{
134 struct st6422_settings *sensor_settings;
135
136 if (sd->bridge != BRIDGE_ST6422)
137 return -ENODEV;
138
139 info("st6422 sensor detected");
140
141 sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
142 if (!sensor_settings)
143 return -ENOMEM;
144
145 sd->gspca_dev.cam.cam_mode = st6422_mode;
146 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
147 sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
148 sd->desc.ctrls = st6422_ctrl;
149 sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
150 sd->sensor_priv = sensor_settings;
151
152 return 0;
153}
154
155static int st6422_init(struct sd *sd)
156{
157 int err = 0, i;
158
159 const u16 st6422_bridge_init[][2] = {
160 { STV_ISO_ENABLE, 0x00 }, /* disable capture */
161 { 0x1436, 0x00 },
162 { 0x1432, 0x03 }, /* 0x00-0x1F brightness */
163 { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */
164 { 0x0509, 0x38 }, /* R */
165 { 0x050a, 0x38 }, /* G */
166 { 0x050b, 0x38 }, /* B */
167 { 0x050c, 0x2a },
168 { 0x050d, 0x01 },
169
170
171 { 0x1431, 0x00 }, /* 0x00-0x07 ??? */
172 { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
173 { 0x1438, 0x18 }, /* 640x480 */
174/* 18 bayes */
175/* 10 compressed? */
176
177 { 0x1439, 0x00 },
178/* anti-noise? 0xa2 gives a perfect image */
179
180 { 0x143b, 0x05 },
181 { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */
182
183
184/* shutter time 0x0000-0x03FF */
185/* low value give good picures on moving objects (but requires much light) */
186/* high value gives good picures in darkness (but tends to be overexposed) */
187 { 0x143e, 0x01 },
188 { 0x143d, 0x00 },
189
190 { 0x1442, 0xe2 },
191/* write: 1x1x xxxx */
192/* read: 1x1x xxxx */
193/* bit 5 == button pressed and hold if 0 */
194/* write 0xe2,0xea */
195
196/* 0x144a */
197/* 0x00 init */
198/* bit 7 == button has been pressed, but not handled */
199
200/* interrupt */
201/* if(urb->iso_frame_desc[i].status == 0x80) { */
202/* if(urb->iso_frame_desc[i].status == 0x88) { */
203
204 { 0x1500, 0xd0 },
205 { 0x1500, 0xd0 },
206 { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
207
208 { 0x1501, 0xaf },
209/* high val-> light area gets darker */
210/* low val -> light area gets lighter */
211 { 0x1502, 0xc2 },
212/* high val-> light area gets darker */
213/* low val -> light area gets lighter */
214 { 0x1503, 0x45 },
215/* high val-> light area gets darker */
216/* low val -> light area gets lighter */
217 { 0x1505, 0x02 },
218/* 2 : 324x248 80352 bytes */
219/* 7 : 248x162 40176 bytes */
220/* c+f: 162*124 20088 bytes */
221
222 { 0x150e, 0x8e },
223 { 0x150f, 0x37 },
224 { 0x15c0, 0x00 },
225 { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
226
227
228 { 0x143f, 0x01 }, /* commit settings */
229
230 };
231
232 for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
233 err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
234 st6422_bridge_init[i][1]);
235 }
236
237 return err;
238}
239
240static void st6422_disconnect(struct sd *sd)
241{
242 sd->sensor = NULL;
243 kfree(sd->sensor_priv);
244}
245
246static int setbrightness(struct sd *sd)
247{
248 struct st6422_settings *sensor_settings = sd->sensor_priv;
249
250 /* val goes from 0 -> 31 */
251 return stv06xx_write_bridge(sd, 0x1432,
252 sensor_settings->ctrls[BRIGHTNESS].val);
253}
254
255static int setcontrast(struct sd *sd)
256{
257 struct st6422_settings *sensor_settings = sd->sensor_priv;
258
259 /* Val goes from 0 -> 15 */
260 return stv06xx_write_bridge(sd, 0x143a,
261 sensor_settings->ctrls[CONTRAST].val | 0xf0);
262}
263
264static int setgain(struct sd *sd)
265{
266 struct st6422_settings *sensor_settings = sd->sensor_priv;
267 u8 gain;
268 int err;
269
270 gain = sensor_settings->ctrls[GAIN].val;
271
272 /* Set red, green, blue, gain */
273 err = stv06xx_write_bridge(sd, 0x0509, gain);
274 if (err < 0)
275 return err;
276
277 err = stv06xx_write_bridge(sd, 0x050a, gain);
278 if (err < 0)
279 return err;
280
281 err = stv06xx_write_bridge(sd, 0x050b, gain);
282 if (err < 0)
283 return err;
284
285 /* 2 mystery writes */
286 err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
287 if (err < 0)
288 return err;
289
290 return stv06xx_write_bridge(sd, 0x050d, 0x01);
291}
292
293static int setexposure(struct sd *sd)
294{
295 struct st6422_settings *sensor_settings = sd->sensor_priv;
296 u16 expo;
297 int err;
298
299 expo = sensor_settings->ctrls[EXPOSURE].val;
300 err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
301 if (err < 0)
302 return err;
303
304 return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
305}
306
307static int st6422_start(struct sd *sd)
308{
309 int err;
310 struct cam *cam = &sd->gspca_dev.cam;
311
312 if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
313 err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
314 else
315 err = stv06xx_write_bridge(sd, 0x1505, 0x02);
316 if (err < 0)
317 return err;
318
319 err = setbrightness(sd);
320 if (err < 0)
321 return err;
322
323 err = setcontrast(sd);
324 if (err < 0)
325 return err;
326
327 err = setexposure(sd);
328 if (err < 0)
329 return err;
330
331 err = setgain(sd);
332 if (err < 0)
333 return err;
334
335 /* commit settings */
336 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
337 return (err < 0) ? err : 0;
338}
339
340static int st6422_stop(struct sd *sd)
341{
342 PDEBUG(D_STREAM, "Halting stream");
343
344 return 0;
345}
346
347static void st6422_set_brightness(struct gspca_dev *gspca_dev)
348{
349 int err;
350 struct sd *sd = (struct sd *) gspca_dev;
351
352 err = setbrightness(sd);
353
354 /* commit settings */
355 if (err >= 0)
356 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
357
358 gspca_dev->usb_err = err;
359}
360
361static void st6422_set_contrast(struct gspca_dev *gspca_dev)
362{
363 int err;
364 struct sd *sd = (struct sd *) gspca_dev;
365
366 err = setcontrast(sd);
367
368 /* commit settings */
369 if (err >= 0)
370 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
371
372 gspca_dev->usb_err = err;
373}
374
375static void st6422_set_gain(struct gspca_dev *gspca_dev)
376{
377 int err;
378 struct sd *sd = (struct sd *) gspca_dev;
379
380 err = setgain(sd);
381
382 /* commit settings */
383 if (err >= 0)
384 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
385
386 gspca_dev->usb_err = err;
387}
388
389static void st6422_set_exposure(struct gspca_dev *gspca_dev)
390{
391 int err;
392 struct sd *sd = (struct sd *) gspca_dev;
393
394 err = setexposure(sd);
395
396 /* commit settings */
397 if (err >= 0)
398 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
399
400 gspca_dev->usb_err = err;
401}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
new file mode 100644
index 00000000000..d7498e06432
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
@@ -0,0 +1,52 @@
1/*
2 * Support for the sensor part which is integrated (I think) into the
3 * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
4 * but instead direct bridge writes.
5 *
6 * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
7 *
8 * Strongly based on qc-usb-messenger, which is:
9 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
10 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
11 * Copyright (c) 2002, 2003 Tuukka Toivonen
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29#ifndef STV06XX_ST6422_H_
30#define STV06XX_ST6422_H_
31
32#include "stv06xx_sensor.h"
33
34static int st6422_probe(struct sd *sd);
35static int st6422_start(struct sd *sd);
36static int st6422_init(struct sd *sd);
37static int st6422_stop(struct sd *sd);
38static void st6422_disconnect(struct sd *sd);
39
40const struct stv06xx_sensor stv06xx_sensor_st6422 = {
41 .name = "ST6422",
42 /* No known way to lower framerate in case of less bandwidth */
43 .min_packet_size = { 300, 847 },
44 .max_packet_size = { 300, 847 },
45 .init = st6422_init,
46 .probe = st6422_probe,
47 .start = st6422_start,
48 .stop = st6422_stop,
49 .disconnect = st6422_disconnect,
50};
51
52#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
new file mode 100644
index 00000000000..f8398434c32
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
@@ -0,0 +1,392 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#include "stv06xx_vv6410.h"
31
32static struct v4l2_pix_format vv6410_mode[] = {
33 {
34 356,
35 292,
36 V4L2_PIX_FMT_SGRBG8,
37 V4L2_FIELD_NONE,
38 .sizeimage = 356 * 292,
39 .bytesperline = 356,
40 .colorspace = V4L2_COLORSPACE_SRGB,
41 .priv = 0
42 }
43};
44
45static const struct ctrl vv6410_ctrl[] = {
46#define HFLIP_IDX 0
47 {
48 {
49 .id = V4L2_CID_HFLIP,
50 .type = V4L2_CTRL_TYPE_BOOLEAN,
51 .name = "horizontal flip",
52 .minimum = 0,
53 .maximum = 1,
54 .step = 1,
55 .default_value = 0
56 },
57 .set = vv6410_set_hflip,
58 .get = vv6410_get_hflip
59 },
60#define VFLIP_IDX 1
61 {
62 {
63 .id = V4L2_CID_VFLIP,
64 .type = V4L2_CTRL_TYPE_BOOLEAN,
65 .name = "vertical flip",
66 .minimum = 0,
67 .maximum = 1,
68 .step = 1,
69 .default_value = 0
70 },
71 .set = vv6410_set_vflip,
72 .get = vv6410_get_vflip
73 },
74#define GAIN_IDX 2
75 {
76 {
77 .id = V4L2_CID_GAIN,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "analog gain",
80 .minimum = 0,
81 .maximum = 15,
82 .step = 1,
83 .default_value = 10
84 },
85 .set = vv6410_set_analog_gain,
86 .get = vv6410_get_analog_gain
87 },
88#define EXPOSURE_IDX 3
89 {
90 {
91 .id = V4L2_CID_EXPOSURE,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "exposure",
94 .minimum = 0,
95 .maximum = 32768,
96 .step = 1,
97 .default_value = 20000
98 },
99 .set = vv6410_set_exposure,
100 .get = vv6410_get_exposure
101 }
102 };
103
104static int vv6410_probe(struct sd *sd)
105{
106 u16 data;
107 int err, i;
108 s32 *sensor_settings;
109
110 err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
111 if (err < 0)
112 return -ENODEV;
113
114 if (data == 0x19) {
115 info("vv6410 sensor detected");
116
117 sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32),
118 GFP_KERNEL);
119 if (!sensor_settings)
120 return -ENOMEM;
121
122 sd->gspca_dev.cam.cam_mode = vv6410_mode;
123 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
124 sd->desc.ctrls = vv6410_ctrl;
125 sd->desc.nctrls = ARRAY_SIZE(vv6410_ctrl);
126
127 for (i = 0; i < sd->desc.nctrls; i++)
128 sensor_settings[i] = vv6410_ctrl[i].qctrl.default_value;
129 sd->sensor_priv = sensor_settings;
130 return 0;
131 }
132 return -ENODEV;
133}
134
135static int vv6410_init(struct sd *sd)
136{
137 int err = 0, i;
138 s32 *sensor_settings = sd->sensor_priv;
139
140 for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
141 /* if NULL then len contains single value */
142 if (stv_bridge_init[i].data == NULL) {
143 err = stv06xx_write_bridge(sd,
144 stv_bridge_init[i].start,
145 stv_bridge_init[i].len);
146 } else {
147 int j;
148 for (j = 0; j < stv_bridge_init[i].len; j++)
149 err = stv06xx_write_bridge(sd,
150 stv_bridge_init[i].start + j,
151 stv_bridge_init[i].data[j]);
152 }
153 }
154
155 if (err < 0)
156 return err;
157
158 err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
159 ARRAY_SIZE(vv6410_sensor_init));
160 if (err < 0)
161 return err;
162
163 err = vv6410_set_exposure(&sd->gspca_dev,
164 sensor_settings[EXPOSURE_IDX]);
165 if (err < 0)
166 return err;
167
168 err = vv6410_set_analog_gain(&sd->gspca_dev,
169 sensor_settings[GAIN_IDX]);
170
171 return (err < 0) ? err : 0;
172}
173
174static void vv6410_disconnect(struct sd *sd)
175{
176 sd->sensor = NULL;
177 kfree(sd->sensor_priv);
178}
179
180static int vv6410_start(struct sd *sd)
181{
182 int err;
183 struct cam *cam = &sd->gspca_dev.cam;
184 u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
185
186 if (priv & VV6410_CROP_TO_QVGA) {
187 PDEBUG(D_CONF, "Cropping to QVGA");
188 stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1);
189 stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1);
190 } else {
191 stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1);
192 stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1);
193 }
194
195 if (priv & VV6410_SUBSAMPLE) {
196 PDEBUG(D_CONF, "Enabling subsampling");
197 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
198 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
199
200 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
201 } else {
202 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
203 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
204
205 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
206 }
207
208 /* Turn on LED */
209 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
210 if (err < 0)
211 return err;
212
213 err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
214 if (err < 0)
215 return err;
216
217 PDEBUG(D_STREAM, "Starting stream");
218
219 return 0;
220}
221
222static int vv6410_stop(struct sd *sd)
223{
224 int err;
225
226 /* Turn off LED */
227 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
228 if (err < 0)
229 return err;
230
231 err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
232 if (err < 0)
233 return err;
234
235 PDEBUG(D_STREAM, "Halting stream");
236
237 return (err < 0) ? err : 0;
238}
239
240static int vv6410_dump(struct sd *sd)
241{
242 u8 i;
243 int err = 0;
244
245 info("Dumping all vv6410 sensor registers");
246 for (i = 0; i < 0xff && !err; i++) {
247 u16 data;
248 err = stv06xx_read_sensor(sd, i, &data);
249 info("Register 0x%x contained 0x%x", i, data);
250 }
251 return (err < 0) ? err : 0;
252}
253
254static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
255{
256 struct sd *sd = (struct sd *) gspca_dev;
257 s32 *sensor_settings = sd->sensor_priv;
258
259 *val = sensor_settings[HFLIP_IDX];
260 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
261
262 return 0;
263}
264
265static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
266{
267 int err;
268 u16 i2c_data;
269 struct sd *sd = (struct sd *) gspca_dev;
270 s32 *sensor_settings = sd->sensor_priv;
271
272 sensor_settings[HFLIP_IDX] = val;
273 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
274 if (err < 0)
275 return err;
276
277 if (val)
278 i2c_data |= VV6410_HFLIP;
279 else
280 i2c_data &= ~VV6410_HFLIP;
281
282 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
283 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
284
285 return (err < 0) ? err : 0;
286}
287
288static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
289{
290 struct sd *sd = (struct sd *) gspca_dev;
291 s32 *sensor_settings = sd->sensor_priv;
292
293 *val = sensor_settings[VFLIP_IDX];
294 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
295
296 return 0;
297}
298
299static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
300{
301 int err;
302 u16 i2c_data;
303 struct sd *sd = (struct sd *) gspca_dev;
304 s32 *sensor_settings = sd->sensor_priv;
305
306 sensor_settings[VFLIP_IDX] = val;
307 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
308 if (err < 0)
309 return err;
310
311 if (val)
312 i2c_data |= VV6410_VFLIP;
313 else
314 i2c_data &= ~VV6410_VFLIP;
315
316 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
317 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
318
319 return (err < 0) ? err : 0;
320}
321
322static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val)
323{
324 struct sd *sd = (struct sd *) gspca_dev;
325 s32 *sensor_settings = sd->sensor_priv;
326
327 *val = sensor_settings[GAIN_IDX];
328
329 PDEBUG(D_V4L2, "Read analog gain %d", *val);
330
331 return 0;
332}
333
334static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
335{
336 int err;
337 struct sd *sd = (struct sd *) gspca_dev;
338 s32 *sensor_settings = sd->sensor_priv;
339
340 sensor_settings[GAIN_IDX] = val;
341 PDEBUG(D_V4L2, "Set analog gain to %d", val);
342 err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
343
344 return (err < 0) ? err : 0;
345}
346
347static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
348{
349 struct sd *sd = (struct sd *) gspca_dev;
350 s32 *sensor_settings = sd->sensor_priv;
351
352 *val = sensor_settings[EXPOSURE_IDX];
353
354 PDEBUG(D_V4L2, "Read exposure %d", *val);
355
356 return 0;
357}
358
359static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
360{
361 int err;
362 struct sd *sd = (struct sd *) gspca_dev;
363 s32 *sensor_settings = sd->sensor_priv;
364 unsigned int fine, coarse;
365
366 sensor_settings[EXPOSURE_IDX] = val;
367
368 val = (val * val >> 14) + val / 4;
369
370 fine = val % VV6410_CIF_LINELENGTH;
371 coarse = min(512, val / VV6410_CIF_LINELENGTH);
372
373 PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
374 coarse, fine);
375
376 err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
377 if (err < 0)
378 goto out;
379
380 err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
381 if (err < 0)
382 goto out;
383
384 err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
385 if (err < 0)
386 goto out;
387
388 err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
389
390out:
391 return err;
392}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
new file mode 100644
index 00000000000..7fe3587f5f7
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -0,0 +1,259 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_VV6410_H_
31#define STV06XX_VV6410_H_
32
33#include "stv06xx_sensor.h"
34
35#define VV6410_COLS 416
36#define VV6410_ROWS 320
37
38/* Status registers */
39/* Chip identification number including revision indicator */
40#define VV6410_DEVICEH 0x00
41#define VV6410_DEVICEL 0x01
42
43/* User can determine whether timed I2C data
44 has been consumed by interrogating flag states */
45#define VV6410_STATUS0 0x02
46
47/* Current line counter value */
48#define VV6410_LINECOUNTH 0x03
49#define VV6410_LINECOUNTL 0x04
50
51/* End x coordinate of image size */
52#define VV6410_XENDH 0x05
53#define VV6410_XENDL 0x06
54
55/* End y coordinate of image size */
56#define VV6410_YENDH 0x07
57#define VV6410_YENDL 0x08
58
59/* This is the average pixel value returned from the
60 dark line offset cancellation algorithm */
61#define VV6410_DARKAVGH 0x09
62#define VV6410_DARKAVGL 0x0a
63
64/* This is the average pixel value returned from the
65 black line offset cancellation algorithm */
66#define VV6410_BLACKAVGH 0x0b
67#define VV6410_BLACKAVGL 0x0c
68
69/* Flags to indicate whether the x or y image coordinates have been clipped */
70#define VV6410_STATUS1 0x0d
71
72/* Setup registers */
73
74/* Low-power/sleep modes & video timing */
75#define VV6410_SETUP0 0x10
76
77/* Various parameters */
78#define VV6410_SETUP1 0x11
79
80/* Contains pixel counter reset value used by external sync */
81#define VV6410_SYNCVALUE 0x12
82
83/* Frame grabbing modes (FST, LST and QCK) */
84#define VV6410_FGMODES 0x14
85
86/* FST and QCK mapping modes. */
87#define VV6410_PINMAPPING 0x15
88
89/* Data resolution */
90#define VV6410_DATAFORMAT 0x16
91
92/* Output coding formats */
93#define VV6410_OPFORMAT 0x17
94
95/* Various mode select bits */
96#define VV6410_MODESELECT 0x18
97
98/* Exposure registers */
99/* Fine exposure. */
100#define VV6410_FINEH 0x20
101#define VV6410_FINEL 0x21
102
103/* Coarse exposure */
104#define VV6410_COARSEH 0x22
105#define VV6410_COARSEL 0x23
106
107/* Analog gain setting */
108#define VV6410_ANALOGGAIN 0x24
109
110/* Clock division */
111#define VV6410_CLKDIV 0x25
112
113/* Dark line offset cancellation value */
114#define VV6410_DARKOFFSETH 0x2c
115#define VV6410_DARKOFFSETL 0x2d
116
117/* Dark line offset cancellation enable */
118#define VV6410_DARKOFFSETSETUP 0x2e
119
120/* Video timing registers */
121/* Line Length (Pixel Clocks) */
122#define VV6410_LINELENGTHH 0x52
123#define VV6410_LINELENGTHL 0x53
124
125/* X-co-ordinate of top left corner of region of interest (x-offset) */
126#define VV6410_XOFFSETH 0x57
127#define VV6410_XOFFSETL 0x58
128
129/* Y-coordinate of top left corner of region of interest (y-offset) */
130#define VV6410_YOFFSETH 0x59
131#define VV6410_YOFFSETL 0x5a
132
133/* Field length (Lines) */
134#define VV6410_FIELDLENGTHH 0x61
135#define VV6410_FIELDLENGTHL 0x62
136
137/* System registers */
138/* Black offset cancellation default value */
139#define VV6410_BLACKOFFSETH 0x70
140#define VV6410_BLACKOFFSETL 0x71
141
142/* Black offset cancellation setup */
143#define VV6410_BLACKOFFSETSETUP 0x72
144
145/* Analog Control Register 0 */
146#define VV6410_CR0 0x75
147
148/* Analog Control Register 1 */
149#define VV6410_CR1 0x76
150
151/* ADC Setup Register */
152#define VV6410_AS0 0x77
153
154/* Analog Test Register */
155#define VV6410_AT0 0x78
156
157/* Audio Amplifier Setup Register */
158#define VV6410_AT1 0x79
159
160#define VV6410_HFLIP (1 << 3)
161#define VV6410_VFLIP (1 << 4)
162
163#define VV6410_LOW_POWER_MODE (1 << 0)
164#define VV6410_SOFT_RESET (1 << 2)
165#define VV6410_PAL_25_FPS (0 << 3)
166
167#define VV6410_CLK_DIV_2 (1 << 1)
168
169#define VV6410_FINE_EXPOSURE 320
170#define VV6410_COARSE_EXPOSURE 192
171#define VV6410_DEFAULT_GAIN 5
172
173#define VV6410_SUBSAMPLE 0x01
174#define VV6410_CROP_TO_QVGA 0x02
175
176#define VV6410_CIF_LINELENGTH 415
177
178static int vv6410_probe(struct sd *sd);
179static int vv6410_start(struct sd *sd);
180static int vv6410_init(struct sd *sd);
181static int vv6410_stop(struct sd *sd);
182static int vv6410_dump(struct sd *sd);
183static void vv6410_disconnect(struct sd *sd);
184
185/* V4L2 controls supported by the driver */
186static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
187static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
188static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
189static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
190static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val);
191static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
192static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
193static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
194
195const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
196 .name = "ST VV6410",
197 .i2c_flush = 5,
198 .i2c_addr = 0x20,
199 .i2c_len = 1,
200 /* FIXME (see if we can lower packet_size-s, needs testing, and also
201 adjusting framerate when the bandwidth gets lower) */
202 .min_packet_size = { 1023 },
203 .max_packet_size = { 1023 },
204 .init = vv6410_init,
205 .probe = vv6410_probe,
206 .start = vv6410_start,
207 .stop = vv6410_stop,
208 .dump = vv6410_dump,
209 .disconnect = vv6410_disconnect,
210};
211
212/* If NULL, only single value to write, stored in len */
213struct stv_init {
214 const u8 *data;
215 u16 start;
216 u8 len;
217};
218
219static const u8 x1500[] = { /* 0x1500 - 0x150f */
220 0x0b, 0xa7, 0xb7, 0x00, 0x00
221};
222
223static const u8 x1536[] = { /* 0x1536 - 0x153b */
224 0x02, 0x00, 0x60, 0x01, 0x20, 0x01
225};
226
227static const struct stv_init stv_bridge_init[] = {
228 /* This reg is written twice. Some kind of reset? */
229 {NULL, 0x1620, 0x80},
230 {NULL, 0x1620, 0x00},
231 {NULL, 0x1443, 0x00},
232 {NULL, 0x1423, 0x04},
233 {x1500, 0x1500, ARRAY_SIZE(x1500)},
234 {x1536, 0x1536, ARRAY_SIZE(x1536)},
235};
236
237static const u8 vv6410_sensor_init[][2] = {
238 /* Setup registers */
239 {VV6410_SETUP0, VV6410_SOFT_RESET},
240 {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
241 /* Use shuffled read-out mode */
242 {VV6410_SETUP1, BIT(6)},
243 /* All modes to 1 */
244 {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
245 {VV6410_PINMAPPING, 0x00},
246 /* Pre-clock generator divide off */
247 {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
248
249 {VV6410_CLKDIV, VV6410_CLK_DIV_2},
250
251 /* System registers */
252 /* Enable voltage doubler */
253 {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
254 {VV6410_AT0, 0x00},
255 /* Power up audio, differential */
256 {VV6410_AT1, BIT(4)|BIT(0)},
257};
258
259#endif