sonixj.c 94.8 KB
Newer Older
1
/*
2
 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
3
 *
4
 * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr>
5
 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#define MODULE_NAME "sonixj"

24
#include <linux/input.h>
25 26 27
#include "gspca.h"
#include "jpeg.h"

28
MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
29 30 31
MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
MODULE_LICENSE("GPL");

32 33
static int starcam;

34 35 36 37 38 39 40 41 42
/* controls */
enum e_ctrl {
	BRIGHTNESS,
	CONTRAST,
	COLORS,
	BLUE,
	RED,
	GAMMA,
	AUTOGAIN,
43
	HFLIP,
44 45
	VFLIP,
	SHARPNESS,
46
	ILLUM,
47 48 49 50
	FREQ,
	NCTRLS		/* number of controls */
};

51 52 53 54
/* specific webcam descriptor */
struct sd {
	struct gspca_dev gspca_dev;	/* !! must be the first item */

55 56
	struct gspca_ctrl ctrls[NCTRLS];

57
	atomic_t avg_lum;
58 59
	u32 exposure;

60 61 62 63 64 65
	struct work_struct work;
	struct workqueue_struct *work_thread;

	u32 pktsz;			/* (used by pkt_scan) */
	u16 npkt;
	u8 nchg;
66 67
	s8 short_mark;

68
	u8 quality;			/* image quality */
69 70 71
#define QUALITY_MIN 25
#define QUALITY_MAX 90
#define QUALITY_DEF 70
72

73 74
	u8 reg01;
	u8 reg17;
75
	u8 reg18;
76
	u8 flags;
77

78
	s8 ag_cnt;
79 80
#define AG_CNT_START 13

81
	u8 bridge;
82 83 84 85
#define BRIDGE_SN9C102P 0
#define BRIDGE_SN9C105 1
#define BRIDGE_SN9C110 2
#define BRIDGE_SN9C120 3
86
	u8 sensor;			/* Type of image sensor chip */
87 88 89 90 91
	u8 i2c_addr;

	u8 jpeg_hdr[JPEG_HDR_SZ];
};
enum sensors {
92
	SENSOR_ADCM1700,
93
	SENSOR_GC0307,
94 95
	SENSOR_HV7131R,
	SENSOR_MI0360,
96
	SENSOR_MI0360B,
97 98 99 100 101 102 103
	SENSOR_MO4000,
	SENSOR_MT9V111,
	SENSOR_OM6802,
	SENSOR_OV7630,
	SENSOR_OV7648,
	SENSOR_OV7660,
	SENSOR_PO1030,
104
	SENSOR_PO2030N,
105
	SENSOR_SOI768,
106
	SENSOR_SP80708,
107 108
};

109 110
static void qual_upd(struct work_struct *work);

111
/* device flags */
112 113
#define F_PDN_INV	0x01	/* inverse pin S_PWR_DN / sn_xxx tables */
#define F_ILLUM		0x02	/* presence of illuminator */
114

115 116 117 118 119 120 121 122 123 124 125 126 127
/* sn9c1xx definitions */
/* register 0x01 */
#define S_PWR_DN	0x01	/* sensor power down */
#define S_PDN_INV	0x02	/* inverse pin S_PWR_DN */
#define V_TX_EN		0x04	/* video transfer enable */
#define LED		0x08	/* output to pin LED */
#define SCL_SEL_OD	0x20	/* open-drain mode */
#define SYS_SEL_48M	0x40	/* system clock 0: 24MHz, 1: 48MHz */
/* register 0x17 */
#define MCK_SIZE_MASK	0x1f	/* sensor master clock */
#define SEN_CLK_EN	0x20	/* enable sensor clock */
#define DEF_EN		0x80	/* defect pixel by 0: soft, 1: hard */

128
/* V4L2 controls supported by the driver */
129 130 131 132 133 134
static void setbrightness(struct gspca_dev *gspca_dev);
static void setcontrast(struct gspca_dev *gspca_dev);
static void setcolors(struct gspca_dev *gspca_dev);
static void setredblue(struct gspca_dev *gspca_dev);
static void setgamma(struct gspca_dev *gspca_dev);
static void setautogain(struct gspca_dev *gspca_dev);
135
static void sethvflip(struct gspca_dev *gspca_dev);
136
static void setsharpness(struct gspca_dev *gspca_dev);
137
static void setillum(struct gspca_dev *gspca_dev);
138 139 140 141
static void setfreq(struct gspca_dev *gspca_dev);

static const struct ctrl sd_ctrls[NCTRLS] = {
[BRIGHTNESS] =  {
142 143 144 145 146
	    {
		.id      = V4L2_CID_BRIGHTNESS,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Brightness",
		.minimum = 0,
147
		.maximum = 0xff,
148
		.step    = 1,
149
		.default_value = 0x80,
150
	    },
151
	    .set_control = setbrightness
152
	},
153
[CONTRAST] = {
154 155 156 157 158
	    {
		.id      = V4L2_CID_CONTRAST,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Contrast",
		.minimum = 0,
159 160
#define CONTRAST_MAX 127
		.maximum = CONTRAST_MAX,
161
		.step    = 1,
162
		.default_value = 63,
163
	    },
164
	    .set_control = setcontrast
165
	},
166
[COLORS] = {
167 168 169
	    {
		.id      = V4L2_CID_SATURATION,
		.type    = V4L2_CTRL_TYPE_INTEGER,
170
		.name    = "Saturation",
171
		.minimum = 0,
172
		.maximum = 40,
173
		.step    = 1,
174 175
#define COLORS_DEF 25
		.default_value = COLORS_DEF,
176
	    },
177
	    .set_control = setcolors
178
	},
179
[BLUE] = {
180 181 182 183 184 185 186
	    {
		.id      = V4L2_CID_BLUE_BALANCE,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Blue Balance",
		.minimum = 24,
		.maximum = 40,
		.step    = 1,
187
		.default_value = 32,
188
	    },
189
	    .set_control = setredblue
190
	},
191
[RED] = {
192 193 194 195 196 197 198
	    {
		.id      = V4L2_CID_RED_BALANCE,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Red Balance",
		.minimum = 24,
		.maximum = 40,
		.step    = 1,
199
		.default_value = 32,
200
	    },
201
	    .set_control = setredblue
202
	},
203
[GAMMA] = {
204 205 206 207 208 209 210 211 212 213
	    {
		.id      = V4L2_CID_GAMMA,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Gamma",
		.minimum = 0,
		.maximum = 40,
		.step    = 1,
#define GAMMA_DEF 20
		.default_value = GAMMA_DEF,
	    },
214
	    .set_control = setgamma
215
	},
216
[AUTOGAIN] = {
217 218 219 220 221 222 223
	    {
		.id      = V4L2_CID_AUTOGAIN,
		.type    = V4L2_CTRL_TYPE_BOOLEAN,
		.name    = "Auto Gain",
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
224
		.default_value = 1
225
	    },
226
	    .set_control = setautogain
227
	},
228 229 230 231 232 233 234 235 236 237 238 239
[HFLIP] = {
	    {
		.id      = V4L2_CID_HFLIP,
		.type    = V4L2_CTRL_TYPE_BOOLEAN,
		.name    = "Mirror",
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
		.default_value = 0,
	    },
	    .set_control = sethvflip
	},
240
[VFLIP] = {
241 242 243 244 245 246 247
	    {
		.id      = V4L2_CID_VFLIP,
		.type    = V4L2_CTRL_TYPE_BOOLEAN,
		.name    = "Vflip",
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
248
		.default_value = 0,
249
	    },
250
	    .set_control = sethvflip
251
	},
252
[SHARPNESS] = {
253 254 255 256 257 258 259
	    {
		.id	 = V4L2_CID_SHARPNESS,
		.type    = V4L2_CTRL_TYPE_INTEGER,
		.name    = "Sharpness",
		.minimum = 0,
		.maximum = 255,
		.step    = 1,
260
		.default_value = 90,
261
	    },
262
	    .set_control = setsharpness
263
	},
264
[ILLUM] = {
265
	    {
266
		.id      = V4L2_CID_ILLUMINATORS_1,
267
		.type    = V4L2_CTRL_TYPE_BOOLEAN,
268
		.name    = "Illuminator / infrared",
269 270 271
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
272
		.default_value = 0,
273
	    },
274
	    .set_control = setillum
275
	},
276
/* ov7630/ov7648/ov7660 only */
277
[FREQ] = {
278 279 280 281 282 283 284
	    {
		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
		.type    = V4L2_CTRL_TYPE_MENU,
		.name    = "Light frequency filter",
		.minimum = 0,
		.maximum = 2,	/* 0: 0, 1: 50Hz, 2:60Hz */
		.step    = 1,
285
		.default_value = 1,
286
	    },
287
	    .set_control = setfreq
288
	},
289 290
};

291
/* table of the disabled controls */
292
static const __u32 ctrl_dis[] = {
293
[SENSOR_ADCM1700] =	(1 << AUTOGAIN) |
294
			(1 << HFLIP) |
295 296 297
			(1 << VFLIP) |
			(1 << FREQ),

298
[SENSOR_GC0307] =	(1 << HFLIP) |
299 300 301
			(1 << VFLIP) |
			(1 << FREQ),

302
[SENSOR_HV7131R] =	(1 << HFLIP) |
303 304
			(1 << FREQ),

305
[SENSOR_MI0360] =	(1 << HFLIP) |
306 307 308
			(1 << VFLIP) |
			(1 << FREQ),

309
[SENSOR_MI0360B] =	(1 << HFLIP) |
310 311 312
			(1 << VFLIP) |
			(1 << FREQ),

313
[SENSOR_MO4000] =	(1 << HFLIP) |
314 315 316
			(1 << VFLIP) |
			(1 << FREQ),

317 318
[SENSOR_MT9V111] =	(1 << HFLIP) |
			(1 << VFLIP) |
319 320
			(1 << FREQ),

321
[SENSOR_OM6802] =	(1 << HFLIP) |
322 323 324
			(1 << VFLIP) |
			(1 << FREQ),

325
[SENSOR_OV7630] =	(1 << HFLIP),
326

327
[SENSOR_OV7648] =	(1 << HFLIP),
328 329

[SENSOR_OV7660] =	(1 << AUTOGAIN) |
330
			(1 << HFLIP) |
331 332 333
			(1 << VFLIP),

[SENSOR_PO1030] =	(1 << AUTOGAIN) |
334
			(1 << HFLIP) |
335 336 337 338 339
			(1 << VFLIP) |
			(1 << FREQ),

[SENSOR_PO2030N] =	(1 << AUTOGAIN) |
			(1 << FREQ),
340

341
[SENSOR_SOI768] =	(1 << AUTOGAIN) |
342
			(1 << HFLIP) |
343 344 345 346
			(1 << VFLIP) |
			(1 << FREQ),

[SENSOR_SP80708] =	(1 << AUTOGAIN) |
347
			(1 << HFLIP) |
348 349
			(1 << VFLIP) |
			(1 << FREQ),
350 351
};

352 353 354 355 356 357 358
static const struct v4l2_pix_format cif_mode[] = {
	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
		.bytesperline = 352,
		.sizeimage = 352 * 288 * 4 / 8 + 590,
		.colorspace = V4L2_COLORSPACE_JPEG,
		.priv = 0},
};
359
static const struct v4l2_pix_format vga_mode[] = {
360 361
	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
		.bytesperline = 160,
362
		.sizeimage = 160 * 120 * 4 / 8 + 590,
363 364 365 366 367 368 369 370 371
		.colorspace = V4L2_COLORSPACE_JPEG,
		.priv = 2},
	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
		.bytesperline = 320,
		.sizeimage = 320 * 240 * 3 / 8 + 590,
		.colorspace = V4L2_COLORSPACE_JPEG,
		.priv = 1},
	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
		.bytesperline = 640,
