spca561.c revision 95c967c167785eb991cf6b22fb854dd8d61d0ff8
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
25436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#include <linux/input.h>
266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#include "gspca.h"
276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_LICENSE("GPL");
316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* specific webcam descriptor */
336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestruct sd {
346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct gspca_dev gspca_dev;	/* !! must be the first item */
356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
367879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	__u16 exposure;			/* rev12a only */
370fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede#define EXPOSURE_MIN 1
38d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define EXPOSURE_DEF 700		/* == 10 fps */
39d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define EXPOSURE_MAX (2047 + 325)	/* see setexposure */
407879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
415b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 contrast;			/* rev72a only */
425b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define CONTRAST_MIN 0x00
435b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define CONTRAST_DEF 0x20
445b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define CONTRAST_MAX 0x3f
455b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine
467879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	__u8 brightness;		/* rev72a only */
477879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define BRIGHTNESS_MIN 0
485b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define BRIGHTNESS_DEF 0x20
495b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine#define BRIGHTNESS_MAX 0x3f
507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
515b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 white;
529035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede#define HUE_MIN 1
539035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede#define HUE_DEF 0x40
549035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede#define HUE_MAX 0x7f
557879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 autogain;
577879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define AUTOGAIN_MIN 0
587879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define AUTOGAIN_DEF 1
597879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define AUTOGAIN_MAX 1
607879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
617879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	__u8 gain;			/* rev12a only */
62d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define GAIN_MIN 0
63d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define GAIN_DEF 63
64d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede#define GAIN_MAX 255
656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
66d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine#define EXPO12A_DEF 3
67d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	__u8 expo12a;		/* expo/gain? for rev 12a */
68d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine
696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 chip_revision;
707879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define Rev012A 0
717879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define Rev072A 1
727879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	signed char ag_cnt;
746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define AG_CNT_START 13
756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
77cc611b8aef7a8a9a2e614f1bdf3e2b8f066c8c8dJean-Francois Moinestatic const struct v4l2_pix_format sif_012a_mode[] = {
78c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
79c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 160,
80c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 160 * 120,
81c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
82c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 3},
83c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
84c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 176,
85c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 176 * 144,
86c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
87c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 2},
88c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
89c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 320,
90c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 320 * 240 * 4 / 8,
91c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
92c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 1},
93c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
94c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 352,
95c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 352 * 288 * 4 / 8,
96c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
97c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 0},
986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
100cc611b8aef7a8a9a2e614f1bdf3e2b8f066c8c8dJean-Francois Moinestatic const struct v4l2_pix_format sif_072a_mode[] = {
101b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
102b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 160,
103b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 160 * 120,
104b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
105b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 3},
106b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
107b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 176,
108b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 176 * 144,
109b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
110b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 2},
111b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
112b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 320,
113b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 320 * 240,
114b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
115b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 1},
116b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
117b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 352,
118b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 352 * 288,
119b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
120b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 0},
121b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine};
122b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine
1236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/*
1246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * Initialization data
1256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * I'm not very sure how to split initialization from open data
1266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * chunks. For now, we'll consider everything as initialization
1276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine */
1286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* Frame packet header offsets for the spca561 */
1296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_SNAP 1
1306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_TYPE 2
1316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_COMPRESS 3
1326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_FRAMSEQ   4
1336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_GPIO 5
1346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_USBBUFF 6
1356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2GRAVE 7
1366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2RAVE 8
1376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2BAVE 9
1386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2GBAVE 10
1396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1GRAVE 11
1406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1RAVE 12
1416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1BAVE 13
1426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1GBAVE 14
1436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_FREQ 15
1446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_VSYNC 16
1456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_INDEX_I2C_BASE 0x8800
1466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_SNAPBIT 0x20
1476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_SNAPCTRL 0x40
1486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
1490dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_reset[][2] = {
1506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8114},	/* Software GPIO output data */
1516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8114},	/* Software GPIO output data */
1526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8112},	/* Some kind of reset */
1530dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{}
1540dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine};
1550dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const __u16 rev72a_init_data1[][2] = {
1566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0003, 0x8701},	/* PCLK clock delay adjustment */
1576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8703},	/* HSYNC from cmos inverted */
1586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0011, 0x8118},	/* Enable and conf sensor */
1596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8118},	/* Conf sensor */
1606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0092, 0x8804},	/* I know nothing about these */
1616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0010, 0x8802},	/* 0x88xx registers, so I won't */
162f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
163f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
1640dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_init_sensor1[][2] = {
1650dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0001, 0x000d},
1660dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0002, 0x0018},
1670dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0004, 0x0165},
1680dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0005, 0x0021},
1690dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0007, 0x00aa},
1700dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0020, 0x1504},
1710dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0039, 0x0002},
1720dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0035, 0x0010},
1730dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0009, 0x1049},
1740dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0028, 0x000b},
1750dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x003b, 0x000f},
1760dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x003c, 0x0000},
177f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
178f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
179f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moinestatic const __u16 rev72a_init_data2[][2] = {
1806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0018, 0x8601},	/* Pixel/line selection for color separation */
1816a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8602},	/* Optical black level for user setting */
1826a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0060, 0x8604},	/* Optical black horizontal offset */
1836a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8605},	/* Optical black vertical offset */
1846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8603},	/* Non-automatic optical black level */
1856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */
1866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x865f},	/* Vertical valid pixels window (x2) */
1876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00b0, 0x865d},	/* Horizontal valid pixels window (x2) */
1886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0090, 0x865e},	/* Vertical valid lines window (x2) */
1896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00e0, 0x8406},	/* Memory buffer threshold */
1906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8660},	/* Compensation memory stuff */
1916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8201},	/* Output address for r/w serial EEPROM */
1926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0008, 0x8200},	/* Clear valid bit for serial EEPROM */
1936a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8200},	/* OprMode to be executed by hardware */
1940dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine/* from ms-win */
1950dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0000, 0x8611},	/* R offset for white balance */
1960dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x00fd, 0x8612},	/* Gr offset for white balance */
1970dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0003, 0x8613},	/* B offset for white balance */
1986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8614},	/* Gb offset for white balance */
1995b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/* from ms-win */
2005b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0035, 0x8651},	/* R gain for white balance */
2015b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0040, 0x8652},	/* Gr gain for white balance */
2025b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x005f, 0x8653},	/* B gain for white balance */
2035b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0040, 0x8654},	/* Gb gain for white balance */
2046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8502},	/* Maximum average bit rate stuff */
2056a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0011, 0x8802},
2060dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine
2076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0087, 0x8700},	/* Set master clock (96Mhz????) */
2086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0081, 0x8702},	/* Master clock output enable */
2096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8500},	/* Set image type (352x288 no compression) */
2116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* Originally was 0x0010 (352x288 compression) */
2126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */
2146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0003, 0x865c},	/* Vertical offset for valid lines */
215f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
216f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
2170dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_init_sensor2[][2] = {
2180dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0003, 0x0121},
2190dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0004, 0x0165},
2200dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0005, 0x002f},	/* blanking control column */
2210dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0006, 0x0000},	/* blanking mode row*/
2220dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x000a, 0x0002},
2230dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0009, 0x1061},	/* setexposure times && pixel clock
2246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				 * 0001 0 | 000 0110 0001 */
2250dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0035, 0x0014},
2266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
2286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/******************** QC Express etch2 stuff ********************/
230a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 Pb100_1map8300[][2] = {
2316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* reg, value */
2326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8320, 0x3304},
2336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8303, 0x0125},	/* image area */
2356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8304, 0x0169},
2366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8328, 0x000b},
2377879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{0x833c, 0x0001},		/*fixme: win:07*/
2386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2397879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{0x832f, 0x1904},		/*fixme: was 0419*/
2406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8307, 0x00aa},
2416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8301, 0x0003},
2426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8302, 0x000e},
2436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
245a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 Pb100_2map8300[][2] = {
2466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* reg, value */
2476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8339, 0x0000},
2486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8307, 0x00aa},
2496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
2516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
252a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 spca561_161rev12A_data1[][2] = {
2536b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x29, 0x8118},		/* Control register (various enable bits) */
2546b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x08, 0x8114},		/* GPIO: Led off */
2556b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x0e, 0x8112},		/* 0x0e stream off 0x3e stream on */
2566c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x00, 0x8102},		/* white balance - new */
2576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x92, 0x8804},
2586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x04, 0x8802},		/* windows uses 08 */
2596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
261a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 spca561_161rev12A_data2[][2] = {
2626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x21, 0x8118},
2636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x10, 0x8500},
2646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8601},
2656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8602},
2666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x04, 0x8501},
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	{0x90, 0x8604},
2736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8605},
2746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xb0, 0x8603},
2756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* sensor gains */
2776c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x07, 0x8601},		/* white balance - new */
2786c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x07, 0x8602},		/* white balance - new */
2796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8610},		/* *red */
2806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8611},		/* 3f   *green */
2816a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8612},		/* green *blue */
2826a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8613},		/* blue *green */
2836c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x43, 0x8614},		/* green *red - white balance - was 0x35 */
2846c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x40, 0x8615},		/* 40   *green - white balance - was 0x35 */
2856c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x71, 0x8616},		/* 7a   *blue - white balance - was 0x35 */
2866c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x40, 0x8617},		/* 40   *green - white balance - was 0x35 */
2876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0c, 0x8620},		/* 0c */
2896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xc8, 0x8631},		/* c8 */
2906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xc8, 0x8634},		/* c8 */
2916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x23, 0x8635},		/* 23 */
2926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x1f, 0x8636},		/* 1f */
2936a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xdd, 0x8637},		/* dd */
2946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xe1, 0x8638},		/* e1 */
2956a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x1d, 0x8639},		/* 1d */
2966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x21, 0x863a},		/* 21 */
2976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xe3, 0x863b},		/* e3 */
2986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xdf, 0x863c},		/* df */
2996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xf0, 0x8505},
3006a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x32, 0x850a},
3017879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/*	{0x99, 0x8700},		 * - white balance - new (removed) */
3026b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	/* HDG we used to do this in stop0, making the init state and the state
3036b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	   after a start / stop different, so do this here instead. */
3046b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x29, 0x8118},
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)
3180b656321f338a2e5e3d9a9bdce959a2d76857967Jean-François Moine		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;
4649035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede	sd->white = HUE_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
6001d00d6c1ff13607974fcd9469aa9466fcd253c3aJean-François Moine		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);
6486b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede
6496b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	/* Led ON (bit 3 -> 0 */
6506b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	reg_w_val(gspca_dev->dev, 0x8114, 0x00);
65172ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moine	return 0;
6527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
65372ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moinestatic int sd_start_72a(struct gspca_dev *gspca_dev)
6547879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
6557879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct usb_device *dev = gspca_dev->dev;
6567879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	int Clck;
6577879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	int mode;
6587879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
6590dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_reset);
6600dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	msleep(200);
6610dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_init_data1);
6620dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
6630dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine
6647879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6657879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	switch (mode) {
6667879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	default:
667a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	case 0:
668a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine		Clck = 0x27;		/* ms-win 0x87 */
669a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine		break;
670a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	case 1:
6717879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x25;
6727879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		break;
6737879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	case 2:
6747879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x22;
6757879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		break;
6767879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	case 3:
6777879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x21;
6786a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		break;
6796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
6807879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	reg_w_val(dev, 0x8700, Clck);	/* 0x27 clock */
681a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	reg_w_val(dev, 0x8702, 0x81);
682a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	reg_w_val(dev, 0x8500, mode);	/* mode */
6830dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
6845b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	setcontrast(gspca_dev);
6855b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/*	setbrightness(gspca_dev);	 * fixme: bad values */
6867879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	setautogain(gspca_dev);
6870dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	reg_w_val(dev, 0x8112, 0x10 | 0x20);
68872ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moine	return 0;
6896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
6906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
6916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void sd_stopN(struct gspca_dev *gspca_dev)
6926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
693d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
694d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine
695d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	if (sd->chip_revision == Rev012A) {
696d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
6976b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede		/* Led Off (bit 3 -> 1 */
6986b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede		reg_w_val(gspca_dev->dev, 0x8114, 0x08);
699d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	} else {
700d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		reg_w_val(gspca_dev->dev, 0x8112, 0x20);
701d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine/*		reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
702d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	}
7036a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
7046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
705cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moinestatic void do_autogain(struct gspca_dev *gspca_dev)
7066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
7076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
708cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int expotimes;
709cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int pixelclk;
710cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int gainG;
7116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 R, Gr, Gb, B;
7126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	int y;
7136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 luma_mean = 110;
7146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 luma_delta = 20;
7156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 spring = 4;
7166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
717cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (sd->ag_cnt < 0)
718cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		return;
719cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (--sd->ag_cnt >= 0)
720cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		return;
721cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	sd->ag_cnt = AG_CNT_START;
722cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine
7236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	switch (sd->chip_revision) {
7246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	case Rev072A:
725739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8621, 1);
726739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		Gr = gspca_dev->usb_buf[0];
727739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8622, 1);
728739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		R = gspca_dev->usb_buf[0];
729739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8623, 1);
730739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		B = gspca_dev->usb_buf[0];
731739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8624, 1);
732739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		Gb = gspca_dev->usb_buf[0];
7336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
7346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
7356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
7366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
7376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		if (y < luma_mean - luma_delta ||
7396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		    y > luma_mean + luma_delta) {
7406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes = i2c_read(gspca_dev, 0x09, 0x10);
7416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			pixelclk = 0x0800;
7426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes = expotimes & 0x07ff;
7436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
7446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"Exposition Times 0x%03X Clock 0x%04X ",
7456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes,pixelclk); */
7466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gainG = i2c_read(gspca_dev, 0x35, 0x10);
7476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
7486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"reading Gain register %d", gainG); */
7496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes += (luma_mean - y) >> spring;
7516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gainG += (luma_mean - y) / 50;
7526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
7536a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"compute expotimes %d gain %d",
7546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes,gainG); */
7556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			if (gainG > 0x3f)
7576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				gainG = 0x3f;
75835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			else if (gainG < 3)
7596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				gainG = 3;
7606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			i2c_write(gspca_dev, gainG, 0x35);
7616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
76235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			if (expotimes > 0x0256)
7636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes = 0x0256;
76435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			else if (expotimes < 3)
7656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes = 3;
7666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
7676a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		}
7686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		break;
7696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
7706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
7716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
77376dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			u8 *data,		/* isoc packet */
7746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			int len)		/* iso packet length */
7756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
7760fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
7770fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede
778576ed7b5696b9435e8e6a6ec0c57da1f19c7e469Jean-Francois Moine	len--;
779576ed7b5696b9435e8e6a6ec0c57da1f19c7e469Jean-Francois Moine	switch (*data++) {			/* sequence number */
78035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	case 0:					/* start of frame */
78176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
782436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede
783436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		/* This should never happen */
784436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		if (len < 2) {
785436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			PDEBUG(D_ERR, "Short SOF packet, ignoring");
786436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			gspca_dev->last_packet_type = DISCARD_PACKET;
787436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			return;
788436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		}
789436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede
7902856643e2e18f306227ae1257b63fc713d426dc7Jean-François Moine#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
791436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		if (data[0] & 0x20) {
792436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
793436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_sync(gspca_dev->input_dev);
794436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
795436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_sync(gspca_dev->input_dev);
796436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		}
797436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#endif
798436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede
7996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		if (data[1] & 0x10) {
8006a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* compressed bayer */
80176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
8026a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		} else {
80354ab92ca05550550bcec2462de2605f35d079b66Hans de Goede			/* raw bayer (with a header, which we skip) */
8040fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			if (sd->chip_revision == Rev012A) {
8050fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				data += 20;
8060fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				len -= 20;
8070fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			} else {
8080fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				data += 16;
8090fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				len -= 16;
8100fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			}
81176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
8126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		}
8136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return;
81435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	case 0xff:			/* drop (empty mpackets) */
8156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return;
8166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
81776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
8186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8207879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 72a only */
8216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
8226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sd->brightness = val;
8266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	if (gspca_dev->streaming)
8276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		setbrightness(gspca_dev);
8286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
8326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8346a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	*val = sd->brightness;
8366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8397879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 72a only */
8406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
8416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sd->contrast = val;
8456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	if (gspca_dev->streaming)
8466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		setcontrast(gspca_dev);
8476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
8516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8536a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	*val = sd->contrast;
8556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
8596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sd->autogain = val;
863cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (gspca_dev->streaming)
864cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		setautogain(gspca_dev);
8656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8676a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
8696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
8706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	*val = sd->autogain;
8736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
8746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
8756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8766c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moinestatic int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
8776c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine{
8786c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8796c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8806c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	sd->white = val;
8816c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	if (gspca_dev->streaming)
8826c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine		setwhite(gspca_dev);
8836c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	return 0;
8846c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine}
8856c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8866c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moinestatic int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val)
8876c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine{
8886c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8896c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8906c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	*val = sd->white;
8916c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	return 0;
8926c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine}
8936c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8947879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev12a only */
8957879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
8967879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
8977879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
8987879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8997879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	sd->exposure = val;
9007879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	if (gspca_dev->streaming)
9017879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		setexposure(gspca_dev);
9027879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
9037879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9047879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9057879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
9067879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
9077879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
9087879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9097879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	*val = sd->exposure;
9107879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
9117879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9127879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9137879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev12a only */
9147879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
9157879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
9167879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
9177879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9187879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	sd->gain = val;
9197879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	if (gspca_dev->streaming)
9207879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		setgain(gspca_dev);
9217879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
9227879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9237879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9247879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
9257879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
9267879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
9277879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9287879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	*val = sd->gain;
9297879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
9307879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
9317879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9327879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* control tables */
9337e64dc4c4d6f5c8935fac25c7fc7aa83f9880ed7Marton Nemethstatic const struct ctrl sd_ctrls_12a[] = {
9347879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9357879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
9369035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.id = V4L2_CID_HUE,
9377879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9389035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.name = "Hue",
9399035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.minimum = HUE_MIN,
9409035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.maximum = HUE_MAX,
9417879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9429035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.default_value = HUE_DEF,
9437879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9447879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setwhite,
9457879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getwhite,
9467879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
9477879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9487879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
9497879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_EXPOSURE,
9507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9517879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Exposure",
9527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = EXPOSURE_MIN,
9537879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = EXPOSURE_MAX,
9547879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9557879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = EXPOSURE_DEF,
9567879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9577879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setexposure,
9587879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getexposure,
9597879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
9607879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9617879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
9627879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_GAIN,
9637879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9647879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Gain",
9657879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = GAIN_MIN,
9667879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = GAIN_MAX,
9677879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9687879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = GAIN_DEF,
9697879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9707879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setgain,
9717879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getgain,
9727879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
9737879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
9747879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
9757e64dc4c4d6f5c8935fac25c7fc7aa83f9880ed7Marton Nemethstatic const struct ctrl sd_ctrls_72a[] = {
9767879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
9775b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    {
9789035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.id = V4L2_CID_HUE,
9795b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9809035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.name = "Hue",
9819035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.minimum = HUE_MIN,
9829035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.maximum = HUE_MAX,
9835b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		.step = 1,
9849035f2e27a99a7ea702973ab4fd47c0dd94a8c6eHans de Goede		.default_value = HUE_DEF,
9855b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    },
9865b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    .set = sd_setwhite,
9875b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	    .get = sd_getwhite,
9885b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	},
9895b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{
9907879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	   {
9917879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_BRIGHTNESS,
9927879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
9937879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Brightness",
9947879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = BRIGHTNESS_MIN,
9957879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = BRIGHTNESS_MAX,
9967879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
9977879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = BRIGHTNESS_DEF,
9987879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
9997879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setbrightness,
10007879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getbrightness,
10017879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
10027879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
10037879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
10047879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_CONTRAST,
10057879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_INTEGER,
10067879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Contrast",
10077879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = CONTRAST_MIN,
10087879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = CONTRAST_MAX,
10097879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
10107879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = CONTRAST_DEF,
10117879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
10127879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setcontrast,
10137879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getcontrast,
10147879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
10157879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{
10167879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    {
10177879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.id = V4L2_CID_AUTOGAIN,
10187879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.type = V4L2_CTRL_TYPE_BOOLEAN,
10197879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.name = "Auto Gain",
10207879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.minimum = AUTOGAIN_MIN,
10217879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.maximum = AUTOGAIN_MAX,
10227879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.step = 1,
10237879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		.default_value = AUTOGAIN_DEF,
10247879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    },
10257879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .set = sd_setautogain,
10267879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	    .get = sd_getautogain,
10277879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	},
10287879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
10297879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
10306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* sub-driver description */
10317879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc sd_desc_12a = {
10326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.name = MODULE_NAME,
10337879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.ctrls = sd_ctrls_12a,
10347879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.nctrls = ARRAY_SIZE(sd_ctrls_12a),
10356a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.config = sd_config,
1036012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine	.init = sd_init_12a,
10377879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.start = sd_start_12a,
10387879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.stopN = sd_stopN,
10397879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.pkt_scan = sd_pkt_scan,
10402856643e2e18f306227ae1257b63fc713d426dc7Jean-François Moine#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1041436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede	.other_input = 1,
1042436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#endif
10437879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
10447879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc sd_desc_72a = {
10457879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.name = MODULE_NAME,
10467879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.ctrls = sd_ctrls_72a,
10477879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.nctrls = ARRAY_SIZE(sd_ctrls_72a),
10487879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.config = sd_config,
1049012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine	.init = sd_init_72a,
10507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.start = sd_start_72a,
10516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.stopN = sd_stopN,
10526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.pkt_scan = sd_pkt_scan,
1053cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	.dq_callback = do_autogain,
10542856643e2e18f306227ae1257b63fc713d426dc7Jean-François Moine#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1055436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede	.other_input = 1,
1056436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#endif
10576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
10587879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc *sd_desc[2] = {
10597879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	&sd_desc_12a,
10607879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	&sd_desc_72a
10617879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
10626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- module initialisation -- */
106495c967c167785eb991cf6b22fb854dd8d61d0ff8Jean-François Moinestatic const struct usb_device_id device_table[] = {
106587581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
106687581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
106787581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
1068f8f73d01a31488ec8e923b2148043579d43d0378John Ellson	{USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
106987581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
107087581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
107187581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
107287581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
107387581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
107487581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
107587581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
107687581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
107787581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
107887581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
107987581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
108087581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
10816a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
10826a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
10836a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_DEVICE_TABLE(usb, device_table);
10856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- device connect -- */
10876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_probe(struct usb_interface *intf,
10886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		    const struct usb_device_id *id)
10896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
10907879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return gspca_dev_probe(intf, id,
10917879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine				sd_desc[id->driver_info],
10927879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine				sizeof(struct sd),
10936a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			       THIS_MODULE);
10946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
10956a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
10966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic struct usb_driver sd_driver = {
10976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.name = MODULE_NAME,
10986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.id_table = device_table,
10996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.probe = sd_probe,
11006a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.disconnect = gspca_disconnect,
11016a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine#ifdef CONFIG_PM
11026a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine	.suspend = gspca_suspend,
11036a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine	.resume = gspca_resume,
11046a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine#endif
11056a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
11066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
11076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- module insert / remove -- */
11086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int __init sd_mod_init(void)
11096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
1110548264375b1c0d51b418bf7ab6d2fec647307ab7Jean-François Moine	return usb_register(&sd_driver);
11116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
11126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void __exit sd_mod_exit(void)
11136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
11146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	usb_deregister(&sd_driver);
11156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
11166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
11176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinemodule_init(sd_mod_init);
11186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinemodule_exit(sd_mod_exit);
1119