1 #include <linux/bitops.h>
2 #include <linux/device.h>
3 #include <linux/delay.h>
4 #include <linux/errno.h>
6 #include <linux/gpio.h>
7 #include <linux/init.h>
10 #include <linux/kernel.h>
12 #include <linux/kmod.h>
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/string.h>
16 #include <linux/slab.h>
17 #include <linux/types.h>
18 #include <media/v4l2-device.h>
19 #include <asm/intel-mid.h>
23 static struct drv201_device drv201_dev
;
25 static int drv201_i2c_rd8(struct i2c_client
*client
, u8 reg
, u8
*val
)
27 struct i2c_msg msg
[2];
32 msg
[0].addr
= DRV201_VCM_ADDR
;
37 msg
[1].addr
= DRV201_VCM_ADDR
;
38 msg
[1].flags
= I2C_M_RD
;
42 if (i2c_transfer(client
->adapter
, msg
, 2) != 2)
48 static int drv201_i2c_wr8(struct i2c_client
*client
, u8 reg
, u8 val
)
54 msg
.addr
= DRV201_VCM_ADDR
;
58 if (i2c_transfer(client
->adapter
, &msg
, 1) != 1)
63 static int drv201_i2c_wr16(struct i2c_client
*client
, u8 reg
, u16 val
)
68 buf
[1] = (u8
)(val
>> 8);
69 buf
[2] = (u8
)(val
& 0xff);
70 msg
.addr
= DRV201_VCM_ADDR
;
74 if (i2c_transfer(client
->adapter
, &msg
, 1) != 1)
79 int drv201_vcm_power_up(struct v4l2_subdev
*sd
)
81 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
86 ret
= drv201_dev
.platform_data
->power_ctrl(sd
, 1);
89 /* Wait for VBAT to stabilize */
92 * Jiggle SCL pin to wake up device.
93 * Drv201 expect SCL from low to high to wake device up.
94 * So the 1st access to i2c would fail.
95 * Using following function to wake device up.
97 drv201_i2c_wr8(client
, DRV201_CONTROL
, DRV201_RESET
);
99 /* Need 100us to transit from SHUTDOWN to STANDBY*/
100 usleep_range(WAKEUP_DELAY_US
, WAKEUP_DELAY_US
* 10);
103 ret
= drv201_i2c_wr8(client
, DRV201_CONTROL
, DRV201_RESET
);
108 ret
= drv201_i2c_rd8(client
, DRV201_CONTROL
, &value
);
111 if (value
!= DEFAULT_CONTROL_VAL
) {
116 drv201_dev
.focus
= DRV201_MAX_FOCUS_POS
;
117 drv201_dev
.initialized
= true;
121 drv201_dev
.platform_data
->power_ctrl(sd
, 0);
125 int drv201_vcm_power_down(struct v4l2_subdev
*sd
)
127 return drv201_dev
.platform_data
->power_ctrl(sd
, 0);
131 int drv201_t_focus_vcm(struct v4l2_subdev
*sd
, u16 val
)
133 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
134 u16 data
= val
& VCM_CODE_MASK
;
136 if (!drv201_dev
.initialized
)
138 return drv201_i2c_wr16(client
, DRV201_VCM_CURRENT
, data
);
141 int drv201_t_focus_abs(struct v4l2_subdev
*sd
, s32 value
)
145 value
= clamp(value
, 0, DRV201_MAX_FOCUS_POS
);
146 ret
= drv201_t_focus_vcm(sd
, value
);
148 drv201_dev
.number_of_steps
= value
- drv201_dev
.focus
;
149 drv201_dev
.focus
= value
;
150 getnstimeofday(&(drv201_dev
.timestamp_t_focus_abs
));
156 int drv201_t_focus_rel(struct v4l2_subdev
*sd
, s32 value
)
158 return drv201_t_focus_abs(sd
, drv201_dev
.focus
+ value
);
161 int drv201_q_focus_status(struct v4l2_subdev
*sd
, s32
*value
)
164 struct timespec temptime
;
165 const struct timespec timedelay
= {
167 min_t(u32
, abs(drv201_dev
.number_of_steps
)*DELAY_PER_STEP_NS
,
168 DELAY_MAX_PER_STEP_NS
),
171 ktime_get_ts(&temptime
);
173 temptime
= timespec_sub(temptime
, (drv201_dev
.timestamp_t_focus_abs
));
175 if (timespec_compare(&temptime
, &timedelay
) <= 0) {
176 status
|= ATOMISP_FOCUS_STATUS_MOVING
;
177 status
|= ATOMISP_FOCUS_HP_IN_PROGRESS
;
179 status
|= ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE
;
180 status
|= ATOMISP_FOCUS_HP_COMPLETE
;
187 int drv201_q_focus_abs(struct v4l2_subdev
*sd
, s32
*value
)
191 drv201_q_focus_status(sd
, &val
);
193 if (val
& ATOMISP_FOCUS_STATUS_MOVING
)
194 *value
= drv201_dev
.focus
- drv201_dev
.number_of_steps
;
196 *value
= drv201_dev
.focus
;
201 int drv201_t_vcm_slew(struct v4l2_subdev
*sd
, s32 value
)
206 int drv201_t_vcm_timing(struct v4l2_subdev
*sd
, s32 value
)
211 int drv201_vcm_init(struct v4l2_subdev
*sd
)
213 drv201_dev
.platform_data
= camera_get_af_platform_data();
214 return (NULL
== drv201_dev
.platform_data
) ? -ENODEV
: 0;