spca561.c revision d0848eb2864c0f1ef52d586cd33c68a103b0a2ac
16a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/*
26a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * Sunplus spca561 subdriver
36a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine *
46a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
56a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine *
66a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
76a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine *
86a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * This program is free software; you can redistribute it and/or modify
96a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * it under the terms of the GNU General Public License as published by
106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * the Free Software Foundation; either version 2 of the License, or
116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * any later version.
126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine *
136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * This program is distributed in the hope that it will be useful,
146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * but WITHOUT ANY WARRANTY; without even the implied warranty of
156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * GNU General Public License for more details.
176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine *
186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * You should have received a copy of the GNU General Public License
196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * along with this program; if not, write to the Free Software
206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine */
226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define MODULE_NAME "spca561"
246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#include "gspca.h"
266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_LICENSE("GPL");
306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* specific webcam descriptor */
326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestruct sd {
336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct gspca_dev gspca_dev;	/* !! must be the first item */
346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
357879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	__u16 exposure;			/* rev12a only */
360fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede#define EXPOSURE_MIN 1
37d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define EXPOSURE_DEF 700		/* == 10 fps */
38d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define EXPOSURE_MAX (2047 + 325)	/* see setexposure */
397879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
405b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 contrast;			/* rev72a only */
415b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define CONTRAST_MIN 0x00
425b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define CONTRAST_DEF 0x20
435b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define CONTRAST_MAX 0x3f
445b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine
457879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	__u8 brightness;		/* rev72a only */
467879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define BRIGHTNESS_MIN 0
475b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define BRIGHTNESS_DEF 0x20
485b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define BRIGHTNESS_MAX 0x3f
497879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
505b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 white;
513a1ea7050345734acc3a33b2b00a611b9b7bf640Jean-Francois Moine#define WHITE_MIN 1
527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define WHITE_DEF 0x40
537879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define WHITE_MAX 0x7f
547879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 autogain;
567879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define AUTOGAIN_MIN 0
577879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define AUTOGAIN_DEF 1
587879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define AUTOGAIN_MAX 1
597879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
607879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	__u8 gain;			/* rev12a only */
61d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define GAIN_MIN 0
62d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define GAIN_DEF 63
63d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define GAIN_MAX 255
646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
65d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine#define EXPO12A_DEF 3
66d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	__u8 expo12a;		/* expo/gain? for rev 12a */
67d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine
686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 chip_revision;
697879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define Rev012A 0
707879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define Rev072A 1
717879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	signed char ag_cnt;
736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define AG_CNT_START 13
746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
76cc611b8aef7a8a9a2e614f1bdf3e2b8f066c8c8dJean-Francois Moinestatic const struct v4l2_pix_format sif_012a_mode[] = {
77c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
78c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 160,
79c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 160 * 120,
80c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
81c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 3},
82c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
83c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 176,
84c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 176 * 144,
85c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
86c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 2},
87c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
88c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 320,
89c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 320 * 240 * 4 / 8,
90c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
91c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 1},
92c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
93c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 352,
94c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 352 * 288 * 4 / 8,
95c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
96c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 0},
976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
99cc611b8aef7a8a9a2e614f1bdf3e2b8f066c8c8dJean-Francois Moinestatic const struct v4l2_pix_format sif_072a_mode[] = {
100b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
101b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 160,
102b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 160 * 120,
103b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
104b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 3},
105b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
106b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 176,
107b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 176 * 144,
108b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
109b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 2},
110b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
111b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 320,
112b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 320 * 240,
113b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
114b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 1},
115b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
116b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 352,
117b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 352 * 288,
118b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
119b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 0},
120b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine};
121b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine
1226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/*
1236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * Initialization data
1246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * I'm not very sure how to split initialization from open data
1256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * chunks. For now, we'll consider everything as initialization
1266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine */
1276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* Frame packet header offsets for the spca561 */
1286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_SNAP 1
1296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_TYPE 2
1306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_COMPRESS 3
1316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_FRAMSEQ   4
1326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_GPIO 5
1336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_USBBUFF 6
1346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2GRAVE 7
1356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2RAVE 8
1366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2BAVE 9
1376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2GBAVE 10
1386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1GRAVE 11
1396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1RAVE 12
1406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1BAVE 13
1416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1GBAVE 14
1426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_FREQ 15
1436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_VSYNC 16
1446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_INDEX_I2C_BASE 0x8800
1456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_SNAPBIT 0x20
1466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_SNAPCTRL 0x40
1476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
1480dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_reset[][2] = {
1496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8114},	/* Software GPIO output data */
1506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8114},	/* Software GPIO output data */
1516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8112},	/* Some kind of reset */
1520dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{}
1530dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine};
1540dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const __u16 rev72a_init_data1[][2] = {
1556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0003, 0x8701},	/* PCLK clock delay adjustment */
1566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8703},	/* HSYNC from cmos inverted */
1576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0011, 0x8118},	/* Enable and conf sensor */
1586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8118},	/* Conf sensor */
1596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0092, 0x8804},	/* I know nothing about these */
1606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0010, 0x8802},	/* 0x88xx registers, so I won't */
161f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
162f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
1630dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_init_sensor1[][2] = {
1640dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0001, 0x000d},
1650dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0002, 0x0018},
1660dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0004, 0x0165},
1670dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0005, 0x0021},
1680dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0007, 0x00aa},
1690dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0020, 0x1504},
1700dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0039, 0x0002},
1710dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0035, 0x0010},
1720dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0009, 0x1049},
1730dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0028, 0x000b},
1740dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x003b, 0x000f},
1750dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x003c, 0x0000},
176f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
177f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
178f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moinestatic const __u16 rev72a_init_data2[][2] = {
1796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0018, 0x8601},	/* Pixel/line selection for color separation */
1806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8602},	/* Optical black level for user setting */
1816a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0060, 0x8604},	/* Optical black horizontal offset */
1826a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8605},	/* Optical black vertical offset */
1836a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8603},	/* Non-automatic optical black level */
1846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */
1856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x865f},	/* Vertical valid pixels window (x2) */
1866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00b0, 0x865d},	/* Horizontal valid pixels window (x2) */
1876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0090, 0x865e},	/* Vertical valid lines window (x2) */
1886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00e0, 0x8406},	/* Memory buffer threshold */
1896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8660},	/* Compensation memory stuff */
1906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8201},	/* Output address for r/w serial EEPROM */
1916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0008, 0x8200},	/* Clear valid bit for serial EEPROM */
1926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8200},	/* OprMode to be executed by hardware */
1930dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine/* from ms-win */
1940dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0000, 0x8611},	/* R offset for white balance */
1950dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x00fd, 0x8612},	/* Gr offset for white balance */
1960dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0003, 0x8613},	/* B offset for white balance */
1976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8614},	/* Gb offset for white balance */
1985b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/* from ms-win */
1995b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0035, 0x8651},	/* R gain for white balance */
2005b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0040, 0x8652},	/* Gr gain for white balance */
2015b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x005f, 0x8653},	/* B gain for white balance */
2025b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0040, 0x8654},	/* Gb gain for white balance */
2036a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8502},	/* Maximum average bit rate stuff */
2046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0011, 0x8802},
2050dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine
2066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0087, 0x8700},	/* Set master clock (96Mhz????) */
2076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0081, 0x8702},	/* Master clock output enable */
2086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8500},	/* Set image type (352x288 no compression) */
2106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* Originally was 0x0010 (352x288 compression) */
2116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */
2136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0003, 0x865c},	/* Vertical offset for valid lines */
214f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
215f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
2160dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_init_sensor2[][2] = {
2170dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0003, 0x0121},
2180dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0004, 0x0165},
2190dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0005, 0x002f},	/* blanking control column */
2200dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0006, 0x0000},	/* blanking mode row*/
2210dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x000a, 0x0002},
2220dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0009, 0x1061},	/* setexposure times && pixel clock
2236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				 * 0001 0 | 000 0110 0001 */
2240dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0035, 0x0014},
2256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
2276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/******************** QC Express etch2 stuff ********************/
229a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 Pb100_1map8300[][2] = {
2306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* reg, value */
2316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8320, 0x3304},
2326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8303, 0x0125},	/* image area */
2346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8304, 0x0169},
2356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8328, 0x000b},
2367879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{0x833c, 0x0001},		/*fixme: win:07*/
2376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2387879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{0x832f, 0x1904},		/*fixme: was 0419*/
2396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8307, 0x00aa},
2406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8301, 0x0003},
2416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8302, 0x000e},
2426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
244a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 Pb100_2map8300[][2] = {
2456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* reg, value */
2466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8339, 0x0000},
2476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8307, 0x00aa},
2486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
2506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
251a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 spca561_161rev12A_data1[][2] = {
2526c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x29, 0x8118},		/* white balance - was 21 */
2536c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x08, 0x8114},		/* white balance - was 01 */
2546c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x0e, 0x8112},		/* white balance - was 00 */
2556c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x00, 0x8102},		/* white balance - new */
2566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x92, 0x8804},
2576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x04, 0x8802},		/* windows uses 08 */
2586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
260a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 spca561_161rev12A_data2[][2] = {
2616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x21, 0x8118},
2626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x10, 0x8500},
2636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8601},
2646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8602},
2656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x04, 0x8501},
2666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x21, 0x8118},
2676a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8201},		/* windows uses 02 */
2696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x08, 0x8200},
2706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x01, 0x8200},
2716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8114},
2736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x01, 0x8114},		/* windows uses 00 */
2746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x90, 0x8604},
2766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8605},
2776a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xb0, 0x8603},
2786a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* sensor gains */
2806c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x07, 0x8601},		/* white balance - new */
2816c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x07, 0x8602},		/* white balance - new */
2826a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8610},		/* *red */
2836a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8611},		/* 3f   *green */
2846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8612},		/* green *blue */
2856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8613},		/* blue *green */
2866c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x43, 0x8614},		/* green *red - white balance - was 0x35 */
2876c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x40, 0x8615},		/* 40   *green - white balance - was 0x35 */
2886c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x71, 0x8616},		/* 7a   *blue - white balance - was 0x35 */
2896c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x40, 0x8617},		/* 40   *green - white balance - was 0x35 */
2906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0c, 0x8620},		/* 0c */
2926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xc8, 0x8631},		/* c8 */
2936a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xc8, 0x8634},		/* c8 */
2946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x23, 0x8635},		/* 23 */
2956a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x1f, 0x8636},		/* 1f */
2966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xdd, 0x8637},		/* dd */
2976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xe1, 0x8638},		/* e1 */
2986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x1d, 0x8639},		/* 1d */
2996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x21, 0x863a},		/* 21 */
3006a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xe3, 0x863b},		/* e3 */
3016a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xdf, 0x863c},		/* df */
3026a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xf0, 0x8505},
3036a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x32, 0x850a},
3047879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/*	{0x99, 0x8700},		 * - white balance - new (removed) */
3056a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
3066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
3076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
30835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
30935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
31035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int ret;
31135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
31235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
31335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			      0,		/* request */
31435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
31535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			      value, index, NULL, 0, 500);
31635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
31735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	if (ret < 0)
31835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		PDEBUG(D_ERR, "reg write: error %d", ret);
31935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
32035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
32135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void write_vector(struct gspca_dev *gspca_dev,
32235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			const __u16 data[][2])
3236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
32435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	struct usb_device *dev = gspca_dev->dev;
32535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int i;
3266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
32735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	i = 0;
32835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	while (data[i][1] != 0) {
32935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		reg_w_val(dev, data[i][1], data[i][0]);
3306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		i++;
3316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
3326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
33335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
33435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine/* read 'len' bytes to gspca_dev->usb_buf */
33535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void reg_r(struct gspca_dev *gspca_dev,
33635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		  __u16 index, __u16 length)
33735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
33835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	usb_control_msg(gspca_dev->dev,
33935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			usb_rcvctrlpipe(gspca_dev->dev, 0),
34035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* request */
34135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
34235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* value */
34335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			index, gspca_dev->usb_buf, length, 500);
34435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
34535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
34635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine/* write 'len' bytes from gspca_dev->usb_buf */
34735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void reg_w_buf(struct gspca_dev *gspca_dev,
34835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		      __u16 index, __u16 len)
34935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
35035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	usb_control_msg(gspca_dev->dev,
35135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			usb_sndctrlpipe(gspca_dev->dev, 0),
35235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* request */
35335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
35435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* value */
35535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			index, gspca_dev->usb_buf, len, 500);
35635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
35735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
35835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
35935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
36035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int retry = 60;
36135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
36235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8801, reg);
36335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8805, value);
36435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
36535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	do {
36635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		reg_r(gspca_dev, 0x8803, 1);
36735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		if (!gspca_dev->usb_buf[0])
36835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			return;
3690dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine		msleep(10);
37035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	} while (--retry);
37135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
37235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
37335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
37435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
37535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int retry = 60;
37635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	__u8 value;
37735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
37835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8804, 0x92);
37935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8801, reg);
38035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
38135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	do {
38235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		reg_r(gspca_dev, 0x8803, 1);
38335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		if (!gspca_dev->usb_buf[0]) {
38435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			reg_r(gspca_dev, 0x8800, 1);
38535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			value = gspca_dev->usb_buf[0];
38635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			reg_r(gspca_dev, 0x8805, 1);
38735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			return ((int) value << 8) | gspca_dev->usb_buf[0];
38835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		}
3890dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine		msleep(10);
39035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	} while (--retry);
39135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	return -1;
39235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
39335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
39435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void sensor_mapwrite(struct gspca_dev *gspca_dev,
39535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			    const __u16 (*sensormap)[2])
39635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
39735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	while ((*sensormap)[0]) {
39835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		gspca_dev->usb_buf[0] = (*sensormap)[1];
39935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
40035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		reg_w_buf(gspca_dev, (*sensormap)[0], 2);
40135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		sensormap++;
40235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	}
40335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
40435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
405f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moinestatic void write_sensor_72a(struct gspca_dev *gspca_dev,
406f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine			    const __u16 (*sensor)[2])
407f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine{
408f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	while ((*sensor)[0]) {
409f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine		i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
410f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine		sensor++;
411f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	}
412f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine}
413f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine
4146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void init_161rev12A(struct gspca_dev *gspca_dev)
4156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
4166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	write_vector(gspca_dev, spca561_161rev12A_data1);
4176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sensor_mapwrite(gspca_dev, Pb100_1map8300);
4187879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/*fixme: should be in sd_start*/
4196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	write_vector(gspca_dev, spca561_161rev12A_data2);
4206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sensor_mapwrite(gspca_dev, Pb100_2map8300);
4216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
4226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* this function is called at probe time */
4246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_config(struct gspca_dev *gspca_dev,
4256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		     const struct usb_device_id *id)
4266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
4276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
4286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct cam *cam;
4296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u16 vendor, product;
4306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 data1, data2;
4316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* Read frm global register the USB product and vendor IDs, just to
4336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	 * prove that we can communicate with the device.  This works, which
4346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	 * confirms at we are communicating properly and that the device
4356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	 * is a 561. */
436739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8104, 1);
437739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data1 = gspca_dev->usb_buf[0];
438739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8105, 1);
439739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data2 = gspca_dev->usb_buf[0];
4406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	vendor = (data2 << 8) | data1;
441739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8106, 1);
442739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data1 = gspca_dev->usb_buf[0];
443739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8107, 1);
444739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data2 = gspca_dev->usb_buf[0];
4456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	product = (data2 << 8) | data1;
4466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	if (vendor != id->idVendor || product != id->idProduct) {
4476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		PDEBUG(D_PROBE, "Bad vendor / product from device");
4486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return -EINVAL;
4496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
4509d64fdb15b1b9ce9144cfde4001e9194ccde42d1Jean-Francois Moine
4516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	cam = &gspca_dev->cam;
4526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	gspca_dev->nbalt = 7 + 1;	/* choose alternate 7 first */
4539d64fdb15b1b9ce9144cfde4001e9194ccde42d1Jean-Francois Moine
4549d64fdb15b1b9ce9144cfde4001e9194ccde42d1Jean-Francois Moine	sd->chip_revision = id->driver_info;
455b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	if (sd->chip_revision == Rev012A) {
456b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->cam_mode = sif_012a_mode;
457b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->nmodes = ARRAY_SIZE(sif_012a_mode);
458b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	} else {
459b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->cam_mode = sif_072a_mode;
460b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->nmodes = ARRAY_SIZE(sif_072a_mode);
461b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	}
4626c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	sd->brightness = BRIGHTNESS_DEF;
4636c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	sd->contrast = CONTRAST_DEF;
4646c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	sd->white = WHITE_DEF;
4657879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	sd->exposure = EXPOSURE_DEF;
4667879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	sd->autogain = AUTOGAIN_DEF;
4677879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	sd->gain = GAIN_DEF;
468d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	sd->expo12a = EXPO12A_DEF;
4696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
4706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
4716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
472012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine/* this function is called at probe and resume time */
473012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moinestatic int sd_init_12a(struct gspca_dev *gspca_dev)
4746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
4757879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	PDEBUG(D_STREAM, "Chip revision: 012a");
4767879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	init_161rev12A(gspca_dev);
4777879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
4787879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
479012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moinestatic int sd_init_72a(struct gspca_dev *gspca_dev)
4807879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
4817879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	PDEBUG(D_STREAM, "Chip revision: 072a");
4820dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_reset);
4830dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	msleep(200);
484f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_vector(gspca_dev, rev72a_init_data1);
485f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
486f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_vector(gspca_dev, rev72a_init_data2);
487f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
4880dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8112, 0x30);
4896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
4906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
4916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4925b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/* rev 72a only */
4935b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moinestatic void setbrightness(struct gspca_dev *gspca_dev)
4946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
4956a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
4966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct usb_device *dev = gspca_dev->dev;
4975b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 value;
4986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4995b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	value = sd->brightness;
5005b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine
5015b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	/* offsets for white balance */
5025b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(dev, 0x8611, value);		/* R */
5035b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(dev, 0x8612, value);		/* Gr */
5045b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(dev, 0x8613, value);		/* B */
5055b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(dev, 0x8614, value);		/* Gb */
5066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
5076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
5086c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moinestatic void setwhite(struct gspca_dev *gspca_dev)
5096c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine{
5106c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
5116c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	__u16 white;
5125b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 blue, red;
5135b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u16 reg;
5146c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
5157879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	/* try to emulate MS-win as possible */
5165b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	white = sd->white;
5175b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	red = 0x20 + white * 3 / 8;
5185b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	blue = 0x90 - white * 5 / 8;
5195b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	if (sd->chip_revision == Rev012A) {
5205b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		reg = 0x8614;
5215b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	} else {
5225b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		reg = 0x8651;
5235b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		red += sd->contrast - 0x20;
5245b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		blue += sd->contrast - 0x20;
5255b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	}
5265b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(gspca_dev->dev, reg, red);
5275b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(gspca_dev->dev, reg + 2, blue);
5285b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine}
5295b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine
5305b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moinestatic void setcontrast(struct gspca_dev *gspca_dev)
5315b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine{
5325b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
5335b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	struct usb_device *dev = gspca_dev->dev;
5345b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 value;
5355b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine
5365b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	if (sd->chip_revision != Rev072A)
5375b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		return;
5385b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	value = sd->contrast + 0x20;
5395b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine
5405b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	/* gains for white balance */
5415b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	setwhite(gspca_dev);
5425b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/*	reg_w_val(dev, 0x8651, value);		 * R - done by setwhite */
5435b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(dev, 0x8652, value);		/* Gr */
5445b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/*	reg_w_val(dev, 0x8653, value);		 * B - done by setwhite */
5455b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(dev, 0x8654, value);		/* Gb */
5467879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
5477879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
5487879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 12a only */
5497879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic void setexposure(struct gspca_dev *gspca_dev)
5507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
5517879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
552d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	int i, expo = 0;
5537879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
5540fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	/* Register 0x8309 controls exposure for the spca561,
5550fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   the basic exposure setting goes from 1-2047, where 1 is completely
5560fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   dark and 2047 is very bright. It not only influences exposure but
5570fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   also the framerate (to allow for longer exposure) from 1 - 300 it
5580fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   only raises the exposure time then from 300 - 600 it halves the
5590fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   framerate to be able to further raise the exposure time and for every
5600fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   300 more it halves the framerate again. This allows for a maximum
5610fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
5620fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
5630fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   configure a divider for the base framerate which us used at the
5640fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   exposure setting of 1-300. These bits configure the base framerate
5650fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   according to the following formula: fps = 60 / (value + 2) */
566d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
567d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	/* We choose to use the high bits setting the fixed framerate divisor
568d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   asap, as setting high basic exposure setting without the fixed
569d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   divider in combination with high gains makes the cam stop */
570d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	int table[] =  { 0, 450, 550, 625, EXPOSURE_MAX };
571d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
572d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
573d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede		if (sd->exposure <= table[i + 1]) {
574d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede			expo  = sd->exposure - table[i];
575d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede			if (i)
576d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede				expo += 300;
577d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede			expo |= i << 11;
578d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede			break;
579d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede		}
5800fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	}
581d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
58235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	gspca_dev->usb_buf[0] = expo;
58335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	gspca_dev->usb_buf[1] = expo >> 8;
58435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_buf(gspca_dev, 0x8309, 2);
5857879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
5867879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
5877879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 12a only */
5887879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic void setgain(struct gspca_dev *gspca_dev)
5897879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
5907879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
5917879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
592d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	/* gain reg low 6 bits  0-63 gain, bit 6 and 7, both double the
593d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   sensitivity when set, so 31 + one of them set == 63, and 15
594d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   with both of them set == 63 */
595d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	if (sd->gain < 64)
596d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede		gspca_dev->usb_buf[0] = sd->gain;
597d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	else if (sd->gain < 128)
598d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede		gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40;
599d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	else
600d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede		gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0;
601d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
60235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	gspca_dev->usb_buf[1] = 0;
60335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_buf(gspca_dev, 0x8335, 2);
6046c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine}
6056c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
606cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moinestatic void setautogain(struct gspca_dev *gspca_dev)
607cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine{
608cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
609cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine
610d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	if (sd->autogain)
611d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		sd->ag_cnt = AG_CNT_START;
612d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	else
613d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		sd->ag_cnt = -1;
614cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine}
615cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine
61672ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moinestatic int sd_start_12a(struct gspca_dev *gspca_dev)
6176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
6186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct usb_device *dev = gspca_dev->dev;
6196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	int mode;
6205b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	static const __u8 Reg8391[8] =
6215b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		{0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
6226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
623c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6247879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	if (mode <= 1) {
6257879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		/* Use compression on 320x240 and above */
6267879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		reg_w_val(dev, 0x8500, 0x10 | mode);
6277879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	} else {
6287879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		/* I couldn't get the compression to work below 320x240
6297879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		 * Fortunately at these resolutions the bandwidth
6307879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		 * is sufficient to push raw frames at ~20fps */
6317879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		reg_w_val(dev, 0x8500, mode);
6327879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	}		/* -- qq@kuku.eu.org */
63335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
6345b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	gspca_dev->usb_buf[0] = 0xaa;
6355b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	gspca_dev->usb_buf[1] = 0x00;
6365b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_buf(gspca_dev, 0x8307, 2);
6375b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	/* clock - lower 0x8X values lead to fps > 30 */
6385b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
6397879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine					/* 0x8f 0x85 0x27 clock */
6407879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
6417879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	reg_w_val(gspca_dev->dev, 0x850b, 0x03);
6425b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	memcpy(gspca_dev->usb_buf, Reg8391, 8);
6435b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_buf(gspca_dev, 0x8391, 8);
6445b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_buf(gspca_dev, 0x8390, 8);
6457879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	setwhite(gspca_dev);
646d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	setgain(gspca_dev);
6470fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	setexposure(gspca_dev);
64872ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moine	return 0;
6497879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
65072ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moinestatic int sd_start_72a(struct gspca_dev *gspca_dev)
6517879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
6527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct usb_device *dev = gspca_dev->dev;
6537879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	int Clck;
6547879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	int mode;
6557879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
6560dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_reset);
6570dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	msleep(200);
6580dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_init_data1);
6590dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
6600dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine
6617879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6627879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	switch (mode) {
6637879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	default:
664a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	case 0:
665a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine		Clck = 0x27;		/* ms-win 0x87 */
666a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine		break;
667a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	case 1:
6687879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x25;
6697879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		break;
6707879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	case 2:
6717879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x22;
6727879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		break;
6737879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	case 3:
6747879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x21;
6756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		break;
6766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
6777879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	reg_w_val(dev, 0x8700, Clck);	/* 0x27 clock */
678a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	reg_w_val(dev, 0x8702, 0x81);
679a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	reg_w_val(dev, 0x8500, mode);	/* mode */
6800dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
6815b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	setcontrast(gspca_dev);
6825b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/*	setbrightness(gspca_dev);	 * fixme: bad values */
6837879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	setautogain(gspca_dev);
6840dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	reg_w_val(dev, 0x8112, 0x10 | 0x20);
68572ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moine	return 0;
6866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
6876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
6886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void sd_stopN(struct gspca_dev *gspca_dev)
6896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
690d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
691d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine
692d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	if (sd->chip_revision == Rev012A) {
693d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
694d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	} else {
695d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		reg_w_val(gspca_dev->dev, 0x8112, 0x20);
696d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine/*		reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
697d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	}
6986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
6996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
70098522a7be97f2b23451342e36c39f412f0461e24Jean-Francois Moine/* called on streamoff with alt 0 and on disconnect */
7016a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void sd_stop0(struct gspca_dev *gspca_dev)
7026a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
703d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
704d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine
70598522a7be97f2b23451342e36c39f412f0461e24Jean-Francois Moine	if (!gspca_dev->present)
70698522a7be97f2b23451342e36c39f412f0461e24Jean-Francois Moine		return;
707d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	if (sd->chip_revision == Rev012A) {
708d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		reg_w_val(gspca_dev->dev, 0x8118, 0x29);
709d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		reg_w_val(gspca_dev->dev, 0x8114, 0x08);
710d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	}
711012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine/*	reg_w_val(gspca_dev->dev, 0x8114, 0); */
7126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
7136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
714cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moinestatic void do_autogain(struct gspca_dev *gspca_dev)
7156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
7166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
717cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int expotimes;
718cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int pixelclk;
719cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int gainG;
7206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 R, Gr, Gb, B;
7216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	int y;
7226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 luma_mean = 110;
7236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 luma_delta = 20;
7246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 spring = 4;
7256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
726cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (sd->ag_cnt < 0)
727cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		return;
728cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (--sd->ag_cnt >= 0)
729cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		return;
730cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	sd->ag_cnt = AG_CNT_START;
731cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine
7326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	switch (sd->chip_revision) {
7336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	case Rev072A:
734739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8621, 1);
735739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		Gr = gspca_dev->usb_buf[0];
736739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8622, 1);
737739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		R = gspca_dev->usb_buf[0];
738739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8623, 1);
739739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		B = gspca_dev->usb_buf[0];
740739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8624, 1);
741739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		Gb = gspca_dev->usb_buf[0];
7426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
7436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
7446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
7456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
7466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		if (y < luma_mean - luma_delta ||
7486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		    y > luma_mean + luma_delta) {
7496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes = i2c_read(gspca_dev, 0x09, 0x10);
7506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			pixelclk = 0x0800;
7516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes = expotimes & 0x07ff;
7526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
7536a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"Exposition Times 0x%03X Clock 0x%04X ",
7546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes,pixelclk); */
7556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gainG = i2c_read(gspca_dev, 0x35, 0x10);
7566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
7576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"reading Gain register %d", gainG); */
7586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes += (luma_mean - y) >> spring;
7606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gainG += (luma_mean - y) / 50;
7616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
7626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"compute expotimes %d gain %d",
7636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes,gainG); */
7646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			if (gainG > 0x3f)
7666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				gainG = 0x3f;
76735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			else if (gainG < 3)
7686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				gainG = 3;
7696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			i2c_write(gspca_dev, gainG, 0x35);
7706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
77135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			if (expotimes > 0x0256)
7726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes = 0x0256;
77335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			else if (expotimes < 3)
7746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes = 3;
7756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
7766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		}
7776a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		break;
7786a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
7796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
7806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7816a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
7826a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			struct gspca_frame *frame, /* target */
7836a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			__u8 *data,		/* isoc packet */
7846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			int len)		/* iso packet length */
7856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
7860fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
7870fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede
788576ed7b5696b9435e8e6a6ec0c57da1f19c7e469Jean-Francois Moine	len--;
789576ed7b5696b9435e8e6a6ec0c57da1f19c7e469Jean-Francois Moine	switch (*data++) {			/* sequence number */
79035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	case 0:					/* start of frame */
7916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
7926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine					data, 0);
7936a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		if (data[1] & 0x10) {
7946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* compressed bayer */
7956a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gspca_frame_add(gspca_dev, FIRST_PACKET,
7966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine					frame, data, len);
7976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		} else {
79854ab92ca05550550bcec2462de2605f35d079b66Hans de Goede			/* raw bayer (with a header, which we skip) */
7990fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			if (sd->chip_revision == Rev012A) {
8000fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				data += 20;
8010fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				len -= 20;
8020fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			} else {
8030fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				data += 16;
8040fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				len -= 16;
8050fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			}
8066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gspca_frame_add(gspca_dev, FIRST_PACKET,
8076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine						frame, data, len);
8086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		}
8096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return;
81035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	case 0xff:			/* drop (empty mpackets) */
8116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return;
8126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
8136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
8146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8167879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 72a only */
8176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
8186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sd->brightness = val;
8226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	if (gspca_dev->streaming)
8236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		setbrightness(gspca_dev);
8246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
8286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	*val = sd->brightness;
8326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8357879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 72a only */
8366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
8376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sd->contrast = val;
8416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	if (gspca_dev->streaming)
8426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		setcontrast(gspca_dev);
8436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
8476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	*val = sd->contrast;
8516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8536a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
8556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sd->autogain = val;
859cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (gspca_dev->streaming)
860cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		setautogain(gspca_dev);
8616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
8656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8676a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	*val = sd->autogain;
8696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8726c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moinestatic int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
8736c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine{
8746c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8756c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8766c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	sd->white = val;
8776c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	if (gspca_dev->streaming)
8786c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine		setwhite(gspca_dev);
8796c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	return 0;
8806c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine}
8816c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8826c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moinestatic int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val)
8836c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine{
8846c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8856c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8866c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	*val = sd->white;
8876c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	return 0;
8886c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine}
8896c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8907879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev12a only */
8917879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
8927879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
8937879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8947879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8957879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	sd->exposure = val;
8967879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	if (gspca_dev->streaming)
8977879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		setexposure(gspca_dev);
8987879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
8997879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9007879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9017879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
9027879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
9037879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
9047879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9057879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	*val = sd->exposure;
9067879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
9077879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9087879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9097879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev12a only */
9107879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
9117879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
9127879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
9137879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9147879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	sd->gain = val;
9157879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	if (gspca_dev->streaming)
9167879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		setgain(gspca_dev);
9177879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
9187879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9197879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9207879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
9217879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
9227879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
9237879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9247879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	*val = sd->gain;
9257879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
9267879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9277879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9287879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* control tables */
9297879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic struct ctrl sd_ctrls_12a[] = {
9307879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9317879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
9327879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_DO_WHITE_BALANCE,
9337879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
934695ebd125ade17101861c9eb99f74e6cc9a516edMauro Carvalho Chehab		.name = "White Balance",
9357879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = WHITE_MIN,
9367879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = WHITE_MAX,
9377879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9387879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = WHITE_DEF,
9397879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9407879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setwhite,
9417879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getwhite,
9427879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
9437879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9447879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
9457879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_EXPOSURE,
9467879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9477879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Exposure",
9487879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = EXPOSURE_MIN,
9497879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = EXPOSURE_MAX,
9507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9517879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = EXPOSURE_DEF,
9527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9537879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setexposure,
9547879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getexposure,
9557879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
9567879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9577879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
9587879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_GAIN,
9597879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9607879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Gain",
9617879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = GAIN_MIN,
9627879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = GAIN_MAX,
9637879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9647879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = GAIN_DEF,
9657879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9667879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setgain,
9677879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getgain,
9687879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
9697879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
9707879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9717879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic struct ctrl sd_ctrls_72a[] = {
9727879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9735b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    {
9745b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.id = V4L2_CID_DO_WHITE_BALANCE,
9755b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9765b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.name = "White Balance",
9775b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.minimum = WHITE_MIN,
9785b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.maximum = WHITE_MAX,
9795b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.step = 1,
9805b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.default_value = WHITE_DEF,
9815b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    },
9825b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    .set = sd_setwhite,
9835b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    .get = sd_getwhite,
9845b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	},
9855b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{
9867879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	   {
9877879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_BRIGHTNESS,
9887879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9897879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Brightness",
9907879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = BRIGHTNESS_MIN,
9917879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = BRIGHTNESS_MAX,
9927879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9937879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = BRIGHTNESS_DEF,
9947879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9957879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setbrightness,
9967879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getbrightness,
9977879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
9987879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9997879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
10007879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_CONTRAST,
10017879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
10027879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Contrast",
10037879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = CONTRAST_MIN,
10047879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = CONTRAST_MAX,
10057879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
10067879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = CONTRAST_DEF,
10077879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
10087879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setcontrast,
10097879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getcontrast,
10107879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
10117879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
10127879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
10137879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_AUTOGAIN,
10147879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_BOOLEAN,
10157879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Auto Gain",
10167879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = AUTOGAIN_MIN,
10177879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = AUTOGAIN_MAX,
10187879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
10197879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = AUTOGAIN_DEF,
10207879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
10217879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setautogain,
10227879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getautogain,
10237879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
10247879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
10257879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
10266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* sub-driver description */
10277879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc sd_desc_12a = {
10286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.name = MODULE_NAME,
10297879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.ctrls = sd_ctrls_12a,
10307879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.nctrls = ARRAY_SIZE(sd_ctrls_12a),
10316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.config = sd_config,
1032012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine	.init = sd_init_12a,
10337879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.start = sd_start_12a,
10347879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.stopN = sd_stopN,
10357879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.stop0 = sd_stop0,
10367879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.pkt_scan = sd_pkt_scan,
10377879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
10387879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc sd_desc_72a = {
10397879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.name = MODULE_NAME,
10407879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.ctrls = sd_ctrls_72a,
10417879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.nctrls = ARRAY_SIZE(sd_ctrls_72a),
10427879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.config = sd_config,
1043012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine	.init = sd_init_72a,
10447879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.start = sd_start_72a,
10456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.stopN = sd_stopN,
10466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.stop0 = sd_stop0,
10476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.pkt_scan = sd_pkt_scan,
1048cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	.dq_callback = do_autogain,
10496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
10507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc *sd_desc[2] = {
10517879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	&sd_desc_12a,
10527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	&sd_desc_72a
10537879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
10546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- module initialisation -- */
1056a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __devinitdata struct usb_device_id device_table[] = {
105787581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
105887581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
105987581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
106087581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
106187581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
106287581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
106387581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
106487581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
106587581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
106687581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
106787581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
106887581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
106987581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
107087581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
107187581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
10726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
10736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
10746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_DEVICE_TABLE(usb, device_table);
10766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10776a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- device connect -- */
10786a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_probe(struct usb_interface *intf,
10796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		    const struct usb_device_id *id)
10806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
10817879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return gspca_dev_probe(intf, id,
10827879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine				sd_desc[id->driver_info],
10837879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine				sizeof(struct sd),
10846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			       THIS_MODULE);
10856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
10866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic struct usb_driver sd_driver = {
10886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.name = MODULE_NAME,
10896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.id_table = device_table,
10906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.probe = sd_probe,
10916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.disconnect = gspca_disconnect,
10926a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine#ifdef CONFIG_PM
10936a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine	.suspend = gspca_suspend,
10946a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine	.resume = gspca_resume,
10956a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine#endif
10966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
10976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- module insert / remove -- */
10996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int __init sd_mod_init(void)
11006a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
1101f69e9529ed96ff917096d0b7b3015c8d8ea5750dAlexey Klimov	int ret;
1102f69e9529ed96ff917096d0b7b3015c8d8ea5750dAlexey Klimov	ret = usb_register(&sd_driver);
1103f69e9529ed96ff917096d0b7b3015c8d8ea5750dAlexey Klimov	if (ret < 0)
1104e6b148490f5e9ebb90ecb4a8de930be1b8936a16Alexey Klimov		return ret;
110510b0e96ed9a1ce0412ef981cf6250f9de3c80b02Jean-Francois Moine	PDEBUG(D_PROBE, "registered");
11066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
11076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
11086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void __exit sd_mod_exit(void)
11096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
11106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	usb_deregister(&sd_driver);
11116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	PDEBUG(D_PROBE, "deregistered");
11126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
11136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
11146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinemodule_init(sd_mod_init);
11156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinemodule_exit(sd_mod_exit);
1116