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>
22 struct ad5816g_device ad5816g_dev
;
24 static int ad5816g_i2c_rd8(struct i2c_client
*client
, u8 reg
, u8
*val
)
26 struct i2c_msg msg
[2];
31 msg
[0].addr
= AD5816G_VCM_ADDR
;
36 msg
[1].addr
= AD5816G_VCM_ADDR
;
37 msg
[1].flags
= I2C_M_RD
;
41 if (i2c_transfer(client
->adapter
, msg
, 2) != 2)
47 static int ad5816g_i2c_wr8(struct i2c_client
*client
, u8 reg
, u8 val
)
53 msg
.addr
= AD5816G_VCM_ADDR
;
57 if (i2c_transfer(client
->adapter
, &msg
, 1) != 1)
62 static int ad5816g_i2c_wr16(struct i2c_client
*client
, u8 reg
, u16 val
)
67 buf
[1] = (u8
)(val
>> 8);
68 buf
[2] = (u8
)(val
& 0xff);
69 msg
.addr
= AD5816G_VCM_ADDR
;
73 if (i2c_transfer(client
->adapter
, &msg
, 1) != 1)
78 static int ad5816g_set_arc_mode(struct i2c_client
*client
)
82 ret
= ad5816g_i2c_wr8(client
, AD5816G_CONTROL
, AD5816G_ARC_EN
);
86 ret
= ad5816g_i2c_wr8(client
, AD5816G_MODE
,
87 AD5816G_MODE_2_5M_SWITCH_CLOCK
);
91 ret
= ad5816g_i2c_wr8(client
, AD5816G_VCM_FREQ
, AD5816G_DEF_FREQ
);
95 int ad5816g_vcm_power_up(struct v4l2_subdev
*sd
)
97 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
102 ret
= ad5816g_dev
.platform_data
->power_ctrl(sd
, 1);
105 /* waiting time AD5816G(vcm) - t1 + t2
106 * t1(1ms) -Time from VDD high to first i2c cmd
107 * t2(100us) - exit power-down mode time
109 usleep_range(1100, 2200);
111 ret
= ad5816g_i2c_rd8(client
, AD5816G_IC_INFO
, &ad5816g_id
);
114 if (ad5816g_id
!= AD5816G_ID
) {
118 ret
= ad5816g_set_arc_mode(client
);
122 /* set the VCM_THRESHOLD */
123 ret
= ad5816g_i2c_wr8(client
, AD5816G_VCM_THRESHOLD
,
124 AD5816G_DEF_THRESHOLD
);
129 ad5816g_dev
.platform_data
->power_ctrl(sd
, 0);
133 int ad5816g_vcm_power_down(struct v4l2_subdev
*sd
)
135 return ad5816g_dev
.platform_data
->power_ctrl(sd
, 0);
139 static int ad5816g_t_focus_vcm(struct v4l2_subdev
*sd
, u16 val
)
141 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
142 u16 data
= val
& VCM_CODE_MASK
;
144 return ad5816g_i2c_wr16(client
, AD5816G_VCM_CODE_MSB
, data
);
147 int ad5816g_t_focus_abs(struct v4l2_subdev
*sd
, s32 value
)
151 value
= clamp(value
, 0, AD5816G_MAX_FOCUS_POS
);
152 ret
= ad5816g_t_focus_vcm(sd
, value
);
154 ad5816g_dev
.number_of_steps
= value
- ad5816g_dev
.focus
;
155 ad5816g_dev
.focus
= value
;
156 getnstimeofday(&(ad5816g_dev
.timestamp_t_focus_abs
));
162 int ad5816g_t_focus_rel(struct v4l2_subdev
*sd
, s32 value
)
165 return ad5816g_t_focus_abs(sd
, ad5816g_dev
.focus
+ value
);
168 int ad5816g_q_focus_status(struct v4l2_subdev
*sd
, s32
*value
)
171 struct timespec temptime
;
172 const struct timespec timedelay
= {
174 min_t(u32
, abs(ad5816g_dev
.number_of_steps
) * DELAY_PER_STEP_NS
,
175 DELAY_MAX_PER_STEP_NS
),
178 ktime_get_ts(&temptime
);
180 temptime
= timespec_sub(temptime
, (ad5816g_dev
.timestamp_t_focus_abs
));
182 if (timespec_compare(&temptime
, &timedelay
) <= 0) {
183 status
|= ATOMISP_FOCUS_STATUS_MOVING
;
184 status
|= ATOMISP_FOCUS_HP_IN_PROGRESS
;
186 status
|= ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE
;
187 status
|= ATOMISP_FOCUS_HP_COMPLETE
;
194 int ad5816g_q_focus_abs(struct v4l2_subdev
*sd
, s32
*value
)
198 ad5816g_q_focus_status(sd
, &val
);
200 if (val
& ATOMISP_FOCUS_STATUS_MOVING
)
201 *value
= ad5816g_dev
.focus
- ad5816g_dev
.number_of_steps
;
203 *value
= ad5816g_dev
.focus
;
208 int ad5816g_t_vcm_slew(struct v4l2_subdev
*sd
, s32 value
)
213 int ad5816g_t_vcm_timing(struct v4l2_subdev
*sd
, s32 value
)