]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/dream/camera/mt9d112.c
staging: Final semaphore cleanup
[net-next-2.6.git] / drivers / staging / dream / camera / mt9d112.c
CommitLineData
eb7b797b
BS
1/*
2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
3 */
4
5#include <linux/delay.h>
5a0e3ad6 6#include <linux/slab.h>
eb7b797b
BS
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
25struct mt9d112_work {
26 struct work_struct work;
27};
28
29static struct mt9d112_work *mt9d112_sensorw;
30static struct i2c_client *mt9d112_client;
31
32struct mt9d112_ctrl {
33 const struct msm_camera_sensor_info *sensordata;
34};
35
36
37static struct mt9d112_ctrl *mt9d112_ctrl;
38
39static DECLARE_WAIT_QUEUE_HEAD(mt9d112_wait_queue);
45f4d024 40DEFINE_SEMAPHORE(mt9d112_sem);
eb7b797b
BS
41
42
43/*=============================================================
44 EXTERNAL DECLARATIONS
45==============================================================*/
46extern struct mt9d112_reg mt9d112_regs;
47
48
49/*=============================================================*/
50
51static 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
67static 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
87static 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
124static 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
145static 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
171static 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
205static 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
213static 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
274static 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
382static 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
509static 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
578init_probe_fail:
579 return rc;
580}
581
582int 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
608init_done:
609 return rc;
610
611init_fail:
612 kfree(mt9d112_ctrl);
613 return rc;
614}
615
616static 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
623int 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
660int 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
672static 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
697probe_failure:
698 kfree(mt9d112_sensorw);
699 mt9d112_sensorw = NULL;
700 CDBG("mt9d112_probe failed!\n");
701 return rc;
702}
703
704static const struct i2c_device_id mt9d112_i2c_id[] = {
705 { "mt9d112", 0},
706 { },
707};
708
709static 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
718static 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
739probe_done:
740 CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
741 return rc;
742}
743
744static int __mt9d112_probe(struct platform_device *pdev)
745{
746 return msm_camera_drv_start(pdev, mt9d112_sensor_probe);
747}
748
749static struct platform_driver msm_camera_driver = {
750 .probe = __mt9d112_probe,
751 .driver = {
752 .name = "msm_camera_mt9d112",
753 .owner = THIS_MODULE,
754 },
755};
756
757static int __init mt9d112_init(void)
758{
759 return platform_driver_register(&msm_camera_driver);
760}
761
762module_init(mt9d112_init);