msm: camera: kernel driver for ov12830

Support for 12.8M Omnivision image sensor of ov12830 for 8x26.
ov12830 uses 4 Lane MIPI interface with AVDD DVDD IOVDD
power supply.

Change-Id: I86fde35ca54a8eec0113f78490e09a48162e1e2c
Signed-off-by: feim <Flynn@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 734926f..a8a76ed 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3390,9 +3390,11 @@
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6f.qcom,camera"),
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "90.qcom,camera"),
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6d.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6f.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "90.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6d.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,camera"),
 
 	/* CCI clocks */
 	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 74ec99a..cdc14a1 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -191,6 +191,15 @@
 		and QSXGA snapshot at 15 fps.
 		This sensor driver does not support auto focus.
 
+config OV12830
+	bool "OmniVision OV12830 (BAYER 12MP)"
+	depends on MSMB_CAMERA
+	---help---
+		OmniVision 12.8 MP Bayer Sensor with auto focus.uses
+		4 mipi lanes, preview config = 2112 * 1500 at 30 fps,
+		snapshot config = 4224 * 3000 at 15 fps.
+		2 lanes max fps is 18, 4 lanes max fps is 24.
+
 config MSM_V4L2_VIDEO_OVERLAY_DEVICE
 	tristate "Qualcomm MSM V4l2 video overlay device"
 	---help---
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index 18ac623..40d9791 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_IMX135) += imx135.o
 obj-$(CONFIG_OV8825) += ov8825.o
 obj-$(CONFIG_s5k4e1) += s5k4e1.o
+obj-$(CONFIG_OV12830) += ov12830.o
 obj-$(CONFIG_OV2720) += ov2720.o
 obj-$(CONFIG_OV9724) += ov9724.o
 obj-$(CONFIG_HI256) += hi256.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov12830.c b/drivers/media/platform/msm/camera_v2/sensor/ov12830.c
new file mode 100644
index 0000000..593892e
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov12830.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2013, The Linux Foundation. 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_sensor.h"
+#define OV12830_SENSOR_NAME "ov12830"
+DEFINE_MSM_MUTEX(ov12830_mut);
+
+static struct msm_sensor_ctrl_t ov12830_s_ctrl;
+
+static struct msm_sensor_power_setting ov12830_power_setting[] = {
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VIO,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VANA,
+		.config_val = 0,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_VDIG,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_VDIG,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VAF,
+		.config_val = 0,
+		.delay = 15,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 15,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_AF_PWDM,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_AF_PWDM,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 40,
+	},
+	{
+		.seq_type = SENSOR_CLK,
+		.seq_val = SENSOR_CAM_MCLK,
+		.config_val = 24000000,
+		.delay = 5,
+	},
+	{
+		.seq_type = SENSOR_I2C_MUX,
+		.seq_val = 0,
+		.config_val = 0,
+		.delay = 0,
+	},
+};
+
+static struct v4l2_subdev_info ov12830_subdev_info[] = {
+	{
+		.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.fmt    = 1,
+		.order    = 0,
+	},
+};
+
+static const struct i2c_device_id ov12830_i2c_id[] = {
+	{OV12830_SENSOR_NAME,
+	(kernel_ulong_t)&ov12830_s_ctrl},
+	{ }
+};
+
+static int msm_ov12830_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	return msm_sensor_i2c_probe(client, id, &ov12830_s_ctrl);
+}
+
+static struct i2c_driver ov12830_i2c_driver = {
+	.id_table = ov12830_i2c_id,
+	.probe  = msm_ov12830_i2c_probe,
+	.driver = {
+		.name = OV12830_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client ov12830_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id ov12830_dt_match[] = {
+	{.compatible = "qcom,ov12830",
+	.data = &ov12830_s_ctrl},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, ov12830_dt_match);
+
+static struct platform_driver ov12830_platform_driver = {
+	.driver = {
+		.name = "qcom,ov12830",
+		.owner = THIS_MODULE,
+		.of_match_table = ov12830_dt_match,
+	},
+};
+
+static int32_t ov12830_platform_probe
+	(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	const struct of_device_id *match;
+	match = of_match_device(ov12830_dt_match, &pdev->dev);
+	rc = msm_sensor_platform_probe(pdev, match->data);
+	return rc;
+}
+
+static int __init ov12830_init_module(void)
+{
+	int32_t rc = 0;
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	rc = platform_driver_probe(&ov12830_platform_driver,
+		ov12830_platform_probe);
+	if (!rc)
+		return rc;
+	pr_debug("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&ov12830_i2c_driver);
+}
+
+static void __exit ov12830_exit_module(void)
+{
+	pr_info("%s:%d\n", __func__, __LINE__);
+	if (ov12830_s_ctrl.pdev) {
+		msm_sensor_free_sensor_data(&ov12830_s_ctrl);
+		platform_driver_unregister
+			(&ov12830_platform_driver);
+	} else {
+		i2c_del_driver(&ov12830_i2c_driver);
+	}
+}
+
+static struct msm_sensor_ctrl_t ov12830_s_ctrl = {
+	.sensor_i2c_client = &ov12830_sensor_i2c_client,
+	.power_setting_array.power_setting = ov12830_power_setting,
+	.power_setting_array.size =
+		ARRAY_SIZE(ov12830_power_setting),
+	.msm_sensor_mutex = &ov12830_mut,
+	.sensor_v4l2_subdev_info = ov12830_subdev_info,
+	.sensor_v4l2_subdev_info_size =
+		ARRAY_SIZE(ov12830_subdev_info),
+};
+
+module_init(ov12830_init_module);
+module_exit(ov12830_exit_module);
+MODULE_DESCRIPTION("ov12830");
+MODULE_LICENSE("GPL v2");