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
23133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches
256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define MODULE_NAME "spca561"
266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
27436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#include <linux/input.h>
286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#include "gspca.h"
296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_LICENSE("GPL");
336a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
343fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil#define EXPOSURE_MAX (2047 + 325)
353fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil
366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* specific webcam descriptor */
376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestruct sd {
386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct gspca_dev gspca_dev;	/* !! must be the first item */
396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
403fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct { /* hue/contrast control cluster */
413fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		struct v4l2_ctrl *contrast;
423fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		struct v4l2_ctrl *hue;
433fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	};
443fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct v4l2_ctrl *autogain;
456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
46d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine#define EXPO12A_DEF 3
47d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	__u8 expo12a;		/* expo/gain? for rev 12a */
48d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine
496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 chip_revision;
507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define Rev012A 0
517879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine#define Rev072A 1
527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
536a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	signed char ag_cnt;
546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define AG_CNT_START 13
556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
57cc611b8aef7a8a9a2e614f1bdf3e2b8f066c8c8dJean-Francois Moinestatic const struct v4l2_pix_format sif_012a_mode[] = {
58c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
59c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 160,
60c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 160 * 120,
61c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
62c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 3},
63c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
64c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 176,
65c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 176 * 144,
66c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
67c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 2},
68c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
69c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 320,
70c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 320 * 240 * 4 / 8,
71c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
72c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 1},
73c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	{352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
74c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.bytesperline = 352,
75c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.sizeimage = 352 * 288 * 4 / 8,
76c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
77c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine		.priv = 0},
786a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
80cc611b8aef7a8a9a2e614f1bdf3e2b8f066c8c8dJean-Francois Moinestatic const struct v4l2_pix_format sif_072a_mode[] = {
81b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
82b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 160,
83b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 160 * 120,
84b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
85b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 3},
86b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
87b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 176,
88b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 176 * 144,
89b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
90b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 2},
91b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
92b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 320,
93b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 320 * 240,
94b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
95b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 1},
96b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	{352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
97b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.bytesperline = 352,
98b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.sizeimage = 352 * 288,
99b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.colorspace = V4L2_COLORSPACE_SRGB,
100b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		.priv = 0},
101b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine};
102b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine
1036a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/*
1046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * Initialization data
1056a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * I'm not very sure how to split initialization from open data
1066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine * chunks. For now, we'll consider everything as initialization
1076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine */
1086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* Frame packet header offsets for the spca561 */
1096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_SNAP 1
1106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_TYPE 2
1116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_COMPRESS 3
1126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_FRAMSEQ   4
1136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_GPIO 5
1146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_USBBUFF 6
1156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2GRAVE 7
1166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2RAVE 8
1176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2BAVE 9
1186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN2GBAVE 10
1196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1GRAVE 11
1206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1RAVE 12
1216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1BAVE 13
1226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_WIN1GBAVE 14
1236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_FREQ 15
1246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_OFFSET_VSYNC 16
1256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_INDEX_I2C_BASE 0x8800
1266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_SNAPBIT 0x20
1276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine#define SPCA561_SNAPCTRL 0x40
1286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
1290dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_reset[][2] = {
1306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8114},	/* Software GPIO output data */
1316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8114},	/* Software GPIO output data */
1326a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8112},	/* Some kind of reset */
1330dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{}
1340dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine};
1350dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const __u16 rev72a_init_data1[][2] = {
1366a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0003, 0x8701},	/* PCLK clock delay adjustment */
1376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8703},	/* HSYNC from cmos inverted */
1386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0011, 0x8118},	/* Enable and conf sensor */
1396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8118},	/* Conf sensor */
1406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0092, 0x8804},	/* I know nothing about these */
1416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0010, 0x8802},	/* 0x88xx registers, so I won't */
142f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
143f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
1440dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_init_sensor1[][2] = {
1450dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0001, 0x000d},
1460dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0002, 0x0018},
1470dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0004, 0x0165},
1480dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0005, 0x0021},
1490dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0007, 0x00aa},
1500dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0020, 0x1504},
1510dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0039, 0x0002},
1520dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0035, 0x0010},
1530dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0009, 0x1049},
1540dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0028, 0x000b},
1550dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x003b, 0x000f},
1560dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x003c, 0x0000},
157f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
158f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
159f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moinestatic const __u16 rev72a_init_data2[][2] = {
1606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0018, 0x8601},	/* Pixel/line selection for color separation */
1616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8602},	/* Optical black level for user setting */
1626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0060, 0x8604},	/* Optical black horizontal offset */
1636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8605},	/* Optical black vertical offset */
1646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8603},	/* Non-automatic optical black level */
1656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */
1666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x865f},	/* Vertical valid pixels window (x2) */
1676a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00b0, 0x865d},	/* Horizontal valid pixels window (x2) */
1686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0090, 0x865e},	/* Vertical valid lines window (x2) */
1696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00e0, 0x8406},	/* Memory buffer threshold */
1706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8660},	/* Compensation memory stuff */
1716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8201},	/* Output address for r/w serial EEPROM */
1726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0008, 0x8200},	/* Clear valid bit for serial EEPROM */
1736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0001, 0x8200},	/* OprMode to be executed by hardware */
1740dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine/* from ms-win */
1750dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0000, 0x8611},	/* R offset for white balance */
1760dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x00fd, 0x8612},	/* Gr offset for white balance */
1770dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0003, 0x8613},	/* B offset for white balance */
1786a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8614},	/* Gb offset for white balance */
1795b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/* from ms-win */
1805b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0035, 0x8651},	/* R gain for white balance */
1815b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0040, 0x8652},	/* Gr gain for white balance */
1825b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x005f, 0x8653},	/* B gain for white balance */
1835b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	{0x0040, 0x8654},	/* Gb gain for white balance */
1846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x8502},	/* Maximum average bit rate stuff */
1856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0011, 0x8802},
1860dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine
1876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0087, 0x8700},	/* Set master clock (96Mhz????) */
1886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0081, 0x8702},	/* Master clock output enable */
1896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
1906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0000, 0x8500},	/* Set image type (352x288 no compression) */
1916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* Originally was 0x0010 (352x288 compression) */
1926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
1936a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */
1946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0003, 0x865c},	/* Vertical offset for valid lines */
195f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	{}
196f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine};
1970dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moinestatic const u16 rev72a_init_sensor2[][2] = {
1980dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0003, 0x0121},
1990dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0004, 0x0165},
2000dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0005, 0x002f},	/* blanking control column */
2010dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0006, 0x0000},	/* blanking mode row*/
2020dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x000a, 0x0002},
2030dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0009, 0x1061},	/* setexposure times && pixel clock
2046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				 * 0001 0 | 000 0110 0001 */
2050dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	{0x0035, 0x0014},
2066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
2086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/******************** QC Express etch2 stuff ********************/
210a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 Pb100_1map8300[][2] = {
2116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* reg, value */
2126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8320, 0x3304},
2136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8303, 0x0125},	/* image area */
2156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8304, 0x0169},
2166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8328, 0x000b},
2177879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{0x833c, 0x0001},		/*fixme: win:07*/
2186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2197879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	{0x832f, 0x1904},		/*fixme: was 0419*/
2206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8307, 0x00aa},
2216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8301, 0x0003},
2226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8302, 0x000e},
2236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
225a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 Pb100_2map8300[][2] = {
2266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* reg, value */
2276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8339, 0x0000},
2286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x8307, 0x00aa},
2296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
2316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
232a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 spca561_161rev12A_data1[][2] = {
2336b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x29, 0x8118},		/* Control register (various enable bits) */
2346b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x08, 0x8114},		/* GPIO: Led off */
2356b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x0e, 0x8112},		/* 0x0e stream off 0x3e stream on */
2366c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x00, 0x8102},		/* white balance - new */
2376a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x92, 0x8804},
2386a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x04, 0x8802},		/* windows uses 08 */
2396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
241a5ae2062252e697d38e53dbbeb91460252208914Jean-Francois Moinestatic const __u16 spca561_161rev12A_data2[][2] = {
2426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x21, 0x8118},
2436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x10, 0x8500},
2446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8601},
2456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8602},
2466a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x04, 0x8501},
2476a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x07, 0x8201},		/* windows uses 02 */
2496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x08, 0x8200},
2506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x01, 0x8200},
2516a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x90, 0x8604},
2536a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8605},
2546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xb0, 0x8603},
2556a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* sensor gains */
2576c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x07, 0x8601},		/* white balance - new */
2586c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x07, 0x8602},		/* white balance - new */
2596a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8610},		/* *red */
2606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8611},		/* 3f   *green */
2616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8612},		/* green *blue */
2626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x00, 0x8613},		/* blue *green */
2636c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x43, 0x8614},		/* green *red - white balance - was 0x35 */
2646c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x40, 0x8615},		/* 40   *green - white balance - was 0x35 */
2656c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x71, 0x8616},		/* 7a   *blue - white balance - was 0x35 */
2666c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	{0x40, 0x8617},		/* 40   *green - white balance - was 0x35 */
2676a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
2686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x0c, 0x8620},		/* 0c */
2696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xc8, 0x8631},		/* c8 */
2706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xc8, 0x8634},		/* c8 */
2716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x23, 0x8635},		/* 23 */
2726a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x1f, 0x8636},		/* 1f */
2736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xdd, 0x8637},		/* dd */
2746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xe1, 0x8638},		/* e1 */
2756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x1d, 0x8639},		/* 1d */
2766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x21, 0x863a},		/* 21 */
2776a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xe3, 0x863b},		/* e3 */
2786a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xdf, 0x863c},		/* df */
2796a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0xf0, 0x8505},
2806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{0x32, 0x850a},
2817879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/*	{0x99, 0x8700},		 * - white balance - new (removed) */
2826b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	/* HDG we used to do this in stop0, making the init state and the state
2836b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	   after a start / stop different, so do this here instead. */
2846b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	{0x29, 0x8118},
2856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
2866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
2876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
288c93396e13576928a073154b5715761ff8a998368Theodore Kilgorestatic void reg_w_val(struct gspca_dev *gspca_dev, __u16 index, __u8 value)
28935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
29035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int ret;
291c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	struct usb_device *dev = gspca_dev->dev;
29235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
29335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
29435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			      0,		/* request */
29535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
29635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			      value, index, NULL, 0, 500);
29735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
29835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	if (ret < 0)
299133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		pr_err("reg write: error %d\n", ret);
30035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
30135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
30235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void write_vector(struct gspca_dev *gspca_dev,
30335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			const __u16 data[][2])
3046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
30535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int i;
3066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
30735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	i = 0;
30835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	while (data[i][1] != 0) {
309c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, data[i][1], data[i][0]);
3106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		i++;
3116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
3126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
31335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
31435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine/* read 'len' bytes to gspca_dev->usb_buf */
31535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void reg_r(struct gspca_dev *gspca_dev,
31635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		  __u16 index, __u16 length)
31735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
31835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	usb_control_msg(gspca_dev->dev,
31935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			usb_rcvctrlpipe(gspca_dev->dev, 0),
32035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* request */
32135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
32235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* value */
32335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			index, gspca_dev->usb_buf, length, 500);
32435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
32535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
32635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine/* write 'len' bytes from gspca_dev->usb_buf */
32735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void reg_w_buf(struct gspca_dev *gspca_dev,
32835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		      __u16 index, __u16 len)
32935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
33035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	usb_control_msg(gspca_dev->dev,
33135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			usb_sndctrlpipe(gspca_dev->dev, 0),
33235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* request */
33335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
33435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			0,			/* value */
33535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			index, gspca_dev->usb_buf, len, 500);
33635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
33735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
33835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
33935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
34035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int retry = 60;
34135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
342c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8801, reg);
343c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8805, value);
344c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8800, value >> 8);
34535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	do {
34635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		reg_r(gspca_dev, 0x8803, 1);
34735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		if (!gspca_dev->usb_buf[0])
34835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			return;
3490dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine		msleep(10);
35035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	} while (--retry);
35135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
35235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
35335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
35435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
35535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	int retry = 60;
35635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	__u8 value;
35735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
358c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8804, 0x92);
359c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8801, reg);
360c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8802, mode | 0x01);
36135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	do {
36235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		reg_r(gspca_dev, 0x8803, 1);
36335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		if (!gspca_dev->usb_buf[0]) {
36435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			reg_r(gspca_dev, 0x8800, 1);
36535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			value = gspca_dev->usb_buf[0];
36635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			reg_r(gspca_dev, 0x8805, 1);
36735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			return ((int) value << 8) | gspca_dev->usb_buf[0];
36835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		}
3690dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine		msleep(10);
37035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	} while (--retry);
37135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	return -1;
37235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
37335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
37435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moinestatic void sensor_mapwrite(struct gspca_dev *gspca_dev,
37535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			    const __u16 (*sensormap)[2])
37635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine{
37735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	while ((*sensormap)[0]) {
37835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		gspca_dev->usb_buf[0] = (*sensormap)[1];
37935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
38035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		reg_w_buf(gspca_dev, (*sensormap)[0], 2);
38135dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine		sensormap++;
38235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	}
38335dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine}
38435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
385f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moinestatic void write_sensor_72a(struct gspca_dev *gspca_dev,
386f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine			    const __u16 (*sensor)[2])
387f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine{
388f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	while ((*sensor)[0]) {
389f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine		i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
390f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine		sensor++;
391f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	}
392f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine}
393f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine
3946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void init_161rev12A(struct gspca_dev *gspca_dev)
3956a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
3966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	write_vector(gspca_dev, spca561_161rev12A_data1);
3976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sensor_mapwrite(gspca_dev, Pb100_1map8300);
3987879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/*fixme: should be in sd_start*/
3996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	write_vector(gspca_dev, spca561_161rev12A_data2);
4006a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	sensor_mapwrite(gspca_dev, Pb100_2map8300);
4016a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
4026a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4036a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* this function is called at probe time */
4046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_config(struct gspca_dev *gspca_dev,
4056a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		     const struct usb_device_id *id)
4066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
4076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
4086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct cam *cam;
4096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u16 vendor, product;
4106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 data1, data2;
4116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	/* Read frm global register the USB product and vendor IDs, just to
4136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	 * prove that we can communicate with the device.  This works, which
4146a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	 * confirms at we are communicating properly and that the device
4156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	 * is a 561. */
416739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8104, 1);
417739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data1 = gspca_dev->usb_buf[0];
418739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8105, 1);
419739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data2 = gspca_dev->usb_buf[0];
4206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	vendor = (data2 << 8) | data1;
421739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8106, 1);
422739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data1 = gspca_dev->usb_buf[0];
423739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	reg_r(gspca_dev, 0x8107, 1);
424739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine	data2 = gspca_dev->usb_buf[0];
4256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	product = (data2 << 8) | data1;
4266a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	if (vendor != id->idVendor || product != id->idProduct) {
4276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		PDEBUG(D_PROBE, "Bad vendor / product from device");
4286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return -EINVAL;
4296a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
4309d64fdb15b1b9ce9144cfde4001e9194ccde42d1Jean-Francois Moine
4316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	cam = &gspca_dev->cam;
432eb3fb7c9633f79077c7c650efe0edec1840926daHans de Goede	cam->needs_full_bandwidth = 1;
4339d64fdb15b1b9ce9144cfde4001e9194ccde42d1Jean-Francois Moine
4349d64fdb15b1b9ce9144cfde4001e9194ccde42d1Jean-Francois Moine	sd->chip_revision = id->driver_info;
435b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	if (sd->chip_revision == Rev012A) {
436b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->cam_mode = sif_012a_mode;
437b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->nmodes = ARRAY_SIZE(sif_012a_mode);
438b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	} else {
439b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->cam_mode = sif_072a_mode;
440b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine		cam->nmodes = ARRAY_SIZE(sif_072a_mode);
441b77c0046a63e7aa87152f9978cf7c46e7bead7fcJean-Francois Moine	}
442d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	sd->expo12a = EXPO12A_DEF;
4436a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
4446a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
4456a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
446012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine/* this function is called at probe and resume time */
447012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moinestatic int sd_init_12a(struct gspca_dev *gspca_dev)
4486a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
4497879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	PDEBUG(D_STREAM, "Chip revision: 012a");
4507879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	init_161rev12A(gspca_dev);
4517879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
4527879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
453012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moinestatic int sd_init_72a(struct gspca_dev *gspca_dev)
4547879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
4557879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	PDEBUG(D_STREAM, "Chip revision: 072a");
4560dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_reset);
4570dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	msleep(200);
458f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_vector(gspca_dev, rev72a_init_data1);
459f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
460f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_vector(gspca_dev, rev72a_init_data2);
461f8a04a6fc4373001a7f311540dba5e4f4d86300fJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
462c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8112, 0x30);
4636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	return 0;
4646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
4656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4663fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic void setbrightness(struct gspca_dev *gspca_dev, s32 val)
4676a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
468a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
469a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede	__u16 reg;
4705b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine
471a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede	if (sd->chip_revision == Rev012A)
472a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede		reg = 0x8610;
473a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede	else
474a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede		reg = 0x8611;
475a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede
476c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, reg + 0, val);		/* R */
477c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, reg + 1, val);		/* Gr */
478c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, reg + 2, val);		/* B */
479c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, reg + 3, val);		/* Gb */
4806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
4816a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
4823fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
4836c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine{
4846c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
4855b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u8 blue, red;
4865b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	__u16 reg;
4876c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
4887879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	/* try to emulate MS-win as possible */
4895b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	red = 0x20 + white * 3 / 8;
4905b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	blue = 0x90 - white * 5 / 8;
4915b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	if (sd->chip_revision == Rev012A) {
4925b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		reg = 0x8614;
4935b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	} else {
4945b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		reg = 0x8651;
4953fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		red += contrast - 0x20;
4963fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		blue += contrast - 0x20;
497c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, 0x8652, contrast + 0x20); /* Gr */
498c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, 0x8654, contrast + 0x20); /* Gb */
4995b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	}
500c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, reg, red);
501c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, reg + 2, blue);
5027879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
5037879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
5047879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 12a only */
5053fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic void setexposure(struct gspca_dev *gspca_dev, s32 val)
5067879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
507d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	int i, expo = 0;
5087879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
5090fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	/* Register 0x8309 controls exposure for the spca561,
5100fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   the basic exposure setting goes from 1-2047, where 1 is completely
5110fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   dark and 2047 is very bright. It not only influences exposure but
5120fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   also the framerate (to allow for longer exposure) from 1 - 300 it
5130fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   only raises the exposure time then from 300 - 600 it halves the
5140fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   framerate to be able to further raise the exposure time and for every
5150fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   300 more it halves the framerate again. This allows for a maximum
5160fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
5170fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
5180fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   configure a divider for the base framerate which us used at the
5190fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   exposure setting of 1-300. These bits configure the base framerate
5200fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	   according to the following formula: fps = 60 / (value + 2) */
521d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
522d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	/* We choose to use the high bits setting the fixed framerate divisor
523d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   asap, as setting high basic exposure setting without the fixed
524d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   divider in combination with high gains makes the cam stop */
525d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	int table[] =  { 0, 450, 550, 625, EXPOSURE_MAX };
526d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
527d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
5283fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		if (val <= table[i + 1]) {
5293fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			expo  = val - table[i];
530d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede			if (i)
531d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede				expo += 300;
532d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede			expo |= i << 11;
533d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede			break;
534d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede		}
5350fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	}
536d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
53735dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	gspca_dev->usb_buf[0] = expo;
53835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	gspca_dev->usb_buf[1] = expo >> 8;
53935dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_buf(gspca_dev, 0x8309, 2);
5407879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
5417879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
5427879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine/* rev 12a only */
5433fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic void setgain(struct gspca_dev *gspca_dev, s32 val)
5447879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
545d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	/* gain reg low 6 bits  0-63 gain, bit 6 and 7, both double the
546d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   sensitivity when set, so 31 + one of them set == 63, and 15
547d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	   with both of them set == 63 */
5483fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	if (val < 64)
5493fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		gspca_dev->usb_buf[0] = val;
5503fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	else if (val < 128)
5513fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		gspca_dev->usb_buf[0] = (val / 2) | 0x40;
552d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede	else
5533fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		gspca_dev->usb_buf[0] = (val / 4) | 0xc0;
554d0848eb2864c0f1ef52d586cd33c68a103b0a2acHans de Goede
55535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	gspca_dev->usb_buf[1] = 0;
55635dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	reg_w_buf(gspca_dev, 0x8335, 2);
5576c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine}
5586c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
5593fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic void setautogain(struct gspca_dev *gspca_dev, s32 val)
560cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine{
561cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
562cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine
5633fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	if (val)
564d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		sd->ag_cnt = AG_CNT_START;
565d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	else
566d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine		sd->ag_cnt = -1;
567cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine}
568cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine
56972ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moinestatic int sd_start_12a(struct gspca_dev *gspca_dev)
5706a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
5716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	int mode;
5725b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	static const __u8 Reg8391[8] =
5735b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine		{0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
5746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
575c2446b3eba97243acbe2ad0939a28b5edb97eae7Jean-Francois Moine	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
5767879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	if (mode <= 1) {
5777879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		/* Use compression on 320x240 and above */
578c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, 0x8500, 0x10 | mode);
5797879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	} else {
5807879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		/* I couldn't get the compression to work below 320x240
5817879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		 * Fortunately at these resolutions the bandwidth
5827879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		 * is sufficient to push raw frames at ~20fps */
583c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, 0x8500, mode);
5847879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	}		/* -- qq@kuku.eu.org */
58535dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine
5865b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	gspca_dev->usb_buf[0] = 0xaa;
5875b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	gspca_dev->usb_buf[1] = 0x00;
5885b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_buf(gspca_dev, 0x8307, 2);
5895b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	/* clock - lower 0x8X values lead to fps > 30 */
590c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8700, 0x8a);
5917879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine					/* 0x8f 0x85 0x27 clock */
592c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8112, 0x1e | 0x20);
593c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x850b, 0x03);
5945b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	memcpy(gspca_dev->usb_buf, Reg8391, 8);
5955b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_buf(gspca_dev, 0x8391, 8);
5965b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine	reg_w_buf(gspca_dev, 0x8390, 8);
5976b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede
5986b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede	/* Led ON (bit 3 -> 0 */
599c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8114, 0x00);
60072ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moine	return 0;
6017879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
60272ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moinestatic int sd_start_72a(struct gspca_dev *gspca_dev)
6037879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
6043fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct sd *sd = (struct sd *) gspca_dev;
6057879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	int Clck;
6067879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	int mode;
6077879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
6080dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_reset);
6090dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	msleep(200);
6100dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_vector(gspca_dev, rev72a_init_data1);
6110dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
6120dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine
6137879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6147879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	switch (mode) {
6157879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	default:
616a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	case 0:
617a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine		Clck = 0x27;		/* ms-win 0x87 */
618a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine		break;
619a48196a2f74a2e19e67debe194e337dfc583702fJean-Francois Moine	case 1:
6207879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x25;
6217879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		break;
6227879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	case 2:
6237879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x22;
6247879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		break;
6257879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	case 3:
6267879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine		Clck = 0x21;
6276a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		break;
6286a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
629c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8700, Clck);	/* 0x27 clock */
630c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8702, 0x81);
631c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8500, mode);	/* mode */
6320dbc2c1674b346ff22f729af14efa4822f81325cJean-Francois Moine	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
6333fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),
6343fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			v4l2_ctrl_g_ctrl(sd->contrast));
6355b7ed28ec5deb57f790e38af8d813310b830743cJean-Francois Moine/*	setbrightness(gspca_dev);	 * fixme: bad values */
6363fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
637c93396e13576928a073154b5715761ff8a998368Theodore Kilgore	reg_w_val(gspca_dev, 0x8112, 0x10 | 0x20);
63872ab97cecb7225a4c9f74cdd80268b50b74697bbJean-Francois Moine	return 0;
6396a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
6406a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
6416a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void sd_stopN(struct gspca_dev *gspca_dev)
6426a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
643d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
644d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine
645d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	if (sd->chip_revision == Rev012A) {
646c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, 0x8112, 0x0e);
6476b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0Hans de Goede		/* Led Off (bit 3 -> 1 */
648c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, 0x8114, 0x08);
649d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	} else {
650c93396e13576928a073154b5715761ff8a998368Theodore Kilgore		reg_w_val(gspca_dev, 0x8112, 0x20);
651c93396e13576928a073154b5715761ff8a998368Theodore Kilgore/*		reg_w_val(gspca_dev, 0x8102, 0x00); ?? */
652d698dc6b0477d3165a7f320b3ce36d1cbd361c94Jean-Francois Moine	}
6536a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
6546a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
655cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moinestatic void do_autogain(struct gspca_dev *gspca_dev)
6566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
6576a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	struct sd *sd = (struct sd *) gspca_dev;
658cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int expotimes;
659cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int pixelclk;
660cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	int gainG;
6616a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 R, Gr, Gb, B;
6626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	int y;
6636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 luma_mean = 110;
6646a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 luma_delta = 20;
6656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	__u8 spring = 4;
6666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
667cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (sd->ag_cnt < 0)
668cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		return;
669cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	if (--sd->ag_cnt >= 0)
670cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine		return;
671cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	sd->ag_cnt = AG_CNT_START;
672cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine
6736a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	switch (sd->chip_revision) {
6746a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	case Rev072A:
675739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8621, 1);
676739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		Gr = gspca_dev->usb_buf[0];
677739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8622, 1);
678739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		R = gspca_dev->usb_buf[0];
679739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8623, 1);
680739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		B = gspca_dev->usb_buf[0];
681739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		reg_r(gspca_dev, 0x8624, 1);
682739570bb218bb4607df1f197282561e97a98e54aJean-Francois Moine		Gb = gspca_dev->usb_buf[0];
6836a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
6846a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
6856a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
6866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		/* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
6876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
6886a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		if (y < luma_mean - luma_delta ||
6896a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		    y > luma_mean + luma_delta) {
6906a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes = i2c_read(gspca_dev, 0x09, 0x10);
6916a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			pixelclk = 0x0800;
6926a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes = expotimes & 0x07ff;
6936a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
6946a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"Exposition Times 0x%03X Clock 0x%04X ",
6956a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes,pixelclk); */
6966a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gainG = i2c_read(gspca_dev, 0x35, 0x10);
6976a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
6986a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"reading Gain register %d", gainG); */
6996a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7006a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			expotimes += (luma_mean - y) >> spring;
7016a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			gainG += (luma_mean - y) / 50;
7026a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* PDEBUG(D_PACK,
7036a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				"compute expotimes %d gain %d",
7046a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes,gainG); */
7056a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			if (gainG > 0x3f)
7076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				gainG = 0x3f;
70835dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			else if (gainG < 3)
7096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				gainG = 3;
7106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			i2c_write(gspca_dev, gainG, 0x35);
7116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
71235dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			if (expotimes > 0x0256)
7136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes = 0x0256;
71435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine			else if (expotimes < 3)
7156a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine				expotimes = 3;
7166a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
7176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		}
7186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		break;
7196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
7206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
7216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
72376dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			u8 *data,		/* isoc packet */
7246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			int len)		/* iso packet length */
7256a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
7260fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
7270fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede
728576ed7b5696b9435e8e6a6ec0c57da1f19c7e469Jean-Francois Moine	len--;
729576ed7b5696b9435e8e6a6ec0c57da1f19c7e469Jean-Francois Moine	switch (*data++) {			/* sequence number */
73035dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	case 0:					/* start of frame */
73176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
732436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede
733436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		/* This should never happen */
734436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		if (len < 2) {
735c93396e13576928a073154b5715761ff8a998368Theodore Kilgore			PERR("Short SOF packet, ignoring");
736436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			gspca_dev->last_packet_type = DISCARD_PACKET;
737436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			return;
738436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		}
739436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede
74060d21563785535e518589ab58b0295ecaa06233fPeter Senna Tschudin#if IS_ENABLED(CONFIG_INPUT)
741436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		if (data[0] & 0x20) {
742436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
743436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_sync(gspca_dev->input_dev);
744436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
745436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede			input_sync(gspca_dev->input_dev);
746436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede		}
747436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#endif
748436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede
7496a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		if (data[1] & 0x10) {
7506a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			/* compressed bayer */
75176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
7526a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		} else {
75354ab92ca05550550bcec2462de2605f35d079b66Hans de Goede			/* raw bayer (with a header, which we skip) */
7540fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			if (sd->chip_revision == Rev012A) {
7550fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				data += 20;
7560fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				len -= 20;
7570fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			} else {
7580fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				data += 16;
7590fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede				len -= 16;
7600fc23d20699a6a3b7e34b3be2cc5e60317ba7849Hans de Goede			}
76176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
7626a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		}
7636a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return;
76435dc1b4cfa75dc0fa5ed44991b41db814e0f7741Jean-Francois Moine	case 0xff:			/* drop (empty mpackets) */
7656a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		return;
7666a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	}
76776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
7686a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
7696a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7703fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
7716a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
7723fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct gspca_dev *gspca_dev =
7733fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
7743fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct sd *sd = (struct sd *)gspca_dev;
7756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7763fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	gspca_dev->usb_err = 0;
7776a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7783fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	if (!gspca_dev->streaming)
7793fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		return 0;
7806a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
7813fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	switch (ctrl->id) {
7823fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	case V4L2_CID_BRIGHTNESS:
7833fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		setbrightness(gspca_dev, ctrl->val);
7843fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		break;
7853fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	case V4L2_CID_CONTRAST:
7863fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		/* hue/contrast control cluster for 72a */
7873fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		setwhite(gspca_dev, sd->hue->val, ctrl->val);
7883fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		break;
7893fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	case V4L2_CID_HUE:
7903fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		/* just plain hue control for 12a */
7913fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		setwhite(gspca_dev, ctrl->val, 0);
7923fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		break;
7933fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	case V4L2_CID_EXPOSURE:
7943fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		setexposure(gspca_dev, ctrl->val);
7953fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		break;
7963fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	case V4L2_CID_GAIN:
7973fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		setgain(gspca_dev, ctrl->val);
7983fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		break;
7993fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	case V4L2_CID_AUTOGAIN:
8003fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		setautogain(gspca_dev, ctrl->val);
8013fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		break;
8023fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	}
8033fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	return gspca_dev->usb_err;
8046c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine}
8056c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8063fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
8073fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	.s_ctrl = sd_s_ctrl,
8083fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil};
8096c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36Jean-Francois Moine
8103fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic int sd_init_controls_12a(struct gspca_dev *gspca_dev)
8117879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
8123fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
8137879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8143fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	gspca_dev->vdev.ctrl_handler = hdl;
8153fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	v4l2_ctrl_handler_init(hdl, 3);
8163fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
8173fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
8183fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
819a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
820a8931d5948cdd55f899f107c61f375d34a580304Hans de Goede	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
8213fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			V4L2_CID_EXPOSURE, 1, EXPOSURE_MAX, 1, 700);
8223fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
8233fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			V4L2_CID_GAIN, 0, 255, 1, 63);
8247879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8253fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	if (hdl->error) {
8263fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		pr_err("Could not initialize controls\n");
8273fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		return hdl->error;
8283fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	}
8297879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
8307879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
8317879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8323fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuilstatic int sd_init_controls_72a(struct gspca_dev *gspca_dev)
8337879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine{
8343fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct sd *sd = (struct sd *)gspca_dev;
8353fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
8367879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8373fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	gspca_dev->vdev.ctrl_handler = hdl;
8383fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	v4l2_ctrl_handler_init(hdl, 4);
8393fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
8403fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x20);
8413fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
8423fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
8433fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
8443fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			V4L2_CID_BRIGHTNESS, 0, 0x3f, 1, 0x20);
8453fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
8463fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
8477879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8483fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	if (hdl->error) {
8493fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		pr_err("Could not initialize controls\n");
8503fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil		return hdl->error;
8513fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	}
8523fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	v4l2_ctrl_cluster(2, &sd->contrast);
8537879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return 0;
8547879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine}
8557879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine
8566a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* sub-driver description */
8577879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc sd_desc_12a = {
8586a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.name = MODULE_NAME,
8593fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	.init_controls = sd_init_controls_12a,
8606a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.config = sd_config,
861012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine	.init = sd_init_12a,
8627879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.start = sd_start_12a,
8637879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.stopN = sd_stopN,
8647879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.pkt_scan = sd_pkt_scan,
86560d21563785535e518589ab58b0295ecaa06233fPeter Senna Tschudin#if IS_ENABLED(CONFIG_INPUT)
866436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede	.other_input = 1,
867436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#endif
8687879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
8697879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc sd_desc_72a = {
8707879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.name = MODULE_NAME,
8713fa24bf5e159d10d160015e08decb48cfa1663a8Hans Verkuil	.init_controls = sd_init_controls_72a,
8727879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.config = sd_config,
873012d6b029ec17f45374303bbdccd0bc206725751Jean-Francois Moine	.init = sd_init_72a,
8747879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	.start = sd_start_72a,
8756a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.stopN = sd_stopN,
8766a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.pkt_scan = sd_pkt_scan,
877cebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2aJean-Francois Moine	.dq_callback = do_autogain,
87860d21563785535e518589ab58b0295ecaa06233fPeter Senna Tschudin#if IS_ENABLED(CONFIG_INPUT)
879436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede	.other_input = 1,
880436c2c533a2a2f98d95347f4d5b4022becb046f6Hans de Goede#endif
8816a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
8827879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moinestatic const struct sd_desc *sd_desc[2] = {
8837879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	&sd_desc_12a,
8847879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	&sd_desc_72a
8857879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine};
8866a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
8876a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- module initialisation -- */
88895c967c167785eb991cf6b22fb854dd8d61d0ff8Jean-François Moinestatic const struct usb_device_id device_table[] = {
88987581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
89087581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
89187581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
892f8f73d01a31488ec8e923b2148043579d43d0378John Ellson	{USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
89387581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
89487581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
89587581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
89687581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
89787581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
89887581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
89987581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
90087581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
90187581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
90287581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
90387581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
90487581aa5f10959224fc7e1a30ac9af53949d0ef2Jean-Francois Moine	{USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
9056a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	{}
9066a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
9076a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
9086a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois MoineMODULE_DEVICE_TABLE(usb, device_table);
9096a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
9106a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine/* -- device connect -- */
9116a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic int sd_probe(struct usb_interface *intf,
9126a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine		    const struct usb_device_id *id)
9136a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine{
9147879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine	return gspca_dev_probe(intf, id,
9157879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine				sd_desc[id->driver_info],
9167879d459f1601be742d0d63930d17cd4aac956fdJean-Francois Moine				sizeof(struct sd),
9176a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine			       THIS_MODULE);
9186a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine}
9196a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
9206a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moinestatic struct usb_driver sd_driver = {
9216a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.name = MODULE_NAME,
9226a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.id_table = device_table,
9236a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.probe = sd_probe,
9246a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine	.disconnect = gspca_disconnect,
9256a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine#ifdef CONFIG_PM
9266a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine	.suspend = gspca_suspend,
9276a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine	.resume = gspca_resume,
9288bb58964bc139d5ff5285f84aa302977d221754dHans de Goede	.reset_resume = gspca_resume,
9296a709749228c5f76f128c69c16f39a52d639bd96Jean-Francois Moine#endif
9306a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine};
9316a7eba24e4f0ff725d33159f6265e3a79d53a833Jean-Francois Moine
932ecb3b2b35db49778b6d89e3ffd0c400776c20735Greg Kroah-Hartmanmodule_usb_driver(sd_driver);
933