• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/media/video/gspca/stv06xx/
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 as bit 0 toggles r/w */
167		reg += 2;
168	}
169
170	return stv06xx_write_sensor_bytes(sd, regs, len);
171}
172
173static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
174{
175	struct hdcs *hdcs = sd->sensor_priv;
176	u8 val;
177	int ret;
178
179	if (hdcs->state == state)
180		return 0;
181
182	/* we need to go idle before running or sleeping */
183	if (hdcs->state != HDCS_STATE_IDLE) {
184		ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
185		if (ret)
186			return ret;
187	}
188
189	hdcs->state = HDCS_STATE_IDLE;
190
191	if (state == HDCS_STATE_IDLE)
192		return 0;
193
194	switch (state) {
195	case HDCS_STATE_SLEEP:
196		val = HDCS_SLEEP_MODE;
197		break;
198
199	case HDCS_STATE_RUN:
200		val = HDCS_RUN_ENABLE;
201		break;
202
203	default:
204		return -EINVAL;
205	}
206
207	ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
208
209	/* Update the state if the write succeeded */
210	if (!ret)
211		hdcs->state = state;
212
213	return ret;
214}
215
216static int hdcs_reset(struct sd *sd)
217{
218	struct hdcs *hdcs = sd->sensor_priv;
219	int err;
220
221	err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
222	if (err < 0)
223		return err;
224
225	err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
226	if (err < 0)
227		hdcs->state = HDCS_STATE_IDLE;
228
229	return err;
230}
231
232static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
233{
234	struct sd *sd = (struct sd *) gspca_dev;
235	struct hdcs *hdcs = sd->sensor_priv;
236
237	*val = hdcs->exp_cache;
238
239	return 0;
240}
241
242static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
243{
244	struct sd *sd = (struct sd *) gspca_dev;
245	struct hdcs *hdcs = sd->sensor_priv;
246	int rowexp, srowexp;
247	int max_srowexp;
248	/* Column time period */
249	int ct;
250	/* Column processing period */
251	int cp;
252	/* Row processing period */
253	int rp;
254	/* Minimum number of column timing periods
255	   within the column processing period */
256	int mnct;
257	int cycles, err;
258	u8 exp[14];
259
260	val &= 0xff;
261	hdcs->exp_cache = val;
262
263	cycles = val * HDCS_CLK_FREQ_MHZ * 257;
264
265	ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
266	cp = hdcs->exp.cto + (hdcs->w * ct / 2);
267
268	/* the cycles one row takes */
269	rp = hdcs->exp.rs + cp;
270
271	rowexp = cycles / rp;
272
273	/* the remaining cycles */
274	cycles -= rowexp * rp;
275
276	/* calculate sub-row exposure */
277	if (IS_1020(sd)) {
278		/* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
279		srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;
280
281		mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
282		max_srowexp = hdcs->w - mnct;
283	} else {
284		/* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
285		srowexp = cp - hdcs->exp.er - 6 - cycles;
286
287		mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
288		max_srowexp = cp - mnct * ct - 1;
289	}
290
291	if (srowexp < 0)
292		srowexp = 0;
293	else if (srowexp > max_srowexp)
294		srowexp = max_srowexp;
295
296	if (IS_1020(sd)) {
297		exp[0] = HDCS20_CONTROL;
298		exp[1] = 0x00;		/* Stop streaming */
299		exp[2] = HDCS_ROWEXPL;
300		exp[3] = rowexp & 0xff;
301		exp[4] = HDCS_ROWEXPH;
302		exp[5] = rowexp >> 8;
303		exp[6] = HDCS20_SROWEXP;
304		exp[7] = (srowexp >> 2) & 0xff;
305		exp[8] = HDCS20_ERROR;
306		exp[9] = 0x10;		/* Clear exposure error flag*/
307		exp[10] = HDCS20_CONTROL;
308		exp[11] = 0x04;		/* Restart streaming */
309		err = stv06xx_write_sensor_bytes(sd, exp, 6);
310	} else {
311		exp[0] = HDCS00_CONTROL;
312		exp[1] = 0x00;         /* Stop streaming */
313		exp[2] = HDCS_ROWEXPL;
314		exp[3] = rowexp & 0xff;
315		exp[4] = HDCS_ROWEXPH;
316		exp[5] = rowexp >> 8;
317		exp[6] = HDCS00_SROWEXPL;
318		exp[7] = srowexp & 0xff;
319		exp[8] = HDCS00_SROWEXPH;
320		exp[9] = srowexp >> 8;
321		exp[10] = HDCS_STATUS;
322		exp[11] = 0x10;         /* Clear exposure error flag*/
323		exp[12] = HDCS00_CONTROL;
324		exp[13] = 0x04;         /* Restart streaming */
325		err = stv06xx_write_sensor_bytes(sd, exp, 7);
326		if (err < 0)
327			return err;
328	}
329	PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
330	       val, rowexp, srowexp);
331	return err;
332}
333
334static int hdcs_set_gains(struct sd *sd, u8 g)
335{
336	struct hdcs *hdcs = sd->sensor_priv;
337	int err;
338	u8 gains[4];
339
340	hdcs->gain_cache = g;
341
342	/* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
343	if (g > 127)
344		g = 0x80 | (g / 2);
345
346	gains[0] = g;
347	gains[1] = g;
348	gains[2] = g;
349	gains[3] = g;
350
351	err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
352		return err;
353}
354
355static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
356{
357	struct sd *sd = (struct sd *) gspca_dev;
358	struct hdcs *hdcs = sd->sensor_priv;
359
360	*val = hdcs->gain_cache;
361
362	return 0;
363}
364
365static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
366{
367	PDEBUG(D_V4L2, "Writing gain %d", val);
368	return hdcs_set_gains((struct sd *) gspca_dev,
369			       val & 0xff);
370}
371
372static int hdcs_set_size(struct sd *sd,
373		unsigned int width, unsigned int height)
374{
375	struct hdcs *hdcs = sd->sensor_priv;
376	u8 win[4];
377	unsigned int x, y;
378	int err;
379
380	/* must be multiple of 4 */
381	width = (width + 3) & ~0x3;
382	height = (height + 3) & ~0x3;
383
384	if (width > hdcs->array.width)
385		width = hdcs->array.width;
386
387	if (IS_1020(sd)) {
388		/* the borders are also invalid */
389		if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
390				  > hdcs->array.height)
391			height = hdcs->array.height - 2 * hdcs->array.border -
392				HDCS_1020_BOTTOM_Y_SKIP;
393
394		y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
395				+ hdcs->array.top;
396	} else {
397		if (height > hdcs->array.height)
398			height = hdcs->array.height;
399
400		y = hdcs->array.top + (hdcs->array.height - height) / 2;
401	}
402
403	x = hdcs->array.left + (hdcs->array.width - width) / 2;
404
405	win[0] = y / 4;
406	win[1] = x / 4;
407	win[2] = (y + height) / 4 - 1;
408	win[3] = (x + width) / 4 - 1;
409
410	err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
411	if (err < 0)
412		return err;
413
414	/* Update the current width and height */
415	hdcs->w = width;
416	hdcs->h = height;
417	return err;
418}
419
420static int hdcs_probe_1x00(struct sd *sd)
421{
422	struct hdcs *hdcs;
423	u16 sensor;
424	int ret;
425
426	ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
427	if (ret < 0 || sensor != 0x08)
428		return -ENODEV;
429
430	info("HDCS-1000/1100 sensor detected");
431
432	sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
433	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
434	sd->desc.ctrls = hdcs1x00_ctrl;
435	sd->desc.nctrls = ARRAY_SIZE(hdcs1x00_ctrl);
436
437	hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
438	if (!hdcs)
439		return -ENOMEM;
440
441	hdcs->array.left = 8;
442	hdcs->array.top = 8;
443	hdcs->array.width = HDCS_1X00_DEF_WIDTH;
444	hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
445	hdcs->array.border = 4;
446
447	hdcs->exp.cto = 4;
448	hdcs->exp.cpo = 2;
449	hdcs->exp.rs = 186;
450	hdcs->exp.er = 100;
451
452	/*
453	 * Frame rate on HDCS-1000 with STV600 depends on PSMP:
454	 *  4 = doesn't work at all
455	 *  5 = 7.8 fps,
456	 *  6 = 6.9 fps,
457	 *  8 = 6.3 fps,
458	 * 10 = 5.5 fps,
459	 * 15 = 4.4 fps,
460	 * 31 = 2.8 fps
461	 *
462	 * Frame rate on HDCS-1000 with STV602 depends on PSMP:
463	 * 15 = doesn't work at all
464	 * 18 = doesn't work at all
465	 * 19 = 7.3 fps
466	 * 20 = 7.4 fps
467	 * 21 = 7.4 fps
468	 * 22 = 7.4 fps
469	 * 24 = 6.3 fps
470	 * 30 = 5.4 fps
471	 */
472	hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
473
474	sd->sensor_priv = hdcs;
475
476	return 0;
477}
478
479static int hdcs_probe_1020(struct sd *sd)
480{
481	struct hdcs *hdcs;
482	u16 sensor;
483	int ret;
484
485	ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
486	if (ret < 0 || sensor != 0x10)
487		return -ENODEV;
488
489	info("HDCS-1020 sensor detected");
490
491	sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
492	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
493	sd->desc.ctrls = hdcs1020_ctrl;
494	sd->desc.nctrls = ARRAY_SIZE(hdcs1020_ctrl);
495
496	hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
497	if (!hdcs)
498		return -ENOMEM;
499
500	/*
501	 * From Andrey's test image: looks like HDCS-1020 upper-left
502	 * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
503	 * visible pixel at 375,299 (x maybe even larger?)
504	 */
505	hdcs->array.left = 24;
506	hdcs->array.top  = 4;
507	hdcs->array.width = HDCS_1020_DEF_WIDTH;
508	hdcs->array.height = 304;
509	hdcs->array.border = 4;
510
511	hdcs->psmp = 6;
512
513	hdcs->exp.cto = 3;
514	hdcs->exp.cpo = 3;
515	hdcs->exp.rs = 155;
516	hdcs->exp.er = 96;
517
518	sd->sensor_priv = hdcs;
519
520	return 0;
521}
522
523static int hdcs_start(struct sd *sd)
524{
525	PDEBUG(D_STREAM, "Starting stream");
526
527	return hdcs_set_state(sd, HDCS_STATE_RUN);
528}
529
530static int hdcs_stop(struct sd *sd)
531{
532	PDEBUG(D_STREAM, "Halting stream");
533
534	return hdcs_set_state(sd, HDCS_STATE_SLEEP);
535}
536
537static void hdcs_disconnect(struct sd *sd)
538{
539	PDEBUG(D_PROBE, "Disconnecting the sensor");
540	kfree(sd->sensor_priv);
541}
542
543static int hdcs_init(struct sd *sd)
544{
545	struct hdcs *hdcs = sd->sensor_priv;
546	int i, err = 0;
547
548	/* Set the STV0602AA in STV0600 emulation mode */
549	if (sd->bridge == BRIDGE_STV602)
550		stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
551
552	/* Execute the bridge init */
553	for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
554		err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
555					   stv_bridge_init[i][1]);
556	}
557	if (err < 0)
558		return err;
559
560	/* sensor soft reset */
561	hdcs_reset(sd);
562
563	/* Execute the sensor init */
564	for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
565		err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
566					     stv_sensor_init[i][1]);
567	}
568	if (err < 0)
569		return err;
570
571	/* Enable continous frame capture, bit 2: stop when frame complete */
572	err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
573	if (err < 0)
574		return err;
575
576	/* Set PGA sample duration
577	(was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
578	if (IS_1020(sd))
579		err = stv06xx_write_sensor(sd, HDCS_TCTRL,
580				(HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
581	else
582		err = stv06xx_write_sensor(sd, HDCS_TCTRL,
583				(HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
584	if (err < 0)
585		return err;
586
587	err = hdcs_set_gains(sd, HDCS_DEFAULT_GAIN);
588	if (err < 0)
589		return err;
590
591	err = hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
592	if (err < 0)
593		return err;
594
595	err = hdcs_set_exposure(&sd->gspca_dev, HDCS_DEFAULT_EXPOSURE);
596	return err;
597}
598
599static int hdcs_dump(struct sd *sd)
600{
601	u16 reg, val;
602
603	info("Dumping sensor registers:");
604
605	for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
606		stv06xx_read_sensor(sd, reg, &val);
607		info("reg 0x%02x = 0x%02x", reg, val);
608	}
609	return 0;
610}
611