1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/kthread.h>
22#include "m5602_s5k83a.h"
23
24static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl);
25
26static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = {
27 .s_ctrl = s5k83a_s_ctrl,
28};
29
30static struct v4l2_pix_format s5k83a_modes[] = {
31 {
32 640,
33 480,
34 V4L2_PIX_FMT_SBGGR8,
35 V4L2_FIELD_NONE,
36 .sizeimage =
37 640 * 480,
38 .bytesperline = 640,
39 .colorspace = V4L2_COLORSPACE_SRGB,
40 .priv = 0
41 }
42};
43
44static void s5k83a_dump_registers(struct sd *sd);
45static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
46static int s5k83a_set_led_indication(struct sd *sd, u8 val);
47static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
48 __s32 vflip, __s32 hflip);
49
50int s5k83a_probe(struct sd *sd)
51{
52 u8 prod_id = 0, ver_id = 0;
53 int i, err = 0;
54 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
55
56 if (force_sensor) {
57 if (force_sensor == S5K83A_SENSOR) {
58 pr_info("Forcing a %s sensor\n", s5k83a.name);
59 goto sensor_found;
60 }
61
62
63 return -ENODEV;
64 }
65
66 PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
67
68
69 for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
70 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
71 if (preinit_s5k83a[i][0] == SENSOR)
72 err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
73 data, 2);
74 else
75 err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
76 data[0]);
77 }
78
79
80
81
82 if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
83 return -ENODEV;
84
85 if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
86 return -ENODEV;
87
88 if ((prod_id == 0xff) || (ver_id == 0xff))
89 return -ENODEV;
90 else
91 pr_info("Detected a s5k83a sensor\n");
92
93sensor_found:
94 sd->gspca_dev.cam.cam_mode = s5k83a_modes;
95 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
96
97
98 sd->rotation_thread = NULL;
99
100 return 0;
101}
102
103int s5k83a_init(struct sd *sd)
104{
105 int i, err = 0;
106
107 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
108 u8 data[2] = {0x00, 0x00};
109
110 switch (init_s5k83a[i][0]) {
111 case BRIDGE:
112 err = m5602_write_bridge(sd,
113 init_s5k83a[i][1],
114 init_s5k83a[i][2]);
115 break;
116
117 case SENSOR:
118 data[0] = init_s5k83a[i][2];
119 err = m5602_write_sensor(sd,
120 init_s5k83a[i][1], data, 1);
121 break;
122
123 case SENSOR_LONG:
124 data[0] = init_s5k83a[i][2];
125 data[1] = init_s5k83a[i][3];
126 err = m5602_write_sensor(sd,
127 init_s5k83a[i][1], data, 2);
128 break;
129 default:
130 pr_info("Invalid stream command, exiting init\n");
131 return -EINVAL;
132 }
133 }
134
135 if (dump_sensor)
136 s5k83a_dump_registers(sd);
137
138 return err;
139}
140
141int s5k83a_init_controls(struct sd *sd)
142{
143 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
144
145 sd->gspca_dev.vdev.ctrl_handler = hdl;
146 v4l2_ctrl_handler_init(hdl, 6);
147
148 v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_BRIGHTNESS,
149 0, 255, 1, S5K83A_DEFAULT_BRIGHTNESS);
150
151 v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_EXPOSURE,
152 0, S5K83A_MAXIMUM_EXPOSURE, 1,
153 S5K83A_DEFAULT_EXPOSURE);
154
155 v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_GAIN,
156 0, 255, 1, S5K83A_DEFAULT_GAIN);
157
158 sd->hflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_HFLIP,
159 0, 1, 1, 0);
160 sd->vflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_VFLIP,
161 0, 1, 1, 0);
162
163 if (hdl->error) {
164 pr_err("Could not initialize controls\n");
165 return hdl->error;
166 }
167
168 v4l2_ctrl_cluster(2, &sd->hflip);
169
170 return 0;
171}
172
173static int rotation_thread_function(void *data)
174{
175 struct sd *sd = (struct sd *) data;
176 u8 reg, previous_rotation = 0;
177 __s32 vflip, hflip;
178
179 set_current_state(TASK_INTERRUPTIBLE);
180 while (!schedule_timeout(100)) {
181 if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
182 break;
183
184 s5k83a_get_rotation(sd, ®);
185 if (previous_rotation != reg) {
186 previous_rotation = reg;
187 pr_info("Camera was flipped\n");
188
189 hflip = sd->hflip->val;
190 vflip = sd->vflip->val;
191
192 if (reg) {
193 vflip = !vflip;
194 hflip = !hflip;
195 }
196 s5k83a_set_flip_real((struct gspca_dev *) sd,
197 vflip, hflip);
198 }
199
200 mutex_unlock(&sd->gspca_dev.usb_lock);
201 set_current_state(TASK_INTERRUPTIBLE);
202 }
203
204
205 if (previous_rotation) {
206 hflip = sd->hflip->val;
207 vflip = sd->vflip->val;
208 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
209 }
210
211 sd->rotation_thread = NULL;
212 return 0;
213}
214
215int s5k83a_start(struct sd *sd)
216{
217 int i, err = 0;
218
219
220
221
222 sd->rotation_thread = kthread_create(rotation_thread_function,
223 sd, "rotation thread");
224 wake_up_process(sd->rotation_thread);
225
226
227 for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
228 u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
229 if (start_s5k83a[i][0] == SENSOR)
230 err = m5602_write_sensor(sd, start_s5k83a[i][1],
231 data, 2);
232 else
233 err = m5602_write_bridge(sd, start_s5k83a[i][1],
234 data[0]);
235 }
236 if (err < 0)
237 return err;
238
239 return s5k83a_set_led_indication(sd, 1);
240}
241
242int s5k83a_stop(struct sd *sd)
243{
244 if (sd->rotation_thread)
245 kthread_stop(sd->rotation_thread);
246
247 return s5k83a_set_led_indication(sd, 0);
248}
249
250void s5k83a_disconnect(struct sd *sd)
251{
252 s5k83a_stop(sd);
253
254 sd->sensor = NULL;
255}
256
257static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
258{
259 int err;
260 u8 data[2];
261 struct sd *sd = (struct sd *) gspca_dev;
262
263 data[0] = 0x00;
264 data[1] = 0x20;
265 err = m5602_write_sensor(sd, 0x14, data, 2);
266 if (err < 0)
267 return err;
268
269 data[0] = 0x01;
270 data[1] = 0x00;
271 err = m5602_write_sensor(sd, 0x0d, data, 2);
272 if (err < 0)
273 return err;
274
275
276
277 data[0] = val >> 3;
278 data[1] = val >> 1;
279 err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
280
281 return err;
282}
283
284static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
285{
286 int err;
287 u8 data[1];
288 struct sd *sd = (struct sd *) gspca_dev;
289
290 data[0] = val;
291 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
292 return err;
293}
294
295static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
296{
297 int err;
298 u8 data[2];
299 struct sd *sd = (struct sd *) gspca_dev;
300
301 data[0] = 0;
302 data[1] = val;
303 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
304 return err;
305}
306
307static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
308 __s32 vflip, __s32 hflip)
309{
310 int err;
311 u8 data[1];
312 struct sd *sd = (struct sd *) gspca_dev;
313
314 data[0] = 0x05;
315 err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
316 if (err < 0)
317 return err;
318
319
320 data[0] = S5K83A_FLIP_MASK;
321 data[0] = (vflip) ? data[0] | 0x40 : data[0];
322 data[0] = (hflip) ? data[0] | 0x80 : data[0];
323
324 err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
325 if (err < 0)
326 return err;
327
328 data[0] = (vflip) ? 0x0b : 0x0a;
329 err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
330 if (err < 0)
331 return err;
332
333 data[0] = (hflip) ? 0x0a : 0x0b;
334 err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
335 return err;
336}
337
338static int s5k83a_set_hvflip(struct gspca_dev *gspca_dev)
339{
340 int err;
341 u8 reg;
342 struct sd *sd = (struct sd *) gspca_dev;
343 int hflip = sd->hflip->val;
344 int vflip = sd->vflip->val;
345
346 err = s5k83a_get_rotation(sd, ®);
347 if (err < 0)
348 return err;
349 if (reg) {
350 hflip = !hflip;
351 vflip = !vflip;
352 }
353
354 err = s5k83a_set_flip_real(gspca_dev, vflip, hflip);
355 return err;
356}
357
358static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl)
359{
360 struct gspca_dev *gspca_dev =
361 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
362 int err;
363
364 if (!gspca_dev->streaming)
365 return 0;
366
367 switch (ctrl->id) {
368 case V4L2_CID_BRIGHTNESS:
369 err = s5k83a_set_brightness(gspca_dev, ctrl->val);
370 break;
371 case V4L2_CID_EXPOSURE:
372 err = s5k83a_set_exposure(gspca_dev, ctrl->val);
373 break;
374 case V4L2_CID_GAIN:
375 err = s5k83a_set_gain(gspca_dev, ctrl->val);
376 break;
377 case V4L2_CID_HFLIP:
378 err = s5k83a_set_hvflip(gspca_dev);
379 break;
380 default:
381 return -EINVAL;
382 }
383
384 return err;
385}
386
387static int s5k83a_set_led_indication(struct sd *sd, u8 val)
388{
389 int err = 0;
390 u8 data[1];
391
392 err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
393 if (err < 0)
394 return err;
395
396 if (val)
397 data[0] = data[0] | S5K83A_GPIO_LED_MASK;
398 else
399 data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
400
401 err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
402
403 return err;
404}
405
406
407static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
408{
409 int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
410 *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
411 return err;
412}
413
414static void s5k83a_dump_registers(struct sd *sd)
415{
416 int address;
417 u8 page, old_page;
418 m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
419
420 for (page = 0; page < 16; page++) {
421 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
422 pr_info("Dumping the s5k83a register state for page 0x%x\n",
423 page);
424 for (address = 0; address <= 0xff; address++) {
425 u8 val = 0;
426 m5602_read_sensor(sd, address, &val, 1);
427 pr_info("register 0x%x contains 0x%x\n", address, val);
428 }
429 }
430 pr_info("s5k83a register state dump complete\n");
431
432 for (page = 0; page < 16; page++) {
433 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
434 pr_info("Probing for which registers that are read/write for page 0x%x\n",
435 page);
436 for (address = 0; address <= 0xff; address++) {
437 u8 old_val, ctrl_val, test_val = 0xff;
438
439 m5602_read_sensor(sd, address, &old_val, 1);
440 m5602_write_sensor(sd, address, &test_val, 1);
441 m5602_read_sensor(sd, address, &ctrl_val, 1);
442
443 if (ctrl_val == test_val)
444 pr_info("register 0x%x is writeable\n",
445 address);
446 else
447 pr_info("register 0x%x is read only\n",
448 address);
449
450
451 m5602_write_sensor(sd, address, &old_val, 1);
452 }
453 }
454 pr_info("Read/write register probing complete\n");
455 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
456}
457