1
2
3
4
5#include <linux/delay.h>
6#include <linux/types.h>
7#include <linux/i2c.h>
8#include <linux/uaccess.h>
9#include <linux/miscdevice.h>
10#include <media/msm_camera.h>
11#include <mach/gpio.h>
12#include "mt9d112.h"
13
14
15
16#define REG_MT9D112_MODEL_ID 0x3000
17#define MT9D112_MODEL_ID 0x1580
18
19
20#define REG_MT9D112_SENSOR_RESET 0x301A
21#define REG_MT9D112_STANDBY_CONTROL 0x3202
22#define REG_MT9D112_MCU_BOOT 0x3386
23
24struct mt9d112_work {
25 struct work_struct work;
26};
27
28static struct mt9d112_work *mt9d112_sensorw;
29static struct i2c_client *mt9d112_client;
30
31struct mt9d112_ctrl {
32 const struct msm_camera_sensor_info *sensordata;
33};
34
35
36static struct mt9d112_ctrl *mt9d112_ctrl;
37
38static DECLARE_WAIT_QUEUE_HEAD(mt9d112_wait_queue);
39DECLARE_MUTEX(mt9d112_sem);
40
41
42
43
44
45extern struct mt9d112_reg mt9d112_regs;
46
47
48
49
50static int mt9d112_reset(const struct msm_camera_sensor_info *dev)
51{
52 int rc = 0;
53
54 rc = gpio_request(dev->sensor_reset, "mt9d112");
55
56 if (!rc) {
57 rc = gpio_direction_output(dev->sensor_reset, 0);
58 mdelay(20);
59 rc = gpio_direction_output(dev->sensor_reset, 1);
60 }
61
62 gpio_free(dev->sensor_reset);
63 return rc;
64}
65
66static int32_t mt9d112_i2c_txdata(unsigned short saddr,
67 unsigned char *txdata, int length)
68{
69 struct i2c_msg msg[] = {
70 {
71 .addr = saddr,
72 .flags = 0,
73 .len = length,
74 .buf = txdata,
75 },
76 };
77
78 if (i2c_transfer(mt9d112_client->adapter, msg, 1) < 0) {
79 CDBG("mt9d112_i2c_txdata failed\n");
80 return -EIO;
81 }
82
83 return 0;
84}
85
86static int32_t mt9d112_i2c_write(unsigned short saddr,
87 unsigned short waddr, unsigned short wdata, enum mt9d112_width width)
88{
89 int32_t rc = -EIO;
90 unsigned char buf[4];
91
92 memset(buf, 0, sizeof(buf));
93 switch (width) {
94 case WORD_LEN: {
95 buf[0] = (waddr & 0xFF00)>>8;
96 buf[1] = (waddr & 0x00FF);
97 buf[2] = (wdata & 0xFF00)>>8;
98 buf[3] = (wdata & 0x00FF);
99
100 rc = mt9d112_i2c_txdata(saddr, buf, 4);
101 }
102 break;
103
104 case BYTE_LEN: {
105 buf[0] = waddr;
106 buf[1] = wdata;
107 rc = mt9d112_i2c_txdata(saddr, buf, 2);
108 }
109 break;
110
111 default:
112 break;
113 }
114
115 if (rc < 0)
116 CDBG(
117 "i2c_write failed, addr = 0x%x, val = 0x%x!\n",
118 waddr, wdata);
119
120 return rc;
121}
122
123static int32_t mt9d112_i2c_write_table(
124 struct mt9d112_i2c_reg_conf const *reg_conf_tbl,
125 int num_of_items_in_table)
126{
127 int i;
128 int32_t rc = -EIO;
129
130 for (i = 0; i < num_of_items_in_table; i++) {
131 rc = mt9d112_i2c_write(mt9d112_client->addr,
132 reg_conf_tbl->waddr, reg_conf_tbl->wdata,
133 reg_conf_tbl->width);
134 if (rc < 0)
135 break;
136 if (reg_conf_tbl->mdelay_time != 0)
137 mdelay(reg_conf_tbl->mdelay_time);
138 reg_conf_tbl++;
139 }
140
141 return rc;
142}
143
144static int mt9d112_i2c_rxdata(unsigned short saddr,
145 unsigned char *rxdata, int length)
146{
147 struct i2c_msg msgs[] = {
148 {
149 .addr = saddr,
150 .flags = 0,
151 .len = 2,
152 .buf = rxdata,
153 },
154 {
155 .addr = saddr,
156 .flags = I2C_M_RD,
157 .len = length,
158 .buf = rxdata,
159 },
160 };
161
162 if (i2c_transfer(mt9d112_client->adapter, msgs, 2) < 0) {
163 CDBG("mt9d112_i2c_rxdata failed!\n");
164 return -EIO;
165 }
166
167 return 0;
168}
169
170static int32_t mt9d112_i2c_read(unsigned short saddr,
171 unsigned short raddr, unsigned short *rdata, enum mt9d112_width width)
172{
173 int32_t rc = 0;
174 unsigned char buf[4];
175
176 if (!rdata)
177 return -EIO;
178
179 memset(buf, 0, sizeof(buf));
180
181 switch (width) {
182 case WORD_LEN: {
183 buf[0] = (raddr & 0xFF00)>>8;
184 buf[1] = (raddr & 0x00FF);
185
186 rc = mt9d112_i2c_rxdata(saddr, buf, 2);
187 if (rc < 0)
188 return rc;
189
190 *rdata = buf[0] << 8 | buf[1];
191 }
192 break;
193
194 default:
195 break;
196 }
197
198 if (rc < 0)
199 CDBG("mt9d112_i2c_read failed!\n");
200
201 return rc;
202}
203
204static int32_t mt9d112_set_lens_roll_off(void)
205{
206 int32_t rc = 0;
207 rc = mt9d112_i2c_write_table(&mt9d112_regs.rftbl[0],
208 mt9d112_regs.rftbl_size);
209 return rc;
210}
211
212static long mt9d112_reg_init(void)
213{
214 int32_t array_length;
215 int32_t i;
216 long rc;
217
218
219 rc = mt9d112_i2c_write_table(&mt9d112_regs.plltbl[0],
220 mt9d112_regs.plltbl_size);
221
222 if (rc < 0)
223 return rc;
224
225
226 array_length = mt9d112_regs.prev_snap_reg_settings_size;
227
228
229 for (i = 0; i < array_length; i++) {
230 rc = mt9d112_i2c_write(mt9d112_client->addr,
231 mt9d112_regs.prev_snap_reg_settings[i].register_address,
232 mt9d112_regs.prev_snap_reg_settings[i].register_value,
233 WORD_LEN);
234
235 if (rc < 0)
236 return rc;
237 }
238
239
240 array_length = mt9d112_regs.noise_reduction_reg_settings_size;
241
242 for (i = 0; i < array_length; i++) {
243 rc = mt9d112_i2c_write(mt9d112_client->addr,
244 mt9d112_regs.noise_reduction_reg_settings[i].register_address,
245 mt9d112_regs.noise_reduction_reg_settings[i].register_value,
246 WORD_LEN);
247
248 if (rc < 0)
249 return rc;
250 }
251
252
253 rc =
254 mt9d112_i2c_write(mt9d112_client->addr,
255 0x35A4,
256 0x0593,
257 WORD_LEN);
258 if (rc < 0)
259 return rc;
260
261 rc = mt9d112_i2c_write_table(&mt9d112_regs.stbl[0],
262 mt9d112_regs.stbl_size);
263 if (rc < 0)
264 return rc;
265
266 rc = mt9d112_set_lens_roll_off();
267 if (rc < 0)
268 return rc;
269
270 return 0;
271}
272
273static long mt9d112_set_sensor_mode(int mode)
274{
275 uint16_t clock;
276 long rc = 0;
277
278 switch (mode) {
279 case SENSOR_PREVIEW_MODE:
280 rc =
281 mt9d112_i2c_write(mt9d112_client->addr,
282 0x338C, 0xA20C, WORD_LEN);
283 if (rc < 0)
284 return rc;
285
286 rc =
287 mt9d112_i2c_write(mt9d112_client->addr,
288 0x3390, 0x0004, WORD_LEN);
289 if (rc < 0)
290 return rc;
291
292 rc =
293 mt9d112_i2c_write(mt9d112_client->addr,
294 0x338C, 0xA215, WORD_LEN);
295 if (rc < 0)
296 return rc;
297
298 rc =
299 mt9d112_i2c_write(mt9d112_client->addr,
300 0x3390, 0x0004, WORD_LEN);
301 if (rc < 0)
302 return rc;
303
304 rc =
305 mt9d112_i2c_write(mt9d112_client->addr,
306 0x338C, 0xA20B, WORD_LEN);
307 if (rc < 0)
308 return rc;
309
310 rc =
311 mt9d112_i2c_write(mt9d112_client->addr,
312 0x3390, 0x0000, WORD_LEN);
313 if (rc < 0)
314 return rc;
315
316 clock = 0x0250;
317
318 rc =
319 mt9d112_i2c_write(mt9d112_client->addr,
320 0x341C, clock, WORD_LEN);
321 if (rc < 0)
322 return rc;
323
324 rc =
325 mt9d112_i2c_write(mt9d112_client->addr,
326 0x338C, 0xA103, WORD_LEN);
327 if (rc < 0)
328 return rc;
329
330 rc =
331 mt9d112_i2c_write(mt9d112_client->addr,
332 0x3390, 0x0001, WORD_LEN);
333 if (rc < 0)
334 return rc;
335
336 mdelay(5);
337 break;
338
339 case SENSOR_SNAPSHOT_MODE:
340
341 rc =
342 mt9d112_i2c_write(mt9d112_client->addr,
343 0x341C, 0x0120, WORD_LEN);
344 if (rc < 0)
345 return rc;
346
347 rc =
348 mt9d112_i2c_write(mt9d112_client->addr,
349 0x338C, 0xA120, WORD_LEN);
350 if (rc < 0)
351 return rc;
352
353 rc =
354 mt9d112_i2c_write(mt9d112_client->addr,
355 0x3390, 0x0002, WORD_LEN);
356 if (rc < 0)
357 return rc;
358
359 mdelay(5);
360
361 rc =
362 mt9d112_i2c_write(mt9d112_client->addr,
363 0x338C, 0xA103, WORD_LEN);
364 if (rc < 0)
365 return rc;
366
367 rc =
368 mt9d112_i2c_write(mt9d112_client->addr,
369 0x3390, 0x0002, WORD_LEN);
370 if (rc < 0)
371 return rc;
372 break;
373
374 default:
375 return -EINVAL;
376 }
377
378 return 0;
379}
380
381static long mt9d112_set_effect(int mode, int effect)
382{
383 uint16_t reg_addr;
384 uint16_t reg_val;
385 long rc = 0;
386
387 switch (mode) {
388 case SENSOR_PREVIEW_MODE:
389
390 reg_addr = 0x2799;
391 break;
392
393 case SENSOR_SNAPSHOT_MODE:
394
395 reg_addr = 0x279B;
396 break;
397
398 default:
399 reg_addr = 0x2799;
400 break;
401 }
402
403 switch (effect) {
404 case CAMERA_EFFECT_OFF: {
405 reg_val = 0x6440;
406
407 rc = mt9d112_i2c_write(mt9d112_client->addr,
408 0x338C, reg_addr, WORD_LEN);
409 if (rc < 0)
410 return rc;
411
412 rc = mt9d112_i2c_write(mt9d112_client->addr,
413 0x3390, reg_val, WORD_LEN);
414 if (rc < 0)
415 return rc;
416 }
417 break;
418
419 case CAMERA_EFFECT_MONO: {
420 reg_val = 0x6441;
421 rc = mt9d112_i2c_write(mt9d112_client->addr,
422 0x338C, reg_addr, WORD_LEN);
423 if (rc < 0)
424 return rc;
425
426 rc = mt9d112_i2c_write(mt9d112_client->addr,
427 0x3390, reg_val, WORD_LEN);
428 if (rc < 0)
429 return rc;
430 }
431 break;
432
433 case CAMERA_EFFECT_NEGATIVE: {
434 reg_val = 0x6443;
435 rc = mt9d112_i2c_write(mt9d112_client->addr,
436 0x338C, reg_addr, WORD_LEN);
437 if (rc < 0)
438 return rc;
439
440 rc = mt9d112_i2c_write(mt9d112_client->addr,
441 0x3390, reg_val, WORD_LEN);
442 if (rc < 0)
443 return rc;
444 }
445 break;
446
447 case CAMERA_EFFECT_SOLARIZE: {
448 reg_val = 0x6445;
449 rc = mt9d112_i2c_write(mt9d112_client->addr,
450 0x338C, reg_addr, WORD_LEN);
451 if (rc < 0)
452 return rc;
453
454 rc = mt9d112_i2c_write(mt9d112_client->addr,
455 0x3390, reg_val, WORD_LEN);
456 if (rc < 0)
457 return rc;
458 }
459 break;
460
461 case CAMERA_EFFECT_SEPIA: {
462 reg_val = 0x6442;
463 rc = mt9d112_i2c_write(mt9d112_client->addr,
464 0x338C, reg_addr, WORD_LEN);
465 if (rc < 0)
466 return rc;
467
468 rc = mt9d112_i2c_write(mt9d112_client->addr,
469 0x3390, reg_val, WORD_LEN);
470 if (rc < 0)
471 return rc;
472 }
473 break;
474
475 case CAMERA_EFFECT_PASTEL:
476 case CAMERA_EFFECT_MOSAIC:
477 case CAMERA_EFFECT_RESIZE:
478 return -EINVAL;
479
480 default: {
481 reg_val = 0x6440;
482 rc = mt9d112_i2c_write(mt9d112_client->addr,
483 0x338C, reg_addr, WORD_LEN);
484 if (rc < 0)
485 return rc;
486
487 rc = mt9d112_i2c_write(mt9d112_client->addr,
488 0x3390, reg_val, WORD_LEN);
489 if (rc < 0)
490 return rc;
491
492 return -EINVAL;
493 }
494 }
495
496
497 rc = mt9d112_i2c_write(mt9d112_client->addr,
498 0x338C, 0xA103, WORD_LEN);
499 if (rc < 0)
500 return rc;
501
502 rc = mt9d112_i2c_write(mt9d112_client->addr,
503 0x3390, 0x0005, WORD_LEN);
504
505 return rc;
506}
507
508static int mt9d112_sensor_init_probe(const struct msm_camera_sensor_info *data)
509{
510 uint16_t model_id = 0;
511 int rc = 0;
512
513 CDBG("init entry \n");
514 rc = mt9d112_reset(data);
515 if (rc < 0) {
516 CDBG("reset failed!\n");
517 goto init_probe_fail;
518 }
519
520 mdelay(5);
521
522
523
524 rc = mt9d112_i2c_write(mt9d112_client->addr,
525 REG_MT9D112_MCU_BOOT, 0x0501, WORD_LEN);
526 if (rc < 0)
527 goto init_probe_fail;
528
529
530 rc = mt9d112_i2c_write(mt9d112_client->addr,
531 REG_MT9D112_MCU_BOOT, 0x0500, WORD_LEN);
532 if (rc < 0)
533 goto init_probe_fail;
534
535 mdelay(5);
536
537
538 rc = mt9d112_i2c_write(mt9d112_client->addr,
539 REG_MT9D112_SENSOR_RESET, 0x0ACC, WORD_LEN);
540 if (rc < 0)
541 goto init_probe_fail;
542
543 rc = mt9d112_i2c_write(mt9d112_client->addr,
544 REG_MT9D112_STANDBY_CONTROL, 0x0008, WORD_LEN);
545 if (rc < 0)
546 goto init_probe_fail;
547
548
549 rc = mt9d112_i2c_write(mt9d112_client->addr,
550 0x33F4, 0x031D, WORD_LEN);
551 if (rc < 0)
552 goto init_probe_fail;
553
554 mdelay(5);
555
556
557
558 rc = mt9d112_i2c_read(mt9d112_client->addr,
559 REG_MT9D112_MODEL_ID, &model_id, WORD_LEN);
560 if (rc < 0)
561 goto init_probe_fail;
562
563 CDBG("mt9d112 model_id = 0x%x\n", model_id);
564
565
566 if (model_id != MT9D112_MODEL_ID) {
567 rc = -EINVAL;
568 goto init_probe_fail;
569 }
570
571 rc = mt9d112_reg_init();
572 if (rc < 0)
573 goto init_probe_fail;
574
575 return rc;
576
577init_probe_fail:
578 return rc;
579}
580
581int mt9d112_sensor_init(const struct msm_camera_sensor_info *data)
582{
583 int rc = 0;
584
585 mt9d112_ctrl = kzalloc(sizeof(struct mt9d112_ctrl), GFP_KERNEL);
586 if (!mt9d112_ctrl) {
587 CDBG("mt9d112_init failed!\n");
588 rc = -ENOMEM;
589 goto init_done;
590 }
591
592 if (data)
593 mt9d112_ctrl->sensordata = data;
594
595
596 msm_camio_clk_rate_set(24000000);
597 mdelay(5);
598
599 msm_camio_camif_pad_reg_reset();
600
601 rc = mt9d112_sensor_init_probe(data);
602 if (rc < 0) {
603 CDBG("mt9d112_sensor_init failed!\n");
604 goto init_fail;
605 }
606
607init_done:
608 return rc;
609
610init_fail:
611 kfree(mt9d112_ctrl);
612 return rc;
613}
614
615static int mt9d112_init_client(struct i2c_client *client)
616{
617
618 init_waitqueue_head(&mt9d112_wait_queue);
619 return 0;
620}
621
622int mt9d112_sensor_config(void __user *argp)
623{
624 struct sensor_cfg_data cfg_data;
625 long rc = 0;
626
627 if (copy_from_user(&cfg_data,
628 (void *)argp,
629 sizeof(struct sensor_cfg_data)))
630 return -EFAULT;
631
632
633
634 CDBG("mt9d112_ioctl, cfgtype = %d, mode = %d\n",
635 cfg_data.cfgtype, cfg_data.mode);
636
637 switch (cfg_data.cfgtype) {
638 case CFG_SET_MODE:
639 rc = mt9d112_set_sensor_mode(
640 cfg_data.mode);
641 break;
642
643 case CFG_SET_EFFECT:
644 rc = mt9d112_set_effect(cfg_data.mode,
645 cfg_data.cfg.effect);
646 break;
647
648 case CFG_GET_AF_MAX_STEPS:
649 default:
650 rc = -EINVAL;
651 break;
652 }
653
654
655
656 return rc;
657}
658
659int mt9d112_sensor_release(void)
660{
661 int rc = 0;
662
663
664
665 kfree(mt9d112_ctrl);
666
667
668 return rc;
669}
670
671static int mt9d112_i2c_probe(struct i2c_client *client,
672 const struct i2c_device_id *id)
673{
674 int rc = 0;
675 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
676 rc = -ENOTSUPP;
677 goto probe_failure;
678 }
679
680 mt9d112_sensorw =
681 kzalloc(sizeof(struct mt9d112_work), GFP_KERNEL);
682
683 if (!mt9d112_sensorw) {
684 rc = -ENOMEM;
685 goto probe_failure;
686 }
687
688 i2c_set_clientdata(client, mt9d112_sensorw);
689 mt9d112_init_client(client);
690 mt9d112_client = client;
691
692 CDBG("mt9d112_probe succeeded!\n");
693
694 return 0;
695
696probe_failure:
697 kfree(mt9d112_sensorw);
698 mt9d112_sensorw = NULL;
699 CDBG("mt9d112_probe failed!\n");
700 return rc;
701}
702
703static const struct i2c_device_id mt9d112_i2c_id[] = {
704 { "mt9d112", 0},
705 { },
706};
707
708static struct i2c_driver mt9d112_i2c_driver = {
709 .id_table = mt9d112_i2c_id,
710 .probe = mt9d112_i2c_probe,
711 .remove = __exit_p(mt9d112_i2c_remove),
712 .driver = {
713 .name = "mt9d112",
714 },
715};
716
717static int mt9d112_sensor_probe(const struct msm_camera_sensor_info *info,
718 struct msm_sensor_ctrl *s)
719{
720 int rc = i2c_add_driver(&mt9d112_i2c_driver);
721 if (rc < 0 || mt9d112_client == NULL) {
722 rc = -ENOTSUPP;
723 goto probe_done;
724 }
725
726
727 msm_camio_clk_rate_set(24000000);
728 mdelay(5);
729
730 rc = mt9d112_sensor_init_probe(info);
731 if (rc < 0)
732 goto probe_done;
733
734 s->s_init = mt9d112_sensor_init;
735 s->s_release = mt9d112_sensor_release;
736 s->s_config = mt9d112_sensor_config;
737
738probe_done:
739 CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
740 return rc;
741}
742
743static int __mt9d112_probe(struct platform_device *pdev)
744{
745 return msm_camera_drv_start(pdev, mt9d112_sensor_probe);
746}
747
748static struct platform_driver msm_camera_driver = {
749 .probe = __mt9d112_probe,
750 .driver = {
751 .name = "msm_camera_mt9d112",
752 .owner = THIS_MODULE,
753 },
754};
755
756static int __init mt9d112_init(void)
757{
758 return platform_driver_register(&msm_camera_driver);
759}
760
761module_init(mt9d112_init);
762