2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
5 #include <linux/delay.h>
6 #include <linux/slab.h>
7 #include <linux/types.h>
9 #include <linux/uaccess.h>
10 #include <linux/miscdevice.h>
11 #include <media/msm_camera.h>
12 #include <mach/gpio.h>
15 /* Micron MT9D112 Registers and their values */
16 /* Sensor Core Registers */
17 #define REG_MT9D112_MODEL_ID 0x3000
18 #define MT9D112_MODEL_ID 0x1580
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
26 struct work_struct work
;
29 static struct mt9d112_work
*mt9d112_sensorw
;
30 static struct i2c_client
*mt9d112_client
;
33 const struct msm_camera_sensor_info
*sensordata
;
37 static struct mt9d112_ctrl
*mt9d112_ctrl
;
39 static DECLARE_WAIT_QUEUE_HEAD(mt9d112_wait_queue
);
40 DECLARE_MUTEX(mt9d112_sem
);
43 /*=============================================================
45 ==============================================================*/
46 extern struct mt9d112_reg mt9d112_regs
;
49 /*=============================================================*/
51 static int mt9d112_reset(const struct msm_camera_sensor_info
*dev
)
55 rc
= gpio_request(dev
->sensor_reset
, "mt9d112");
58 rc
= gpio_direction_output(dev
->sensor_reset
, 0);
60 rc
= gpio_direction_output(dev
->sensor_reset
, 1);
63 gpio_free(dev
->sensor_reset
);
67 static int32_t mt9d112_i2c_txdata(unsigned short saddr
,
68 unsigned char *txdata
, int length
)
70 struct i2c_msg msg
[] = {
79 if (i2c_transfer(mt9d112_client
->adapter
, msg
, 1) < 0) {
80 CDBG("mt9d112_i2c_txdata failed\n");
87 static int32_t mt9d112_i2c_write(unsigned short saddr
,
88 unsigned short waddr
, unsigned short wdata
, enum mt9d112_width width
)
93 memset(buf
, 0, sizeof(buf
));
96 buf
[0] = (waddr
& 0xFF00)>>8;
97 buf
[1] = (waddr
& 0x00FF);
98 buf
[2] = (wdata
& 0xFF00)>>8;
99 buf
[3] = (wdata
& 0x00FF);
101 rc
= mt9d112_i2c_txdata(saddr
, buf
, 4);
108 rc
= mt9d112_i2c_txdata(saddr
, buf
, 2);
118 "i2c_write failed, addr = 0x%x, val = 0x%x!\n",
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
)
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
);
137 if (reg_conf_tbl
->mdelay_time
!= 0)
138 mdelay(reg_conf_tbl
->mdelay_time
);
145 static int mt9d112_i2c_rxdata(unsigned short saddr
,
146 unsigned char *rxdata
, int length
)
148 struct i2c_msg msgs
[] = {
163 if (i2c_transfer(mt9d112_client
->adapter
, msgs
, 2) < 0) {
164 CDBG("mt9d112_i2c_rxdata failed!\n");
171 static int32_t mt9d112_i2c_read(unsigned short saddr
,
172 unsigned short raddr
, unsigned short *rdata
, enum mt9d112_width width
)
175 unsigned char buf
[4];
180 memset(buf
, 0, sizeof(buf
));
184 buf
[0] = (raddr
& 0xFF00)>>8;
185 buf
[1] = (raddr
& 0x00FF);
187 rc
= mt9d112_i2c_rxdata(saddr
, buf
, 2);
191 *rdata
= buf
[0] << 8 | buf
[1];
200 CDBG("mt9d112_i2c_read failed!\n");
205 static int32_t mt9d112_set_lens_roll_off(void)
208 rc
= mt9d112_i2c_write_table(&mt9d112_regs
.rftbl
[0],
209 mt9d112_regs
.rftbl_size
);
213 static long mt9d112_reg_init(void)
215 int32_t array_length
;
219 /* PLL Setup Start */
220 rc
= mt9d112_i2c_write_table(&mt9d112_regs
.plltbl
[0],
221 mt9d112_regs
.plltbl_size
);
227 array_length
= mt9d112_regs
.prev_snap_reg_settings_size
;
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
,
240 /* Configure for Noise Reduction, Saturation and Aperture Correction */
241 array_length
= mt9d112_regs
.noise_reduction_reg_settings_size
;
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
,
253 /* Set Color Kill Saturation point to optimum value */
255 mt9d112_i2c_write(mt9d112_client
->addr
,
262 rc
= mt9d112_i2c_write_table(&mt9d112_regs
.stbl
[0],
263 mt9d112_regs
.stbl_size
);
267 rc
= mt9d112_set_lens_roll_off();
274 static long mt9d112_set_sensor_mode(int mode
)
280 case SENSOR_PREVIEW_MODE
:
282 mt9d112_i2c_write(mt9d112_client
->addr
,
283 0x338C, 0xA20C, WORD_LEN
);
288 mt9d112_i2c_write(mt9d112_client
->addr
,
289 0x3390, 0x0004, WORD_LEN
);
294 mt9d112_i2c_write(mt9d112_client
->addr
,
295 0x338C, 0xA215, WORD_LEN
);
300 mt9d112_i2c_write(mt9d112_client
->addr
,
301 0x3390, 0x0004, WORD_LEN
);
306 mt9d112_i2c_write(mt9d112_client
->addr
,
307 0x338C, 0xA20B, WORD_LEN
);
312 mt9d112_i2c_write(mt9d112_client
->addr
,
313 0x3390, 0x0000, WORD_LEN
);
320 mt9d112_i2c_write(mt9d112_client
->addr
,
321 0x341C, clock
, WORD_LEN
);
326 mt9d112_i2c_write(mt9d112_client
->addr
,
327 0x338C, 0xA103, WORD_LEN
);
332 mt9d112_i2c_write(mt9d112_client
->addr
,
333 0x3390, 0x0001, WORD_LEN
);
340 case SENSOR_SNAPSHOT_MODE
:
341 /* Switch to lower fps for Snapshot */
343 mt9d112_i2c_write(mt9d112_client
->addr
,
344 0x341C, 0x0120, WORD_LEN
);
349 mt9d112_i2c_write(mt9d112_client
->addr
,
350 0x338C, 0xA120, WORD_LEN
);
355 mt9d112_i2c_write(mt9d112_client
->addr
,
356 0x3390, 0x0002, WORD_LEN
);
363 mt9d112_i2c_write(mt9d112_client
->addr
,
364 0x338C, 0xA103, WORD_LEN
);
369 mt9d112_i2c_write(mt9d112_client
->addr
,
370 0x3390, 0x0002, WORD_LEN
);
382 static long mt9d112_set_effect(int mode
, int effect
)
389 case SENSOR_PREVIEW_MODE
:
390 /* Context A Special Effects */
394 case SENSOR_SNAPSHOT_MODE
:
395 /* Context B Special Effects */
405 case CAMERA_EFFECT_OFF
: {
408 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
409 0x338C, reg_addr
, WORD_LEN
);
413 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
414 0x3390, reg_val
, WORD_LEN
);
420 case CAMERA_EFFECT_MONO
: {
422 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
423 0x338C, reg_addr
, WORD_LEN
);
427 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
428 0x3390, reg_val
, WORD_LEN
);
434 case CAMERA_EFFECT_NEGATIVE
: {
436 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
437 0x338C, reg_addr
, WORD_LEN
);
441 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
442 0x3390, reg_val
, WORD_LEN
);
448 case CAMERA_EFFECT_SOLARIZE
: {
450 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
451 0x338C, reg_addr
, WORD_LEN
);
455 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
456 0x3390, reg_val
, WORD_LEN
);
462 case CAMERA_EFFECT_SEPIA
: {
464 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
465 0x338C, reg_addr
, WORD_LEN
);
469 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
470 0x3390, reg_val
, WORD_LEN
);
476 case CAMERA_EFFECT_PASTEL
:
477 case CAMERA_EFFECT_MOSAIC
:
478 case CAMERA_EFFECT_RESIZE
:
483 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
484 0x338C, reg_addr
, WORD_LEN
);
488 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
489 0x3390, reg_val
, WORD_LEN
);
497 /* Refresh Sequencer */
498 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
499 0x338C, 0xA103, WORD_LEN
);
503 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
504 0x3390, 0x0005, WORD_LEN
);
509 static int mt9d112_sensor_init_probe(const struct msm_camera_sensor_info
*data
)
511 uint16_t model_id
= 0;
514 CDBG("init entry \n");
515 rc
= mt9d112_reset(data
);
517 CDBG("reset failed!\n");
518 goto init_probe_fail
;
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
);
528 goto init_probe_fail
;
530 /* Pull MCU from Reset - Start MCU */
531 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
532 REG_MT9D112_MCU_BOOT
, 0x0500, WORD_LEN
);
534 goto init_probe_fail
;
538 /* Micron Suggested - Power up block */
539 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
540 REG_MT9D112_SENSOR_RESET
, 0x0ACC, WORD_LEN
);
542 goto init_probe_fail
;
544 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
545 REG_MT9D112_STANDBY_CONTROL
, 0x0008, WORD_LEN
);
547 goto init_probe_fail
;
549 /* FUSED_DEFECT_CORRECTION */
550 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
551 0x33F4, 0x031D, WORD_LEN
);
553 goto init_probe_fail
;
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
);
562 goto init_probe_fail
;
564 CDBG("mt9d112 model_id = 0x%x\n", model_id
);
566 /* Check if it matches it with the value in Datasheet */
567 if (model_id
!= MT9D112_MODEL_ID
) {
569 goto init_probe_fail
;
572 rc
= mt9d112_reg_init();
574 goto init_probe_fail
;
582 int mt9d112_sensor_init(const struct msm_camera_sensor_info
*data
)
586 mt9d112_ctrl
= kzalloc(sizeof(struct mt9d112_ctrl
), GFP_KERNEL
);
588 CDBG("mt9d112_init failed!\n");
594 mt9d112_ctrl
->sensordata
= data
;
596 /* Input MCLK = 24MHz */
597 msm_camio_clk_rate_set(24000000);
600 msm_camio_camif_pad_reg_reset();
602 rc
= mt9d112_sensor_init_probe(data
);
604 CDBG("mt9d112_sensor_init failed!\n");
616 static int mt9d112_init_client(struct i2c_client
*client
)
618 /* Initialize the MSM_CAMI2C Chip */
619 init_waitqueue_head(&mt9d112_wait_queue
);
623 int mt9d112_sensor_config(void __user
*argp
)
625 struct sensor_cfg_data cfg_data
;
628 if (copy_from_user(&cfg_data
,
630 sizeof(struct sensor_cfg_data
)))
633 /* down(&mt9d112_sem); */
635 CDBG("mt9d112_ioctl, cfgtype = %d, mode = %d\n",
636 cfg_data
.cfgtype
, cfg_data
.mode
);
638 switch (cfg_data
.cfgtype
) {
640 rc
= mt9d112_set_sensor_mode(
645 rc
= mt9d112_set_effect(cfg_data
.mode
,
646 cfg_data
.cfg
.effect
);
649 case CFG_GET_AF_MAX_STEPS
:
655 /* up(&mt9d112_sem); */
660 int mt9d112_sensor_release(void)
664 /* down(&mt9d112_sem); */
667 /* up(&mt9d112_sem); */
672 static int mt9d112_i2c_probe(struct i2c_client
*client
,
673 const struct i2c_device_id
*id
)
676 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
682 kzalloc(sizeof(struct mt9d112_work
), GFP_KERNEL
);
684 if (!mt9d112_sensorw
) {
689 i2c_set_clientdata(client
, mt9d112_sensorw
);
690 mt9d112_init_client(client
);
691 mt9d112_client
= client
;
693 CDBG("mt9d112_probe succeeded!\n");
698 kfree(mt9d112_sensorw
);
699 mt9d112_sensorw
= NULL
;
700 CDBG("mt9d112_probe failed!\n");
704 static const struct i2c_device_id mt9d112_i2c_id
[] = {
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
),
718 static int mt9d112_sensor_probe(const struct msm_camera_sensor_info
*info
,
719 struct msm_sensor_ctrl
*s
)
721 int rc
= i2c_add_driver(&mt9d112_i2c_driver
);
722 if (rc
< 0 || mt9d112_client
== NULL
) {
727 /* Input MCLK = 24MHz */
728 msm_camio_clk_rate_set(24000000);
731 rc
= mt9d112_sensor_init_probe(info
);
735 s
->s_init
= mt9d112_sensor_init
;
736 s
->s_release
= mt9d112_sensor_release
;
737 s
->s_config
= mt9d112_sensor_config
;
740 CDBG("%s %s:%d\n", __FILE__
, __func__
, __LINE__
);
744 static int __mt9d112_probe(struct platform_device
*pdev
)
746 return msm_camera_drv_start(pdev
, mt9d112_sensor_probe
);
749 static struct platform_driver msm_camera_driver
= {
750 .probe
= __mt9d112_probe
,
752 .name
= "msm_camera_mt9d112",
753 .owner
= THIS_MODULE
,
757 static int __init
mt9d112_init(void)
759 return platform_driver_register(&msm_camera_driver
);
762 module_init(mt9d112_init
);