blob: 20d9c15a305d5ca972f4e834b6547e80aefec579 [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>
Márton Németh6763cc02009-11-09 07:10:46 -030096#include <media/v4l2-chip-ident.h>
Marton Nemeth1408b842009-11-02 08:13:21 -030097#include "gspca.h"
Jean-François Moineac399cd2012-02-27 05:40:47 -030098/* Include pac common sof detection functions */
99#include "pac_common.h"
Marton Nemeth1408b842009-11-02 08:13:21 -0300100
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300101#define PAC7302_RGB_BALANCE_MIN 0
102#define PAC7302_RGB_BALANCE_MAX 200
103#define PAC7302_RGB_BALANCE_DEFAULT 100
104#define PAC7302_GAIN_DEFAULT 15
105#define PAC7302_GAIN_KNEE 42
106#define PAC7302_EXPOSURE_DEFAULT 66 /* 33 ms / 30 fps */
107#define PAC7302_EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
Hans de Goede74233cd2012-05-14 11:16:09 -0300108
Jean-François Moineae251e62012-02-27 05:15:12 -0300109MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
110 "Thomas Kaiser thomas@kaiser-linux.li");
Marton Nemeth1408b842009-11-02 08:13:21 -0300111MODULE_DESCRIPTION("Pixart PAC7302");
112MODULE_LICENSE("GPL");
113
Marton Nemeth1408b842009-11-02 08:13:21 -0300114struct sd {
115 struct gspca_dev gspca_dev; /* !! must be the first item */
116
Hans de Goede74233cd2012-05-14 11:16:09 -0300117 struct { /* brightness / contrast cluster */
118 struct v4l2_ctrl *brightness;
119 struct v4l2_ctrl *contrast;
120 };
121 struct v4l2_ctrl *saturation;
122 struct v4l2_ctrl *white_balance;
123 struct v4l2_ctrl *red_balance;
124 struct v4l2_ctrl *blue_balance;
125 struct { /* flip cluster */
126 struct v4l2_ctrl *hflip;
127 struct v4l2_ctrl *vflip;
128 };
Frank Schäferb1a19c02012-09-09 15:02:21 -0300129 struct v4l2_ctrl *sharpness;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300130 u8 flags;
131#define FL_HFLIP 0x01 /* mirrored by default */
132#define FL_VFLIP 0x02 /* vertical flipped by default */
Marton Nemeth1408b842009-11-02 08:13:21 -0300133
134 u8 sof_read;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300135 s8 autogain_ignore_frames;
Marton Nemeth1408b842009-11-02 08:13:21 -0300136
137 atomic_t avg_lum;
138};
139
Marton Nemeth1408b842009-11-02 08:13:21 -0300140static const struct v4l2_pix_format vga_mode[] = {
141 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
142 .bytesperline = 640,
143 .sizeimage = 640 * 480 * 3 / 8 + 590,
144 .colorspace = V4L2_COLORSPACE_JPEG,
Jean-François Moineae251e62012-02-27 05:15:12 -0300145 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300146};
147
148#define LOAD_PAGE3 255
Marton Nemeth1408b842009-11-02 08:13:21 -0300149#define END_OF_SEQUENCE 0
150
Jean-François Moineae251e62012-02-27 05:15:12 -0300151static const u8 init_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300152/* index,value */
153 0xff, 0x01, /* page 1 */
154 0x78, 0x00, /* deactivate */
155 0xff, 0x01,
156 0x78, 0x40, /* led off */
157};
Jean-François Moineae251e62012-02-27 05:15:12 -0300158static const u8 start_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300159/* index, len, [value]* */
160 0xff, 1, 0x00, /* page 0 */
161 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
162 0x00, 0x00, 0x00, 0x00,
163 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
164 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
165 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
166 0x26, 2, 0xaa, 0xaa,
167 0x2e, 1, 0x31,
168 0x38, 1, 0x01,
169 0x3a, 3, 0x14, 0xff, 0x5a,
170 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
171 0x00, 0x54, 0x11,
172 0x55, 1, 0x00,
Jean-François Moineae251e62012-02-27 05:15:12 -0300173 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
Marton Nemeth1408b842009-11-02 08:13:21 -0300174 0x6b, 1, 0x00,
175 0x6e, 3, 0x08, 0x06, 0x00,
176 0x72, 3, 0x00, 0xff, 0x00,
177 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
178 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
179 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
180 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
181 0xd2, 0xeb,
182 0xaf, 1, 0x02,
183 0xb5, 2, 0x08, 0x08,
184 0xb8, 2, 0x08, 0x88,
185 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
186 0xcc, 1, 0x00,
187 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
188 0xc1, 0xd7, 0xec,
189 0xdc, 1, 0x01,
190 0xff, 1, 0x01, /* page 1 */
191 0x12, 3, 0x02, 0x00, 0x01,
192 0x3e, 2, 0x00, 0x00,
193 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
194 0x7c, 1, 0x00,
195 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
196 0x02, 0x00,
197 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
198 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
199 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
200 0xd8, 1, 0x01,
201 0xdb, 2, 0x00, 0x01,
202 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
203 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
204 0xeb, 1, 0x00,
205 0xff, 1, 0x02, /* page 2 */
206 0x22, 1, 0x00,
207 0xff, 1, 0x03, /* page 3 */
208 0, LOAD_PAGE3, /* load the page 3 */
209 0x11, 1, 0x01,
210 0xff, 1, 0x02, /* page 2 */
211 0x13, 1, 0x00,
212 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
213 0x27, 2, 0x14, 0x0c,
214 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
215 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
216 0x6e, 1, 0x08,
217 0xff, 1, 0x01, /* page 1 */
218 0x78, 1, 0x00,
219 0, END_OF_SEQUENCE /* end of sequence */
220};
221
222#define SKIP 0xaa
223/* page 3 - the value SKIP says skip the index - see reg_w_page() */
Jean-François Moineae251e62012-02-27 05:15:12 -0300224static const u8 page3_7302[] = {
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300225 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
Marton Nemeth1408b842009-11-02 08:13:21 -0300226 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
227 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
229 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
230 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
231 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
232 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
Jean-Francois Moinecdf955c2010-01-11 15:06:12 -0300234 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
Marton Nemeth1408b842009-11-02 08:13:21 -0300235 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
239 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
240 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
241 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
244 0x00
245};
246
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300247static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300248 u8 index,
Jean-François Moine0aeb5ec2010-12-28 06:59:04 -0300249 const u8 *buffer, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300250{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300251 int ret;
252
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300253 if (gspca_dev->usb_err < 0)
254 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300255 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300256 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300257 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-François Moinea1317132010-06-24 04:50:26 -0300258 0, /* request */
Marton Nemeth1408b842009-11-02 08:13:21 -0300259 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
260 0, /* value */
261 index, gspca_dev->usb_buf, len,
262 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300263 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300264 pr_err("reg_w_buf failed i: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300265 index, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300266 gspca_dev->usb_err = ret;
267 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300268}
269
270
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300271static void reg_w(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300272 u8 index,
273 u8 value)
Marton Nemeth1408b842009-11-02 08:13:21 -0300274{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300275 int ret;
276
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300277 if (gspca_dev->usb_err < 0)
278 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300279 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300280 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300281 usb_sndctrlpipe(gspca_dev->dev, 0),
282 0, /* request */
283 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
284 0, index, gspca_dev->usb_buf, 1,
285 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300286 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300287 pr_err("reg_w() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300288 index, value, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300289 gspca_dev->usb_err = ret;
290 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300291}
292
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300293static void reg_w_seq(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300294 const u8 *seq, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300295{
296 while (--len >= 0) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300297 reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300298 seq += 2;
299 }
300}
301
302/* load the beginning of a page */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300303static void reg_w_page(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300304 const u8 *page, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300305{
306 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300307 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300308
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300309 if (gspca_dev->usb_err < 0)
310 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300311 for (index = 0; index < len; index++) {
312 if (page[index] == SKIP) /* skip this index */
313 continue;
314 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300315 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300316 usb_sndctrlpipe(gspca_dev->dev, 0),
317 0, /* request */
318 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
319 0, index, gspca_dev->usb_buf, 1,
320 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300321 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300322 pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300323 index, page[index], ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300324 gspca_dev->usb_err = ret;
Márton Némethb1784b32009-11-07 05:52:02 -0300325 break;
326 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300327 }
328}
329
330/* output a variable sequence */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300331static void reg_w_var(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300332 const u8 *seq,
333 const u8 *page3, unsigned int page3_len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300334{
335 int index, len;
336
337 for (;;) {
338 index = *seq++;
339 len = *seq++;
340 switch (len) {
341 case END_OF_SEQUENCE:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300342 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300343 case LOAD_PAGE3:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300344 reg_w_page(gspca_dev, page3, page3_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300345 break;
346 default:
347 if (len > USB_BUF_SZ) {
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300348 PERR("Incorrect variable sequence");
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300349 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300350 }
351 while (len > 0) {
352 if (len < 8) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300353 reg_w_buf(gspca_dev,
Márton Némethb1784b32009-11-07 05:52:02 -0300354 index, seq, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300355 seq += len;
356 break;
357 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300358 reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300359 seq += 8;
360 index += 8;
361 len -= 8;
362 }
363 }
364 }
365 /* not reached */
366}
367
368/* this function is called at probe time for pac7302 */
369static int sd_config(struct gspca_dev *gspca_dev,
370 const struct usb_device_id *id)
371{
372 struct sd *sd = (struct sd *) gspca_dev;
373 struct cam *cam;
374
375 cam = &gspca_dev->cam;
376
Marton Nemeth1408b842009-11-02 08:13:21 -0300377 cam->cam_mode = vga_mode; /* only 640x480 */
378 cam->nmodes = ARRAY_SIZE(vga_mode);
379
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300380 sd->flags = id->driver_info;
Marton Nemeth1408b842009-11-02 08:13:21 -0300381 return 0;
382}
383
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300384static void setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300385{
386 struct sd *sd = (struct sd *) gspca_dev;
387 int i, v;
Jean-François Moineae251e62012-02-27 05:15:12 -0300388 static const u8 max[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300389 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
390 0xd4, 0xec};
Jean-François Moineae251e62012-02-27 05:15:12 -0300391 static const u8 delta[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300392 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
393 0x11, 0x0b};
394
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300395 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300396 for (i = 0; i < 10; i++) {
397 v = max[i];
Hans de Goede74233cd2012-05-14 11:16:09 -0300398 v += (sd->brightness->val - sd->brightness->maximum)
399 * 150 / sd->brightness->maximum; /* 200 ? */
400 v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
Marton Nemeth1408b842009-11-02 08:13:21 -0300401 if (v < 0)
402 v = 0;
403 else if (v > 0xff)
404 v = 0xff;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300405 reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300406 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300407 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300408}
409
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300410static void setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300411{
412 struct sd *sd = (struct sd *) gspca_dev;
413 int i, v;
414 static const int a[9] =
415 {217, -212, 0, -101, 170, -67, -38, -315, 355};
416 static const int b[9] =
417 {19, 106, 0, 19, 106, 1, 19, 106, 1};
418
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300419 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
420 reg_w(gspca_dev, 0x11, 0x01);
421 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300422 for (i = 0; i < 9; i++) {
Hans de Goede74233cd2012-05-14 11:16:09 -0300423 v = a[i] * sd->saturation->val / sd->saturation->maximum;
424 v += b[i];
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300425 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
426 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300427 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300428 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300429}
430
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300431static void setwhitebalance(struct gspca_dev *gspca_dev)
Marton Nemeth23fbee62009-11-08 04:35:12 -0300432{
433 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300434
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300435 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Hans de Goede74233cd2012-05-14 11:16:09 -0300436 reg_w(gspca_dev, 0xc6, sd->white_balance->val);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300437
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300438 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300439}
440
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300441static u8 rgbbalance_ctrl_to_reg_value(s32 rgb_ctrl_val)
442{
443 const unsigned int k = 1000; /* precision factor */
444 unsigned int norm;
445
446 /* Normed value [0...k] */
447 norm = k * (rgb_ctrl_val - PAC7302_RGB_BALANCE_MIN)
448 / (PAC7302_RGB_BALANCE_MAX - PAC7302_RGB_BALANCE_MIN);
449 /* Qudratic apporach improves control at small (register) values: */
450 return 64 * norm * norm / (k*k) + 32 * norm / k + 32;
451 /* Y = 64*X*X + 32*X + 32
452 * => register values 0x20-0x80; Windows driver uses these limits */
453
454 /* NOTE: for full value range (0x00-0xff) use
455 * Y = 254*X*X + X
456 * => 254 * norm * norm / (k*k) + 1 * norm / k */
457}
458
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300459static void setredbalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300460{
461 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300462
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300463 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
464 reg_w(gspca_dev, 0x01,
465 rgbbalance_ctrl_to_reg_value(sd->red_balance->val));
Márton Németh265a8092009-11-07 15:15:56 -0300466
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300467 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300468}
469
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300470static void setbluebalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300471{
472 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300473
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300474 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300475 reg_w(gspca_dev, 0x03,
476 rgbbalance_ctrl_to_reg_value(sd->blue_balance->val));
Márton Németh265a8092009-11-07 15:15:56 -0300477
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300478 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300479}
480
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300481static void setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300482{
Hans de Goededf8b9852012-04-28 10:12:28 -0300483 u8 reg10, reg12;
484
Hans de Goede74233cd2012-05-14 11:16:09 -0300485 if (gspca_dev->gain->val < 32) {
486 reg10 = gspca_dev->gain->val;
Hans de Goededf8b9852012-04-28 10:12:28 -0300487 reg12 = 0;
488 } else {
489 reg10 = 31;
Hans de Goede74233cd2012-05-14 11:16:09 -0300490 reg12 = gspca_dev->gain->val - 31;
Hans de Goededf8b9852012-04-28 10:12:28 -0300491 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300492
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300493 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goededf8b9852012-04-28 10:12:28 -0300494 reg_w(gspca_dev, 0x10, reg10);
495 reg_w(gspca_dev, 0x12, reg12);
Marton Nemeth1408b842009-11-02 08:13:21 -0300496
497 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300498 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300499}
500
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300501static void setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300502{
Jean-François Moineae251e62012-02-27 05:15:12 -0300503 u8 clockdiv;
504 u16 exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -0300505
Hans de Goede895d4642012-04-28 10:31:17 -0300506 /*
507 * Register 2 of frame 3 contains the clock divider configuring the
508 * no fps according to the formula: 90 / reg. sd->exposure is the
509 * desired exposure time in 0.5 ms.
510 */
Hans de Goede74233cd2012-05-14 11:16:09 -0300511 clockdiv = (90 * gspca_dev->exposure->val + 1999) / 2000;
Marton Nemeth1408b842009-11-02 08:13:21 -0300512
Hans de Goede895d4642012-04-28 10:31:17 -0300513 /*
514 * Note clockdiv = 3 also works, but when running at 30 fps, depending
515 * on the scene being recorded, the camera switches to another
516 * quantization table for certain JPEG blocks, and we don't know how
517 * to decompress these blocks. So we cap the framerate at 15 fps.
518 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300519 if (clockdiv < 6)
520 clockdiv = 6;
521 else if (clockdiv > 63)
522 clockdiv = 63;
523
Hans de Goede895d4642012-04-28 10:31:17 -0300524 /*
525 * Register 2 MUST be a multiple of 3, except when between 6 and 12?
526 * Always round up, otherwise we cannot get the desired frametime
527 * using the partial frame time exposure control.
528 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300529 if (clockdiv < 6 || clockdiv > 12)
530 clockdiv = ((clockdiv + 2) / 3) * 3;
531
Hans de Goede895d4642012-04-28 10:31:17 -0300532 /*
533 * frame exposure time in ms = 1000 * clockdiv / 90 ->
534 * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90)
535 */
Hans de Goede74233cd2012-05-14 11:16:09 -0300536 exposure = (gspca_dev->exposure->val * 45 * 448) / (1000 * clockdiv);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300537 /* 0 = use full frametime, 448 = no exposure, reverse it */
538 exposure = 448 - exposure;
539
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300540 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300541 reg_w(gspca_dev, 0x02, clockdiv);
542 reg_w(gspca_dev, 0x0e, exposure & 0xff);
543 reg_w(gspca_dev, 0x0f, exposure >> 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300544
545 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300546 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300547}
548
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300549static void sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300550{
551 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300552 u8 data, hflip, vflip;
553
Hans de Goede74233cd2012-05-14 11:16:09 -0300554 hflip = sd->hflip->val;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300555 if (sd->flags & FL_HFLIP)
556 hflip = !hflip;
Hans de Goede74233cd2012-05-14 11:16:09 -0300557 vflip = sd->vflip->val;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300558 if (sd->flags & FL_VFLIP)
559 vflip = !vflip;
Marton Nemeth1408b842009-11-02 08:13:21 -0300560
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300561 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300562 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300563 reg_w(gspca_dev, 0x21, data);
564
Marton Nemeth1408b842009-11-02 08:13:21 -0300565 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300566 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300567}
568
Frank Schäferb1a19c02012-09-09 15:02:21 -0300569static void setsharpness(struct gspca_dev *gspca_dev)
570{
571 struct sd *sd = (struct sd *) gspca_dev;
572
573 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
574 reg_w(gspca_dev, 0xb6, sd->sharpness->val);
575
576 reg_w(gspca_dev, 0xdc, 0x01);
577}
578
Marton Nemeth1408b842009-11-02 08:13:21 -0300579/* this function is called at probe and resume time for pac7302 */
580static int sd_init(struct gspca_dev *gspca_dev)
581{
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300582 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
583 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300584}
585
Hans de Goede74233cd2012-05-14 11:16:09 -0300586static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
587{
588 struct gspca_dev *gspca_dev =
589 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
590 struct sd *sd = (struct sd *)gspca_dev;
591
592 gspca_dev->usb_err = 0;
593
594 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
595 /* when switching to autogain set defaults to make sure
596 we are on a valid point of the autogain gain /
597 exposure knee graph, and give this change time to
598 take effect before doing autogain. */
599 gspca_dev->exposure->val = PAC7302_EXPOSURE_DEFAULT;
600 gspca_dev->gain->val = PAC7302_GAIN_DEFAULT;
601 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
602 }
603
604 if (!gspca_dev->streaming)
605 return 0;
606
607 switch (ctrl->id) {
608 case V4L2_CID_BRIGHTNESS:
609 setbrightcont(gspca_dev);
610 break;
611 case V4L2_CID_SATURATION:
612 setcolors(gspca_dev);
613 break;
614 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
615 setwhitebalance(gspca_dev);
616 break;
617 case V4L2_CID_RED_BALANCE:
618 setredbalance(gspca_dev);
619 break;
620 case V4L2_CID_BLUE_BALANCE:
621 setbluebalance(gspca_dev);
622 break;
623 case V4L2_CID_AUTOGAIN:
624 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
625 setexposure(gspca_dev);
626 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
627 setgain(gspca_dev);
628 break;
629 case V4L2_CID_HFLIP:
630 sethvflip(gspca_dev);
631 break;
Frank Schäferb1a19c02012-09-09 15:02:21 -0300632 case V4L2_CID_SHARPNESS:
633 setsharpness(gspca_dev);
634 break;
Hans de Goede74233cd2012-05-14 11:16:09 -0300635 default:
636 return -EINVAL;
637 }
638 return gspca_dev->usb_err;
639}
640
641static const struct v4l2_ctrl_ops sd_ctrl_ops = {
642 .s_ctrl = sd_s_ctrl,
643};
644
645/* this function is called at probe time */
646static int sd_init_controls(struct gspca_dev *gspca_dev)
647{
648 struct sd *sd = (struct sd *) gspca_dev;
649 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
650
651 gspca_dev->vdev.ctrl_handler = hdl;
Frank Schäferb1a19c02012-09-09 15:02:21 -0300652 v4l2_ctrl_handler_init(hdl, 12);
Hans de Goede74233cd2012-05-14 11:16:09 -0300653
654 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
655 V4L2_CID_BRIGHTNESS, 0, 32, 1, 16);
656 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
657 V4L2_CID_CONTRAST, 0, 255, 1, 127);
658
659 sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
660 V4L2_CID_SATURATION, 0, 255, 1, 127);
661 sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
662 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
Frank Schäferf58e5cd2012-09-09 15:02:22 -0300663 0, 255, 1, 55);
Hans de Goede74233cd2012-05-14 11:16:09 -0300664 sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300665 V4L2_CID_RED_BALANCE,
666 PAC7302_RGB_BALANCE_MIN,
667 PAC7302_RGB_BALANCE_MAX,
668 1, PAC7302_RGB_BALANCE_DEFAULT);
Hans de Goede74233cd2012-05-14 11:16:09 -0300669 sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
Frank Schäfer2b34e9d2012-09-23 10:29:43 -0300670 V4L2_CID_BLUE_BALANCE,
671 PAC7302_RGB_BALANCE_MIN,
672 PAC7302_RGB_BALANCE_MAX,
673 1, PAC7302_RGB_BALANCE_DEFAULT);
Hans de Goede74233cd2012-05-14 11:16:09 -0300674
675 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
676 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
677 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
678 V4L2_CID_EXPOSURE, 0, 1023, 1,
679 PAC7302_EXPOSURE_DEFAULT);
680 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
681 V4L2_CID_GAIN, 0, 62, 1,
682 PAC7302_GAIN_DEFAULT);
683
684 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
685 V4L2_CID_HFLIP, 0, 1, 1, 0);
686 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
687 V4L2_CID_VFLIP, 0, 1, 1, 0);
688
Frank Schäferb1a19c02012-09-09 15:02:21 -0300689 sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
690 V4L2_CID_SHARPNESS, 0, 15, 1, 8);
691
Hans de Goede74233cd2012-05-14 11:16:09 -0300692 if (hdl->error) {
693 pr_err("Could not initialize controls\n");
694 return hdl->error;
695 }
696
697 v4l2_ctrl_cluster(2, &sd->brightness);
698 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
699 v4l2_ctrl_cluster(2, &sd->hflip);
700 return 0;
701}
702
703/* -- start the camera -- */
Marton Nemeth1408b842009-11-02 08:13:21 -0300704static int sd_start(struct gspca_dev *gspca_dev)
705{
706 struct sd *sd = (struct sd *) gspca_dev;
707
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300708 reg_w_var(gspca_dev, start_7302,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300709 page3_7302, sizeof(page3_7302));
Marton Nemeth1408b842009-11-02 08:13:21 -0300710
Marton Nemeth1408b842009-11-02 08:13:21 -0300711 sd->sof_read = 0;
Hans de Goede74233cd2012-05-14 11:16:09 -0300712 sd->autogain_ignore_frames = 0;
713 atomic_set(&sd->avg_lum, 270 + sd->brightness->val);
Marton Nemeth1408b842009-11-02 08:13:21 -0300714
715 /* start stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300716 reg_w(gspca_dev, 0xff, 0x01);
717 reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300718
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300719 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300720}
721
722static void sd_stopN(struct gspca_dev *gspca_dev)
723{
Márton Némethb1784b32009-11-07 05:52:02 -0300724
Márton Németh67c98f72009-11-07 05:45:33 -0300725 /* stop stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300726 reg_w(gspca_dev, 0xff, 0x01);
727 reg_w(gspca_dev, 0x78, 0x00);
Marton Nemeth1408b842009-11-02 08:13:21 -0300728}
729
730/* called on streamoff with alt 0 and on disconnect for pac7302 */
731static void sd_stop0(struct gspca_dev *gspca_dev)
732{
733 if (!gspca_dev->present)
734 return;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300735 reg_w(gspca_dev, 0xff, 0x01);
736 reg_w(gspca_dev, 0x78, 0x40);
Marton Nemeth1408b842009-11-02 08:13:21 -0300737}
738
Marton Nemeth1408b842009-11-02 08:13:21 -0300739static void do_autogain(struct gspca_dev *gspca_dev)
740{
741 struct sd *sd = (struct sd *) gspca_dev;
742 int avg_lum = atomic_read(&sd->avg_lum);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300743 int desired_lum;
744 const int deadzone = 30;
Marton Nemeth1408b842009-11-02 08:13:21 -0300745
Jean-François Moineac399cd2012-02-27 05:40:47 -0300746 if (sd->autogain_ignore_frames < 0)
Marton Nemeth1408b842009-11-02 08:13:21 -0300747 return;
748
Jean-François Moineac399cd2012-02-27 05:40:47 -0300749 if (sd->autogain_ignore_frames > 0) {
Marton Nemeth1408b842009-11-02 08:13:21 -0300750 sd->autogain_ignore_frames--;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300751 } else {
Hans de Goede74233cd2012-05-14 11:16:09 -0300752 desired_lum = 270 + sd->brightness->val;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300753
Hans de Goede74233cd2012-05-14 11:16:09 -0300754 if (gspca_expo_autogain(gspca_dev, avg_lum, desired_lum,
755 deadzone, PAC7302_GAIN_KNEE,
756 PAC7302_EXPOSURE_KNEE))
757 sd->autogain_ignore_frames =
758 PAC_AUTOGAIN_IGNORE_FRAMES;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300759 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300760}
761
Jean-François Moine7532e812012-02-27 05:21:57 -0300762/* JPEG header */
763static const u8 jpeg_header[] = {
764 0xff, 0xd8, /* SOI: Start of Image */
Marton Nemeth1408b842009-11-02 08:13:21 -0300765
Jean-François Moine7532e812012-02-27 05:21:57 -0300766 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
767 0x00, 0x11, /* length = 17 bytes (including this length field) */
768 0x08, /* Precision: 8 */
769 0x02, 0x80, /* height = 640 (image rotated) */
770 0x01, 0xe0, /* width = 480 */
771 0x03, /* Number of image components: 3 */
772 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
773 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
774 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
775
776 0xff, 0xda, /* SOS: Start Of Scan */
777 0x00, 0x0c, /* length = 12 bytes (including this length field) */
778 0x03, /* number of components: 3 */
779 0x01, 0x00, /* selector 1, table 0x00 */
780 0x02, 0x11, /* selector 2, table 0x11 */
781 0x03, 0x11, /* selector 3, table 0x11 */
782 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
783 0x00 /* Successive approximation: 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300784};
785
Marton Nemeth1408b842009-11-02 08:13:21 -0300786/* this function is run at interrupt level */
787static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300788 u8 *data, /* isoc packet */
Marton Nemeth1408b842009-11-02 08:13:21 -0300789 int len) /* iso packet length */
790{
791 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300792 u8 *image;
Jean-François Moineae251e62012-02-27 05:15:12 -0300793 u8 *sof;
Marton Nemeth1408b842009-11-02 08:13:21 -0300794
Theodore Kilgorec93396e2013-02-04 13:17:55 -0300795 sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300796 if (sof) {
797 int n, lum_offset, footer_length;
798
Hans de Goede895d4642012-04-28 10:31:17 -0300799 /*
800 * 6 bytes after the FF D9 EOF marker a number of lumination
801 * bytes are send corresponding to different parts of the
802 * image, the 14th and 15th byte after the EOF seem to
803 * correspond to the center of the image.
804 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300805 lum_offset = 61 + sizeof pac_sof_marker;
806 footer_length = 74;
807
808 /* Finish decoding current frame */
809 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
810 if (n < 0) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300811 gspca_dev->image_len += n;
Marton Nemeth1408b842009-11-02 08:13:21 -0300812 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300813 } else {
814 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Marton Nemeth1408b842009-11-02 08:13:21 -0300815 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300816
817 image = gspca_dev->image;
818 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300819 && image[gspca_dev->image_len - 2] == 0xff
820 && image[gspca_dev->image_len - 1] == 0xd9)
821 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Marton Nemeth1408b842009-11-02 08:13:21 -0300822
823 n = sof - data;
824 len -= n;
825 data = sof;
826
827 /* Get average lumination */
828 if (gspca_dev->last_packet_type == LAST_PACKET &&
829 n >= lum_offset)
830 atomic_set(&sd->avg_lum, data[-lum_offset] +
831 data[-lum_offset + 1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300832
833 /* Start the new frame with the jpeg header */
834 /* The PAC7302 has the image rotated 90 degrees */
Jean-François Moine7532e812012-02-27 05:21:57 -0300835 gspca_frame_add(gspca_dev, FIRST_PACKET,
836 jpeg_header, sizeof jpeg_header);
Marton Nemeth1408b842009-11-02 08:13:21 -0300837 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300838 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300839}
840
Márton Németh6763cc02009-11-09 07:10:46 -0300841#ifdef CONFIG_VIDEO_ADV_DEBUG
842static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
Hans Verkuil977ba3b2013-03-24 08:28:46 -0300843 const struct v4l2_dbg_register *reg)
Márton Németh6763cc02009-11-09 07:10:46 -0300844{
Jean-François Moineae251e62012-02-27 05:15:12 -0300845 u8 index;
846 u8 value;
Márton Németh6763cc02009-11-09 07:10:46 -0300847
Hans de Goede895d4642012-04-28 10:31:17 -0300848 /*
849 * reg->reg: bit0..15: reserved for register index (wIndex is 16bit
850 * long on the USB bus)
851 */
Márton Németh6763cc02009-11-09 07:10:46 -0300852 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
853 reg->match.addr == 0 &&
854 (reg->reg < 0x000000ff) &&
855 (reg->val <= 0x000000ff)
856 ) {
857 /* Currently writing to page 0 is only supported. */
858 /* reg_w() only supports 8bit index */
Jean-François Moineae251e62012-02-27 05:15:12 -0300859 index = reg->reg;
860 value = reg->val;
Márton Németh6763cc02009-11-09 07:10:46 -0300861
Hans de Goede895d4642012-04-28 10:31:17 -0300862 /*
863 * Note that there shall be no access to other page
864 * by any other function between the page switch and
865 * the actual register write.
866 */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300867 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
868 reg_w(gspca_dev, index, value);
Márton Németh6763cc02009-11-09 07:10:46 -0300869
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300870 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh6763cc02009-11-09 07:10:46 -0300871 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300872 return gspca_dev->usb_err;
Márton Németh6763cc02009-11-09 07:10:46 -0300873}
874
875static int sd_chip_ident(struct gspca_dev *gspca_dev,
876 struct v4l2_dbg_chip_ident *chip)
877{
878 int ret = -EINVAL;
879
880 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
881 chip->match.addr == 0) {
882 chip->revision = 0;
883 chip->ident = V4L2_IDENT_UNKNOWN;
884 ret = 0;
885 }
886 return ret;
887}
888#endif
889
Peter Senna Tschudinae814c02013-01-24 19:29:03 -0300890#if IS_ENABLED(CONFIG_INPUT)
Márton Némethaed6f1b2010-01-28 16:33:38 -0300891static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
892 u8 *data, /* interrupt packet data */
893 int len) /* interrput packet length */
894{
895 int ret = -EINVAL;
896 u8 data0, data1;
897
898 if (len == 2) {
899 data0 = data[0];
900 data1 = data[1];
901 if ((data0 == 0x00 && data1 == 0x11) ||
902 (data0 == 0x22 && data1 == 0x33) ||
903 (data0 == 0x44 && data1 == 0x55) ||
904 (data0 == 0x66 && data1 == 0x77) ||
905 (data0 == 0x88 && data1 == 0x99) ||
906 (data0 == 0xaa && data1 == 0xbb) ||
907 (data0 == 0xcc && data1 == 0xdd) ||
908 (data0 == 0xee && data1 == 0xff)) {
909 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
910 input_sync(gspca_dev->input_dev);
911 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
912 input_sync(gspca_dev->input_dev);
913 ret = 0;
914 }
915 }
916
917 return ret;
918}
919#endif
920
Marton Nemeth1408b842009-11-02 08:13:21 -0300921/* sub-driver description for pac7302 */
Márton Némethaabcdfb2010-01-05 12:39:02 -0300922static const struct sd_desc sd_desc = {
Jean-François Moineae251e62012-02-27 05:15:12 -0300923 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -0300924 .config = sd_config,
925 .init = sd_init,
Hans de Goede74233cd2012-05-14 11:16:09 -0300926 .init_controls = sd_init_controls,
Marton Nemeth1408b842009-11-02 08:13:21 -0300927 .start = sd_start,
928 .stopN = sd_stopN,
929 .stop0 = sd_stop0,
930 .pkt_scan = sd_pkt_scan,
931 .dq_callback = do_autogain,
Márton Németh6763cc02009-11-09 07:10:46 -0300932#ifdef CONFIG_VIDEO_ADV_DEBUG
933 .set_register = sd_dbg_s_register,
934 .get_chip_ident = sd_chip_ident,
935#endif
Peter Senna Tschudinae814c02013-01-24 19:29:03 -0300936#if IS_ENABLED(CONFIG_INPUT)
Márton Némethaed6f1b2010-01-28 16:33:38 -0300937 .int_pkt_scan = sd_int_pkt_scan,
938#endif
Marton Nemeth1408b842009-11-02 08:13:21 -0300939};
940
941/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300942static const struct usb_device_id device_table[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300943 {USB_DEVICE(0x06f8, 0x3009)},
Jean-François Moinedd32f982012-02-27 04:58:59 -0300944 {USB_DEVICE(0x06f8, 0x301b)},
Marton Nemeth1408b842009-11-02 08:13:21 -0300945 {USB_DEVICE(0x093a, 0x2620)},
946 {USB_DEVICE(0x093a, 0x2621)},
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300947 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
Hans de Goede87f7b772014-07-09 06:20:44 -0300948 {USB_DEVICE(0x093a, 0x2623), .driver_info = FL_VFLIP},
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300949 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
Márton Németh4e6aeef2010-06-14 17:21:37 -0300950 {USB_DEVICE(0x093a, 0x2625)},
Marton Nemeth1408b842009-11-02 08:13:21 -0300951 {USB_DEVICE(0x093a, 0x2626)},
Jozsef Marton5b843252012-05-15 12:05:36 -0300952 {USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -0300953 {USB_DEVICE(0x093a, 0x2628)},
Jean-Francois Moinec4322bf2009-12-02 07:04:35 -0300954 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -0300955 {USB_DEVICE(0x093a, 0x262a)},
956 {USB_DEVICE(0x093a, 0x262c)},
Hans de Goede4d6454d2011-12-30 19:15:53 -0300957 {USB_DEVICE(0x145f, 0x013c)},
Frank Schäfer97d2fbf2012-09-09 15:02:19 -0300958 {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */
Marton Nemeth1408b842009-11-02 08:13:21 -0300959 {}
960};
961MODULE_DEVICE_TABLE(usb, device_table);
962
963/* -- device connect -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300964static int sd_probe(struct usb_interface *intf,
Marton Nemeth1408b842009-11-02 08:13:21 -0300965 const struct usb_device_id *id)
966{
967 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
968 THIS_MODULE);
969}
970
971static struct usb_driver sd_driver = {
Jean-François Moineae251e62012-02-27 05:15:12 -0300972 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -0300973 .id_table = device_table,
974 .probe = sd_probe,
975 .disconnect = gspca_disconnect,
976#ifdef CONFIG_PM
977 .suspend = gspca_suspend,
978 .resume = gspca_resume,
Hans de Goede8bb58962012-06-30 06:44:47 -0300979 .reset_resume = gspca_resume,
Marton Nemeth1408b842009-11-02 08:13:21 -0300980#endif
981};
982
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800983module_usb_driver(sd_driver);