372 373
		/* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
		.sizeimage = 640 * 480 * 3 / 4 + 590,
374 375
		.colorspace = V4L2_COLORSPACE_JPEG,
		.priv = 0},
376 377
};

378 379
static const u8 sn_adcm1700[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
380
	0x00,	0x43,	0x60,	0x00,	0x1a,	0x00,	0x00,	0x00,
381 382 383 384 385 386 387 388
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x80,	0x51,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x05,	0x01,	0x05,	0x16,	0x12,	0x42,
/*	reg18	reg19	reg1a	reg1b */
	0x06,	0x00,	0x00,	0x00
};

389 390 391 392 393 394 395 396 397 398 399
static const u8 sn_gc0307[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
	0x00,	0x61,	0x62,	0x00,	0x1a,	0x00,	0x00,	0x00,
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x80,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x03,	0x01,	0x08,	0x28,	0x1e,	0x02,
/*	reg18	reg19	reg1a	reg1b */
	0x06,	0x00,	0x00,	0x00
};

400
static const u8 sn_hv7131[0x1c] = {
401
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
402
	0x00,	0x03,	0x60,	0x00,	0x1a,	0x20,	0x20,	0x20,
403
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
404
	0x81,	0x11,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
405 406
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x01,	0x03,	0x28,	0x1e,	0x41,
407 408
/*	reg18	reg19	reg1a	reg1b */
	0x0a,	0x00,	0x00,	0x00
409 410
};

411
static const u8 sn_mi0360[0x1c] = {
412
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
413
	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
414
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
415
	0x81,	0x5d,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
416 417
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x02,	0x0a,	0x28,	0x1e,	0x61,
418 419
/*	reg18	reg19	reg1a	reg1b */
	0x06,	0x00,	0x00,	0x00
420 421
};

422 423 424 425 426 427 428 429 430 431 432
static const u8 sn_mi0360b[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
	0x00,	0x61,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x81,	0x5d,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x02,	0x0a,	0x28,	0x1e,	0x40,
/*	reg18	reg19	reg1a	reg1b */
	0x06,	0x00,	0x00,	0x00
};

433
static const u8 sn_mo4000[0x1c] = {
434
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
435
	0x00,	0x23,	0x60,	0x00,	0x1a,	0x00,	0x20,	0x18,
436 437 438 439
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	 0x00,	0x0b,	0x0f,	0x14,	0x28,	0x1e,	0x40,
440 441
/*	reg18	reg19	reg1a	reg1b */
	0x08,	0x00,	0x00,	0x00
442 443
};

444 445 446 447
static const u8 sn_mt9v111[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
448
	0x81,	0x5c,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
449 450 451 452 453 454
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x02,	0x1c,	0x28,	0x1e,	0x40,
/*	reg18	reg19	reg1a	reg1b */
	0x06,	0x00,	0x00,	0x00
};

455
static const u8 sn_om6802[0x1c] = {
456
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
457
	0x00,	0x23,	0x72,	0x00,	0x1a,	0x20,	0x20,	0x19,
458 459 460 461
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x80,	0x34,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x51,	0x01,	0x00,	0x28,	0x1e,	0x40,
462 463
/*	reg18	reg19	reg1a	reg1b */
	0x05,	0x00,	0x00,	0x00
464 465
};

466
static const u8 sn_ov7630[0x1c] = {
467
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
468
	0x00,	0x21,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
469
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
470
	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
471 472
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x04,	0x01,	0x0a,	0x28,	0x1e,	0xc2,
473 474
/*	reg18	reg19	reg1a	reg1b */
	0x0b,	0x00,	0x00,	0x00
475 476
};

477
static const u8 sn_ov7648[0x1c] = {
478
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
479
	0x00,	0x63,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
480
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
481
	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
482
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
483
	0x03,	0x00,	0x00,	0x01,	0x00,	0x28,	0x1e,	0x00,
484 485
/*	reg18	reg19	reg1a	reg1b */
	0x0b,	0x00,	0x00,	0x00
486 487
};

488
static const u8 sn_ov7660[0x1c] = {
489
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
490
	0x00,	0x61,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
491
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
492
	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
493 494
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x01,	0x01,	0x08,	0x28,	0x1e,	0x20,
495 496
/*	reg18	reg19	reg1a	reg1b */
	0x07,	0x00,	0x00,	0x00
497 498
};

499 500 501 502 503 504 505 506 507 508 509
static const u8 sn_po1030[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
	0x00,	0x21,	0x62,	0x00,	0x1a,	0x20,	0x20,	0x20,
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x81,	0x6e,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x06,	0x06,	0x28,	0x1e,	0x00,
/*	reg18	reg19	reg1a	reg1b */
	0x07,	0x00,	0x00,	0x00
};

510 511 512 513 514 515 516 517 518 519 520
static const u8 sn_po2030n[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
	0x00,	0x63,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x81,	0x6e,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x01,	0x14,	0x28,	0x1e,	0x00,
/*	reg18	reg19	reg1a	reg1b */
	0x07,	0x00,	0x00,	0x00
};

521 522 523 524 525 526 527 528 529 530 531
static const u8 sn_soi768[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
	0x00,	0x21,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x01,	0x08,	0x28,	0x1e,	0x00,
/*	reg18	reg19	reg1a	reg1b */
	0x07,	0x00,	0x00,	0x00
};

532 533 534 535
static const u8 sn_sp80708[0x1c] = {
/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
	0x00,	0x63,	0x60,	0x00,	0x1a,	0x20,	0x20,	0x20,
/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
536
	0x81,	0x18,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
537 538 539 540 541 542
/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
	0x03,	0x00,	0x00,	0x03,	0x04,	0x28,	0x1e,	0x00,
/*	reg18	reg19	reg1a	reg1b */
	0x07,	0x00,	0x00,	0x00
};

543
/* sequence specific to the sensors - !! index = SENSOR_xxx */
544
static const u8 *sn_tb[] = {
545
[SENSOR_ADCM1700] =	sn_adcm1700,
546
[SENSOR_GC0307] =	sn_gc0307,
547 548
[SENSOR_HV7131R] =	sn_hv7131,
[SENSOR_MI0360] =	sn_mi0360,
549
[SENSOR_MI0360B] =	sn_mi0360b,
550 551 552 553 554 555 556
[SENSOR_MO4000] =	sn_mo4000,
[SENSOR_MT9V111] =	sn_mt9v111,
[SENSOR_OM6802] =	sn_om6802,
[SENSOR_OV7630] =	sn_ov7630,
[SENSOR_OV7648] =	sn_ov7648,
[SENSOR_OV7660] =	sn_ov7660,
[SENSOR_PO1030] =	sn_po1030,
557
[SENSOR_PO2030N] =	sn_po2030n,
558 559
[SENSOR_SOI768] =	sn_soi768,
[SENSOR_SP80708] =	sn_sp80708,
560 561
};

562
/* default gamma table */
563
static const u8 gamma_def[17] = {
564 565 566
	0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
	0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
};
567 568 569 570 571
/* gamma for sensor ADCM1700 */
static const u8 gamma_spec_0[17] = {
	0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
	0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
};
572 573 574 575 576
/* gamma for sensors HV7131R and MT9V111 */
static const u8 gamma_spec_1[17] = {
	0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
	0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
};
577
/* gamma for sensor GC0307 */
578
static const u8 gamma_spec_2[17] = {
579 580 581 582 583
	0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,
	0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb
};
/* gamma for sensor SP80708 */
static const u8 gamma_spec_3[17] = {
584 585 586
	0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
	0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
};
587

588
/* color matrix and offsets */
589
static const u8 reg84[] = {
590 591 592 593
	0x14, 0x00, 0x27, 0x00, 0x07, 0x00,	/* YR YG YB gains */
	0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,	/* UR UG UB */
	0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,	/* VR VG VB */
	0x00, 0x00, 0x00			/* YUV offsets */
594
};
595 596 597

#define DELAY	0xdd

