pac7302.c revision 23fbee6f88d59b4edca0855242d55e5b7cfc2401
11408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*
21408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *		Pixart PAC7302 library
31408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *		Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
41408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
51408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
61408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
71408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * Separated from Pixart PAC7311 library by M�rton N�meth <nm127@freemail.hu>
81408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
91408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is free software; you can redistribute it and/or modify
101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * it under the terms of the GNU General Public License as published by
111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * the Free Software Foundation; either version 2 of the License, or
121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * any later version.
131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is distributed in the hope that it will be useful,
151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * but WITHOUT ANY WARRANTY; without even the implied warranty of
161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * GNU General Public License for more details.
181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * You should have received a copy of the GNU General Public License
201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * along with this program; if not, write to the Free Software
211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth */
231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* Some documentation about various registers as determined by trial and error.
251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   When the register addresses differ between the 7202 and the 7311 the 2
261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   different addresses are written as 7302addr/7311addr, when one of the 2
271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   addresses is a - sign that register description is not valid for the
281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   matching IC.
291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Register page 1:
311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x08	Unknown compressor related, must always be 8 except when not
341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x1b	Auto white balance related, bit 0 is AWB enable (inverted)
361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		bits 345 seem to toggle per color gains on/off (inverted)
371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x78		Global control, bit 6 controls the LED (inverted)
381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x80	JPEG compression ratio ? Best not touched
391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Register page 3/4:
411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x02		Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x0f	Master gain 1-245, low value = high gain
461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x10/-	Master gain 0-31
471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x10	Another gain 0-15, limited influence (1-2x gain I guess)
481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x27	Seems to toggle various gains on / off, Setting bit 7 seems to
501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		completely disable the analog amplification block. Set to 0x68
511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		for max gain, 0x14 for minimal gain.
52265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
53265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   The registers are accessed in the following functions:
54265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
55265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   Page | Register   | Function
56265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   -----+------------+---------------------------------------------------
57265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0x0f..0x20 | setcolors()
58265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xa2..0xab | setbrightcont()
59265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc5       | setredbalance()
6023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth    0   | 0xc6       | setwhitebalance()
61265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc7       | setbluebalance()
62265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xdc       | setbrightcont(), setcolors()
63265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x02       | setexposure()
64265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x10       | setgain()
65265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x11       | setcolors(), setgain(), setexposure(), sethvflip()
66265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x21       | sethvflip()
671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth*/
681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define MODULE_NAME "pac7302"
701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#include "gspca.h"
721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
731408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
741408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DESCRIPTION("Pixart PAC7302");
751408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_LICENSE("GPL");
761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* specific webcam descriptor for pac7302 */
781408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstruct sd {
791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct gspca_dev gspca_dev;		/* !! must be the first item */
801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char brightness;
821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char contrast;
831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char colors;
8423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	unsigned char white_balance;
85265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	unsigned char red_balance;
86265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	unsigned char blue_balance;
871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char gain;
881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char exposure;
891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char autogain;
901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 hflip;
911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 vflip;
921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	u8 sof_read;
941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	u8 autogain_ignore_frames;
951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	atomic_t avg_lum;
971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* V4L2 controls supported by the driver */
1001408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
1011408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
1021408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
1031408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
1041408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
1051408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
10623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
10723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
108265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
109265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
110265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
111265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
1121408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
1131408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
1141408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
1151408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
1161408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
1171408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
1181408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
1191408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
1201408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
1211408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
1221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1231408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct ctrl sd_ctrls[] = {
1241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is pac7302 only */
1251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_BRIGHTNESS,
1281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Brightness",
1301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define BRIGHTNESS_MAX 0x20
1321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = BRIGHTNESS_MAX,
1331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define BRIGHTNESS_DEF 0x10
1351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = BRIGHTNESS_DEF,
1361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setbrightness,
1381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getbrightness,
1391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
1401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is for both the 7302 and the 7311 */
1411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_CONTRAST,
1441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Contrast",
1461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define CONTRAST_MAX 255
1481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = CONTRAST_MAX,
1491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define CONTRAST_DEF 127
1511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = CONTRAST_DEF,
1521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setcontrast,
1541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getcontrast,
1551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
1561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is pac7302 only */
1571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_SATURATION,
1601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Saturation",
1621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define COLOR_MAX 255
1641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = COLOR_MAX,
1651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define COLOR_DEF 127
1671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = COLOR_DEF,
1681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setcolors,
1701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getcolors,
1711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
172265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	{
173265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
17423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.id      = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
17523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
17623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.name    = "White Balance",
17723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.minimum = 0,
17823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.maximum = 255,
17923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.step    = 1,
18023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth#define WHITEBALANCE_DEF 4
18123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.default_value = WHITEBALANCE_DEF,
18223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    },
18323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    .set = sd_setwhitebalance,
18423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    .get = sd_getwhitebalance,
18523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	},
18623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	{
18723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    {
188265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_RED_BALANCE,
189265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
190265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Red",
191265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
192265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
193265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
194265a8098e75e156985abfaac250ee4f2b407f863Márton Németh#define REDBALANCE_DEF 1
195265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.default_value = REDBALANCE_DEF,
196265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
197265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .set = sd_setredbalance,
198265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .get = sd_getredbalance,
199265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
200265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	{
201265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
202265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_BLUE_BALANCE,
203265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
204265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Blue",
205265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
206265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
207265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
208265a8098e75e156985abfaac250ee4f2b407f863Márton Németh#define BLUEBALANCE_DEF 1
209265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.default_value = BLUEBALANCE_DEF,
210265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
211265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .set = sd_setbluebalance,
212265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .get = sd_getbluebalance,
213265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
2141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* All controls below are for both the 7302 and the 7311 */
2151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_GAIN,
2181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
2191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Gain",
2201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_MAX 255
2221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = GAIN_MAX,
2231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_DEF 127
2251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
2261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = GAIN_DEF,
2271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setgain,
2291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getgain,
2301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_EXPOSURE,
2341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
2351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Exposure",
2361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_MAX 255
2381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = EXPOSURE_MAX,
2391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
2411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
2421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = EXPOSURE_DEF,
2431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setexposure,
2451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getexposure,
2461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_AUTOGAIN,
2501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Auto Gain",
2521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define AUTOGAIN_DEF 1
2561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = AUTOGAIN_DEF,
2571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setautogain,
2591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getautogain,
2601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_HFLIP,
2641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Mirror",
2661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define HFLIP_DEF 0
2701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = HFLIP_DEF,
2711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_sethflip,
2731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_gethflip,
2741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_VFLIP,
2781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Vflip",
2801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define VFLIP_DEF 0
2841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = VFLIP_DEF,
2851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setvflip,
2871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getvflip,
2881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
2901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
2911408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const struct v4l2_pix_format vga_mode[] = {
2921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
2931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.bytesperline = 640,
2941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.sizeimage = 640 * 480 * 3 / 8 + 590,
2951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.colorspace = V4L2_COLORSPACE_JPEG,
2961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.priv = 0},
2971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
2981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
2991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define LOAD_PAGE3		255
3001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define LOAD_PAGE4		254
3011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define END_OF_SEQUENCE		0
3021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* pac 7302 */
3041408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 init_7302[] = {
3051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index,value */
3061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,		/* page 1 */
3071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x00,		/* deactivate */
3081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,
3091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x40,		/* led off */
3101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3111408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 start_7302[] = {
3121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index, len, [value]* */
3131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x00,		/* page 0 */
3141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 12,	0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
3151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x00, 0x00, 0x00,
3161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0d, 24,	0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
3171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
3181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
3191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x26, 2,	0xaa, 0xaa,
3201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2e, 1,	0x31,
3211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x38, 1,	0x01,
3221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3a, 3,	0x14, 0xff, 0x5a,
3231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x43, 11,	0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
3241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x54, 0x11,
3251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x55, 1,	0x00,
3261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x62, 4, 	0x10, 0x1e, 0x1e, 0x18,
3271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6b, 1,	0x00,
3281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 3,	0x08, 0x06, 0x00,
3291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x72, 3,	0x00, 0xff, 0x00,
3301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7d, 23,	0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
3311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
3321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
3331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa2, 10,	0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
3341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xd2, 0xeb,
3351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xaf, 1,	0x02,
3361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb5, 2,	0x08, 0x08,
3371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb8, 2,	0x08, 0x88,
3381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc4, 4,	0xae, 0x01, 0x04, 0x01,
3391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xcc, 1,	0x00,
3401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd1, 11,	0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
3411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xc1, 0xd7, 0xec,
3421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdc, 1,	0x01,
3431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x12, 3,	0x02, 0x00, 0x01,
3451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3e, 2,	0x00, 0x00,
3461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x76, 5,	0x01, 0x20, 0x40, 0x00, 0xf2,
3471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7c, 1,	0x00,
3481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7f, 10,	0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
3491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x02, 0x00,
3501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x96, 5,	0x01, 0x10, 0x04, 0x01, 0x04,
3511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 14,	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
3521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
3531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd8, 1,	0x01,
3541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdb, 2,	0x00, 0x01,
3551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xde, 7,	0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
3561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xe6, 4,	0x00, 0x00, 0x00, 0x01,
3571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xeb, 1,	0x00,
3581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 1,	0x00,
3601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x03,		/* page 3 */
3611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, LOAD_PAGE3,			/* load the page 3 */
3621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x11, 1,	0x01,
3631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x13, 1,	0x00,
3651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 4,	0x1f, 0xa4, 0xf0, 0x96,
3661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x27, 2,	0x14, 0x0c,
3671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2a, 5,	0xc8, 0x00, 0x18, 0x12, 0x22,
3681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x64, 8,	0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
3691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 1,	0x08,
3701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 1,	0x00,
3721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, END_OF_SEQUENCE		/* end of sequence */
3731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define SKIP		0xaa
3761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* page 3 - the value SKIP says skip the index - see reg_w_page() */
3771408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 page3_7302[] = {
3781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
3791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
3801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
3821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
3831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
3841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
3851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
3871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
3881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
3901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
3921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
3931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
3941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
3951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
3971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00
3981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
400b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_buf(struct gspca_dev *gspca_dev,
4011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 index,
4021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  const char *buffer, int len)
4031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4044f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
4054f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
4061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	memcpy(gspca_dev->usb_buf, buffer, len);
4074f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
4081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
4091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			1,		/* request */
4101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,		/* value */
4121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			index, gspca_dev->usb_buf, len,
4131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
4144f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	if (ret < 0)
4154f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		PDEBUG(D_ERR, "reg_w_buf(): "
4164f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		"Failed to write registers to index 0x%x, error %i",
4174f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		index, ret);
418b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
422b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w(struct gspca_dev *gspca_dev,
4231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 index,
4241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 value)
4251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4264f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
4274f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
4281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_dev->usb_buf[0] = value;
4294f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
4301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
4311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,			/* request */
4321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0, index, gspca_dev->usb_buf, 1,
4341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
4354f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	if (ret < 0)
4364f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		PDEBUG(D_ERR, "reg_w(): "
4374f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		"Failed to write register to index 0x%x, value 0x%x, error %i",
4384f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		index, value, ret);
439b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
442b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_seq(struct gspca_dev *gspca_dev,
4431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		const __u8 *seq, int len)
4441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
445b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	while (--len >= 0) {
447b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
448b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, seq[0], seq[1]);
4491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		seq += 2;
4501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
451b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* load the beginning of a page */
455b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_page(struct gspca_dev *gspca_dev,
4561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *page, int len)
4571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index;
459b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (index = 0; index < len; index++) {
4621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (page[index] == SKIP)		/* skip this index */
4631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			continue;
4641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		gspca_dev->usb_buf[0] = page[index];
4654f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		ret = usb_control_msg(gspca_dev->dev,
4661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				usb_sndctrlpipe(gspca_dev->dev, 0),
4671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0,			/* request */
4681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0, index, gspca_dev->usb_buf, 1,
4701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				500);
471b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (ret < 0) {
4724f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			PDEBUG(D_ERR, "reg_w_page(): "
4734f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			"Failed to write register to index 0x%x, "
4744f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			"value 0x%x, error %i",
4754f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			index, page[index], ret);
476b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			break;
477b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		}
4781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
479b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* output a variable sequence */
483b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_var(struct gspca_dev *gspca_dev,
4841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *seq,
4851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *page3, unsigned int page3_len,
4861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *page4, unsigned int page4_len)
4871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index, len;
489b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (;;) {
4921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		index = *seq++;
4931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len = *seq++;
4941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		switch (len) {
4951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case END_OF_SEQUENCE:
496b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			return ret;
4971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case LOAD_PAGE4:
498b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w_page(gspca_dev, page4, page4_len);
4991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			break;
5001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case LOAD_PAGE3:
501b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w_page(gspca_dev, page3, page3_len);
5021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			break;
5031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		default:
5041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			if (len > USB_BUF_SZ) {
5051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				PDEBUG(D_ERR|D_STREAM,
5061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					"Incorrect variable sequence");
507b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh				return -EINVAL;
5081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
5091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			while (len > 0) {
5101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				if (len < 8) {
511b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh					ret = reg_w_buf(gspca_dev,
512b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh						index, seq, len);
513b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh					if (ret < 0)
514b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh						return ret;
5151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					seq += len;
5161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					break;
5171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				}
518b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh				ret = reg_w_buf(gspca_dev, index, seq, 8);
5191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				seq += 8;
5201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				index += 8;
5211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				len -= 8;
5221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
5231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
524b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (ret < 0)
525b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			return ret;
5261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
5271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* not reached */
5281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe time for pac7302 */
5311408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_config(struct gspca_dev *gspca_dev,
5321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
5331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct cam *cam;
5361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam = &gspca_dev->cam;
5381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_CONF, "Find Sensor PAC7302");
5401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->cam_mode = vga_mode;	/* only 640x480 */
5411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->nmodes = ARRAY_SIZE(vga_mode);
5421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->brightness = BRIGHTNESS_DEF;
5441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->contrast = CONTRAST_DEF;
5451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->colors = COLOR_DEF;
54623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	sd->white_balance = WHITEBALANCE_DEF;
547265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->red_balance = REDBALANCE_DEF;
548265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->blue_balance = BLUEBALANCE_DEF;
5491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->gain = GAIN_DEF;
5501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->exposure = EXPOSURE_DEF;
5511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain = AUTOGAIN_DEF;
5521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->hflip = HFLIP_DEF;
5531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->vflip = VFLIP_DEF;
5541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
5551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
558b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setbrightcont(struct gspca_dev *gspca_dev)
5591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
562b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
5631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const __u8 max[10] =
5641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
5651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0xd4, 0xec};
5661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const __u8 delta[10] =
5671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
5681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0x11, 0x0b};
5691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
570b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
5711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 10; i++) {
5721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v = max[i];
5731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v += (sd->brightness - BRIGHTNESS_MAX)
5741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			* 150 / BRIGHTNESS_MAX;		/* 200 ? */
5751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v -= delta[i] * sd->contrast / CONTRAST_MAX;
5761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (v < 0)
5771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0;
5781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		else if (v > 0xff)
5791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0xff;
580b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
581b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, 0xa2 + i, v);
5821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
583b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
584b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
585b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
5861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
589b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setcolors(struct gspca_dev *gspca_dev)
5901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
593b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
5941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int a[9] =
5951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{217, -212, 0, -101, 170, -67, -38, -315, 355};
5961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int b[9] =
5971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{19, 106, 0, 19, 106, 1, 19, 106, 1};
5981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
599b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);	/* page 3 */
600b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
601b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
602b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
603b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
6041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 9; i++) {
6051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v = a[i] * sd->colors / COLOR_MAX + b[i];
606b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
607b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
608b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
609b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
6101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
611b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
612b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
6131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
614b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
6151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
61723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int setwhitebalance(struct gspca_dev *gspca_dev)
61823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
61923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
62023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	int ret;
62123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
62223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
62323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
62423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = reg_w(gspca_dev, 0xc6, sd->white_balance);
62523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
62623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
62723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = reg_w(gspca_dev, 0xdc, 0x01);
62823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
62923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	return ret;
63023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
63123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
632265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int setredbalance(struct gspca_dev *gspca_dev)
633265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
634265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
635265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret;
636265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
637265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
638265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
639265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xc5, sd->red_balance);
640265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
641265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
642265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
643265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
644265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
645265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
646265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
647265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int setbluebalance(struct gspca_dev *gspca_dev)
648265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
649265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
650265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret;
651265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
652265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
653265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
654265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xc7, sd->blue_balance);
655265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
656265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
657265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
658265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
659265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
660265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
661265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
662b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setgain(struct gspca_dev *gspca_dev)
6631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
665b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
6661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
667b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
668b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
669b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x10, sd->gain >> 3);
6701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
672b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
673b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
674b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
6751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
677b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setexposure(struct gspca_dev *gspca_dev)
6781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
680b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
6811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 reg;
6821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* register 2 of frame 3/4 contains the clock divider configuring the
6841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   no fps according to the formula: 60 / reg. sd->exposure is the
6851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   desired exposure time in ms. */
6861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	reg = 120 * sd->exposure / 1000;
6871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (reg < 2)
6881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = 2;
6891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else if (reg > 63)
6901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = 63;
6911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* On the pac7302 reg2 MUST be a multiple of 3, so round it to
6931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   the nearest multiple of 3, except when between 6 and 12? */
6941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (reg < 6 || reg > 12)
6951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = ((reg + 1) / 3) * 3;
696b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
697b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
698b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x02, reg);
6991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
701b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
702b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
703b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
7041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
706b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int sethvflip(struct gspca_dev *gspca_dev)
7071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
709b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
7101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 data;
7111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
712b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
7131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
714b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
715b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x21, data);
7161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
717b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
718b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
719b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
7201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe and resume time for pac7302 */
7231408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_init(struct gspca_dev *gspca_dev)
7241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
725b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
7261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7281408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_start(struct gspca_dev *gspca_dev)
7291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
731b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
7321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->sof_read = 0;
7341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
735b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w_var(gspca_dev, start_7302,
7361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		page3_7302, sizeof(page3_7302),
7371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		NULL, 0);
738b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
739b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = setbrightcont(gspca_dev);
740b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
741b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = setcolors(gspca_dev);
742b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
74323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = setwhitebalance(gspca_dev);
74423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
745265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setredbalance(gspca_dev);
746265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
747265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setbluebalance(gspca_dev);
748265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
749b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		setgain(gspca_dev);
750b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
751b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		setexposure(gspca_dev);
752b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
753b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		sethvflip(gspca_dev);
7541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* only resolution 640x480 is supported for pac7302 */
7561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->sof_read = 0;
7581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain_ignore_frames = 0;
7591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	atomic_set(&sd->avg_lum, -1);
7601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* start stream */
762b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
763b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xff, 0x01);
764b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
765b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x78, 0x01);
7661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
767b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
7681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7701408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stopN(struct gspca_dev *gspca_dev)
7711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
772b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
773b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh
77467c98f72e132e191ff4db0ac7bd81ea94fa5c667Márton Németh	/* stop stream */
775b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x01);
776b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
777b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x78, 0x00);
7781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* called on streamoff with alt 0 and on disconnect for pac7302 */
7811408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stop0(struct gspca_dev *gspca_dev)
7821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
783b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
784b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh
7851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (!gspca_dev->present)
7861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
787b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x01);
788b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
789b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x78, 0x40);
7901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* Include pac common sof detection functions */
7931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#include "pac_common.h"
7941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7951408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void do_autogain(struct gspca_dev *gspca_dev)
7961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
7981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int avg_lum = atomic_read(&sd->avg_lum);
7991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int desired_lum, deadzone;
8001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (avg_lum == -1)
8021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
8031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	desired_lum = 270 + sd->brightness * 4;
8051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* Hack hack, with the 7202 the first exposure step is
8061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   pretty large, so if we're about to make the first
8071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   exposure increase make the deadzone large to avoid
8081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   oscilating */
8091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
8101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->exposure > EXPOSURE_DEF &&
8111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->exposure < 42)
8121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		deadzone = 90;
8131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else
8141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		deadzone = 30;
8151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sd->autogain_ignore_frames > 0)
8171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames--;
8181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
8191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			deadzone, GAIN_KNEE, EXPOSURE_KNEE))
8201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
8211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* JPEG header, part 1 */
8241408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const unsigned char pac_jpeg_header1[] = {
8251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xd8,		/* SOI: Start of Image */
8261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xc0,		/* SOF0: Start of Frame (Baseline DCT) */
8281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x11,		/* length = 17 bytes (including this length field) */
8291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x08			/* Precision: 8 */
8301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  /* 2 bytes is placed here: number of image lines */
8311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  /* 2 bytes is placed here: samples per line */
8321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
8331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* JPEG header, continued */
8351408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const unsigned char pac_jpeg_header2[] = {
8361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03,			/* Number of image components: 3 */
8371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x01, 0x21, 0x00,	/* ID=1, Subsampling 1x1, Quantization table: 0 */
8381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x02, 0x11, 0x01,	/* ID=2, Subsampling 2x1, Quantization table: 1 */
8391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03, 0x11, 0x01,	/* ID=3, Subsampling 2x1, Quantization table: 1 */
8401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xda,		/* SOS: Start Of Scan */
8421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x0c,		/* length = 12 bytes (including this length field) */
8431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03,			/* number of components: 3 */
8441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x01, 0x00,		/* selector 1, table 0x00 */
8451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x02, 0x11,		/* selector 2, table 0x11 */
8461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03, 0x11,		/* selector 3, table 0x11 */
8471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x3f,		/* Spectral selection: 0 .. 63 */
8481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00			/* Successive approximation: 0 */
8491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
8501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8511408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void pac_start_frame(struct gspca_dev *gspca_dev,
8521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		struct gspca_frame *frame,
8531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		__u16 lines, __u16 samples_per_line)
8541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char tmpbuf[4];
8561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
8581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_jpeg_header1, sizeof(pac_jpeg_header1));
8591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[0] = lines >> 8;
8611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[1] = lines & 0xff;
8621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[2] = samples_per_line >> 8;
8631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[3] = samples_per_line & 0xff;
8641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
8661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		tmpbuf, sizeof(tmpbuf));
8671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
8681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_jpeg_header2, sizeof(pac_jpeg_header2));
8691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is run at interrupt level */
8721408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
8731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			struct gspca_frame *frame,	/* target */
8741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			__u8 *data,			/* isoc packet */
8751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			int len)			/* iso packet length */
8761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
8781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char *sof;
8791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sof = pac_find_sof(&sd->sof_read, data, len);
8811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sof) {
8821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		int n, lum_offset, footer_length;
8831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* 6 bytes after the FF D9 EOF marker a number of lumination
8851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   bytes are send corresponding to different parts of the
8861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   image, the 14th and 15th byte after the EOF seem to
8871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   correspond to the center of the image */
8881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		lum_offset = 61 + sizeof pac_sof_marker;
8891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		footer_length = 74;
8901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Finish decoding current frame */
8921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
8931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (n < 0) {
8941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			frame->data_end += n;
8951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			n = 0;
8961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
8971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
8981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					data, n);
8991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->last_packet_type != DISCARD_PACKET &&
9001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				frame->data_end[-2] == 0xff &&
9011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				frame->data_end[-1] == 0xd9)
9021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
9031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth						NULL, 0);
9041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = sof - data;
9061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len -= n;
9071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		data = sof;
9081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Get average lumination */
9101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->last_packet_type == LAST_PACKET &&
9111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				n >= lum_offset)
9121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			atomic_set(&sd->avg_lum, data[-lum_offset] +
9131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth						data[-lum_offset + 1]);
9141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		else
9151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			atomic_set(&sd->avg_lum, -1);
9161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Start the new frame with the jpeg header */
9181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* The PAC7302 has the image rotated 90 degrees */
9191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_start_frame(gspca_dev, frame,
9201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			gspca_dev->width, gspca_dev->height);
9211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
9221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
9231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9251408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
9261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->brightness = val;
9301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
9311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setbrightcont(gspca_dev);
9321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9351408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
9361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->brightness;
9401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9431408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
9441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->contrast = val;
9481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming) {
9491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setbrightcont(gspca_dev);
9501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
9511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9541408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
9551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->contrast;
9591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9621408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
9631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->colors = val;
9671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
9681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setcolors(gspca_dev);
9691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9721408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
9731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->colors;
9771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
98023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
98123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
98223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
98323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	int ret = 0;
98423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
98523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	sd->white_balance = val;
98623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (gspca_dev->streaming)
98723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = setwhitebalance(gspca_dev);
98823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
98923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = 0;
99023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	return ret;
99123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
99223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
99323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
99423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
99523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
99623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
99723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	*val = sd->white_balance;
99823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	return 0;
99923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
100023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
1001265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
1002265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1003265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1004265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret = 0;
1005265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1006265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->red_balance = val;
1007265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (gspca_dev->streaming)
1008265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setredbalance(gspca_dev);
1009265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
1010265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = 0;
1011265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
1012265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1013265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1014265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
1015265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1016265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1017265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1018265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	*val = sd->red_balance;
1019265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return 0;
1020265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1021265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1022265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
1023265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1024265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1025265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret = 0;
1026265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1027265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->blue_balance = val;
1028265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (gspca_dev->streaming)
1029265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setbluebalance(gspca_dev);
1030265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
1031265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = 0;
1032265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
1033265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1034265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1035265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
1036265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1037265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1038265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1039265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	*val = sd->blue_balance;
1040265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return 0;
1041265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1042265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
10431408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
10441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->gain = val;
10481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setgain(gspca_dev);
10501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10531408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
10541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->gain;
10581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10611408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
10621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->exposure = val;
10661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setexposure(gspca_dev);
10681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10711408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
10721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->exposure;
10761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10791408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
10801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain = val;
10841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* when switching to autogain set defaults to make sure
10851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   we are on a valid point of the autogain gain /
10861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   exposure knee graph, and give this change time to
10871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   take effect before doing autogain. */
10881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sd->autogain) {
10891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->exposure = EXPOSURE_DEF;
10901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->gain = GAIN_DEF;
10911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->streaming) {
10921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->autogain_ignore_frames =
10931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				PAC_AUTOGAIN_IGNORE_FRAMES;
10941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			setexposure(gspca_dev);
10951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			setgain(gspca_dev);
10961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
10971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
10981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11021408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
11031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->autogain;
11071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11101408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
11111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->hflip = val;
11151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
11161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sethvflip(gspca_dev);
11171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11201408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
11211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->hflip;
11251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11281408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
11291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->vflip = val;
11331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
11341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sethvflip(gspca_dev);
11351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11381408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
11391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->vflip;
11431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* sub-driver description for pac7302 */
11471408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct sd_desc sd_desc = {
11481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.name = MODULE_NAME,
11491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.ctrls = sd_ctrls,
11501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.nctrls = ARRAY_SIZE(sd_ctrls),
11511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.config = sd_config,
11521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.init = sd_init,
11531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.start = sd_start,
11541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stopN = sd_stopN,
11551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stop0 = sd_stop0,
11561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.pkt_scan = sd_pkt_scan,
11571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.dq_callback = do_autogain,
11581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
11591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- module initialisation -- */
11611408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic __devinitdata struct usb_device_id device_table[] = {
11621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x06f8, 0x3009)},
11631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2620)},
11641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2621)},
11651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2622)},
11661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2624)},
11671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2626)},
11681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2628)},
11691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2629)},
11701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262a)},
11711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262c)},
11721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{}
11731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
11741408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DEVICE_TABLE(usb, device_table);
11751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- device connect -- */
11771408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_probe(struct usb_interface *intf,
11781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
11791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
11811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				THIS_MODULE);
11821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11841408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct usb_driver sd_driver = {
11851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.name = MODULE_NAME,
11861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.id_table = device_table,
11871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.probe = sd_probe,
11881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.disconnect = gspca_disconnect,
11891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#ifdef CONFIG_PM
11901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.suspend = gspca_suspend,
11911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.resume = gspca_resume,
11921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#endif
11931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
11941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- module insert / remove -- */
11961408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int __init sd_mod_init(void)
11971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int ret;
11991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	ret = usb_register(&sd_driver);
12001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (ret < 0)
12011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return ret;
12021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_PROBE, "registered");
12031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
12041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12051408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void __exit sd_mod_exit(void)
12061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
12071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	usb_deregister(&sd_driver);
12081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_PROBE, "deregistered");
12091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12111408b8472910e894b290205b4baed5b14b8f45afMarton Nemethmodule_init(sd_mod_init);
12121408b8472910e894b290205b4baed5b14b8f45afMarton Nemethmodule_exit(sd_mod_exit);
1213