msm: camera: IMX074 actuator using unified actuator

Signed-off-by: Sreesudhan Ramakrish Ramkumar <srramku@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 80c05b5..b5aa72a 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -959,6 +959,19 @@
 	},
 };
 
+#ifdef CONFIG_IMX074_ACT
+static struct i2c_board_info imx074_actuator_i2c_info = {
+	I2C_BOARD_INFO("imx074_act", 0x11),
+};
+
+static struct msm_actuator_info imx074_actuator_info = {
+	.board_info     = &imx074_actuator_i2c_info,
+	.bus_id         = MSM_8960_GSBI4_QUP_I2C_BUS_ID,
+	.vcm_pwd        = 0,
+	.vcm_enable     = 1,
+};
+#endif
+
 #ifdef CONFIG_IMX074
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_LED,
@@ -984,6 +997,9 @@
 	.gpio_conf = &gpio_conf,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
+#ifdef CONFIG_IMX074_ACT
+	.actuator_info = &imx074_actuator_info
+#endif
 };
 
 struct platform_device msm8960_camera_sensor_imx074 = {
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index 56fd9db..a86460b 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -101,6 +101,13 @@
 	---help---
 	  Aptina 8M Bayer Sensor modules with Autofocus
 
+config IMX074_ACT
+	bool "Actuator IMX074 (BAYER 13.5M)"
+	depends on MSM_CAMERA && ARCH_MSM8960
+	default y
+	---help---
+	Actuator for SONY 13.5 MP Bayer Sensor
+
 config S5K3E2FX
 	bool "Sensor s5k3e2fx (Samsung 5M)"
 	depends on MSM_CAMERA && !ARCH_MSM8X60 && !MSM_CAMERA_V4L2
diff --git a/drivers/media/video/msm/actuators/Makefile b/drivers/media/video/msm/actuators/Makefile
index 70a3a19..4f4d5ee 100644
--- a/drivers/media/video/msm/actuators/Makefile
+++ b/drivers/media/video/msm/actuators/Makefile
@@ -2,3 +2,4 @@
 EXTRA_CFLAGS += -Idrivers/media/video/msm
 EXTRA_CFLAGS += -Idrivers/media/video/msm/io
 obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
+obj-$(CONFIG_IMX074_ACT) += imx074_act.o
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
new file mode 100644
index 0000000..67e897d
--- /dev/null
+++ b/drivers/media/video/msm/actuators/imx074_act.c
@@ -0,0 +1,231 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_actuator.h"
+#include "msm_logging.h"
+#include "msm_camera_i2c.h"
+
+#define	IMX074_TOTAL_STEPS_NEAR_TO_FAR			52
+DEFINE_MUTEX(imx074_act_mutex);
+static struct msm_actuator_ctrl_t imx074_act_t;
+
+static struct region_params_t g_regions[] = {
+	/* step_bound[0] - macro side boundary
+	 * step_bound[1] - infinity side boundary
+	 */
+	/* Region 1 */
+	{
+		.step_bound = {IMX074_TOTAL_STEPS_NEAR_TO_FAR, 0},
+		.code_per_step = 2,
+	},
+};
+
+static uint16_t g_scenario[] = {
+	/* MOVE_NEAR and MOVE_FAR dir*/
+	IMX074_TOTAL_STEPS_NEAR_TO_FAR,
+};
+
+static struct damping_params_t g_damping[] = {
+	/* MOVE_NEAR Dir */
+	/* Scene 1 => Damping params */
+	{
+		.damping_step = 2,
+		.damping_delay = 0,
+	},
+};
+
+static struct damping_t g_damping_params[] = {
+	/* MOVE_NEAR and MOVE_FAR dir */
+	/* Region 1 */
+	{
+		.ringing_params = g_damping,
+	},
+};
+
+static int32_t imx074_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
+	int16_t next_lens_position)
+{
+	msm_camera_i2c_write(&a_ctrl->i2c_client,
+			     0x00,
+			     next_lens_position,
+			     MSM_CAMERA_I2C_BYTE_DATA);
+	return 0;
+}
+
+int32_t imx074_act_write_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	uint16_t curr_lens_pos,
+	struct damping_params_t *damping_params,
+	int8_t sign_direction,
+	int16_t code_boundary)
+{
+	int32_t rc = 0;
+	uint16_t dac_value = 0;
+
+	LINFO("%s called, curr lens pos = %d, code_boundary = %d\n",
+		  __func__,
+		  curr_lens_pos,
+		  code_boundary);
+
+	if (sign_direction == 1)
+		dac_value = (code_boundary - curr_lens_pos) | 0x80;
+	else
+		dac_value = (curr_lens_pos - code_boundary);
+
+	LINFO("%s dac_value = %d\n",
+	      __func__,
+	      dac_value);
+
+	rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, dac_value);
+
+	return rc;
+}
+
+static int32_t imx074_act_set_default_focus(struct msm_actuator_ctrl_t *a_ctrl)
+{
+	int32_t rc;
+	LINFO("%s called\n",
+	      __func__);
+	/* Initialize to infinity */
+	msm_camera_i2c_write(&a_ctrl->i2c_client,
+		0x01,
+		0xA9,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(&a_ctrl->i2c_client,
+		0x02,
+		0xD2,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(&a_ctrl->i2c_client,
+		0x03,
+		0x0C,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(&a_ctrl->i2c_client,
+		0x04,
+		0x14,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(&a_ctrl->i2c_client,
+		0x05,
+		0xB6,
+		MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(&a_ctrl->i2c_client,
+		0x06,
+		0x4F,
+		MSM_CAMERA_I2C_BYTE_DATA);
+
+	rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, 0x7F);
+	rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, 0x7F);
+	a_ctrl->curr_step_pos = 0;
+	return rc;
+}
+
+static const struct i2c_device_id imx074_act_i2c_id[] = {
+	{"imx074_act", (kernel_ulong_t)&imx074_act_t},
+	{ }
+};
+
+static int imx074_act_config(
+	void __user *argp)
+{
+	LINFO("%s called\n", __func__);
+	return (int) msm_actuator_config(&imx074_act_t, argp);
+}
+
+static int imx074_i2c_add_driver_table(
+	void)
+{
+	LINFO("%s called\n", __func__);
+	return (int) msm_actuator_init_table(&imx074_act_t);
+}
+
+static struct i2c_driver imx074_act_i2c_driver = {
+	.id_table = imx074_act_i2c_id,
+	.probe  = msm_actuator_i2c_probe,
+	.remove = __exit_p(imx074_act_i2c_remove),
+	.driver = {
+		.name = "imx074_act",
+	},
+};
+
+static int __init imx074_i2c_add_driver(
+	void)
+{
+	LINFO("%s called\n", __func__);
+	return i2c_add_driver(imx074_act_t.i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops imx074_act_subdev_core_ops;
+
+static struct v4l2_subdev_ops imx074_act_subdev_ops = {
+	.core = &imx074_act_subdev_core_ops,
+};
+
+static int32_t imx074_act_create_subdevice(
+	void *board_info,
+	void *sdev)
+{
+	LINFO("%s called\n", __func__);
+
+	return (int) msm_actuator_create_subdevice(&imx074_act_t,
+		(struct i2c_board_info const *)board_info,
+		(struct v4l2_subdev *)sdev);
+}
+
+static struct msm_actuator_ctrl_t imx074_act_t = {
+	.i2c_driver = &imx074_act_i2c_driver,
+	.i2c_addr = 0xE4,
+	.act_v4l2_subdev_ops = &imx074_act_subdev_ops,
+	.actuator_ext_ctrl = {
+		.a_init_table = imx074_i2c_add_driver_table,
+		.a_create_subdevice = imx074_act_create_subdevice,
+		.a_config = imx074_act_config,
+	},
+
+	.i2c_client = {
+		.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
+	},
+
+	.set_info = {
+		.total_steps = IMX074_TOTAL_STEPS_NEAR_TO_FAR,
+	},
+
+	.curr_step_pos = 0,
+	.curr_region_index = 0,
+	.initial_code = 0x7F,
+	.actuator_mutex = &imx074_act_mutex,
+
+	.func_tbl = {
+		.actuator_init_table = msm_actuator_init_table,
+		.actuator_move_focus = msm_actuator_move_focus,
+		.actuator_write_focus = imx074_act_write_focus,
+		.actuator_set_default_focus = imx074_act_set_default_focus,
+		.actuator_i2c_write = imx074_wrapper_i2c_write,
+	},
+
+	/* Initialize scenario */
+	.ringing_scenario[MOVE_NEAR] = g_scenario,
+	.scenario_size[MOVE_NEAR] = ARRAY_SIZE(g_scenario),
+	.ringing_scenario[MOVE_FAR] = g_scenario,
+	.scenario_size[MOVE_FAR] = ARRAY_SIZE(g_scenario),
+
+	/* Initialize region params */
+	.region_params = g_regions,
+	.region_size = ARRAY_SIZE(g_regions),
+
+	/* Initialize damping params */
+	.damping[MOVE_NEAR] = g_damping_params,
+	.damping[MOVE_FAR] = g_damping_params,
+};
+
+subsys_initcall(imx074_i2c_add_driver);
+MODULE_DESCRIPTION("IMX074 actuator");
+MODULE_LICENSE("GPL v2");