pac7302.c revision 37b372e5ebe187037e01885151a0afb546a38520
11408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*
21408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *		Pixart PAC7302 library
31408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *		Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
41408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
51408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
61408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
71408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * Separated from Pixart PAC7311 library by M�rton N�meth <nm127@freemail.hu>
81408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
91408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is free software; you can redistribute it and/or modify
101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * it under the terms of the GNU General Public License as published by
111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * the Free Software Foundation; either version 2 of the License, or
121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * any later version.
131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * This program is distributed in the hope that it will be useful,
151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * but WITHOUT ANY WARRANTY; without even the implied warranty of
161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * GNU General Public License for more details.
181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth *
191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * You should have received a copy of the GNU General Public License
201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * along with this program; if not, write to the Free Software
211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth */
231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* Some documentation about various registers as determined by trial and error.
251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   When the register addresses differ between the 7202 and the 7311 the 2
261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   different addresses are written as 7302addr/7311addr, when one of the 2
271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   addresses is a - sign that register description is not valid for the
281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   matching IC.
291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Register page 1:
311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x08	Unknown compressor related, must always be 8 except when not
341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x1b	Auto white balance related, bit 0 is AWB enable (inverted)
361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		bits 345 seem to toggle per color gains on/off (inverted)
371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x78		Global control, bit 6 controls the LED (inverted)
381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x80	JPEG compression ratio ? Best not touched
391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Register page 3/4:
411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   Address	Description
431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x02		Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x0f	Master gain 1-245, low value = high gain
461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x10/-	Master gain 0-31
471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x10	Another gain 0-15, limited influence (1-2x gain I guess)
481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth   -/0x27	Seems to toggle various gains on / off, Setting bit 7 seems to
501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		completely disable the analog amplification block. Set to 0x68
511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		for max gain, 0x14 for minimal gain.
52265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
53265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   The registers are accessed in the following functions:
54265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
55265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   Page | Register   | Function
56265a8098e75e156985abfaac250ee4f2b407f863Márton Németh   -----+------------+---------------------------------------------------
57265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0x0f..0x20 | setcolors()
58265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xa2..0xab | setbrightcont()
59265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc5       | setredbalance()
6023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth    0   | 0xc6       | setwhitebalance()
61265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xc7       | setbluebalance()
62265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    0   | 0xdc       | setbrightcont(), setcolors()
63265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x02       | setexposure()
64265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x10       | setgain()
65265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x11       | setcolors(), setgain(), setexposure(), sethvflip()
66265a8098e75e156985abfaac250ee4f2b407f863Márton Németh    3   | 0x21       | sethvflip()
671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth*/
681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define MODULE_NAME "pac7302"
701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
716763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#include <media/v4l2-chip-ident.h>
721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#include "gspca.h"
731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
741408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
751408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DESCRIPTION("Pixart PAC7302");
761408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_LICENSE("GPL");
771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* specific webcam descriptor for pac7302 */
791408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstruct sd {
801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct gspca_dev gspca_dev;		/* !! must be the first item */
811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char brightness;
831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char contrast;
841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char colors;
8523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	unsigned char white_balance;
86265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	unsigned char red_balance;
87265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	unsigned char blue_balance;
881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char gain;
891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char exposure;
901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char autogain;
911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 hflip;
921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 vflip;
93fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	u8 flags;
94fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine#define FL_HFLIP 0x01		/* mirrored by default */
95fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine#define FL_VFLIP 0x02		/* vertical flipped by default */
961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	u8 sof_read;
981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	u8 autogain_ignore_frames;
991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	atomic_t avg_lum;
1011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
1021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* V4L2 controls supported by the driver */
1041408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
1051408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
1061408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
1071408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
1081408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
1091408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
11023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
11123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
112265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
113265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
114265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
115265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
1161408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
1171408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
1181408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
1191408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
1201408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
1211408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
1221408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
1231408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
1241408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
1251408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
1261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
1271408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct ctrl sd_ctrls[] = {
1281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is pac7302 only */
1291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_BRIGHTNESS,
1321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Brightness",
1341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define BRIGHTNESS_MAX 0x20
1361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = BRIGHTNESS_MAX,
1371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define BRIGHTNESS_DEF 0x10
1391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = BRIGHTNESS_DEF,
1401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setbrightness,
1421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getbrightness,
1431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
1441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is for both the 7302 and the 7311 */
1451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_CONTRAST,
1481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Contrast",
1501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define CONTRAST_MAX 255
1521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = CONTRAST_MAX,
1531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define CONTRAST_DEF 127
1551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = CONTRAST_DEF,
1561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setcontrast,
1581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getcontrast,
1591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
1601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This control is pac7302 only */
1611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
1621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
1631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_SATURATION,
1641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
1651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Saturation",
1661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
1671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define COLOR_MAX 255
1681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = COLOR_MAX,
1691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
1701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define COLOR_DEF 127
1711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = COLOR_DEF,
1721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
1731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setcolors,
1741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getcolors,
1751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
176265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	{
177265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
17823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.id      = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
17923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
18023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.name    = "White Balance",
18123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.minimum = 0,
18223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.maximum = 255,
18323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.step    = 1,
18423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth#define WHITEBALANCE_DEF 4
18523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		.default_value = WHITEBALANCE_DEF,
18623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    },
18723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    .set = sd_setwhitebalance,
18823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    .get = sd_getwhitebalance,
18923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	},
19023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	{
19123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	    {
192265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_RED_BALANCE,
193265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
194265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Red",
195265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
196265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
197265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
198265a8098e75e156985abfaac250ee4f2b407f863Márton Németh#define REDBALANCE_DEF 1
199265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.default_value = REDBALANCE_DEF,
200265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
201265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .set = sd_setredbalance,
202265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .get = sd_getredbalance,
203265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
204265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	{
205265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    {
206265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.id      = V4L2_CID_BLUE_BALANCE,
207265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.type    = V4L2_CTRL_TYPE_INTEGER,
208265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.name    = "Blue",
209265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.minimum = 0,
210265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.maximum = 3,
211265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.step    = 1,
212265a8098e75e156985abfaac250ee4f2b407f863Márton Németh#define BLUEBALANCE_DEF 1
213265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		.default_value = BLUEBALANCE_DEF,
214265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    },
215265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .set = sd_setbluebalance,
216265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	    .get = sd_getbluebalance,
217265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	},
2181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* All controls below are for both the 7302 and the 7311 */
2191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_GAIN,
2221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
2231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Gain",
2241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_MAX 255
2261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = GAIN_MAX,
2271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_DEF 127
2291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
2301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = GAIN_DEF,
2311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setgain,
2331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getgain,
2341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_EXPOSURE,
2381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_INTEGER,
2391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Exposure",
2401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_MAX 255
2421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = EXPOSURE_MAX,
2431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
2451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
2461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = EXPOSURE_DEF,
2471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setexposure,
2491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getexposure,
2501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_AUTOGAIN,
2541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Auto Gain",
2561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define AUTOGAIN_DEF 1
2601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = AUTOGAIN_DEF,
2611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setautogain,
2631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getautogain,
2641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_HFLIP,
2681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Mirror",
2701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define HFLIP_DEF 0
2741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = HFLIP_DEF,
2751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_sethflip,
2771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_gethflip,
2781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{
2801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    {
2811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.id      = V4L2_CID_VFLIP,
2821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.type    = V4L2_CTRL_TYPE_BOOLEAN,
2831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.name    = "Vflip",
2841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.minimum = 0,
2851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.maximum = 1,
2861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.step    = 1,
2871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define VFLIP_DEF 0
2881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.default_value = VFLIP_DEF,
2891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    },
2901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .set = sd_setvflip,
2911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	    .get = sd_getvflip,
2921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	},
2931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
2941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
2951408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const struct v4l2_pix_format vga_mode[] = {
2961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
2971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.bytesperline = 640,
2981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.sizeimage = 640 * 480 * 3 / 8 + 590,
2991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.colorspace = V4L2_COLORSPACE_JPEG,
3001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		.priv = 0},
3011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define LOAD_PAGE3		255
3041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define LOAD_PAGE4		254
3051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define END_OF_SEQUENCE		0
3061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* pac 7302 */
3081408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 init_7302[] = {
3091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index,value */
3101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,		/* page 1 */
3111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x00,		/* deactivate */
3121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 0x01,
3131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 0x40,		/* led off */
3141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3151408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 start_7302[] = {
3161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/*	index, len, [value]* */
3171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x00,		/* page 0 */
3181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 12,	0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
3191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x00, 0x00, 0x00,
3201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0d, 24,	0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
3211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
3221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
3231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x26, 2,	0xaa, 0xaa,
3241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2e, 1,	0x31,
3251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x38, 1,	0x01,
3261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3a, 3,	0x14, 0xff, 0x5a,
3271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x43, 11,	0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
3281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x00, 0x54, 0x11,
3291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x55, 1,	0x00,
3301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x62, 4, 	0x10, 0x1e, 0x1e, 0x18,
3311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6b, 1,	0x00,
3321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 3,	0x08, 0x06, 0x00,
3331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x72, 3,	0x00, 0xff, 0x00,
3341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7d, 23,	0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
3351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
3361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
3371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa2, 10,	0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
3381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xd2, 0xeb,
3391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xaf, 1,	0x02,
3401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb5, 2,	0x08, 0x08,
3411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xb8, 2,	0x08, 0x88,
3421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc4, 4,	0xae, 0x01, 0x04, 0x01,
3431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xcc, 1,	0x00,
3441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd1, 11,	0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
3451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0xc1, 0xd7, 0xec,
3461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdc, 1,	0x01,
3471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x12, 3,	0x02, 0x00, 0x01,
3491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x3e, 2,	0x00, 0x00,
3501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x76, 5,	0x01, 0x20, 0x40, 0x00, 0xf2,
3511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7c, 1,	0x00,
3521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x7f, 10,	0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
3531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x02, 0x00,
3541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x96, 5,	0x01, 0x10, 0x04, 0x01, 0x04,
3551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 14,	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
3561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
3571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xd8, 1,	0x01,
3581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xdb, 2,	0x00, 0x01,
3591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xde, 7,	0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
3601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xe6, 4,	0x00, 0x00, 0x00, 0x01,
3611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xeb, 1,	0x00,
3621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 1,	0x00,
3641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x03,		/* page 3 */
3651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, LOAD_PAGE3,			/* load the page 3 */
3661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x11, 1,	0x01,
3671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x02,		/* page 2 */
3681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x13, 1,	0x00,
3691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x22, 4,	0x1f, 0xa4, 0xf0, 0x96,
3701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x27, 2,	0x14, 0x0c,
3711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x2a, 5,	0xc8, 0x00, 0x18, 0x12, 0x22,
3721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x64, 8,	0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
3731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x6e, 1,	0x08,
3741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xff, 1,	0x01,		/* page 1 */
3751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x78, 1,	0x00,
3761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0, END_OF_SEQUENCE		/* end of sequence */
3771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
3781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
3791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#define SKIP		0xaa
3801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* page 3 - the value SKIP says skip the index - see reg_w_page() */
3811408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const __u8 page3_7302[] = {
3821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
3831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
3841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
3861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
3871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
3881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
3891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
3911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
3921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
3941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
3961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
3971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
3981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
3991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
4011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	0x00
4021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
4031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
404b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_buf(struct gspca_dev *gspca_dev,
4051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 index,
4061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  const char *buffer, int len)
4071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4084f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
4094f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
4101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	memcpy(gspca_dev->usb_buf, buffer, len);
4114f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
4121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
4131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			1,		/* request */
4141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,		/* value */
4161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			index, gspca_dev->usb_buf, len,
4171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
4184f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	if (ret < 0)
4194f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		PDEBUG(D_ERR, "reg_w_buf(): "
4204f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		"Failed to write registers to index 0x%x, error %i",
4214f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		index, ret);
422b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
426b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w(struct gspca_dev *gspca_dev,
4271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 index,
4281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		  __u8 value)
4291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4304f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	int ret;
4314f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth
4321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	gspca_dev->usb_buf[0] = value;
4334f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	ret = usb_control_msg(gspca_dev->dev,
4341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			usb_sndctrlpipe(gspca_dev->dev, 0),
4351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0,			/* request */
4361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			0, index, gspca_dev->usb_buf, 1,
4381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			500);
4394f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth	if (ret < 0)
4404f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		PDEBUG(D_ERR, "reg_w(): "
4414f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		"Failed to write register to index 0x%x, value 0x%x, error %i",
4424f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		index, value, ret);
443b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
446b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_seq(struct gspca_dev *gspca_dev,
4471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		const __u8 *seq, int len)
4481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
449b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	while (--len >= 0) {
451b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
452b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, seq[0], seq[1]);
4531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		seq += 2;
4541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
455b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* load the beginning of a page */
459b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_page(struct gspca_dev *gspca_dev,
4601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *page, int len)
4611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index;
463b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (index = 0; index < len; index++) {
4661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (page[index] == SKIP)		/* skip this index */
4671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			continue;
4681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		gspca_dev->usb_buf[0] = page[index];
4694f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth		ret = usb_control_msg(gspca_dev->dev,
4701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				usb_sndctrlpipe(gspca_dev->dev, 0),
4711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0,			/* request */
4721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
4731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				0, index, gspca_dev->usb_buf, 1,
4741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				500);
475b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (ret < 0) {
4764f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			PDEBUG(D_ERR, "reg_w_page(): "
4774f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			"Failed to write register to index 0x%x, "
4784f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			"value 0x%x, error %i",
4794f7309e27865b88df7b0b0ad59e0376dba1806afMarton Nemeth			index, page[index], ret);
480b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			break;
481b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		}
4821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
483b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
4841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
4851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* output a variable sequence */
487b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int reg_w_var(struct gspca_dev *gspca_dev,
4881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *seq,
4891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *page3, unsigned int page3_len,
4901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const __u8 *page4, unsigned int page4_len)
4911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
4921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int index, len;
493b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
4941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
4951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (;;) {
4961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		index = *seq++;
4971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len = *seq++;
4981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		switch (len) {
4991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case END_OF_SEQUENCE:
500b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			return ret;
5011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case LOAD_PAGE4:
502b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w_page(gspca_dev, page4, page4_len);
5031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			break;
5041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		case LOAD_PAGE3:
505b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w_page(gspca_dev, page3, page3_len);
5061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			break;
5071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		default:
5081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			if (len > USB_BUF_SZ) {
5091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				PDEBUG(D_ERR|D_STREAM,
5101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					"Incorrect variable sequence");
511b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh				return -EINVAL;
5121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
5131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			while (len > 0) {
5141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				if (len < 8) {
515b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh					ret = reg_w_buf(gspca_dev,
516b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh						index, seq, len);
517b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh					if (ret < 0)
518b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh						return ret;
5191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					seq += len;
5201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					break;
5211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				}
522b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh				ret = reg_w_buf(gspca_dev, index, seq, 8);
5231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				seq += 8;
5241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				index += 8;
5251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				len -= 8;
5261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			}
5271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
528b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (ret < 0)
529b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			return ret;
5301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
5311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* not reached */
5321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe time for pac7302 */
5351408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_config(struct gspca_dev *gspca_dev,
5361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
5371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct cam *cam;
5401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam = &gspca_dev->cam;
5421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_CONF, "Find Sensor PAC7302");
5441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->cam_mode = vga_mode;	/* only 640x480 */
5451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	cam->nmodes = ARRAY_SIZE(vga_mode);
5461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->brightness = BRIGHTNESS_DEF;
5481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->contrast = CONTRAST_DEF;
5491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->colors = COLOR_DEF;
55023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	sd->white_balance = WHITEBALANCE_DEF;
551265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->red_balance = REDBALANCE_DEF;
552265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->blue_balance = BLUEBALANCE_DEF;
5531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->gain = GAIN_DEF;
5541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->exposure = EXPOSURE_DEF;
5551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain = AUTOGAIN_DEF;
5561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->hflip = HFLIP_DEF;
5571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->vflip = VFLIP_DEF;
558fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	sd->flags = id->driver_info;
5591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
5601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
563b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setbrightcont(struct gspca_dev *gspca_dev)
5641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
567b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
5681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const __u8 max[10] =
5691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
5701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0xd4, 0xec};
5711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const __u8 delta[10] =
5721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
5731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		 0x11, 0x0b};
5741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
575b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
5761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 10; i++) {
5771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v = max[i];
5781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v += (sd->brightness - BRIGHTNESS_MAX)
5791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			* 150 / BRIGHTNESS_MAX;		/* 200 ? */
5801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v -= delta[i] * sd->contrast / CONTRAST_MAX;
5811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (v < 0)
5821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0;
5831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		else if (v > 0xff)
5841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			v = 0xff;
585b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
586b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, 0xa2 + i, v);
5871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
588b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
589b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
590b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
5911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
5921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
5931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* This function is used by pac7302 only */
594b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setcolors(struct gspca_dev *gspca_dev)
5951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
5961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
5971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int i, v;
598b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
5991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int a[9] =
6001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{217, -212, 0, -101, 170, -67, -38, -315, 355};
6011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	static const int b[9] =
6021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		{19, 106, 0, 19, 106, 1, 19, 106, 1};
6031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
604b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);	/* page 3 */
605b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
606b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
607b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
608b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
6091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	for (i = 0; i < 9; i++) {
6101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		v = a[i] * sd->colors / COLOR_MAX + b[i];
611b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
612b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
613b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		if (0 <= ret)
614b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh			ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
6151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
616b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
617b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
6181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
619b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
6201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
62223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int setwhitebalance(struct gspca_dev *gspca_dev)
62323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
62423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
62523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	int ret;
62623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
62723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
62823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
62923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = reg_w(gspca_dev, 0xc6, sd->white_balance);
63023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
63123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
63223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = reg_w(gspca_dev, 0xdc, 0x01);
63323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
63423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	return ret;
63523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
63623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
637265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int setredbalance(struct gspca_dev *gspca_dev)
638265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
639265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
640265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret;
641265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
642265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
643265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
644265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xc5, sd->red_balance);
645265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
646265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
647265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
648265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
649265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
650265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
651265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
652265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int setbluebalance(struct gspca_dev *gspca_dev)
653265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
654265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
655265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret;
656265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
657265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
658265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
659265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xc7, sd->blue_balance);
660265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
661265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
662265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = reg_w(gspca_dev, 0xdc, 0x01);
663265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
664265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
665265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
666265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
667b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setgain(struct gspca_dev *gspca_dev)
6681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
670b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
6711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
672b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
673b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
674b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x10, sd->gain >> 3);
6751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
677b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
678b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
679b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
6801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
6811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
682b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int setexposure(struct gspca_dev *gspca_dev)
6831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
6841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
685b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
6861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	__u8 reg;
6871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* register 2 of frame 3/4 contains the clock divider configuring the
6891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   no fps according to the formula: 60 / reg. sd->exposure is the
6901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   desired exposure time in ms. */
6911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	reg = 120 * sd->exposure / 1000;
6921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (reg < 2)
6931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = 2;
6941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else if (reg > 63)
6951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = 63;
6961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
6971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* On the pac7302 reg2 MUST be a multiple of 3, so round it to
6981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   the nearest multiple of 3, except when between 6 and 12? */
6991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (reg < 6 || reg > 12)
7001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		reg = ((reg + 1) / 3) * 3;
701b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
702b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
703b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x02, reg);
7041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
706b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
707b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
708b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
7091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
711b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Némethstatic int sethvflip(struct gspca_dev *gspca_dev)
7121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
714b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
715fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	u8 data, hflip, vflip;
716fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine
717fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	hflip = sd->hflip;
718fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	if (sd->flags & FL_HFLIP)
719fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine		hflip = !hflip;
720fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	vflip = sd->vflip;
721fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	if (sd->flags & FL_VFLIP)
722fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine		vflip = !vflip;
7231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
724b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
725fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
726b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
727b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x21, data);
7281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* load registers to sensor (Bit 0, auto clear) */
729b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
730b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x11, 0x01);
731b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
7321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is called at probe and resume time for pac7302 */
7351408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_init(struct gspca_dev *gspca_dev)
7361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
737b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
7381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7401408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_start(struct gspca_dev *gspca_dev)
7411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
7421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
743b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret = 0;
7441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->sof_read = 0;
7461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
747b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w_var(gspca_dev, start_7302,
7481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		page3_7302, sizeof(page3_7302),
7491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		NULL, 0);
750b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
751b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = setbrightcont(gspca_dev);
752b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
753b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = setcolors(gspca_dev);
754b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
75523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = setwhitebalance(gspca_dev);
75623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
757265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setredbalance(gspca_dev);
758265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
759265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setbluebalance(gspca_dev);
760265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
761012880be6e1c8503e2901f8de90cc1e711334989Marton Nemeth		ret = setgain(gspca_dev);
762b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
763012880be6e1c8503e2901f8de90cc1e711334989Marton Nemeth		ret = setexposure(gspca_dev);
764b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
765012880be6e1c8503e2901f8de90cc1e711334989Marton Nemeth		ret = sethvflip(gspca_dev);
7661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* only resolution 640x480 is supported for pac7302 */
7681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->sof_read = 0;
7701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain_ignore_frames = 0;
7711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	atomic_set(&sd->avg_lum, -1);
7721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* start stream */
774b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
775b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0xff, 0x01);
776b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
777b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x78, 0x01);
7781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
779b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	return ret;
7801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7821408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stopN(struct gspca_dev *gspca_dev)
7831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
784b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
785b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh
78667c98f72e132e191ff4db0ac7bd81ea94fa5c667Márton Németh	/* stop stream */
787b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x01);
788b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
789b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x78, 0x00);
7901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
7911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
7921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* called on streamoff with alt 0 and on disconnect for pac7302 */
7931408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_stop0(struct gspca_dev *gspca_dev)
7941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
795b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	int ret;
796b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh
7971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (!gspca_dev->present)
7981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
799b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	ret = reg_w(gspca_dev, 0xff, 0x01);
800b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh	if (0 <= ret)
801b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4Márton Németh		ret = reg_w(gspca_dev, 0x78, 0x40);
8021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* Include pac common sof detection functions */
8051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#include "pac_common.h"
8061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8071408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void do_autogain(struct gspca_dev *gspca_dev)
8081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
8101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int avg_lum = atomic_read(&sd->avg_lum);
8111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int desired_lum, deadzone;
8121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (avg_lum == -1)
8141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return;
8151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	desired_lum = 270 + sd->brightness * 4;
8171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* Hack hack, with the 7202 the first exposure step is
8181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   pretty large, so if we're about to make the first
8191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   exposure increase make the deadzone large to avoid
8201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   oscilating */
8211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
8221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->exposure > EXPOSURE_DEF &&
8231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->exposure < 42)
8241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		deadzone = 90;
8251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else
8261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		deadzone = 30;
8271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sd->autogain_ignore_frames > 0)
8291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames--;
8301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
8311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			deadzone, GAIN_KNEE, EXPOSURE_KNEE))
8321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
8331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* JPEG header, part 1 */
8361408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const unsigned char pac_jpeg_header1[] = {
8371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xd8,		/* SOI: Start of Image */
8381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xc0,		/* SOF0: Start of Frame (Baseline DCT) */
8401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x11,		/* length = 17 bytes (including this length field) */
8411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x08			/* Precision: 8 */
8421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  /* 2 bytes is placed here: number of image lines */
8431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  /* 2 bytes is placed here: samples per line */
8441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
8451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* JPEG header, continued */
8471408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic const unsigned char pac_jpeg_header2[] = {
8481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03,			/* Number of image components: 3 */
8491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x01, 0x21, 0x00,	/* ID=1, Subsampling 1x1, Quantization table: 0 */
8501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x02, 0x11, 0x01,	/* ID=2, Subsampling 2x1, Quantization table: 1 */
8511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03, 0x11, 0x01,	/* ID=3, Subsampling 2x1, Quantization table: 1 */
8521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0xff, 0xda,		/* SOS: Start Of Scan */
8541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x0c,		/* length = 12 bytes (including this length field) */
8551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03,			/* number of components: 3 */
8561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x01, 0x00,		/* selector 1, table 0x00 */
8571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x02, 0x11,		/* selector 2, table 0x11 */
8581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x03, 0x11,		/* selector 3, table 0x11 */
8591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00, 0x3f,		/* Spectral selection: 0 .. 63 */
8601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth  0x00			/* Successive approximation: 0 */
8611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
8621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8631408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void pac_start_frame(struct gspca_dev *gspca_dev,
8641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		struct gspca_frame *frame,
8651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		__u16 lines, __u16 samples_per_line)
8661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char tmpbuf[4];
8681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
86976dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, FIRST_PACKET,
8701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_jpeg_header1, sizeof(pac_jpeg_header1));
8711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[0] = lines >> 8;
8731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[1] = lines & 0xff;
8741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[2] = samples_per_line >> 8;
8751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	tmpbuf[3] = samples_per_line & 0xff;
8761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
87776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET,
8781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		tmpbuf, sizeof(tmpbuf));
87976dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET,
8801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_jpeg_header2, sizeof(pac_jpeg_header2));
8811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
8821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* this function is run at interrupt level */
8841408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
88576dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			u8 *data,			/* isoc packet */
8861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			int len)			/* iso packet length */
8871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
8881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
88976dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	struct gspca_frame *frame;
8901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	unsigned char *sof;
8911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
8921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sof = pac_find_sof(&sd->sof_read, data, len);
8931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sof) {
8941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		int n, lum_offset, footer_length;
8951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
89676dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		frame = gspca_get_i_frame(gspca_dev);
89776dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		if (frame == NULL) {
89876dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_dev->last_packet_type = DISCARD_PACKET;
89976dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			return;
90076dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		}
90176dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine
9021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* 6 bytes after the FF D9 EOF marker a number of lumination
9031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   bytes are send corresponding to different parts of the
9041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   image, the 14th and 15th byte after the EOF seem to
9051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		   correspond to the center of the image */
9061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		lum_offset = 61 + sizeof pac_sof_marker;
9071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		footer_length = 74;
9081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Finish decoding current frame */
9101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
9111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (n < 0) {
9121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			frame->data_end += n;
9131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			n = 0;
9141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
91576dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine		gspca_frame_add(gspca_dev, INTER_PACKET,
9161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth					data, n);
9171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->last_packet_type != DISCARD_PACKET &&
9181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				frame->data_end[-2] == 0xff &&
9191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				frame->data_end[-1] == 0xd9)
92076dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine			gspca_frame_add(gspca_dev, LAST_PACKET,
9211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth						NULL, 0);
9221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		n = sof - data;
9241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		len -= n;
9251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		data = sof;
9261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Get average lumination */
9281408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->last_packet_type == LAST_PACKET &&
9291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				n >= lum_offset)
9301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			atomic_set(&sd->avg_lum, data[-lum_offset] +
9311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth						data[-lum_offset + 1]);
9321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		else
9331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			atomic_set(&sd->avg_lum, -1);
9341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* Start the new frame with the jpeg header */
9361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		/* The PAC7302 has the image rotated 90 degrees */
9371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		pac_start_frame(gspca_dev, frame,
9381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			gspca_dev->width, gspca_dev->height);
9391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
94076dd272b56cd1c7fa013ef5d7eb28c4d319e322bJean-Francois Moine	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
9411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9431408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
9441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->brightness = val;
9481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
9491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setbrightcont(gspca_dev);
9501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9531408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
9541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->brightness;
9581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9611408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
9621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->contrast = val;
9661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming) {
9671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setbrightcont(gspca_dev);
9681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
9691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9721408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
9731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->contrast;
9771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9801408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
9811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->colors = val;
9851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
9861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setcolors(gspca_dev);
9871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9891408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9901408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
9911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
9921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
9931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
9941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->colors;
9951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
9961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
9971408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
99823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
99923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
100023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
100123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	int ret = 0;
100223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
100323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	sd->white_balance = val;
100423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (gspca_dev->streaming)
100523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = setwhitebalance(gspca_dev);
100623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	if (0 <= ret)
100723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth		ret = 0;
100823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	return ret;
100923fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
101023fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
101123fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemethstatic int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
101223fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth{
101323fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
101423fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
101523fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	*val = sd->white_balance;
101623fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth	return 0;
101723fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth}
101823fbee6f88d59b4edca0855242d55e5b7cfc2401Marton Nemeth
1019265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
1020265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1021265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1022265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret = 0;
1023265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1024265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->red_balance = val;
1025265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (gspca_dev->streaming)
1026265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setredbalance(gspca_dev);
1027265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
1028265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = 0;
1029265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
1030265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1031265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1032265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
1033265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1034265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1035265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1036265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	*val = sd->red_balance;
1037265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return 0;
1038265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1039265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1040265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
1041265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1042265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1043265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	int ret = 0;
1044265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1045265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	sd->blue_balance = val;
1046265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (gspca_dev->streaming)
1047265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = setbluebalance(gspca_dev);
1048265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	if (0 <= ret)
1049265a8098e75e156985abfaac250ee4f2b407f863Márton Németh		ret = 0;
1050265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return ret;
1051265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1052265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1053265a8098e75e156985abfaac250ee4f2b407f863Márton Némethstatic int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
1054265a8098e75e156985abfaac250ee4f2b407f863Márton Németh{
1055265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	struct sd *sd = (struct sd *) gspca_dev;
1056265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
1057265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	*val = sd->blue_balance;
1058265a8098e75e156985abfaac250ee4f2b407f863Márton Németh	return 0;
1059265a8098e75e156985abfaac250ee4f2b407f863Márton Németh}
1060265a8098e75e156985abfaac250ee4f2b407f863Márton Németh
10611408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
10621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->gain = val;
10661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10671408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setgain(gspca_dev);
10681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10711408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
10721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->gain;
10761408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10791408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
10801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10821408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10831408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->exposure = val;
10841408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
10851408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		setexposure(gspca_dev);
10861408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10871408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10881408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10891408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
10901408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10911408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
10921408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10931408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->exposure;
10941408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
10951408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
10961408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
10971408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
10981408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
10991408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11001408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11011408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->autogain = val;
11021408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	/* when switching to autogain set defaults to make sure
11031408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   we are on a valid point of the autogain gain /
11041408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   exposure knee graph, and give this change time to
11051408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	   take effect before doing autogain. */
11061408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (sd->autogain) {
11071408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->exposure = EXPOSURE_DEF;
11081408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sd->gain = GAIN_DEF;
11091408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		if (gspca_dev->streaming) {
11101408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			sd->autogain_ignore_frames =
11111408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				PAC_AUTOGAIN_IGNORE_FRAMES;
11121408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			setexposure(gspca_dev);
11131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			setgain(gspca_dev);
11141408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		}
11151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	}
11161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11201408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
11211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->autogain;
11251408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11261408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11271408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11281408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
11291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11321408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->hflip = val;
11331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
11341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sethvflip(gspca_dev);
11351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11361408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11371408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11381408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
11391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11401408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->hflip;
11431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11451408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11461408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
11471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11481408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	sd->vflip = val;
11511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (gspca_dev->streaming)
11521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		sethvflip(gspca_dev);
11531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11551408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11561408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
11571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
11581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	struct sd *sd = (struct sd *) gspca_dev;
11591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	*val = sd->vflip;
11611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
11621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
11631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
11646763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#ifdef CONFIG_VIDEO_ADV_DEBUG
11656763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Némethstatic int sd_dbg_s_register(struct gspca_dev *gspca_dev,
11666763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			struct v4l2_dbg_register *reg)
11676763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh{
11686763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	int ret = -EINVAL;
11696763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	__u8 index;
11706763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	__u8 value;
11716763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11726763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	/* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
11736763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			       long on the USB bus)
11746763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	*/
11756763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
11766763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    reg->match.addr == 0 &&
11776763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    (reg->reg < 0x000000ff) &&
11786763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    (reg->val <= 0x000000ff)
11796763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	) {
11806763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* Currently writing to page 0 is only supported. */
11816763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* reg_w() only supports 8bit index */
11826763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		index = reg->reg & 0x000000ff;
11836763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		value = reg->val & 0x000000ff;
11846763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11856763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		/* Note that there shall be no access to other page
11866763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		   by any other function between the page swith and
11876763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		   the actual register write */
11886763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		ret = reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
11896763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		if (0 <= ret)
11906763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			ret = reg_w(gspca_dev, index, value);
11916763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11926763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		if (0 <= ret)
11936763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			ret = reg_w(gspca_dev, 0xdc, 0x01);
11946763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	}
11956763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	return ret;
11966763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh}
11976763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
11986763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Némethstatic int sd_chip_ident(struct gspca_dev *gspca_dev,
11996763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh			struct v4l2_dbg_chip_ident *chip)
12006763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh{
12016763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	int ret = -EINVAL;
12026763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
12036763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
12046763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	    chip->match.addr == 0) {
12056763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		chip->revision = 0;
12066763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		chip->ident = V4L2_IDENT_UNKNOWN;
12076763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh		ret = 0;
12086763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	}
12096763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	return ret;
12106763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh}
12116763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#endif
12126763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh
12131408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* sub-driver description for pac7302 */
12141408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct sd_desc sd_desc = {
12151408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.name = MODULE_NAME,
12161408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.ctrls = sd_ctrls,
12171408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.nctrls = ARRAY_SIZE(sd_ctrls),
12181408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.config = sd_config,
12191408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.init = sd_init,
12201408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.start = sd_start,
12211408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stopN = sd_stopN,
12221408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.stop0 = sd_stop0,
12231408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.pkt_scan = sd_pkt_scan,
12241408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.dq_callback = do_autogain,
12256763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#ifdef CONFIG_VIDEO_ADV_DEBUG
12266763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	.set_register = sd_dbg_s_register,
12276763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh	.get_chip_ident = sd_chip_ident,
12286763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8Márton Németh#endif
12291408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
12301408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12311408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- module initialisation -- */
123237b372e5ebe187037e01885151a0afb546a38520Márton Némethstatic const struct usb_device_id device_table[] __devinitconst = {
12331408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x06f8, 0x3009)},
12341408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2620)},
12351408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2621)},
1236fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	{USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1237fe2b6032513099b82cd19ef8da5050f02a18d3ecJean-Francois Moine	{USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
12381408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2626)},
12391408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x2628)},
1240c4322bfca8907109689eb6b244258bf52277f7dcJean-Francois Moine	{USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
12411408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262a)},
12421408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{USB_DEVICE(0x093a, 0x262c)},
12431408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	{}
12441408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
12451408b8472910e894b290205b4baed5b14b8f45afMarton NemethMODULE_DEVICE_TABLE(usb, device_table);
12461408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12471408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- device connect -- */
124837b372e5ebe187037e01885151a0afb546a38520Márton Némethstatic int __devinit sd_probe(struct usb_interface *intf,
12491408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth			const struct usb_device_id *id)
12501408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
12511408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
12521408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth				THIS_MODULE);
12531408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12541408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12551408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic struct usb_driver sd_driver = {
12561408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.name = MODULE_NAME,
12571408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.id_table = device_table,
12581408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.probe = sd_probe,
12591408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.disconnect = gspca_disconnect,
12601408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#ifdef CONFIG_PM
12611408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.suspend = gspca_suspend,
12621408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	.resume = gspca_resume,
12631408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth#endif
12641408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth};
12651408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12661408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth/* -- module insert / remove -- */
12671408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic int __init sd_mod_init(void)
12681408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
12691408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	int ret;
12701408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	ret = usb_register(&sd_driver);
12711408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	if (ret < 0)
12721408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth		return ret;
12731408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_PROBE, "registered");
12741408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	return 0;
12751408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12761408b8472910e894b290205b4baed5b14b8f45afMarton Nemethstatic void __exit sd_mod_exit(void)
12771408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth{
12781408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	usb_deregister(&sd_driver);
12791408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth	PDEBUG(D_PROBE, "deregistered");
12801408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth}
12811408b8472910e894b290205b4baed5b14b8f45afMarton Nemeth
12821408b8472910e894b290205b4baed5b14b8f45afMarton Nemethmodule_init(sd_mod_init);
12831408b8472910e894b290205b4baed5b14b8f45afMarton Nemethmodule_exit(sd_mod_exit);
1284