• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/dream/camera/
1/*
2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
3 */
4
5#include <linux/delay.h>
6#include <linux/types.h>
7#include <linux/slab.h>
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);
126DECLARE_MUTEX(mt9p012_sem);
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 (rc >= 0)
1007		goto init_done;
1008
1009	/* TODO:
1010	 * gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 0);
1011	 * gpio_free(mt9p012_ctrl->sensordata->vcm_pwd); */
1012init_fail1:
1013	mt9p012_probe_init_done(data);
1014	kfree(mt9p012_ctrl);
1015init_done:
1016	return rc;
1017}
1018
1019static int mt9p012_init_client(struct i2c_client *client)
1020{
1021	/* Initialize the MSM_CAMI2C Chip */
1022	init_waitqueue_head(&mt9p012_wait_queue);
1023	return 0;
1024}
1025
1026static int32_t mt9p012_set_sensor_mode(int mode, int res)
1027{
1028	int32_t rc = 0;
1029
1030	switch (mode) {
1031	case SENSOR_PREVIEW_MODE:
1032		rc = mt9p012_video_config(mode, res);
1033		break;
1034
1035	case SENSOR_SNAPSHOT_MODE:
1036		rc = mt9p012_snapshot_config(mode);
1037		break;
1038
1039	case SENSOR_RAW_SNAPSHOT_MODE:
1040		rc = mt9p012_raw_snapshot_config(mode);
1041		break;
1042
1043	default:
1044		rc = -EINVAL;
1045		break;
1046	}
1047
1048	return rc;
1049}
1050
1051int mt9p012_sensor_config(void __user *argp)
1052{
1053	struct sensor_cfg_data cdata;
1054	int rc = 0;
1055
1056	if (copy_from_user(&cdata,
1057			(void *)argp,
1058			sizeof(struct sensor_cfg_data)))
1059		return -EFAULT;
1060
1061	down(&mt9p012_sem);
1062
1063		CDBG("%s: cfgtype = %d\n", __func__, cdata.cfgtype);
1064	switch (cdata.cfgtype) {
1065	case CFG_GET_PICT_FPS:
1066		mt9p012_get_pict_fps(cdata.cfg.gfps.prevfps,
1067				&(cdata.cfg.gfps.pictfps));
1068
1069		if (copy_to_user((void *)argp, &cdata,
1070				sizeof(struct sensor_cfg_data)))
1071			rc = -EFAULT;
1072		break;
1073
1074	case CFG_GET_PREV_L_PF:
1075		cdata.cfg.prevl_pf = mt9p012_get_prev_lines_pf();
1076
1077		if (copy_to_user((void *)argp,
1078				&cdata,
1079				sizeof(struct sensor_cfg_data)))
1080			rc = -EFAULT;
1081		break;
1082
1083	case CFG_GET_PREV_P_PL:
1084		cdata.cfg.prevp_pl = mt9p012_get_prev_pixels_pl();
1085
1086		if (copy_to_user((void *)argp,
1087				&cdata,
1088				sizeof(struct sensor_cfg_data)))
1089			rc = -EFAULT;
1090		break;
1091
1092	case CFG_GET_PICT_L_PF:
1093		cdata.cfg.pictl_pf = mt9p012_get_pict_lines_pf();
1094
1095		if (copy_to_user((void *)argp,
1096				&cdata,
1097				sizeof(struct sensor_cfg_data)))
1098			rc = -EFAULT;
1099		break;
1100
1101	case CFG_GET_PICT_P_PL:
1102		cdata.cfg.pictp_pl = mt9p012_get_pict_pixels_pl();
1103
1104		if (copy_to_user((void *)argp,
1105				&cdata,
1106				sizeof(struct sensor_cfg_data)))
1107			rc = -EFAULT;
1108		break;
1109
1110	case CFG_GET_PICT_MAX_EXP_LC:
1111		cdata.cfg.pict_max_exp_lc =
1112			mt9p012_get_pict_max_exp_lc();
1113
1114		if (copy_to_user((void *)argp,
1115				&cdata,
1116				sizeof(struct sensor_cfg_data)))
1117			rc = -EFAULT;
1118		break;
1119
1120	case CFG_SET_FPS:
1121	case CFG_SET_PICT_FPS:
1122		rc = mt9p012_set_fps(&(cdata.cfg.fps));
1123		break;
1124
1125	case CFG_SET_EXP_GAIN:
1126		rc = mt9p012_write_exp_gain(cdata.cfg.exp_gain.gain,
1127				cdata.cfg.exp_gain.line);
1128		break;
1129
1130	case CFG_SET_PICT_EXP_GAIN:
1131		CDBG("Line:%d CFG_SET_PICT_EXP_GAIN \n", __LINE__);
1132		rc = mt9p012_set_pict_exp_gain(cdata.cfg.exp_gain.gain,
1133				cdata.cfg.exp_gain.line);
1134		break;
1135
1136	case CFG_SET_MODE:
1137		rc = mt9p012_set_sensor_mode(cdata.mode, cdata.rs);
1138		break;
1139
1140	case CFG_PWR_DOWN:
1141		rc = mt9p012_power_down();
1142		break;
1143
1144	case CFG_MOVE_FOCUS:
1145		CDBG("mt9p012_ioctl: CFG_MOVE_FOCUS: cdata.cfg.focus.dir=%d cdata.cfg.focus.steps=%d\n",
1146				cdata.cfg.focus.dir, cdata.cfg.focus.steps);
1147		rc = mt9p012_move_focus(cdata.cfg.focus.dir,
1148					cdata.cfg.focus.steps);
1149		break;
1150
1151	case CFG_SET_DEFAULT_FOCUS:
1152		rc = mt9p012_set_default_focus();
1153		break;
1154
1155	case CFG_SET_LENS_SHADING:
1156		CDBG("%s: CFG_SET_LENS_SHADING\n", __func__);
1157		rc = mt9p012_lens_shading_enable(cdata.cfg.lens_shading);
1158		break;
1159
1160	case CFG_GET_AF_MAX_STEPS:
1161		cdata.max_steps = MT9P012_STEPS_NEAR_TO_CLOSEST_INF;
1162		if (copy_to_user((void *)argp,
1163				&cdata,
1164				sizeof(struct sensor_cfg_data)))
1165			rc = -EFAULT;
1166		break;
1167
1168	case CFG_SET_EFFECT:
1169	default:
1170		rc = -EINVAL;
1171		break;
1172	}
1173
1174	up(&mt9p012_sem);
1175	return rc;
1176}
1177
1178int mt9p012_sensor_release(void)
1179{
1180	int rc = -EBADF;
1181
1182	down(&mt9p012_sem);
1183
1184	mt9p012_power_down();
1185
1186	gpio_direction_output(mt9p012_ctrl->sensordata->sensor_reset,
1187		0);
1188	gpio_free(mt9p012_ctrl->sensordata->sensor_reset);
1189
1190	gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 0);
1191	gpio_free(mt9p012_ctrl->sensordata->vcm_pwd);
1192
1193	kfree(mt9p012_ctrl);
1194	mt9p012_ctrl = NULL;
1195
1196	CDBG("mt9p012_release completed\n");
1197
1198	up(&mt9p012_sem);
1199	return rc;
1200}
1201
1202static int mt9p012_i2c_probe(struct i2c_client *client,
1203	const struct i2c_device_id *id)
1204{
1205	int rc = 0;
1206	CDBG("mt9p012_probe called!\n");
1207
1208	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1209		CDBG("i2c_check_functionality failed\n");
1210		goto probe_failure;
1211	}
1212
1213	mt9p012_sensorw = kzalloc(sizeof(struct mt9p012_work), GFP_KERNEL);
1214	if (!mt9p012_sensorw) {
1215		CDBG("kzalloc failed.\n");
1216		rc = -ENOMEM;
1217		goto probe_failure;
1218	}
1219
1220	i2c_set_clientdata(client, mt9p012_sensorw);
1221	mt9p012_init_client(client);
1222	mt9p012_client = client;
1223
1224	mdelay(50);
1225
1226	CDBG("mt9p012_probe successed! rc = %d\n", rc);
1227	return 0;
1228
1229probe_failure:
1230	CDBG("mt9p012_probe failed! rc = %d\n", rc);
1231	return rc;
1232}
1233
1234static const struct i2c_device_id mt9p012_i2c_id[] = {
1235	{ "mt9p012", 0},
1236	{ }
1237};
1238
1239static struct i2c_driver mt9p012_i2c_driver = {
1240	.id_table = mt9p012_i2c_id,
1241	.probe  = mt9p012_i2c_probe,
1242	.remove = __exit_p(mt9p012_i2c_remove),
1243	.driver = {
1244		.name = "mt9p012",
1245	},
1246};
1247
1248static int mt9p012_sensor_probe(const struct msm_camera_sensor_info *info,
1249				struct msm_sensor_ctrl *s)
1250{
1251	int rc = i2c_add_driver(&mt9p012_i2c_driver);
1252	if (rc < 0 || mt9p012_client == NULL) {
1253		rc = -ENOTSUPP;
1254		goto probe_done;
1255	}
1256
1257	msm_camio_clk_rate_set(MT9P012_DEFAULT_CLOCK_RATE);
1258	mdelay(20);
1259
1260	rc = mt9p012_probe_init_sensor(info);
1261	if (rc < 0)
1262		goto probe_done;
1263
1264	s->s_init = mt9p012_sensor_open_init;
1265	s->s_release = mt9p012_sensor_release;
1266	s->s_config  = mt9p012_sensor_config;
1267	mt9p012_probe_init_done(info);
1268
1269probe_done:
1270	CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
1271	return rc;
1272}
1273
1274static int __mt9p012_probe(struct platform_device *pdev)
1275{
1276	return msm_camera_drv_start(pdev, mt9p012_sensor_probe);
1277}
1278
1279static struct platform_driver msm_camera_driver = {
1280	.probe = __mt9p012_probe,
1281	.driver = {
1282		.name = "msm_camera_mt9p012",
1283		.owner = THIS_MODULE,
1284	},
1285};
1286
1287static int __init mt9p012_init(void)
1288{
1289	return platform_driver_register(&msm_camera_driver);
1290}
1291
1292module_init(mt9p012_init);
1293