ext4: fix undefined behavior in ext4_fill_flex_info()
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / dream / camera / mt9d112.c
blob4f938f9dfc4709bc9960ac084de65703a5e4b084
1 /*
2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
3 */
5 #include <linux/delay.h>
6 #include <linux/types.h>
7 #include <linux/i2c.h>
8 #include <linux/uaccess.h>
9 #include <linux/miscdevice.h>
10 #include <media/msm_camera.h>
11 #include <mach/gpio.h>
12 #include "mt9d112.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
24 struct mt9d112_work {
25 struct work_struct work;
28 static struct mt9d112_work *mt9d112_sensorw;
29 static struct i2c_client *mt9d112_client;
31 struct mt9d112_ctrl {
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 /*=============================================================
43 EXTERNAL DECLARATIONS
44 ==============================================================*/
45 extern struct mt9d112_reg mt9d112_regs;
48 /*=============================================================*/
50 static int mt9d112_reset(const struct msm_camera_sensor_info *dev)
52 int rc = 0;
54 rc = gpio_request(dev->sensor_reset, "mt9d112");
56 if (!rc) {
57 rc = gpio_direction_output(dev->sensor_reset, 0);
58 mdelay(20);
59 rc = gpio_direction_output(dev->sensor_reset, 1);
62 gpio_free(dev->sensor_reset);
63 return rc;
66 static int32_t mt9d112_i2c_txdata(unsigned short saddr,
67 unsigned char *txdata, int length)
69 struct i2c_msg msg[] = {
71 .addr = saddr,
72 .flags = 0,
73 .len = length,
74 .buf = txdata,
78 if (i2c_transfer(mt9d112_client->adapter, msg, 1) < 0) {
79 CDBG("mt9d112_i2c_txdata failed\n");
80 return -EIO;
83 return 0;
86 static int32_t mt9d112_i2c_write(unsigned short saddr,
87 unsigned short waddr, unsigned short wdata, enum mt9d112_width width)
89 int32_t rc = -EIO;
90 unsigned char buf[4];
92 memset(buf, 0, sizeof(buf));
93 switch (width) {
94 case WORD_LEN: {
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);
102 break;
104 case BYTE_LEN: {
105 buf[0] = waddr;
106 buf[1] = wdata;
107 rc = mt9d112_i2c_txdata(saddr, buf, 2);
109 break;
111 default:
112 break;
115 if (rc < 0)
116 CDBG(
117 "i2c_write failed, addr = 0x%x, val = 0x%x!\n",
118 waddr, wdata);
120 return rc;
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)
127 int i;
128 int32_t rc = -EIO;
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);
134 if (rc < 0)
135 break;
136 if (reg_conf_tbl->mdelay_time != 0)
137 mdelay(reg_conf_tbl->mdelay_time);
138 reg_conf_tbl++;
141 return rc;
144 static int mt9d112_i2c_rxdata(unsigned short saddr,
145 unsigned char *rxdata, int length)
147 struct i2c_msg msgs[] = {
149 .addr = saddr,
150 .flags = 0,
151 .len = 2,
152 .buf = rxdata,
155 .addr = saddr,
156 .flags = I2C_M_RD,
157 .len = length,
158 .buf = rxdata,
162 if (i2c_transfer(mt9d112_client->adapter, msgs, 2) < 0) {
163 CDBG("mt9d112_i2c_rxdata failed!\n");
164 return -EIO;
167 return 0;
170 static int32_t mt9d112_i2c_read(unsigned short saddr,
171 unsigned short raddr, unsigned short *rdata, enum mt9d112_width width)
173 int32_t rc = 0;
174 unsigned char buf[4];
176 if (!rdata)
177 return -EIO;
179 memset(buf, 0, sizeof(buf));
181 switch (width) {
182 case WORD_LEN: {
183 buf[0] = (raddr & 0xFF00)>>8;
184 buf[1] = (raddr & 0x00FF);
186 rc = mt9d112_i2c_rxdata(saddr, buf, 2);
187 if (rc < 0)
188 return rc;
190 *rdata = buf[0] << 8 | buf[1];
192 break;
194 default:
195 break;
198 if (rc < 0)
199 CDBG("mt9d112_i2c_read failed!\n");
201 return rc;
204 static int32_t mt9d112_set_lens_roll_off(void)
206 int32_t rc = 0;
207 rc = mt9d112_i2c_write_table(&mt9d112_regs.rftbl[0],
208 mt9d112_regs.rftbl_size);
209 return rc;
212 static long mt9d112_reg_init(void)
214 int32_t array_length;
215 int32_t i;
216 long rc;
218 /* PLL Setup Start */
219 rc = mt9d112_i2c_write_table(&mt9d112_regs.plltbl[0],
220 mt9d112_regs.plltbl_size);
222 if (rc < 0)
223 return rc;
224 /* PLL Setup End */
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,
233 WORD_LEN);
235 if (rc < 0)
236 return rc;
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,
246 WORD_LEN);
248 if (rc < 0)
249 return rc;
252 /* Set Color Kill Saturation point to optimum value */
253 rc =
254 mt9d112_i2c_write(mt9d112_client->addr,
255 0x35A4,
256 0x0593,
257 WORD_LEN);
258 if (rc < 0)
259 return rc;
261 rc = mt9d112_i2c_write_table(&mt9d112_regs.stbl[0],
262 mt9d112_regs.stbl_size);
263 if (rc < 0)
264 return rc;
266 rc = mt9d112_set_lens_roll_off();
267 if (rc < 0)
268 return rc;
270 return 0;
273 static long mt9d112_set_sensor_mode(int mode)
275 uint16_t clock;
276 long rc = 0;
278 switch (mode) {
279 case SENSOR_PREVIEW_MODE:
280 rc =
281 mt9d112_i2c_write(mt9d112_client->addr,
282 0x338C, 0xA20C, WORD_LEN);
283 if (rc < 0)
284 return rc;
286 rc =
287 mt9d112_i2c_write(mt9d112_client->addr,
288 0x3390, 0x0004, WORD_LEN);
289 if (rc < 0)
290 return rc;
292 rc =
293 mt9d112_i2c_write(mt9d112_client->addr,
294 0x338C, 0xA215, WORD_LEN);
295 if (rc < 0)
296 return rc;
298 rc =
299 mt9d112_i2c_write(mt9d112_client->addr,
300 0x3390, 0x0004, WORD_LEN);
301 if (rc < 0)
302 return rc;
304 rc =
305 mt9d112_i2c_write(mt9d112_client->addr,
306 0x338C, 0xA20B, WORD_LEN);
307 if (rc < 0)
308 return rc;
310 rc =
311 mt9d112_i2c_write(mt9d112_client->addr,
312 0x3390, 0x0000, WORD_LEN);
313 if (rc < 0)
314 return rc;
316 clock = 0x0250;
318 rc =
319 mt9d112_i2c_write(mt9d112_client->addr,
320 0x341C, clock, WORD_LEN);
321 if (rc < 0)
322 return rc;
324 rc =
325 mt9d112_i2c_write(mt9d112_client->addr,
326 0x338C, 0xA103, WORD_LEN);
327 if (rc < 0)
328 return rc;
330 rc =
331 mt9d112_i2c_write(mt9d112_client->addr,
332 0x3390, 0x0001, WORD_LEN);
333 if (rc < 0)
334 return rc;
336 mdelay(5);
337 break;
339 case SENSOR_SNAPSHOT_MODE:
340 /* Switch to lower fps for Snapshot */
341 rc =
342 mt9d112_i2c_write(mt9d112_client->addr,
343 0x341C, 0x0120, WORD_LEN);
344 if (rc < 0)
345 return rc;
347 rc =
348 mt9d112_i2c_write(mt9d112_client->addr,
349 0x338C, 0xA120, WORD_LEN);
350 if (rc < 0)
351 return rc;
353 rc =
354 mt9d112_i2c_write(mt9d112_client->addr,
355 0x3390, 0x0002, WORD_LEN);
356 if (rc < 0)
357 return rc;
359 mdelay(5);
361 rc =
362 mt9d112_i2c_write(mt9d112_client->addr,
363 0x338C, 0xA103, WORD_LEN);
364 if (rc < 0)
365 return rc;
367 rc =
368 mt9d112_i2c_write(mt9d112_client->addr,
369 0x3390, 0x0002, WORD_LEN);
370 if (rc < 0)
371 return rc;
372 break;
374 default:
375 return -EINVAL;
378 return 0;
381 static long mt9d112_set_effect(int mode, int effect)
383 uint16_t reg_addr;
384 uint16_t reg_val;
385 long rc = 0;
387 switch (mode) {
388 case SENSOR_PREVIEW_MODE:
389 /* Context A Special Effects */
390 reg_addr = 0x2799;
391 break;
393 case SENSOR_SNAPSHOT_MODE:
394 /* Context B Special Effects */
395 reg_addr = 0x279B;
396 break;
398 default:
399 reg_addr = 0x2799;
400 break;
403 switch (effect) {
404 case CAMERA_EFFECT_OFF: {
405 reg_val = 0x6440;
407 rc = mt9d112_i2c_write(mt9d112_client->addr,
408 0x338C, reg_addr, WORD_LEN);
409 if (rc < 0)
410 return rc;
412 rc = mt9d112_i2c_write(mt9d112_client->addr,
413 0x3390, reg_val, WORD_LEN);
414 if (rc < 0)
415 return rc;
417 break;
419 case CAMERA_EFFECT_MONO: {
420 reg_val = 0x6441;
421 rc = mt9d112_i2c_write(mt9d112_client->addr,
422 0x338C, reg_addr, WORD_LEN);
423 if (rc < 0)
424 return rc;
426 rc = mt9d112_i2c_write(mt9d112_client->addr,
427 0x3390, reg_val, WORD_LEN);
428 if (rc < 0)
429 return rc;
431 break;
433 case CAMERA_EFFECT_NEGATIVE: {
434 reg_val = 0x6443;
435 rc = mt9d112_i2c_write(mt9d112_client->addr,
436 0x338C, reg_addr, WORD_LEN);
437 if (rc < 0)
438 return rc;
440 rc = mt9d112_i2c_write(mt9d112_client->addr,
441 0x3390, reg_val, WORD_LEN);
442 if (rc < 0)
443 return rc;
445 break;
447 case CAMERA_EFFECT_SOLARIZE: {
448 reg_val = 0x6445;
449 rc = mt9d112_i2c_write(mt9d112_client->addr,
450 0x338C, reg_addr, WORD_LEN);
451 if (rc < 0)
452 return rc;
454 rc = mt9d112_i2c_write(mt9d112_client->addr,
455 0x3390, reg_val, WORD_LEN);
456 if (rc < 0)
457 return rc;
459 break;
461 case CAMERA_EFFECT_SEPIA: {
462 reg_val = 0x6442;
463 rc = mt9d112_i2c_write(mt9d112_client->addr,
464 0x338C, reg_addr, WORD_LEN);
465 if (rc < 0)
466 return rc;
468 rc = mt9d112_i2c_write(mt9d112_client->addr,
469 0x3390, reg_val, WORD_LEN);
470 if (rc < 0)
471 return rc;
473 break;
475 case CAMERA_EFFECT_PASTEL:
476 case CAMERA_EFFECT_MOSAIC:
477 case CAMERA_EFFECT_RESIZE:
478 return -EINVAL;
480 default: {
481 reg_val = 0x6440;
482 rc = mt9d112_i2c_write(mt9d112_client->addr,
483 0x338C, reg_addr, WORD_LEN);
484 if (rc < 0)
485 return rc;
487 rc = mt9d112_i2c_write(mt9d112_client->addr,
488 0x3390, reg_val, WORD_LEN);
489 if (rc < 0)
490 return rc;
492 return -EINVAL;
496 /* Refresh Sequencer */
497 rc = mt9d112_i2c_write(mt9d112_client->addr,
498 0x338C, 0xA103, WORD_LEN);
499 if (rc < 0)
500 return rc;
502 rc = mt9d112_i2c_write(mt9d112_client->addr,
503 0x3390, 0x0005, WORD_LEN);
505 return rc;
508 static int mt9d112_sensor_init_probe(const struct msm_camera_sensor_info *data)
510 uint16_t model_id = 0;
511 int rc = 0;
513 CDBG("init entry \n");
514 rc = mt9d112_reset(data);
515 if (rc < 0) {
516 CDBG("reset failed!\n");
517 goto init_probe_fail;
520 mdelay(5);
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);
526 if (rc < 0)
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);
532 if (rc < 0)
533 goto init_probe_fail;
535 mdelay(5);
537 /* Micron Suggested - Power up block */
538 rc = mt9d112_i2c_write(mt9d112_client->addr,
539 REG_MT9D112_SENSOR_RESET, 0x0ACC, WORD_LEN);
540 if (rc < 0)
541 goto init_probe_fail;
543 rc = mt9d112_i2c_write(mt9d112_client->addr,
544 REG_MT9D112_STANDBY_CONTROL, 0x0008, WORD_LEN);
545 if (rc < 0)
546 goto init_probe_fail;
548 /* FUSED_DEFECT_CORRECTION */
549 rc = mt9d112_i2c_write(mt9d112_client->addr,
550 0x33F4, 0x031D, WORD_LEN);
551 if (rc < 0)
552 goto init_probe_fail;
554 mdelay(5);
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);
560 if (rc < 0)
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) {
567 rc = -EINVAL;
568 goto init_probe_fail;
571 rc = mt9d112_reg_init();
572 if (rc < 0)
573 goto init_probe_fail;
575 return rc;
577 init_probe_fail:
578 return rc;
581 int mt9d112_sensor_init(const struct msm_camera_sensor_info *data)
583 int rc = 0;
585 mt9d112_ctrl = kzalloc(sizeof(struct mt9d112_ctrl), GFP_KERNEL);
586 if (!mt9d112_ctrl) {
587 CDBG("mt9d112_init failed!\n");
588 rc = -ENOMEM;
589 goto init_done;
592 if (data)
593 mt9d112_ctrl->sensordata = data;
595 /* Input MCLK = 24MHz */
596 msm_camio_clk_rate_set(24000000);
597 mdelay(5);
599 msm_camio_camif_pad_reg_reset();
601 rc = mt9d112_sensor_init_probe(data);
602 if (rc < 0) {
603 CDBG("mt9d112_sensor_init failed!\n");
604 goto init_fail;
607 init_done:
608 return rc;
610 init_fail:
611 kfree(mt9d112_ctrl);
612 return rc;
615 static int mt9d112_init_client(struct i2c_client *client)
617 /* Initialize the MSM_CAMI2C Chip */
618 init_waitqueue_head(&mt9d112_wait_queue);
619 return 0;
622 int mt9d112_sensor_config(void __user *argp)
624 struct sensor_cfg_data cfg_data;
625 long rc = 0;
627 if (copy_from_user(&cfg_data,
628 (void *)argp,
629 sizeof(struct sensor_cfg_data)))
630 return -EFAULT;
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) {
638 case CFG_SET_MODE:
639 rc = mt9d112_set_sensor_mode(
640 cfg_data.mode);
641 break;
643 case CFG_SET_EFFECT:
644 rc = mt9d112_set_effect(cfg_data.mode,
645 cfg_data.cfg.effect);
646 break;
648 case CFG_GET_AF_MAX_STEPS:
649 default:
650 rc = -EINVAL;
651 break;
654 /* up(&mt9d112_sem); */
656 return rc;
659 int mt9d112_sensor_release(void)
661 int rc = 0;
663 /* down(&mt9d112_sem); */
665 kfree(mt9d112_ctrl);
666 /* up(&mt9d112_sem); */
668 return rc;
671 static int mt9d112_i2c_probe(struct i2c_client *client,
672 const struct i2c_device_id *id)
674 int rc = 0;
675 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
676 rc = -ENOTSUPP;
677 goto probe_failure;
680 mt9d112_sensorw =
681 kzalloc(sizeof(struct mt9d112_work), GFP_KERNEL);
683 if (!mt9d112_sensorw) {
684 rc = -ENOMEM;
685 goto probe_failure;
688 i2c_set_clientdata(client, mt9d112_sensorw);
689 mt9d112_init_client(client);
690 mt9d112_client = client;
692 CDBG("mt9d112_probe succeeded!\n");
694 return 0;
696 probe_failure:
697 kfree(mt9d112_sensorw);
698 mt9d112_sensorw = NULL;
699 CDBG("mt9d112_probe failed!\n");
700 return rc;
703 static const struct i2c_device_id mt9d112_i2c_id[] = {
704 { "mt9d112", 0},
705 { },
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),
712 .driver = {
713 .name = "mt9d112",
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) {
722 rc = -ENOTSUPP;
723 goto probe_done;
726 /* Input MCLK = 24MHz */
727 msm_camio_clk_rate_set(24000000);
728 mdelay(5);
730 rc = mt9d112_sensor_init_probe(info);
731 if (rc < 0)
732 goto probe_done;
734 s->s_init = mt9d112_sensor_init;
735 s->s_release = mt9d112_sensor_release;
736 s->s_config = mt9d112_sensor_config;
738 probe_done:
739 CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
740 return rc;
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,
750 .driver = {
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);