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);