pac7302.c revision aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78a
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>
8aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh * Camera button input handling by Márton Németh <nm127@freemail.hu>
9aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is free software; you can redistribute it and/or modify
121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * it under the terms of the GNU General Public License as published by
131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * the Free Software Foundation; either version 2 of the License, or
141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * any later version.
151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is distributed in the hope that it will be useful,
171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * but WITHOUT ANY WARRANTY; without even the implied warranty of
181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * GNU General Public License for more details.
201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * You should have received a copy of the GNU General Public License
221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * along with this program; if not, write to the Free Software
231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth */
251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* Some documentation about various registers as determined by trial and error.
271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   When the register addresses differ between the 7202 and the 7311 the 2
281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   different addresses are written as 7302addr/7311addr, when one of the 2
291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   addresses is a - sign that register description is not valid for the
301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   matching IC.
311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Register page 1:
331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x08	Unknown compressor related, must always be 8 except when not
361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x1b	Auto white balance related, bit 0 is AWB enable (inverted)
381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		bits 345 seem to toggle per color gains on/off (inverted)
391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x78		Global control, bit 6 controls the LED (inverted)
401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x80	JPEG compression ratio ? Best not touched
411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Register page 3/4:
431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x02		Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x0f	Master gain 1-245, low value = high gain
481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x10/-	Master gain 0-31
491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x10	Another gain 0-15, limited influence (1-2x gain I guess)
501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x27	Seems to toggle various gains on / off, Setting bit 7 seems to
521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		completely disable the analog amplification block. Set to 0x68
531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		for max gain, 0x14 for minimal gain.
54265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
55265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   The registers are accessed in the following functions:
56265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
57265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   Page | Register   | Function
58265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   -----+------------+---------------------------------------------------
59265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0x0f..0x20 | setcolors()
60265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xa2..0xab | setbrightcont()
61265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc5       | setredbalance()
6223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth    0   | 0xc6       | setwhitebalance()
63265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc7       | setbluebalance()
64265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xdc       | setbrightcont(), setcolors()
65265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x02       | setexposure()
66265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x10       | setgain()
67265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x11       | setcolors(), setgain(), setexposure(), sethvflip()
68265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x21       | sethvflip()
691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth*/
701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define MODULE_NAME "pac7302"
721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
73aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#include <linux/input.h>
746763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#include <media/v4l2-chip-ident.h>
751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#include "gspca.h"
761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
771408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
781408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DESCRIPTION("Pixart PAC7302");
791408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_LICENSE("GPL");
801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* specific webcam descriptor for pac7302 */
821408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstruct sd {
831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct gspca_dev gspca_dev;		/* !! must be the first item */
841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char brightness;
861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char contrast;
871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char colors;
8823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	unsigned char white_balance;
89265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	unsigned char red_balance;
90265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	unsigned char blue_balance;
911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char gain;
921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char exposure;
931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char autogain;
941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 hflip;
951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 vflip;
96fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	u8 flags;
97fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine#define FL_HFLIP 0x01		/* mirrored by default */
98fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine#define FL_VFLIP 0x02		/* vertical flipped by default */
991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	u8 sof_read;
1011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	u8 autogain_ignore_frames;
1021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	atomic_t avg_lum;
1041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
1051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* V4L2 controls supported by the driver */
1071408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
1081408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
1091408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
1101408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
1111408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
1121408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
11323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
11423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
115265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
116265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
117265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
118265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
1191408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
1201408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
1211408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
1221408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
1231408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
1241408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
1251408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
1261408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
1271408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
1281408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
1291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1307e64dc4c4d6f5c8935fac25c7fc7aa83f9880ed7Marton Nemethstatic const struct ctrl sd_ctrls[] = {
1311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is pac7302 only */
1321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_BRIGHTNESS,
1351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Brightness",
1371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define BRIGHTNESS_MAX 0x20
1391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = BRIGHTNESS_MAX,
1401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define BRIGHTNESS_DEF 0x10
1421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = BRIGHTNESS_DEF,
1431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setbrightness,
1451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getbrightness,
1461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
1471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is for both the 7302 and the 7311 */
1481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_CONTRAST,
1511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Contrast",
1531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define CONTRAST_MAX 255
1551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = CONTRAST_MAX,
1561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define CONTRAST_DEF 127
1581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = CONTRAST_DEF,
1591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setcontrast,
1611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getcontrast,
1621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
1631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is pac7302 only */
1641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_SATURATION,
1671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Saturation",
1691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define COLOR_MAX 255
1711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = COLOR_MAX,
1721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define COLOR_DEF 127
1741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = COLOR_DEF,
1751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setcolors,
1771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getcolors,
1781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
179265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	{
180265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
18123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.id      = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
18223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
18323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.name    = "White Balance",
18423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.minimum = 0,
18523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.maximum = 255,
18623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.step    = 1,
18723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth#define WHITEBALANCE_DEF 4
18823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.default_value = WHITEBALANCE_DEF,
18923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    },
19023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    .set = sd_setwhitebalance,
19123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    .get = sd_getwhitebalance,
19223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	},
19323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	{
19423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    {
195265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_RED_BALANCE,
196265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
197265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Red",
198265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
199265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
200265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
201265a8098e75e156985abfaac250ee4f2b407f863Márton Németh#define REDBALANCE_DEF 1
202265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.default_value = REDBALANCE_DEF,
203265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
204265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .set = sd_setredbalance,
205265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .get = sd_getredbalance,
206265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
207265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	{
208265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
209265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_BLUE_BALANCE,
210265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
211265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Blue",
212265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
213265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
214265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
215265a8098e75e156985abfaac250ee4f2b407f863Márton Németh#define BLUEBALANCE_DEF 1
216265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.default_value = BLUEBALANCE_DEF,
217265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
218265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .set = sd_setbluebalance,
219265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .get = sd_getbluebalance,
220265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
2211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* All controls below are for both the 7302 and the 7311 */
2221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_GAIN,
2251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
2261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Gain",
2271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_MAX 255
2291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = GAIN_MAX,
2301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_DEF 127
2321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
2331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = GAIN_DEF,
2341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setgain,
2361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getgain,
2371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_EXPOSURE,
2411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
2421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Exposure",
2431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_MAX 255
2451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = EXPOSURE_MAX,
2461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
2481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
2491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = EXPOSURE_DEF,
2501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setexposure,
2521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getexposure,
2531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_AUTOGAIN,
2571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Auto Gain",
2591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define AUTOGAIN_DEF 1
2631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = AUTOGAIN_DEF,
2641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setautogain,
2661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getautogain,
2671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_HFLIP,
2711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Mirror",
2731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define HFLIP_DEF 0
2771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = HFLIP_DEF,
2781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_sethflip,
2801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_gethflip,
2811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_VFLIP,
2851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Vflip",
2871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define VFLIP_DEF 0
2911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = VFLIP_DEF,
2921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setvflip,
2941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getvflip,
2951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
2971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
2981408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const struct v4l2_pix_format vga_mode[] = {
2991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
3001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.bytesperline = 640,
3011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.sizeimage = 640 * 480 * 3 / 8 + 590,
3021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.colorspace = V4L2_COLORSPACE_JPEG,
3031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.priv = 0},
3041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define LOAD_PAGE3		255
3071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define END_OF_SEQUENCE		0
3081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* pac 7302 */
3101408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 init_7302[] = {
3111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index,value */
3121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,		/* page 1 */
3131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x00,		/* deactivate */
3141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,
3151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x40,		/* led off */
3161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3171408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 start_7302[] = {
3181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index, len, [value]* */
3191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x00,		/* page 0 */
3201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 12,	0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
3211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x00, 0x00, 0x00,
3221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0d, 24,	0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
3231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
3241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
3251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x26, 2,	0xaa, 0xaa,
3261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2e, 1,	0x31,
3271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x38, 1,	0x01,
3281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3a, 3,	0x14, 0xff, 0x5a,
3291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x43, 11,	0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
3301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x54, 0x11,
3311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x55, 1,	0x00,
3321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x62, 4, 	0x10, 0x1e, 0x1e, 0x18,
3331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6b, 1,	0x00,
3341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 3,	0x08, 0x06, 0x00,
3351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x72, 3,	0x00, 0xff, 0x00,
3361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7d, 23,	0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
3371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
3381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
3391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa2, 10,	0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
3401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xd2, 0xeb,
3411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xaf, 1,	0x02,
3421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb5, 2,	0x08, 0x08,
3431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb8, 2,	0x08, 0x88,
3441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc4, 4,	0xae, 0x01, 0x04, 0x01,
3451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xcc, 1,	0x00,
3461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd1, 11,	0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
3471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xc1, 0xd7, 0xec,
3481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdc, 1,	0x01,
3491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x12, 3,	0x02, 0x00, 0x01,
3511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3e, 2,	0x00, 0x00,
3521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x76, 5,	0x01, 0x20, 0x40, 0x00, 0xf2,
3531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7c, 1,	0x00,
3541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7f, 10,	0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
3551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x02, 0x00,
3561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x96, 5,	0x01, 0x10, 0x04, 0x01, 0x04,
3571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 14,	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
3581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
3591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd8, 1,	0x01,
3601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdb, 2,	0x00, 0x01,
3611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xde, 7,	0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
3621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xe6, 4,	0x00, 0x00, 0x00, 0x01,
3631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xeb, 1,	0x00,
3641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 1,	0x00,
3661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x03,		/* page 3 */
3671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, LOAD_PAGE3,			/* load the page 3 */
3681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x11, 1,	0x01,
3691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x13, 1,	0x00,
3711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 4,	0x1f, 0xa4, 0xf0, 0x96,
3721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x27, 2,	0x14, 0x0c,
3731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2a, 5,	0xc8, 0x00, 0x18, 0x12, 0x22,
3741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x64, 8,	0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
3751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 1,	0x08,
3761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 1,	0x00,
3781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, END_OF_SEQUENCE		/* end of sequence */
3791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define SKIP		0xaa
3821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* page 3 - the value SKIP says skip the index - see reg_w_page() */
3831408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 page3_7302[] = {
3841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
3851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
3861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
3881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
3891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
3901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
3911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
393cdf955cd8e45d8279c53b47a2c0e0c5decaaca86Jean-Francois Moine	SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
3941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
3961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
3981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
3991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
4001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
4011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
4031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00
4041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
4051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
406be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_buf(struct gspca_dev *gspca_dev,
4071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 index,
4081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  const char *buffer, int len)
4091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4104f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
4114f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
412be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (gspca_dev->usb_err < 0)
413be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		return;
4141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	memcpy(gspca_dev->usb_buf, buffer, len);
4154f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
4161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
4171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			1,		/* request */
4181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,		/* value */
4201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			index, gspca_dev->usb_buf, len,
4211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
422be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (ret < 0) {
4234f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		PDEBUG(D_ERR, "reg_w_buf(): "
4244f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		"Failed to write registers to index 0x%x, error %i",
4254f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		index, ret);
426be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		gspca_dev->usb_err = ret;
427be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	}
4281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
431be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w(struct gspca_dev *gspca_dev,
4321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 index,
4331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 value)
4341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4354f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
4364f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
437be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (gspca_dev->usb_err < 0)
438be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		return;
4391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_dev->usb_buf[0] = value;
4404f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
4411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
4421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,			/* request */
4431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0, index, gspca_dev->usb_buf, 1,
4451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
446be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (ret < 0) {
4474f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		PDEBUG(D_ERR, "reg_w(): "
4484f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		"Failed to write register to index 0x%x, value 0x%x, error %i",
4494f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		index, value, ret);
450be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		gspca_dev->usb_err = ret;
451be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	}
4521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
454be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_seq(struct gspca_dev *gspca_dev,
4551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		const __u8 *seq, int len)
4561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	while (--len >= 0) {
458be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, seq[0], seq[1]);
4591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		seq += 2;
4601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
4611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* load the beginning of a page */
464be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_page(struct gspca_dev *gspca_dev,
4651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *page, int len)
4661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index;
468b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
470be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	if (gspca_dev->usb_err < 0)
471be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		return;
4721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (index = 0; index < len; index++) {
4731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (page[index] == SKIP)		/* skip this index */
4741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			continue;
4751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		gspca_dev->usb_buf[0] = page[index];
4764f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		ret = usb_control_msg(gspca_dev->dev,
4771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				usb_sndctrlpipe(gspca_dev->dev, 0),
4781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0,			/* request */
4791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0, index, gspca_dev->usb_buf, 1,
4811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				500);
482b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (ret < 0) {
4834f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			PDEBUG(D_ERR, "reg_w_page(): "
4844f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			"Failed to write register to index 0x%x, "
4854f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			"value 0x%x, error %i",
4864f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			index, page[index], ret);
487be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine			gspca_dev->usb_err = ret;
488b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			break;
489b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		}
4901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
4911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* output a variable sequence */
494be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void reg_w_var(struct gspca_dev *gspca_dev,
4951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *seq,
49623a5de202bc385b69eb91a5db36699e9579ec03eJean-Francois Moine			const __u8 *page3, unsigned int page3_len)
4971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index, len;
4991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (;;) {
5011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		index = *seq++;
5021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len = *seq++;
5031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		switch (len) {
5041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case END_OF_SEQUENCE:
505be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine			return;
5061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case LOAD_PAGE3:
507be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine			reg_w_page(gspca_dev, page3, page3_len);
5081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			break;
5091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		default:
5101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			if (len > USB_BUF_SZ) {
5111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				PDEBUG(D_ERR|D_STREAM,
5121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					"Incorrect variable sequence");
513be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine				return;
5141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
5151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			while (len > 0) {
5161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				if (len < 8) {
517be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine					reg_w_buf(gspca_dev,
518b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh						index, seq, len);
5191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					seq += len;
5201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					break;
5211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				}
522be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine				reg_w_buf(gspca_dev, index, seq, 8);
5231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				seq += 8;
5241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				index += 8;
5251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				len -= 8;
5261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
5271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
5281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
5291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* not reached */
5301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe time for pac7302 */
5331408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_config(struct gspca_dev *gspca_dev,
5341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
5351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct cam *cam;
5381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam = &gspca_dev->cam;
5401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_CONF, "Find Sensor PAC7302");
5421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->cam_mode = vga_mode;	/* only 640x480 */
5431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->nmodes = ARRAY_SIZE(vga_mode);
5441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->brightness = BRIGHTNESS_DEF;
5461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->contrast = CONTRAST_DEF;
5471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->colors = COLOR_DEF;
54823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	sd->white_balance = WHITEBALANCE_DEF;
549265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->red_balance = REDBALANCE_DEF;
550265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->blue_balance = BLUEBALANCE_DEF;
5511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->gain = GAIN_DEF;
5521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->exposure = EXPOSURE_DEF;
5531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain = AUTOGAIN_DEF;
5541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->hflip = HFLIP_DEF;
5551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->vflip = VFLIP_DEF;
556fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	sd->flags = id->driver_info;
5571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
5581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
561be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setbrightcont(struct gspca_dev *gspca_dev)
5621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
5651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const __u8 max[10] =
5661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
5671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0xd4, 0xec};
5681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const __u8 delta[10] =
5691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
5701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0x11, 0x0b};
5711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
572be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
5731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 10; i++) {
5741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v = max[i];
5751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v += (sd->brightness - BRIGHTNESS_MAX)
5761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			* 150 / BRIGHTNESS_MAX;		/* 200 ? */
5771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v -= delta[i] * sd->contrast / CONTRAST_MAX;
5781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (v < 0)
5791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0;
5801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		else if (v > 0xff)
5811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0xff;
582be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0xa2 + i, v);
5831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
584be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
5851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
588be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setcolors(struct gspca_dev *gspca_dev)
5891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
5921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int a[9] =
5931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{217, -212, 0, -101, 170, -67, -38, -315, 355};
5941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int b[9] =
5951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{19, 106, 0, 19, 106, 1, 19, 106, 1};
5961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
597be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
598be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
599be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
6001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 9; i++) {
6011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v = a[i] * sd->colors / COLOR_MAX + b[i];
602be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
603be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
6041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
605be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
6061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
6071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
609be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setwhitebalance(struct gspca_dev *gspca_dev)
61023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
61123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
61223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
613be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
614be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xc6, sd->white_balance);
61523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
616be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
61723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
61823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
61923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
620be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setredbalance(struct gspca_dev *gspca_dev)
621265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
622265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
623265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
624be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
625be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xc5, sd->red_balance);
626265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
627be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
628265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
629265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
630265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
631be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setbluebalance(struct gspca_dev *gspca_dev)
632265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
633265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
634265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
635be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
636be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xc7, sd->blue_balance);
637265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
638be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xdc, 0x01);
639265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
640265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
641265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
642be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setgain(struct gspca_dev *gspca_dev)
6431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
6451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
646be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
647be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x10, sd->gain >> 3);
6481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
650be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
6511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
653be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void setexposure(struct gspca_dev *gspca_dev)
6541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
6561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 reg;
6571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* register 2 of frame 3/4 contains the clock divider configuring the
6591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   no fps according to the formula: 60 / reg. sd->exposure is the
6601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   desired exposure time in ms. */
6611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	reg = 120 * sd->exposure / 1000;
6621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (reg < 2)
6631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = 2;
6641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else if (reg > 63)
6651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = 63;
6661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* On the pac7302 reg2 MUST be a multiple of 3, so round it to
6681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   the nearest multiple of 3, except when between 6 and 12? */
6691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (reg < 6 || reg > 12)
6701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = ((reg + 1) / 3) * 3;
671be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
672be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x02, reg);
6731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
675be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
6761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
678be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moinestatic void sethvflip(struct gspca_dev *gspca_dev)
6791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
681fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	u8 data, hflip, vflip;
682fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine
683fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	hflip = sd->hflip;
684fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	if (sd->flags & FL_HFLIP)
685fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine		hflip = !hflip;
686fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	vflip = sd->vflip;
687fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	if (sd->flags & FL_VFLIP)
688fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine		vflip = !vflip;
6891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
690be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
691fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
692be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x21, data);
693be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine
6941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
695be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x11, 0x01);
6961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe and resume time for pac7302 */
6991408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_init(struct gspca_dev *gspca_dev)
7001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
701be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
702be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
7031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7051408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_start(struct gspca_dev *gspca_dev)
7061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
7081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->sof_read = 0;
7101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
711be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w_var(gspca_dev, start_7302,
71223a5de202bc385b69eb91a5db36699e9579ec03eJean-Francois Moine		page3_7302, sizeof(page3_7302));
713be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setbrightcont(gspca_dev);
714be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setcolors(gspca_dev);
715be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setwhitebalance(gspca_dev);
716be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setredbalance(gspca_dev);
717be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setbluebalance(gspca_dev);
718be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setgain(gspca_dev);
719be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	setexposure(gspca_dev);
720be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	sethvflip(gspca_dev);
7211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* only resolution 640x480 is supported for pac7302 */
7231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->sof_read = 0;
7251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain_ignore_frames = 0;
7261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	atomic_set(&sd->avg_lum, -1);
7271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* start stream */
729be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x01);
730be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x78, 0x01);
7311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
732be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
7331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7351408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stopN(struct gspca_dev *gspca_dev)
7361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
737b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh
73867c98f72e132e191ff4db0ac7bd81ea94fa5c667Márton Németh	/* stop stream */
739be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x01);
740be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x78, 0x00);
7411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* called on streamoff with alt 0 and on disconnect for pac7302 */
7441408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stop0(struct gspca_dev *gspca_dev)
7451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (!gspca_dev->present)
7471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
748be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0xff, 0x01);
749be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	reg_w(gspca_dev, 0x78, 0x40);
7501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* Include pac common sof detection functions */
7531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#include "pac_common.h"
7541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7551408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void do_autogain(struct gspca_dev *gspca_dev)
7561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
7581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int avg_lum = atomic_read(&sd->avg_lum);
7591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int desired_lum, deadzone;
7601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (avg_lum == -1)
7621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
7631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	desired_lum = 270 + sd->brightness * 4;
7651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* Hack hack, with the 7202 the first exposure step is
7661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   pretty large, so if we're about to make the first
7671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   exposure increase make the deadzone large to avoid
7681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   oscilating */
7691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
7701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->exposure > EXPOSURE_DEF &&
7711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->exposure < 42)
7721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		deadzone = 90;
7731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else
7741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		deadzone = 30;
7751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sd->autogain_ignore_frames > 0)
7771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames--;
7781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
7791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			deadzone, GAIN_KNEE, EXPOSURE_KNEE))
7801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
7811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* JPEG header, part 1 */
7841408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const unsigned char pac_jpeg_header1[] = {
7851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xd8,		/* SOI: Start of Image */
7861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xc0,		/* SOF0: Start of Frame (Baseline DCT) */
7881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x11,		/* length = 17 bytes (including this length field) */
7891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x08			/* Precision: 8 */
7901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  /* 2 bytes is placed here: number of image lines */
7911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  /* 2 bytes is placed here: samples per line */
7921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
7931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* JPEG header, continued */
7951408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const unsigned char pac_jpeg_header2[] = {
7961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03,			/* Number of image components: 3 */
7971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x01, 0x21, 0x00,	/* ID=1, Subsampling 1x1, Quantization table: 0 */
7981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x02, 0x11, 0x01,	/* ID=2, Subsampling 2x1, Quantization table: 1 */
7991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03, 0x11, 0x01,	/* ID=3, Subsampling 2x1, Quantization table: 1 */
8001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xda,		/* SOS: Start Of Scan */
8021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x0c,		/* length = 12 bytes (including this length field) */
8031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03,			/* number of components: 3 */
8041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x01, 0x00,		/* selector 1, table 0x00 */
8051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x02, 0x11,		/* selector 2, table 0x11 */
8061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03, 0x11,		/* selector 3, table 0x11 */
8071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x3f,		/* Spectral selection: 0 .. 63 */
8081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00			/* Successive approximation: 0 */
8091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
8101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8111408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void pac_start_frame(struct gspca_dev *gspca_dev,
8121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		struct gspca_frame *frame,
8131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		__u16 lines, __u16 samples_per_line)
8141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char tmpbuf[4];
8161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
81776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, FIRST_PACKET,
8181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_jpeg_header1, sizeof(pac_jpeg_header1));
8191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[0] = lines >> 8;
8211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[1] = lines & 0xff;
8221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[2] = samples_per_line >> 8;
8231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[3] = samples_per_line & 0xff;
8241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
82576dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET,
8261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		tmpbuf, sizeof(tmpbuf));
82776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET,
8281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_jpeg_header2, sizeof(pac_jpeg_header2));
8291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is run at interrupt level */
8321408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
83376dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			u8 *data,			/* isoc packet */
8341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			int len)			/* iso packet length */
8351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
83776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	struct gspca_frame *frame;
8381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char *sof;
8391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sof = pac_find_sof(&sd->sof_read, data, len);
8411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sof) {
8421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		int n, lum_offset, footer_length;
8431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
84476dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		frame = gspca_get_i_frame(gspca_dev);
84576dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		if (frame == NULL) {
84676dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_dev->last_packet_type = DISCARD_PACKET;
84776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			return;
84876dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		}
84976dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine
8501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* 6 bytes after the FF D9 EOF marker a number of lumination
8511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   bytes are send corresponding to different parts of the
8521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   image, the 14th and 15th byte after the EOF seem to
8531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   correspond to the center of the image */
8541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		lum_offset = 61 + sizeof pac_sof_marker;
8551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		footer_length = 74;
8561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Finish decoding current frame */
8581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
8591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (n < 0) {
8601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			frame->data_end += n;
8611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			n = 0;
8621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
86376dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		gspca_frame_add(gspca_dev, INTER_PACKET,
8641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					data, n);
8651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->last_packet_type != DISCARD_PACKET &&
8661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				frame->data_end[-2] == 0xff &&
8671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				frame->data_end[-1] == 0xd9)
86876dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_frame_add(gspca_dev, LAST_PACKET,
8691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth						NULL, 0);
8701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = sof - data;
8721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len -= n;
8731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		data = sof;
8741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Get average lumination */
8761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->last_packet_type == LAST_PACKET &&
8771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				n >= lum_offset)
8781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			atomic_set(&sd->avg_lum, data[-lum_offset] +
8791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth						data[-lum_offset + 1]);
8801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		else
8811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			atomic_set(&sd->avg_lum, -1);
8821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Start the new frame with the jpeg header */
8841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* The PAC7302 has the image rotated 90 degrees */
8851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_start_frame(gspca_dev, frame,
8861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			gspca_dev->width, gspca_dev->height);
8871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
88876dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
8891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8911408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
8921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
8941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->brightness = val;
8961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
8971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setbrightcont(gspca_dev);
898be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
8991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9011408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
9021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->brightness;
9061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9091408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
9101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->contrast = val;
9141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming) {
9151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setbrightcont(gspca_dev);
9161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
917be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
9181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9201408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
9211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->contrast;
9251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9281408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
9291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->colors = val;
9331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
9341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setcolors(gspca_dev);
935be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
9361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9381408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
9391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->colors;
9431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
94623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
94723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
94823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
94923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
95023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	sd->white_balance = val;
95123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (gspca_dev->streaming)
952be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		setwhitebalance(gspca_dev);
953be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
95423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
95523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
95623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
95723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
95823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
95923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
96023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	*val = sd->white_balance;
96123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	return 0;
96223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
96323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
964265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
965265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
966265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
967265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
968265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->red_balance = val;
969265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (gspca_dev->streaming)
970be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		setredbalance(gspca_dev);
971be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
972265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
973265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
974265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
975265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
976265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
977265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
978265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	*val = sd->red_balance;
979265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return 0;
980265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
981265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
982265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
983265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
984265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
985265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
986265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->blue_balance = val;
987265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (gspca_dev->streaming)
988be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		setbluebalance(gspca_dev);
989be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
990265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
991265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
992265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
993265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
994265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
995265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
996265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	*val = sd->blue_balance;
997265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return 0;
998265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
999265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
10001408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
10011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->gain = val;
10051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setgain(gspca_dev);
1007be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
10081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10101408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
10111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->gain;
10151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10181408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
10191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->exposure = val;
10231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setexposure(gspca_dev);
1025be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
10261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10281408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
10291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->exposure;
10331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10361408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
10371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain = val;
10411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* when switching to autogain set defaults to make sure
10421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   we are on a valid point of the autogain gain /
10431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   exposure knee graph, and give this change time to
10441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   take effect before doing autogain. */
10451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sd->autogain) {
10461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->exposure = EXPOSURE_DEF;
10471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->gain = GAIN_DEF;
10481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->streaming) {
10491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->autogain_ignore_frames =
10501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				PAC_AUTOGAIN_IGNORE_FRAMES;
10511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			setexposure(gspca_dev);
10521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			setgain(gspca_dev);
10531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
10541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
10551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1056be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
10571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10591408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
10601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->autogain;
10641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10671408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
10681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->hflip = val;
10721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sethvflip(gspca_dev);
1074be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
10751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10771408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
10781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->hflip;
10821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10851408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
10861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->vflip = val;
10901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sethvflip(gspca_dev);
1092be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
10931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10951408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
10961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->vflip;
11001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11036763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#ifdef CONFIG_VIDEO_ADV_DEBUG
11046763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Némethstatic int sd_dbg_s_register(struct gspca_dev *gspca_dev,
11056763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			struct v4l2_dbg_register *reg)
11066763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh{
11076763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	__u8 index;
11086763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	__u8 value;
11096763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11106763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	/* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
11116763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			       long on the USB bus)
11126763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	*/
11136763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
11146763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    reg->match.addr == 0 &&
11156763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    (reg->reg < 0x000000ff) &&
11166763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    (reg->val <= 0x000000ff)
11176763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	) {
11186763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* Currently writing to page 0 is only supported. */
11196763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* reg_w() only supports 8bit index */
11206763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		index = reg->reg & 0x000000ff;
11216763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		value = reg->val & 0x000000ff;
11226763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11236763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* Note that there shall be no access to other page
11246763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		   by any other function between the page swith and
11256763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		   the actual register write */
1126be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
1127be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, index, value);
11286763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
1129be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine		reg_w(gspca_dev, 0xdc, 0x01);
11306763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	}
1131be927befd091481f88c5806aa0585f25ab2ee3a1Jean-Francois Moine	return gspca_dev->usb_err;
11326763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh}
11336763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11346763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Némethstatic int sd_chip_ident(struct gspca_dev *gspca_dev,
11356763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			struct v4l2_dbg_chip_ident *chip)
11366763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh{
11376763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	int ret = -EINVAL;
11386763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11396763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
11406763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    chip->match.addr == 0) {
11416763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		chip->revision = 0;
11426763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		chip->ident = V4L2_IDENT_UNKNOWN;
11436763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		ret = 0;
11446763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	}
11456763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	return ret;
11466763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh}
11476763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#endif
11486763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
1149aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#ifdef CONFIG_INPUT
1150aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Némethstatic int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1151aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			u8 *data,		/* interrupt packet data */
1152aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			int len)		/* interrput packet length */
1153aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh{
1154aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	int ret = -EINVAL;
1155aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	u8 data0, data1;
1156aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh
1157aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	if (len == 2) {
1158aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		data0 = data[0];
1159aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		data1 = data[1];
1160aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		if ((data0 == 0x00 && data1 == 0x11) ||
1161aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x22 && data1 == 0x33) ||
1162aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x44 && data1 == 0x55) ||
1163aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x66 && data1 == 0x77) ||
1164aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0x88 && data1 == 0x99) ||
1165aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0xaa && data1 == 0xbb) ||
1166aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0xcc && data1 == 0xdd) ||
1167aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		    (data0 == 0xee && data1 == 0xff)) {
1168aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1169aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_sync(gspca_dev->input_dev);
1170aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1171aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			input_sync(gspca_dev->input_dev);
1172aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh			ret = 0;
1173aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh		}
1174aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	}
1175aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh
1176aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	return ret;
1177aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh}
1178aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#endif
1179aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh
11801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* sub-driver description for pac7302 */
1181aabcdfb65be31d7f9486d1400fa217c8827dddd3Márton Némethstatic const struct sd_desc sd_desc = {
11821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.name = MODULE_NAME,
11831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.ctrls = sd_ctrls,
11841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.nctrls = ARRAY_SIZE(sd_ctrls),
11851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.config = sd_config,
11861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.init = sd_init,
11871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.start = sd_start,
11881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stopN = sd_stopN,
11891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stop0 = sd_stop0,
11901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.pkt_scan = sd_pkt_scan,
11911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.dq_callback = do_autogain,
11926763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#ifdef CONFIG_VIDEO_ADV_DEBUG
11936763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	.set_register = sd_dbg_s_register,
11946763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	.get_chip_ident = sd_chip_ident,
11956763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#endif
1196aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#ifdef CONFIG_INPUT
1197aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh	.int_pkt_scan = sd_int_pkt_scan,
1198aed6f1b5fe4e95cf8a9fc149e25041aa8cc7c78aMárton Németh#endif
11991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
12001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- module initialisation -- */
120237b372e5ebe187037e01885151a0afb546a38520Márton Némethstatic const struct usb_device_id device_table[] __devinitconst = {
12031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x06f8, 0x3009)},
12041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2620)},
12051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2621)},
1206fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	{USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1207fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	{USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
12081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2626)},
12091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2628)},
1210c4322bfca8907109689eb6b244258bf52277f7dcJean-Francois Moine	{USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
12111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262a)},
12121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262c)},
12131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{}
12141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
12151408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DEVICE_TABLE(usb, device_table);
12161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- device connect -- */
121837b372e5ebe187037e01885151a0afb546a38520Márton Némethstatic int __devinit sd_probe(struct usb_interface *intf,
12191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
12201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
12211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
12221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				THIS_MODULE);
12231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12251408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct usb_driver sd_driver = {
12261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.name = MODULE_NAME,
12271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.id_table = device_table,
12281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.probe = sd_probe,
12291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.disconnect = gspca_disconnect,
12301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#ifdef CONFIG_PM
12311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.suspend = gspca_suspend,
12321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.resume = gspca_resume,
12331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#endif
12341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
12351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- module insert / remove -- */
12371408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int __init sd_mod_init(void)
12381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
12391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int ret;
12401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	ret = usb_register(&sd_driver);
12411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (ret < 0)
12421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return ret;
12431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_PROBE, "registered");
12441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
12451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12461408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void __exit sd_mod_exit(void)
12471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
12481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	usb_deregister(&sd_driver);
12491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_PROBE, "deregistered");
12501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12521408b8472910e894b290205b4baed5b14b8f45afMarton Nemethmodule_init(sd_mod_init);
12531408b8472910e894b290205b4baed5b14b8f45afMarton Nemethmodule_exit(sd_mod_exit);
1254