]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/dream/camera/mt9p012_fox.c
semaphore: Remove mutex emulation
[net-next-2.6.git] / drivers / staging / dream / camera / mt9p012_fox.c
CommitLineData
eb7b797b
BS
1/*
2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
3 */
4
5#include <linux/delay.h>
6#include <linux/types.h>
5a0e3ad6 7#include <linux/slab.h>
eb7b797b
BS
8#include <linux/i2c.h>
9#include <linux/uaccess.h>
10#include <linux/miscdevice.h>
11#include <linux/kernel.h>
12#include <media/msm_camera.h>
13#include <mach/gpio.h>
14#include <mach/camera.h>
15#include "mt9p012.h"
16
17/*=============================================================
18 SENSOR REGISTER DEFINES
19==============================================================*/
20#define MT9P012_REG_MODEL_ID 0x0000
21#define MT9P012_MODEL_ID 0x2801
22#define REG_GROUPED_PARAMETER_HOLD 0x0104
23#define GROUPED_PARAMETER_HOLD 0x0100
24#define GROUPED_PARAMETER_UPDATE 0x0000
25#define REG_COARSE_INT_TIME 0x3012
26#define REG_VT_PIX_CLK_DIV 0x0300
27#define REG_VT_SYS_CLK_DIV 0x0302
28#define REG_PRE_PLL_CLK_DIV 0x0304
29#define REG_PLL_MULTIPLIER 0x0306
30#define REG_OP_PIX_CLK_DIV 0x0308
31#define REG_OP_SYS_CLK_DIV 0x030A
32#define REG_SCALE_M 0x0404
33#define REG_FRAME_LENGTH_LINES 0x300A
34#define REG_LINE_LENGTH_PCK 0x300C
35#define REG_X_ADDR_START 0x3004
36#define REG_Y_ADDR_START 0x3002
37#define REG_X_ADDR_END 0x3008
38#define REG_Y_ADDR_END 0x3006
39#define REG_X_OUTPUT_SIZE 0x034C
40#define REG_Y_OUTPUT_SIZE 0x034E
41#define REG_FINE_INTEGRATION_TIME 0x3014
42#define REG_ROW_SPEED 0x3016
43#define MT9P012_REG_RESET_REGISTER 0x301A
44#define MT9P012_RESET_REGISTER_PWON 0x10CC
45#define MT9P012_RESET_REGISTER_PWOFF 0x10C8
46#define REG_READ_MODE 0x3040
47#define REG_GLOBAL_GAIN 0x305E
48#define REG_TEST_PATTERN_MODE 0x3070
49
50#define MT9P012_REV_7
51
52
53enum mt9p012_test_mode {
54 TEST_OFF,
55 TEST_1,
56 TEST_2,
57 TEST_3
58};
59
60enum mt9p012_resolution {
61 QTR_SIZE,
62 FULL_SIZE,
63 INVALID_SIZE
64};
65
66enum mt9p012_reg_update {
67 /* Sensor egisters that need to be updated during initialization */
68 REG_INIT,
69 /* Sensor egisters that needs periodic I2C writes */
70 UPDATE_PERIODIC,
71 /* All the sensor Registers will be updated */
72 UPDATE_ALL,
73 /* Not valid update */
74 UPDATE_INVALID
75};
76
77enum mt9p012_setting {
78 RES_PREVIEW,
79 RES_CAPTURE
80};
81
82/* actuator's Slave Address */
83#define MT9P012_AF_I2C_ADDR 0x18
84
85/* AF Total steps parameters */
86#define MT9P012_STEPS_NEAR_TO_CLOSEST_INF 32
87#define MT9P012_TOTAL_STEPS_NEAR_TO_FAR 32
88
89#define MT9P012_MU5M0_PREVIEW_DUMMY_PIXELS 0
90#define MT9P012_MU5M0_PREVIEW_DUMMY_LINES 0
91
92/* Time in milisecs for waiting for the sensor to reset.*/
93#define MT9P012_RESET_DELAY_MSECS 66
94
95/* for 20 fps preview */
96#define MT9P012_DEFAULT_CLOCK_RATE 24000000
97#define MT9P012_DEFAULT_MAX_FPS 26 /* ???? */
98
99struct mt9p012_work {
100 struct work_struct work;
101};
102static struct mt9p012_work *mt9p012_sensorw;
103static struct i2c_client *mt9p012_client;
104
105struct mt9p012_ctrl {
106 const struct msm_camera_sensor_info *sensordata;
107
108 int sensormode;
109 uint32_t fps_divider; /* init to 1 * 0x00000400 */
110 uint32_t pict_fps_divider; /* init to 1 * 0x00000400 */
111
112 uint16_t curr_lens_pos;
113 uint16_t init_curr_lens_pos;
114 uint16_t my_reg_gain;
115 uint32_t my_reg_line_count;
116
117 enum mt9p012_resolution prev_res;
118 enum mt9p012_resolution pict_res;
119 enum mt9p012_resolution curr_res;
120 enum mt9p012_test_mode set_test;
121};
122
123
124static struct mt9p012_ctrl *mt9p012_ctrl;
125static DECLARE_WAIT_QUEUE_HEAD(mt9p012_wait_queue);
45f4d024 126DEFINE_SEMAPHORE(mt9p012_sem);
eb7b797b
BS
127
128/*=============================================================
129 EXTERNAL DECLARATIONS
130==============================================================*/
131extern struct mt9p012_reg mt9p012_regs; /* from mt9p012_reg.c */
132
133
134
135/*=============================================================*/
136
137static int mt9p012_i2c_rxdata(unsigned short saddr, unsigned char *rxdata,
138 int length)
139{
140 struct i2c_msg msgs[] = {
141 {
142 .addr = saddr,
143 .flags = 0,
144 .len = 2,
145 .buf = rxdata,
146 },
147 {
148 .addr = saddr,
149 .flags = I2C_M_RD,
150 .len = length,
151 .buf = rxdata,
152 },
153 };
154
155 if (i2c_transfer(mt9p012_client->adapter, msgs, 2) < 0) {
156 CDBG("mt9p012_i2c_rxdata failed!\n");
157 return -EIO;
158 }
159
160 return 0;
161}
162
163static int32_t mt9p012_i2c_read_w(unsigned short saddr, unsigned short raddr,
164 unsigned short *rdata)
165{
166 int32_t rc = 0;
167 unsigned char buf[4];
168
169 if (!rdata)
170 return -EIO;
171
172 memset(buf, 0, sizeof(buf));
173
174 buf[0] = (raddr & 0xFF00)>>8;
175 buf[1] = (raddr & 0x00FF);
176
177 rc = mt9p012_i2c_rxdata(saddr, buf, 2);
178 if (rc < 0)
179 return rc;
180
181 *rdata = buf[0] << 8 | buf[1];
182
183 if (rc < 0)
184 CDBG("mt9p012_i2c_read failed!\n");
185
186 return rc;
187}
188
189static int32_t mt9p012_i2c_txdata(unsigned short saddr, unsigned char *txdata,
190 int length)
191{
192 struct i2c_msg msg[] = {
193 {
194 .addr = saddr,
195 .flags = 0,
196 .len = length,
197 .buf = txdata,
198 },
199 };
200
201 if (i2c_transfer(mt9p012_client->adapter, msg, 1) < 0) {
202 CDBG("mt9p012_i2c_txdata failed\n");
203 return -EIO;
204 }
205
206 return 0;
207}
208
209static int32_t mt9p012_i2c_write_b(unsigned short saddr, unsigned short baddr,
210 unsigned short bdata)
211{
212 int32_t rc = -EIO;
213 unsigned char buf[2];
214
215 memset(buf, 0, sizeof(buf));
216 buf[0] = baddr;
217 buf[1] = bdata;
218 rc = mt9p012_i2c_txdata(saddr, buf, 2);
219
220 if (rc < 0)
221 CDBG("i2c_write failed, saddr = 0x%x addr = 0x%x, val =0x%x!\n",
222 saddr, baddr, bdata);
223
224 return rc;
225}
226
227static int32_t mt9p012_i2c_write_w(unsigned short saddr, unsigned short waddr,
228 unsigned short wdata)
229{
230 int32_t rc = -EIO;
231 unsigned char buf[4];
232
233 memset(buf, 0, sizeof(buf));
234 buf[0] = (waddr & 0xFF00)>>8;
235 buf[1] = (waddr & 0x00FF);
236 buf[2] = (wdata & 0xFF00)>>8;
237 buf[3] = (wdata & 0x00FF);
238
239 rc = mt9p012_i2c_txdata(saddr, buf, 4);
240
241 if (rc < 0)
242 CDBG("i2c_write_w failed, addr = 0x%x, val = 0x%x!\n",
243 waddr, wdata);
244
245 return rc;
246}
247
248static int32_t mt9p012_i2c_write_w_table(
249 struct mt9p012_i2c_reg_conf *reg_conf_tbl, int num)
250{
251 int i;
252 int32_t rc = -EIO;
253
254 for (i = 0; i < num; i++) {
255 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
256 reg_conf_tbl->waddr, reg_conf_tbl->wdata);
257 if (rc < 0)
258 break;
259 reg_conf_tbl++;
260 }
261
262 return rc;
263}
264
265static int32_t mt9p012_test(enum mt9p012_test_mode mo)
266{
267 int32_t rc = 0;
268
269 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
270 REG_GROUPED_PARAMETER_HOLD,
271 GROUPED_PARAMETER_HOLD);
272 if (rc < 0)
273 return rc;
274
275 if (mo == TEST_OFF)
276 return 0;
277 else {
278 rc = mt9p012_i2c_write_w_table(mt9p012_regs.ttbl, mt9p012_regs.ttbl_size);
279 if (rc < 0)
280 return rc;
281
282 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
283 REG_TEST_PATTERN_MODE, (uint16_t)mo);
284 if (rc < 0)
285 return rc;
286 }
287
288 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
289 REG_GROUPED_PARAMETER_HOLD,
290 GROUPED_PARAMETER_UPDATE);
291 if (rc < 0)
292 return rc;
293
294 return rc;
295}
296
297static int32_t mt9p012_lens_shading_enable(uint8_t is_enable)
298{
299 int32_t rc = 0;
300
301 CDBG("%s: entered. enable = %d\n", __func__, is_enable);
302
303 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
304 REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD);
305 if (rc < 0)
306 return rc;
307
308 rc = mt9p012_i2c_write_w(mt9p012_client->addr, 0x3780,
309 ((uint16_t) is_enable) << 15);
310 if (rc < 0)
311 return rc;
312
313 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
314 REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE);
315
316 CDBG("%s: exiting. rc = %d\n", __func__, rc);
317 return rc;
318}
319
320static int32_t mt9p012_set_lc(void)
321{
322 int32_t rc;
323
324 rc = mt9p012_i2c_write_w_table(mt9p012_regs.lctbl, mt9p012_regs.lctbl_size);
325 if (rc < 0)
326 return rc;
327
328 rc = mt9p012_i2c_write_w_table(mt9p012_regs.rftbl, mt9p012_regs.rftbl_size);
329
330 return rc;
331}
332
333static void mt9p012_get_pict_fps(uint16_t fps, uint16_t *pfps)
334{
335 /* input fps is preview fps in Q8 format */
336 uint32_t divider; /*Q10 */
337 uint32_t pclk_mult; /*Q10 */
338
339 if (mt9p012_ctrl->prev_res == QTR_SIZE) {
340 divider = (uint32_t)
341 (((mt9p012_regs.reg_pat[RES_PREVIEW].frame_length_lines *
342 mt9p012_regs.reg_pat[RES_PREVIEW].line_length_pck) * 0x00000400) /
343 (mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines *
344 mt9p012_regs.reg_pat[RES_CAPTURE].line_length_pck));
345
346 pclk_mult =
347 (uint32_t) ((mt9p012_regs.reg_pat[RES_CAPTURE].pll_multiplier *
348 0x00000400) / (mt9p012_regs.reg_pat[RES_PREVIEW].pll_multiplier));
349 } else {
350 /* full size resolution used for preview. */
351 divider = 0x00000400; /*1.0 */
352 pclk_mult = 0x00000400; /*1.0 */
353 }
354
355 /* Verify PCLK settings and frame sizes. */
356 *pfps = (uint16_t) (fps * divider * pclk_mult / 0x00000400 /
357 0x00000400);
358}
359
360static uint16_t mt9p012_get_prev_lines_pf(void)
361{
362 if (mt9p012_ctrl->prev_res == QTR_SIZE)
363 return mt9p012_regs.reg_pat[RES_PREVIEW].frame_length_lines;
364 else
365 return mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines;
366}
367
368static uint16_t mt9p012_get_prev_pixels_pl(void)
369{
370 if (mt9p012_ctrl->prev_res == QTR_SIZE)
371 return mt9p012_regs.reg_pat[RES_PREVIEW].line_length_pck;
372 else
373 return mt9p012_regs.reg_pat[RES_CAPTURE].line_length_pck;
374}
375
376static uint16_t mt9p012_get_pict_lines_pf(void)
377{
378 return mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines;
379}
380
381static uint16_t mt9p012_get_pict_pixels_pl(void)
382{
383 return mt9p012_regs.reg_pat[RES_CAPTURE].line_length_pck;
384}
385
386static uint32_t mt9p012_get_pict_max_exp_lc(void)
387{
388 uint16_t snapshot_lines_per_frame;
389
390 if (mt9p012_ctrl->pict_res == QTR_SIZE)
391 snapshot_lines_per_frame =
392 mt9p012_regs.reg_pat[RES_PREVIEW].frame_length_lines - 1;
393 else
394 snapshot_lines_per_frame =
395 mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines - 1;
396
397 return snapshot_lines_per_frame * 24;
398}
399
400static int32_t mt9p012_set_fps(struct fps_cfg *fps)
401{
402 /* input is new fps in Q10 format */
403 int32_t rc = 0;
404
405 mt9p012_ctrl->fps_divider = fps->fps_div;
406 mt9p012_ctrl->pict_fps_divider = fps->pict_fps_div;
407
408 rc =
409 mt9p012_i2c_write_w(mt9p012_client->addr,
410 REG_GROUPED_PARAMETER_HOLD,
411 GROUPED_PARAMETER_HOLD);
412 if (rc < 0)
413 return -EBUSY;
414
415 rc =
416 mt9p012_i2c_write_w(mt9p012_client->addr,
417 REG_LINE_LENGTH_PCK,
418 (mt9p012_regs.reg_pat[RES_PREVIEW].line_length_pck *
419 fps->f_mult / 0x00000400));
420 if (rc < 0)
421 return rc;
422
423 rc =
424 mt9p012_i2c_write_w(mt9p012_client->addr,
425 REG_GROUPED_PARAMETER_HOLD,
426 GROUPED_PARAMETER_UPDATE);
427
428 return rc;
429}
430
431static int32_t mt9p012_write_exp_gain(uint16_t gain, uint32_t line)
432{
433 uint16_t max_legal_gain = 0x01FF;
434 uint32_t line_length_ratio = 0x00000400;
435 enum mt9p012_setting setting;
436 int32_t rc = 0;
437
438 CDBG("Line:%d mt9p012_write_exp_gain \n", __LINE__);
439
440 if (mt9p012_ctrl->sensormode == SENSOR_PREVIEW_MODE) {
441 mt9p012_ctrl->my_reg_gain = gain;
442 mt9p012_ctrl->my_reg_line_count = (uint16_t)line;
443 }
444
445 if (gain > max_legal_gain) {
446 CDBG("Max legal gain Line:%d \n", __LINE__);
447 gain = max_legal_gain;
448 }
449
450 /* Verify no overflow */
451 if (mt9p012_ctrl->sensormode != SENSOR_SNAPSHOT_MODE) {
452 line = (uint32_t)(line * mt9p012_ctrl->fps_divider /
453 0x00000400);
454 setting = RES_PREVIEW;
455 } else {
456 line = (uint32_t)(line * mt9p012_ctrl->pict_fps_divider /
457 0x00000400);
458 setting = RES_CAPTURE;
459 }
460
461 /* Set digital gain to 1 */
462#ifdef MT9P012_REV_7
463 gain |= 0x1000;
464#else
465 gain |= 0x0200;
466#endif
467
468 if ((mt9p012_regs.reg_pat[setting].frame_length_lines - 1) < line) {
469 line_length_ratio = (uint32_t) (line * 0x00000400) /
470 (mt9p012_regs.reg_pat[setting].frame_length_lines - 1);
471 } else
472 line_length_ratio = 0x00000400;
473
474 rc =
475 mt9p012_i2c_write_w(mt9p012_client->addr,
476 REG_GROUPED_PARAMETER_HOLD,
477 GROUPED_PARAMETER_HOLD);
478 if (rc < 0) {
479 CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
480 return rc;
481 }
482
483 rc =
484 mt9p012_i2c_write_w(
485 mt9p012_client->addr,
486 REG_GLOBAL_GAIN, gain);
487 if (rc < 0) {
488 CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
489 return rc;
490 }
491
492 rc =
493 mt9p012_i2c_write_w(mt9p012_client->addr,
494 REG_COARSE_INT_TIME,
495 line);
496 if (rc < 0) {
497 CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
498 return rc;
499 }
500
501 CDBG("mt9p012_write_exp_gain: gain = %d, line = %d\n", gain, line);
502
503 rc =
504 mt9p012_i2c_write_w(mt9p012_client->addr,
505 REG_GROUPED_PARAMETER_HOLD,
506 GROUPED_PARAMETER_UPDATE);
507 if (rc < 0)
508 CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
509
510 return rc;
511}
512
513static int32_t mt9p012_set_pict_exp_gain(uint16_t gain, uint32_t line)
514{
515 int32_t rc = 0;
516
517 CDBG("Line:%d mt9p012_set_pict_exp_gain \n", __LINE__);
518
519 rc =
520 mt9p012_write_exp_gain(gain, line);
521 if (rc < 0) {
522 CDBG("Line:%d mt9p012_set_pict_exp_gain failed... \n",
523 __LINE__);
524 return rc;
525 }
526
527 rc =
528 mt9p012_i2c_write_w(mt9p012_client->addr,
529 MT9P012_REG_RESET_REGISTER,
530 0x10CC | 0x0002);
531 if (rc < 0) {
532 CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
533 return rc;
534 }
535
536 mdelay(5);
537
538 /* camera_timed_wait(snapshot_wait*exposure_ratio); */
539 return rc;
540}
541
542static int32_t mt9p012_setting(enum mt9p012_reg_update rupdate,
543 enum mt9p012_setting rt)
544{
545 int32_t rc = 0;
546
547 switch (rupdate) {
548 case UPDATE_PERIODIC:
549 if (rt == RES_PREVIEW || rt == RES_CAPTURE) {
550
551 struct mt9p012_i2c_reg_conf ppc_tbl[] = {
552 {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD},
553 {REG_ROW_SPEED, mt9p012_regs.reg_pat[rt].row_speed},
554 {REG_X_ADDR_START, mt9p012_regs.reg_pat[rt].x_addr_start},
555 {REG_X_ADDR_END, mt9p012_regs.reg_pat[rt].x_addr_end},
556 {REG_Y_ADDR_START, mt9p012_regs.reg_pat[rt].y_addr_start},
557 {REG_Y_ADDR_END, mt9p012_regs.reg_pat[rt].y_addr_end},
558 {REG_READ_MODE, mt9p012_regs.reg_pat[rt].read_mode},
559 {REG_SCALE_M, mt9p012_regs.reg_pat[rt].scale_m},
560 {REG_X_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].x_output_size},
561 {REG_Y_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].y_output_size},
562
563 {REG_LINE_LENGTH_PCK, mt9p012_regs.reg_pat[rt].line_length_pck},
564 {REG_FRAME_LENGTH_LINES,
565 (mt9p012_regs.reg_pat[rt].frame_length_lines *
566 mt9p012_ctrl->fps_divider / 0x00000400)},
567 {REG_COARSE_INT_TIME, mt9p012_regs.reg_pat[rt].coarse_int_time},
568 {REG_FINE_INTEGRATION_TIME, mt9p012_regs.reg_pat[rt].fine_int_time},
569 {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE},
570 };
571
572 rc = mt9p012_i2c_write_w_table(&ppc_tbl[0],
573 ARRAY_SIZE(ppc_tbl));
574 if (rc < 0)
575 return rc;
576
577 rc = mt9p012_test(mt9p012_ctrl->set_test);
578 if (rc < 0)
579 return rc;
580
581 rc =
582 mt9p012_i2c_write_w(mt9p012_client->addr,
583 MT9P012_REG_RESET_REGISTER,
584 MT9P012_RESET_REGISTER_PWON | 0x0002);
585 if (rc < 0)
586 return rc;
587
588 mdelay(5); /* 15? wait for sensor to transition*/
589
590 return rc;
591 }
592 break; /* UPDATE_PERIODIC */
593
594 case REG_INIT:
595 if (rt == RES_PREVIEW || rt == RES_CAPTURE) {
596 struct mt9p012_i2c_reg_conf ipc_tbl1[] = {
597 {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWOFF},
598 {REG_VT_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_pix_clk_div},
599 {REG_VT_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_sys_clk_div},
600 {REG_PRE_PLL_CLK_DIV, mt9p012_regs.reg_pat[rt].pre_pll_clk_div},
601 {REG_PLL_MULTIPLIER, mt9p012_regs.reg_pat[rt].pll_multiplier},
602 {REG_OP_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].op_pix_clk_div},
603 {REG_OP_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].op_sys_clk_div},
604#ifdef MT9P012_REV_7
605 {0x30B0, 0x0001},
606 {0x308E, 0xE060},
607 {0x3092, 0x0A52},
608 {0x3094, 0x4656},
609 {0x3096, 0x5652},
610 {0x30CA, 0x8006},
611 {0x312A, 0xDD02},
612 {0x312C, 0x00E4},
613 {0x3170, 0x299A},
614#endif
615 /* optimized settings for noise */
616 {0x3088, 0x6FF6},
617 {0x3154, 0x0282},
618 {0x3156, 0x0381},
619 {0x3162, 0x04CE},
620 {0x0204, 0x0010},
621 {0x0206, 0x0010},
622 {0x0208, 0x0010},
623 {0x020A, 0x0010},
624 {0x020C, 0x0010},
625 {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWON},
626 };
627
628 struct mt9p012_i2c_reg_conf ipc_tbl2[] = {
629 {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWOFF},
630 {REG_VT_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_pix_clk_div},
631 {REG_VT_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_sys_clk_div},
632 {REG_PRE_PLL_CLK_DIV, mt9p012_regs.reg_pat[rt].pre_pll_clk_div},
633 {REG_PLL_MULTIPLIER, mt9p012_regs.reg_pat[rt].pll_multiplier},
634 {REG_OP_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].op_pix_clk_div},
635 {REG_OP_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].op_sys_clk_div},
636#ifdef MT9P012_REV_7
637 {0x30B0, 0x0001},
638 {0x308E, 0xE060},
639 {0x3092, 0x0A52},
640 {0x3094, 0x4656},
641 {0x3096, 0x5652},
642 {0x30CA, 0x8006},
643 {0x312A, 0xDD02},
644 {0x312C, 0x00E4},
645 {0x3170, 0x299A},
646#endif
647 /* optimized settings for noise */
648 {0x3088, 0x6FF6},
649 {0x3154, 0x0282},
650 {0x3156, 0x0381},
651 {0x3162, 0x04CE},
652 {0x0204, 0x0010},
653 {0x0206, 0x0010},
654 {0x0208, 0x0010},
655 {0x020A, 0x0010},
656 {0x020C, 0x0010},
657 {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWON},
658 };
659
660 struct mt9p012_i2c_reg_conf ipc_tbl3[] = {
661 {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD},
662 /* Set preview or snapshot mode */
663 {REG_ROW_SPEED, mt9p012_regs.reg_pat[rt].row_speed},
664 {REG_X_ADDR_START, mt9p012_regs.reg_pat[rt].x_addr_start},
665 {REG_X_ADDR_END, mt9p012_regs.reg_pat[rt].x_addr_end},
666 {REG_Y_ADDR_START, mt9p012_regs.reg_pat[rt].y_addr_start},
667 {REG_Y_ADDR_END, mt9p012_regs.reg_pat[rt].y_addr_end},
668 {REG_READ_MODE, mt9p012_regs.reg_pat[rt].read_mode},
669 {REG_SCALE_M, mt9p012_regs.reg_pat[rt].scale_m},
670 {REG_X_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].x_output_size},
671 {REG_Y_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].y_output_size},
672 {REG_LINE_LENGTH_PCK, mt9p012_regs.reg_pat[rt].line_length_pck},
673 {REG_FRAME_LENGTH_LINES,
674 mt9p012_regs.reg_pat[rt].frame_length_lines},
675 {REG_COARSE_INT_TIME, mt9p012_regs.reg_pat[rt].coarse_int_time},
676 {REG_FINE_INTEGRATION_TIME, mt9p012_regs.reg_pat[rt].fine_int_time},
677 {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE},
678 };
679
680 /* reset fps_divider */
681 mt9p012_ctrl->fps_divider = 1 * 0x0400;
682
683 rc = mt9p012_i2c_write_w_table(&ipc_tbl1[0],
684 ARRAY_SIZE(ipc_tbl1));
685 if (rc < 0)
686 return rc;
687
688 rc = mt9p012_i2c_write_w_table(&ipc_tbl2[0],
689 ARRAY_SIZE(ipc_tbl2));
690 if (rc < 0)
691 return rc;
692
693 mdelay(5);
694
695 rc = mt9p012_i2c_write_w_table(&ipc_tbl3[0],
696 ARRAY_SIZE(ipc_tbl3));
697 if (rc < 0)
698 return rc;
699
700 /* load lens shading */
701 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
702 REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD);
703 if (rc < 0)
704 return rc;
705
706 rc = mt9p012_set_lc();
707 if (rc < 0)
708 return rc;
709
710 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
711 REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE);
712
713 if (rc < 0)
714 return rc;
715 }
716 break; /* case REG_INIT: */
717
718 default:
719 rc = -EINVAL;
720 break;
721 } /* switch (rupdate) */
722
723 return rc;
724}
725
726static int32_t mt9p012_video_config(int mode, int res)
727{
728 int32_t rc;
729
730 switch (res) {
731 case QTR_SIZE:
732 rc = mt9p012_setting(UPDATE_PERIODIC, RES_PREVIEW);
733 if (rc < 0)
734 return rc;
735
736 CDBG("mt9p012 sensor configuration done!\n");
737 break;
738
739 case FULL_SIZE:
740 rc =
741 mt9p012_setting(UPDATE_PERIODIC, RES_CAPTURE);
742 if (rc < 0)
743 return rc;
744
745 break;
746
747 default:
748 return 0;
749 } /* switch */
750
751 mt9p012_ctrl->prev_res = res;
752 mt9p012_ctrl->curr_res = res;
753 mt9p012_ctrl->sensormode = mode;
754
755 rc =
756 mt9p012_write_exp_gain(mt9p012_ctrl->my_reg_gain,
757 mt9p012_ctrl->my_reg_line_count);
758
759 rc =
760 mt9p012_i2c_write_w(mt9p012_client->addr,
761 MT9P012_REG_RESET_REGISTER,
762 0x10cc|0x0002);
763
764 return rc;
765}
766
767static int32_t mt9p012_snapshot_config(int mode)
768{
769 int32_t rc = 0;
770
771 rc = mt9p012_setting(UPDATE_PERIODIC, RES_CAPTURE);
772 if (rc < 0)
773 return rc;
774
775 mt9p012_ctrl->curr_res = mt9p012_ctrl->pict_res;
776
777 mt9p012_ctrl->sensormode = mode;
778
779 return rc;
780}
781
782static int32_t mt9p012_raw_snapshot_config(int mode)
783{
784 int32_t rc = 0;
785
786 rc = mt9p012_setting(UPDATE_PERIODIC, RES_CAPTURE);
787 if (rc < 0)
788 return rc;
789
790 mt9p012_ctrl->curr_res = mt9p012_ctrl->pict_res;
791
792 mt9p012_ctrl->sensormode = mode;
793
794 return rc;
795}
796
797static int32_t mt9p012_power_down(void)
798{
799 int32_t rc = 0;
800
801 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
802 MT9P012_REG_RESET_REGISTER,
803 MT9P012_RESET_REGISTER_PWOFF);
804
805 mdelay(5);
806 return rc;
807}
808
809static int32_t mt9p012_move_focus(int direction, int32_t num_steps)
810{
811 int16_t step_direction;
812 int16_t actual_step;
813 int16_t next_position;
814 uint8_t code_val_msb, code_val_lsb;
815
816 if (num_steps > MT9P012_TOTAL_STEPS_NEAR_TO_FAR)
817 num_steps = MT9P012_TOTAL_STEPS_NEAR_TO_FAR;
818 else if (num_steps == 0) {
819 CDBG("mt9p012_move_focus failed at line %d ...\n", __LINE__);
820 return -EINVAL;
821 }
822
823 if (direction == MOVE_NEAR)
824 step_direction = 16; /* 10bit */
825 else if (direction == MOVE_FAR)
826 step_direction = -16; /* 10 bit */
827 else {
828 CDBG("mt9p012_move_focus failed at line %d ...\n", __LINE__);
829 return -EINVAL;
830 }
831
832 if (mt9p012_ctrl->curr_lens_pos < mt9p012_ctrl->init_curr_lens_pos)
833 mt9p012_ctrl->curr_lens_pos =
834 mt9p012_ctrl->init_curr_lens_pos;
835
836 actual_step = (int16_t)(step_direction * (int16_t)num_steps);
837 next_position = (int16_t)(mt9p012_ctrl->curr_lens_pos + actual_step);
838
839 if (next_position > 1023)
840 next_position = 1023;
841 else if (next_position < 0)
842 next_position = 0;
843
844 code_val_msb = next_position >> 4;
845 code_val_lsb = (next_position & 0x000F) << 4;
846 /* code_val_lsb |= mode_mask; */
847
848 /* Writing the digital code for current to the actuator */
849 if (mt9p012_i2c_write_b(MT9P012_AF_I2C_ADDR >> 1,
850 code_val_msb, code_val_lsb) < 0) {
851 CDBG("mt9p012_move_focus failed at line %d ...\n", __LINE__);
852 return -EBUSY;
853 }
854
855 /* Storing the current lens Position */
856 mt9p012_ctrl->curr_lens_pos = next_position;
857
858 return 0;
859}
860
861static int32_t mt9p012_set_default_focus(void)
862{
863 int32_t rc = 0;
864 uint8_t code_val_msb, code_val_lsb;
865
866 code_val_msb = 0x00;
867 code_val_lsb = 0x00;
868
869 /* Write the digital code for current to the actuator */
870 rc = mt9p012_i2c_write_b(MT9P012_AF_I2C_ADDR >> 1,
871 code_val_msb, code_val_lsb);
872
873 mt9p012_ctrl->curr_lens_pos = 0;
874 mt9p012_ctrl->init_curr_lens_pos = 0;
875
876 return rc;
877}
878
879static int mt9p012_probe_init_done(const struct msm_camera_sensor_info *data)
880{
881 gpio_direction_output(data->sensor_reset, 0);
882 gpio_free(data->sensor_reset);
883 return 0;
884}
885
886static int mt9p012_probe_init_sensor(const struct msm_camera_sensor_info *data)
887{
888 int32_t rc;
889 uint16_t chipid;
890
891 rc = gpio_request(data->sensor_reset, "mt9p012");
892 if (!rc)
893 gpio_direction_output(data->sensor_reset, 1);
894 else
895 goto init_probe_done;
896
897 mdelay(20);
898
899 /* RESET the sensor image part via I2C command */
900 CDBG("mt9p012_sensor_init(): reseting sensor.\n");
901 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
902 MT9P012_REG_RESET_REGISTER, 0x10CC|0x0001);
903 if (rc < 0) {
904 CDBG("sensor reset failed. rc = %d\n", rc);
905 goto init_probe_fail;
906 }
907
908 mdelay(MT9P012_RESET_DELAY_MSECS);
909
910 /* 3. Read sensor Model ID: */
911 rc = mt9p012_i2c_read_w(mt9p012_client->addr,
912 MT9P012_REG_MODEL_ID, &chipid);
913 if (rc < 0)
914 goto init_probe_fail;
915
916 /* 4. Compare sensor ID to MT9T012VC ID: */
917 if (chipid != MT9P012_MODEL_ID) {
918 CDBG("mt9p012 wrong model_id = 0x%x\n", chipid);
919 rc = -ENODEV;
920 goto init_probe_fail;
921 }
922
923 rc = mt9p012_i2c_write_w(mt9p012_client->addr, 0x306E, 0x9000);
924 if (rc < 0) {
925 CDBG("REV_7 write failed. rc = %d\n", rc);
926 goto init_probe_fail;
927 }
928
929 /* RESET_REGISTER, enable parallel interface and disable serialiser */
930 CDBG("mt9p012_sensor_init(): enabling parallel interface.\n");
931 rc = mt9p012_i2c_write_w(mt9p012_client->addr, 0x301A, 0x10CC);
932 if (rc < 0) {
933 CDBG("enable parallel interface failed. rc = %d\n", rc);
934 goto init_probe_fail;
935 }
936
937 /* To disable the 2 extra lines */
938 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
939 0x3064, 0x0805);
940
941 if (rc < 0) {
942 CDBG("disable the 2 extra lines failed. rc = %d\n", rc);
943 goto init_probe_fail;
944 }
945
946 mdelay(MT9P012_RESET_DELAY_MSECS);
947 goto init_probe_done;
948
949init_probe_fail:
950 mt9p012_probe_init_done(data);
951init_probe_done:
952 return rc;
953}
954
955static int mt9p012_sensor_open_init(const struct msm_camera_sensor_info *data)
956{
957 int32_t rc;
958
959 mt9p012_ctrl = kzalloc(sizeof(struct mt9p012_ctrl), GFP_KERNEL);
960 if (!mt9p012_ctrl) {
961 CDBG("mt9p012_init failed!\n");
962 rc = -ENOMEM;
963 goto init_done;
964 }
965
966 mt9p012_ctrl->fps_divider = 1 * 0x00000400;
967 mt9p012_ctrl->pict_fps_divider = 1 * 0x00000400;
968 mt9p012_ctrl->set_test = TEST_OFF;
969 mt9p012_ctrl->prev_res = QTR_SIZE;
970 mt9p012_ctrl->pict_res = FULL_SIZE;
971
972 if (data)
973 mt9p012_ctrl->sensordata = data;
974
975 /* enable mclk first */
976 msm_camio_clk_rate_set(MT9P012_DEFAULT_CLOCK_RATE);
977 mdelay(20);
978
979 msm_camio_camif_pad_reg_reset();
980 mdelay(20);
981
982 rc = mt9p012_probe_init_sensor(data);
983 if (rc < 0)
984 goto init_fail1;
985
986 if (mt9p012_ctrl->prev_res == QTR_SIZE)
987 rc = mt9p012_setting(REG_INIT, RES_PREVIEW);
988 else
989 rc = mt9p012_setting(REG_INIT, RES_CAPTURE);
990
991 if (rc < 0) {
992 CDBG("mt9p012_setting failed. rc = %d\n", rc);
993 goto init_fail1;
994 }
995
996 /* sensor : output enable */
997 CDBG("mt9p012_sensor_open_init(): enabling output.\n");
998 rc = mt9p012_i2c_write_w(mt9p012_client->addr,
999 MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWON);
1000 if (rc < 0) {
1001 CDBG("sensor output enable failed. rc = %d\n", rc);
1002 goto init_fail1;
1003 }
1004
1005 /* TODO: enable AF actuator */
1006#if 0
1007 CDBG("enable AF actuator, gpio = %d\n",
1008 mt9p012_ctrl->sensordata->vcm_pwd);
1009 rc = gpio_request(mt9p012_ctrl->sensordata->vcm_pwd, "mt9p012");
1010 if (!rc)
1011 gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 1);
1012 else {
1013 CDBG("mt9p012_ctrl gpio request failed!\n");
1014 goto init_fail1;
1015 }
1016 mdelay(20);
1017
1018 rc = mt9p012_set_default_focus();
1019#endif
1020 if (rc >= 0)
1021 goto init_done;
1022
1023 /* TODO:
1024 * gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 0);
1025 * gpio_free(mt9p012_ctrl->sensordata->vcm_pwd); */
1026init_fail1:
1027 mt9p012_probe_init_done(data);
1028 kfree(mt9p012_ctrl);
1029init_done:
1030 return rc;
1031}
1032
1033static int mt9p012_init_client(struct i2c_client *client)
1034{
1035 /* Initialize the MSM_CAMI2C Chip */
1036 init_waitqueue_head(&mt9p012_wait_queue);
1037 return 0;
1038}
1039
1040static int32_t mt9p012_set_sensor_mode(int mode, int res)
1041{
1042 int32_t rc = 0;
1043
1044 switch (mode) {
1045 case SENSOR_PREVIEW_MODE:
1046 rc = mt9p012_video_config(mode, res);
1047 break;
1048
1049 case SENSOR_SNAPSHOT_MODE:
1050 rc = mt9p012_snapshot_config(mode);
1051 break;
1052
1053 case SENSOR_RAW_SNAPSHOT_MODE:
1054 rc = mt9p012_raw_snapshot_config(mode);
1055 break;
1056
1057 default:
1058 rc = -EINVAL;
1059 break;
1060 }
1061
1062 return rc;
1063}
1064
1065int mt9p012_sensor_config(void __user *argp)
1066{
1067 struct sensor_cfg_data cdata;
1068 int rc = 0;
1069
1070 if (copy_from_user(&cdata,
1071 (void *)argp,
1072 sizeof(struct sensor_cfg_data)))
1073 return -EFAULT;
1074
1075 down(&mt9p012_sem);
1076
1077 CDBG("%s: cfgtype = %d\n", __func__, cdata.cfgtype);
1078 switch (cdata.cfgtype) {
1079 case CFG_GET_PICT_FPS:
1080 mt9p012_get_pict_fps(cdata.cfg.gfps.prevfps,
1081 &(cdata.cfg.gfps.pictfps));
1082
1083 if (copy_to_user((void *)argp, &cdata,
1084 sizeof(struct sensor_cfg_data)))
1085 rc = -EFAULT;
1086 break;
1087
1088 case CFG_GET_PREV_L_PF:
1089 cdata.cfg.prevl_pf = mt9p012_get_prev_lines_pf();
1090
1091 if (copy_to_user((void *)argp,
1092 &cdata,
1093 sizeof(struct sensor_cfg_data)))
1094 rc = -EFAULT;
1095 break;
1096
1097 case CFG_GET_PREV_P_PL:
1098 cdata.cfg.prevp_pl = mt9p012_get_prev_pixels_pl();
1099
1100 if (copy_to_user((void *)argp,
1101 &cdata,
1102 sizeof(struct sensor_cfg_data)))
1103 rc = -EFAULT;
1104 break;
1105
1106 case CFG_GET_PICT_L_PF:
1107 cdata.cfg.pictl_pf = mt9p012_get_pict_lines_pf();
1108
1109 if (copy_to_user((void *)argp,
1110 &cdata,
1111 sizeof(struct sensor_cfg_data)))
1112 rc = -EFAULT;
1113 break;
1114
1115 case CFG_GET_PICT_P_PL:
1116 cdata.cfg.pictp_pl = mt9p012_get_pict_pixels_pl();
1117
1118 if (copy_to_user((void *)argp,
1119 &cdata,
1120 sizeof(struct sensor_cfg_data)))
1121 rc = -EFAULT;
1122 break;
1123
1124 case CFG_GET_PICT_MAX_EXP_LC:
1125 cdata.cfg.pict_max_exp_lc =
1126 mt9p012_get_pict_max_exp_lc();
1127
1128 if (copy_to_user((void *)argp,
1129 &cdata,
1130 sizeof(struct sensor_cfg_data)))
1131 rc = -EFAULT;
1132 break;
1133
1134 case CFG_SET_FPS:
1135 case CFG_SET_PICT_FPS:
1136 rc = mt9p012_set_fps(&(cdata.cfg.fps));
1137 break;
1138
1139 case CFG_SET_EXP_GAIN:
1140 rc = mt9p012_write_exp_gain(cdata.cfg.exp_gain.gain,
1141 cdata.cfg.exp_gain.line);
1142 break;
1143
1144 case CFG_SET_PICT_EXP_GAIN:
1145 CDBG("Line:%d CFG_SET_PICT_EXP_GAIN \n", __LINE__);
1146 rc = mt9p012_set_pict_exp_gain(cdata.cfg.exp_gain.gain,
1147 cdata.cfg.exp_gain.line);
1148 break;
1149
1150 case CFG_SET_MODE:
1151 rc = mt9p012_set_sensor_mode(cdata.mode, cdata.rs);
1152 break;
1153
1154 case CFG_PWR_DOWN:
1155 rc = mt9p012_power_down();
1156 break;
1157
1158 case CFG_MOVE_FOCUS:
1159 CDBG("mt9p012_ioctl: CFG_MOVE_FOCUS: cdata.cfg.focus.dir=%d cdata.cfg.focus.steps=%d\n",
1160 cdata.cfg.focus.dir, cdata.cfg.focus.steps);
1161 rc = mt9p012_move_focus(cdata.cfg.focus.dir,
1162 cdata.cfg.focus.steps);
1163 break;
1164
1165 case CFG_SET_DEFAULT_FOCUS:
1166 rc = mt9p012_set_default_focus();
1167 break;
1168
1169 case CFG_SET_LENS_SHADING:
1170 CDBG("%s: CFG_SET_LENS_SHADING\n", __func__);
1171 rc = mt9p012_lens_shading_enable(cdata.cfg.lens_shading);
1172 break;
1173
1174 case CFG_GET_AF_MAX_STEPS:
1175 cdata.max_steps = MT9P012_STEPS_NEAR_TO_CLOSEST_INF;
1176 if (copy_to_user((void *)argp,
1177 &cdata,
1178 sizeof(struct sensor_cfg_data)))
1179 rc = -EFAULT;
1180 break;
1181
1182 case CFG_SET_EFFECT:
1183 default:
1184 rc = -EINVAL;
1185 break;
1186 }
1187
1188 up(&mt9p012_sem);
1189 return rc;
1190}
1191
1192int mt9p012_sensor_release(void)
1193{
1194 int rc = -EBADF;
1195
1196 down(&mt9p012_sem);
1197
1198 mt9p012_power_down();
1199
1200 gpio_direction_output(mt9p012_ctrl->sensordata->sensor_reset,
1201 0);
1202 gpio_free(mt9p012_ctrl->sensordata->sensor_reset);
1203
1204 gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 0);
1205 gpio_free(mt9p012_ctrl->sensordata->vcm_pwd);
1206
1207 kfree(mt9p012_ctrl);
1208 mt9p012_ctrl = NULL;
1209
1210 CDBG("mt9p012_release completed\n");
1211
1212 up(&mt9p012_sem);
1213 return rc;
1214}
1215
1216static int mt9p012_i2c_probe(struct i2c_client *client,
1217 const struct i2c_device_id *id)
1218{
1219 int rc = 0;
1220 CDBG("mt9p012_probe called!\n");
1221
1222 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1223 CDBG("i2c_check_functionality failed\n");
1224 goto probe_failure;
1225 }
1226
1227 mt9p012_sensorw = kzalloc(sizeof(struct mt9p012_work), GFP_KERNEL);
1228 if (!mt9p012_sensorw) {
1229 CDBG("kzalloc failed.\n");
1230 rc = -ENOMEM;
1231 goto probe_failure;
1232 }
1233
1234 i2c_set_clientdata(client, mt9p012_sensorw);
1235 mt9p012_init_client(client);
1236 mt9p012_client = client;
1237
1238 mdelay(50);
1239
1240 CDBG("mt9p012_probe successed! rc = %d\n", rc);
1241 return 0;
1242
1243probe_failure:
1244 CDBG("mt9p012_probe failed! rc = %d\n", rc);
1245 return rc;
1246}
1247
1248static const struct i2c_device_id mt9p012_i2c_id[] = {
1249 { "mt9p012", 0},
1250 { }
1251};
1252
1253static struct i2c_driver mt9p012_i2c_driver = {
1254 .id_table = mt9p012_i2c_id,
1255 .probe = mt9p012_i2c_probe,
1256 .remove = __exit_p(mt9p012_i2c_remove),
1257 .driver = {
1258 .name = "mt9p012",
1259 },
1260};
1261
1262static int mt9p012_sensor_probe(const struct msm_camera_sensor_info *info,
1263 struct msm_sensor_ctrl *s)
1264{
1265 int rc = i2c_add_driver(&mt9p012_i2c_driver);
1266 if (rc < 0 || mt9p012_client == NULL) {
1267 rc = -ENOTSUPP;
1268 goto probe_done;
1269 }
1270
1271 msm_camio_clk_rate_set(MT9P012_DEFAULT_CLOCK_RATE);
1272 mdelay(20);
1273
1274 rc = mt9p012_probe_init_sensor(info);
1275 if (rc < 0)
1276 goto probe_done;
1277
1278 s->s_init = mt9p012_sensor_open_init;
1279 s->s_release = mt9p012_sensor_release;
1280 s->s_config = mt9p012_sensor_config;
1281 mt9p012_probe_init_done(info);
1282
1283probe_done:
1284 CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
1285 return rc;
1286}
1287
1288static int __mt9p012_probe(struct platform_device *pdev)
1289{
1290 return msm_camera_drv_start(pdev, mt9p012_sensor_probe);
1291}
1292
1293static struct platform_driver msm_camera_driver = {
1294 .probe = __mt9p012_probe,
1295 .driver = {
1296 .name = "msm_camera_mt9p012",
1297 .owner = THIS_MODULE,
1298 },
1299};
1300
1301static int __init mt9p012_init(void)
1302{
1303 return platform_driver_register(&msm_camera_driver);
1304}
1305
1306module_init(mt9p012_init);