2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
5 #include <linux/delay.h>
6 #include <linux/slab.h>
7 #include <linux/types.h>
9 #include <linux/uaccess.h>
10 #include <linux/miscdevice.h>
11 #include <media/msm_camera.h>
12 #include <mach/gpio.h>
13 #include <mach/camera.h>
16 #define S5K3E2FX_REG_MODEL_ID 0x0000
17 #define S5K3E2FX_MODEL_ID 0x3E2F
20 #define REG_PRE_PLL_CLK_DIV 0x0305
21 #define REG_PLL_MULTIPLIER_MSB 0x0306
22 #define REG_PLL_MULTIPLIER_LSB 0x0307
23 #define REG_VT_PIX_CLK_DIV 0x0301
24 #define REG_VT_SYS_CLK_DIV 0x0303
25 #define REG_OP_PIX_CLK_DIV 0x0309
26 #define REG_OP_SYS_CLK_DIV 0x030B
28 /* Data Format Registers */
29 #define REG_CCP_DATA_FORMAT_MSB 0x0112
30 #define REG_CCP_DATA_FORMAT_LSB 0x0113
33 #define REG_X_OUTPUT_SIZE_MSB 0x034C
34 #define REG_X_OUTPUT_SIZE_LSB 0x034D
35 #define REG_Y_OUTPUT_SIZE_MSB 0x034E
36 #define REG_Y_OUTPUT_SIZE_LSB 0x034F
39 #define REG_X_EVEN_INC 0x0381
40 #define REG_X_ODD_INC 0x0383
41 #define REG_Y_EVEN_INC 0x0385
42 #define REG_Y_ODD_INC 0x0387
43 /*Reserved register */
44 #define REG_BINNING_ENABLE 0x3014
47 #define REG_FRAME_LENGTH_LINES_MSB 0x0340
48 #define REG_FRAME_LENGTH_LINES_LSB 0x0341
49 #define REG_LINE_LENGTH_PCK_MSB 0x0342
50 #define REG_LINE_LENGTH_PCK_LSB 0x0343
53 /* Reserved registers */
54 #define REG_SHADE_CLK_ENABLE 0x30AC
55 #define REG_SEL_CCP 0x30C4
56 #define REG_VPIX 0x3024
57 #define REG_CLAMP_ON 0x3015
58 #define REG_OFFSET 0x307E
60 /* CDS timing settings */
61 /* Reserved registers */
62 #define REG_LD_START 0x3000
63 #define REG_LD_END 0x3001
64 #define REG_SL_START 0x3002
65 #define REG_SL_END 0x3003
66 #define REG_RX_START 0x3004
67 #define REG_S1_START 0x3005
68 #define REG_S1_END 0x3006
69 #define REG_S1S_START 0x3007
70 #define REG_S1S_END 0x3008
71 #define REG_S3_START 0x3009
72 #define REG_S3_END 0x300A
73 #define REG_CMP_EN_START 0x300B
74 #define REG_CLP_SL_START 0x300C
75 #define REG_CLP_SL_END 0x300D
76 #define REG_OFF_START 0x300E
77 #define REG_RMP_EN_START 0x300F
78 #define REG_TX_START 0x3010
79 #define REG_TX_END 0x3011
80 #define REG_STX_WIDTH 0x3012
81 #define REG_TYPE1_AF_ENABLE 0x3130
82 #define DRIVER_ENABLED 0x0001
83 #define AUTO_START_ENABLED 0x0010
84 #define REG_NEW_POSITION 0x3131
85 #define REG_3152_RESERVED 0x3152
86 #define REG_315A_RESERVED 0x315A
87 #define REG_ANALOGUE_GAIN_CODE_GLOBAL_MSB 0x0204
88 #define REG_ANALOGUE_GAIN_CODE_GLOBAL_LSB 0x0205
89 #define REG_FINE_INTEGRATION_TIME 0x0200
90 #define REG_COARSE_INTEGRATION_TIME 0x0202
91 #define REG_COARSE_INTEGRATION_TIME_LSB 0x0203
93 /* Mode select register */
94 #define S5K3E2FX_REG_MODE_SELECT 0x0100
95 #define S5K3E2FX_MODE_SELECT_STREAM 0x01 /* start streaming */
96 #define S5K3E2FX_MODE_SELECT_SW_STANDBY 0x00 /* software standby */
97 #define S5K3E2FX_REG_SOFTWARE_RESET 0x0103
98 #define S5K3E2FX_SOFTWARE_RESET 0x01
99 #define REG_TEST_PATTERN_MODE 0x0601
102 uint8_t pre_pll_clk_div
; /* 0x0305 */
103 uint8_t pll_multiplier_msb
; /* 0x0306 */
104 uint8_t pll_multiplier_lsb
; /* 0x0307 */
105 uint8_t vt_pix_clk_div
; /* 0x0301 */
106 uint8_t vt_sys_clk_div
; /* 0x0303 */
107 uint8_t op_pix_clk_div
; /* 0x0309 */
108 uint8_t op_sys_clk_div
; /* 0x030B */
109 uint8_t ccp_data_format_msb
; /* 0x0112 */
110 uint8_t ccp_data_format_lsb
; /* 0x0113 */
111 uint8_t x_output_size_msb
; /* 0x034C */
112 uint8_t x_output_size_lsb
; /* 0x034D */
113 uint8_t y_output_size_msb
; /* 0x034E */
114 uint8_t y_output_size_lsb
; /* 0x034F */
115 uint8_t x_even_inc
; /* 0x0381 */
116 uint8_t x_odd_inc
; /* 0x0383 */
117 uint8_t y_even_inc
; /* 0x0385 */
118 uint8_t y_odd_inc
; /* 0x0387 */
119 uint8_t binning_enable
; /* 0x3014 */
120 uint8_t frame_length_lines_msb
; /* 0x0340 */
121 uint8_t frame_length_lines_lsb
; /* 0x0341 */
122 uint8_t line_length_pck_msb
; /* 0x0342 */
123 uint8_t line_length_pck_lsb
; /* 0x0343 */
124 uint8_t shade_clk_enable
; /* 0x30AC */
125 uint8_t sel_ccp
; /* 0x30C4 */
126 uint8_t vpix
; /* 0x3024 */
127 uint8_t clamp_on
; /* 0x3015 */
128 uint8_t offset
; /* 0x307E */
129 uint8_t ld_start
; /* 0x3000 */
130 uint8_t ld_end
; /* 0x3001 */
131 uint8_t sl_start
; /* 0x3002 */
132 uint8_t sl_end
; /* 0x3003 */
133 uint8_t rx_start
; /* 0x3004 */
134 uint8_t s1_start
; /* 0x3005 */
135 uint8_t s1_end
; /* 0x3006 */
136 uint8_t s1s_start
; /* 0x3007 */
137 uint8_t s1s_end
; /* 0x3008 */
138 uint8_t s3_start
; /* 0x3009 */
139 uint8_t s3_end
; /* 0x300A */
140 uint8_t cmp_en_start
; /* 0x300B */
141 uint8_t clp_sl_start
; /* 0x300C */
142 uint8_t clp_sl_end
; /* 0x300D */
143 uint8_t off_start
; /* 0x300E */
144 uint8_t rmp_en_start
; /* 0x300F */
145 uint8_t tx_start
; /* 0x3010 */
146 uint8_t tx_end
; /* 0x3011 */
147 uint8_t stx_width
; /* 0x3012 */
148 uint8_t reg_3152_reserved
; /* 0x3152 */
149 uint8_t reg_315A_reserved
; /* 0x315A */
150 uint8_t analogue_gain_code_global_msb
; /* 0x0204 */
151 uint8_t analogue_gain_code_global_lsb
; /* 0x0205 */
152 uint8_t fine_integration_time
; /* 0x0200 */
153 uint8_t coarse_integration_time
; /* 0x0202 */
160 struct reg_struct s5k3e2fx_reg_pat
[2] = {
162 0x06, /* pre_pll_clk_div REG=0x0305 */
163 0x00, /* pll_multiplier_msb REG=0x0306 */
164 0x88, /* pll_multiplier_lsb REG=0x0307 */
165 0x0a, /* vt_pix_clk_div REG=0x0301 */
166 0x01, /* vt_sys_clk_div REG=0x0303 */
167 0x0a, /* op_pix_clk_div REG=0x0309 */
168 0x01, /* op_sys_clk_div REG=0x030B */
169 0x0a, /* ccp_data_format_msb REG=0x0112 */
170 0x0a, /* ccp_data_format_lsb REG=0x0113 */
171 0x05, /* x_output_size_msb REG=0x034C */
172 0x10, /* x_output_size_lsb REG=0x034D */
173 0x03, /* y_output_size_msb REG=0x034E */
174 0xcc, /* y_output_size_lsb REG=0x034F */
176 /* enable binning for preview */
177 0x01, /* x_even_inc REG=0x0381 */
178 0x01, /* x_odd_inc REG=0x0383 */
179 0x01, /* y_even_inc REG=0x0385 */
180 0x03, /* y_odd_inc REG=0x0387 */
181 0x06, /* binning_enable REG=0x3014 */
183 0x03, /* frame_length_lines_msb REG=0x0340 */
184 0xde, /* frame_length_lines_lsb REG=0x0341 */
185 0x0a, /* line_length_pck_msb REG=0x0342 */
186 0xac, /* line_length_pck_lsb REG=0x0343 */
187 0x81, /* shade_clk_enable REG=0x30AC */
188 0x01, /* sel_ccp REG=0x30C4 */
189 0x04, /* vpix REG=0x3024 */
190 0x00, /* clamp_on REG=0x3015 */
191 0x02, /* offset REG=0x307E */
192 0x03, /* ld_start REG=0x3000 */
193 0x9c, /* ld_end REG=0x3001 */
194 0x02, /* sl_start REG=0x3002 */
195 0x9e, /* sl_end REG=0x3003 */
196 0x05, /* rx_start REG=0x3004 */
197 0x0f, /* s1_start REG=0x3005 */
198 0x24, /* s1_end REG=0x3006 */
199 0x7c, /* s1s_start REG=0x3007 */
200 0x9a, /* s1s_end REG=0x3008 */
201 0x10, /* s3_start REG=0x3009 */
202 0x14, /* s3_end REG=0x300A */
203 0x10, /* cmp_en_start REG=0x300B */
204 0x04, /* clp_sl_start REG=0x300C */
205 0x26, /* clp_sl_end REG=0x300D */
206 0x02, /* off_start REG=0x300E */
207 0x0e, /* rmp_en_start REG=0x300F */
208 0x30, /* tx_start REG=0x3010 */
209 0x4e, /* tx_end REG=0x3011 */
210 0x1E, /* stx_width REG=0x3012 */
211 0x08, /* reg_3152_reserved REG=0x3152 */
212 0x10, /* reg_315A_reserved REG=0x315A */
213 0x00, /* analogue_gain_code_global_msb REG=0x0204 */
214 0x80, /* analogue_gain_code_global_lsb REG=0x0205 */
215 0x02, /* fine_integration_time REG=0x0200 */
216 0x03, /* coarse_integration_time REG=0x0202 */
223 0x06, /* pre_pll_clk_div REG=0x0305 */
224 0x00, /* pll_multiplier_msb REG=0x0306 */
225 0x88, /* pll_multiplier_lsb REG=0x0307 */
226 0x0a, /* vt_pix_clk_div REG=0x0301 */
227 0x01, /* vt_sys_clk_div REG=0x0303 */
228 0x0a, /* op_pix_clk_div REG=0x0309 */
229 0x01, /* op_sys_clk_div REG=0x030B */
230 0x0a, /* ccp_data_format_msb REG=0x0112 */
231 0x0a, /* ccp_data_format_lsb REG=0x0113 */
232 0x0a, /* x_output_size_msb REG=0x034C */
233 0x30, /* x_output_size_lsb REG=0x034D */
234 0x07, /* y_output_size_msb REG=0x034E */
235 0xa8, /* y_output_size_lsb REG=0x034F */
237 /* disable binning for snapshot */
238 0x01, /* x_even_inc REG=0x0381 */
239 0x01, /* x_odd_inc REG=0x0383 */
240 0x01, /* y_even_inc REG=0x0385 */
241 0x01, /* y_odd_inc REG=0x0387 */
242 0x00, /* binning_enable REG=0x3014 */
244 0x07, /* frame_length_lines_msb REG=0x0340 */
245 0xb6, /* frame_length_lines_lsb REG=0x0341 */
246 0x0a, /* line_length_pck_msb REG=0x0342 */
247 0xac, /* line_length_pck_lsb REG=0x0343 */
248 0x81, /* shade_clk_enable REG=0x30AC */
249 0x01, /* sel_ccp REG=0x30C4 */
250 0x04, /* vpix REG=0x3024 */
251 0x00, /* clamp_on REG=0x3015 */
252 0x02, /* offset REG=0x307E */
253 0x03, /* ld_start REG=0x3000 */
254 0x9c, /* ld_end REG=0x3001 */
255 0x02, /* sl_start REG=0x3002 */
256 0x9e, /* sl_end REG=0x3003 */
257 0x05, /* rx_start REG=0x3004 */
258 0x0f, /* s1_start REG=0x3005 */
259 0x24, /* s1_end REG=0x3006 */
260 0x7c, /* s1s_start REG=0x3007 */
261 0x9a, /* s1s_end REG=0x3008 */
262 0x10, /* s3_start REG=0x3009 */
263 0x14, /* s3_end REG=0x300A */
264 0x10, /* cmp_en_start REG=0x300B */
265 0x04, /* clp_sl_start REG=0x300C */
266 0x26, /* clp_sl_end REG=0x300D */
267 0x02, /* off_start REG=0x300E */
268 0x0e, /* rmp_en_start REG=0x300F */
269 0x30, /* tx_start REG=0x3010 */
270 0x4e, /* tx_end REG=0x3011 */
271 0x1E, /* stx_width REG=0x3012 */
272 0x08, /* reg_3152_reserved REG=0x3152 */
273 0x10, /* reg_315A_reserved REG=0x315A */
274 0x00, /* analogue_gain_code_global_msb REG=0x0204 */
275 0x80, /* analogue_gain_code_global_lsb REG=0x0205 */
276 0x02, /* fine_integration_time REG=0x0200 */
277 0x03, /* coarse_integration_time REG=0x0202 */
285 struct s5k3e2fx_work
{
286 struct work_struct work
;
288 static struct s5k3e2fx_work
*s5k3e2fx_sensorw
;
289 static struct i2c_client
*s5k3e2fx_client
;
291 struct s5k3e2fx_ctrl
{
292 const struct msm_camera_sensor_info
*sensordata
;
295 uint32_t fps_divider
; /* init to 1 * 0x00000400 */
296 uint32_t pict_fps_divider
; /* init to 1 * 0x00000400 */
298 uint16_t curr_lens_pos
;
299 uint16_t init_curr_lens_pos
;
300 uint16_t my_reg_gain
;
301 uint32_t my_reg_line_count
;
303 enum msm_s_resolution prev_res
;
304 enum msm_s_resolution pict_res
;
305 enum msm_s_resolution curr_res
;
306 enum msm_s_test_mode set_test
;
309 struct s5k3e2fx_i2c_reg_conf
{
310 unsigned short waddr
;
314 static struct s5k3e2fx_ctrl
*s5k3e2fx_ctrl
;
315 static DECLARE_WAIT_QUEUE_HEAD(s5k3e2fx_wait_queue
);
316 DECLARE_MUTEX(s5k3e2fx_sem
);
318 static int s5k3e2fx_i2c_rxdata(unsigned short saddr
, unsigned char *rxdata
,
321 struct i2c_msg msgs
[] = {
336 if (i2c_transfer(s5k3e2fx_client
->adapter
, msgs
, 2) < 0) {
337 CDBG("s5k3e2fx_i2c_rxdata failed!\n");
344 static int32_t s5k3e2fx_i2c_txdata(unsigned short saddr
,
345 unsigned char *txdata
, int length
)
347 struct i2c_msg msg
[] = {
356 if (i2c_transfer(s5k3e2fx_client
->adapter
, msg
, 1) < 0) {
357 CDBG("s5k3e2fx_i2c_txdata failed\n");
364 static int32_t s5k3e2fx_i2c_write_b(unsigned short saddr
, unsigned short waddr
,
368 unsigned char buf
[4];
370 memset(buf
, 0, sizeof(buf
));
371 buf
[0] = (waddr
& 0xFF00)>>8;
372 buf
[1] = (waddr
& 0x00FF);
375 rc
= s5k3e2fx_i2c_txdata(saddr
, buf
, 3);
378 CDBG("i2c_write_w failed, addr = 0x%x, val = 0x%x!\n",
384 static int32_t s5k3e2fx_i2c_write_table(
385 struct s5k3e2fx_i2c_reg_conf
*reg_cfg_tbl
, int num
)
389 for (i
= 0; i
< num
; i
++) {
398 static int32_t s5k3e2fx_i2c_read_w(unsigned short saddr
, unsigned short raddr
,
399 unsigned short *rdata
)
402 unsigned char buf
[4];
407 memset(buf
, 0, sizeof(buf
));
409 buf
[0] = (raddr
& 0xFF00)>>8;
410 buf
[1] = (raddr
& 0x00FF);
412 rc
= s5k3e2fx_i2c_rxdata(saddr
, buf
, 2);
416 *rdata
= buf
[0] << 8 | buf
[1];
419 CDBG("s5k3e2fx_i2c_read failed!\n");
424 static int s5k3e2fx_probe_init_done(const struct msm_camera_sensor_info
*data
)
426 gpio_direction_output(data
->sensor_reset
, 0);
427 gpio_free(data
->sensor_reset
);
431 static int s5k3e2fx_probe_init_sensor(const struct msm_camera_sensor_info
*data
)
436 rc
= gpio_request(data
->sensor_reset
, "s5k3e2fx");
438 gpio_direction_output(data
->sensor_reset
, 1);
440 goto init_probe_done
;
444 CDBG("s5k3e2fx_sensor_init(): reseting sensor.\n");
446 rc
= s5k3e2fx_i2c_read_w(s5k3e2fx_client
->addr
,
447 S5K3E2FX_REG_MODEL_ID
, &chipid
);
449 goto init_probe_fail
;
451 if (chipid
!= S5K3E2FX_MODEL_ID
) {
452 CDBG("S5K3E2FX wrong model_id = 0x%x\n", chipid
);
454 goto init_probe_fail
;
457 goto init_probe_done
;
460 s5k3e2fx_probe_init_done(data
);
465 static int s5k3e2fx_init_client(struct i2c_client
*client
)
467 /* Initialize the MSM_CAMI2C Chip */
468 init_waitqueue_head(&s5k3e2fx_wait_queue
);
472 static const struct i2c_device_id s5k3e2fx_i2c_id
[] = {
477 static int s5k3e2fx_i2c_probe(struct i2c_client
*client
,
478 const struct i2c_device_id
*id
)
481 CDBG("s5k3e2fx_probe called!\n");
483 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
484 CDBG("i2c_check_functionality failed\n");
488 s5k3e2fx_sensorw
= kzalloc(sizeof(struct s5k3e2fx_work
), GFP_KERNEL
);
489 if (!s5k3e2fx_sensorw
) {
490 CDBG("kzalloc failed.\n");
495 i2c_set_clientdata(client
, s5k3e2fx_sensorw
);
496 s5k3e2fx_init_client(client
);
497 s5k3e2fx_client
= client
;
501 CDBG("s5k3e2fx_probe successed! rc = %d\n", rc
);
505 CDBG("s5k3e2fx_probe failed! rc = %d\n", rc
);
509 static struct i2c_driver s5k3e2fx_i2c_driver
= {
510 .id_table
= s5k3e2fx_i2c_id
,
511 .probe
= s5k3e2fx_i2c_probe
,
512 .remove
= __exit_p(s5k3e2fx_i2c_remove
),
518 static int32_t s5k3e2fx_test(enum msm_s_test_mode mo
)
522 if (mo
== S_TEST_OFF
)
525 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
,
526 REG_TEST_PATTERN_MODE
, (uint16_t)mo
);
531 static int32_t s5k3e2fx_setting(enum msm_s_reg_update rupdate
,
532 enum msm_s_setting rt
)
538 case S_UPDATE_PERIODIC
:
539 if (rt
== S_RES_PREVIEW
|| rt
== S_RES_CAPTURE
) {
541 struct s5k3e2fx_i2c_reg_conf tbl_1
[] = {
542 {REG_CCP_DATA_FORMAT_MSB
, s5k3e2fx_reg_pat
[rt
].ccp_data_format_msb
},
543 {REG_CCP_DATA_FORMAT_LSB
, s5k3e2fx_reg_pat
[rt
].ccp_data_format_lsb
},
544 {REG_X_OUTPUT_SIZE_MSB
, s5k3e2fx_reg_pat
[rt
].x_output_size_msb
},
545 {REG_X_OUTPUT_SIZE_LSB
, s5k3e2fx_reg_pat
[rt
].x_output_size_lsb
},
546 {REG_Y_OUTPUT_SIZE_MSB
, s5k3e2fx_reg_pat
[rt
].y_output_size_msb
},
547 {REG_Y_OUTPUT_SIZE_LSB
, s5k3e2fx_reg_pat
[rt
].y_output_size_lsb
},
548 {REG_X_EVEN_INC
, s5k3e2fx_reg_pat
[rt
].x_even_inc
},
549 {REG_X_ODD_INC
, s5k3e2fx_reg_pat
[rt
].x_odd_inc
},
550 {REG_Y_EVEN_INC
, s5k3e2fx_reg_pat
[rt
].y_even_inc
},
551 {REG_Y_ODD_INC
, s5k3e2fx_reg_pat
[rt
].y_odd_inc
},
552 {REG_BINNING_ENABLE
, s5k3e2fx_reg_pat
[rt
].binning_enable
},
555 struct s5k3e2fx_i2c_reg_conf tbl_2
[] = {
556 {REG_FRAME_LENGTH_LINES_MSB
, 0},
557 {REG_FRAME_LENGTH_LINES_LSB
, 0},
558 {REG_LINE_LENGTH_PCK_MSB
, s5k3e2fx_reg_pat
[rt
].line_length_pck_msb
},
559 {REG_LINE_LENGTH_PCK_LSB
, s5k3e2fx_reg_pat
[rt
].line_length_pck_lsb
},
560 {REG_SHADE_CLK_ENABLE
, s5k3e2fx_reg_pat
[rt
].shade_clk_enable
},
561 {REG_SEL_CCP
, s5k3e2fx_reg_pat
[rt
].sel_ccp
},
562 {REG_VPIX
, s5k3e2fx_reg_pat
[rt
].vpix
},
563 {REG_CLAMP_ON
, s5k3e2fx_reg_pat
[rt
].clamp_on
},
564 {REG_OFFSET
, s5k3e2fx_reg_pat
[rt
].offset
},
565 {REG_LD_START
, s5k3e2fx_reg_pat
[rt
].ld_start
},
566 {REG_LD_END
, s5k3e2fx_reg_pat
[rt
].ld_end
},
567 {REG_SL_START
, s5k3e2fx_reg_pat
[rt
].sl_start
},
568 {REG_SL_END
, s5k3e2fx_reg_pat
[rt
].sl_end
},
569 {REG_RX_START
, s5k3e2fx_reg_pat
[rt
].rx_start
},
570 {REG_S1_START
, s5k3e2fx_reg_pat
[rt
].s1_start
},
571 {REG_S1_END
, s5k3e2fx_reg_pat
[rt
].s1_end
},
572 {REG_S1S_START
, s5k3e2fx_reg_pat
[rt
].s1s_start
},
573 {REG_S1S_END
, s5k3e2fx_reg_pat
[rt
].s1s_end
},
574 {REG_S3_START
, s5k3e2fx_reg_pat
[rt
].s3_start
},
575 {REG_S3_END
, s5k3e2fx_reg_pat
[rt
].s3_end
},
576 {REG_CMP_EN_START
, s5k3e2fx_reg_pat
[rt
].cmp_en_start
},
577 {REG_CLP_SL_START
, s5k3e2fx_reg_pat
[rt
].clp_sl_start
},
578 {REG_CLP_SL_END
, s5k3e2fx_reg_pat
[rt
].clp_sl_end
},
579 {REG_OFF_START
, s5k3e2fx_reg_pat
[rt
].off_start
},
580 {REG_RMP_EN_START
, s5k3e2fx_reg_pat
[rt
].rmp_en_start
},
581 {REG_TX_START
, s5k3e2fx_reg_pat
[rt
].tx_start
},
582 {REG_TX_END
, s5k3e2fx_reg_pat
[rt
].tx_end
},
583 {REG_STX_WIDTH
, s5k3e2fx_reg_pat
[rt
].stx_width
},
584 {REG_3152_RESERVED
, s5k3e2fx_reg_pat
[rt
].reg_3152_reserved
},
585 {REG_315A_RESERVED
, s5k3e2fx_reg_pat
[rt
].reg_315A_reserved
},
586 {REG_ANALOGUE_GAIN_CODE_GLOBAL_MSB
, s5k3e2fx_reg_pat
[rt
].analogue_gain_code_global_msb
},
587 {REG_ANALOGUE_GAIN_CODE_GLOBAL_LSB
, s5k3e2fx_reg_pat
[rt
].analogue_gain_code_global_lsb
},
588 {REG_FINE_INTEGRATION_TIME
, s5k3e2fx_reg_pat
[rt
].fine_integration_time
},
589 {REG_COARSE_INTEGRATION_TIME
, s5k3e2fx_reg_pat
[rt
].coarse_integration_time
},
590 {S5K3E2FX_REG_MODE_SELECT
, S5K3E2FX_MODE_SELECT_STREAM
},
593 rc
= s5k3e2fx_i2c_write_table(&tbl_1
[0],
599 (uint16_t)((s5k3e2fx_reg_pat
[rt
].frame_length_lines_msb
<< 8) & 0xFF00) +
600 s5k3e2fx_reg_pat
[rt
].frame_length_lines_lsb
;
602 num_lperf
= num_lperf
* s5k3e2fx_ctrl
->fps_divider
/ 0x0400;
604 tbl_2
[0] = (struct s5k3e2fx_i2c_reg_conf
) {REG_FRAME_LENGTH_LINES_MSB
, (num_lperf
& 0xFF00) >> 8};
605 tbl_2
[1] = (struct s5k3e2fx_i2c_reg_conf
) {REG_FRAME_LENGTH_LINES_LSB
, (num_lperf
& 0x00FF)};
607 rc
= s5k3e2fx_i2c_write_table(&tbl_2
[0],
614 rc
= s5k3e2fx_test(s5k3e2fx_ctrl
->set_test
);
618 break; /* UPDATE_PERIODIC */
621 if (rt
== S_RES_PREVIEW
|| rt
== S_RES_CAPTURE
) {
623 struct s5k3e2fx_i2c_reg_conf tbl_3
[] = {
624 {S5K3E2FX_REG_SOFTWARE_RESET
, S5K3E2FX_SOFTWARE_RESET
},
625 {S5K3E2FX_REG_MODE_SELECT
, S5K3E2FX_MODE_SELECT_SW_STANDBY
},
627 {REG_PRE_PLL_CLK_DIV
, s5k3e2fx_reg_pat
[rt
].pre_pll_clk_div
},
628 {REG_PLL_MULTIPLIER_MSB
, s5k3e2fx_reg_pat
[rt
].pll_multiplier_msb
},
629 {REG_PLL_MULTIPLIER_LSB
, s5k3e2fx_reg_pat
[rt
].pll_multiplier_lsb
},
630 {REG_VT_PIX_CLK_DIV
, s5k3e2fx_reg_pat
[rt
].vt_pix_clk_div
},
631 {REG_VT_SYS_CLK_DIV
, s5k3e2fx_reg_pat
[rt
].vt_sys_clk_div
},
632 {REG_OP_PIX_CLK_DIV
, s5k3e2fx_reg_pat
[rt
].op_pix_clk_div
},
633 {REG_OP_SYS_CLK_DIV
, s5k3e2fx_reg_pat
[rt
].op_sys_clk_div
},
635 {REG_CCP_DATA_FORMAT_MSB
, s5k3e2fx_reg_pat
[rt
].ccp_data_format_msb
},
636 {REG_CCP_DATA_FORMAT_LSB
, s5k3e2fx_reg_pat
[rt
].ccp_data_format_lsb
},
638 {REG_X_OUTPUT_SIZE_MSB
, s5k3e2fx_reg_pat
[rt
].x_output_size_msb
},
639 {REG_X_OUTPUT_SIZE_LSB
, s5k3e2fx_reg_pat
[rt
].x_output_size_lsb
},
640 {REG_Y_OUTPUT_SIZE_MSB
, s5k3e2fx_reg_pat
[rt
].y_output_size_msb
},
641 {REG_Y_OUTPUT_SIZE_LSB
, s5k3e2fx_reg_pat
[rt
].y_output_size_lsb
},
643 {REG_X_EVEN_INC
, s5k3e2fx_reg_pat
[rt
].x_even_inc
},
644 {REG_X_ODD_INC
, s5k3e2fx_reg_pat
[rt
].x_odd_inc
},
645 {REG_Y_EVEN_INC
, s5k3e2fx_reg_pat
[rt
].y_even_inc
},
646 {REG_Y_ODD_INC
, s5k3e2fx_reg_pat
[rt
].y_odd_inc
},
647 {REG_BINNING_ENABLE
, s5k3e2fx_reg_pat
[rt
].binning_enable
},
649 {REG_FRAME_LENGTH_LINES_MSB
, s5k3e2fx_reg_pat
[rt
].frame_length_lines_msb
},
650 {REG_FRAME_LENGTH_LINES_LSB
, s5k3e2fx_reg_pat
[rt
].frame_length_lines_lsb
},
651 {REG_LINE_LENGTH_PCK_MSB
, s5k3e2fx_reg_pat
[rt
].line_length_pck_msb
},
652 {REG_LINE_LENGTH_PCK_LSB
, s5k3e2fx_reg_pat
[rt
].line_length_pck_lsb
},
654 {REG_SHADE_CLK_ENABLE
, s5k3e2fx_reg_pat
[rt
].shade_clk_enable
},
655 {REG_SEL_CCP
, s5k3e2fx_reg_pat
[rt
].sel_ccp
},
656 {REG_VPIX
, s5k3e2fx_reg_pat
[rt
].vpix
},
657 {REG_CLAMP_ON
, s5k3e2fx_reg_pat
[rt
].clamp_on
},
658 {REG_OFFSET
, s5k3e2fx_reg_pat
[rt
].offset
},
659 /* CDS timing setting */
660 {REG_LD_START
, s5k3e2fx_reg_pat
[rt
].ld_start
},
661 {REG_LD_END
, s5k3e2fx_reg_pat
[rt
].ld_end
},
662 {REG_SL_START
, s5k3e2fx_reg_pat
[rt
].sl_start
},
663 {REG_SL_END
, s5k3e2fx_reg_pat
[rt
].sl_end
},
664 {REG_RX_START
, s5k3e2fx_reg_pat
[rt
].rx_start
},
665 {REG_S1_START
, s5k3e2fx_reg_pat
[rt
].s1_start
},
666 {REG_S1_END
, s5k3e2fx_reg_pat
[rt
].s1_end
},
667 {REG_S1S_START
, s5k3e2fx_reg_pat
[rt
].s1s_start
},
668 {REG_S1S_END
, s5k3e2fx_reg_pat
[rt
].s1s_end
},
669 {REG_S3_START
, s5k3e2fx_reg_pat
[rt
].s3_start
},
670 {REG_S3_END
, s5k3e2fx_reg_pat
[rt
].s3_end
},
671 {REG_CMP_EN_START
, s5k3e2fx_reg_pat
[rt
].cmp_en_start
},
672 {REG_CLP_SL_START
, s5k3e2fx_reg_pat
[rt
].clp_sl_start
},
673 {REG_CLP_SL_END
, s5k3e2fx_reg_pat
[rt
].clp_sl_end
},
674 {REG_OFF_START
, s5k3e2fx_reg_pat
[rt
].off_start
},
675 {REG_RMP_EN_START
, s5k3e2fx_reg_pat
[rt
].rmp_en_start
},
676 {REG_TX_START
, s5k3e2fx_reg_pat
[rt
].tx_start
},
677 {REG_TX_END
, s5k3e2fx_reg_pat
[rt
].tx_end
},
678 {REG_STX_WIDTH
, s5k3e2fx_reg_pat
[rt
].stx_width
},
679 {REG_3152_RESERVED
, s5k3e2fx_reg_pat
[rt
].reg_3152_reserved
},
680 {REG_315A_RESERVED
, s5k3e2fx_reg_pat
[rt
].reg_315A_reserved
},
681 {REG_ANALOGUE_GAIN_CODE_GLOBAL_MSB
, s5k3e2fx_reg_pat
[rt
].analogue_gain_code_global_msb
},
682 {REG_ANALOGUE_GAIN_CODE_GLOBAL_LSB
, s5k3e2fx_reg_pat
[rt
].analogue_gain_code_global_lsb
},
683 {REG_FINE_INTEGRATION_TIME
, s5k3e2fx_reg_pat
[rt
].fine_integration_time
},
684 {REG_COARSE_INTEGRATION_TIME
, s5k3e2fx_reg_pat
[rt
].coarse_integration_time
},
685 {S5K3E2FX_REG_MODE_SELECT
, S5K3E2FX_MODE_SELECT_STREAM
},
688 /* reset fps_divider */
689 s5k3e2fx_ctrl
->fps_divider
= 1 * 0x0400;
690 rc
= s5k3e2fx_i2c_write_table(&tbl_3
[0],
695 break; /* case REG_INIT: */
700 } /* switch (rupdate) */
705 static int s5k3e2fx_sensor_open_init(const struct msm_camera_sensor_info
*data
)
709 s5k3e2fx_ctrl
= kzalloc(sizeof(struct s5k3e2fx_ctrl
), GFP_KERNEL
);
710 if (!s5k3e2fx_ctrl
) {
711 CDBG("s5k3e2fx_init failed!\n");
716 s5k3e2fx_ctrl
->fps_divider
= 1 * 0x00000400;
717 s5k3e2fx_ctrl
->pict_fps_divider
= 1 * 0x00000400;
718 s5k3e2fx_ctrl
->set_test
= S_TEST_OFF
;
719 s5k3e2fx_ctrl
->prev_res
= S_QTR_SIZE
;
720 s5k3e2fx_ctrl
->pict_res
= S_FULL_SIZE
;
723 s5k3e2fx_ctrl
->sensordata
= data
;
725 /* enable mclk first */
726 msm_camio_clk_rate_set(24000000);
729 msm_camio_camif_pad_reg_reset();
732 rc
= s5k3e2fx_probe_init_sensor(data
);
736 if (s5k3e2fx_ctrl
->prev_res
== S_QTR_SIZE
)
737 rc
= s5k3e2fx_setting(S_REG_INIT
, S_RES_PREVIEW
);
739 rc
= s5k3e2fx_setting(S_REG_INIT
, S_RES_CAPTURE
);
742 CDBG("s5k3e2fx_setting failed. rc = %d\n", rc
);
747 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
, 0x3146, 0x3A);
751 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
, 0x3130, 0x03);
758 s5k3e2fx_probe_init_done(data
);
759 kfree(s5k3e2fx_ctrl
);
764 static int32_t s5k3e2fx_power_down(void)
770 static int s5k3e2fx_sensor_release(void)
776 s5k3e2fx_power_down();
778 gpio_direction_output(s5k3e2fx_ctrl
->sensordata
->sensor_reset
,
780 gpio_free(s5k3e2fx_ctrl
->sensordata
->sensor_reset
);
782 kfree(s5k3e2fx_ctrl
);
783 s5k3e2fx_ctrl
= NULL
;
785 CDBG("s5k3e2fx_release completed\n");
791 static void s5k3e2fx_get_pict_fps(uint16_t fps
, uint16_t *pfps
)
793 /* input fps is preview fps in Q8 format */
794 uint32_t divider
; /* Q10 */
797 ((s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_h
+
798 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].blk_l
) *
799 (s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_w
+
800 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].blk_p
)) * 0x00000400 /
801 ((s5k3e2fx_reg_pat
[S_RES_CAPTURE
].size_h
+
802 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_l
) *
803 (s5k3e2fx_reg_pat
[S_RES_CAPTURE
].size_w
+
804 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_p
));
806 /* Verify PCLK settings and frame sizes. */
807 *pfps
= (uint16_t)(fps
* divider
/ 0x00000400);
810 static uint16_t s5k3e2fx_get_prev_lines_pf(void)
812 return (s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_h
+
813 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].blk_l
);
816 static uint16_t s5k3e2fx_get_prev_pixels_pl(void)
818 return s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_w
+
819 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].blk_p
;
822 static uint16_t s5k3e2fx_get_pict_lines_pf(void)
824 return s5k3e2fx_reg_pat
[S_RES_CAPTURE
].size_h
+
825 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_l
;
828 static uint16_t s5k3e2fx_get_pict_pixels_pl(void)
830 return s5k3e2fx_reg_pat
[S_RES_CAPTURE
].size_w
+
831 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_p
;
834 static uint32_t s5k3e2fx_get_pict_max_exp_lc(void)
836 uint32_t snapshot_lines_per_frame
;
838 if (s5k3e2fx_ctrl
->pict_res
== S_QTR_SIZE
)
839 snapshot_lines_per_frame
=
840 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_h
+
841 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].blk_l
;
843 snapshot_lines_per_frame
= 3961 * 3;
845 return snapshot_lines_per_frame
;
848 static int32_t s5k3e2fx_set_fps(struct fps_cfg
*fps
)
850 /* input is new fps in Q10 format */
853 s5k3e2fx_ctrl
->fps_divider
= fps
->fps_div
;
855 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
,
856 REG_FRAME_LENGTH_LINES_MSB
,
857 (((s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_h
+
858 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].blk_l
) *
859 s5k3e2fx_ctrl
->fps_divider
/ 0x400) & 0xFF00) >> 8);
863 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
,
864 REG_FRAME_LENGTH_LINES_LSB
,
865 (((s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_h
+
866 s5k3e2fx_reg_pat
[S_RES_PREVIEW
].blk_l
) *
867 s5k3e2fx_ctrl
->fps_divider
/ 0x400) & 0xFF00));
873 static int32_t s5k3e2fx_write_exp_gain(uint16_t gain
, uint32_t line
)
877 uint16_t max_legal_gain
= 0x0200;
878 uint32_t ll_ratio
; /* Q10 */
879 uint16_t ll_pck
, fl_lines
;
881 uint8_t gain_msb
, gain_lsb
;
882 uint8_t intg_t_msb
, intg_t_lsb
;
883 uint8_t ll_pck_msb
, ll_pck_lsb
, tmp
;
885 struct s5k3e2fx_i2c_reg_conf tbl
[2];
887 CDBG("Line:%d s5k3e2fx_write_exp_gain \n", __LINE__
);
889 if (s5k3e2fx_ctrl
->sensormode
== SENSOR_PREVIEW_MODE
) {
891 s5k3e2fx_ctrl
->my_reg_gain
= gain
;
892 s5k3e2fx_ctrl
->my_reg_line_count
= (uint16_t)line
;
894 fl_lines
= s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_h
+
895 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_l
;
897 ll_pck
= s5k3e2fx_reg_pat
[S_RES_PREVIEW
].size_w
+
898 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_p
;
902 fl_lines
= s5k3e2fx_reg_pat
[S_RES_CAPTURE
].size_h
+
903 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_l
;
905 ll_pck
= s5k3e2fx_reg_pat
[S_RES_CAPTURE
].size_w
+
906 s5k3e2fx_reg_pat
[S_RES_CAPTURE
].blk_p
;
909 if (gain
> max_legal_gain
)
910 gain
= max_legal_gain
;
913 line
= (line
* s5k3e2fx_ctrl
->fps_divider
);
915 if (fl_lines
< (line
/ 0x400))
916 ll_ratio
= (line
/ (fl_lines
- offset
));
920 /* update gain registers */
921 gain_msb
= (gain
& 0xFF00) >> 8;
922 gain_lsb
= gain
& 0x00FF;
923 tbl
[0].waddr
= REG_ANALOGUE_GAIN_CODE_GLOBAL_MSB
;
924 tbl
[0].bdata
= gain_msb
;
925 tbl
[1].waddr
= REG_ANALOGUE_GAIN_CODE_GLOBAL_LSB
;
926 tbl
[1].bdata
= gain_lsb
;
927 rc
= s5k3e2fx_i2c_write_table(&tbl
[0], ARRAY_SIZE(tbl
));
929 goto write_gain_done
;
931 ll_pck
= ll_pck
* ll_ratio
;
932 ll_pck_msb
= ((ll_pck
/ 0x400) & 0xFF00) >> 8;
933 ll_pck_lsb
= (ll_pck
/ 0x400) & 0x00FF;
934 tbl
[0].waddr
= REG_LINE_LENGTH_PCK_MSB
;
935 tbl
[0].bdata
= s5k3e2fx_reg_pat
[S_RES_PREVIEW
].line_length_pck_msb
;
936 tbl
[1].waddr
= REG_LINE_LENGTH_PCK_LSB
;
937 tbl
[1].bdata
= s5k3e2fx_reg_pat
[S_RES_PREVIEW
].line_length_pck_lsb
;
938 rc
= s5k3e2fx_i2c_write_table(&tbl
[0], ARRAY_SIZE(tbl
));
940 goto write_gain_done
;
942 tmp
= (ll_pck
* 0x400) / ll_ratio
;
943 intg_t_msb
= (tmp
& 0xFF00) >> 8;
944 intg_t_lsb
= (tmp
& 0x00FF);
945 tbl
[0].waddr
= REG_COARSE_INTEGRATION_TIME
;
946 tbl
[0].bdata
= intg_t_msb
;
947 tbl
[1].waddr
= REG_COARSE_INTEGRATION_TIME_LSB
;
948 tbl
[1].bdata
= intg_t_lsb
;
949 rc
= s5k3e2fx_i2c_write_table(&tbl
[0], ARRAY_SIZE(tbl
));
955 static int32_t s5k3e2fx_set_pict_exp_gain(uint16_t gain
, uint32_t line
)
959 CDBG("Line:%d s5k3e2fx_set_pict_exp_gain \n", __LINE__
);
962 s5k3e2fx_write_exp_gain(gain
, line
);
967 static int32_t s5k3e2fx_video_config(int mode
, int res
)
973 rc
= s5k3e2fx_setting(S_UPDATE_PERIODIC
, S_RES_PREVIEW
);
977 CDBG("s5k3e2fx sensor configuration done!\n");
981 rc
= s5k3e2fx_setting(S_UPDATE_PERIODIC
, S_RES_CAPTURE
);
991 s5k3e2fx_ctrl
->prev_res
= res
;
992 s5k3e2fx_ctrl
->curr_res
= res
;
993 s5k3e2fx_ctrl
->sensormode
= mode
;
996 s5k3e2fx_write_exp_gain(s5k3e2fx_ctrl
->my_reg_gain
,
997 s5k3e2fx_ctrl
->my_reg_line_count
);
1002 static int32_t s5k3e2fx_snapshot_config(int mode
)
1006 rc
= s5k3e2fx_setting(S_UPDATE_PERIODIC
, S_RES_CAPTURE
);
1010 s5k3e2fx_ctrl
->curr_res
= s5k3e2fx_ctrl
->pict_res
;
1011 s5k3e2fx_ctrl
->sensormode
= mode
;
1016 static int32_t s5k3e2fx_raw_snapshot_config(int mode
)
1020 rc
= s5k3e2fx_setting(S_UPDATE_PERIODIC
, S_RES_CAPTURE
);
1024 s5k3e2fx_ctrl
->curr_res
= s5k3e2fx_ctrl
->pict_res
;
1025 s5k3e2fx_ctrl
->sensormode
= mode
;
1030 static int32_t s5k3e2fx_set_sensor_mode(int mode
, int res
)
1035 case SENSOR_PREVIEW_MODE
:
1036 rc
= s5k3e2fx_video_config(mode
, res
);
1039 case SENSOR_SNAPSHOT_MODE
:
1040 rc
= s5k3e2fx_snapshot_config(mode
);
1043 case SENSOR_RAW_SNAPSHOT_MODE
:
1044 rc
= s5k3e2fx_raw_snapshot_config(mode
);
1055 static int32_t s5k3e2fx_set_default_focus(void)
1059 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
,
1064 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
,
1069 s5k3e2fx_ctrl
->curr_lens_pos
= 0;
1074 static int32_t s5k3e2fx_move_focus(int direction
, int32_t num_steps
)
1078 int16_t step_direction
;
1079 int16_t actual_step
;
1080 int16_t next_pos
, pos_offset
;
1081 int16_t init_code
= 50;
1082 uint8_t next_pos_msb
, next_pos_lsb
;
1084 uint32_t gain
; /* Q10 format */
1086 if (direction
== MOVE_NEAR
)
1087 step_direction
= 20;
1088 else if (direction
== MOVE_FAR
)
1089 step_direction
= -20;
1091 CDBG("s5k3e2fx_move_focus failed at line %d ...\n", __LINE__
);
1095 actual_step
= step_direction
* (int16_t)num_steps
;
1096 pos_offset
= init_code
+ s5k3e2fx_ctrl
->curr_lens_pos
;
1097 gain
= ((actual_step
<< 10) / 5) >> 10;
1099 for (i
= 0; i
<= 4; i
++)
1102 /* Ring Damping Code */
1103 for (i
= 0; i
<= 4; i
++) {
1104 next_pos
= (int16_t)(pos_offset
+ s_move
[i
]);
1106 if (next_pos
> (738 + init_code
))
1107 next_pos
= 738 + init_code
;
1108 else if (next_pos
< 0)
1111 CDBG("next_position in damping mode = %d\n", next_pos
);
1112 /* Writing the Values to the actuator */
1113 if (next_pos
== init_code
)
1116 next_pos_msb
= next_pos
>> 8;
1117 next_pos_lsb
= next_pos
& 0x00FF;
1119 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
, 0x3131, next_pos_msb
);
1123 rc
= s5k3e2fx_i2c_write_b(s5k3e2fx_client
->addr
, 0x3132, next_pos_lsb
);
1127 pos_offset
= next_pos
;
1128 s5k3e2fx_ctrl
->curr_lens_pos
= pos_offset
- init_code
;
1136 static int s5k3e2fx_sensor_config(void __user
*argp
)
1138 struct sensor_cfg_data cdata
;
1141 if (copy_from_user(&cdata
,
1143 sizeof(struct sensor_cfg_data
)))
1146 down(&s5k3e2fx_sem
);
1148 CDBG("%s: cfgtype = %d\n", __func__
, cdata
.cfgtype
);
1149 switch (cdata
.cfgtype
) {
1150 case CFG_GET_PICT_FPS
:
1151 s5k3e2fx_get_pict_fps(cdata
.cfg
.gfps
.prevfps
,
1152 &(cdata
.cfg
.gfps
.pictfps
));
1154 if (copy_to_user((void *)argp
, &cdata
,
1155 sizeof(struct sensor_cfg_data
)))
1159 case CFG_GET_PREV_L_PF
:
1160 cdata
.cfg
.prevl_pf
= s5k3e2fx_get_prev_lines_pf();
1162 if (copy_to_user((void *)argp
,
1164 sizeof(struct sensor_cfg_data
)))
1168 case CFG_GET_PREV_P_PL
:
1169 cdata
.cfg
.prevp_pl
= s5k3e2fx_get_prev_pixels_pl();
1171 if (copy_to_user((void *)argp
,
1173 sizeof(struct sensor_cfg_data
)))
1177 case CFG_GET_PICT_L_PF
:
1178 cdata
.cfg
.pictl_pf
= s5k3e2fx_get_pict_lines_pf();
1180 if (copy_to_user((void *)argp
,
1182 sizeof(struct sensor_cfg_data
)))
1186 case CFG_GET_PICT_P_PL
:
1187 cdata
.cfg
.pictp_pl
= s5k3e2fx_get_pict_pixels_pl();
1189 if (copy_to_user((void *)argp
,
1191 sizeof(struct sensor_cfg_data
)))
1195 case CFG_GET_PICT_MAX_EXP_LC
:
1196 cdata
.cfg
.pict_max_exp_lc
=
1197 s5k3e2fx_get_pict_max_exp_lc();
1199 if (copy_to_user((void *)argp
,
1201 sizeof(struct sensor_cfg_data
)))
1206 case CFG_SET_PICT_FPS
:
1207 rc
= s5k3e2fx_set_fps(&(cdata
.cfg
.fps
));
1210 case CFG_SET_EXP_GAIN
:
1212 s5k3e2fx_write_exp_gain(cdata
.cfg
.exp_gain
.gain
,
1213 cdata
.cfg
.exp_gain
.line
);
1216 case CFG_SET_PICT_EXP_GAIN
:
1217 CDBG("Line:%d CFG_SET_PICT_EXP_GAIN \n", __LINE__
);
1219 s5k3e2fx_set_pict_exp_gain(
1220 cdata
.cfg
.exp_gain
.gain
,
1221 cdata
.cfg
.exp_gain
.line
);
1226 s5k3e2fx_set_sensor_mode(
1227 cdata
.mode
, cdata
.rs
);
1231 rc
= s5k3e2fx_power_down();
1234 case CFG_MOVE_FOCUS
:
1236 s5k3e2fx_move_focus(
1237 cdata
.cfg
.focus
.dir
,
1238 cdata
.cfg
.focus
.steps
);
1241 case CFG_SET_DEFAULT_FOCUS
:
1243 s5k3e2fx_set_default_focus();
1246 case CFG_GET_AF_MAX_STEPS
:
1247 case CFG_SET_EFFECT
:
1248 case CFG_SET_LENS_SHADING
:
1258 static int s5k3e2fx_sensor_probe(const struct msm_camera_sensor_info
*info
,
1259 struct msm_sensor_ctrl
*s
)
1263 rc
= i2c_add_driver(&s5k3e2fx_i2c_driver
);
1264 if (rc
< 0 || s5k3e2fx_client
== NULL
) {
1269 msm_camio_clk_rate_set(24000000);
1272 rc
= s5k3e2fx_probe_init_sensor(info
);
1276 s
->s_init
= s5k3e2fx_sensor_open_init
;
1277 s
->s_release
= s5k3e2fx_sensor_release
;
1278 s
->s_config
= s5k3e2fx_sensor_config
;
1279 s5k3e2fx_probe_init_done(info
);
1284 CDBG("SENSOR PROBE FAILS!\n");
1288 static int __s5k3e2fx_probe(struct platform_device
*pdev
)
1290 return msm_camera_drv_start(pdev
, s5k3e2fx_sensor_probe
);
1293 static struct platform_driver msm_camera_driver
= {
1294 .probe
= __s5k3e2fx_probe
,
1296 .name
= "msm_camera_s5k3e2fx",
1297 .owner
= THIS_MODULE
,
1301 static int __init
s5k3e2fx_init(void)
1303 return platform_driver_register(&msm_camera_driver
);
1306 module_init(s5k3e2fx_init
);