blob: f9da55b20fa37cac2b219fef821e1123eb4b1d24 [file] [log] [blame]
Kyle Guinnd661e622009-01-16 05:36:14 -03001/*
2 * Mars MR97310A library
3 *
4 * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "mr97310a"
22
23#include "gspca.h"
24
25MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>");
26MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
27MODULE_LICENSE("GPL");
28
29/* specific webcam descriptor */
30struct sd {
31 struct gspca_dev gspca_dev; /* !! must be the first item */
Kyle Guinnd661e622009-01-16 05:36:14 -030032 u8 sof_read;
Kyle Guinnd661e622009-01-16 05:36:14 -030033};
34
35/* V4L2 controls supported by the driver */
36static struct ctrl sd_ctrls[] = {
37};
38
39static const struct v4l2_pix_format vga_mode[] = {
40 {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
41 .bytesperline = 160,
42 .sizeimage = 160 * 120,
43 .colorspace = V4L2_COLORSPACE_SRGB,
44 .priv = 4},
45 {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
46 .bytesperline = 176,
47 .sizeimage = 176 * 144,
48 .colorspace = V4L2_COLORSPACE_SRGB,
49 .priv = 3},
50 {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
51 .bytesperline = 320,
52 .sizeimage = 320 * 240,
53 .colorspace = V4L2_COLORSPACE_SRGB,
54 .priv = 2},
55 {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
56 .bytesperline = 352,
57 .sizeimage = 352 * 288,
58 .colorspace = V4L2_COLORSPACE_SRGB,
59 .priv = 1},
60 {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
61 .bytesperline = 640,
62 .sizeimage = 640 * 480,
63 .colorspace = V4L2_COLORSPACE_SRGB,
64 .priv = 0},
65};
66
67/* the bytes to write are in gspca_dev->usb_buf */
68static int reg_w(struct gspca_dev *gspca_dev, int len)
69{
70 int rc;
71
72 rc = usb_bulk_msg(gspca_dev->dev,
73 usb_sndbulkpipe(gspca_dev->dev, 4),
Jean-Francois Moine92e8c912009-02-02 16:25:38 -030074 gspca_dev->usb_buf, len, NULL, 500);
Kyle Guinnd661e622009-01-16 05:36:14 -030075 if (rc < 0)
76 PDEBUG(D_ERR, "reg write [%02x] error %d",
77 gspca_dev->usb_buf[0], rc);
78 return rc;
79}
80
81/* this function is called at probe time */
82static int sd_config(struct gspca_dev *gspca_dev,
83 const struct usb_device_id *id)
84{
85 struct cam *cam;
86
87 cam = &gspca_dev->cam;
88 cam->cam_mode = vga_mode;
89 cam->nmodes = ARRAY_SIZE(vga_mode);
90 return 0;
91}
92
93/* this function is called at probe and resume time */
94static int sd_init(struct gspca_dev *gspca_dev)
95{
96 return 0;
97}
98
99static int sd_start(struct gspca_dev *gspca_dev)
100{
101 struct sd *sd = (struct sd *) gspca_dev;
102 __u8 *data = gspca_dev->usb_buf;
103 int err_code;
104
105 sd->sof_read = 0;
106
107 /* Note: register descriptions guessed from MR97113A driver */
108
109 data[0] = 0x01;
110 data[1] = 0x01;
111 err_code = reg_w(gspca_dev, 2);
112 if (err_code < 0)
113 return err_code;
114
115 data[0] = 0x00;
116 data[1] = 0x0d;
117 data[2] = 0x01;
118 data[5] = 0x2b;
119 data[7] = 0x00;
120 data[9] = 0x50; /* reg 8, no scale down */
121 data[10] = 0xc0;
122
123 switch (gspca_dev->width) {
124 case 160:
125 data[9] |= 0x0c; /* reg 8, 4:1 scale down */
126 /* fall thru */
127 case 320:
128 data[9] |= 0x04; /* reg 8, 2:1 scale down */
129 /* fall thru */
130 case 640:
131 default:
132 data[3] = 0x50; /* reg 2, H size */
133 data[4] = 0x78; /* reg 3, V size */
134 data[6] = 0x04; /* reg 5, H start */
135 data[8] = 0x03; /* reg 7, V start */
136 break;
137
138 case 176:
139 data[9] |= 0x04; /* reg 8, 2:1 scale down */
140 /* fall thru */
141 case 352:
142 data[3] = 0x2c; /* reg 2, H size */
143 data[4] = 0x48; /* reg 3, V size */
144 data[6] = 0x94; /* reg 5, H start */
145 data[8] = 0x63; /* reg 7, V start */
146 break;
147 }
148
149 err_code = reg_w(gspca_dev, 11);
150 if (err_code < 0)
151 return err_code;
152
153 data[0] = 0x0a;
154 data[1] = 0x80;
155 err_code = reg_w(gspca_dev, 2);
156 if (err_code < 0)
157 return err_code;
158
159 data[0] = 0x14;
160 data[1] = 0x0a;
161 err_code = reg_w(gspca_dev, 2);
162 if (err_code < 0)
163 return err_code;
164
165 data[0] = 0x1b;
166 data[1] = 0x00;
167 err_code = reg_w(gspca_dev, 2);
168 if (err_code < 0)
169 return err_code;
170
171 data[0] = 0x15;
172 data[1] = 0x16;
173 err_code = reg_w(gspca_dev, 2);
174 if (err_code < 0)
175 return err_code;
176
177 data[0] = 0x16;
178 data[1] = 0x10;
179 err_code = reg_w(gspca_dev, 2);
180 if (err_code < 0)
181 return err_code;
182
183 data[0] = 0x17;
184 data[1] = 0x3a;
185 err_code = reg_w(gspca_dev, 2);
186 if (err_code < 0)
187 return err_code;
188
189 data[0] = 0x18;
190 data[1] = 0x68;
191 err_code = reg_w(gspca_dev, 2);
192 if (err_code < 0)
193 return err_code;
194
195 data[0] = 0x1f;
196 data[1] = 0x00;
197 data[2] = 0x02;
198 data[3] = 0x06;
199 data[4] = 0x59;
200 data[5] = 0x0c;
201 data[6] = 0x16;
202 data[7] = 0x00;
203 data[8] = 0x07;
204 data[9] = 0x00;
205 data[10] = 0x01;
206 err_code = reg_w(gspca_dev, 11);
207 if (err_code < 0)
208 return err_code;
209
210 data[0] = 0x1f;
211 data[1] = 0x04;
212 data[2] = 0x11;
213 data[3] = 0x01;
214 err_code = reg_w(gspca_dev, 4);
215 if (err_code < 0)
216 return err_code;
217
218 data[0] = 0x1f;
219 data[1] = 0x00;
220 data[2] = 0x0a;
221 data[3] = 0x00;
222 data[4] = 0x01;
223 data[5] = 0x00;
224 data[6] = 0x00;
225 data[7] = 0x01;
226 data[8] = 0x00;
227 data[9] = 0x0a;
228 err_code = reg_w(gspca_dev, 10);
229 if (err_code < 0)
230 return err_code;
231
232 data[0] = 0x1f;
233 data[1] = 0x04;
234 data[2] = 0x11;
235 data[3] = 0x01;
236 err_code = reg_w(gspca_dev, 4);
237 if (err_code < 0)
238 return err_code;
239
240 data[0] = 0x1f;
241 data[1] = 0x00;
242 data[2] = 0x12;
243 data[3] = 0x00;
244 data[4] = 0x63;
245 data[5] = 0x00;
246 data[6] = 0x70;
247 data[7] = 0x00;
Kyle Guinnceb35be2009-01-17 04:32:32 -0300248 data[8] = 0x00;
249 err_code = reg_w(gspca_dev, 9);
Kyle Guinnd661e622009-01-16 05:36:14 -0300250 if (err_code < 0)
251 return err_code;
252
253 data[0] = 0x1f;
254 data[1] = 0x04;
255 data[2] = 0x11;
256 data[3] = 0x01;
257 err_code = reg_w(gspca_dev, 4);
258 if (err_code < 0)
259 return err_code;
260
261 data[0] = 0x00;
262 data[1] = 0x4d; /* ISOC transfering enable... */
263 err_code = reg_w(gspca_dev, 2);
264 return err_code;
265}
266
267static void sd_stopN(struct gspca_dev *gspca_dev)
268{
269 int result;
270
271 gspca_dev->usb_buf[0] = 1;
272 gspca_dev->usb_buf[1] = 0;
273 result = reg_w(gspca_dev, 2);
274 if (result < 0)
275 PDEBUG(D_ERR, "Camera Stop failed");
276}
277
278/* Include pac common sof detection functions */
279#include "pac_common.h"
280
281static void sd_pkt_scan(struct gspca_dev *gspca_dev,
282 struct gspca_frame *frame, /* target */
283 __u8 *data, /* isoc packet */
284 int len) /* iso packet length */
285{
Kyle Guinnd661e622009-01-16 05:36:14 -0300286 unsigned char *sof;
287
288 sof = pac_find_sof(gspca_dev, data, len);
289 if (sof) {
290 int n;
291
292 /* finish decoding current frame */
293 n = sof - data;
294 if (n > sizeof pac_sof_marker)
295 n -= sizeof pac_sof_marker;
296 else
297 n = 0;
298 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
299 data, n);
Theodore Kilgore9832d762009-03-13 13:04:31 -0300300 /* Start next frame. */
301 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
302 pac_sof_marker, sizeof pac_sof_marker);
Kyle Guinnd661e622009-01-16 05:36:14 -0300303 len -= sof - data;
304 data = sof;
305 }
Kyle Guinnd661e622009-01-16 05:36:14 -0300306 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
307}
308
309/* sub-driver description */
310static const struct sd_desc sd_desc = {
311 .name = MODULE_NAME,
312 .ctrls = sd_ctrls,
313 .nctrls = ARRAY_SIZE(sd_ctrls),
314 .config = sd_config,
315 .init = sd_init,
316 .start = sd_start,
317 .stopN = sd_stopN,
318 .pkt_scan = sd_pkt_scan,
319};
320
321/* -- module initialisation -- */
322static const __devinitdata struct usb_device_id device_table[] = {
323 {USB_DEVICE(0x08ca, 0x0111)},
324 {}
325};
326MODULE_DEVICE_TABLE(usb, device_table);
327
328/* -- device connect -- */
329static int sd_probe(struct usb_interface *intf,
330 const struct usb_device_id *id)
331{
332 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
333 THIS_MODULE);
334}
335
336static struct usb_driver sd_driver = {
337 .name = MODULE_NAME,
338 .id_table = device_table,
339 .probe = sd_probe,
340 .disconnect = gspca_disconnect,
341#ifdef CONFIG_PM
342 .suspend = gspca_suspend,
343 .resume = gspca_resume,
344#endif
345};
346
347/* -- module insert / remove -- */
348static int __init sd_mod_init(void)
349{
Alexey Klimov5d3fa302009-03-27 15:57:46 -0300350 int ret;
351
352 ret = usb_register(&sd_driver);
353 if (ret < 0)
354 return ret;
Kyle Guinnd661e622009-01-16 05:36:14 -0300355 PDEBUG(D_PROBE, "registered");
356 return 0;
357}
358static void __exit sd_mod_exit(void)
359{
360 usb_deregister(&sd_driver);
361 PDEBUG(D_PROBE, "deregistered");
362}
363
364module_init(sd_mod_init);
365module_exit(sd_mod_exit);