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