11408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*
2ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine * Pixart PAC7302 driver
31408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
4ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
5ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
61408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
7cc2f82c22f3f954f0858642bd782f48e8ccbf058Jean-Francois Moine * Separated from Pixart PAC7311 library by Márton Németh
8aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh * Camera button input handling by Márton Németh <nm127@freemail.hu>
9aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is free software; you can redistribute it and/or modify
121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * it under the terms of the GNU General Public License as published by
131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * the Free Software Foundation; either version 2 of the License, or
141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * any later version.
151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is distributed in the hope that it will be useful,
171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * but WITHOUT ANY WARRANTY; without even the implied warranty of
181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * GNU General Public License for more details.
201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * You should have received a copy of the GNU General Public License
221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * along with this program; if not, write to the Free Software
231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth */
251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* Some documentation about various registers as determined by trial and error.
271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Register page 1:
291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x78		Global control, bit 6 controls the LED (inverted)
321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
335fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   Register page 3:
341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
365fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   0x02		Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
385fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   0x03		Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
395fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   0x04		Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
405fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede		63 -> ~27 fps, the 2 msb's must always be 1 !!
415fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   0x05		Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
425fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede		1 -> ~30 fps, 2 -> ~20 fps
435fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   0x0e		Exposure bits 0-7, 0-448, 0 = use full frame time
445fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   0x0f		Exposure bit 8, 0-448, 448 = no exposure at all
455fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede   0x10		Master gain 0-31
461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
47265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
48265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   The registers are accessed in the following functions:
49265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
50265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   Page | Register   | Function
51265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   -----+------------+---------------------------------------------------
52265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0x0f..0x20 | setcolors()
53265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xa2..0xab | setbrightcont()
54265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc5       | setredbalance()
5523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth    0   | 0xc6       | setwhitebalance()
56265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc7       | setbluebalance()
57265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xdc       | setbrightcont(), setcolors()
58265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x02       | setexposure()
59265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x10       | setgain()
60265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x11       | setcolors(), setgain(), setexposure(), sethvflip()
61265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x21       | sethvflip()
621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth*/
631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
64133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
65133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches
66aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#include <linux/input.h>
676763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#include <media/v4l2-chip-ident.h>
681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#include "gspca.h"
69ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine/* Include pac common sof detection functions */
70ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine#include "pac_common.h"
711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
72ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François MoineMODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
73ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		"Thomas Kaiser thomas@kaiser-linux.li");
741408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DESCRIPTION("Pixart PAC7302");
751408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_LICENSE("GPL");
761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
77aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moineenum e_ctrl {
78aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	BRIGHTNESS,
79aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	CONTRAST,
80aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	COLORS,
81aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	WHITE_BALANCE,
82aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	RED_BALANCE,
83aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	BLUE_BALANCE,
84aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	GAIN,
85aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	AUTOGAIN,
86aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	EXPOSURE,
87aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	VFLIP,
88aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	HFLIP,
89aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	NCTRLS		/* number of controls */
90aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine};
91aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine
921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* specific webcam descriptor for pac7302 */
931408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstruct sd {
941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct gspca_dev gspca_dev;		/* !! must be the first item */
951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
96aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	struct gspca_ctrl ctrls[NCTRLS];
97aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine
98fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	u8 flags;
99fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine#define FL_HFLIP 0x01		/* mirrored by default */
100fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine#define FL_VFLIP 0x02		/* vertical flipped by default */
1011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	u8 sof_read;
103ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	s8 autogain_ignore_frames;
1041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	atomic_t avg_lum;
1061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
1071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* V4L2 controls supported by the driver */
109aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void setbrightcont(struct gspca_dev *gspca_dev);
110aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void setcolors(struct gspca_dev *gspca_dev);
111aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void setwhitebalance(struct gspca_dev *gspca_dev);
112aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void setredbalance(struct gspca_dev *gspca_dev);
113aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void setbluebalance(struct gspca_dev *gspca_dev);
114aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void setgain(struct gspca_dev *gspca_dev);
115aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void setexposure(struct gspca_dev *gspca_dev);
116ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moinestatic void setautogain(struct gspca_dev *gspca_dev);
117aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moinestatic void sethvflip(struct gspca_dev *gspca_dev);
1181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1197e64dc4c4d6f5c8935fac25c7fc7aa83f9880ed7Marton Nemethstatic const struct ctrl sd_ctrls[] = {
120aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[BRIGHTNESS] = {
1211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_BRIGHTNESS,
1231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Brightness",
1251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define BRIGHTNESS_MAX 0x20
1271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = BRIGHTNESS_MAX,
1281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
129aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 0x10,
1301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
131aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setbrightcont
1321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
133aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[CONTRAST] = {
1341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_CONTRAST,
1361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Contrast",
1381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define CONTRAST_MAX 255
1401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = CONTRAST_MAX,
1411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
142aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 127,
1431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
144aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setbrightcont
1451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
146aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[COLORS] = {
1471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_SATURATION,
1491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Saturation",
1511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define COLOR_MAX 255
1531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = COLOR_MAX,
1541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
155aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 127
1561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
157aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setcolors
1581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
159aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[WHITE_BALANCE] = {
160265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
16123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.id      = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
16223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
16323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.name    = "White Balance",
16423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.minimum = 0,
16523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.maximum = 255,
16623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.step    = 1,
167aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 4,
16823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    },
169aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setwhitebalance
17023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	},
171aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[RED_BALANCE] = {
17223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    {
173265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_RED_BALANCE,
174265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
175265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Red",
176265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
177265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
178265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
179aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 1,
180265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
181aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setredbalance
182265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
183aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[BLUE_BALANCE] = {
184265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
185265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_BLUE_BALANCE,
186265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
187265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Blue",
188265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
189265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
190265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
191aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 1,
192265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
193aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setbluebalance
194265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
195aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[GAIN] = {
1961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_GAIN,
1981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Gain",
2001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
201aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.maximum = 255,
2021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_DEF 127
2041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
2051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = GAIN_DEF,
2061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
207aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setgain
2081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
209aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[EXPOSURE] = {
2101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_EXPOSURE,
2121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
2131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Exposure",
2141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2155fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede		.maximum = 1023,
2161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2175fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede#define EXPOSURE_DEF  66  /*  33 ms / 30 fps */
2185fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede#define EXPOSURE_KNEE 133 /*  66 ms / 15 fps */
2191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = EXPOSURE_DEF,
2201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
221aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = setexposure
2221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
223aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[AUTOGAIN] = {
2241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_AUTOGAIN,
2261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Auto Gain",
2281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define AUTOGAIN_DEF 1
2321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = AUTOGAIN_DEF,
2331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
234ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	    .set_control = setautogain,
2351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
236aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[HFLIP] = {
2371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_HFLIP,
2391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Mirror",
2411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
244aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 0,
2451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
246aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = sethvflip,
2471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
248aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine[VFLIP] = {
2491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_VFLIP,
2511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Vflip",
2531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
256aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		.default_value = 0,
2571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
258aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	    .set_control = sethvflip
2591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
2611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
2621408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const struct v4l2_pix_format vga_mode[] = {
2631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
2641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.bytesperline = 640,
2651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.sizeimage = 640 * 480 * 3 / 8 + 590,
2661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.colorspace = V4L2_COLORSPACE_JPEG,
267ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	},
2681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
2691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
2701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define LOAD_PAGE3		255
2711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define END_OF_SEQUENCE		0
2721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
2731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* pac 7302 */
274ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moinestatic const u8 init_7302[] = {
2751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index,value */
2761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,		/* page 1 */
2771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x00,		/* deactivate */
2781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,
2791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x40,		/* led off */
2801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
281ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moinestatic const u8 start_7302[] = {
2821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index, len, [value]* */
2831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x00,		/* page 0 */
2841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 12,	0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
2851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x00, 0x00, 0x00,
2861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0d, 24,	0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
2871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
2881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
2891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x26, 2,	0xaa, 0xaa,
2901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2e, 1,	0x31,
2911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x38, 1,	0x01,
2921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3a, 3,	0x14, 0xff, 0x5a,
2931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x43, 11,	0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
2941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x54, 0x11,
2951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x55, 1,	0x00,
296ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	0x62, 4,	0x10, 0x1e, 0x1e, 0x18,
2971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6b, 1,	0x00,
2981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 3,	0x08, 0x06, 0x00,
2991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x72, 3,	0x00, 0xff, 0x00,
3001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7d, 23,	0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
3011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
3021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
3031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa2, 10,	0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
3041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xd2, 0xeb,
3051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xaf, 1,	0x02,
3061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb5, 2,	0x08, 0x08,
3071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb8, 2,	0x08, 0x88,
3081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc4, 4,	0xae, 0x01, 0x04, 0x01,
3091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xcc, 1,	0x00,
3101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd1, 11,	0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
3111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xc1, 0xd7, 0xec,
3121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdc, 1,	0x01,
3131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x12, 3,	0x02, 0x00, 0x01,
3151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3e, 2,	0x00, 0x00,
3161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x76, 5,	0x01, 0x20, 0x40, 0x00, 0xf2,
3171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7c, 1,	0x00,
3181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7f, 10,	0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
3191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x02, 0x00,
3201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x96, 5,	0x01, 0x10, 0x04, 0x01, 0x04,
3211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 14,	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
3221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
3231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd8, 1,	0x01,
3241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdb, 2,	0x00, 0x01,
3251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xde, 7,	0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
3261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xe6, 4,	0x00, 0x00, 0x00, 0x01,
3271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xeb, 1,	0x00,
3281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 1,	0x00,
3301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x03,		/* page 3 */
3311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, LOAD_PAGE3,			/* load the page 3 */
3321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x11, 1,	0x01,
3331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x13, 1,	0x00,
3351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 4,	0x1f, 0xa4, 0xf0, 0x96,
3361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x27, 2,	0x14, 0x0c,
3371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2a, 5,	0xc8, 0x00, 0x18, 0x12, 0x22,
3381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x64, 8,	0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
3391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 1,	0x08,
3401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 1,	0x00,
3421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, END_OF_SEQUENCE		/* end of sequence */
3431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define SKIP		0xaa
3461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* page 3 - the value SKIP says skip the index - see reg_w_page() */
347ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moinestatic const u8 page3_7302[] = {
3485fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
3491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
3501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
3521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
3531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
3541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
3551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
357cdf955cd8e45d8279c53b47a2c0e0c5decaaca86Jean-Francois Moine	SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
3581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
3601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
3621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
3631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
3641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
3651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
3671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00
3681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
370be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_buf(struct gspca_dev *gspca_dev,
371ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		u8 index,
3720aeb5ec74b0a95f1699040f0262a6fd5507d6e8fJean-François Moine		  const u8 *buffer, int len)
3731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
3744f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
3754f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
376be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (gspca_dev->usb_err < 0)
377be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		return;
3781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	memcpy(gspca_dev->usb_buf, buffer, len);
3794f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
3801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
381a1317135d109f4b6dd89caa1a9b2b6c8d54b09cdJean-François Moine			0,		/* request */
3821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
3831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,		/* value */
3841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			index, gspca_dev->usb_buf, len,
3851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
386be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (ret < 0) {
387ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		pr_err("reg_w_buf failed i: %02x error %d\n",
388133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		       index, ret);
389be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		gspca_dev->usb_err = ret;
390be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	}
3911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
3921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
394be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w(struct gspca_dev *gspca_dev,
395ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		u8 index,
396ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		u8 value)
3971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
3984f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
3994f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
400be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (gspca_dev->usb_err < 0)
401be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		return;
4021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_dev->usb_buf[0] = value;
4034f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
4041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
4051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,			/* request */
4061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0, index, gspca_dev->usb_buf, 1,
4081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
409be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (ret < 0) {
410ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		pr_err("reg_w() failed i: %02x v: %02x error %d\n",
411133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches		       index, value, ret);
412be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		gspca_dev->usb_err = ret;
413be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	}
4141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
416be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_seq(struct gspca_dev *gspca_dev,
417ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		const u8 *seq, int len)
4181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	while (--len >= 0) {
420be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, seq[0], seq[1]);
4211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		seq += 2;
4221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
4231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* load the beginning of a page */
426be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_page(struct gspca_dev *gspca_dev,
427ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine			const u8 *page, int len)
4281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index;
430b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
432be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (gspca_dev->usb_err < 0)
433be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		return;
4341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (index = 0; index < len; index++) {
4351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (page[index] == SKIP)		/* skip this index */
4361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			continue;
4371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		gspca_dev->usb_buf[0] = page[index];
4384f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		ret = usb_control_msg(gspca_dev->dev,
4391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				usb_sndctrlpipe(gspca_dev->dev, 0),
4401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0,			/* request */
4411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0, index, gspca_dev->usb_buf, 1,
4431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				500);
444b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (ret < 0) {
445ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine			pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
446133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches			       index, page[index], ret);
447be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine			gspca_dev->usb_err = ret;
448b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			break;
449b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		}
4501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
4511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* output a variable sequence */
454be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_var(struct gspca_dev *gspca_dev,
455ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine			const u8 *seq,
456ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine			const u8 *page3, unsigned int page3_len)
4571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index, len;
4591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (;;) {
4611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		index = *seq++;
4621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len = *seq++;
4631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		switch (len) {
4641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case END_OF_SEQUENCE:
465be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine			return;
4661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case LOAD_PAGE3:
467be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine			reg_w_page(gspca_dev, page3, page3_len);
4681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			break;
4691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		default:
470ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine#ifdef GSPCA_DEBUG
4711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			if (len > USB_BUF_SZ) {
4721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				PDEBUG(D_ERR|D_STREAM,
4731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					"Incorrect variable sequence");
474be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine				return;
4751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
476ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine#endif
4771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			while (len > 0) {
4781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				if (len < 8) {
479be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine					reg_w_buf(gspca_dev,
480b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh						index, seq, len);
4811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					seq += len;
4821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					break;
4831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				}
484be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine				reg_w_buf(gspca_dev, index, seq, 8);
4851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				seq += 8;
4861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				index += 8;
4871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				len -= 8;
4881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
4891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
4901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
4911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* not reached */
4921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe time for pac7302 */
4951408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_config(struct gspca_dev *gspca_dev,
4961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
4971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
4991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct cam *cam;
5001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam = &gspca_dev->cam;
5021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->cam_mode = vga_mode;	/* only 640x480 */
5041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->nmodes = ARRAY_SIZE(vga_mode);
5051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
506aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	gspca_dev->cam.ctrls = sd->ctrls;
507aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine
508fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	sd->flags = id->driver_info;
5091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
5101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
513be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setbrightcont(struct gspca_dev *gspca_dev)
5141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
517ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	static const u8 max[10] =
5181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
5191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0xd4, 0xec};
520ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	static const u8 delta[10] =
5211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
5221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0x11, 0x0b};
5231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
524be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
5251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 10; i++) {
5261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v = max[i];
527aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		v += (sd->ctrls[BRIGHTNESS].val - BRIGHTNESS_MAX)
5281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			* 150 / BRIGHTNESS_MAX;		/* 200 ? */
529aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		v -= delta[i] * sd->ctrls[CONTRAST].val / CONTRAST_MAX;
5301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (v < 0)
5311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0;
5321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		else if (v > 0xff)
5331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0xff;
534be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0xa2 + i, v);
5351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
536be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
5371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
540be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setcolors(struct gspca_dev *gspca_dev)
5411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
5441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int a[9] =
5451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{217, -212, 0, -101, 170, -67, -38, -315, 355};
5461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int b[9] =
5471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{19, 106, 0, 19, 106, 1, 19, 106, 1};
5481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
549be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
550be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
551be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
5521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 9; i++) {
553aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine		v = a[i] * sd->ctrls[COLORS].val / COLOR_MAX + b[i];
554be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
555be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
5561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
557be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
5581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
560be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setwhitebalance(struct gspca_dev *gspca_dev)
56123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
56223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
56323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
564be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
565aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	reg_w(gspca_dev, 0xc6, sd->ctrls[WHITE_BALANCE].val);
56623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
567be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
56823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
56923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
570be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setredbalance(struct gspca_dev *gspca_dev)
571265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
572265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
573265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
574be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
575aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	reg_w(gspca_dev, 0xc5, sd->ctrls[RED_BALANCE].val);
576265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
577be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
578265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
579265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
580be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setbluebalance(struct gspca_dev *gspca_dev)
581265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
582265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
583265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
584be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
585aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	reg_w(gspca_dev, 0xc7, sd->ctrls[BLUE_BALANCE].val);
586265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
587be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
588265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
589265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
590be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setgain(struct gspca_dev *gspca_dev)
5911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
594be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
595aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3);
5961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
598be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
5991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
601be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setexposure(struct gspca_dev *gspca_dev)
6021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
604ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	u8 clockdiv;
605ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	u16 exposure;
6065fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede
6075fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	/* register 2 of frame 3 contains the clock divider configuring the
6085fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	   no fps according to the formula: 90 / reg. sd->exposure is the
6095fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	   desired exposure time in 0.5 ms. */
610aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000;
6115fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede
6125fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	/* Note clockdiv = 3 also works, but when running at 30 fps, depending
6135fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	   on the scene being recorded, the camera switches to another
6145fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	   quantization table for certain JPEG blocks, and we don't know how
6155fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	   to decompress these blocks. So we cap the framerate at 15 fps */
6165fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	if (clockdiv < 6)
6175fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede		clockdiv = 6;
6185fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	else if (clockdiv > 63)
6195fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede		clockdiv = 63;
6205fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede
6215fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	/* reg2 MUST be a multiple of 3, except when between 6 and 12?
6225fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	   Always round up, otherwise we cannot get the desired frametime
6235fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	   using the partial frame time exposure control */
6245fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	if (clockdiv < 6 || clockdiv > 12)
6255fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede		clockdiv = ((clockdiv + 2) / 3) * 3;
6265fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede
6275fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	/* frame exposure time in ms = 1000 * clockdiv / 90    ->
6285fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
629aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv);
6305fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	/* 0 = use full frametime, 448 = no exposure, reverse it */
6315fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	exposure = 448 - exposure;
6325fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede
633be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
6345fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	reg_w(gspca_dev, 0x02, clockdiv);
6355fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	reg_w(gspca_dev, 0x0e, exposure & 0xff);
6365fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	reg_w(gspca_dev, 0x0f, exposure >> 8);
6371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
639be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
6401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
642ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moinestatic void setautogain(struct gspca_dev *gspca_dev)
643ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine{
644ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	struct sd *sd = (struct sd *) gspca_dev;
645ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine
646ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	/* when switching to autogain set defaults to make sure
647ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	   we are on a valid point of the autogain gain /
648ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	   exposure knee graph, and give this change time to
649ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	   take effect before doing autogain. */
650ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	if (sd->ctrls[AUTOGAIN].val) {
651ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine		sd->ctrls[EXPOSURE].val = EXPOSURE_DEF;
652ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine		sd->ctrls[GAIN].val = GAIN_DEF;
653ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine		sd->autogain_ignore_frames =
654ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine				PAC_AUTOGAIN_IGNORE_FRAMES;
655ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	} else {
656ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine		sd->autogain_ignore_frames = -1;
657ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	}
658ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	setexposure(gspca_dev);
659ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	setgain(gspca_dev);
660ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine}
661ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine
662be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void sethvflip(struct gspca_dev *gspca_dev)
6631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
665fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	u8 data, hflip, vflip;
666fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine
667aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	hflip = sd->ctrls[HFLIP].val;
668fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	if (sd->flags & FL_HFLIP)
669fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine		hflip = !hflip;
670aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine	vflip = sd->ctrls[VFLIP].val;
671fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	if (sd->flags & FL_VFLIP)
672fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine		vflip = !vflip;
6731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
674be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
675fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
676be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x21, data);
677be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine
6781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
679be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
6801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe and resume time for pac7302 */
6831408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_init(struct gspca_dev *gspca_dev)
6841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
685be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
686be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
6871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6891408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_start(struct gspca_dev *gspca_dev)
6901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
6921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
693be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w_var(gspca_dev, start_7302,
69423a5de202bc385b69eb91a5db36699e9579ec03eJean-Francois Moine		page3_7302, sizeof(page3_7302));
695be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setbrightcont(gspca_dev);
696be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setcolors(gspca_dev);
697be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setwhitebalance(gspca_dev);
698be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setredbalance(gspca_dev);
699be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setbluebalance(gspca_dev);
700ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	setautogain(gspca_dev);
701be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	sethvflip(gspca_dev);
7021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* only resolution 640x480 is supported for pac7302 */
7041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->sof_read = 0;
706ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val);
7071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* start stream */
709be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x01);
710be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x78, 0x01);
7111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
712be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
7131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7151408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stopN(struct gspca_dev *gspca_dev)
7161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
717b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh
71867c98f72e132e191ff4db0ac7bd81ea94fa5c667Márton Németh	/* stop stream */
719be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x01);
720be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x78, 0x00);
7211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* called on streamoff with alt 0 and on disconnect for pac7302 */
7241408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stop0(struct gspca_dev *gspca_dev)
7251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (!gspca_dev->present)
7271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
728be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x01);
729be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x78, 0x40);
7301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
732aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine/* !! coarse_grained_expo_autogain is not used !! */
733aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine#define exp_too_low_cnt flags
734aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine#define exp_too_high_cnt sof_read
735aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine#include "autogain_functions.h"
736aa5b7925f19f9bb586136fef55188deaf094805dJean-François Moine
7371408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void do_autogain(struct gspca_dev *gspca_dev)
7381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
7401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int avg_lum = atomic_read(&sd->avg_lum);
7415fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	int desired_lum;
7425fb2dde28122e74bbab9dae3cc04bcbc8c08b332Hans de Goede	const int deadzone = 30;
7431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
744ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	if (sd->autogain_ignore_frames < 0)
7451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
7461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
747ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	if (sd->autogain_ignore_frames > 0) {
7481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames--;
749ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	} else {
750ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine		desired_lum = 270 + sd->ctrls[BRIGHTNESS].val;
751ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine
752ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine		auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
753ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine				deadzone, GAIN_KNEE, EXPOSURE_KNEE);
7541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
755ac399cd313f13d5208567c01ff70a476605804b7Jean-François Moine	}
7561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7587532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine/* JPEG header */
7597532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moinestatic const u8 jpeg_header[] = {
7607532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0xff, 0xd8,	/* SOI: Start of Image */
7617532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine
7627532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0xff, 0xc0,	/* SOF0: Start of Frame (Baseline DCT) */
7637532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x00, 0x11,	/* length = 17 bytes (including this length field) */
7647532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x08,		/* Precision: 8 */
7657532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x02, 0x80,	/* height = 640 (image rotated) */
7667532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x01, 0xe0,	/* width = 480 */
7677532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x03,		/* Number of image components: 3 */
7687532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
7697532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
7707532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
7717532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine
7727532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0xff, 0xda,	/* SOS: Start Of Scan */
7737532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x00, 0x0c,	/* length = 12 bytes (including this length field) */
7747532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x03,		/* number of components: 3 */
7757532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x01, 0x00,	/* selector 1, table 0x00 */
7767532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x02, 0x11,	/* selector 2, table 0x11 */
7777532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x03, 0x11,	/* selector 3, table 0x11 */
7787532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x00, 0x3f,	/* Spectral selection: 0 .. 63 */
7797532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine	0x00		/* Successive approximation: 0 */
7801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
7811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is run at interrupt level */
7831408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
78476dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			u8 *data,			/* isoc packet */
7851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			int len)			/* iso packet length */
7861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
788b192ca983746585e807259414f8d6f58cb28311fJean-François Moine	u8 *image;
789ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	u8 *sof;
7901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sof = pac_find_sof(&sd->sof_read, data, len);
7921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sof) {
7931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		int n, lum_offset, footer_length;
7941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* 6 bytes after the FF D9 EOF marker a number of lumination
7961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   bytes are send corresponding to different parts of the
7971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   image, the 14th and 15th byte after the EOF seem to
7981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   correspond to the center of the image */
7991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		lum_offset = 61 + sizeof pac_sof_marker;
8001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		footer_length = 74;
8011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Finish decoding current frame */
8031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
8041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (n < 0) {
805b192ca983746585e807259414f8d6f58cb28311fJean-François Moine			gspca_dev->image_len += n;
8061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			n = 0;
807b192ca983746585e807259414f8d6f58cb28311fJean-François Moine		} else {
808b192ca983746585e807259414f8d6f58cb28311fJean-François Moine			gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
8091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
810f7059eaa285c0460569ffd26c43ae07e3f03cd6cJean-François Moine
811f7059eaa285c0460569ffd26c43ae07e3f03cd6cJean-François Moine		image = gspca_dev->image;
812f7059eaa285c0460569ffd26c43ae07e3f03cd6cJean-François Moine		if (image != NULL
813b192ca983746585e807259414f8d6f58cb28311fJean-François Moine		 && image[gspca_dev->image_len - 2] == 0xff
814b192ca983746585e807259414f8d6f58cb28311fJean-François Moine		 && image[gspca_dev->image_len - 1] == 0xd9)
815b192ca983746585e807259414f8d6f58cb28311fJean-François Moine			gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
8161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = sof - data;
8181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len -= n;
8191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		data = sof;
8201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Get average lumination */
8221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->last_packet_type == LAST_PACKET &&
8231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				n >= lum_offset)
8241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			atomic_set(&sd->avg_lum, data[-lum_offset] +
8251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth						data[-lum_offset + 1]);
8261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Start the new frame with the jpeg header */
8281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* The PAC7302 has the image rotated 90 degrees */
8297532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine		gspca_frame_add(gspca_dev, FIRST_PACKET,
8307532e815995da3c83d28dc051ab62a03a7788ab4Jean-François Moine				jpeg_header, sizeof jpeg_header);
8311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
83276dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
8331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8356763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#ifdef CONFIG_VIDEO_ADV_DEBUG
8366763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Némethstatic int sd_dbg_s_register(struct gspca_dev *gspca_dev,
8376763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			struct v4l2_dbg_register *reg)
8386763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh{
839ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	u8 index;
840ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	u8 value;
8416763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
8426763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	/* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
8436763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			       long on the USB bus)
8446763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	*/
8456763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
8466763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    reg->match.addr == 0 &&
8476763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    (reg->reg < 0x000000ff) &&
8486763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    (reg->val <= 0x000000ff)
8496763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	) {
8506763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* Currently writing to page 0 is only supported. */
8516763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* reg_w() only supports 8bit index */
852ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		index = reg->reg;
853ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine		value = reg->val;
8546763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
8556763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* Note that there shall be no access to other page
8566763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		   by any other function between the page swith and
8576763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		   the actual register write */
858be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
859be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, index, value);
8606763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
861be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0xdc, 0x01);
8626763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	}
863be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
8646763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh}
8656763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
8666763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Némethstatic int sd_chip_ident(struct gspca_dev *gspca_dev,
8676763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			struct v4l2_dbg_chip_ident *chip)
8686763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh{
8696763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	int ret = -EINVAL;
8706763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
8716763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
8726763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    chip->match.addr == 0) {
8736763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		chip->revision = 0;
8746763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		chip->ident = V4L2_IDENT_UNKNOWN;
8756763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		ret = 0;
8766763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	}
8776763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	return ret;
8786763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh}
8796763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#endif
8806763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
8812856643e2e18f306227ae1257b63fc713d426dc7Jean-François Moine#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
882aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Némethstatic int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
883aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			u8 *data,		/* interrupt packet data */
884aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			int len)		/* interrput packet length */
885aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh{
886aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	int ret = -EINVAL;
887aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	u8 data0, data1;
888aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh
889aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	if (len == 2) {
890aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		data0 = data[0];
891aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		data1 = data[1];
892aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		if ((data0 == 0x00 && data1 == 0x11) ||
893aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x22 && data1 == 0x33) ||
894aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x44 && data1 == 0x55) ||
895aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x66 && data1 == 0x77) ||
896aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x88 && data1 == 0x99) ||
897aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0xaa && data1 == 0xbb) ||
898aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0xcc && data1 == 0xdd) ||
899aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0xee && data1 == 0xff)) {
900aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
901aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_sync(gspca_dev->input_dev);
902aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
903aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_sync(gspca_dev->input_dev);
904aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			ret = 0;
905aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		}
906aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	}
907aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh
908aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	return ret;
909aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh}
910aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#endif
911aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh
9121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* sub-driver description for pac7302 */
913aabcdfb65be31d7f9486d1400fa217c8827dddd3Márton Némethstatic const struct sd_desc sd_desc = {
914ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	.name = KBUILD_MODNAME,
9151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.ctrls = sd_ctrls,
9161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.nctrls = ARRAY_SIZE(sd_ctrls),
9171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.config = sd_config,
9181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.init = sd_init,
9191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.start = sd_start,
9201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stopN = sd_stopN,
9211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stop0 = sd_stop0,
9221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.pkt_scan = sd_pkt_scan,
9231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.dq_callback = do_autogain,
9246763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#ifdef CONFIG_VIDEO_ADV_DEBUG
9256763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	.set_register = sd_dbg_s_register,
9266763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	.get_chip_ident = sd_chip_ident,
9276763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#endif
9282856643e2e18f306227ae1257b63fc713d426dc7Jean-François Moine#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
929aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	.int_pkt_scan = sd_int_pkt_scan,
930aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#endif
9311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
9321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- module initialisation -- */
93495c967c167785eb991cf6b22fb854dd8d61d0ff8Jean-François Moinestatic const struct usb_device_id device_table[] = {
9351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x06f8, 0x3009)},
936dd32f98120e7a763b125a3d5f60799a97b0a2b51Jean-François Moine	{USB_DEVICE(0x06f8, 0x301b)},
9371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2620)},
9381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2621)},
939fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	{USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
940fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	{USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
9414e6aeefeb822c70d70de4d3b9970939e5de9c647Márton Németh	{USB_DEVICE(0x093a, 0x2625)},
9421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2626)},
9431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2628)},
944c4322bfca8907109689eb6b244258bf52277f7dcJean-Francois Moine	{USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
9451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262a)},
9461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262c)},
9474d6454dbae935825e729f34dc7410bb1b22c7944Hans de Goede	{USB_DEVICE(0x145f, 0x013c)},
9481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{}
9491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
9501408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DEVICE_TABLE(usb, device_table);
9511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- device connect -- */
95395c967c167785eb991cf6b22fb854dd8d61d0ff8Jean-François Moinestatic int sd_probe(struct usb_interface *intf,
9541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
9551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
9571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				THIS_MODULE);
9581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9601408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct usb_driver sd_driver = {
961ae251e6b18cff8c1bd1d825f8862b083a33be421Jean-François Moine	.name = KBUILD_MODNAME,
9621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.id_table = device_table,
9631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.probe = sd_probe,
9641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.disconnect = gspca_disconnect,
9651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#ifdef CONFIG_PM
9661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.suspend = gspca_suspend,
9671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.resume = gspca_resume,
9681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#endif
9691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
9701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
971ecb3b2b35db49778b6d89e3ffd0c400776c20735Greg Kroah-Hartmanmodule_usb_driver(sd_driver);
972