1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * SPCA506 chip based cameras function |
4 | * M Xhaard 15/04/2004 based on different work Mark Taylor and others |
5 | * and my own snoopy file on a pv-321c donate by a german compagny |
6 | * "Firma Frank Gmbh" from Saarbruecken |
7 | * |
8 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> |
9 | */ |
10 | |
11 | #define MODULE_NAME "spca506" |
12 | |
13 | #include "gspca.h" |
14 | |
15 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>" ); |
16 | MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver" ); |
17 | MODULE_LICENSE("GPL" ); |
18 | |
19 | /* specific webcam descriptor */ |
20 | struct sd { |
21 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
22 | |
23 | char norme; |
24 | char channel; |
25 | }; |
26 | |
27 | static const struct v4l2_pix_format vga_mode[] = { |
28 | {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, |
29 | .bytesperline = 160, |
30 | .sizeimage = 160 * 120 * 3 / 2, |
31 | .colorspace = V4L2_COLORSPACE_SRGB, |
32 | .priv = 5}, |
33 | {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, |
34 | .bytesperline = 176, |
35 | .sizeimage = 176 * 144 * 3 / 2, |
36 | .colorspace = V4L2_COLORSPACE_SRGB, |
37 | .priv = 4}, |
38 | {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, |
39 | .bytesperline = 320, |
40 | .sizeimage = 320 * 240 * 3 / 2, |
41 | .colorspace = V4L2_COLORSPACE_SRGB, |
42 | .priv = 2}, |
43 | {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, |
44 | .bytesperline = 352, |
45 | .sizeimage = 352 * 288 * 3 / 2, |
46 | .colorspace = V4L2_COLORSPACE_SRGB, |
47 | .priv = 1}, |
48 | {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, |
49 | .bytesperline = 640, |
50 | .sizeimage = 640 * 480 * 3 / 2, |
51 | .colorspace = V4L2_COLORSPACE_SRGB, |
52 | .priv = 0}, |
53 | }; |
54 | |
55 | #define SPCA50X_OFFSET_DATA 10 |
56 | |
57 | #define SAA7113_bright 0x0a /* defaults 0x80 */ |
58 | #define SAA7113_contrast 0x0b /* defaults 0x47 */ |
59 | #define SAA7113_saturation 0x0c /* defaults 0x40 */ |
60 | #define SAA7113_hue 0x0d /* defaults 0x00 */ |
61 | #define SAA7113_I2C_BASE_WRITE 0x4a |
62 | |
63 | /* read 'len' bytes to gspca_dev->usb_buf */ |
64 | static void reg_r(struct gspca_dev *gspca_dev, |
65 | __u16 req, |
66 | __u16 index, |
67 | __u16 length) |
68 | { |
69 | usb_control_msg(dev: gspca_dev->dev, |
70 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
71 | request: req, |
72 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
73 | value: 0, /* value */ |
74 | index, data: gspca_dev->usb_buf, size: length, |
75 | timeout: 500); |
76 | } |
77 | |
78 | static void reg_w(struct usb_device *dev, |
79 | __u16 req, |
80 | __u16 value, |
81 | __u16 index) |
82 | { |
83 | usb_control_msg(dev, |
84 | usb_sndctrlpipe(dev, 0), |
85 | request: req, |
86 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
87 | value, index, |
88 | NULL, size: 0, timeout: 500); |
89 | } |
90 | |
91 | static void spca506_Initi2c(struct gspca_dev *gspca_dev) |
92 | { |
93 | reg_w(dev: gspca_dev->dev, req: 0x07, SAA7113_I2C_BASE_WRITE, index: 0x0004); |
94 | } |
95 | |
96 | static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur, |
97 | __u16 reg) |
98 | { |
99 | int retry = 60; |
100 | |
101 | reg_w(dev: gspca_dev->dev, req: 0x07, value: reg, index: 0x0001); |
102 | reg_w(dev: gspca_dev->dev, req: 0x07, value: valeur, index: 0x0000); |
103 | while (retry--) { |
104 | reg_r(gspca_dev, req: 0x07, index: 0x0003, length: 2); |
105 | if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00) |
106 | break; |
107 | } |
108 | } |
109 | |
110 | static void spca506_SetNormeInput(struct gspca_dev *gspca_dev, |
111 | __u16 norme, |
112 | __u16 channel) |
113 | { |
114 | struct sd *sd = (struct sd *) gspca_dev; |
115 | /* fixme: check if channel == 0..3 and 6..9 (8 values) */ |
116 | __u8 setbit0 = 0x00; |
117 | __u8 setbit1 = 0x00; |
118 | __u8 videomask = 0x00; |
119 | |
120 | gspca_dbg(gspca_dev, D_STREAM, "** Open Set Norme **\n" ); |
121 | spca506_Initi2c(gspca_dev); |
122 | /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */ |
123 | /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */ |
124 | /* and exclude SAA7113 reserved channel set default 0 otherwise */ |
125 | if (norme & V4L2_STD_NTSC) |
126 | setbit0 = 0x01; |
127 | if (channel == 4 || channel == 5 || channel > 9) |
128 | channel = 0; |
129 | if (channel < 4) |
130 | setbit1 = 0x02; |
131 | videomask = (0x48 | setbit0 | setbit1); |
132 | reg_w(dev: gspca_dev->dev, req: 0x08, value: videomask, index: 0x0000); |
133 | spca506_WriteI2c(gspca_dev, valeur: (0xc0 | (channel & 0x0F)), reg: 0x02); |
134 | |
135 | if (norme & V4L2_STD_NTSC) |
136 | spca506_WriteI2c(gspca_dev, valeur: 0x33, reg: 0x0e); |
137 | /* Chrominance Control NTSC N */ |
138 | else if (norme & V4L2_STD_SECAM) |
139 | spca506_WriteI2c(gspca_dev, valeur: 0x53, reg: 0x0e); |
140 | /* Chrominance Control SECAM */ |
141 | else |
142 | spca506_WriteI2c(gspca_dev, valeur: 0x03, reg: 0x0e); |
143 | /* Chrominance Control PAL BGHIV */ |
144 | |
145 | sd->norme = norme; |
146 | sd->channel = channel; |
147 | gspca_dbg(gspca_dev, D_STREAM, "Set Video Byte to 0x%2x\n" , videomask); |
148 | gspca_dbg(gspca_dev, D_STREAM, "Set Norme: %08x Channel %d" , |
149 | norme, channel); |
150 | } |
151 | |
152 | static void spca506_GetNormeInput(struct gspca_dev *gspca_dev, |
153 | __u16 *norme, __u16 *channel) |
154 | { |
155 | struct sd *sd = (struct sd *) gspca_dev; |
156 | |
157 | /* Read the register is not so good value change so |
158 | we use your own copy in spca50x struct */ |
159 | *norme = sd->norme; |
160 | *channel = sd->channel; |
161 | gspca_dbg(gspca_dev, D_STREAM, "Get Norme: %d Channel %d\n" , |
162 | *norme, *channel); |
163 | } |
164 | |
165 | static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code, |
166 | __u16 xmult, __u16 ymult) |
167 | { |
168 | struct usb_device *dev = gspca_dev->dev; |
169 | |
170 | gspca_dbg(gspca_dev, D_STREAM, "** SetSize **\n" ); |
171 | reg_w(dev, req: 0x04, value: (0x18 | (code & 0x07)), index: 0x0000); |
172 | /* Soft snap 0x40 Hard 0x41 */ |
173 | reg_w(dev, req: 0x04, value: 0x41, index: 0x0001); |
174 | reg_w(dev, req: 0x04, value: 0x00, index: 0x0002); |
175 | /* reserved */ |
176 | reg_w(dev, req: 0x04, value: 0x00, index: 0x0003); |
177 | |
178 | /* reserved */ |
179 | reg_w(dev, req: 0x04, value: 0x00, index: 0x0004); |
180 | /* reserved */ |
181 | reg_w(dev, req: 0x04, value: 0x01, index: 0x0005); |
182 | /* reserced */ |
183 | reg_w(dev, req: 0x04, value: xmult, index: 0x0006); |
184 | /* reserved */ |
185 | reg_w(dev, req: 0x04, value: ymult, index: 0x0007); |
186 | /* compression 1 */ |
187 | reg_w(dev, req: 0x04, value: 0x00, index: 0x0008); |
188 | /* T=64 -> 2 */ |
189 | reg_w(dev, req: 0x04, value: 0x00, index: 0x0009); |
190 | /* threshold2D */ |
191 | reg_w(dev, req: 0x04, value: 0x21, index: 0x000a); |
192 | /* quantization */ |
193 | reg_w(dev, req: 0x04, value: 0x00, index: 0x000b); |
194 | } |
195 | |
196 | /* this function is called at probe time */ |
197 | static int sd_config(struct gspca_dev *gspca_dev, |
198 | const struct usb_device_id *id) |
199 | { |
200 | struct cam *cam; |
201 | |
202 | cam = &gspca_dev->cam; |
203 | cam->cam_mode = vga_mode; |
204 | cam->nmodes = ARRAY_SIZE(vga_mode); |
205 | return 0; |
206 | } |
207 | |
208 | /* this function is called at probe and resume time */ |
209 | static int sd_init(struct gspca_dev *gspca_dev) |
210 | { |
211 | struct usb_device *dev = gspca_dev->dev; |
212 | |
213 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0004); |
214 | reg_w(dev, req: 0x03, value: 0xFF, index: 0x0003); |
215 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0000); |
216 | reg_w(dev, req: 0x03, value: 0x1c, index: 0x0001); |
217 | reg_w(dev, req: 0x03, value: 0x18, index: 0x0001); |
218 | /* Init on PAL and composite input0 */ |
219 | spca506_SetNormeInput(gspca_dev, norme: 0, channel: 0); |
220 | reg_w(dev, req: 0x03, value: 0x1c, index: 0x0001); |
221 | reg_w(dev, req: 0x03, value: 0x18, index: 0x0001); |
222 | reg_w(dev, req: 0x05, value: 0x00, index: 0x0000); |
223 | reg_w(dev, req: 0x05, value: 0xef, index: 0x0001); |
224 | reg_w(dev, req: 0x05, value: 0x00, index: 0x00c1); |
225 | reg_w(dev, req: 0x05, value: 0x00, index: 0x00c2); |
226 | reg_w(dev, req: 0x06, value: 0x18, index: 0x0002); |
227 | reg_w(dev, req: 0x06, value: 0xf5, index: 0x0011); |
228 | reg_w(dev, req: 0x06, value: 0x02, index: 0x0012); |
229 | reg_w(dev, req: 0x06, value: 0xfb, index: 0x0013); |
230 | reg_w(dev, req: 0x06, value: 0x00, index: 0x0014); |
231 | reg_w(dev, req: 0x06, value: 0xa4, index: 0x0051); |
232 | reg_w(dev, req: 0x06, value: 0x40, index: 0x0052); |
233 | reg_w(dev, req: 0x06, value: 0x71, index: 0x0053); |
234 | reg_w(dev, req: 0x06, value: 0x40, index: 0x0054); |
235 | /************************************************/ |
236 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0004); |
237 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0003); |
238 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0004); |
239 | reg_w(dev, req: 0x03, value: 0xFF, index: 0x0003); |
240 | reg_w(dev, req: 0x02, value: 0x00, index: 0x0000); |
241 | reg_w(dev, req: 0x03, value: 0x60, index: 0x0000); |
242 | reg_w(dev, req: 0x03, value: 0x18, index: 0x0001); |
243 | /* for a better reading mx :) */ |
244 | /*sdca506_WriteI2c(value,register) */ |
245 | spca506_Initi2c(gspca_dev); |
246 | spca506_WriteI2c(gspca_dev, valeur: 0x08, reg: 0x01); |
247 | spca506_WriteI2c(gspca_dev, valeur: 0xc0, reg: 0x02); |
248 | /* input composite video */ |
249 | spca506_WriteI2c(gspca_dev, valeur: 0x33, reg: 0x03); |
250 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x04); |
251 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x05); |
252 | spca506_WriteI2c(gspca_dev, valeur: 0x0d, reg: 0x06); |
253 | spca506_WriteI2c(gspca_dev, valeur: 0xf0, reg: 0x07); |
254 | spca506_WriteI2c(gspca_dev, valeur: 0x98, reg: 0x08); |
255 | spca506_WriteI2c(gspca_dev, valeur: 0x03, reg: 0x09); |
256 | spca506_WriteI2c(gspca_dev, valeur: 0x80, reg: 0x0a); |
257 | spca506_WriteI2c(gspca_dev, valeur: 0x47, reg: 0x0b); |
258 | spca506_WriteI2c(gspca_dev, valeur: 0x48, reg: 0x0c); |
259 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x0d); |
260 | spca506_WriteI2c(gspca_dev, valeur: 0x03, reg: 0x0e); /* Chroma Pal adjust */ |
261 | spca506_WriteI2c(gspca_dev, valeur: 0x2a, reg: 0x0f); |
262 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x10); |
263 | spca506_WriteI2c(gspca_dev, valeur: 0x0c, reg: 0x11); |
264 | spca506_WriteI2c(gspca_dev, valeur: 0xb8, reg: 0x12); |
265 | spca506_WriteI2c(gspca_dev, valeur: 0x01, reg: 0x13); |
266 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x14); |
267 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x15); |
268 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x16); |
269 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x17); |
270 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x18); |
271 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x19); |
272 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1a); |
273 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1b); |
274 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1c); |
275 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1d); |
276 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1e); |
277 | spca506_WriteI2c(gspca_dev, valeur: 0xa1, reg: 0x1f); |
278 | spca506_WriteI2c(gspca_dev, valeur: 0x02, reg: 0x40); |
279 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x41); |
280 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x42); |
281 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x43); |
282 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x44); |
283 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x45); |
284 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x46); |
285 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x47); |
286 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x48); |
287 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x49); |
288 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4a); |
289 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4b); |
290 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4c); |
291 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4d); |
292 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4e); |
293 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4f); |
294 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x50); |
295 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x51); |
296 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x52); |
297 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x53); |
298 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x54); |
299 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x55); |
300 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x56); |
301 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x57); |
302 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x58); |
303 | spca506_WriteI2c(gspca_dev, valeur: 0x54, reg: 0x59); |
304 | spca506_WriteI2c(gspca_dev, valeur: 0x07, reg: 0x5a); |
305 | spca506_WriteI2c(gspca_dev, valeur: 0x83, reg: 0x5b); |
306 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5c); |
307 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5d); |
308 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5e); |
309 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5f); |
310 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x60); |
311 | spca506_WriteI2c(gspca_dev, valeur: 0x05, reg: 0x61); |
312 | spca506_WriteI2c(gspca_dev, valeur: 0x9f, reg: 0x62); |
313 | gspca_dbg(gspca_dev, D_STREAM, "** Close Init *\n" ); |
314 | return 0; |
315 | } |
316 | |
317 | static int sd_start(struct gspca_dev *gspca_dev) |
318 | { |
319 | struct usb_device *dev = gspca_dev->dev; |
320 | __u16 norme; |
321 | __u16 channel; |
322 | |
323 | /**************************************/ |
324 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0004); |
325 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0003); |
326 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0004); |
327 | reg_w(dev, req: 0x03, value: 0xFF, index: 0x0003); |
328 | reg_w(dev, req: 0x02, value: 0x00, index: 0x0000); |
329 | reg_w(dev, req: 0x03, value: 0x60, index: 0x0000); |
330 | reg_w(dev, req: 0x03, value: 0x18, index: 0x0001); |
331 | |
332 | /*sdca506_WriteI2c(value,register) */ |
333 | spca506_Initi2c(gspca_dev); |
334 | spca506_WriteI2c(gspca_dev, valeur: 0x08, reg: 0x01); /* Increment Delay */ |
335 | /* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */ |
336 | spca506_WriteI2c(gspca_dev, valeur: 0x33, reg: 0x03); |
337 | /* Analog Input Control 2 */ |
338 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x04); |
339 | /* Analog Input Control 3 */ |
340 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x05); |
341 | /* Analog Input Control 4 */ |
342 | spca506_WriteI2c(gspca_dev, valeur: 0x0d, reg: 0x06); |
343 | /* Horizontal Sync Start 0xe9-0x0d */ |
344 | spca506_WriteI2c(gspca_dev, valeur: 0xf0, reg: 0x07); |
345 | /* Horizontal Sync Stop 0x0d-0xf0 */ |
346 | |
347 | spca506_WriteI2c(gspca_dev, valeur: 0x98, reg: 0x08); /* Sync Control */ |
348 | /* Defaults value */ |
349 | spca506_WriteI2c(gspca_dev, valeur: 0x03, reg: 0x09); /* Luminance Control */ |
350 | spca506_WriteI2c(gspca_dev, valeur: 0x80, reg: 0x0a); |
351 | /* Luminance Brightness */ |
352 | spca506_WriteI2c(gspca_dev, valeur: 0x47, reg: 0x0b); /* Luminance Contrast */ |
353 | spca506_WriteI2c(gspca_dev, valeur: 0x48, reg: 0x0c); |
354 | /* Chrominance Saturation */ |
355 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x0d); |
356 | /* Chrominance Hue Control */ |
357 | spca506_WriteI2c(gspca_dev, valeur: 0x2a, reg: 0x0f); |
358 | /* Chrominance Gain Control */ |
359 | /**************************************/ |
360 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x10); |
361 | /* Format/Delay Control */ |
362 | spca506_WriteI2c(gspca_dev, valeur: 0x0c, reg: 0x11); /* Output Control 1 */ |
363 | spca506_WriteI2c(gspca_dev, valeur: 0xb8, reg: 0x12); /* Output Control 2 */ |
364 | spca506_WriteI2c(gspca_dev, valeur: 0x01, reg: 0x13); /* Output Control 3 */ |
365 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x14); /* reserved */ |
366 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x15); /* VGATE START */ |
367 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x16); /* VGATE STOP */ |
368 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x17); /* VGATE Control (MSB) */ |
369 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x18); |
370 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x19); |
371 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1a); |
372 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1b); |
373 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1c); |
374 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1d); |
375 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x1e); |
376 | spca506_WriteI2c(gspca_dev, valeur: 0xa1, reg: 0x1f); |
377 | spca506_WriteI2c(gspca_dev, valeur: 0x02, reg: 0x40); |
378 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x41); |
379 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x42); |
380 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x43); |
381 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x44); |
382 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x45); |
383 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x46); |
384 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x47); |
385 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x48); |
386 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x49); |
387 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4a); |
388 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4b); |
389 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4c); |
390 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4d); |
391 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4e); |
392 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x4f); |
393 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x50); |
394 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x51); |
395 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x52); |
396 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x53); |
397 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x54); |
398 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x55); |
399 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x56); |
400 | spca506_WriteI2c(gspca_dev, valeur: 0xff, reg: 0x57); |
401 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x58); |
402 | spca506_WriteI2c(gspca_dev, valeur: 0x54, reg: 0x59); |
403 | spca506_WriteI2c(gspca_dev, valeur: 0x07, reg: 0x5a); |
404 | spca506_WriteI2c(gspca_dev, valeur: 0x83, reg: 0x5b); |
405 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5c); |
406 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5d); |
407 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5e); |
408 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x5f); |
409 | spca506_WriteI2c(gspca_dev, valeur: 0x00, reg: 0x60); |
410 | spca506_WriteI2c(gspca_dev, valeur: 0x05, reg: 0x61); |
411 | spca506_WriteI2c(gspca_dev, valeur: 0x9f, reg: 0x62); |
412 | /**************************************/ |
413 | reg_w(dev, req: 0x05, value: 0x00, index: 0x0003); |
414 | reg_w(dev, req: 0x05, value: 0x00, index: 0x0004); |
415 | reg_w(dev, req: 0x03, value: 0x10, index: 0x0001); |
416 | reg_w(dev, req: 0x03, value: 0x78, index: 0x0000); |
417 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { |
418 | case 0: |
419 | spca506_Setsize(gspca_dev, code: 0, xmult: 0x10, ymult: 0x10); |
420 | break; |
421 | case 1: |
422 | spca506_Setsize(gspca_dev, code: 1, xmult: 0x1a, ymult: 0x1a); |
423 | break; |
424 | case 2: |
425 | spca506_Setsize(gspca_dev, code: 2, xmult: 0x1c, ymult: 0x1c); |
426 | break; |
427 | case 4: |
428 | spca506_Setsize(gspca_dev, code: 4, xmult: 0x34, ymult: 0x34); |
429 | break; |
430 | default: |
431 | /* case 5: */ |
432 | spca506_Setsize(gspca_dev, code: 5, xmult: 0x40, ymult: 0x40); |
433 | break; |
434 | } |
435 | |
436 | /* compress setting and size */ |
437 | /* set i2c luma */ |
438 | reg_w(dev, req: 0x02, value: 0x01, index: 0x0000); |
439 | reg_w(dev, req: 0x03, value: 0x12, index: 0x0000); |
440 | reg_r(gspca_dev, req: 0x04, index: 0x0001, length: 2); |
441 | gspca_dbg(gspca_dev, D_STREAM, "webcam started\n" ); |
442 | spca506_GetNormeInput(gspca_dev, norme: &norme, channel: &channel); |
443 | spca506_SetNormeInput(gspca_dev, norme, channel); |
444 | return 0; |
445 | } |
446 | |
447 | static void sd_stopN(struct gspca_dev *gspca_dev) |
448 | { |
449 | struct usb_device *dev = gspca_dev->dev; |
450 | |
451 | reg_w(dev, req: 0x02, value: 0x00, index: 0x0000); |
452 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0004); |
453 | reg_w(dev, req: 0x03, value: 0x00, index: 0x0003); |
454 | } |
455 | |
456 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
457 | u8 *data, /* isoc packet */ |
458 | int len) /* iso packet length */ |
459 | { |
460 | switch (data[0]) { |
461 | case 0: /* start of frame */ |
462 | gspca_frame_add(gspca_dev, packet_type: LAST_PACKET, NULL, len: 0); |
463 | data += SPCA50X_OFFSET_DATA; |
464 | len -= SPCA50X_OFFSET_DATA; |
465 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, data, len); |
466 | break; |
467 | case 0xff: /* drop */ |
468 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ |
469 | break; |
470 | default: |
471 | data += 1; |
472 | len -= 1; |
473 | gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data, len); |
474 | break; |
475 | } |
476 | } |
477 | |
478 | static void setbrightness(struct gspca_dev *gspca_dev, s32 val) |
479 | { |
480 | spca506_Initi2c(gspca_dev); |
481 | spca506_WriteI2c(gspca_dev, valeur: val, SAA7113_bright); |
482 | spca506_WriteI2c(gspca_dev, valeur: 0x01, reg: 0x09); |
483 | } |
484 | |
485 | static void setcontrast(struct gspca_dev *gspca_dev, s32 val) |
486 | { |
487 | spca506_Initi2c(gspca_dev); |
488 | spca506_WriteI2c(gspca_dev, valeur: val, SAA7113_contrast); |
489 | spca506_WriteI2c(gspca_dev, valeur: 0x01, reg: 0x09); |
490 | } |
491 | |
492 | static void setcolors(struct gspca_dev *gspca_dev, s32 val) |
493 | { |
494 | spca506_Initi2c(gspca_dev); |
495 | spca506_WriteI2c(gspca_dev, valeur: val, SAA7113_saturation); |
496 | spca506_WriteI2c(gspca_dev, valeur: 0x01, reg: 0x09); |
497 | } |
498 | |
499 | static void sethue(struct gspca_dev *gspca_dev, s32 val) |
500 | { |
501 | spca506_Initi2c(gspca_dev); |
502 | spca506_WriteI2c(gspca_dev, valeur: val, SAA7113_hue); |
503 | spca506_WriteI2c(gspca_dev, valeur: 0x01, reg: 0x09); |
504 | } |
505 | |
506 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
507 | { |
508 | struct gspca_dev *gspca_dev = |
509 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); |
510 | |
511 | gspca_dev->usb_err = 0; |
512 | |
513 | if (!gspca_dev->streaming) |
514 | return 0; |
515 | |
516 | switch (ctrl->id) { |
517 | case V4L2_CID_BRIGHTNESS: |
518 | setbrightness(gspca_dev, val: ctrl->val); |
519 | break; |
520 | case V4L2_CID_CONTRAST: |
521 | setcontrast(gspca_dev, val: ctrl->val); |
522 | break; |
523 | case V4L2_CID_SATURATION: |
524 | setcolors(gspca_dev, val: ctrl->val); |
525 | break; |
526 | case V4L2_CID_HUE: |
527 | sethue(gspca_dev, val: ctrl->val); |
528 | break; |
529 | } |
530 | return gspca_dev->usb_err; |
531 | } |
532 | |
533 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { |
534 | .s_ctrl = sd_s_ctrl, |
535 | }; |
536 | |
537 | static int sd_init_controls(struct gspca_dev *gspca_dev) |
538 | { |
539 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; |
540 | |
541 | gspca_dev->vdev.ctrl_handler = hdl; |
542 | v4l2_ctrl_handler_init(hdl, 4); |
543 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
544 | V4L2_CID_BRIGHTNESS, min: 0, max: 255, step: 1, def: 128); |
545 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
546 | V4L2_CID_CONTRAST, min: 0, max: 255, step: 1, def: 0x47); |
547 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
548 | V4L2_CID_SATURATION, min: 0, max: 255, step: 1, def: 0x40); |
549 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
550 | V4L2_CID_HUE, min: 0, max: 255, step: 1, def: 0); |
551 | |
552 | if (hdl->error) { |
553 | pr_err("Could not initialize controls\n" ); |
554 | return hdl->error; |
555 | } |
556 | return 0; |
557 | } |
558 | |
559 | /* sub-driver description */ |
560 | static const struct sd_desc sd_desc = { |
561 | .name = MODULE_NAME, |
562 | .config = sd_config, |
563 | .init = sd_init, |
564 | .init_controls = sd_init_controls, |
565 | .start = sd_start, |
566 | .stopN = sd_stopN, |
567 | .pkt_scan = sd_pkt_scan, |
568 | }; |
569 | |
570 | /* -- module initialisation -- */ |
571 | static const struct usb_device_id device_table[] = { |
572 | {USB_DEVICE(0x06e1, 0xa190)}, |
573 | /* {USB_DEVICE(0x0733, 0x0430)}, FIXME: may be IntelPCCameraPro BRIDGE_SPCA505 */ |
574 | {USB_DEVICE(0x0734, 0x043b)}, |
575 | {USB_DEVICE(0x99fa, 0x8988)}, |
576 | {} |
577 | }; |
578 | MODULE_DEVICE_TABLE(usb, device_table); |
579 | |
580 | /* -- device connect -- */ |
581 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) |
582 | { |
583 | return gspca_dev_probe(intf, id, sd_desc: &sd_desc, dev_size: sizeof(struct sd), |
584 | THIS_MODULE); |
585 | } |
586 | |
587 | static struct usb_driver sd_driver = { |
588 | .name = MODULE_NAME, |
589 | .id_table = device_table, |
590 | .probe = sd_probe, |
591 | .disconnect = gspca_disconnect, |
592 | #ifdef CONFIG_PM |
593 | .suspend = gspca_suspend, |
594 | .resume = gspca_resume, |
595 | .reset_resume = gspca_resume, |
596 | #endif |
597 | }; |
598 | |
599 | module_usb_driver(sd_driver); |
600 | |