blob: a9150964356329d93ea136e151c0d7f0aebf8590 [file] [log] [blame]
Marton Nemeth1408b842009-11-02 08:13:21 -03001/*
Jean-François Moineae251e62012-02-27 05:15:12 -03002 * Pixart PAC7302 driver
Marton Nemeth1408b842009-11-02 08:13:21 -03003 *
Jean-François Moineae251e62012-02-27 05:15:12 -03004 * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
Marton Nemeth1408b842009-11-02 08:13:21 -03006 *
Jean-Francois Moinecc2f82c2010-01-28 16:35:40 -03007 * Separated from Pixart PAC7311 library by Márton Németh
Márton Némethaed6f1b2010-01-28 16:33:38 -03008 * Camera button input handling by Márton Németh <nm127@freemail.hu>
9 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
Marton Nemeth1408b842009-11-02 08:13:21 -030010 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
Hans de Goede895d4642012-04-28 10:31:17 -030026/*
27 * Some documentation about various registers as determined by trial and error.
28 *
Frank Schäferb1a19c02012-09-09 15:02:21 -030029 * Register page 0:
30 *
31 * Address Description
Frank Schäfer6f9b3312012-09-23 10:29:42 -030032 * 0x01 Red balance control
33 * 0x02 Green balance control
34 * 0x03 Blue balance control
Frank Schäfer780d6172012-09-09 15:02:24 -030035 * The Windows driver uses a quadratic approach to map
36 * the settable values (0-200) on register values:
Frank Schäfer6f9b3312012-09-23 10:29:42 -030037 * min=0x20, default=0x40, max=0x80
38 * 0x0f-0x20 Color and saturation control
Frank Schäfer780d6172012-09-09 15:02:24 -030039 * 0xa2-0xab Brightness, contrast and gamma control
Frank Schäferb1a19c02012-09-09 15:02:21 -030040 * 0xb6 Sharpness control (bits 0-4)
41 *
Hans de Goede895d4642012-04-28 10:31:17 -030042 * Register page 1:
43 *
44 * Address Description
45 * 0x78 Global control, bit 6 controls the LED (inverted)
Hans de Goede48bb7312012-04-27 13:00:57 -030046 * 0x80 Compression balance, 2 interesting settings:
47 * 0x0f Default
48 * 0x50 Values >= this switch the camera to a lower compression,
49 * using the same table for both luminance and chrominance.
50 * This gives a sharper picture. Only usable when running
51 * at < 15 fps! Note currently the driver does not use this
52 * as the quality gain is small and the generated JPG-s are
53 * only understood by v4l-utils >= 0.8.9
Hans de Goede895d4642012-04-28 10:31:17 -030054 *
55 * Register page 3:
56 *
57 * Address Description
58 * 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
59 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
60 * 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
61 * 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
62 * 63 -> ~27 fps, the 2 msb's must always be 1 !!
63 * 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
64 * 1 -> ~30 fps, 2 -> ~20 fps
65 * 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
66 * 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
Hans de Goede48bb7312012-04-27 13:00:57 -030067 * 0x10 Gain 0-31
68 * 0x12 Another gain 0-31, unlike 0x10 this one seems to start with an
69 * amplification value of 1 rather then 0 at its lowest setting
Hans de Goede895d4642012-04-28 10:31:17 -030070 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
Hans de Goede48bb7312012-04-27 13:00:57 -030071 * 0x80 Another framerate control, best left at 1, moving it from 1 to
72 * 2 causes the framerate to become 3/4th of what it was, and
73 * also seems to cause pixel averaging, resulting in an effective
74 * resolution of 320x240 and thus a much blockier image
Hans de Goede895d4642012-04-28 10:31:17 -030075 *
76 * The registers are accessed in the following functions:
77 *
78 * Page | Register | Function
79 * -----+------------+---------------------------------------------------
Frank Schäfer2b34e9d2012-09-23 10:29:43 -030080 * 0 | 0x01 | setredbalance()
81 * 0 | 0x03 | setbluebalance()
Hans de Goede895d4642012-04-28 10:31:17 -030082 * 0 | 0x0f..0x20 | setcolors()
83 * 0 | 0xa2..0xab | setbrightcont()
Frank Schäferb1a19c02012-09-09 15:02:21 -030084 * 0 | 0xb6 | setsharpness()
Hans de Goede895d4642012-04-28 10:31:17 -030085 * 0 | 0xc6 | setwhitebalance()
Hans de Goede895d4642012-04-28 10:31:17 -030086 * 0 | 0xdc | setbrightcont(), setcolors()
87 * 3 | 0x02 | setexposure()
Hans de Goededf8b9852012-04-28 10:12:28 -030088 * 3 | 0x10, 0x12 | setgain()
Hans de Goede895d4642012-04-28 10:31:17 -030089 * 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
90 * 3 | 0x21 | sethvflip()
91 */
Marton Nemeth1408b842009-11-02 08:13:21 -030092
Joe Perches133a9fe2011-08-21 19:56:57 -030093#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
94
Márton Némethaed6f1b2010-01-28 16:33:38 -030095#include <linux/input.h>
Marton Nemeth1408b842009-11-02 08:13:21 -030096#include "gspca.h"
Jean-François Moineac399cd2012-02-27 05:40:47 -030097/* Include pac common sof detection functions */
98#include "pac_common.h"
Marton Nemeth1408b842009-11-02 08:13:21 -030099
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300100#define PAC7302_RGB_BALANCE_MIN 0
101#define PAC7302_RGB_BALANCE_MAX 200
102#define PAC7302_RGB_BALANCE_DEFAULT 100
103#define PAC7302_GAIN_DEFAULT 15
104#define PAC7302_GAIN_KNEE 42
105#define PAC7302_EXPOSURE_DEFAULT 66 /* 33 ms / 30 fps */
106#define PAC7302_EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
Hans de Goede74233cd2012-05-14 11:16:09 -0300107
Jean-François Moineae251e62012-02-27 05:15:12 -0300108MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
109 "Thomas Kaiser thomas@kaiser-linux.li");
Marton Nemeth1408b842009-11-02 08:13:21 -0300110MODULE_DESCRIPTION("Pixart PAC7302");
111MODULE_LICENSE("GPL");
112
Marton Nemeth1408b842009-11-02 08:13:21 -0300113struct sd {
114 struct gspca_dev gspca_dev; /* !! must be the first item */
115
Hans de Goede74233cd2012-05-14 11:16:09 -0300116 struct { /* brightness / contrast cluster */
117 struct v4l2_ctrl *brightness;
118 struct v4l2_ctrl *contrast;
119 };
120 struct v4l2_ctrl *saturation;
121 struct v4l2_ctrl *white_balance;
122 struct v4l2_ctrl *red_balance;
123 struct v4l2_ctrl *blue_balance;
124 struct { /* flip cluster */
125 struct v4l2_ctrl *hflip;
126 struct v4l2_ctrl *vflip;
127 };
Frank Schäferb1a19c02012-09-09 15:02:21 -0300128 struct v4l2_ctrl *sharpness;
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -0300129 u8 flags;
130#define FL_HFLIP 0x01 /* mirrored by default */
131#define FL_VFLIP 0x02 /* vertical flipped by default */
Marton Nemeth1408b842009-11-02 08:13:21 -0300132
133 u8 sof_read;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300134 s8 autogain_ignore_frames;
Marton Nemeth1408b842009-11-02 08:13:21 -0300135
136 atomic_t avg_lum;
137};
138
Marton Nemeth1408b842009-11-02 08:13:21 -0300139static const struct v4l2_pix_format vga_mode[] = {
140 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
141 .bytesperline = 640,
142 .sizeimage = 640 * 480 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
Jean-François Moineae251e62012-02-27 05:15:12 -0300144 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300145};
146
147#define LOAD_PAGE3 255
Marton Nemeth1408b842009-11-02 08:13:21 -0300148#define END_OF_SEQUENCE 0
149
Jean-François Moineae251e62012-02-27 05:15:12 -0300150static const u8 init_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300151/* index,value */
152 0xff, 0x01, /* page 1 */
153 0x78, 0x00, /* deactivate */
154 0xff, 0x01,
155 0x78, 0x40, /* led off */
156};
Jean-François Moineae251e62012-02-27 05:15:12 -0300157static const u8 start_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300158/* index, len, [value]* */
159 0xff, 1, 0x00, /* page 0 */
160 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
161 0x00, 0x00, 0x00, 0x00,
162 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
163 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
164 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
165 0x26, 2, 0xaa, 0xaa,
166 0x2e, 1, 0x31,
167 0x38, 1, 0x01,
168 0x3a, 3, 0x14, 0xff, 0x5a,
169 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
170 0x00, 0x54, 0x11,
171 0x55, 1, 0x00,
Jean-François Moineae251e62012-02-27 05:15:12 -0300172 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
Marton Nemeth1408b842009-11-02 08:13:21 -0300173 0x6b, 1, 0x00,
174 0x6e, 3, 0x08, 0x06, 0x00,
175 0x72, 3, 0x00, 0xff, 0x00,
176 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
177 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
178 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
179 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
180 0xd2, 0xeb,
181 0xaf, 1, 0x02,
182 0xb5, 2, 0x08, 0x08,
183 0xb8, 2, 0x08, 0x88,
184 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
185 0xcc, 1, 0x00,
186 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
187 0xc1, 0xd7, 0xec,
188 0xdc, 1, 0x01,
189 0xff, 1, 0x01, /* page 1 */
190 0x12, 3, 0x02, 0x00, 0x01,
191 0x3e, 2, 0x00, 0x00,
192 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
193 0x7c, 1, 0x00,
194 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
195 0x02, 0x00,
196 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
197 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
198 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
199 0xd8, 1, 0x01,
200 0xdb, 2, 0x00, 0x01,
201 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
202 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
203 0xeb, 1, 0x00,
204 0xff, 1, 0x02, /* page 2 */
205 0x22, 1, 0x00,
206 0xff, 1, 0x03, /* page 3 */
207 0, LOAD_PAGE3, /* load the page 3 */
208 0x11, 1, 0x01,
209 0xff, 1, 0x02, /* page 2 */
210 0x13, 1, 0x00,
211 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
212 0x27, 2, 0x14, 0x0c,
213 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
214 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
215 0x6e, 1, 0x08,
216 0xff, 1, 0x01, /* page 1 */
217 0x78, 1, 0x00,
218 0, END_OF_SEQUENCE /* end of sequence */
219};
220
221#define SKIP 0xaa
222/* page 3 - the value SKIP says skip the index - see reg_w_page() */
Jean-François Moineae251e62012-02-27 05:15:12 -0300223static const u8 page3_7302[] = {
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300224 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
Marton Nemeth1408b842009-11-02 08:13:21 -0300225 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
226 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
228 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
229 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
230 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
231 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
Jean-Francois Moinecdf955c2010-01-11 15:06:12 -0300233 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
Marton Nemeth1408b842009-11-02 08:13:21 -0300234 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
238 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
239 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
240 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
243 0x00
244};
245
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300246static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300247 u8 index,
Jean-François Moine0aeb5ec2010-12-28 06:59:04 -0300248 const u8 *buffer, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300249{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300250 int ret;
251
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300252 if (gspca_dev->usb_err < 0)
253 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300254 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300255 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300256 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-François Moinea1317132010-06-24 04:50:26 -0300257 0, /* request */
Marton Nemeth1408b842009-11-02 08:13:21 -0300258 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
259 0, /* value */
260 index, gspca_dev->usb_buf, len,
261 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300262 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300263 pr_err("reg_w_buf failed i: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300264 index, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300265 gspca_dev->usb_err = ret;
266 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300267}
268
269
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300270static void reg_w(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300271 u8 index,
272 u8 value)
Marton Nemeth1408b842009-11-02 08:13:21 -0300273{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300274 int ret;
275
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300276 if (gspca_dev->usb_err < 0)
277 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300278 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300279 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300280 usb_sndctrlpipe(gspca_dev->dev, 0),
281 0, /* request */
282 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
283 0, index, gspca_dev->usb_buf, 1,
284 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300285 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300286 pr_err("reg_w() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300287 index, value, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300288 gspca_dev->usb_err = ret;
289 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300290}
291
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300292static void reg_w_seq(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300293 const u8 *seq, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300294{
295 while (--len >= 0) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300296 reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300297 seq += 2;
298 }
299}
300
301/* load the beginning of a page */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300302static void reg_w_page(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300303 const u8 *page, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300304{
305 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300306 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300307
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300308 if (gspca_dev->usb_err < 0)
309 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300310 for (index = 0; index < len; index++) {
311 if (page[index] == SKIP) /* skip this index */
312 continue;
313 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300314 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300315 usb_sndctrlpipe(gspca_dev->dev, 0),
316 0, /* request */
317 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
318 0, index, gspca_dev->usb_buf, 1,
319 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300320 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300321 pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300322 index, page[index], ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300323 gspca_dev->usb_err = ret;
Márton Némethb1784b32009-11-07 05:52:02 -0300324 break;
325 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300326 }
327}
328
329/* output a variable sequence */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300330static void reg_w_var(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300331 const u8 *seq,
332 const u8 *page3, unsigned int page3_len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300333{
334 int index, len;
335
336 for (;;) {
337 index = *seq++;
338 len = *seq++;
339 switch (len) {
340 case END_OF_SEQUENCE:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300341 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300342 case LOAD_PAGE3:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300343 reg_w_page(gspca_dev, page3, page3_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300344 break;
345 default:
346 if (len > USB_BUF_SZ) {
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300347 PERR("Incorrect variable sequence");
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300348 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300349 }
350 while (len > 0) {
351 if (len < 8) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300352 reg_w_buf(gspca_dev,
Márton Némethb1784b32009-11-07 05:52:02 -0300353 index, seq, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300354 seq += len;
355 break;
356 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300357 reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300358 seq += 8;
359 index += 8;
360 len -= 8;
361 }
362 }
363 }
364 /* not reached */
365}
366
367/* this function is called at probe time for pac7302 */
368static int sd_config(struct gspca_dev *gspca_dev,
369 const struct usb_device_id *id)
370{
371 struct sd *sd = (struct sd *) gspca_dev;
372 struct cam *cam;
373
374 cam = &gspca_dev->cam;
375
Marton Nemeth1408b842009-11-02 08:13:21 -0300376 cam->cam_mode = vga_mode; /* only 640x480 */
377 cam->nmodes = ARRAY_SIZE(vga_mode);
378
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -0300379 sd->flags = id->driver_info;
Marton Nemeth1408b842009-11-02 08:13:21 -0300380 return 0;
381}
382
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300383static void setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300384{
385 struct sd *sd = (struct sd *) gspca_dev;
386 int i, v;
Jean-François Moineae251e62012-02-27 05:15:12 -0300387 static const u8 max[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300388 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
389 0xd4, 0xec};
Jean-François Moineae251e62012-02-27 05:15:12 -0300390 static const u8 delta[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300391 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
392 0x11, 0x0b};
393
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300394 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300395 for (i = 0; i < 10; i++) {
396 v = max[i];
Hans de Goede74233cd2012-05-14 11:16:09 -0300397 v += (sd->brightness->val - sd->brightness->maximum)
398 * 150 / sd->brightness->maximum; /* 200 ? */
399 v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
Marton Nemeth1408b842009-11-02 08:13:21 -0300400 if (v < 0)
401 v = 0;
402 else if (v > 0xff)
403 v = 0xff;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300404 reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300405 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300406 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300407}
408
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300409static void setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300410{
411 struct sd *sd = (struct sd *) gspca_dev;
412 int i, v;
413 static const int a[9] =
414 {217, -212, 0, -101, 170, -67, -38, -315, 355};
415 static const int b[9] =
416 {19, 106, 0, 19, 106, 1, 19, 106, 1};
417
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300418 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
419 reg_w(gspca_dev, 0x11, 0x01);
420 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300421 for (i = 0; i < 9; i++) {
Hans de Goede74233cd2012-05-14 11:16:09 -0300422 v = a[i] * sd->saturation->val / sd->saturation->maximum;
423 v += b[i];
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300424 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
425 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300426 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300427 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300428}
429
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300430static void setwhitebalance(struct gspca_dev *gspca_dev)
Marton Nemeth23fbee62009-11-08 04:35:12 -0300431{
432 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300433
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300434 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Hans de Goede74233cd2012-05-14 11:16:09 -0300435 reg_w(gspca_dev, 0xc6, sd->white_balance->val);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300436
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300437 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300438}
439
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300440static u8 rgbbalance_ctrl_to_reg_value(s32 rgb_ctrl_val)
441{
442 const unsigned int k = 1000; /* precision factor */
443 unsigned int norm;
444
445 /* Normed value [0...k] */
446 norm = k * (rgb_ctrl_val - PAC7302_RGB_BALANCE_MIN)
447 / (PAC7302_RGB_BALANCE_MAX - PAC7302_RGB_BALANCE_MIN);
448 /* Qudratic apporach improves control at small (register) values: */
449 return 64 * norm * norm / (k*k) + 32 * norm / k + 32;
450 /* Y = 64*X*X + 32*X + 32
451 * => register values 0x20-0x80; Windows driver uses these limits */
452
453 /* NOTE: for full value range (0x00-0xff) use
454 * Y = 254*X*X + X
455 * => 254 * norm * norm / (k*k) + 1 * norm / k */
456}
457
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300458static void setredbalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300459{
460 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300461
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300462 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
463 reg_w(gspca_dev, 0x01,
464 rgbbalance_ctrl_to_reg_value(sd->red_balance->val));
Márton Németh265a8092009-11-07 15:15:56 -0300465
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300466 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300467}
468
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300469static void setbluebalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300470{
471 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300472
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300473 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300474 reg_w(gspca_dev, 0x03,
475 rgbbalance_ctrl_to_reg_value(sd->blue_balance->val));
Márton Németh265a8092009-11-07 15:15:56 -0300476
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300477 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300478}
479
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300480static void setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300481{
Hans de Goededf8b9852012-04-28 10:12:28 -0300482 u8 reg10, reg12;
483
Hans de Goede74233cd2012-05-14 11:16:09 -0300484 if (gspca_dev->gain->val < 32) {
485 reg10 = gspca_dev->gain->val;
Hans de Goededf8b9852012-04-28 10:12:28 -0300486 reg12 = 0;
487 } else {
488 reg10 = 31;
Hans de Goede74233cd2012-05-14 11:16:09 -0300489 reg12 = gspca_dev->gain->val - 31;
Hans de Goededf8b9852012-04-28 10:12:28 -0300490 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300491
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300492 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goededf8b9852012-04-28 10:12:28 -0300493 reg_w(gspca_dev, 0x10, reg10);
494 reg_w(gspca_dev, 0x12, reg12);
Marton Nemeth1408b842009-11-02 08:13:21 -0300495
496 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300497 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300498}
499
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300500static void setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300501{
Jean-François Moineae251e62012-02-27 05:15:12 -0300502 u8 clockdiv;
503 u16 exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -0300504
Hans de Goede895d4642012-04-28 10:31:17 -0300505 /*
506 * Register 2 of frame 3 contains the clock divider configuring the
507 * no fps according to the formula: 90 / reg. sd->exposure is the
508 * desired exposure time in 0.5 ms.
509 */
Hans de Goede74233cd2012-05-14 11:16:09 -0300510 clockdiv = (90 * gspca_dev->exposure->val + 1999) / 2000;
Marton Nemeth1408b842009-11-02 08:13:21 -0300511
Hans de Goede895d4642012-04-28 10:31:17 -0300512 /*
513 * Note clockdiv = 3 also works, but when running at 30 fps, depending
514 * on the scene being recorded, the camera switches to another
515 * quantization table for certain JPEG blocks, and we don't know how
516 * to decompress these blocks. So we cap the framerate at 15 fps.
517 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300518 if (clockdiv < 6)
519 clockdiv = 6;
520 else if (clockdiv > 63)
521 clockdiv = 63;
522
Hans de Goede895d4642012-04-28 10:31:17 -0300523 /*
524 * Register 2 MUST be a multiple of 3, except when between 6 and 12?
525 * Always round up, otherwise we cannot get the desired frametime
526 * using the partial frame time exposure control.
527 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300528 if (clockdiv < 6 || clockdiv > 12)
529 clockdiv = ((clockdiv + 2) / 3) * 3;
530
Hans de Goede895d4642012-04-28 10:31:17 -0300531 /*
532 * frame exposure time in ms = 1000 * clockdiv / 90 ->
533 * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90)
534 */
Hans de Goede74233cd2012-05-14 11:16:09 -0300535 exposure = (gspca_dev->exposure->val * 45 * 448) / (1000 * clockdiv);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300536 /* 0 = use full frametime, 448 = no exposure, reverse it */
537 exposure = 448 - exposure;
538
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300539 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300540 reg_w(gspca_dev, 0x02, clockdiv);
541 reg_w(gspca_dev, 0x0e, exposure & 0xff);
542 reg_w(gspca_dev, 0x0f, exposure >> 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300543
544 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300545 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300546}
547
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300548static void sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300549{
550 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -0300551 u8 data, hflip, vflip;
552
Hans de Goede74233cd2012-05-14 11:16:09 -0300553 hflip = sd->hflip->val;
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -0300554 if (sd->flags & FL_HFLIP)
555 hflip = !hflip;
Hans de Goede74233cd2012-05-14 11:16:09 -0300556 vflip = sd->vflip->val;
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -0300557 if (sd->flags & FL_VFLIP)
558 vflip = !vflip;
Marton Nemeth1408b842009-11-02 08:13:21 -0300559
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300560 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -0300561 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300562 reg_w(gspca_dev, 0x21, data);
563
Marton Nemeth1408b842009-11-02 08:13:21 -0300564 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300565 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300566}
567
Frank Schäferb1a19c02012-09-09 15:02:21 -0300568static void setsharpness(struct gspca_dev *gspca_dev)
569{
570 struct sd *sd = (struct sd *) gspca_dev;
571
572 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
573 reg_w(gspca_dev, 0xb6, sd->sharpness->val);
574
575 reg_w(gspca_dev, 0xdc, 0x01);
576}
577
Marton Nemeth1408b842009-11-02 08:13:21 -0300578/* this function is called at probe and resume time for pac7302 */
579static int sd_init(struct gspca_dev *gspca_dev)
580{
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300581 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
582 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300583}
584
Hans de Goede74233cd2012-05-14 11:16:09 -0300585static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
586{
587 struct gspca_dev *gspca_dev =
588 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
589 struct sd *sd = (struct sd *)gspca_dev;
590
591 gspca_dev->usb_err = 0;
592
593 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
594 /* when switching to autogain set defaults to make sure
595 we are on a valid point of the autogain gain /
596 exposure knee graph, and give this change time to
597 take effect before doing autogain. */
598 gspca_dev->exposure->val = PAC7302_EXPOSURE_DEFAULT;
599 gspca_dev->gain->val = PAC7302_GAIN_DEFAULT;
600 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
601 }
602
603 if (!gspca_dev->streaming)
604 return 0;
605
606 switch (ctrl->id) {
607 case V4L2_CID_BRIGHTNESS:
608 setbrightcont(gspca_dev);
609 break;
610 case V4L2_CID_SATURATION:
611 setcolors(gspca_dev);
612 break;
613 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
614 setwhitebalance(gspca_dev);
615 break;
616 case V4L2_CID_RED_BALANCE:
617 setredbalance(gspca_dev);
618 break;
619 case V4L2_CID_BLUE_BALANCE:
620 setbluebalance(gspca_dev);
621 break;
622 case V4L2_CID_AUTOGAIN:
623 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
624 setexposure(gspca_dev);
625 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
626 setgain(gspca_dev);
627 break;
628 case V4L2_CID_HFLIP:
629 sethvflip(gspca_dev);
630 break;
Frank Schäferb1a19c02012-09-09 15:02:21 -0300631 case V4L2_CID_SHARPNESS:
632 setsharpness(gspca_dev);
633 break;
Hans de Goede74233cd2012-05-14 11:16:09 -0300634 default:
635 return -EINVAL;
636 }
637 return gspca_dev->usb_err;
638}
639
640static const struct v4l2_ctrl_ops sd_ctrl_ops = {
641 .s_ctrl = sd_s_ctrl,
642};
643
644/* this function is called at probe time */
645static int sd_init_controls(struct gspca_dev *gspca_dev)
646{
647 struct sd *sd = (struct sd *) gspca_dev;
648 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
649
650 gspca_dev->vdev.ctrl_handler = hdl;
Frank Schäferb1a19c02012-09-09 15:02:21 -0300651 v4l2_ctrl_handler_init(hdl, 12);
Hans de Goede74233cd2012-05-14 11:16:09 -0300652
653 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
654 V4L2_CID_BRIGHTNESS, 0, 32, 1, 16);
655 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
656 V4L2_CID_CONTRAST, 0, 255, 1, 127);
657
658 sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
659 V4L2_CID_SATURATION, 0, 255, 1, 127);
660 sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
661 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
Frank Schäferf58e5cd2012-09-09 15:02:22 -0300662 0, 255, 1, 55);
Hans de Goede74233cd2012-05-14 11:16:09 -0300663 sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300664 V4L2_CID_RED_BALANCE,
665 PAC7302_RGB_BALANCE_MIN,
666 PAC7302_RGB_BALANCE_MAX,
667 1, PAC7302_RGB_BALANCE_DEFAULT);
Hans de Goede74233cd2012-05-14 11:16:09 -0300668 sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300669 V4L2_CID_BLUE_BALANCE,
670 PAC7302_RGB_BALANCE_MIN,
671 PAC7302_RGB_BALANCE_MAX,
672 1, PAC7302_RGB_BALANCE_DEFAULT);
Hans de Goede74233cd2012-05-14 11:16:09 -0300673
674 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
675 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
676 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
677 V4L2_CID_EXPOSURE, 0, 1023, 1,
678 PAC7302_EXPOSURE_DEFAULT);
679 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
680 V4L2_CID_GAIN, 0, 62, 1,
681 PAC7302_GAIN_DEFAULT);
682
683 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
684 V4L2_CID_HFLIP, 0, 1, 1, 0);
685 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
686 V4L2_CID_VFLIP, 0, 1, 1, 0);
687
Frank Schäferb1a19c02012-09-09 15:02:21 -0300688 sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
689 V4L2_CID_SHARPNESS, 0, 15, 1, 8);
690
Hans de Goede74233cd2012-05-14 11:16:09 -0300691 if (hdl->error) {
692 pr_err("Could not initialize controls\n");
693 return hdl->error;
694 }
695
696 v4l2_ctrl_cluster(2, &sd->brightness);
697 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
698 v4l2_ctrl_cluster(2, &sd->hflip);
699 return 0;
700}
701
702/* -- start the camera -- */
Marton Nemeth1408b842009-11-02 08:13:21 -0300703static int sd_start(struct gspca_dev *gspca_dev)
704{
705 struct sd *sd = (struct sd *) gspca_dev;
706
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300707 reg_w_var(gspca_dev, start_7302,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300708 page3_7302, sizeof(page3_7302));
Marton Nemeth1408b842009-11-02 08:13:21 -0300709
Marton Nemeth1408b842009-11-02 08:13:21 -0300710 sd->sof_read = 0;
Hans de Goede74233cd2012-05-14 11:16:09 -0300711 sd->autogain_ignore_frames = 0;
712 atomic_set(&sd->avg_lum, 270 + sd->brightness->val);
Marton Nemeth1408b842009-11-02 08:13:21 -0300713
714 /* start stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300715 reg_w(gspca_dev, 0xff, 0x01);
716 reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300717
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300718 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300719}
720
721static void sd_stopN(struct gspca_dev *gspca_dev)
722{
Márton Némethb1784b32009-11-07 05:52:02 -0300723
Márton Németh67c98f72009-11-07 05:45:33 -0300724 /* stop stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300725 reg_w(gspca_dev, 0xff, 0x01);
726 reg_w(gspca_dev, 0x78, 0x00);
Marton Nemeth1408b842009-11-02 08:13:21 -0300727}
728
729/* called on streamoff with alt 0 and on disconnect for pac7302 */
730static void sd_stop0(struct gspca_dev *gspca_dev)
731{
732 if (!gspca_dev->present)
733 return;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300734 reg_w(gspca_dev, 0xff, 0x01);
735 reg_w(gspca_dev, 0x78, 0x40);
Marton Nemeth1408b842009-11-02 08:13:21 -0300736}
737
Marton Nemeth1408b842009-11-02 08:13:21 -0300738static void do_autogain(struct gspca_dev *gspca_dev)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741 int avg_lum = atomic_read(&sd->avg_lum);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300742 int desired_lum;
743 const int deadzone = 30;
Marton Nemeth1408b842009-11-02 08:13:21 -0300744
Jean-François Moineac399cd2012-02-27 05:40:47 -0300745 if (sd->autogain_ignore_frames < 0)
Marton Nemeth1408b842009-11-02 08:13:21 -0300746 return;
747
Jean-François Moineac399cd2012-02-27 05:40:47 -0300748 if (sd->autogain_ignore_frames > 0) {
Marton Nemeth1408b842009-11-02 08:13:21 -0300749 sd->autogain_ignore_frames--;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300750 } else {
Hans de Goede74233cd2012-05-14 11:16:09 -0300751 desired_lum = 270 + sd->brightness->val;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300752
Hans de Goede74233cd2012-05-14 11:16:09 -0300753 if (gspca_expo_autogain(gspca_dev, avg_lum, desired_lum,
754 deadzone, PAC7302_GAIN_KNEE,
755 PAC7302_EXPOSURE_KNEE))
756 sd->autogain_ignore_frames =
757 PAC_AUTOGAIN_IGNORE_FRAMES;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300758 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300759}
760
Jean-François Moine7532e812012-02-27 05:21:57 -0300761/* JPEG header */
762static const u8 jpeg_header[] = {
763 0xff, 0xd8, /* SOI: Start of Image */
Marton Nemeth1408b842009-11-02 08:13:21 -0300764
Jean-François Moine7532e812012-02-27 05:21:57 -0300765 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
766 0x00, 0x11, /* length = 17 bytes (including this length field) */
767 0x08, /* Precision: 8 */
768 0x02, 0x80, /* height = 640 (image rotated) */
769 0x01, 0xe0, /* width = 480 */
770 0x03, /* Number of image components: 3 */
771 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
772 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
773 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
774
775 0xff, 0xda, /* SOS: Start Of Scan */
776 0x00, 0x0c, /* length = 12 bytes (including this length field) */
777 0x03, /* number of components: 3 */
778 0x01, 0x00, /* selector 1, table 0x00 */
779 0x02, 0x11, /* selector 2, table 0x11 */
780 0x03, 0x11, /* selector 3, table 0x11 */
781 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
782 0x00 /* Successive approximation: 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300783};
784
Marton Nemeth1408b842009-11-02 08:13:21 -0300785/* this function is run at interrupt level */
786static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300787 u8 *data, /* isoc packet */
Marton Nemeth1408b842009-11-02 08:13:21 -0300788 int len) /* iso packet length */
789{
790 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300791 u8 *image;
Jean-François Moineae251e62012-02-27 05:15:12 -0300792 u8 *sof;
Marton Nemeth1408b842009-11-02 08:13:21 -0300793
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300794 sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300795 if (sof) {
796 int n, lum_offset, footer_length;
797
Hans de Goede895d4642012-04-28 10:31:17 -0300798 /*
799 * 6 bytes after the FF D9 EOF marker a number of lumination
800 * bytes are send corresponding to different parts of the
801 * image, the 14th and 15th byte after the EOF seem to
802 * correspond to the center of the image.
803 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300804 lum_offset = 61 + sizeof pac_sof_marker;
805 footer_length = 74;
806
807 /* Finish decoding current frame */
808 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
809 if (n < 0) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300810 gspca_dev->image_len += n;
Marton Nemeth1408b842009-11-02 08:13:21 -0300811 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300812 } else {
813 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Marton Nemeth1408b842009-11-02 08:13:21 -0300814 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300815
816 image = gspca_dev->image;
817 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300818 && image[gspca_dev->image_len - 2] == 0xff
819 && image[gspca_dev->image_len - 1] == 0xd9)
820 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Marton Nemeth1408b842009-11-02 08:13:21 -0300821
822 n = sof - data;
823 len -= n;
824 data = sof;
825
826 /* Get average lumination */
827 if (gspca_dev->last_packet_type == LAST_PACKET &&
828 n >= lum_offset)
829 atomic_set(&sd->avg_lum, data[-lum_offset] +
830 data[-lum_offset + 1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300831
832 /* Start the new frame with the jpeg header */
833 /* The PAC7302 has the image rotated 90 degrees */
Jean-François Moine7532e812012-02-27 05:21:57 -0300834 gspca_frame_add(gspca_dev, FIRST_PACKET,
835 jpeg_header, sizeof jpeg_header);
Marton Nemeth1408b842009-11-02 08:13:21 -0300836 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300837 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300838}
839
Márton Németh6763cc02009-11-09 07:10:46 -0300840#ifdef CONFIG_VIDEO_ADV_DEBUG
841static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
Hans Verkuil977ba3b2013-03-24 08:28:46 -0300842 const struct v4l2_dbg_register *reg)
Márton Németh6763cc02009-11-09 07:10:46 -0300843{
Jean-François Moineae251e62012-02-27 05:15:12 -0300844 u8 index;
845 u8 value;
Márton Németh6763cc02009-11-09 07:10:46 -0300846
Hans de Goede895d4642012-04-28 10:31:17 -0300847 /*
848 * reg->reg: bit0..15: reserved for register index (wIndex is 16bit
849 * long on the USB bus)
850 */
Hans Verkuilb1c85cc2013-05-29 06:59:42 -0300851 if (reg->match.addr == 0 &&
Márton Németh6763cc02009-11-09 07:10:46 -0300852 (reg->reg < 0x000000ff) &&
853 (reg->val <= 0x000000ff)
854 ) {
855 /* Currently writing to page 0 is only supported. */
856 /* reg_w() only supports 8bit index */
Jean-François Moineae251e62012-02-27 05:15:12 -0300857 index = reg->reg;
858 value = reg->val;
Márton Németh6763cc02009-11-09 07:10:46 -0300859
Hans de Goede895d4642012-04-28 10:31:17 -0300860 /*
861 * Note that there shall be no access to other page
862 * by any other function between the page switch and
863 * the actual register write.
864 */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300865 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
866 reg_w(gspca_dev, index, value);
Márton Németh6763cc02009-11-09 07:10:46 -0300867
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300868 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh6763cc02009-11-09 07:10:46 -0300869 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300870 return gspca_dev->usb_err;
Márton Németh6763cc02009-11-09 07:10:46 -0300871}
Márton Németh6763cc02009-11-09 07:10:46 -0300872#endif
873
Peter Senna Tschudinae814c02013-01-24 19:29:03 -0300874#if IS_ENABLED(CONFIG_INPUT)
Márton Némethaed6f1b2010-01-28 16:33:38 -0300875static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
876 u8 *data, /* interrupt packet data */
877 int len) /* interrput packet length */
878{
879 int ret = -EINVAL;
880 u8 data0, data1;
881
882 if (len == 2) {
883 data0 = data[0];
884 data1 = data[1];
885 if ((data0 == 0x00 && data1 == 0x11) ||
886 (data0 == 0x22 && data1 == 0x33) ||
887 (data0 == 0x44 && data1 == 0x55) ||
888 (data0 == 0x66 && data1 == 0x77) ||
889 (data0 == 0x88 && data1 == 0x99) ||
890 (data0 == 0xaa && data1 == 0xbb) ||
891 (data0 == 0xcc && data1 == 0xdd) ||
892 (data0 == 0xee && data1 == 0xff)) {
893 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
894 input_sync(gspca_dev->input_dev);
895 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
896 input_sync(gspca_dev->input_dev);
897 ret = 0;
898 }
899 }
900
901 return ret;
902}
903#endif
904
Marton Nemeth1408b842009-11-02 08:13:21 -0300905/* sub-driver description for pac7302 */
Márton Némethaabcdfb2010-01-05 12:39:02 -0300906static const struct sd_desc sd_desc = {
Jean-François Moineae251e62012-02-27 05:15:12 -0300907 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -0300908 .config = sd_config,
909 .init = sd_init,
Hans de Goede74233cd2012-05-14 11:16:09 -0300910 .init_controls = sd_init_controls,
Marton Nemeth1408b842009-11-02 08:13:21 -0300911 .start = sd_start,
912 .stopN = sd_stopN,
913 .stop0 = sd_stop0,
914 .pkt_scan = sd_pkt_scan,
915 .dq_callback = do_autogain,
Márton Németh6763cc02009-11-09 07:10:46 -0300916#ifdef CONFIG_VIDEO_ADV_DEBUG
917 .set_register = sd_dbg_s_register,
Márton Németh6763cc02009-11-09 07:10:46 -0300918#endif
Peter Senna Tschudinae814c02013-01-24 19:29:03 -0300919#if IS_ENABLED(CONFIG_INPUT)
Márton Némethaed6f1b2010-01-28 16:33:38 -0300920 .int_pkt_scan = sd_int_pkt_scan,
921#endif
Marton Nemeth1408b842009-11-02 08:13:21 -0300922};
923
924/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300925static const struct usb_device_id device_table[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300926 {USB_DEVICE(0x06f8, 0x3009)},
Jean-François Moinedd32f982012-02-27 04:58:59 -0300927 {USB_DEVICE(0x06f8, 0x301b)},
Marton Nemeth1408b842009-11-02 08:13:21 -0300928 {USB_DEVICE(0x093a, 0x2620)},
929 {USB_DEVICE(0x093a, 0x2621)},
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -0300930 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
931 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
Márton Németh4e6aeef2010-06-14 17:21:37 -0300932 {USB_DEVICE(0x093a, 0x2625)},
Marton Nemeth1408b842009-11-02 08:13:21 -0300933 {USB_DEVICE(0x093a, 0x2626)},
Jozsef Marton5b843252012-05-15 12:05:36 -0300934 {USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -0300935 {USB_DEVICE(0x093a, 0x2628)},
Jean-Francois Moinec4322bf2009-12-02 07:04:35 -0300936 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -0300937 {USB_DEVICE(0x093a, 0x262a)},
938 {USB_DEVICE(0x093a, 0x262c)},
Hans de Goede4d6454d2011-12-30 19:15:53 -0300939 {USB_DEVICE(0x145f, 0x013c)},
Frank Schäfer97d2fbf2012-09-09 15:02:19 -0300940 {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */
Marton Nemeth1408b842009-11-02 08:13:21 -0300941 {}
942};
943MODULE_DEVICE_TABLE(usb, device_table);
944
945/* -- device connect -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300946static int sd_probe(struct usb_interface *intf,
Marton Nemeth1408b842009-11-02 08:13:21 -0300947 const struct usb_device_id *id)
948{
949 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
950 THIS_MODULE);
951}
952
953static struct usb_driver sd_driver = {
Jean-François Moineae251e62012-02-27 05:15:12 -0300954 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -0300955 .id_table = device_table,
956 .probe = sd_probe,
957 .disconnect = gspca_disconnect,
958#ifdef CONFIG_PM
959 .suspend = gspca_suspend,
960 .resume = gspca_resume,
Hans de Goede8bb58962012-06-30 06:44:47 -0300961 .reset_resume = gspca_resume,
Marton Nemeth1408b842009-11-02 08:13:21 -0300962#endif
963};
964
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800965module_usb_driver(sd_driver);