int dw9714_vcm_init(struct v4l2_subdev *sd)
{

	/* set VCM to home position and vcm mode to direct*/
	dw9714_dev.vcm_mode = DW9714_DIRECT;
	dw9714_dev.vcm_settings.update = false;
	dw9714_dev.platform_data = camera_get_af_platform_data();
	return (NULL == dw9714_dev.platform_data) ? -ENODEV : 0;

}
int ad5816g_vcm_init(struct v4l2_subdev *sd)
{
	ad5816g_dev.platform_data = camera_get_af_platform_data();
	return (NULL == ad5816g_dev.platform_data) ? -ENODEV : 0;

}
static int dw9719_i2c_wr16(struct i2c_client *client, u8 reg, u16 val)
{
	struct i2c_msg msg;
	u8 buf[3] = { reg, (u8)(val >> 8), (u8)(val & 0xff)};

	msg.addr = DW9719_VCM_ADDR;
	msg.flags = 0;
	msg.len = sizeof(buf);
	msg.buf = buf;

	if (i2c_transfer(client->adapter, &msg, 1) != 1)
		return -EIO;

	return 0;
}

int dw9719_vcm_power_up(struct v4l2_subdev *sd)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int ret;
	u8 value;

	/* Enable power */
	ret = dw9719_dev.platform_data->power_ctrl(sd, 1);
	/* waiting time requested by DW9714A(vcm) */
	if (ret)
		return ret;
	/* Wait for VBAT to stabilize */
	udelay(1);

	/*
	 * Jiggle SCL pin to wake up device.
	 */
	ret = dw9719_i2c_wr8(client, DW9719_CONTROL, 1);
	/* Need 100us to transit from SHUTDOWN to STANDBY*/
	usleep_range(100, 1000);

	/* Enable the ringing compensation */
	ret = dw9719_i2c_wr8(client, DW9719_CONTROL, DW9719_ENABLE_RINGING);
	if (ret < 0)
		goto fail_powerdown;

	/* Use SAC3 mode */
	ret = dw9719_i2c_wr8(client, DW9719_MODE, DW9719_MODE_SAC3);
	if (ret < 0)
		goto fail_powerdown;

	/* Set the resonance frequency */
	ret = dw9719_i2c_wr8(client, DW9719_VCM_FREQ, DW9719_DEFAULT_VCM_FREQ);
	if (ret < 0)
		goto fail_powerdown;

	/* Detect device */
	ret = dw9719_i2c_rd8(client, DW9719_INFO, &value);
	if (ret < 0)
		goto fail_powerdown;
	if (value != DW9719_ID) {
		ret = -ENXIO;
		goto fail_powerdown;
	}
	dw9719_dev.focus = 0;
	dw9719_dev.initialized = true;

	return 0;

fail_powerdown:
	dw9719_dev.platform_data->power_ctrl(sd, 0);
	return ret;
}

int dw9719_vcm_power_down(struct v4l2_subdev *sd)
{
	return dw9719_dev.platform_data->power_ctrl(sd, 0);
}

int dw9719_q_focus_status(struct v4l2_subdev *sd, s32 *value)
{
	static const struct timespec move_time = {

		.tv_sec = 0,
		.tv_nsec = 60000000
	};
	struct timespec current_time, finish_time, delta_time;

	getnstimeofday(&current_time);
	finish_time = timespec_add(dw9719_dev.focus_time, move_time);
	delta_time = timespec_sub(current_time, finish_time);
	if (delta_time.tv_sec >= 0 && delta_time.tv_nsec >= 0) {
		*value = ATOMISP_FOCUS_HP_COMPLETE |
			 ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE;
	} else {
		*value = ATOMISP_FOCUS_STATUS_MOVING |
			 ATOMISP_FOCUS_HP_IN_PROGRESS;
	}

	return 0;
}

int dw9719_t_focus_vcm(struct v4l2_subdev *sd, u16 val)
{
	return -EINVAL;
}

int dw9719_t_focus_abs(struct v4l2_subdev *sd, s32 value)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int ret;

	value = clamp(value, 0, DW9719_MAX_FOCUS_POS);
	ret = dw9719_i2c_wr16(client, DW9719_VCM_CURRENT, value);
	if (ret < 0)
		return ret;

	getnstimeofday(&dw9719_dev.focus_time);
	dw9719_dev.focus = value;

	return 0;
}

int dw9719_t_focus_rel(struct v4l2_subdev *sd, s32 value)
{
	return dw9719_t_focus_abs(sd, dw9719_dev.focus + value);
}

int dw9719_q_focus_abs(struct v4l2_subdev *sd, s32 *value)
{
	*value  = dw9719_dev.focus ;
	return 0;
}
int dw9719_t_vcm_slew(struct v4l2_subdev *sd, s32 value)
{
	return 0;
}

int dw9719_t_vcm_timing(struct v4l2_subdev *sd, s32 value)
{
	return 0;
}

int dw9719_vcm_init(struct v4l2_subdev *sd)
{
	dw9719_dev.platform_data = camera_get_af_platform_data();
	return (NULL == dw9719_dev.platform_data) ? -ENODEV : 0;
}
int drv201_vcm_init(struct v4l2_subdev *sd)
{
	drv201_dev.platform_data = camera_get_af_platform_data();
	return (NULL == drv201_dev.platform_data) ? -ENODEV : 0;
}