598 599
static const u8 adcm1700_sensor_init[][8] = {
	{0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
600
	{0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10},	/* reset */
601
	{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
602
	{0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
603
	{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
604 605 606 607 608
	{0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
609
	{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
610
	{0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
611
	{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
612 613 614 615 616 617 618
	{0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
	{}
};
static const u8 adcm1700_sensor_param1[][8] = {
619
	{0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10},	/* exposure? */
620 621 622 623 624 625
	{0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},

	{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
626
	{0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10},	/* exposure? */
627

628 629 630 631
	{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
632 633
	{}
};
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
static const u8 gc0307_sensor_init[][8] = {
	{0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},
655
	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
	{0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},
	{}
};
static const u8 gc0307_sensor_param1[][8] = {
	{0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},
	{0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},
	{0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},
	{0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},
/*param3*/
	{0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},
	{}
};

686
static const u8 hv7131r_sensor_init[][8] = {
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
	{0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
	{0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
	{0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
/*	{0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
	{0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
/*	{0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */

	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
	{0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
	{0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
	{0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
	{0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
	{0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
	{0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */

	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
706
	{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
707 708 709 710 711 712 713 714
	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},

	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
715 716
	{0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},
							/* set sensor clock */
717
	{}
718
};
719
static const u8 mi0360_sensor_init[][8] = {
720
	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
721
	{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
722
	{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
	{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
	{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
	{0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
	{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
742
	{0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
	{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
	{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
	{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},

	{0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
	{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},

	{0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
	{0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */

	{0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
	{0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
/*	{0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
/*	{0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
	{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
771
	{}
772
};
773 774 775
static const u8 mi0360b_sensor_init[][8] = {
	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
776
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
777
	{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
778
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
	{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
	{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
	{0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
	{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
	{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
	{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
	{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},

	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
	{0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},
	{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},
	{}
};
static const u8 mi0360b_sensor_param1[][8] = {
	{0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},
	{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */

	{0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},
	{0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},
	{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
	{}
};
829
static const u8 mo4000_sensor_init[][8] = {
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
	{0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
850
	{}
851
};
852 853
static const u8 mt9v111_sensor_init[][8] = {
	{0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
854
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
	{0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
	{0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
	{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
	{0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
	{0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
	{0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
	{0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
	{0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
	{0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
	{0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
	{0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
	{0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
871 872 873
	{}
};
static const u8 mt9v111_sensor_param1[][8] = {
874 875 876 877
	{0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
	{0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
	{0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
	{0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
878 879 880
	{0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
	{}
};
881 882 883 884 885
static const u8 om6802_init0[2][8] = {
/*fixme: variable*/
	{0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},
};
886
static const u8 om6802_sensor_init[][8] = {
887 888
	{0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},
						/* factory mode */
889
	{0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
890
						/* output raw RGB */
891
	{0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
892 893
/*	{0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
	{0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
894
		/* auto-exposure speed (0) / white balance mode (auto RGB) */
895 896 897 898 899 900 901 902 903 904 905 906 907
/*	{0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
							 * set color mode */
/*	{0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
						 * max AGC value in AE */
/*	{0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
							 * preset AGC */
/*	{0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
						 * preset brightness */
/*	{0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
							 * preset contrast */
/*	{0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
							 * preset gamma */
	{0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
908
				/* luminance mode (0x4f -> AutoExpo on) */
909 910 911 912 913
	{0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
							/* preset shutter */
/*	{0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
							 * auto frame rate */
/*	{0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
914 915 916 917 918 919 920 921
	{0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
	{}
};
static const u8 om6802_sensor_param1[][8] = {
	{0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},
922 923
	{}
};
924
static const u8 ov7630_sensor_init[][8] = {
925 926
	{0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
927
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
928 929
	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
930
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
931
	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
932
/* win: i2c_r from 00 to 80 */
933 934
	{0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
	{0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
935 936 937
/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
	0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
	{0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
	{0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
	{0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
	{0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
	{0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
	{0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
	{0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
	{0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
	{0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
	{0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
	{0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
	{0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
	{0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
	{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
961 962 963
	{}
};
static const u8 ov7630_sensor_param1[][8] = {
964 965 966
	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
/*fixme: + 0x12, 0x04*/
967 968
/*	{0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},  * COMN
							 * set by setvflip */
969 970 971
	{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
972
/* */
973 974
/*	{0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
/*	{0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
975
/* */
976
	{0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
977
/*	{0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
978 979
	{}
};
980

981
static const u8 ov7648_sensor_init[][8] = {
982 983
	{0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},	/* reset */
984
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
	{0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
	{0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
	{0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
	{0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
	{0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
	{0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
	{0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
	{0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
	{0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
	{0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
	{0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
	{0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
	{0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
	{0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},

	{0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
/*	{0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
/*	{0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
1008
/*	{0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
1009 1010 1011
	{}
};
static const u8 ov7648_sensor_param1[][8] = {
1012
/*	{0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
1013 1014
/*	{0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10},   * COMN
							 * set by setvflip */
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
	{0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
/*	{0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
/*	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},  * GAIN - def */
/*	{0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10},  * B R - def: 80 */
/*...*/
	{0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
/*	{0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
/*	{0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
/*	{0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
/*	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
/*	{0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10},  * B R - def: 80 */

	{}
};

1031
static const u8 ov7660_sensor_init[][8] = {
1032
	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
1033
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
1034
	{0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
1035
						/* Outformat = rawRGB */
1036
	{0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
1037
	{0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
1038 1039 1040 1041 1042
						/* GAIN BLUE RED VREF */
	{0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
						/* COM 1 BAVE GEAVE AECHH */
	{0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
	{0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
1043
	{0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
1044 1045 1046 1047 1048 1049 1050 1051
						/* AECH CLKRC COM7 COM8 */
	{0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
	{0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
						/* HSTART HSTOP VSTRT VSTOP */
	{0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
	{0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
	{0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
					/* BOS GBOS GROS ROS (BGGR offset) */
1052 1053
/*	{0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
	{0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
						/* AEW AEB VPT BBIAS */
	{0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
						/* GbBIAS RSVD EXHCH EXHCL */
	{0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
						/* RBIAS ADVFL ASDVFH YAVE */
	{0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
						/* HSYST HSYEN HREF */
	{0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
	{0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
						/* ADC ACOM OFON TSLB */
	{0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
						/* COM11 COM12 COM13 COM14 */
	{0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
						/* EDGE COM15 COM16 COM17 */
	{0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
	{0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
	{0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
	{0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
	{0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
	{0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
	{0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
	{0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
	{0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
	{0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
						/* LCC1 LCC2 LCC3 LCC4 */
	{0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
1080
	{0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
1081
	{0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
1082
					/* band gap reference [0:3] DBLV */
1083 1084 1085 1086 1087 1088 1089 1090 1091
	{0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
	{0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
	{0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
	{0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
	{0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
	{0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
	{0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
	{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
	{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
1092
	{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
1093
/* not in all ms-win traces*/
1094
	{0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
1095 1096 1097
	{}
};
static const u8 ov7660_sensor_param1[][8] = {
1098
	{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
1099 1100 1101 1102 1103
						/* bits[3..0]reserved */
	{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
						/* VREF vertical frame ctrl */
	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
1104 1105 1106 1107 1108
	{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
	{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
	{0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
/*	{0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
1109
/****** (some exchanges in the win trace) ******/
1110
/*fixme:param2*/
1111
	{0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
1112 1113 1114 1115
	{0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
	{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
/*	{0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},  * RED */
1116
/****** (some exchanges in the win trace) ******/
1117
/******!! startsensor KO if changed !!****/
1118
/*fixme: param3*/
1119 1120 1121 1122
	{0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
1123
	{}
1124 1125
};

1126 1127 1128
static const u8 po1030_sensor_init[][8] = {
/* the sensor registers are described in m5602/m5602_po1030.h */
	{0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */
1129
	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
	{0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},
	{0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},
	{0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
	{0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */
	{0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},
	{0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */
	{0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},
	{0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */
	{0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},
	{0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},
	{0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
	{0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
	{0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},
	{0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},
	{0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},
	{0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */
	{0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},

	{0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},
	{}
};
static const u8 po1030_sensor_param1[][8] = {
/* from ms-win traces - these values change with auto gain/expo/wb.. */
	{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
/* mean values */
	{0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */
	{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */
	{0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */

	{0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */
	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */
	{0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},
/*	{0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */
	{}
};

1180 1181 1182
static const u8 po2030n_sensor_init[][8] = {
	{0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},
1183
	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
1184 1185
	{0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},
1186
	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
	{0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},
	{0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},
	{0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},
	{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},
	{0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},
	{0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},
	{0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},
	{0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},
	{0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},
	{0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},
	{0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},
	{0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},
	{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},
	{0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},
	{}
};
static const u8 po2030n_sensor_param1[][8] = {
	{0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},
1235
	{DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
	{0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10},
/*param2*/
	{0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10},
/*after start*/
	{0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10},
1249
	{DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */
1250
	{0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10},
1251
	{DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */
1252 1253 1254 1255
	{0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10},
	{}
};

1256 1257
static const u8 soi768_sensor_init[][8] = {
	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
1258
	{DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
	{}
};
static const u8 soi768_sensor_param1[][8] = {
	{0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
/* */
/*	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
/*	{0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
/*	{0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
	{0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
/* the next sequence should be used for auto gain */
	{0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
			/* global gain ? : 07 - change with 0x15 at the end */
	{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
	{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},
			/* exposure ? : 0200 - change with 0x1e at the end */
	{}
};

1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358
static const u8 sp80708_sensor_init[][8] = {
	{0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
1359 1360 1361
	{}
};
static const u8 sp80708_sensor_param1[][8] = {
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
	{0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
	{0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
	{}
};

1372 1373
static const u8 (*sensor_init[])[8] = {
[SENSOR_ADCM1700] =	adcm1700_sensor_init,
1374
[SENSOR_GC0307] =	gc0307_sensor_init,
1375 1376
[SENSOR_HV7131R] =	hv7131r_sensor_init,
[SENSOR_MI0360] =	mi0360_sensor_init,
1377
[SENSOR_MI0360B] =	mi0360b_sensor_init,
1378 1379 1380 1381 1382 1383 1384
[SENSOR_MO4000] =	mo4000_sensor_init,
[SENSOR_MT9V111] =	mt9v111_sensor_init,
[SENSOR_OM6802] =	om6802_sensor_init,
[SENSOR_OV7630] =	ov7630_sensor_init,
[SENSOR_OV7648] =	ov7648_sensor_init,
[SENSOR_OV7660] =	ov7660_sensor_init,
[SENSOR_PO1030] =	po1030_sensor_init,
1385
[SENSOR_PO2030N] =	po2030n_sensor_init,
1386
[SENSOR_SOI768] =	soi768_sensor_init,
1387
[SENSOR_SP80708] =	sp80708_sensor_init,
1388 1389
};

1390
/* read <len> bytes to gspca_dev->usb_buf */
1391
static void reg_r(struct gspca_dev *gspca_dev,
1392
		  u16 value, int len)
1393
{
1394 1395 1396 1397
	int ret;

	if (gspca_dev->usb_err < 0)
		return;
1398 1399 1400 1401 1402 1403
#ifdef GSPCA_DEBUG
	if (len > USB_BUF_SZ) {
		err("reg_r: buffer overflow");
		return;
	}
#endif
1404
	ret = usb_control_msg(gspca_dev->dev,
1405
			usb_rcvctrlpipe(gspca_dev->dev, 0),
1406 1407 1408
			0,
			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
			value, 0,
1409
			gspca_dev->usb_buf, len,
1410
			500);
1411
	PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
1412 1413 1414 1415
	if (ret < 0) {
		err("reg_r err %d", ret);
		gspca_dev->usb_err = ret;
	}
1416 1417
}

1418
static void reg_w1(struct gspca_dev *gspca_dev,
1419 1420
		   u16 value,
		   u8 data)
1421
{
1422 1423 1424 1425
	int ret;

	if (gspca_dev->usb_err < 0)
		return;
1426
	PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);
1427
	gspca_dev->usb_buf[0] = data;
1428
	ret = usb_control_msg(gspca_dev->dev,
1429 1430 1431 1432 1433 1434 1435
			usb_sndctrlpipe(gspca_dev->dev, 0),
			0x08,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
			value,
			0,
			gspca_dev->usb_buf, 1,
			500);
1436 1437 1438 1439
	if (ret < 0) {
		err("reg_w1 err %d", ret);
		gspca_dev->usb_err = ret;
	}
1440
}
1441
static void reg_w(struct gspca_dev *gspca_dev,
1442 1443
			  u16 value,
			  const u8 *buffer,
1444 1445
			  int len)
{
1446 1447 1448 1449
	int ret;

	if (gspca_dev->usb_err < 0)
		return;
1450
	PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
1451
		value, buffer[0], buffer[1]);
1452 1453 1454 1455
#ifdef GSPCA_DEBUG
	if (len > USB_BUF_SZ) {
		err("reg_w: buffer overflow");
		return;
1456
	}
1457 1458
#endif
	memcpy(gspca_dev->usb_buf, buffer, len);
1459
	ret = usb_control_msg(gspca_dev->dev,
1460 1461 1462 1463 1464 1465
			usb_sndctrlpipe(gspca_dev->dev, 0),
			0x08,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
			value, 0,
			gspca_dev->usb_buf, len,
			500);
1466 1467 1468 1469
	if (ret < 0) {
		err("reg_w err %d", ret);
		gspca_dev->usb_err = ret;
	}
1470 1471
}

1472
/* I2C write 1 byte */
1473
static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1474 1475
{
	struct sd *sd = (struct sd *) gspca_dev;
1476
	int ret;
1477

1478 1479
	if (gspca_dev->usb_err < 0)
		return;
1480
	PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val);
1481
	switch (sd->sensor) {
1482
	case SENSOR_ADCM1700:
1483 1484
	case SENSOR_OM6802:
	case SENSOR_GC0307:		/* i2c command = a0 (100 kHz) */
1485 1486 1487 1488 1489 1490
		gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
		break;
	default:			/* i2c command = a1 (400 kHz) */
		gspca_dev->usb_buf[0] = 0x81 | (2 << 4);
		break;
	}
1491
	gspca_dev->usb_buf[1] = sd->i2c_addr;
1492 1493 1494 1495 1496 1497
	gspca_dev->usb_buf[2] = reg;
	gspca_dev->usb_buf[3] = val;
	gspca_dev->usb_buf[4] = 0;
	gspca_dev->usb_buf[5] = 0;
	gspca_dev->usb_buf[6] = 0;
	gspca_dev->usb_buf[7] = 0x10;
1498
	ret = usb_control_msg(gspca_dev->dev,
1499 1500 1501 1502 1503 1504 1505
			usb_sndctrlpipe(gspca_dev->dev, 0),
			0x08,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
			0x08,			/* value = i2c */
			0,
			gspca_dev->usb_buf, 8,
			500);
1506 1507 1508 1509
	if (ret < 0) {
		err("i2c_w1 err %d", ret);
		gspca_dev->usb_err = ret;
	}
1510 1511
}

1512 1513
/* I2C write 8 bytes */
static void i2c_w8(struct gspca_dev *gspca_dev,
1514
		   const u8 *buffer)
1515
{
1516 1517 1518 1519
	int ret;

	if (gspca_dev->usb_err < 0)
		return;
1520 1521
	PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..",
		buffer[2], buffer[3]);
1522
	memcpy(gspca_dev->usb_buf, buffer, 8);
1523
	ret = usb_control_msg(gspca_dev->dev,
1524 1525 1526 1527 1528 1529
			usb_sndctrlpipe(gspca_dev->dev, 0),
			0x08,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
			0x08, 0,		/* value, index */
			gspca_dev->usb_buf, 8,
			500);
1530
	msleep(2);
1531 1532 1533 1534
	if (ret < 0) {
		err("i2c_w8 err %d", ret);
		gspca_dev->usb_err = ret;
	}
1535 1536
}

1537 1538
/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */
static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
1539 1540
{
	struct sd *sd = (struct sd *) gspca_dev;
1541
	u8 mode[8];
1542

1543
	switch (sd->sensor) {
1544
	case SENSOR_ADCM1700:
1545 1546
	case SENSOR_OM6802:
	case SENSOR_GC0307:		/* i2c command = a0 (100 kHz) */
1547 1548 1549 1550 1551 1552
		mode[0] = 0x80 | 0x10;
		break;
	default:			/* i2c command = 91 (400 kHz) */
		mode[0] = 0x81 | 0x10;
		break;
	}
1553
	mode[1] = sd->i2c_addr;
1554 1555 1556 1557 1558 1559
	mode[2] = reg;
	mode[3] = 0;
	mode[4] = 0;
	mode[5] = 0;
	mode[6] = 0;
	mode[7] = 0x10;
1560
	i2c_w8(gspca_dev, mode);
1561
	msleep(2);
1562
	mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;
1563
	mode[2] = 0;
1564
	i2c_w8(gspca_dev, mode);
1565
	msleep(2);
1566
	reg_r(gspca_dev, 0x0a, 5);
1567 1568
}

1569 1570 1571 1572
static void i2c_w_seq(struct gspca_dev *gspca_dev,
			const u8 (*data)[8])
{
	while ((*data)[0] != 0) {
1573
		if ((*data)[0] != DELAY)
1574 1575 1576 1577 1578 1579 1580
			i2c_w8(gspca_dev, *data);
		else
			msleep((*data)[1]);
		data++;
	}
}

1581 1582
/* check the ID of the hv7131 sensor */
/* this sequence is needed because it activates the sensor */
1583
static void hv7131r_probe(struct gspca_dev *gspca_dev)
1584
{
1585
	i2c_w1(gspca_dev, 0x02, 0);		/* sensor wakeup */
1586
	msleep(10);
1587
	reg_w1(gspca_dev, 0x02, 0x66);		/* Gpio on */
1588
	msleep(10);
1589 1590
	i2c_r(gspca_dev, 0, 5);			/* read sensor id */
	if (gspca_dev->usb_buf[0] == 0x02	/* chip ID (02 is R) */
1591
	    && gspca_dev->usb_buf[1] == 0x09
1592 1593
	    && gspca_dev->usb_buf[2] == 0x01) {
		PDEBUG(D_PROBE, "Sensor HV7131R found");
1594
		return;
1595
	}
1596
	warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",
1597 1598
		gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
		gspca_dev->usb_buf[2]);
1599 1600
}

1601
static void mi0360_probe(struct gspca_dev *gspca_dev)
1602
{
1603
	struct sd *sd = (struct sd *) gspca_dev;
1604
	int i, j;
1605
	u16 val = 0;
1606
	static const u8 probe_tb[][4][8] = {
1607
	    {					/* mi0360 */
1608 1609 1610 1611 1612
		{0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
		{0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
		{0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
		{0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
	    },
1613
	    {					/* mt9v111 */
1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
		{0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
		{0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
		{0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
		{}
	    },
	};

	for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
		reg_w1(gspca_dev, 0x17, 0x62);
		reg_w1(gspca_dev, 0x01, 0x08);
		for (j = 0; j < 3; j++)
			i2c_w8(gspca_dev, probe_tb[i][j]);
		msleep(2);
		reg_r(gspca_dev, 0x0a, 5);
		val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
		if (probe_tb[i][3][0] != 0)
			i2c_w8(gspca_dev, probe_tb[i][3]);
		reg_w1(gspca_dev, 0x01, 0x29);
		reg_w1(gspca_dev, 0x17, 0x42);
		if (val != 0xffff)
			break;
	}
1636 1637
	if (gspca_dev->usb_err < 0)
		return;
1638
	switch (val) {
1639 1640 1641 1642
	case 0x8221:
		PDEBUG(D_PROBE, "Sensor mi0360b");
		sd->sensor = SENSOR_MI0360B;
		break;
1643 1644
	case 0x823a:
		PDEBUG(D_PROBE, "Sensor mt9v111");
1645 1646
		sd->sensor = SENSOR_MT9V111;
		break;
1647 1648
	case 0x8243:
		PDEBUG(D_PROBE, "Sensor mi0360");
1649 1650 1651 1652
		break;
	default:
		PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);
		break;
1653 1654 1655
	}
}

1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
static void ov7630_probe(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
	u16 val;

	/* check ov76xx */
	reg_w1(gspca_dev, 0x17, 0x62);
	reg_w1(gspca_dev, 0x01, 0x08);
	sd->i2c_addr = 0x21;
	i2c_r(gspca_dev, 0x0a, 2);
	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
	reg_w1(gspca_dev, 0x01, 0x29);
	reg_w1(gspca_dev, 0x17, 0x42);
1669 1670
	if (gspca_dev->usb_err < 0)
		return;
1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681
	if (val == 0x7628) {			/* soi768 */
		sd->sensor = SENSOR_SOI768;
/*fixme: only valid for 0c45:613e?*/
		gspca_dev->cam.input_flags =
				V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
		PDEBUG(D_PROBE, "Sensor soi768");
		return;
	}
	PDEBUG(D_PROBE, "Sensor ov%04x", val);
}

1682 1683 1684
static void ov7648_probe(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
1685
	u16 val;
1686 1687 1688 1689 1690 1691

	/* check ov76xx */
	reg_w1(gspca_dev, 0x17, 0x62);
	reg_w1(gspca_dev, 0x01, 0x08);
	sd->i2c_addr = 0x21;
	i2c_r(gspca_dev, 0x0a, 2);
1692
	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1693 1694
	reg_w1(gspca_dev, 0x01, 0x29);
	reg_w1(gspca_dev, 0x17, 0x42);
1695 1696 1697 1698
	if ((val & 0xff00) == 0x7600) {		/* ov76xx */
		PDEBUG(D_PROBE, "Sensor ov%04x", val);
		return;
	}
1699 1700 1701 1702 1703 1704

	/* check po1030 */
	reg_w1(gspca_dev, 0x17, 0x62);
	reg_w1(gspca_dev, 0x01, 0x08);
	sd->i2c_addr = 0x6e;
	i2c_r(gspca_dev, 0x00, 2);
1705 1706 1707
	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
	reg_w1(gspca_dev, 0x01, 0x29);
	reg_w1(gspca_dev, 0x17, 0x42);
1708 1709
	if (gspca_dev->usb_err < 0)
		return;
1710
	if (val == 0x1030) {			/* po1030 */
1711 1712 1713 1714
		PDEBUG(D_PROBE, "Sensor po1030");
		sd->sensor = SENSOR_PO1030;
		return;
	}
1715
	err("Unknown sensor %04x", val);
1716 1717
}

1718 1719 1720 1721
/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
static void po2030n_probe(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
1722
	u16 val;
1723 1724 1725 1726 1727 1728 1729

	/* check gc0307 */
	reg_w1(gspca_dev, 0x17, 0x62);
	reg_w1(gspca_dev, 0x01, 0x08);
	reg_w1(gspca_dev, 0x02, 0x22);
	sd->i2c_addr = 0x21;
	i2c_r(gspca_dev, 0x00, 1);
1730
	val = gspca_dev->usb_buf[4];
1731 1732
	reg_w1(gspca_dev, 0x01, 0x29);		/* reset */
	reg_w1(gspca_dev, 0x17, 0x42);
1733
	if (val == 0x99) {			/* gc0307 (?) */
1734 1735 1736 1737 1738 1739 1740 1741 1742 1743
		PDEBUG(D_PROBE, "Sensor gc0307");
		sd->sensor = SENSOR_GC0307;
		return;
	}

	/* check po2030n */
	reg_w1(gspca_dev, 0x17, 0x62);
	reg_w1(gspca_dev, 0x01, 0x0a);
	sd->i2c_addr = 0x6e;
	i2c_r(gspca_dev, 0x00, 2);
1744
	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1745 1746
	reg_w1(gspca_dev, 0x01, 0x29);
	reg_w1(gspca_dev, 0x17, 0x42);
1747 1748
	if (gspca_dev->usb_err < 0)
		return;
1749
	if (val == 0x2030) {
1750 1751
		PDEBUG(D_PROBE, "Sensor po2030n");
/*		sd->sensor = SENSOR_PO2030N; */
1752
	} else {
1753
		err("Unknown sensor ID %04x", val);
1754
	}
1755 1756
}

1757 1758 1759 1760 1761 1762 1763
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
			const struct usb_device_id *id)
{
	struct sd *sd = (struct sd *) gspca_dev;
	struct cam *cam;

1764
	sd->bridge = id->driver_info >> 16;
1765 1766
	sd->sensor = id->driver_info >> 8;
	sd->flags = id->driver_info;
1767

1768
	cam = &gspca_dev->cam;
1769 1770 1771 1772 1773 1774 1775
	if (sd->sensor == SENSOR_ADCM1700) {
		cam->cam_mode = cif_mode;
		cam->nmodes = ARRAY_SIZE(cif_mode);
	} else {
		cam->cam_mode = vga_mode;
		cam->nmodes = ARRAY_SIZE(vga_mode);
	}
1776
	cam->npkt = 24;			/* 24 packets per ISOC message */
1777
	cam->ctrls = sd->ctrls;
1778

1779
	sd->ag_cnt = -1;
1780
	sd->quality = QUALITY_DEF;
1781

1782 1783
	INIT_WORK(&sd->work, qual_upd);

1784 1785 1786
	return 0;
}

1787 1788
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
1789 1790
{
	struct sd *sd = (struct sd *) gspca_dev;
1791
	const u8 *sn9c1xx;
1792
	u8 regGpio[] = { 0x29, 0x70 };		/* no audio */
1793
	u8 regF1;
1794

1795
	/* setup a selector by bridge */
1796
	reg_w1(gspca_dev, 0xf1, 0x01);
1797
	reg_r(gspca_dev, 0x00, 1);
1798
	reg_w1(gspca_dev, 0xf1, 0x00);
1799
	reg_r(gspca_dev, 0x00, 1);		/* get sonix chip id */
1800
	regF1 = gspca_dev->usb_buf[0];
1801 1802
	if (gspca_dev->usb_err < 0)
		return gspca_dev->usb_err;
1803
	PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
1804 1805
	if (gspca_dev->audio)
		regGpio[1] |= 0x04;		/* with audio */
1806 1807
	switch (sd->bridge) {
	case BRIDGE_SN9C102P:
1808
	case BRIDGE_SN9C105:
1809 1810
		if (regF1 != 0x11)
			return -ENODEV;
1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835
		break;
	default:
/*	case BRIDGE_SN9C110: */
/*	case BRIDGE_SN9C120: */
		if (regF1 != 0x12)
			return -ENODEV;
	}

	switch (sd->sensor) {
	case SENSOR_MI0360:
		mi0360_probe(gspca_dev);
		break;
	case SENSOR_OV7630:
		ov7630_probe(gspca_dev);
		break;
	case SENSOR_OV7648:
		ov7648_probe(gspca_dev);
		break;
	case SENSOR_PO2030N:
		po2030n_probe(gspca_dev);
		break;
	}

	switch (sd->bridge) {
	case BRIDGE_SN9C102P:
1836
		reg_w1(gspca_dev, 0x02, regGpio[1]);
1837
		break;
1838
	default:
1839
		reg_w(gspca_dev, 0x01, regGpio, 2);
1840 1841 1842
		break;
	}

1843 1844 1845
	if (sd->sensor == SENSOR_OM6802)
		sd->ctrls[SHARPNESS].def = 0x10;

1846 1847 1848
	/* Note we do not disable the sensor clock here (power saving mode),
	   as that also disables the button on the cam. */
	reg_w1(gspca_dev, 0xf1, 0x00);
1849

1850 1851 1852 1853
	/* set the i2c address */
	sn9c1xx = sn_tb[sd->sensor];
	sd->i2c_addr = sn9c1xx[9];

1854
	gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
1855 1856
	if (!(sd->flags & F_ILLUM))
		gspca_dev->ctrl_dis |= (1 << ILLUM);
1857

1858
	return gspca_dev->usb_err;
1859 1860
}

1861 1862
static u32 setexposure(struct gspca_dev *gspca_dev,
			u32 expo)
1863 1864 1865 1866
{
	struct sd *sd = (struct sd *) gspca_dev;

	switch (sd->sensor) {
1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
	case SENSOR_GC0307: {
		int a, b;

		/* expo = 0..255 -> a = 19..43 */
		a = 19 + expo * 25 / 256;
		i2c_w1(gspca_dev, 0x68, a);
		a -= 12;
		b = a * a * 4;			/* heuristic */
		i2c_w1(gspca_dev, 0x03, b >> 8);
		i2c_w1(gspca_dev, 0x04, b);
		break;
	    }
1879
	case SENSOR_HV7131R: {
1880
		u8 Expodoit[] =
1881
			{ 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };
1882 1883 1884 1885

		Expodoit[3] = expo >> 16;
		Expodoit[4] = expo >> 8;
		Expodoit[5] = expo;
1886
		i2c_w8(gspca_dev, Expodoit);
1887 1888
		break;
	    }
1889 1890
	case SENSOR_MI0360:
	case SENSOR_MI0360B: {
1891
		u8 expoMi[] =		/* exposure 0x0635 -> 4 fp/s 0x10 */
1892
			{ 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };
1893 1894 1895 1896
		static const u8 doit[] =		/* update sensor */
			{ 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
		static const u8 sensorgo[] =		/* sensor on */
			{ 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1897 1898 1899 1900 1901 1902 1903

		if (expo > 0x0635)
			expo = 0x0635;
		else if (expo < 0x0001)
			expo = 0x0001;
		expoMi[3] = expo >> 8;
		expoMi[4] = expo;
1904 1905 1906
		i2c_w8(gspca_dev, expoMi);
		i2c_w8(gspca_dev, doit);
		i2c_w8(gspca_dev, sensorgo);
1907 1908 1909
		break;
	    }
	case SENSOR_MO4000: {
1910
		u8 expoMof[] =
1911
			{ 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };
1912
		u8 expoMo10[] =
1913
			{ 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };
1914 1915
		static const u8 gainMo[] =
			{ 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1916 1917 1918 1919 1920 1921

		if (expo > 0x1fff)
			expo = 0x1fff;
		else if (expo < 0x0001)
			expo = 0x0001;
		expoMof[3] = (expo & 0x03fc) >> 2;
1922
		i2c_w8(gspca_dev, expoMof);
1923 1924
		expoMo10[3] = ((expo & 0x1c00) >> 10)
				| ((expo & 0x0003) << 4);
1925 1926
		i2c_w8(gspca_dev, expoMo10);
		i2c_w8(gspca_dev, gainMo);
1927
		PDEBUG(D_FRAM, "set exposure %d",
1928 1929 1930 1931 1932
			((expoMo10[3] & 0x07) << 10)
			| (expoMof[3] << 2)
			| ((expoMo10[3] & 0x30) >> 4));
		break;
	    }
1933 1934 1935 1936
	case SENSOR_MT9V111: {
		u8 expo_c1[] =
			{ 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };

1937 1938 1939 1940
		if (expo > 0x0390)
			expo = 0x0390;
		else if (expo < 0x0060)
			expo = 0x0060;
1941 1942 1943 1944 1945
		expo_c1[3] = expo >> 8;
		expo_c1[4] = expo;
		i2c_w8(gspca_dev, expo_c1);
		break;
	    }
1946
	case SENSOR_OM6802: {
1947
		u8 gainOm[] =
1948
			{ 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1949
				/* preset AGC - works when AutoExpo = off */
1950 1951 1952 1953 1954 1955 1956

		if (expo > 0x03ff)
			expo = 0x03ff;
		 if (expo < 0x0001)
			expo = 0x0001;
		gainOm[3] = expo >> 2;
		i2c_w8(gspca_dev, gainOm);
1957
		reg_w1(gspca_dev, 0x96, expo >> 5);
1958
		PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);
1959 1960
		break;
	    }
1961 1962 1963 1964 1965 1966 1967 1968
	}
	return expo;
}

static void setbrightness(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
	unsigned int expo;
1969
	int brightness;
1970
	u8 k2;
1971

1972 1973
	brightness = sd->ctrls[BRIGHTNESS].val;
	k2 = (brightness - 0x80) >> 2;
1974
	switch (sd->sensor) {
1975
	case SENSOR_ADCM1700:
1976 1977 1978
		if (k2 > 0x1f)
			k2 = 0;		/* only positive Y offset */
		break;
1979
	case SENSOR_HV7131R:
1980
		expo = brightness << 12;
1981 1982 1983 1984 1985 1986 1987 1988
		if (expo > 0x002dc6c0)
			expo = 0x002dc6c0;
		else if (expo < 0x02a0)
			expo = 0x02a0;
		sd->exposure = setexposure(gspca_dev, expo);
		break;
	case SENSOR_MI0360:
	case SENSOR_MO4000:
1989
		expo = brightness << 4;
1990 1991
		sd->exposure = setexposure(gspca_dev, expo);
		break;
1992
	case SENSOR_MI0360B:
1993
		expo = brightness << 2;
1994 1995
		sd->exposure = setexposure(gspca_dev, expo);
		break;
1996
	case SENSOR_GC0307:
1997
		expo = brightness;
1998
		sd->exposure = setexposure(gspca_dev, expo);
1999
		return;			/* don't set the Y offset */
2000 2001 2002 2003
	case SENSOR_MT9V111:
		expo = brightness << 2;
		sd->exposure = setexposure(gspca_dev, expo);
		return;			/* don't set the Y offset */
2004
	case SENSOR_OM6802:
2005
		expo = brightness << 2;
2006
		sd->exposure = setexposure(gspca_dev, expo);
2007
		k2 = brightness >> 3;
2008
		break;
2009 2010
	}

2011
	reg_w1(gspca_dev, 0x96, k2);	/* color matrix Y offset */
2012 2013 2014 2015 2016
}

static void setcontrast(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
2017 2018
	u8 k2;
	u8 contrast[6];
2019

2020 2021
	k2 = sd->ctrls[CONTRAST].val * 0x30 / (CONTRAST_MAX + 1)
				+ 0x10;		/* 10..40 */
2022
	contrast[0] = (k2 + 1) / 2;		/* red */
2023
	contrast[1] = 0;
2024
	contrast[2] = k2;			/* green */
2025
	contrast[3] = 0;
2026
	contrast[4] = (k2 + 1) / 5;		/* blue */
2027 2028
	contrast[5] = 0;
	reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
2029 2030 2031 2032 2033
}

static void setcolors(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
2034
	int i, v, colors;
2035
	const s16 *uv;
2036
	u8 reg8a[12];			/* U & V gains */
2037
	static const s16 uv_com[6] = {	/* same as reg84 in signed decimal */
2038 2039 2040
		-24, -38, 64,		/* UR UG UB */
		 62, -51, -9		/* VR VG VB */
	};
2041 2042 2043 2044
	static const s16 uv_mi0360b[6] = {
		-20, -38, 64,		/* UR UG UB */
		 60, -51, -9		/* VR VG VB */
	};
2045

2046
	colors = sd->ctrls[COLORS].val;
2047 2048 2049 2050
	if (sd->sensor == SENSOR_MI0360B)
		uv = uv_mi0360b;
	else
		uv = uv_com;
2051
	for (i = 0; i < 6; i++) {
2052
		v = uv[i] * colors / COLORS_DEF;
2053 2054
		reg8a[i * 2] = v;
		reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
2055
	}
2056
	reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
2057 2058 2059 2060 2061 2062
}

static void setredblue(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

2063
	reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
2064
/*	reg_w1(gspca_dev, 0x07, 32); */
2065
	reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
2066 2067
}

2068 2069 2070
static void setgamma(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
2071
	int i, val;
2072
	u8 gamma[17];
2073
	const u8 *gamma_base;
2074 2075 2076 2077 2078
	static const u8 delta[17] = {
		0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
		0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
	};

2079
	switch (sd->sensor) {
2080 2081 2082
	case SENSOR_ADCM1700:
		gamma_base = gamma_spec_0;
		break;
2083
	case SENSOR_HV7131R:
2084
	case SENSOR_MI0360B:
2085 2086 2087
	case SENSOR_MT9V111:
		gamma_base = gamma_spec_1;
		break;
2088
	case SENSOR_GC0307:
2089 2090
		gamma_base = gamma_spec_2;
		break;
2091 2092 2093
	case SENSOR_SP80708:
		gamma_base = gamma_spec_3;
		break;
2094 2095 2096 2097
	default:
		gamma_base = gamma_def;
		break;
	}
2098

2099
	val = sd->ctrls[GAMMA].val;
2100
	for (i = 0; i < sizeof gamma; i++)
2101
		gamma[i] = gamma_base[i]
2102
			+ delta[i] * (val - GAMMA_DEF) / 32;
2103 2104 2105
	reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
}

2106 2107 2108 2109
static void setautogain(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

2110
	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
2111
		return;
2112 2113 2114 2115 2116 2117 2118 2119 2120
	switch (sd->sensor) {
	case SENSOR_OV7630:
	case SENSOR_OV7648: {
		u8 comb;

		if (sd->sensor == SENSOR_OV7630)
			comb = 0xc0;
		else
			comb = 0xa0;
2121
		if (sd->ctrls[AUTOGAIN].val)
2122
			comb |= 0x03;
2123 2124 2125 2126
		i2c_w1(&sd->gspca_dev, 0x13, comb);
		return;
	    }
	}
2127
	if (sd->ctrls[AUTOGAIN].val)
2128 2129 2130
		sd->ag_cnt = AG_CNT_START;
	else
		sd->ag_cnt = -1;
2131 2132
}

2133
static void sethvflip(struct gspca_dev *gspca_dev)
2134
{
2135
	struct sd *sd = (struct sd *) gspca_dev;
2136 2137
	u8 comn;

2138 2139 2140
	switch (sd->sensor) {
	case SENSOR_HV7131R:
		comn = 0x18;			/* clkdiv = 1, ablcen = 1 */
2141
		if (sd->ctrls[VFLIP].val)
2142
			comn |= 0x01;
2143
		i2c_w1(gspca_dev, 0x01, comn);	/* sctra */
2144 2145
		break;
	case SENSOR_OV7630:
2146
		comn = 0x02;
2147
		if (!sd->ctrls[VFLIP].val)
2148
			comn |= 0x80;
2149
		i2c_w1(gspca_dev, 0x75, comn);
2150
		break;
2151
	case SENSOR_OV7648:
2152
		comn = 0x06;
2153
		if (sd->ctrls[VFLIP].val)
2154
			comn |= 0x80;
2155
		i2c_w1(gspca_dev, 0x75, comn);
2156
		break;
2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172
	case SENSOR_PO2030N:
		/* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)
		 * (reset value: 0x0A)
		 * bit7: HM: Horizontal Mirror: 0: disable, 1: enable
		 * bit6: VM: Vertical Mirror: 0: disable, 1: enable
		 * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical
		 * bit4: FT: Single Frame Transfer: 0: disable, 1: enable
		 * bit3-0: X
		 */
		comn = 0x0a;
		if (sd->ctrls[HFLIP].val)
			comn |= 0x80;
		if (sd->ctrls[VFLIP].val)
			comn |= 0x40;
		i2c_w1(&sd->gspca_dev, 0x1e, comn);
		break;
2173
	}
2174 2175
}

2176
static void setsharpness(struct gspca_dev *gspca_dev)
2177
{
2178 2179 2180
	struct sd *sd = (struct sd *) gspca_dev;

	reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);
2181 2182
}

2183
static void setillum(struct gspca_dev *gspca_dev)
2184
{
2185 2186
	struct sd *sd = (struct sd *) gspca_dev;

2187
	if (gspca_dev->ctrl_dis & (1 << ILLUM))
2188
		return;
2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204
	switch (sd->sensor) {
	case SENSOR_ADCM1700:
		reg_w1(gspca_dev, 0x02,				/* gpio */
			sd->ctrls[ILLUM].val ? 0x64 : 0x60);
		break;
	case SENSOR_MT9V111:
		if (starcam)
			reg_w1(gspca_dev, 0x02,
				sd->ctrls[ILLUM].val ?
						0x55 : 0x54);	/* 370i */
		else
			reg_w1(gspca_dev, 0x02,
				sd->ctrls[ILLUM].val ?
						0x66 : 0x64);	/* Clip */
		break;
	}
2205 2206
}

2207 2208 2209 2210
static void setfreq(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

2211
	if (gspca_dev->ctrl_dis & (1 << FREQ))
2212
		return;
2213
	if (sd->sensor == SENSOR_OV7660) {
2214 2215
		u8 com8;

2216
		com8 = 0xdf;		/* auto gain/wb/expo */
2217
		switch (sd->ctrls[FREQ].val) {
2218
		case 0: /* Banding filter disabled */
2219
			i2c_w1(gspca_dev, 0x13, com8 | 0x20);
2220 2221
			break;
		case 1: /* 50 hz */
2222
			i2c_w1(gspca_dev, 0x13, com8);
2223 2224 2225
			i2c_w1(gspca_dev, 0x3b, 0x0a);
			break;
		case 2: /* 60 hz */
2226
			i2c_w1(gspca_dev, 0x13, com8);
2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244
			i2c_w1(gspca_dev, 0x3b, 0x02);
			break;
		}
	} else {
		u8 reg2a = 0, reg2b = 0, reg2d = 0;

		/* Get reg2a / reg2d base values */
		switch (sd->sensor) {
		case SENSOR_OV7630:
			reg2a = 0x08;
			reg2d = 0x01;
			break;
		case SENSOR_OV7648:
			reg2a = 0x11;
			reg2d = 0x81;
			break;
		}

2245
		switch (sd->ctrls[FREQ].val) {
2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263
		case 0: /* Banding filter disabled */
			break;
		case 1: /* 50 hz (filter on and framerate adj) */
			reg2a |= 0x80;
			reg2b = 0xac;
			reg2d |= 0x04;
			break;
		case 2: /* 60 hz (filter on, no framerate adj) */
			reg2a |= 0x80;
			reg2d |= 0x04;
			break;
		}
		i2c_w1(gspca_dev, 0x2a, reg2a);
		i2c_w1(gspca_dev, 0x2b, reg2b);
		i2c_w1(gspca_dev, 0x2d, reg2d);
	}
}

2264 2265 2266 2267
static void setjpegqual(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

2268
	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2269 2270 2271
#if USB_BUF_SZ < 64
#error "No room enough in usb_buf for quantization table"
#endif
2272
	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2273 2274 2275 2276 2277 2278 2279
	usb_control_msg(gspca_dev->dev,
			usb_sndctrlpipe(gspca_dev->dev, 0),
			0x08,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
			0x0100, 0,
			gspca_dev->usb_buf, 64,
			500);
2280
	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292
	usb_control_msg(gspca_dev->dev,
			usb_sndctrlpipe(gspca_dev->dev, 0),
			0x08,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
			0x0140, 0,
			gspca_dev->usb_buf, 64,
			500);

	sd->reg18 ^= 0x40;
	reg_w1(gspca_dev, 0x18, sd->reg18);
}

2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305
/* JPEG quality update */
/* This function is executed from a work queue. */
static void qual_upd(struct work_struct *work)
{
	struct sd *sd = container_of(work, struct sd, work);
	struct gspca_dev *gspca_dev = &sd->gspca_dev;

	mutex_lock(&gspca_dev->usb_lock);
	PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
	setjpegqual(gspca_dev);
	mutex_unlock(&gspca_dev->usb_lock);
}

2306
/* -- start the camera -- */
2307
static int sd_start(struct gspca_dev *gspca_dev)
2308 2309 2310
{
	struct sd *sd = (struct sd *) gspca_dev;
	int i;
2311
	u8 reg01, reg17;
2312
	u8 reg0102[2];
2313
	const u8 *sn9c1xx;
2314
	const u8 (*init)[8];
2315
	const u8 *reg9a;
2316
	int mode;
2317 2318 2319 2320 2321
	static const u8 reg9a_def[] =
		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
	static const u8 reg9a_spec[] =
		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
	static const u8 regd4[] = {0x60, 0x00, 0x00};
2322 2323
	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
2324 2325
	static const u8 CA_adcm1700[] =
				{ 0x14, 0xec, 0x0a, 0xf6 };
2326 2327
	static const u8 CA_po2030n[] =
				{ 0x1e, 0xe2, 0x14, 0xec };
2328
	static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
2329 2330
	static const u8 CE_gc0307[] =
				{ 0x32, 0xce, 0x2d, 0xd3 };
2331
	static const u8 CE_ov76xx[] =
2332
				{ 0x32, 0xdd, 0x32, 0xdd };
2333 2334
	static const u8 CE_po2030n[] =
				{ 0x14, 0xe7, 0x1e, 0xdd };
2335

2336 2337 2338 2339
	/* create the JPEG header */
	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
			0x21);		/* JPEG 422 */

2340 2341
	/* initialize the bridge */
	sn9c1xx = sn_tb[sd->sensor];
2342 2343 2344

	/* sensor clock already enabled in sd_init */
	/* reg_w1(gspca_dev, 0xf1, 0x00); */
2345
	reg01 = sn9c1xx[1];
2346
	if (sd->flags & F_PDN_INV)
2347 2348
		reg01 ^= S_PDN_INV;		/* power down inverted */
	reg_w1(gspca_dev, 0x01, reg01);
2349 2350

	/* configure gpio */
2351
	reg0102[0] = reg01;
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376
	reg0102[1] = sn9c1xx[2];
	if (gspca_dev->audio)
		reg0102[1] |= 0x04;	/* keep the audio connection */
	reg_w(gspca_dev, 0x01, reg0102, 2);
	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
	switch (sd->sensor) {
	case SENSOR_GC0307:
	case SENSOR_OV7660:
	case SENSOR_PO1030:
	case SENSOR_PO2030N:
	case SENSOR_SOI768:
	case SENSOR_SP80708:
		reg9a = reg9a_spec;
		break;
	default:
		reg9a = reg9a_def;
		break;
	}
	reg_w(gspca_dev, 0x9a, reg9a, 6);

	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);

	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);

2377
	reg17 = sn9c1xx[0x17];
2378 2379
	switch (sd->sensor) {
	case SENSOR_GC0307:
2380
		msleep(50);		/*fixme: is it useful? */
2381 2382 2383 2384
		break;
	case SENSOR_OM6802:
		msleep(10);
		reg_w1(gspca_dev, 0x02, 0x73);
2385 2386
		reg17 |= SEN_CLK_EN;
		reg_w1(gspca_dev, 0x17, reg17);
2387 2388
		reg_w1(gspca_dev, 0x01, 0x22);
		msleep(100);
2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407
		reg01 = SCL_SEL_OD | S_PDN_INV;
		reg17 &= MCK_SIZE_MASK;
		reg17 |= 0x04;		/* clock / 4 */
		break;
	}
	reg01 |= SYS_SEL_48M;
	reg_w1(gspca_dev, 0x01, reg01);
	reg17 |= SEN_CLK_EN;
	reg_w1(gspca_dev, 0x17, reg17);
	reg01 &= ~S_PWR_DN;		/* sensor power on */
	reg_w1(gspca_dev, 0x01, reg01);
	reg01 &= ~SYS_SEL_48M;
	reg_w1(gspca_dev, 0x01, reg01);

	switch (sd->sensor) {
	case SENSOR_HV7131R:
		hv7131r_probe(gspca_dev);	/*fixme: is it useful? */
		break;
	case SENSOR_OM6802:
2408
		msleep(10);
2409
		reg_w1(gspca_dev, 0x01, reg01);
2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420
		i2c_w8(gspca_dev, om6802_init0[0]);
		i2c_w8(gspca_dev, om6802_init0[1]);
		msleep(15);
		reg_w1(gspca_dev, 0x02, 0x71);
		msleep(150);
		break;
	case SENSOR_SP80708:
		msleep(100);
		reg_w1(gspca_dev, 0x02, 0x62);
		break;
	}
2421

2422 2423 2424
	/* initialize the sensor */
	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);

2425 2426 2427 2428 2429
	reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
	reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
	reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
	reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
2430
	if (sd->sensor == SENSOR_ADCM1700) {
2431 2432
		reg_w1(gspca_dev, 0xd2, 0x3a);	/* AE_H_SIZE = 116 */
		reg_w1(gspca_dev, 0xd3, 0x30);	/* AE_V_SIZE = 96 */
2433
	} else {
2434 2435
		reg_w1(gspca_dev, 0xd2, 0x6a);	/* AE_H_SIZE = 212 */
		reg_w1(gspca_dev, 0xd3, 0x50);	/* AE_V_SIZE = 160 */
2436
	}
2437 2438
	reg_w1(gspca_dev, 0xc6, 0x00);
	reg_w1(gspca_dev, 0xc7, 0x00);
2439
	if (sd->sensor == SENSOR_ADCM1700) {
2440 2441
		reg_w1(gspca_dev, 0xc8, 0x2c);	/* AW_H_STOP = 352 */
		reg_w1(gspca_dev, 0xc9, 0x24);	/* AW_V_STOP = 288 */
2442
	} else {
2443 2444
		reg_w1(gspca_dev, 0xc8, 0x50);	/* AW_H_STOP = 640 */
		reg_w1(gspca_dev, 0xc9, 0x3c);	/* AW_V_STOP = 480 */
2445
	}
2446
	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
2447
	switch (sd->sensor) {
2448 2449
	case SENSOR_OM6802:
/*	case SENSOR_OV7648:		* fixme: sometimes */
2450
		break;
2451
	default:
2452
		reg17 |= DEF_EN;
2453 2454
		break;
	}
2455
	reg_w1(gspca_dev, 0x17, reg17);
2456 2457 2458 2459

	reg_w1(gspca_dev, 0x05, 0x00);		/* red */
	reg_w1(gspca_dev, 0x07, 0x00);		/* green */
	reg_w1(gspca_dev, 0x06, 0x00);		/* blue */
2460
	reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
2461

2462 2463
	setgamma(gspca_dev);

2464
/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
2465 2466
	for (i = 0; i < 8; i++)
		reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
2467
	switch (sd->sensor) {
2468
	case SENSOR_ADCM1700:
2469 2470
	case SENSOR_OV7660:
	case SENSOR_SP80708:
2471 2472
		reg_w1(gspca_dev, 0x9a, 0x05);
		break;
2473
	case SENSOR_GC0307:
2474
	case SENSOR_MT9V111:
2475
	case SENSOR_MI0360B:
2476
		reg_w1(gspca_dev, 0x9a, 0x07);
2477
		break;
2478
	case SENSOR_OV7630:
2479 2480
	case SENSOR_OV7648:
		reg_w1(gspca_dev, 0x9a, 0x0a);
2481
		break;
2482
	case SENSOR_PO2030N:
2483
	case SENSOR_SOI768:
2484 2485
		reg_w1(gspca_dev, 0x9a, 0x06);
		break;
2486
	default:
2487
		reg_w1(gspca_dev, 0x9a, 0x08);
2488 2489
		break;
	}
2490
	setsharpness(gspca_dev);
2491

2492
	reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
2493 2494 2495
	reg_w1(gspca_dev, 0x05, 0x20);		/* red */
	reg_w1(gspca_dev, 0x07, 0x20);		/* green */
	reg_w1(gspca_dev, 0x06, 0x20);		/* blue */
2496

2497
	init = NULL;
2498
	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
2499 2500 2501
	reg01 |= SYS_SEL_48M | V_TX_EN;
	reg17 &= ~MCK_SIZE_MASK;
	reg17 |= 0x02;			/* clock / 2 */
2502
	switch (sd->sensor) {
2503 2504 2505
	case SENSOR_ADCM1700:
		init = adcm1700_sensor_param1;
		break;
2506 2507
	case SENSOR_GC0307:
		init = gc0307_sensor_param1;
2508 2509 2510 2511 2512 2513 2514 2515 2516
		break;
	case SENSOR_HV7131R:
	case SENSOR_MI0360:
		if (mode)
			reg01 |= SYS_SEL_48M;	/* 320x240: clk 48Mhz */
		else
			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */
		reg17 &= ~MCK_SIZE_MASK;
		reg17 |= 0x01;			/* clock / 1 */
2517
		break;
2518 2519 2520
	case SENSOR_MI0360B:
		init = mi0360b_sensor_param1;
		break;
2521
	case SENSOR_MO4000:
2522 2523 2524 2525
		if (mode) {			/* if 320x240 */
			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
			reg17 &= ~MCK_SIZE_MASK;
			reg17 |= 0x01;		/* clock / 1 */
2526 2527
		}
		break;
2528
	case SENSOR_MT9V111:
2529
		init = mt9v111_sensor_param1;
2530
		break;
2531
	case SENSOR_OM6802:
2532
		init = om6802_sensor_param1;
2533 2534
		if (!mode) {			/* if 640x480 */
			reg17 &= ~MCK_SIZE_MASK;
2535
			reg17 |= 0x04;		/* clock / 4 */
2536
		}
2537
		break;
2538
	case SENSOR_OV7630:
2539
		init = ov7630_sensor_param1;
2540
		break;
2541
	case SENSOR_OV7648:
2542
		init = ov7648_sensor_param1;
2543 2544
		reg17 &= ~MCK_SIZE_MASK;
		reg17 |= 0x01;			/* clock / 1 */
2545
		break;
2546
	case SENSOR_OV7660:
2547
		init = ov7660_sensor_param1;
2548
		break;
2549 2550 2551
	case SENSOR_PO1030:
		init = po1030_sensor_param1;
		break;
2552 2553 2554
	case SENSOR_PO2030N:
		init = po2030n_sensor_param1;
		break;
2555 2556 2557
	case SENSOR_SOI768:
		init = soi768_sensor_param1;
		break;
2558
	case SENSOR_SP80708:
2559
		init = sp80708_sensor_param1;
2560
		break;
2561
	}
2562 2563 2564 2565 2566 2567 2568

	/* more sensor initialization - param1 */
	if (init != NULL) {
		i2c_w_seq(gspca_dev, init);
/*		init = NULL; */
	}

2569
	reg_w(gspca_dev, 0xc0, C0, 6);
2570 2571 2572
	switch (sd->sensor) {
	case SENSOR_ADCM1700:
	case SENSOR_GC0307:
2573
	case SENSOR_SOI768:
2574
		reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
2575 2576 2577 2578 2579
		break;
	case SENSOR_PO2030N:
		reg_w(gspca_dev, 0xca, CA_po2030n, 4);
		break;
	default:
2580
		reg_w(gspca_dev, 0xca, CA, 4);
2581 2582
		break;
	}
2583
	switch (sd->sensor) {
2584
	case SENSOR_ADCM1700:
2585 2586
	case SENSOR_OV7630:
	case SENSOR_OV7648:
2587
	case SENSOR_OV7660:
2588
	case SENSOR_SOI768:
2589
		reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
2590
		break;
2591 2592 2593 2594 2595 2596
	case SENSOR_GC0307:
		reg_w(gspca_dev, 0xce, CE_gc0307, 4);
		break;
	case SENSOR_PO2030N:
		reg_w(gspca_dev, 0xce, CE_po2030n, 4);
		break;
2597
	default:
2598
		reg_w(gspca_dev, 0xce, CE, 4);
2599 2600 2601 2602 2603
					/* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
		break;
	}

	/* here change size mode 0 -> VGA; 1 -> CIF */
2604 2605 2606
	sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
	reg_w1(gspca_dev, 0x18, sd->reg18);
	setjpegqual(gspca_dev);
2607

2608
	reg_w1(gspca_dev, 0x17, reg17);
2609 2610 2611
	reg_w1(gspca_dev, 0x01, reg01);
	sd->reg01 = reg01;
	sd->reg17 = reg17;
2612

2613
	sethvflip(gspca_dev);
2614 2615
	setbrightness(gspca_dev);
	setcontrast(gspca_dev);
2616
	setcolors(gspca_dev);
2617
	setautogain(gspca_dev);
2618
	setfreq(gspca_dev);
2619 2620 2621 2622 2623

	sd->pktsz = sd->npkt = 0;
	sd->nchg = sd->short_mark = 0;
	sd->work_thread = create_singlethread_workqueue(MODULE_NAME);

2624
	return gspca_dev->usb_err;
2625 2626 2627 2628 2629
}

static void sd_stopN(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
2630
	static const u8 stophv7131[] =
2631
		{ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
2632
	static const u8 stopmi0360[] =
2633
		{ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
2634
	static const u8 stopov7648[] =
2635
		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
2636 2637
	static const u8 stopsoi768[] =
		{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
2638 2639
	u8 reg01;
	u8 reg17;
2640

2641 2642
	reg01 = sd->reg01;
	reg17 = sd->reg17 & ~SEN_CLK_EN;
2643
	switch (sd->sensor) {
2644
	case SENSOR_ADCM1700:
2645
	case SENSOR_GC0307:
2646 2647 2648 2649 2650 2651 2652
	case SENSOR_PO2030N:
	case SENSOR_SP80708:
		reg01 |= LED;
		reg_w1(gspca_dev, 0x01, reg01);
		reg01 &= ~(LED | V_TX_EN);
		reg_w1(gspca_dev, 0x01, reg01);
/*		reg_w1(gspca_dev, 0x02, 0x??);	 * LED off ? */
2653
		break;
2654
	case SENSOR_HV7131R:
2655 2656
		reg01 &= ~V_TX_EN;
		reg_w1(gspca_dev, 0x01, reg01);
2657
		i2c_w8(gspca_dev, stophv7131);
2658 2659
		break;
	case SENSOR_MI0360:
2660
	case SENSOR_MI0360B:
2661 2662 2663
		reg01 &= ~V_TX_EN;
		reg_w1(gspca_dev, 0x01, reg01);
/*		reg_w1(gspca_dev, 0x02, 0x40);	  * LED off ? */
2664
		i2c_w8(gspca_dev, stopmi0360);
2665
		break;
2666
	case SENSOR_MT9V111:
2667
	case SENSOR_OM6802:
2668
	case SENSOR_PO1030:
2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680
		reg01 &= ~V_TX_EN;
		reg_w1(gspca_dev, 0x01, reg01);
		break;
	case SENSOR_OV7630:
	case SENSOR_OV7648:
		reg01 &= ~V_TX_EN;
		reg_w1(gspca_dev, 0x01, reg01);
		i2c_w8(gspca_dev, stopov7648);
		break;
	case SENSOR_OV7660:
		reg01 &= ~V_TX_EN;
		reg_w1(gspca_dev, 0x01, reg01);
2681
		break;
2682 2683 2684
	case SENSOR_SOI768:
		i2c_w8(gspca_dev, stopsoi768);
		break;
2685
	}
2686 2687 2688 2689 2690 2691 2692 2693 2694 2695

	reg01 |= SCL_SEL_OD;
	reg_w1(gspca_dev, 0x01, reg01);
	reg01 |= S_PWR_DN;		/* sensor power down */
	reg_w1(gspca_dev, 0x01, reg01);
	reg_w1(gspca_dev, 0x17, reg17);
	reg01 &= ~SYS_SEL_48M;		/* clock 24MHz */
	reg_w1(gspca_dev, 0x01, reg01);
	reg01 |= LED;
	reg_w1(gspca_dev, 0x01, reg01);
2696 2697
	/* Don't disable sensor clock as that disables the button on the cam */
	/* reg_w1(gspca_dev, 0xf1, 0x01); */
2698 2699
}

2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713
/* called on streamoff with alt==0 and on disconnect */
/* the usb_lock is held at entry - restore on exit */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

	if (sd->work_thread != NULL) {
		mutex_unlock(&gspca_dev->usb_lock);
		destroy_workqueue(sd->work_thread);
		mutex_lock(&gspca_dev->usb_lock);
		sd->work_thread = NULL;
	}
}

2714
static void do_autogain(struct gspca_dev *gspca_dev)
2715 2716 2717
{
	struct sd *sd = (struct sd *) gspca_dev;
	int delta;
2718
	int expotimes;
2719 2720
	u8 luma_mean = 130;
	u8 luma_delta = 20;
2721

2722 2723 2724 2725 2726 2727 2728 2729 2730
	/* Thanks S., without your advice, autobright should not work :) */
	if (sd->ag_cnt < 0)
		return;
	if (--sd->ag_cnt >= 0)
		return;
	sd->ag_cnt = AG_CNT_START;

	delta = atomic_read(&sd->avg_lum);
	PDEBUG(D_FRAM, "mean lum %d", delta);
2731 2732 2733
	if (delta < luma_mean - luma_delta ||
	    delta > luma_mean + luma_delta) {
		switch (sd->sensor) {
2734 2735 2736 2737 2738 2739 2740 2741
		case SENSOR_GC0307:
			expotimes = sd->exposure;
			expotimes += (luma_mean - delta) >> 6;
			if (expotimes < 0)
				expotimes = 0;
			sd->exposure = setexposure(gspca_dev,
						   (unsigned int) expotimes);
			break;
2742 2743 2744 2745 2746 2747 2748 2749
		case SENSOR_HV7131R:
			expotimes = sd->exposure >> 8;
			expotimes += (luma_mean - delta) >> 4;
			if (expotimes < 0)
				expotimes = 0;
			sd->exposure = setexposure(gspca_dev,
					(unsigned int) (expotimes << 8));
			break;
2750
		case SENSOR_OM6802:
2751
		case SENSOR_MT9V111:
2752 2753 2754 2755 2756 2757 2758 2759
			expotimes = sd->exposure;
			expotimes += (luma_mean - delta) >> 2;
			if (expotimes < 0)
				expotimes = 0;
			sd->exposure = setexposure(gspca_dev,
						   (unsigned int) expotimes);
			setredblue(gspca_dev);
			break;
2760 2761 2762
		default:
/*		case SENSOR_MO4000: */
/*		case SENSOR_MI0360: */
2763
/*		case SENSOR_MI0360B: */
2764 2765 2766 2767 2768 2769
			expotimes = sd->exposure;
			expotimes += (luma_mean - delta) >> 6;
			if (expotimes < 0)
				expotimes = 0;
			sd->exposure = setexposure(gspca_dev,
						   (unsigned int) expotimes);
2770
			setredblue(gspca_dev);
2771 2772 2773 2774 2775
			break;
		}
	}
}

2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798
/* set the average luminosity from an isoc marker */
static void set_lum(struct sd *sd,
		    u8 *data)
{
	int avg_lum;

	/*	w0 w1 w2
	 *	w3 w4 w5
	 *	w6 w7 w8
	 */
	avg_lum = (data[27] << 8) + data[28]		/* w3 */

		+ (data[31] << 8) + data[32]		/* w5 */

		+ (data[23] << 8) + data[24]		/* w1 */

		+ (data[35] << 8) + data[36]		/* w7 */

		+ (data[29] << 10) + (data[30] << 2);	/* w4 * 4 */
	avg_lum >>= 10;
	atomic_set(&sd->avg_lum, avg_lum);
}

2799 2800
/* scan the URB packets */
/* This function is run at interrupt level. */
2801
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2802
			u8 *data,			/* isoc packet */
2803 2804 2805
			int len)			/* iso packet length */
{
	struct sd *sd = (struct sd *) gspca_dev;
2806
	int i, new_qual;
2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845

	/*
	 * A frame ends on the marker
	 *		ff ff 00 c4 c4 96 ..
	 * which is 62 bytes long and is followed by various information
	 * including statuses and luminosity.
	 *
	 * A marker may be splitted on two packets.
	 *
	 * The 6th byte of a marker contains the bits:
	 *	0x08: USB full
	 *	0xc0: frame sequence
	 * When the bit 'USB full' is set, the frame must be discarded;
	 * this is also the case when the 2 bytes before the marker are
	 * not the JPEG end of frame ('ff d9').
	 */

/*fixme: assumption about the following code:
 *	- there can be only one marker in a packet
 */

	/* skip the remaining bytes of a short marker */
	i = sd->short_mark;
	if (i != 0) {
		sd->short_mark = 0;
		if (i < 0	/* if 'ff' at end of previous packet */
		 && data[0] == 0xff
		 && data[1] == 0x00)
			goto marker_found;
		if (data[0] == 0xff && data[1] == 0xff) {
			i = 0;
			goto marker_found;
		}
		len -= i;
		if (len <= 0)
			return;
		data += i;
	}

2846 2847 2848 2849
	/* count the packets and their size */
	sd->npkt++;
	sd->pktsz += len;

2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868
	/* search backwards if there is a marker in the packet */
	for (i = len - 1; --i >= 0; ) {
		if (data[i] != 0xff) {
			i--;
			continue;
		}
		if (data[i + 1] == 0xff) {

			/* (there may be 'ff ff' inside a marker) */
			if (i + 2 >= len || data[i + 2] == 0x00)
				goto marker_found;
		}
	}

	/* no marker found */
	/* add the JPEG header if first fragment */
	if (data[len - 1] == 0xff)
		sd->short_mark = -1;
	if (gspca_dev->last_packet_type == LAST_PACKET)
2869 2870 2871
		gspca_frame_add(gspca_dev, FIRST_PACKET,
				sd->jpeg_hdr, JPEG_HDR_SZ);
	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2872 2873 2874
	return;

	/* marker found */
2875
	/* if some error, discard the frame and decrease the quality */
2876
marker_found:
2877
	new_qual = 0;
2878 2879 2880
	if (i > 2) {
		if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
			gspca_dev->last_packet_type = DISCARD_PACKET;
2881
			new_qual = -3;
2882 2883 2884 2885
		}
	} else if (i + 6 < len) {
		if (data[i + 6] & 0x08) {
			gspca_dev->last_packet_type = DISCARD_PACKET;
2886
			new_qual = -5;
2887 2888
		}
	}
2889

2890 2891
	gspca_frame_add(gspca_dev, LAST_PACKET, data, i);

2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922
	/* compute the filling rate and a new JPEG quality */
	if (new_qual == 0) {
		int r;

		r = (sd->pktsz * 100) /
			(sd->npkt *
				gspca_dev->urb[0]->iso_frame_desc[0].length);
		if (r >= 85)
			new_qual = -3;
		else if (r < 75)
			new_qual = 2;
	}
	if (new_qual != 0) {
		sd->nchg += new_qual;
		if (sd->nchg < -6 || sd->nchg >= 12) {
			sd->nchg = 0;
			new_qual += sd->quality;
			if (new_qual < QUALITY_MIN)
				new_qual = QUALITY_MIN;
			else if (new_qual > QUALITY_MAX)
				new_qual = QUALITY_MAX;
			if (new_qual != sd->quality) {
				sd->quality = new_qual;
				queue_work(sd->work_thread, &sd->work);
			}
		}
	} else {
		sd->nchg = 0;
	}
	sd->pktsz = sd->npkt = 0;

2923 2924 2925 2926
	/* if the marker is smaller than 62 bytes,
	 * memorize the number of bytes to skip in the next packet */
	if (i + 62 > len) {			/* no more usable data */
		sd->short_mark = i + 62 - len;
2927
		return;
2928
	}
2929
	if (sd->ag_cnt >= 0)
2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940
		set_lum(sd, data + i);

	/* if more data, start a new frame */
	i += 62;
	if (i < len) {
		data += i;
		len -= i;
		gspca_frame_add(gspca_dev, FIRST_PACKET,
				sd->jpeg_hdr, JPEG_HDR_SZ);
		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
	}
2941 2942
}

2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954
static int sd_get_jcomp(struct gspca_dev *gspca_dev,
			struct v4l2_jpegcompression *jcomp)
{
	struct sd *sd = (struct sd *) gspca_dev;

	memset(jcomp, 0, sizeof *jcomp);
	jcomp->quality = sd->quality;
	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
			| V4L2_JPEG_MARKER_DQT;
	return 0;
}

2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975
static int sd_querymenu(struct gspca_dev *gspca_dev,
			struct v4l2_querymenu *menu)
{
	switch (menu->id) {
	case V4L2_CID_POWER_LINE_FREQUENCY:
		switch (menu->index) {
		case 0:		/* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
			strcpy((char *) menu->name, "NoFliker");
			return 0;
		case 1:		/* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
			strcpy((char *) menu->name, "50 Hz");
			return 0;
		case 2:		/* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
			strcpy((char *) menu->name, "60 Hz");
			return 0;
		}
		break;
	}
	return -EINVAL;
}

2976
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994
static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
			u8 *data,		/* interrupt packet data */
			int len)		/* interrupt packet length */
{
	int ret = -EINVAL;

	if (len == 1 && data[0] == 1) {
		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
		input_sync(gspca_dev->input_dev);
		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
		input_sync(gspca_dev->input_dev);
		ret = 0;
	}

	return ret;
}
#endif

2995
/* sub-driver description */
2996
static const struct sd_desc sd_desc = {
2997 2998
	.name = MODULE_NAME,
	.ctrls = sd_ctrls,
2999
	.nctrls = NCTRLS,
3000
	.config = sd_config,
3001
	.init = sd_init,
3002 3003
	.start = sd_start,
	.stopN = sd_stopN,
3004
	.stop0 = sd_stop0,
3005
	.pkt_scan = sd_pkt_scan,
3006
	.dq_callback = do_autogain,
3007
	.get_jcomp = sd_get_jcomp,
3008
	.querymenu = sd_querymenu,
3009
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3010 3011
	.int_pkt_scan = sd_int_pkt_scan,
#endif
3012 3013 3014
};

/* -- module initialisation -- */
3015
#define BS(bridge, sensor) \
3016
	.driver_info = (BRIDGE_ ## bridge << 16) \
3017 3018 3019 3020 3021
			| (SENSOR_ ## sensor << 8)
#define BSF(bridge, sensor, flags) \
	.driver_info = (BRIDGE_ ## bridge << 16) \
			| (SENSOR_ ## sensor << 8) \
			| (flags)
3022
static const struct usb_device_id device_table[] = {
3023 3024
	{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
3025 3026
	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037
	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
	{USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},
	{USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},
/*	{USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */
	{USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},
/*	{USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */
/*	{USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
	{USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
/*	{USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
3038
	{USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
3039
						/* or MT9V111 */
3040 3041 3042
/*	{USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
/*	{USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
/*	{USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
3043
	{USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
3044 3045 3046
	{USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
/*	{USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
/*	{USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
3047
/*	{USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
3048 3049 3050 3051
	{USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
	{USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
	{USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
	{USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)},	/*sn9c128*/
3052
	{USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)},	/* /GC0305*/
3053 3054 3055 3056 3057 3058 3059 3060 3061
/*	{USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
	{USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)},	/*sn9c128*/
	{USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)},	/*sn9c128*/
	{USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)},	/*sn9c128*/
	{USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)},	/*sn9c128*/
/*	{USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */
/*	{USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */
/*	{USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */
	{USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)},	/*sn9c325?*/
3062
/*bw600.inf:*/
3063
	{USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)},	/*sn9c325?*/
3064
	{USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},
3065 3066 3067 3068
	{USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},
	{USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},
/*	{USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */
	{USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},
3069
						/* or MT9V111 / MI0360B */
3070 3071 3072 3073 3074 3075
/*	{USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
	{USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
	{USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
	{USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
	{USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
	{USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
3076
	{USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},	/*sn9c120b*/
3077
						/* or GC0305 / GC0307 */
3078 3079
	{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},	/*sn9c120b*/
	{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},	/*sn9c120b*/
3080
	{USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
3081
/*	{USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */	/*sn9c120b*/
3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098
	{}
};
MODULE_DEVICE_TABLE(usb, device_table);

/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
		    const struct usb_device_id *id)
{
	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
				THIS_MODULE);
}

static struct usb_driver sd_driver = {
	.name = MODULE_NAME,
	.id_table = device_table,
	.probe = sd_probe,
	.disconnect = gspca_disconnect,
3099 3100 3101 3102
#ifdef CONFIG_PM
	.suspend = gspca_suspend,
	.resume = gspca_resume,
#endif
3103 3104 3105 3106 3107
};

/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
3108
	return usb_register(&sd_driver);
3109 3110 3111 3112 3113 3114 3115 3116
}
static void __exit sd_mod_exit(void)
{
	usb_deregister(&sd_driver);
}

module_init(sd_mod_init);
module_exit(sd_mod_exit);
3117 3118 3119 3120

module_param(starcam, int, 0644);
MODULE_PARM_DESC(starcam,
	"StarCam model. 0: Clip, 1: 370i");