diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-06-30 14:50:11 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:14:49 -0400 |
commit | 6a7eba24e4f0ff725d33159f6265e3a79d53a833 (patch) | |
tree | 3e50d669cb91affbcfad9333d74ddc452783094f /drivers/media/video/gspca/pac7311.c | |
parent | d43fa32fec442571f10f5d0c3b553413288728de (diff) |
V4L/DVB (8157): gspca: all subdrivers
- remaning subdrivers added
- remove the decoding helper and some specific frame decodings
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/pac7311.c')
-rw-r--r-- | drivers/media/video/gspca/pac7311.c | 754 |
1 files changed, 754 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c new file mode 100644 index 000000000000..8f51976db995 --- /dev/null +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -0,0 +1,754 @@ | |||
1 | /* | ||
2 | * Pixart PAC7311 library | ||
3 | * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li | ||
4 | * | ||
5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #define MODULE_NAME "pac7311" | ||
23 | |||
24 | #include "gspca.h" | ||
25 | |||
26 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0) | ||
27 | static const char version[] = "2.1.0"; | ||
28 | |||
29 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | ||
30 | MODULE_DESCRIPTION("Pixart PAC7311"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | /* specific webcam descriptor */ | ||
34 | struct sd { | ||
35 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
36 | |||
37 | int avg_lum; | ||
38 | |||
39 | unsigned char brightness; | ||
40 | #define BRIGHTNESS_MAX 0x20 | ||
41 | unsigned char contrast; | ||
42 | unsigned char colors; | ||
43 | unsigned char autogain; | ||
44 | |||
45 | char ffseq; | ||
46 | signed char ag_cnt; | ||
47 | #define AG_CNT_START 13 | ||
48 | }; | ||
49 | |||
50 | /* V4L2 controls supported by the driver */ | ||
51 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
52 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
53 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
54 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
55 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
56 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
57 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
58 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
59 | |||
60 | static struct ctrl sd_ctrls[] = { | ||
61 | #define SD_BRIGHTNESS 0 | ||
62 | { | ||
63 | { | ||
64 | .id = V4L2_CID_BRIGHTNESS, | ||
65 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
66 | .name = "Brightness", | ||
67 | .minimum = 0, | ||
68 | .maximum = BRIGHTNESS_MAX, | ||
69 | .step = 1, | ||
70 | .default_value = 0x10, | ||
71 | }, | ||
72 | .set = sd_setbrightness, | ||
73 | .get = sd_getbrightness, | ||
74 | }, | ||
75 | #define SD_CONTRAST 1 | ||
76 | { | ||
77 | { | ||
78 | .id = V4L2_CID_CONTRAST, | ||
79 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
80 | .name = "Contrast", | ||
81 | .minimum = 0, | ||
82 | .maximum = 255, | ||
83 | .step = 1, | ||
84 | .default_value = 127, | ||
85 | }, | ||
86 | .set = sd_setcontrast, | ||
87 | .get = sd_getcontrast, | ||
88 | }, | ||
89 | #define SD_COLOR 2 | ||
90 | { | ||
91 | { | ||
92 | .id = V4L2_CID_SATURATION, | ||
93 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
94 | .name = "Color", | ||
95 | .minimum = 0, | ||
96 | .maximum = 255, | ||
97 | .step = 1, | ||
98 | .default_value = 127, | ||
99 | }, | ||
100 | .set = sd_setcolors, | ||
101 | .get = sd_getcolors, | ||
102 | }, | ||
103 | #define SD_AUTOGAIN 3 | ||
104 | { | ||
105 | { | ||
106 | .id = V4L2_CID_AUTOGAIN, | ||
107 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
108 | .name = "Auto Gain", | ||
109 | .minimum = 0, | ||
110 | .maximum = 1, | ||
111 | .step = 1, | ||
112 | .default_value = 1, | ||
113 | }, | ||
114 | .set = sd_setautogain, | ||
115 | .get = sd_getautogain, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | static struct cam_mode vga_mode[] = { | ||
120 | {V4L2_PIX_FMT_JPEG, 160, 120, 2}, | ||
121 | {V4L2_PIX_FMT_JPEG, 320, 240, 1}, | ||
122 | {V4L2_PIX_FMT_JPEG, 640, 480, 0}, | ||
123 | }; | ||
124 | |||
125 | #define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */ | ||
126 | |||
127 | const unsigned char pac7311_jpeg_header[] = { | ||
128 | 0xff, 0xd8, | ||
129 | 0xff, 0xe0, 0x00, 0x03, 0x20, | ||
130 | 0xff, 0xc0, 0x00, 0x11, 0x08, | ||
131 | 0x01, 0xe0, /* 12: height */ | ||
132 | 0x02, 0x80, /* 14: width */ | ||
133 | 0x03, /* 16 */ | ||
134 | 0x01, 0x21, 0x00, | ||
135 | 0x02, 0x11, 0x01, | ||
136 | 0x03, 0x11, 0x01, | ||
137 | 0xff, 0xdb, 0x00, 0x84, | ||
138 | 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, | ||
139 | 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, | ||
140 | 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, | ||
141 | 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, | ||
142 | 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f, | ||
143 | 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64, | ||
144 | 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18, | ||
145 | 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, | ||
146 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
147 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
148 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
149 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
150 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
151 | 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, | ||
152 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
153 | 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
154 | 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, | ||
155 | 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, | ||
156 | 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, | ||
157 | 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, | ||
158 | 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, | ||
159 | 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, | ||
160 | 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, | ||
161 | 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, | ||
162 | 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, | ||
163 | 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, | ||
164 | 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, | ||
165 | 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, | ||
166 | 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, | ||
167 | 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | ||
168 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, | ||
169 | 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, | ||
170 | 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, | ||
171 | 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | ||
172 | 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
173 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
174 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, | ||
175 | 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, | ||
176 | 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, | ||
177 | 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, | ||
178 | 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, | ||
179 | 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, | ||
180 | 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, | ||
181 | 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, | ||
182 | 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, | ||
183 | 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, | ||
184 | 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, | ||
185 | 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, | ||
186 | 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, | ||
187 | 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, | ||
188 | 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | ||
189 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, | ||
190 | 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, | ||
191 | 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | ||
192 | 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, | ||
193 | 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, | ||
194 | 0x11, 0x00, 0x3f, 0x00 | ||
195 | }; | ||
196 | |||
197 | static void reg_w(struct usb_device *dev, | ||
198 | __u16 req, | ||
199 | __u16 value, | ||
200 | __u16 index, | ||
201 | __u8 *buffer, __u16 length) | ||
202 | { | ||
203 | usb_control_msg(dev, | ||
204 | usb_sndctrlpipe(dev, 0), | ||
205 | req, | ||
206 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
207 | value, index, buffer, length, | ||
208 | 500); | ||
209 | } | ||
210 | |||
211 | static void pac7311_reg_read(struct usb_device *dev, __u16 index, | ||
212 | __u8 *buffer) | ||
213 | { | ||
214 | usb_control_msg(dev, | ||
215 | usb_rcvctrlpipe(dev, 0), | ||
216 | 0, /* request */ | ||
217 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
218 | 0, /* value */ | ||
219 | index, buffer, 1, | ||
220 | 500); | ||
221 | } | ||
222 | |||
223 | static void pac7311_reg_write(struct usb_device *dev, | ||
224 | __u16 index, | ||
225 | __u8 value) | ||
226 | { | ||
227 | __u8 buf; | ||
228 | |||
229 | buf = value; | ||
230 | reg_w(dev, 0x00, value, index, &buf, 1); | ||
231 | } | ||
232 | |||
233 | /* this function is called at probe time */ | ||
234 | static int sd_config(struct gspca_dev *gspca_dev, | ||
235 | const struct usb_device_id *id) | ||
236 | { | ||
237 | struct sd *sd = (struct sd *) gspca_dev; | ||
238 | struct usb_device *dev = gspca_dev->dev; | ||
239 | struct cam *cam; | ||
240 | |||
241 | PDEBUG(D_CONF, "Find Sensor PAC7311"); | ||
242 | pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */ | ||
243 | pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */ | ||
244 | pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ | ||
245 | pac7311_reg_write(dev, 0xff, 0x04); | ||
246 | pac7311_reg_write(dev, 0x27, 0x80); | ||
247 | pac7311_reg_write(dev, 0x28, 0xca); | ||
248 | pac7311_reg_write(dev, 0x29, 0x53); | ||
249 | pac7311_reg_write(dev, 0x2a, 0x0e); | ||
250 | pac7311_reg_write(dev, 0xff, 0x01); | ||
251 | pac7311_reg_write(dev, 0x3e, 0x20); | ||
252 | |||
253 | cam = &gspca_dev->cam; | ||
254 | cam->dev_name = (char *) id->driver_info; | ||
255 | cam->epaddr = 0x05; | ||
256 | cam->cam_mode = vga_mode; | ||
257 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
258 | |||
259 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; | ||
260 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; | ||
261 | sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; | ||
262 | sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
267 | { | ||
268 | struct sd *sd = (struct sd *) gspca_dev; | ||
269 | int brightness; | ||
270 | |||
271 | /*jfm: inverted?*/ | ||
272 | brightness = BRIGHTNESS_MAX - sd->brightness; | ||
273 | pac7311_reg_write(gspca_dev->dev, 0xff, 0x04); | ||
274 | /* pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */ | ||
275 | pac7311_reg_write(gspca_dev->dev, 0x0f, brightness); | ||
276 | /* load registers to sensor (Bit 0, auto clear) */ | ||
277 | pac7311_reg_write(gspca_dev->dev, 0x11, 0x01); | ||
278 | PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness); | ||
279 | } | ||
280 | |||
281 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
282 | { | ||
283 | struct sd *sd = (struct sd *) gspca_dev; | ||
284 | |||
285 | pac7311_reg_write(gspca_dev->dev, 0xff, 0x01); | ||
286 | pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast); | ||
287 | /* load registers to sensor (Bit 0, auto clear) */ | ||
288 | pac7311_reg_write(gspca_dev->dev, 0x11, 0x01); | ||
289 | PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast); | ||
290 | } | ||
291 | |||
292 | static void setcolors(struct gspca_dev *gspca_dev) | ||
293 | { | ||
294 | struct sd *sd = (struct sd *) gspca_dev; | ||
295 | |||
296 | pac7311_reg_write(gspca_dev->dev, 0xff, 0x01); | ||
297 | pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors); | ||
298 | /* load registers to sensor (Bit 0, auto clear) */ | ||
299 | pac7311_reg_write(gspca_dev->dev, 0x11, 0x01); | ||
300 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); | ||
301 | } | ||
302 | |||
303 | /* this function is called at open time */ | ||
304 | static int sd_open(struct gspca_dev *gspca_dev) | ||
305 | { | ||
306 | pac7311_reg_write(gspca_dev->dev, 0x78, 0x00); /* Turn on LED */ | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static void sd_start(struct gspca_dev *gspca_dev) | ||
311 | { | ||
312 | struct usb_device *dev = gspca_dev->dev; | ||
313 | struct sd *sd = (struct sd *) gspca_dev; | ||
314 | |||
315 | pac7311_reg_write(dev, 0xff, 0x01); | ||
316 | reg_w(dev, 0x01, 0, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); | ||
317 | reg_w(dev, 0x01, 0, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8); | ||
318 | reg_w(dev, 0x01, 0, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8); | ||
319 | reg_w(dev, 0x01, 0, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8); | ||
320 | reg_w(dev, 0x01, 0, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8); | ||
321 | reg_w(dev, 0x01, 0, 0x002a, "\x00\x00\x00", 3); | ||
322 | reg_w(dev, 0x01, 0, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8); | ||
323 | reg_w(dev, 0x01, 0, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8); | ||
324 | reg_w(dev, 0x01, 0, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8); | ||
325 | reg_w(dev, 0x01, 0, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8); | ||
326 | reg_w(dev, 0x01, 0, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8); | ||
327 | reg_w(dev, 0x01, 0, 0x0066, "\xd0\xff", 2); | ||
328 | reg_w(dev, 0x01, 0, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6); | ||
329 | reg_w(dev, 0x01, 0, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8); | ||
330 | reg_w(dev, 0x01, 0, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8); | ||
331 | reg_w(dev, 0x01, 0, 0x008f, "\x18\x20", 2); | ||
332 | reg_w(dev, 0x01, 0, 0x0096, "\x01\x08\x04", 3); | ||
333 | reg_w(dev, 0x01, 0, 0x00a0, "\x44\x44\x44\x04", 4); | ||
334 | reg_w(dev, 0x01, 0, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8); | ||
335 | reg_w(dev, 0x01, 0, 0x00f8, "\x3f\x00\x0a\x01\x00", 5); | ||
336 | |||
337 | pac7311_reg_write(dev, 0xff, 0x04); | ||
338 | pac7311_reg_write(dev, 0x02, 0x04); | ||
339 | pac7311_reg_write(dev, 0x03, 0x54); | ||
340 | pac7311_reg_write(dev, 0x04, 0x07); | ||
341 | pac7311_reg_write(dev, 0x05, 0x2b); | ||
342 | pac7311_reg_write(dev, 0x06, 0x09); | ||
343 | pac7311_reg_write(dev, 0x07, 0x0f); | ||
344 | pac7311_reg_write(dev, 0x08, 0x09); | ||
345 | pac7311_reg_write(dev, 0x09, 0x00); | ||
346 | pac7311_reg_write(dev, 0x0c, 0x07); | ||
347 | pac7311_reg_write(dev, 0x0d, 0x00); | ||
348 | pac7311_reg_write(dev, 0x0e, 0x00); | ||
349 | pac7311_reg_write(dev, 0x0f, 0x62); | ||
350 | pac7311_reg_write(dev, 0x10, 0x08); | ||
351 | pac7311_reg_write(dev, 0x12, 0x07); | ||
352 | pac7311_reg_write(dev, 0x13, 0x00); | ||
353 | pac7311_reg_write(dev, 0x14, 0x00); | ||
354 | pac7311_reg_write(dev, 0x15, 0x00); | ||
355 | pac7311_reg_write(dev, 0x16, 0x00); | ||
356 | pac7311_reg_write(dev, 0x17, 0x00); | ||
357 | pac7311_reg_write(dev, 0x18, 0x00); | ||
358 | pac7311_reg_write(dev, 0x19, 0x00); | ||
359 | pac7311_reg_write(dev, 0x1a, 0x00); | ||
360 | pac7311_reg_write(dev, 0x1b, 0x03); | ||
361 | pac7311_reg_write(dev, 0x1c, 0xa0); | ||
362 | pac7311_reg_write(dev, 0x1d, 0x01); | ||
363 | pac7311_reg_write(dev, 0x1e, 0xf4); | ||
364 | pac7311_reg_write(dev, 0x21, 0x00); | ||
365 | pac7311_reg_write(dev, 0x22, 0x08); | ||
366 | pac7311_reg_write(dev, 0x24, 0x03); | ||
367 | pac7311_reg_write(dev, 0x26, 0x00); | ||
368 | pac7311_reg_write(dev, 0x27, 0x01); | ||
369 | pac7311_reg_write(dev, 0x28, 0xca); | ||
370 | pac7311_reg_write(dev, 0x29, 0x10); | ||
371 | pac7311_reg_write(dev, 0x2a, 0x06); | ||
372 | pac7311_reg_write(dev, 0x2b, 0x78); | ||
373 | pac7311_reg_write(dev, 0x2c, 0x00); | ||
374 | pac7311_reg_write(dev, 0x2d, 0x00); | ||
375 | pac7311_reg_write(dev, 0x2e, 0x00); | ||
376 | pac7311_reg_write(dev, 0x2f, 0x00); | ||
377 | pac7311_reg_write(dev, 0x30, 0x23); | ||
378 | pac7311_reg_write(dev, 0x31, 0x28); | ||
379 | pac7311_reg_write(dev, 0x32, 0x04); | ||
380 | pac7311_reg_write(dev, 0x33, 0x11); | ||
381 | pac7311_reg_write(dev, 0x34, 0x00); | ||
382 | pac7311_reg_write(dev, 0x35, 0x00); | ||
383 | pac7311_reg_write(dev, 0x11, 0x01); | ||
384 | setcontrast(gspca_dev); | ||
385 | setbrightness(gspca_dev); | ||
386 | setcolors(gspca_dev); | ||
387 | |||
388 | /* set correct resolution */ | ||
389 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) { | ||
390 | case 2: /* 160x120 */ | ||
391 | pac7311_reg_write(dev, 0xff, 0x04); | ||
392 | pac7311_reg_write(dev, 0x02, 0x03); | ||
393 | pac7311_reg_write(dev, 0xff, 0x01); | ||
394 | pac7311_reg_write(dev, 0x08, 0x09); | ||
395 | pac7311_reg_write(dev, 0x17, 0x20); | ||
396 | pac7311_reg_write(dev, 0x1b, 0x00); | ||
397 | /* pac7311_reg_write(dev, 0x80, 0x69); */ | ||
398 | pac7311_reg_write(dev, 0x87, 0x10); | ||
399 | break; | ||
400 | case 1: /* 320x240 */ | ||
401 | pac7311_reg_write(dev, 0xff, 0x04); | ||
402 | pac7311_reg_write(dev, 0x02, 0x03); | ||
403 | pac7311_reg_write(dev, 0xff, 0x01); | ||
404 | pac7311_reg_write(dev, 0x08, 0x09); | ||
405 | pac7311_reg_write(dev, 0x17, 0x30); | ||
406 | /* pac7311_reg_write(dev, 0x80, 0x3f); */ | ||
407 | pac7311_reg_write(dev, 0x87, 0x11); | ||
408 | break; | ||
409 | case 0: /* 640x480 */ | ||
410 | pac7311_reg_write(dev, 0xff, 0x04); | ||
411 | pac7311_reg_write(dev, 0x02, 0x03); | ||
412 | pac7311_reg_write(dev, 0xff, 0x01); | ||
413 | pac7311_reg_write(dev, 0x08, 0x08); | ||
414 | pac7311_reg_write(dev, 0x17, 0x00); | ||
415 | /* pac7311_reg_write(dev, 0x80, 0x1c); */ | ||
416 | pac7311_reg_write(dev, 0x87, 0x12); | ||
417 | break; | ||
418 | } | ||
419 | |||
420 | /* start stream */ | ||
421 | pac7311_reg_write(dev, 0xff, 0x01); | ||
422 | pac7311_reg_write(dev, 0x78, 0x04); | ||
423 | pac7311_reg_write(dev, 0x78, 0x05); | ||
424 | |||
425 | if (sd->autogain) { | ||
426 | sd->ag_cnt = AG_CNT_START; | ||
427 | sd->avg_lum = 0; | ||
428 | } else { | ||
429 | sd->ag_cnt = -1; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
434 | { | ||
435 | struct usb_device *dev = gspca_dev->dev; | ||
436 | |||
437 | pac7311_reg_write(dev, 0xff, 0x04); | ||
438 | pac7311_reg_write(dev, 0x27, 0x80); | ||
439 | pac7311_reg_write(dev, 0x28, 0xca); | ||
440 | pac7311_reg_write(dev, 0x29, 0x53); | ||
441 | pac7311_reg_write(dev, 0x2a, 0x0e); | ||
442 | pac7311_reg_write(dev, 0xff, 0x01); | ||
443 | pac7311_reg_write(dev, 0x3e, 0x20); | ||
444 | pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */ | ||
445 | pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ | ||
446 | pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ | ||
447 | } | ||
448 | |||
449 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
450 | { | ||
451 | } | ||
452 | |||
453 | /* this function is called at close time */ | ||
454 | static void sd_close(struct gspca_dev *gspca_dev) | ||
455 | { | ||
456 | struct usb_device *dev = gspca_dev->dev; | ||
457 | |||
458 | pac7311_reg_write(dev, 0xff, 0x04); | ||
459 | pac7311_reg_write(dev, 0x27, 0x80); | ||
460 | pac7311_reg_write(dev, 0x28, 0xca); | ||
461 | pac7311_reg_write(dev, 0x29, 0x53); | ||
462 | pac7311_reg_write(dev, 0x2a, 0x0e); | ||
463 | pac7311_reg_write(dev, 0xff, 0x01); | ||
464 | pac7311_reg_write(dev, 0x3e, 0x20); | ||
465 | pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */ | ||
466 | pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ | ||
467 | pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ | ||
468 | } | ||
469 | |||
470 | static void setautogain(struct gspca_dev *gspca_dev, int luma) | ||
471 | { | ||
472 | int luma_mean = 128; | ||
473 | int luma_delta = 20; | ||
474 | __u8 spring = 5; | ||
475 | __u8 Pxclk; | ||
476 | int Gbright; | ||
477 | |||
478 | pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk); | ||
479 | Gbright = Pxclk; | ||
480 | PDEBUG(D_FRAM, "luma mean %d", luma); | ||
481 | if (luma < luma_mean - luma_delta || | ||
482 | luma > luma_mean + luma_delta) { | ||
483 | Gbright += (luma_mean - luma) >> spring; | ||
484 | if (Gbright > 0x1a) | ||
485 | Gbright = 0x1a; | ||
486 | else if (Gbright < 4) | ||
487 | Gbright = 4; | ||
488 | PDEBUG(D_FRAM, "gbright %d", Gbright); | ||
489 | pac7311_reg_write(gspca_dev->dev, 0xff, 0x04); | ||
490 | pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright); | ||
491 | /* load registers to sensor (Bit 0, auto clear) */ | ||
492 | pac7311_reg_write(gspca_dev->dev, 0x11, 0x01); | ||
493 | } | ||
494 | } | ||
495 | |||
496 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
497 | struct gspca_frame *frame, /* target */ | ||
498 | unsigned char *data, /* isoc packet */ | ||
499 | int len) /* iso packet length */ | ||
500 | { | ||
501 | struct sd *sd = (struct sd *) gspca_dev; | ||
502 | unsigned char tmpbuf[4]; | ||
503 | int i, p, ffseq; | ||
504 | |||
505 | /* if (len < 5) { */ | ||
506 | if (len < 6) { | ||
507 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ | ||
508 | return; | ||
509 | } | ||
510 | |||
511 | ffseq = sd->ffseq; | ||
512 | |||
513 | for (p = 0; p < len - 6; p++) { | ||
514 | if ((data[0 + p] == 0xff) | ||
515 | && (data[1 + p] == 0xff) | ||
516 | && (data[2 + p] == 0x00) | ||
517 | && (data[3 + p] == 0xff) | ||
518 | && (data[4 + p] == 0x96)) { | ||
519 | |||
520 | /* start of frame */ | ||
521 | if (sd->ag_cnt >= 0 && p > 28) { | ||
522 | sd->avg_lum += data[p - 23]; | ||
523 | if (--sd->ag_cnt < 0) { | ||
524 | sd->ag_cnt = AG_CNT_START; | ||
525 | setautogain(gspca_dev, | ||
526 | sd->avg_lum / AG_CNT_START); | ||
527 | sd->avg_lum = 0; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | /* copy the end of data to the current frame */ | ||
532 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
533 | data, p); | ||
534 | |||
535 | /* put the JPEG header in the new frame */ | ||
536 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | ||
537 | (unsigned char *) pac7311_jpeg_header, | ||
538 | 12); | ||
539 | tmpbuf[0] = gspca_dev->height >> 8; | ||
540 | tmpbuf[1] = gspca_dev->height & 0xff; | ||
541 | tmpbuf[2] = gspca_dev->width >> 8; | ||
542 | tmpbuf[3] = gspca_dev->width & 0xff; | ||
543 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
544 | tmpbuf, 4); | ||
545 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
546 | (unsigned char *) &pac7311_jpeg_header[16], | ||
547 | PAC7311_JPEG_HEADER_SIZE - 16); | ||
548 | |||
549 | data += p + 7; | ||
550 | len -= p + 7; | ||
551 | ffseq = 0; | ||
552 | break; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | /* remove the 'ff ff ff xx' sequences */ | ||
557 | switch (ffseq) { | ||
558 | case 3: | ||
559 | data += 1; | ||
560 | len -= 1; | ||
561 | break; | ||
562 | case 2: | ||
563 | if (data[0] == 0xff) { | ||
564 | data += 2; | ||
565 | len -= 2; | ||
566 | frame->data_end -= 2; | ||
567 | } | ||
568 | break; | ||
569 | case 1: | ||
570 | if (data[0] == 0xff | ||
571 | && data[1] == 0xff) { | ||
572 | data += 3; | ||
573 | len -= 3; | ||
574 | frame->data_end -= 1; | ||
575 | } | ||
576 | break; | ||
577 | } | ||
578 | for (i = 0; i < len - 4; i++) { | ||
579 | if (data[i] == 0xff | ||
580 | && data[i + 1] == 0xff | ||
581 | && data[i + 2] == 0xff) { | ||
582 | memmove(&data[i], &data[i + 4], len - i - 4); | ||
583 | len -= 4; | ||
584 | } | ||
585 | } | ||
586 | ffseq = 0; | ||
587 | if (data[len - 4] == 0xff) { | ||
588 | if (data[len - 3] == 0xff | ||
589 | && data[len - 2] == 0xff) { | ||
590 | len -= 4; | ||
591 | } | ||
592 | } else if (data[len - 3] == 0xff) { | ||
593 | if (data[len - 2] == 0xff | ||
594 | && data[len - 1] == 0xff) | ||
595 | ffseq = 3; | ||
596 | } else if (data[len - 2] == 0xff) { | ||
597 | if (data[len - 1] == 0xff) | ||
598 | ffseq = 2; | ||
599 | } else if (data[len - 1] == 0xff) | ||
600 | ffseq = 1; | ||
601 | sd->ffseq = ffseq; | ||
602 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
603 | } | ||
604 | |||
605 | static void getbrightness(struct gspca_dev *gspca_dev) | ||
606 | { | ||
607 | /* __u8 brightness = 0; | ||
608 | |||
609 | pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness); | ||
610 | spca50x->brightness = brightness; | ||
611 | return spca50x->brightness; */ | ||
612 | /* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */ | ||
613 | } | ||
614 | |||
615 | |||
616 | |||
617 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
618 | { | ||
619 | struct sd *sd = (struct sd *) gspca_dev; | ||
620 | |||
621 | sd->brightness = val; | ||
622 | if (gspca_dev->streaming) | ||
623 | setbrightness(gspca_dev); | ||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
628 | { | ||
629 | struct sd *sd = (struct sd *) gspca_dev; | ||
630 | |||
631 | getbrightness(gspca_dev); | ||
632 | *val = sd->brightness; | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
637 | { | ||
638 | struct sd *sd = (struct sd *) gspca_dev; | ||
639 | |||
640 | sd->contrast = val; | ||
641 | if (gspca_dev->streaming) | ||
642 | setcontrast(gspca_dev); | ||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
647 | { | ||
648 | struct sd *sd = (struct sd *) gspca_dev; | ||
649 | |||
650 | /* getcontrast(gspca_dev); */ | ||
651 | *val = sd->contrast; | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | ||
656 | { | ||
657 | struct sd *sd = (struct sd *) gspca_dev; | ||
658 | |||
659 | sd->colors = val; | ||
660 | if (gspca_dev->streaming) | ||
661 | setcolors(gspca_dev); | ||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | ||
666 | { | ||
667 | struct sd *sd = (struct sd *) gspca_dev; | ||
668 | |||
669 | /* getcolors(gspca_dev); */ | ||
670 | *val = sd->colors; | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
675 | { | ||
676 | struct sd *sd = (struct sd *) gspca_dev; | ||
677 | |||
678 | sd->autogain = val; | ||
679 | if (val) { | ||
680 | sd->ag_cnt = AG_CNT_START; | ||
681 | sd->avg_lum = 0; | ||
682 | } else { | ||
683 | sd->ag_cnt = -1; | ||
684 | } | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
689 | { | ||
690 | struct sd *sd = (struct sd *) gspca_dev; | ||
691 | |||
692 | *val = sd->autogain; | ||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | /* sub-driver description */ | ||
697 | static struct sd_desc sd_desc = { | ||
698 | .name = MODULE_NAME, | ||
699 | .ctrls = sd_ctrls, | ||
700 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
701 | .config = sd_config, | ||
702 | .open = sd_open, | ||
703 | .start = sd_start, | ||
704 | .stopN = sd_stopN, | ||
705 | .stop0 = sd_stop0, | ||
706 | .close = sd_close, | ||
707 | .pkt_scan = sd_pkt_scan, | ||
708 | }; | ||
709 | |||
710 | /* -- module initialisation -- */ | ||
711 | #define DVNM(name) .driver_info = (kernel_ulong_t) name | ||
712 | static __devinitdata struct usb_device_id device_table[] = { | ||
713 | {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")}, | ||
714 | {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")}, | ||
715 | {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")}, | ||
716 | {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")}, | ||
717 | {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350")}, | ||
718 | {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")}, | ||
719 | {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")}, | ||
720 | {} | ||
721 | }; | ||
722 | MODULE_DEVICE_TABLE(usb, device_table); | ||
723 | |||
724 | /* -- device connect -- */ | ||
725 | static int sd_probe(struct usb_interface *intf, | ||
726 | const struct usb_device_id *id) | ||
727 | { | ||
728 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
729 | THIS_MODULE); | ||
730 | } | ||
731 | |||
732 | static struct usb_driver sd_driver = { | ||
733 | .name = MODULE_NAME, | ||
734 | .id_table = device_table, | ||
735 | .probe = sd_probe, | ||
736 | .disconnect = gspca_disconnect, | ||
737 | }; | ||
738 | |||
739 | /* -- module insert / remove -- */ | ||
740 | static int __init sd_mod_init(void) | ||
741 | { | ||
742 | if (usb_register(&sd_driver) < 0) | ||
743 | return -1; | ||
744 | PDEBUG(D_PROBE, "v%s registered", version); | ||
745 | return 0; | ||
746 | } | ||
747 | static void __exit sd_mod_exit(void) | ||
748 | { | ||
749 | usb_deregister(&sd_driver); | ||
750 | PDEBUG(D_PROBE, "deregistered"); | ||
751 | } | ||
752 | |||
753 | module_init(sd_mod_init); | ||
754 | module_exit(sd_mod_exit); | ||