pac7302.c revision 1408b8472910e894b290205b4baed5b14b8f45af
1/*
2 *		Pixart PAC7302 library
3 *		Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * Separated from Pixart PAC7311 library by M�rton N�meth <nm127@freemail.hu>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/* Some documentation about various registers as determined by trial and error.
25   When the register addresses differ between the 7202 and the 7311 the 2
26   different addresses are written as 7302addr/7311addr, when one of the 2
27   addresses is a - sign that register description is not valid for the
28   matching IC.
29
30   Register page 1:
31
32   Address	Description
33   -/0x08	Unknown compressor related, must always be 8 except when not
34		in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
35   -/0x1b	Auto white balance related, bit 0 is AWB enable (inverted)
36		bits 345 seem to toggle per color gains on/off (inverted)
37   0x78		Global control, bit 6 controls the LED (inverted)
38   -/0x80	JPEG compression ratio ? Best not touched
39
40   Register page 3/4:
41
42   Address	Description
43   0x02		Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
44		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
45   -/0x0f	Master gain 1-245, low value = high gain
46   0x10/-	Master gain 0-31
47   -/0x10	Another gain 0-15, limited influence (1-2x gain I guess)
48   0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
49   -/0x27	Seems to toggle various gains on / off, Setting bit 7 seems to
50		completely disable the analog amplification block. Set to 0x68
51		for max gain, 0x14 for minimal gain.
52*/
53
54#define MODULE_NAME "pac7302"
55
56#include "gspca.h"
57
58MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
59MODULE_DESCRIPTION("Pixart PAC7302");
60MODULE_LICENSE("GPL");
61
62/* specific webcam descriptor for pac7302 */
63struct sd {
64	struct gspca_dev gspca_dev;		/* !! must be the first item */
65
66	unsigned char brightness;
67	unsigned char contrast;
68	unsigned char colors;
69	unsigned char gain;
70	unsigned char exposure;
71	unsigned char autogain;
72	__u8 hflip;
73	__u8 vflip;
74
75	u8 sof_read;
76	u8 autogain_ignore_frames;
77
78	atomic_t avg_lum;
79};
80
81/* V4L2 controls supported by the driver */
82static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
90static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
92static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
93static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
94static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
95static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
96static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
97static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
98
99static struct ctrl sd_ctrls[] = {
100/* This control is pac7302 only */
101	{
102	    {
103		.id      = V4L2_CID_BRIGHTNESS,
104		.type    = V4L2_CTRL_TYPE_INTEGER,
105		.name    = "Brightness",
106		.minimum = 0,
107#define BRIGHTNESS_MAX 0x20
108		.maximum = BRIGHTNESS_MAX,
109		.step    = 1,
110#define BRIGHTNESS_DEF 0x10
111		.default_value = BRIGHTNESS_DEF,
112	    },
113	    .set = sd_setbrightness,
114	    .get = sd_getbrightness,
115	},
116/* This control is for both the 7302 and the 7311 */
117	{
118	    {
119		.id      = V4L2_CID_CONTRAST,
120		.type    = V4L2_CTRL_TYPE_INTEGER,
121		.name    = "Contrast",
122		.minimum = 0,
123#define CONTRAST_MAX 255
124		.maximum = CONTRAST_MAX,
125		.step    = 1,
126#define CONTRAST_DEF 127
127		.default_value = CONTRAST_DEF,
128	    },
129	    .set = sd_setcontrast,
130	    .get = sd_getcontrast,
131	},
132/* This control is pac7302 only */
133	{
134	    {
135		.id      = V4L2_CID_SATURATION,
136		.type    = V4L2_CTRL_TYPE_INTEGER,
137		.name    = "Saturation",
138		.minimum = 0,
139#define COLOR_MAX 255
140		.maximum = COLOR_MAX,
141		.step    = 1,
142#define COLOR_DEF 127
143		.default_value = COLOR_DEF,
144	    },
145	    .set = sd_setcolors,
146	    .get = sd_getcolors,
147	},
148/* All controls below are for both the 7302 and the 7311 */
149	{
150	    {
151		.id      = V4L2_CID_GAIN,
152		.type    = V4L2_CTRL_TYPE_INTEGER,
153		.name    = "Gain",
154		.minimum = 0,
155#define GAIN_MAX 255
156		.maximum = GAIN_MAX,
157		.step    = 1,
158#define GAIN_DEF 127
159#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
160		.default_value = GAIN_DEF,
161	    },
162	    .set = sd_setgain,
163	    .get = sd_getgain,
164	},
165	{
166	    {
167		.id      = V4L2_CID_EXPOSURE,
168		.type    = V4L2_CTRL_TYPE_INTEGER,
169		.name    = "Exposure",
170		.minimum = 0,
171#define EXPOSURE_MAX 255
172		.maximum = EXPOSURE_MAX,
173		.step    = 1,
174#define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
175#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
176		.default_value = EXPOSURE_DEF,
177	    },
178	    .set = sd_setexposure,
179	    .get = sd_getexposure,
180	},
181	{
182	    {
183		.id      = V4L2_CID_AUTOGAIN,
184		.type    = V4L2_CTRL_TYPE_BOOLEAN,
185		.name    = "Auto Gain",
186		.minimum = 0,
187		.maximum = 1,
188		.step    = 1,
189#define AUTOGAIN_DEF 1
190		.default_value = AUTOGAIN_DEF,
191	    },
192	    .set = sd_setautogain,
193	    .get = sd_getautogain,
194	},
195	{
196	    {
197		.id      = V4L2_CID_HFLIP,
198		.type    = V4L2_CTRL_TYPE_BOOLEAN,
199		.name    = "Mirror",
200		.minimum = 0,
201		.maximum = 1,
202		.step    = 1,
203#define HFLIP_DEF 0
204		.default_value = HFLIP_DEF,
205	    },
206	    .set = sd_sethflip,
207	    .get = sd_gethflip,
208	},
209	{
210	    {
211		.id      = V4L2_CID_VFLIP,
212		.type    = V4L2_CTRL_TYPE_BOOLEAN,
213		.name    = "Vflip",
214		.minimum = 0,
215		.maximum = 1,
216		.step    = 1,
217#define VFLIP_DEF 0
218		.default_value = VFLIP_DEF,
219	    },
220	    .set = sd_setvflip,
221	    .get = sd_getvflip,
222	},
223};
224
225static const struct v4l2_pix_format vga_mode[] = {
226	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
227		.bytesperline = 640,
228		.sizeimage = 640 * 480 * 3 / 8 + 590,
229		.colorspace = V4L2_COLORSPACE_JPEG,
230		.priv = 0},
231};
232
233#define LOAD_PAGE3		255
234#define LOAD_PAGE4		254
235#define END_OF_SEQUENCE		0
236
237/* pac 7302 */
238static const __u8 init_7302[] = {
239/*	index,value */
240	0xff, 0x01,		/* page 1 */
241	0x78, 0x00,		/* deactivate */
242	0xff, 0x01,
243	0x78, 0x40,		/* led off */
244};
245static const __u8 start_7302[] = {
246/*	index, len, [value]* */
247	0xff, 1,	0x00,		/* page 0 */
248	0x00, 12,	0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
249			0x00, 0x00, 0x00, 0x00,
250	0x0d, 24,	0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
251			0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
252			0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
253	0x26, 2,	0xaa, 0xaa,
254	0x2e, 1,	0x31,
255	0x38, 1,	0x01,
256	0x3a, 3,	0x14, 0xff, 0x5a,
257	0x43, 11,	0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
258			0x00, 0x54, 0x11,
259	0x55, 1,	0x00,
260	0x62, 4, 	0x10, 0x1e, 0x1e, 0x18,
261	0x6b, 1,	0x00,
262	0x6e, 3,	0x08, 0x06, 0x00,
263	0x72, 3,	0x00, 0xff, 0x00,
264	0x7d, 23,	0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
265			0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
266			0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
267	0xa2, 10,	0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
268			0xd2, 0xeb,
269	0xaf, 1,	0x02,
270	0xb5, 2,	0x08, 0x08,
271	0xb8, 2,	0x08, 0x88,
272	0xc4, 4,	0xae, 0x01, 0x04, 0x01,
273	0xcc, 1,	0x00,
274	0xd1, 11,	0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
275			0xc1, 0xd7, 0xec,
276	0xdc, 1,	0x01,
277	0xff, 1,	0x01,		/* page 1 */
278	0x12, 3,	0x02, 0x00, 0x01,
279	0x3e, 2,	0x00, 0x00,
280	0x76, 5,	0x01, 0x20, 0x40, 0x00, 0xf2,
281	0x7c, 1,	0x00,
282	0x7f, 10,	0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
283			0x02, 0x00,
284	0x96, 5,	0x01, 0x10, 0x04, 0x01, 0x04,
285	0xc8, 14,	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
286			0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
287	0xd8, 1,	0x01,
288	0xdb, 2,	0x00, 0x01,
289	0xde, 7,	0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
290	0xe6, 4,	0x00, 0x00, 0x00, 0x01,
291	0xeb, 1,	0x00,
292	0xff, 1,	0x02,		/* page 2 */
293	0x22, 1,	0x00,
294	0xff, 1,	0x03,		/* page 3 */
295	0, LOAD_PAGE3,			/* load the page 3 */
296	0x11, 1,	0x01,
297	0xff, 1,	0x02,		/* page 2 */
298	0x13, 1,	0x00,
299	0x22, 4,	0x1f, 0xa4, 0xf0, 0x96,
300	0x27, 2,	0x14, 0x0c,
301	0x2a, 5,	0xc8, 0x00, 0x18, 0x12, 0x22,
302	0x64, 8,	0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
303	0x6e, 1,	0x08,
304	0xff, 1,	0x01,		/* page 1 */
305	0x78, 1,	0x00,
306	0, END_OF_SEQUENCE		/* end of sequence */
307};
308
309#define SKIP		0xaa
310/* page 3 - the value SKIP says skip the index - see reg_w_page() */
311static const __u8 page3_7302[] = {
312	0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
313	0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
314	0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315	0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
316	0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
317	0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
318	0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
319	0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320	0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
321	0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
322	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323	0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
324	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325	0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
326	0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
327	0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
328	0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
329	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330	0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
331	0x00
332};
333
334static void reg_w_buf(struct gspca_dev *gspca_dev,
335		  __u8 index,
336		  const char *buffer, int len)
337{
338	memcpy(gspca_dev->usb_buf, buffer, len);
339	usb_control_msg(gspca_dev->dev,
340			usb_sndctrlpipe(gspca_dev->dev, 0),
341			1,		/* request */
342			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
343			0,		/* value */
344			index, gspca_dev->usb_buf, len,
345			500);
346}
347
348
349static void reg_w(struct gspca_dev *gspca_dev,
350		  __u8 index,
351		  __u8 value)
352{
353	gspca_dev->usb_buf[0] = value;
354	usb_control_msg(gspca_dev->dev,
355			usb_sndctrlpipe(gspca_dev->dev, 0),
356			0,			/* request */
357			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
358			0, index, gspca_dev->usb_buf, 1,
359			500);
360}
361
362static void reg_w_seq(struct gspca_dev *gspca_dev,
363		const __u8 *seq, int len)
364{
365	while (--len >= 0) {
366		reg_w(gspca_dev, seq[0], seq[1]);
367		seq += 2;
368	}
369}
370
371/* load the beginning of a page */
372static void reg_w_page(struct gspca_dev *gspca_dev,
373			const __u8 *page, int len)
374{
375	int index;
376
377	for (index = 0; index < len; index++) {
378		if (page[index] == SKIP)		/* skip this index */
379			continue;
380		gspca_dev->usb_buf[0] = page[index];
381		usb_control_msg(gspca_dev->dev,
382				usb_sndctrlpipe(gspca_dev->dev, 0),
383				0,			/* request */
384			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
385				0, index, gspca_dev->usb_buf, 1,
386				500);
387	}
388}
389
390/* output a variable sequence */
391static void reg_w_var(struct gspca_dev *gspca_dev,
392			const __u8 *seq,
393			const __u8 *page3, unsigned int page3_len,
394			const __u8 *page4, unsigned int page4_len)
395{
396	int index, len;
397
398	for (;;) {
399		index = *seq++;
400		len = *seq++;
401		switch (len) {
402		case END_OF_SEQUENCE:
403			return;
404		case LOAD_PAGE4:
405			reg_w_page(gspca_dev, page4, page4_len);
406			break;
407		case LOAD_PAGE3:
408			reg_w_page(gspca_dev, page3, page3_len);
409			break;
410		default:
411			if (len > USB_BUF_SZ) {
412				PDEBUG(D_ERR|D_STREAM,
413					"Incorrect variable sequence");
414				return;
415			}
416			while (len > 0) {
417				if (len < 8) {
418					reg_w_buf(gspca_dev, index, seq, len);
419					seq += len;
420					break;
421				}
422				reg_w_buf(gspca_dev, index, seq, 8);
423				seq += 8;
424				index += 8;
425				len -= 8;
426			}
427		}
428	}
429	/* not reached */
430}
431
432/* this function is called at probe time for pac7302 */
433static int sd_config(struct gspca_dev *gspca_dev,
434			const struct usb_device_id *id)
435{
436	struct sd *sd = (struct sd *) gspca_dev;
437	struct cam *cam;
438
439	cam = &gspca_dev->cam;
440
441	PDEBUG(D_CONF, "Find Sensor PAC7302");
442	cam->cam_mode = vga_mode;	/* only 640x480 */
443	cam->nmodes = ARRAY_SIZE(vga_mode);
444
445	sd->brightness = BRIGHTNESS_DEF;
446	sd->contrast = CONTRAST_DEF;
447	sd->colors = COLOR_DEF;
448	sd->gain = GAIN_DEF;
449	sd->exposure = EXPOSURE_DEF;
450	sd->autogain = AUTOGAIN_DEF;
451	sd->hflip = HFLIP_DEF;
452	sd->vflip = VFLIP_DEF;
453	return 0;
454}
455
456/* This function is used by pac7302 only */
457static void setbrightcont(struct gspca_dev *gspca_dev)
458{
459	struct sd *sd = (struct sd *) gspca_dev;
460	int i, v;
461	static const __u8 max[10] =
462		{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
463		 0xd4, 0xec};
464	static const __u8 delta[10] =
465		{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
466		 0x11, 0x0b};
467
468	reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
469	for (i = 0; i < 10; i++) {
470		v = max[i];
471		v += (sd->brightness - BRIGHTNESS_MAX)
472			* 150 / BRIGHTNESS_MAX;		/* 200 ? */
473		v -= delta[i] * sd->contrast / CONTRAST_MAX;
474		if (v < 0)
475			v = 0;
476		else if (v > 0xff)
477			v = 0xff;
478		reg_w(gspca_dev, 0xa2 + i, v);
479	}
480	reg_w(gspca_dev, 0xdc, 0x01);
481}
482
483/* This function is used by pac7302 only */
484static void setcolors(struct gspca_dev *gspca_dev)
485{
486	struct sd *sd = (struct sd *) gspca_dev;
487	int i, v;
488	static const int a[9] =
489		{217, -212, 0, -101, 170, -67, -38, -315, 355};
490	static const int b[9] =
491		{19, 106, 0, 19, 106, 1, 19, 106, 1};
492
493	reg_w(gspca_dev, 0xff, 0x03);	/* page 3 */
494	reg_w(gspca_dev, 0x11, 0x01);
495	reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
496	for (i = 0; i < 9; i++) {
497		v = a[i] * sd->colors / COLOR_MAX + b[i];
498		reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
499		reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
500	}
501	reg_w(gspca_dev, 0xdc, 0x01);
502	PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
503}
504
505static void setgain(struct gspca_dev *gspca_dev)
506{
507	struct sd *sd = (struct sd *) gspca_dev;
508
509	reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
510	reg_w(gspca_dev, 0x10, sd->gain >> 3);
511
512	/* load registers to sensor (Bit 0, auto clear) */
513	reg_w(gspca_dev, 0x11, 0x01);
514}
515
516static void setexposure(struct gspca_dev *gspca_dev)
517{
518	struct sd *sd = (struct sd *) gspca_dev;
519	__u8 reg;
520
521	/* register 2 of frame 3/4 contains the clock divider configuring the
522	   no fps according to the formula: 60 / reg. sd->exposure is the
523	   desired exposure time in ms. */
524	reg = 120 * sd->exposure / 1000;
525	if (reg < 2)
526		reg = 2;
527	else if (reg > 63)
528		reg = 63;
529
530	/* On the pac7302 reg2 MUST be a multiple of 3, so round it to
531	   the nearest multiple of 3, except when between 6 and 12? */
532	if (reg < 6 || reg > 12)
533		reg = ((reg + 1) / 3) * 3;
534	reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
535	reg_w(gspca_dev, 0x02, reg);
536
537	/* load registers to sensor (Bit 0, auto clear) */
538	reg_w(gspca_dev, 0x11, 0x01);
539}
540
541static void sethvflip(struct gspca_dev *gspca_dev)
542{
543	struct sd *sd = (struct sd *) gspca_dev;
544	__u8 data;
545
546	reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
547	data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
548	reg_w(gspca_dev, 0x21, data);
549	/* load registers to sensor (Bit 0, auto clear) */
550	reg_w(gspca_dev, 0x11, 0x01);
551}
552
553/* this function is called at probe and resume time for pac7302 */
554static int sd_init(struct gspca_dev *gspca_dev)
555{
556	reg_w_seq(gspca_dev, init_7302, sizeof init_7302);
557
558	return 0;
559}
560
561static int sd_start(struct gspca_dev *gspca_dev)
562{
563	struct sd *sd = (struct sd *) gspca_dev;
564
565	sd->sof_read = 0;
566
567	reg_w_var(gspca_dev, start_7302,
568		page3_7302, sizeof(page3_7302),
569		NULL, 0);
570	setbrightcont(gspca_dev);
571	setcolors(gspca_dev);
572	setgain(gspca_dev);
573	setexposure(gspca_dev);
574	sethvflip(gspca_dev);
575
576	/* only resolution 640x480 is supported for pac7302 */
577
578	sd->sof_read = 0;
579	sd->autogain_ignore_frames = 0;
580	atomic_set(&sd->avg_lum, -1);
581
582	/* start stream */
583	reg_w(gspca_dev, 0xff, 0x01);
584	reg_w(gspca_dev, 0x78, 0x01);
585
586	return 0;
587}
588
589static void sd_stopN(struct gspca_dev *gspca_dev)
590{
591	reg_w(gspca_dev, 0xff, 0x01);
592	reg_w(gspca_dev, 0x78, 0x00);
593	reg_w(gspca_dev, 0x78, 0x00);
594}
595
596/* called on streamoff with alt 0 and on disconnect for pac7302 */
597static void sd_stop0(struct gspca_dev *gspca_dev)
598{
599	if (!gspca_dev->present)
600		return;
601	reg_w(gspca_dev, 0xff, 0x01);
602	reg_w(gspca_dev, 0x78, 0x40);
603}
604
605/* Include pac common sof detection functions */
606#include "pac_common.h"
607
608static void do_autogain(struct gspca_dev *gspca_dev)
609{
610	struct sd *sd = (struct sd *) gspca_dev;
611	int avg_lum = atomic_read(&sd->avg_lum);
612	int desired_lum, deadzone;
613
614	if (avg_lum == -1)
615		return;
616
617	desired_lum = 270 + sd->brightness * 4;
618	/* Hack hack, with the 7202 the first exposure step is
619	   pretty large, so if we're about to make the first
620	   exposure increase make the deadzone large to avoid
621	   oscilating */
622	if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
623			sd->exposure > EXPOSURE_DEF &&
624			sd->exposure < 42)
625		deadzone = 90;
626	else
627		deadzone = 30;
628
629	if (sd->autogain_ignore_frames > 0)
630		sd->autogain_ignore_frames--;
631	else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
632			deadzone, GAIN_KNEE, EXPOSURE_KNEE))
633		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
634}
635
636/* JPEG header, part 1 */
637static const unsigned char pac_jpeg_header1[] = {
638  0xff, 0xd8,		/* SOI: Start of Image */
639
640  0xff, 0xc0,		/* SOF0: Start of Frame (Baseline DCT) */
641  0x00, 0x11,		/* length = 17 bytes (including this length field) */
642  0x08			/* Precision: 8 */
643  /* 2 bytes is placed here: number of image lines */
644  /* 2 bytes is placed here: samples per line */
645};
646
647/* JPEG header, continued */
648static const unsigned char pac_jpeg_header2[] = {
649  0x03,			/* Number of image components: 3 */
650  0x01, 0x21, 0x00,	/* ID=1, Subsampling 1x1, Quantization table: 0 */
651  0x02, 0x11, 0x01,	/* ID=2, Subsampling 2x1, Quantization table: 1 */
652  0x03, 0x11, 0x01,	/* ID=3, Subsampling 2x1, Quantization table: 1 */
653
654  0xff, 0xda,		/* SOS: Start Of Scan */
655  0x00, 0x0c,		/* length = 12 bytes (including this length field) */
656  0x03,			/* number of components: 3 */
657  0x01, 0x00,		/* selector 1, table 0x00 */
658  0x02, 0x11,		/* selector 2, table 0x11 */
659  0x03, 0x11,		/* selector 3, table 0x11 */
660  0x00, 0x3f,		/* Spectral selection: 0 .. 63 */
661  0x00			/* Successive approximation: 0 */
662};
663
664static void pac_start_frame(struct gspca_dev *gspca_dev,
665		struct gspca_frame *frame,
666		__u16 lines, __u16 samples_per_line)
667{
668	unsigned char tmpbuf[4];
669
670	gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
671		pac_jpeg_header1, sizeof(pac_jpeg_header1));
672
673	tmpbuf[0] = lines >> 8;
674	tmpbuf[1] = lines & 0xff;
675	tmpbuf[2] = samples_per_line >> 8;
676	tmpbuf[3] = samples_per_line & 0xff;
677
678	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
679		tmpbuf, sizeof(tmpbuf));
680	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
681		pac_jpeg_header2, sizeof(pac_jpeg_header2));
682}
683
684/* this function is run at interrupt level */
685static void sd_pkt_scan(struct gspca_dev *gspca_dev,
686			struct gspca_frame *frame,	/* target */
687			__u8 *data,			/* isoc packet */
688			int len)			/* iso packet length */
689{
690	struct sd *sd = (struct sd *) gspca_dev;
691	unsigned char *sof;
692
693	sof = pac_find_sof(&sd->sof_read, data, len);
694	if (sof) {
695		int n, lum_offset, footer_length;
696
697		/* 6 bytes after the FF D9 EOF marker a number of lumination
698		   bytes are send corresponding to different parts of the
699		   image, the 14th and 15th byte after the EOF seem to
700		   correspond to the center of the image */
701		lum_offset = 61 + sizeof pac_sof_marker;
702		footer_length = 74;
703
704		/* Finish decoding current frame */
705		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
706		if (n < 0) {
707			frame->data_end += n;
708			n = 0;
709		}
710		frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
711					data, n);
712		if (gspca_dev->last_packet_type != DISCARD_PACKET &&
713				frame->data_end[-2] == 0xff &&
714				frame->data_end[-1] == 0xd9)
715			frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
716						NULL, 0);
717
718		n = sof - data;
719		len -= n;
720		data = sof;
721
722		/* Get average lumination */
723		if (gspca_dev->last_packet_type == LAST_PACKET &&
724				n >= lum_offset)
725			atomic_set(&sd->avg_lum, data[-lum_offset] +
726						data[-lum_offset + 1]);
727		else
728			atomic_set(&sd->avg_lum, -1);
729
730		/* Start the new frame with the jpeg header */
731		/* The PAC7302 has the image rotated 90 degrees */
732		pac_start_frame(gspca_dev, frame,
733			gspca_dev->width, gspca_dev->height);
734	}
735	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
736}
737
738static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
739{
740	struct sd *sd = (struct sd *) gspca_dev;
741
742	sd->brightness = val;
743	if (gspca_dev->streaming)
744		setbrightcont(gspca_dev);
745	return 0;
746}
747
748static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
749{
750	struct sd *sd = (struct sd *) gspca_dev;
751
752	*val = sd->brightness;
753	return 0;
754}
755
756static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
757{
758	struct sd *sd = (struct sd *) gspca_dev;
759
760	sd->contrast = val;
761	if (gspca_dev->streaming) {
762		setbrightcont(gspca_dev);
763	}
764	return 0;
765}
766
767static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
768{
769	struct sd *sd = (struct sd *) gspca_dev;
770
771	*val = sd->contrast;
772	return 0;
773}
774
775static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
776{
777	struct sd *sd = (struct sd *) gspca_dev;
778
779	sd->colors = val;
780	if (gspca_dev->streaming)
781		setcolors(gspca_dev);
782	return 0;
783}
784
785static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
786{
787	struct sd *sd = (struct sd *) gspca_dev;
788
789	*val = sd->colors;
790	return 0;
791}
792
793static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
794{
795	struct sd *sd = (struct sd *) gspca_dev;
796
797	sd->gain = val;
798	if (gspca_dev->streaming)
799		setgain(gspca_dev);
800	return 0;
801}
802
803static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
804{
805	struct sd *sd = (struct sd *) gspca_dev;
806
807	*val = sd->gain;
808	return 0;
809}
810
811static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
812{
813	struct sd *sd = (struct sd *) gspca_dev;
814
815	sd->exposure = val;
816	if (gspca_dev->streaming)
817		setexposure(gspca_dev);
818	return 0;
819}
820
821static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
822{
823	struct sd *sd = (struct sd *) gspca_dev;
824
825	*val = sd->exposure;
826	return 0;
827}
828
829static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
830{
831	struct sd *sd = (struct sd *) gspca_dev;
832
833	sd->autogain = val;
834	/* when switching to autogain set defaults to make sure
835	   we are on a valid point of the autogain gain /
836	   exposure knee graph, and give this change time to
837	   take effect before doing autogain. */
838	if (sd->autogain) {
839		sd->exposure = EXPOSURE_DEF;
840		sd->gain = GAIN_DEF;
841		if (gspca_dev->streaming) {
842			sd->autogain_ignore_frames =
843				PAC_AUTOGAIN_IGNORE_FRAMES;
844			setexposure(gspca_dev);
845			setgain(gspca_dev);
846		}
847	}
848
849	return 0;
850}
851
852static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
853{
854	struct sd *sd = (struct sd *) gspca_dev;
855
856	*val = sd->autogain;
857	return 0;
858}
859
860static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
861{
862	struct sd *sd = (struct sd *) gspca_dev;
863
864	sd->hflip = val;
865	if (gspca_dev->streaming)
866		sethvflip(gspca_dev);
867	return 0;
868}
869
870static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
871{
872	struct sd *sd = (struct sd *) gspca_dev;
873
874	*val = sd->hflip;
875	return 0;
876}
877
878static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
879{
880	struct sd *sd = (struct sd *) gspca_dev;
881
882	sd->vflip = val;
883	if (gspca_dev->streaming)
884		sethvflip(gspca_dev);
885	return 0;
886}
887
888static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
889{
890	struct sd *sd = (struct sd *) gspca_dev;
891
892	*val = sd->vflip;
893	return 0;
894}
895
896/* sub-driver description for pac7302 */
897static struct sd_desc sd_desc = {
898	.name = MODULE_NAME,
899	.ctrls = sd_ctrls,
900	.nctrls = ARRAY_SIZE(sd_ctrls),
901	.config = sd_config,
902	.init = sd_init,
903	.start = sd_start,
904	.stopN = sd_stopN,
905	.stop0 = sd_stop0,
906	.pkt_scan = sd_pkt_scan,
907	.dq_callback = do_autogain,
908};
909
910/* -- module initialisation -- */
911static __devinitdata struct usb_device_id device_table[] = {
912	{USB_DEVICE(0x06f8, 0x3009)},
913	{USB_DEVICE(0x093a, 0x2620)},
914	{USB_DEVICE(0x093a, 0x2621)},
915	{USB_DEVICE(0x093a, 0x2622)},
916	{USB_DEVICE(0x093a, 0x2624)},
917	{USB_DEVICE(0x093a, 0x2626)},
918	{USB_DEVICE(0x093a, 0x2628)},
919	{USB_DEVICE(0x093a, 0x2629)},
920	{USB_DEVICE(0x093a, 0x262a)},
921	{USB_DEVICE(0x093a, 0x262c)},
922	{}
923};
924MODULE_DEVICE_TABLE(usb, device_table);
925
926/* -- device connect -- */
927static int sd_probe(struct usb_interface *intf,
928			const struct usb_device_id *id)
929{
930	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
931				THIS_MODULE);
932}
933
934static struct usb_driver sd_driver = {
935	.name = MODULE_NAME,
936	.id_table = device_table,
937	.probe = sd_probe,
938	.disconnect = gspca_disconnect,
939#ifdef CONFIG_PM
940	.suspend = gspca_suspend,
941	.resume = gspca_resume,
942#endif
943};
944
945/* -- module insert / remove -- */
946static int __init sd_mod_init(void)
947{
948	int ret;
949	ret = usb_register(&sd_driver);
950	if (ret < 0)
951		return ret;
952	PDEBUG(D_PROBE, "registered");
953	return 0;
954}
955static void __exit sd_mod_exit(void)
956{
957	usb_deregister(&sd_driver);
958	PDEBUG(D_PROBE, "deregistered");
959}
960
961module_init(sd_mod_init);
962module_exit(sd_mod_exit);
963