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