2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
5 #include <linux/delay.h>
6 #include <linux/types.h>
8 #include <linux/uaccess.h>
9 #include <linux/miscdevice.h>
10 #include <media/msm_camera.h>
11 #include <mach/gpio.h>
14 /* Micron MT9D112 Registers and their values */
15 /* Sensor Core Registers */
16 #define REG_MT9D112_MODEL_ID 0x3000
17 #define MT9D112_MODEL_ID 0x1580
19 /* SOC Registers Page 1 */
20 #define REG_MT9D112_SENSOR_RESET 0x301A
21 #define REG_MT9D112_STANDBY_CONTROL 0x3202
22 #define REG_MT9D112_MCU_BOOT 0x3386
25 struct work_struct work
;
28 static struct mt9d112_work
*mt9d112_sensorw
;
29 static struct i2c_client
*mt9d112_client
;
32 const struct msm_camera_sensor_info
*sensordata
;
36 static struct mt9d112_ctrl
*mt9d112_ctrl
;
38 static DECLARE_WAIT_QUEUE_HEAD(mt9d112_wait_queue
);
39 DECLARE_MUTEX(mt9d112_sem
);
42 /*=============================================================
44 ==============================================================*/
45 extern struct mt9d112_reg mt9d112_regs
;
48 /*=============================================================*/
50 static int mt9d112_reset(const struct msm_camera_sensor_info
*dev
)
54 rc
= gpio_request(dev
->sensor_reset
, "mt9d112");
57 rc
= gpio_direction_output(dev
->sensor_reset
, 0);
59 rc
= gpio_direction_output(dev
->sensor_reset
, 1);
62 gpio_free(dev
->sensor_reset
);
66 static int32_t mt9d112_i2c_txdata(unsigned short saddr
,
67 unsigned char *txdata
, int length
)
69 struct i2c_msg msg
[] = {
78 if (i2c_transfer(mt9d112_client
->adapter
, msg
, 1) < 0) {
79 CDBG("mt9d112_i2c_txdata failed\n");
86 static int32_t mt9d112_i2c_write(unsigned short saddr
,
87 unsigned short waddr
, unsigned short wdata
, enum mt9d112_width width
)
92 memset(buf
, 0, sizeof(buf
));
95 buf
[0] = (waddr
& 0xFF00)>>8;
96 buf
[1] = (waddr
& 0x00FF);
97 buf
[2] = (wdata
& 0xFF00)>>8;
98 buf
[3] = (wdata
& 0x00FF);
100 rc
= mt9d112_i2c_txdata(saddr
, buf
, 4);
107 rc
= mt9d112_i2c_txdata(saddr
, buf
, 2);
117 "i2c_write failed, addr = 0x%x, val = 0x%x!\n",
123 static int32_t mt9d112_i2c_write_table(
124 struct mt9d112_i2c_reg_conf
const *reg_conf_tbl
,
125 int num_of_items_in_table
)
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
);
136 if (reg_conf_tbl
->mdelay_time
!= 0)
137 mdelay(reg_conf_tbl
->mdelay_time
);
144 static int mt9d112_i2c_rxdata(unsigned short saddr
,
145 unsigned char *rxdata
, int length
)
147 struct i2c_msg msgs
[] = {
162 if (i2c_transfer(mt9d112_client
->adapter
, msgs
, 2) < 0) {
163 CDBG("mt9d112_i2c_rxdata failed!\n");
170 static int32_t mt9d112_i2c_read(unsigned short saddr
,
171 unsigned short raddr
, unsigned short *rdata
, enum mt9d112_width width
)
174 unsigned char buf
[4];
179 memset(buf
, 0, sizeof(buf
));
183 buf
[0] = (raddr
& 0xFF00)>>8;
184 buf
[1] = (raddr
& 0x00FF);
186 rc
= mt9d112_i2c_rxdata(saddr
, buf
, 2);
190 *rdata
= buf
[0] << 8 | buf
[1];
199 CDBG("mt9d112_i2c_read failed!\n");
204 static int32_t mt9d112_set_lens_roll_off(void)
207 rc
= mt9d112_i2c_write_table(&mt9d112_regs
.rftbl
[0],
208 mt9d112_regs
.rftbl_size
);
212 static long mt9d112_reg_init(void)
214 int32_t array_length
;
218 /* PLL Setup Start */
219 rc
= mt9d112_i2c_write_table(&mt9d112_regs
.plltbl
[0],
220 mt9d112_regs
.plltbl_size
);
226 array_length
= mt9d112_regs
.prev_snap_reg_settings_size
;
228 /* Configure sensor for Preview mode and Snapshot mode */
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
,
239 /* Configure for Noise Reduction, Saturation and Aperture Correction */
240 array_length
= mt9d112_regs
.noise_reduction_reg_settings_size
;
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
,
252 /* Set Color Kill Saturation point to optimum value */
254 mt9d112_i2c_write(mt9d112_client
->addr
,
261 rc
= mt9d112_i2c_write_table(&mt9d112_regs
.stbl
[0],
262 mt9d112_regs
.stbl_size
);
266 rc
= mt9d112_set_lens_roll_off();
273 static long mt9d112_set_sensor_mode(int mode
)
279 case SENSOR_PREVIEW_MODE
:
281 mt9d112_i2c_write(mt9d112_client
->addr
,
282 0x338C, 0xA20C, WORD_LEN
);
287 mt9d112_i2c_write(mt9d112_client
->addr
,
288 0x3390, 0x0004, WORD_LEN
);
293 mt9d112_i2c_write(mt9d112_client
->addr
,
294 0x338C, 0xA215, WORD_LEN
);
299 mt9d112_i2c_write(mt9d112_client
->addr
,
300 0x3390, 0x0004, WORD_LEN
);
305 mt9d112_i2c_write(mt9d112_client
->addr
,
306 0x338C, 0xA20B, WORD_LEN
);
311 mt9d112_i2c_write(mt9d112_client
->addr
,
312 0x3390, 0x0000, WORD_LEN
);
319 mt9d112_i2c_write(mt9d112_client
->addr
,
320 0x341C, clock
, WORD_LEN
);
325 mt9d112_i2c_write(mt9d112_client
->addr
,
326 0x338C, 0xA103, WORD_LEN
);
331 mt9d112_i2c_write(mt9d112_client
->addr
,
332 0x3390, 0x0001, WORD_LEN
);
339 case SENSOR_SNAPSHOT_MODE
:
340 /* Switch to lower fps for Snapshot */
342 mt9d112_i2c_write(mt9d112_client
->addr
,
343 0x341C, 0x0120, WORD_LEN
);
348 mt9d112_i2c_write(mt9d112_client
->addr
,
349 0x338C, 0xA120, WORD_LEN
);
354 mt9d112_i2c_write(mt9d112_client
->addr
,
355 0x3390, 0x0002, WORD_LEN
);
362 mt9d112_i2c_write(mt9d112_client
->addr
,
363 0x338C, 0xA103, WORD_LEN
);
368 mt9d112_i2c_write(mt9d112_client
->addr
,
369 0x3390, 0x0002, WORD_LEN
);
381 static long mt9d112_set_effect(int mode
, int effect
)
388 case SENSOR_PREVIEW_MODE
:
389 /* Context A Special Effects */
393 case SENSOR_SNAPSHOT_MODE
:
394 /* Context B Special Effects */
404 case CAMERA_EFFECT_OFF
: {
407 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
408 0x338C, reg_addr
, WORD_LEN
);
412 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
413 0x3390, reg_val
, WORD_LEN
);
419 case CAMERA_EFFECT_MONO
: {
421 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
422 0x338C, reg_addr
, WORD_LEN
);
426 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
427 0x3390, reg_val
, WORD_LEN
);
433 case CAMERA_EFFECT_NEGATIVE
: {
435 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
436 0x338C, reg_addr
, WORD_LEN
);
440 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
441 0x3390, reg_val
, WORD_LEN
);
447 case CAMERA_EFFECT_SOLARIZE
: {
449 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
450 0x338C, reg_addr
, WORD_LEN
);
454 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
455 0x3390, reg_val
, WORD_LEN
);
461 case CAMERA_EFFECT_SEPIA
: {
463 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
464 0x338C, reg_addr
, WORD_LEN
);
468 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
469 0x3390, reg_val
, WORD_LEN
);
475 case CAMERA_EFFECT_PASTEL
:
476 case CAMERA_EFFECT_MOSAIC
:
477 case CAMERA_EFFECT_RESIZE
:
482 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
483 0x338C, reg_addr
, WORD_LEN
);
487 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
488 0x3390, reg_val
, WORD_LEN
);
496 /* Refresh Sequencer */
497 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
498 0x338C, 0xA103, WORD_LEN
);
502 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
503 0x3390, 0x0005, WORD_LEN
);
508 static int mt9d112_sensor_init_probe(const struct msm_camera_sensor_info
*data
)
510 uint16_t model_id
= 0;
513 CDBG("init entry \n");
514 rc
= mt9d112_reset(data
);
516 CDBG("reset failed!\n");
517 goto init_probe_fail
;
522 /* Micron suggested Power up block Start:
523 * Put MCU into Reset - Stop MCU */
524 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
525 REG_MT9D112_MCU_BOOT
, 0x0501, WORD_LEN
);
527 goto init_probe_fail
;
529 /* Pull MCU from Reset - Start MCU */
530 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
531 REG_MT9D112_MCU_BOOT
, 0x0500, WORD_LEN
);
533 goto init_probe_fail
;
537 /* Micron Suggested - Power up block */
538 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
539 REG_MT9D112_SENSOR_RESET
, 0x0ACC, WORD_LEN
);
541 goto init_probe_fail
;
543 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
544 REG_MT9D112_STANDBY_CONTROL
, 0x0008, WORD_LEN
);
546 goto init_probe_fail
;
548 /* FUSED_DEFECT_CORRECTION */
549 rc
= mt9d112_i2c_write(mt9d112_client
->addr
,
550 0x33F4, 0x031D, WORD_LEN
);
552 goto init_probe_fail
;
556 /* Micron suggested Power up block End */
557 /* Read the Model ID of the sensor */
558 rc
= mt9d112_i2c_read(mt9d112_client
->addr
,
559 REG_MT9D112_MODEL_ID
, &model_id
, WORD_LEN
);
561 goto init_probe_fail
;
563 CDBG("mt9d112 model_id = 0x%x\n", model_id
);
565 /* Check if it matches it with the value in Datasheet */
566 if (model_id
!= MT9D112_MODEL_ID
) {
568 goto init_probe_fail
;
571 rc
= mt9d112_reg_init();
573 goto init_probe_fail
;
581 int mt9d112_sensor_init(const struct msm_camera_sensor_info
*data
)
585 mt9d112_ctrl
= kzalloc(sizeof(struct mt9d112_ctrl
), GFP_KERNEL
);
587 CDBG("mt9d112_init failed!\n");
593 mt9d112_ctrl
->sensordata
= data
;
595 /* Input MCLK = 24MHz */
596 msm_camio_clk_rate_set(24000000);
599 msm_camio_camif_pad_reg_reset();
601 rc
= mt9d112_sensor_init_probe(data
);
603 CDBG("mt9d112_sensor_init failed!\n");
615 static int mt9d112_init_client(struct i2c_client
*client
)
617 /* Initialize the MSM_CAMI2C Chip */
618 init_waitqueue_head(&mt9d112_wait_queue
);
622 int mt9d112_sensor_config(void __user
*argp
)
624 struct sensor_cfg_data cfg_data
;
627 if (copy_from_user(&cfg_data
,
629 sizeof(struct sensor_cfg_data
)))
632 /* down(&mt9d112_sem); */
634 CDBG("mt9d112_ioctl, cfgtype = %d, mode = %d\n",
635 cfg_data
.cfgtype
, cfg_data
.mode
);
637 switch (cfg_data
.cfgtype
) {
639 rc
= mt9d112_set_sensor_mode(
644 rc
= mt9d112_set_effect(cfg_data
.mode
,
645 cfg_data
.cfg
.effect
);
648 case CFG_GET_AF_MAX_STEPS
:
654 /* up(&mt9d112_sem); */
659 int mt9d112_sensor_release(void)
663 /* down(&mt9d112_sem); */
666 /* up(&mt9d112_sem); */
671 static int mt9d112_i2c_probe(struct i2c_client
*client
,
672 const struct i2c_device_id
*id
)
675 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
681 kzalloc(sizeof(struct mt9d112_work
), GFP_KERNEL
);
683 if (!mt9d112_sensorw
) {
688 i2c_set_clientdata(client
, mt9d112_sensorw
);
689 mt9d112_init_client(client
);
690 mt9d112_client
= client
;
692 CDBG("mt9d112_probe succeeded!\n");
697 kfree(mt9d112_sensorw
);
698 mt9d112_sensorw
= NULL
;
699 CDBG("mt9d112_probe failed!\n");
703 static const struct i2c_device_id mt9d112_i2c_id
[] = {
708 static struct i2c_driver mt9d112_i2c_driver
= {
709 .id_table
= mt9d112_i2c_id
,
710 .probe
= mt9d112_i2c_probe
,
711 .remove
= __exit_p(mt9d112_i2c_remove
),
717 static int mt9d112_sensor_probe(const struct msm_camera_sensor_info
*info
,
718 struct msm_sensor_ctrl
*s
)
720 int rc
= i2c_add_driver(&mt9d112_i2c_driver
);
721 if (rc
< 0 || mt9d112_client
== NULL
) {
726 /* Input MCLK = 24MHz */
727 msm_camio_clk_rate_set(24000000);
730 rc
= mt9d112_sensor_init_probe(info
);
734 s
->s_init
= mt9d112_sensor_init
;
735 s
->s_release
= mt9d112_sensor_release
;
736 s
->s_config
= mt9d112_sensor_config
;
739 CDBG("%s %s:%d\n", __FILE__
, __func__
, __LINE__
);
743 static int __mt9d112_probe(struct platform_device
*pdev
)
745 return msm_camera_drv_start(pdev
, mt9d112_sensor_probe
);
748 static struct platform_driver msm_camera_driver
= {
749 .probe
= __mt9d112_probe
,
751 .name
= "msm_camera_mt9d112",
752 .owner
= THIS_MODULE
,
756 static int __init
mt9d112_init(void)
758 return platform_driver_register(&msm_camera_driver
);
761 module_init(mt9d112_init
);