msm: camera: Add support to V4L2 architecture
New targets are following V4L2 architecture for
camera. Update 7x27a camera drivers to support
new V4L2 architecture to unify all camera drivers
in the same architecture.
Signed-off-by: Suresh Vankadara <svankada@codeaurora.org>
Change-Id: Ie23ac982375041c06b68537d5784d8cdbbc9bf04
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 8961c79..1abfd7b 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -87,6 +87,8 @@
VFE_MSG_V32_START_RECORDING,
VFE_MSG_V32_CAPTURE,
VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_V2X_PREVIEW,
+ VFE_MSG_V2X_CAPTURE,
};
enum vpe_resp_msg {
diff --git a/arch/arm/mach-msm/qdsp5/adsp_info.c b/arch/arm/mach-msm/qdsp5/adsp_info.c
index 62e385d..dea52bb 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_info.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_info.c
@@ -1,6 +1,6 @@
/* arch/arm/mach-msm/adsp_info.c
*
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -89,7 +89,7 @@
QDSP_MODULE(RMTASK, NULL, 0, NULL, NULL),
#if !defined(CONFIG_ARCH_MSM7X30)
QDSP_MODULE(AUDRECTASK, NULL, 0, NULL, NULL),
- QDSP_MODULE(VFETASK, "vfe_clk", 0, adsp_vfe_verify_cmd,
+ QDSP_MODULE(VFETASK, NULL, 0, adsp_vfe_verify_cmd,
adsp_vfe_patch_event),
QDSP_MODULE(QCAMTASK, NULL, 0, NULL, NULL),
QDSP_MODULE(LPMTASK, NULL, 0, adsp_lpm_verify_cmd, NULL),
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index aa0e392..b1dc87e 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -62,7 +62,7 @@
Omni Vision VGA YUV Sensor.
config WEBCAM_OV9726
bool "Sensor OV9726 (VGA Bayer)"
- depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM7X27A) && !MSM_CAMERA_V4L2
+ depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM7X27A)
default n
---help---
Omni Vision VGA Bayer Sensor.
@@ -113,7 +113,7 @@
config MT9E013
bool "Sensor mt9e013 module (BAYER 8M)"
- depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A) && !MSM_CAMERA_V4L2
+ depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A)
default n
---help---
Aptina 8M Bayer Sensor modules with Autofocus
@@ -149,6 +149,13 @@
two mipi lanes, required for msm7x2xA platform.
Say Y here if this is msm7x2xA variant platform.
+config DW9712_ACT
+ bool "Lens actuator dw9721"
+ depends on MSM_CAMERA && S5K4E1
+ ---help---
+ dw9721 lens actuator driver for S5K4E1.
+ Say Y here if this is msm7627A variant platform.
+
config MSM_CAMERA_FLASH_SC628A
bool "Qualcomm MSM camera sc628a flash support"
depends on MSM_CAMERA
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 5454763..b91449a 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -15,7 +15,11 @@
obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/
obj-$(CONFIG_MSM_CAMERA_FLASH) += flash.o
obj-$(CONFIG_ARCH_MSM_ARM11) += msm_vfe7x.o msm_io7x.o
-obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a.o msm_io_7x27a.o
+ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+ obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a_v4l2.o msm_io_7x27a_v4l2.o
+else
+ obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a.o msm_io_7x27a.o
+endif
obj-$(CONFIG_ARCH_MSM7X30) += msm_vfe31.o msm_io_vfe31.o msm_vpe1.o
obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o msm_io8x.o
obj-$(CONFIG_ARCH_MSM8X60) += msm_vfe31.o msm_io_8x60.o msm_vpe1.o
@@ -26,20 +30,20 @@
obj-$(CONFIG_MSM_CAMERA_AF_FOXCONN) += mt9p012_fox.o
obj-$(CONFIG_MSM_CAMERA_AF_BAM) += mt9p012_bam.o
obj-$(CONFIG_MT9P012_KM) += mt9p012_km.o mt9p012_km_reg.o
-obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
obj-$(CONFIG_S5K3E2FX) += s5k3e2fx.o
-obj-$(CONFIG_S5K4E1) += s5k4e1.o s5k4e1_reg.o
#FIXME: Merge the two ifeq causes VX6953 preview not coming up.
ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
obj-$(CONFIG_VX6953) += vx6953_v4l2.o vx6953_reg_v4l2.o
else
obj-$(CONFIG_VX6953) += vx6953.o vx6953_reg.o
obj-$(CONFIG_IMX074) += imx074.o imx074_reg.o
+ obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
+ obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
+ obj-$(CONFIG_S5K4E1) += s5k4e1.o s5k4e1_reg.o
endif
obj-$(CONFIG_QS_S5K4E1) += qs_s5k4e1.o qs_s5k4e1_reg.o
obj-$(CONFIG_VB6801) += vb6801.o
obj-$(CONFIG_IMX072) += imx072.o imx072_reg.o
-obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
obj-$(CONFIG_WEBCAM_OV7692) += ov7692.o
obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd.o
obj-$(CONFIG_OV5640) += ov5640.o
diff --git a/drivers/media/video/msm/actuators/Makefile b/drivers/media/video/msm/actuators/Makefile
index 4f4d5ee..f0a0c69 100644
--- a/drivers/media/video/msm/actuators/Makefile
+++ b/drivers/media/video/msm/actuators/Makefile
@@ -3,3 +3,4 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm/io
obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
obj-$(CONFIG_IMX074_ACT) += imx074_act.o
+obj-$(CONFIG_DW9712_ACT) += dw9712_act.o
diff --git a/drivers/media/video/msm/actuators/dw9712_act.c b/drivers/media/video/msm/actuators/dw9712_act.c
new file mode 100644
index 0000000..562290f
--- /dev/null
+++ b/drivers/media/video/msm/actuators/dw9712_act.c
@@ -0,0 +1,277 @@
+/* Copyright (c) 2012, 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_camera_i2c.h"
+
+#define DW9712_TOTAL_STEPS_NEAR_TO_FAR 32
+DEFINE_MUTEX(dw9712_act_mutex);
+static struct msm_actuator_ctrl_t dw9712_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 = {DW9712_TOTAL_STEPS_NEAR_TO_FAR, 0},
+ .code_per_step = 2,
+ },
+};
+
+static uint16_t g_scenario[] = {
+ /* MOVE_NEAR and MOVE_FAR dir*/
+ DW9712_TOTAL_STEPS_NEAR_TO_FAR,
+};
+
+static int32_t dw9712_af_i2c_txdata(unsigned short saddr,
+ unsigned char *txdata, int length,
+ struct msm_actuator_ctrl_t *a_ctrl)
+{
+ struct i2c_msg msg[] = {
+ {
+ .addr = saddr,
+ .flags = 0,
+ .len = length,
+ .buf = txdata,
+ },
+ };
+ if (i2c_transfer(a_ctrl->i2c_client.client->adapter, msg, 1) < 0) {
+ pr_err("s5k4e1_af_i2c_txdata faild 0x%x\n", saddr);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int32_t dw9712_af_i2c_write_b_sensor(struct msm_actuator_ctrl_t *a_ctrl,
+ uint8_t waddr, uint8_t bdata)
+{
+ int32_t rc = -EFAULT;
+ unsigned char buf[2];
+
+ memset(buf, 0, sizeof(buf));
+ buf[0] = waddr;
+ buf[1] = bdata;
+ rc = dw9712_af_i2c_txdata(a_ctrl->i2c_addr, buf, 2, a_ctrl);
+ if (rc < 0) {
+ pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+ waddr, bdata);
+ }
+ return rc;
+}
+
+static int32_t dw9712_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
+ int16_t next_lens_position, void *params)
+{
+ uint8_t msb, lsb;
+
+ msb = (next_lens_position & 0xFF00) >> 8;
+ lsb = next_lens_position & 0xFF;
+ dw9712_af_i2c_write_b_sensor(a_ctrl, msb, lsb);
+
+ return 0;
+}
+
+int32_t msm_dw9712_act_move_focus(
+ struct msm_actuator_ctrl_t *a_ctrl,
+ int dir,
+ int32_t num_steps)
+{
+ int32_t rc = 0;
+ int8_t sign_dir = 0;
+ int16_t dest_step_pos = 0;
+ uint8_t code_val_msb, code_val_lsb;
+ uint16_t code_val;
+
+ LINFO("%s called, dir %d, num_steps %d\n",
+ __func__,
+ dir,
+ num_steps);
+
+ /* Determine sign direction */
+ if (dir == MOVE_NEAR)
+ sign_dir = 1;
+ else if (dir == MOVE_FAR)
+ sign_dir = -1;
+ else {
+ pr_err("Illegal focus direction\n");
+ rc = -EINVAL;
+ return rc;
+ }
+
+ /* Determine destination step position */
+ dest_step_pos = a_ctrl->curr_step_pos +
+ (sign_dir * num_steps);
+
+ if (dest_step_pos < 0)
+ dest_step_pos = 0;
+ else if (dest_step_pos > 1023)
+ dest_step_pos = 1023;
+
+ if (dest_step_pos == a_ctrl->curr_step_pos)
+ return rc;
+
+ code_val_msb = dest_step_pos >> 4;
+ code_val_lsb = (dest_step_pos & 0x000F) << 4;
+ code_val = (code_val_msb << 8) | (code_val_lsb);
+ rc = dw9712_wrapper_i2c_write(a_ctrl, code_val, NULL);
+ if (rc >= 0) {
+ rc = 0;
+ a_ctrl->curr_step_pos = dest_step_pos;
+ }
+ return 0;
+}
+
+static int32_t dw9712_set_default_focus(
+ struct msm_actuator_ctrl_t *a_ctrl)
+{
+ int32_t rc = 0;
+
+ if (!a_ctrl->step_position_table)
+ a_ctrl->func_tbl.actuator_init_table(a_ctrl);
+
+ if (a_ctrl->curr_step_pos != 0) {
+ rc = a_ctrl->func_tbl.actuator_move_focus(a_ctrl,
+ MOVE_FAR, a_ctrl->curr_step_pos);
+ a_ctrl->curr_step_pos = 0;
+ } else
+ rc = dw9712_wrapper_i2c_write(a_ctrl, 0x00, NULL);
+ if (rc >= 0)
+ rc = 0;
+ return rc;
+}
+
+static const struct i2c_device_id dw9712_act_i2c_id[] = {
+ {"dw9712_act", (kernel_ulong_t)&dw9712_act_t},
+ { }
+};
+
+static int dw9712_act_config(void __user *argp)
+{
+ LINFO("%s called\n", __func__);
+ return (int) msm_actuator_config(&dw9712_act_t, argp);
+}
+
+static int dw9712_i2c_add_driver_table(void)
+{
+ LINFO("%s called\n", __func__);
+ return (int) msm_actuator_init_table(&dw9712_act_t);
+}
+
+static struct i2c_driver dw9712_act_i2c_driver = {
+ .id_table = dw9712_act_i2c_id,
+ .probe = msm_actuator_i2c_probe,
+ .remove = __exit_p(dw9712_act_i2c_remove),
+ .driver = {
+ .name = "dw9712_act",
+ },
+};
+
+static int __init dw9712_i2c_add_driver(void)
+{
+ int rc = 0;
+
+ LINFO("%s called :%x\n", __func__, dw9712_act_t.i2c_addr);
+ rc = i2c_add_driver(dw9712_act_t.i2c_driver);
+ LINFO("%s called:%d %x\n", __func__, rc, dw9712_act_t.i2c_addr);
+ return rc;
+}
+
+static struct v4l2_subdev_core_ops dw9712_act_subdev_core_ops;
+
+static struct v4l2_subdev_ops dw9712_act_subdev_ops = {
+ .core = &dw9712_act_subdev_core_ops,
+};
+
+static int32_t dw9712_act_create_subdevice(
+ void *board_info,
+ void *sdev)
+{
+ int rc = 0;
+
+ struct msm_actuator_info *ptr;
+ LINFO("%s called\n", __func__);
+
+ ptr = board_info;
+ dw9712_act_t.vcm_pwd = ptr->vcm_pwd;
+ dw9712_act_t.vcm_enable = ptr->vcm_enable;
+ LINFO("vcm info: %x %x\n", dw9712_act_t.vcm_pwd,
+ dw9712_act_t.vcm_enable);
+ if (dw9712_act_t.vcm_enable) {
+ rc = gpio_request(dw9712_act_t.vcm_pwd, "dw9712_af");
+ if (!rc) {
+ LINFO("Enable VCM PWD\n");
+ gpio_direction_output(dw9712_act_t.vcm_pwd, 1);
+ }
+ }
+ return (int) msm_actuator_create_subdevice(&dw9712_act_t,
+ ptr->board_info,
+ (struct v4l2_subdev *)sdev);
+}
+
+static struct msm_actuator_ctrl_t dw9712_act_t = {
+ .i2c_driver = &dw9712_act_i2c_driver,
+ .i2c_addr = 0x8C,
+ .act_v4l2_subdev_ops = &dw9712_act_subdev_ops,
+ .actuator_ext_ctrl = {
+ .a_init_table = dw9712_i2c_add_driver_table,
+ .a_create_subdevice = dw9712_act_create_subdevice,
+ .a_config = dw9712_act_config,
+ },
+
+ .i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+ },
+
+ .set_info = {
+ .total_steps = DW9712_TOTAL_STEPS_NEAR_TO_FAR,
+ },
+
+ .curr_step_pos = 0,
+ .curr_region_index = 0,
+ .initial_code = 0x0,
+ .actuator_mutex = &dw9712_act_mutex,
+
+ .func_tbl = {
+ .actuator_init_table = msm_actuator_init_table,
+ .actuator_move_focus = msm_dw9712_act_move_focus,
+ .actuator_set_default_focus = dw9712_set_default_focus,
+ .actuator_i2c_write = dw9712_wrapper_i2c_write,
+ },
+
+ .get_info = {
+ .focal_length_num = 46,
+ .focal_length_den = 10,
+ .f_number_num = 265,
+ .f_number_den = 100,
+ .f_pix_num = 14,
+ .f_pix_den = 10,
+ .total_f_dist_num = 197681,
+ .total_f_dist_den = 1000,
+ },
+
+ /* 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),
+};
+
+subsys_initcall(dw9712_i2c_add_driver);
+MODULE_DESCRIPTION("DW9712 actuator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
index e01d2c7..e4d340d4 100644
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ b/drivers/media/video/msm/actuators/imx074_act.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -186,13 +186,14 @@
};
static int32_t imx074_act_create_subdevice(
- void *board_info,
+ void *act_info,
void *sdev)
{
+ struct msm_actuator_info *info = (struct msm_actuator_info *)act_info;
LINFO("%s called\n", __func__);
return (int) msm_actuator_create_subdevice(&imx074_act_t,
- (struct i2c_board_info const *)board_info,
+ (struct i2c_board_info const *)info->board_info,
(struct v4l2_subdev *)sdev);
}
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index 6fad8dd..9c90282 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -14,6 +14,7 @@
#include <linux/i2c.h>
#include <mach/camera.h>
+#include <mach/gpio.h>
#include <media/v4l2-subdev.h>
#include <media/msm_camera.h>
#include "msm_camera_i2c.h"
@@ -100,6 +101,8 @@
uint16_t region_size;
struct damping_t *damping[2];
void *user_data;
+ uint32_t vcm_pwd;
+ uint32_t vcm_enable;
};
int32_t msm_actuator_i2c_write_b_af(struct msm_actuator_ctrl_t *a_ctrl,
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index 3ce81af..6e8eb122 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -1,3 +1,4 @@
GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
EXTRA_CFLAGS += -Idrivers/media/video/msm
obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o msm_csid.o msm_ispif.o
+obj-$(CONFIG_ARCH_MSM7X27A) += msm_csic.o
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
new file mode 100644
index 0000000..476615d
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -0,0 +1,430 @@
+/* Copyright (c) 2012, 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 <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <media/msm_isp.h>
+#include "msm_csic.h"
+#include "msm.h"
+
+#define DBG_CSIC 0
+
+#define V4L2_IDENT_CSIC 50004
+/* MIPI CSI controller registers */
+#define MIPI_PHY_CONTROL 0x00000000
+#define MIPI_PROTOCOL_CONTROL 0x00000004
+#define MIPI_INTERRUPT_STATUS 0x00000008
+#define MIPI_INTERRUPT_MASK 0x0000000C
+#define MIPI_CAMERA_CNTL 0x00000024
+#define MIPI_CALIBRATION_CONTROL 0x00000018
+#define MIPI_PHY_D0_CONTROL2 0x00000038
+#define MIPI_PHY_D1_CONTROL2 0x0000003C
+#define MIPI_PHY_D2_CONTROL2 0x00000040
+#define MIPI_PHY_D3_CONTROL2 0x00000044
+#define MIPI_PHY_CL_CONTROL 0x00000048
+#define MIPI_PHY_D0_CONTROL 0x00000034
+#define MIPI_PHY_D1_CONTROL 0x00000020
+#define MIPI_PHY_D2_CONTROL 0x0000002C
+#define MIPI_PHY_D3_CONTROL 0x00000030
+#define MIPI_PWR_CNTL 0x00000054
+
+/*
+ * MIPI_PROTOCOL_CONTROL register bits to enable/disable the features of
+ * CSI Rx Block
+ */
+
+/* DPCM scheme */
+#define MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT 0x1e
+/* SW_RST to issue a SW reset to the CSI core */
+#define MIPI_PROTOCOL_CONTROL_SW_RST_BMSK 0x8000000
+/* To Capture Long packet Header Info in MIPI_PROTOCOL_STATUS register */
+#define MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK 0x200000
+/* Data format for unpacking purpose */
+#define MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT 0x13
+/* Enable decoding of payload based on data type filed of packet hdr */
+#define MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK 0x00000
+/* Enable error correction on packet headers */
+#define MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK 0x20000
+
+/*
+ * MIPI_CALIBRATION_CONTROL register contains control info for
+ * calibration impledence controller
+*/
+
+/* Enable bit for calibration pad */
+#define MIPI_CALIBRATION_CONTROL_SWCAL_CAL_EN_SHFT 0x16
+/* With SWCAL_STRENGTH_OVERRIDE_EN, SW_CAL_EN and MANUAL_OVERRIDE_EN
+ * the hardware calibration circuitry associated with CAL_SW_HW_MODE
+ * is bypassed
+*/
+#define MIPI_CALIBRATION_CONTROL_SWCAL_STRENGTH_OVERRIDE_EN_SHFT 0x15
+/* To indicate the Calibration process is in the control of HW/SW */
+#define MIPI_CALIBRATION_CONTROL_CAL_SW_HW_MODE_SHFT 0x14
+/* When this is set the strength value of the data and clk lane impedence
+ * termination is updated with MANUAL_STRENGTH settings and calibration
+ * sensing logic is idle.
+*/
+#define MIPI_CALIBRATION_CONTROL_MANUAL_OVERRIDE_EN_SHFT 0x7
+
+/* Data lane0 control */
+/* T-hs Settle count value for Rx */
+#define MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT 0x18
+/* Rx termination control */
+#define MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT 0x10
+/* LP Rx enable */
+#define MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT 0x4
+/*
+ * Enable for error in sync sequence
+ * 1 - one bit error in sync seq
+ * 0 - requires all 8 bit correct seq
+*/
+#define MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT 0x3
+
+/* Comments are same as D0 */
+#define MIPI_PHY_D1_CONTROL2_SETTLE_COUNT_SHFT 0x18
+#define MIPI_PHY_D1_CONTROL2_HS_TERM_IMP_SHFT 0x10
+#define MIPI_PHY_D1_CONTROL2_LP_REC_EN_SHFT 0x4
+#define MIPI_PHY_D1_CONTROL2_ERR_SOT_HS_EN_SHFT 0x3
+
+/* Comments are same as D0 */
+#define MIPI_PHY_D2_CONTROL2_SETTLE_COUNT_SHFT 0x18
+#define MIPI_PHY_D2_CONTROL2_HS_TERM_IMP_SHFT 0x10
+#define MIPI_PHY_D2_CONTROL2_LP_REC_EN_SHFT 0x4
+#define MIPI_PHY_D2_CONTROL2_ERR_SOT_HS_EN_SHFT 0x3
+
+/* Comments are same as D0 */
+#define MIPI_PHY_D3_CONTROL2_SETTLE_COUNT_SHFT 0x18
+#define MIPI_PHY_D3_CONTROL2_HS_TERM_IMP_SHFT 0x10
+#define MIPI_PHY_D3_CONTROL2_LP_REC_EN_SHFT 0x4
+#define MIPI_PHY_D3_CONTROL2_ERR_SOT_HS_EN_SHFT 0x3
+
+/* PHY_CL_CTRL programs the parameters of clk lane of CSIRXPHY */
+/* HS Rx termination control */
+#define MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT 0x18
+/* Start signal for T-hs delay */
+#define MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT 0x2
+
+/* PHY DATA lane 0 control */
+/*
+ * HS RX equalizer strength control
+ * 00 - 0db 01 - 3db 10 - 5db 11 - 7db
+*/
+#define MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT 0x1c
+/* PHY DATA lane 1 control */
+/* Shutdown signal for MIPI clk phy line */
+#define MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT 0x9
+/* Shutdown signal for MIPI data phy line */
+#define MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT 0x8
+
+#define MSM_AXI_QOS_PREVIEW 200000
+#define MSM_AXI_QOS_SNAPSHOT 200000
+#define MSM_AXI_QOS_RECORDING 200000
+
+#define MIPI_PWR_CNTL_ENA 0x07
+#define MIPI_PWR_CNTL_DIS 0x0
+
+static int msm_csic_config(struct csic_cfg_params *cfg_params)
+{
+ int rc = 0;
+ uint32_t val = 0;
+ struct csic_device *csic_dev;
+ struct msm_camera_csi_params *csic_params;
+ void __iomem *csicbase;
+
+ csic_dev = v4l2_get_subdevdata(cfg_params->subdev);
+ csicbase = csic_dev->base;
+ csic_params = cfg_params->parms;
+
+ /* Enable error correction for DATA lane. Applies to all data lanes */
+ msm_io_w(0x4, csicbase + MIPI_PHY_CONTROL);
+
+ msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
+ csicbase + MIPI_PROTOCOL_CONTROL);
+
+ val = MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK |
+ MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK |
+ MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK;
+ val |= (uint32_t)(csic_params->data_format) <<
+ MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT;
+ val |= csic_params->dpcm_scheme <<
+ MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT;
+ CDBG("%s MIPI_PROTOCOL_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csicbase + MIPI_PROTOCOL_CONTROL);
+
+ val = (0x1 << MIPI_CALIBRATION_CONTROL_SWCAL_CAL_EN_SHFT) |
+ (0x1 <<
+ MIPI_CALIBRATION_CONTROL_SWCAL_STRENGTH_OVERRIDE_EN_SHFT) |
+ (0x1 << MIPI_CALIBRATION_CONTROL_CAL_SW_HW_MODE_SHFT) |
+ (0x1 << MIPI_CALIBRATION_CONTROL_MANUAL_OVERRIDE_EN_SHFT);
+ CDBG("%s MIPI_CALIBRATION_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csicbase + MIPI_CALIBRATION_CONTROL);
+
+ val = (csic_params->settle_cnt <<
+ MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT) |
+ (0x0F << MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT) |
+ (0x1 << MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT) |
+ (0x1 << MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT);
+ CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+ msm_io_w(val, csicbase + MIPI_PHY_D0_CONTROL2);
+ msm_io_w(val, csicbase + MIPI_PHY_D1_CONTROL2);
+ msm_io_w(val, csicbase + MIPI_PHY_D2_CONTROL2);
+ msm_io_w(val, csicbase + MIPI_PHY_D3_CONTROL2);
+
+
+ val = (0x0F << MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT) |
+ (0x1 << MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT);
+ CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csicbase + MIPI_PHY_CL_CONTROL);
+
+ val = 0 << MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT;
+ msm_io_w(val, csicbase + MIPI_PHY_D0_CONTROL);
+
+ val = (0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT) |
+ (0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT);
+ CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csicbase + MIPI_PHY_D1_CONTROL);
+
+ msm_io_w(0x00000000, csicbase + MIPI_PHY_D2_CONTROL);
+ msm_io_w(0x00000000, csicbase + MIPI_PHY_D3_CONTROL);
+
+ /* program number of lanes and lane mapping */
+ switch (csic_params->lane_cnt) {
+ case 1:
+ msm_io_w(csic_params->lane_assign << 8 | 0x4,
+ csicbase + MIPI_CAMERA_CNTL);
+ break;
+ case 2:
+ msm_io_w(csic_params->lane_assign << 8 | 0x5,
+ csicbase + MIPI_CAMERA_CNTL);
+ break;
+ case 3:
+ msm_io_w(csic_params->lane_assign << 8 | 0x6,
+ csicbase + MIPI_CAMERA_CNTL);
+ break;
+ case 4:
+ msm_io_w(csic_params->lane_assign << 8 | 0x7,
+ csicbase + MIPI_CAMERA_CNTL);
+ break;
+ }
+
+ msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_MASK);
+ /*clear IRQ bits - write 1 clears the status*/
+ msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_STATUS);
+
+ return rc;
+}
+
+static irqreturn_t msm_csic_irq(int irq_num, void *data)
+{
+ uint32_t irq;
+ struct csic_device *csic_dev = data;
+
+ pr_info("msm_csic_irq: %x\n", (unsigned int)csic_dev->base);
+ irq = msm_io_r(csic_dev->base + MIPI_INTERRUPT_STATUS);
+ pr_info("%s MIPI_INTERRUPT_STATUS = 0x%x\n", __func__, irq);
+ msm_io_w(irq, csic_dev->base + MIPI_INTERRUPT_STATUS);
+
+ /* TODO: Needs to send this info to upper layers */
+ if ((irq >> 19) & 0x1)
+ pr_info("Unsupported packet format is received\n");
+ return IRQ_HANDLED;
+}
+
+static int msm_csic_subdev_g_chip_ident(struct v4l2_subdev *sd,
+ struct v4l2_dbg_chip_ident *chip)
+{
+ BUG_ON(!chip);
+ chip->ident = V4L2_IDENT_CSIC;
+ chip->revision = 0;
+ return 0;
+}
+
+static struct msm_cam_clk_info csic_clk_info[] = {
+ {"csi_clk", 400000000},
+ {"csi_vfe_clk", -1},
+ {"csi_pclk", -1},
+};
+
+static int msm_csic_init(struct v4l2_subdev *sd, uint32_t *csic_version)
+{
+ int rc = 0;
+ struct csic_device *csic_dev;
+ csic_dev = v4l2_get_subdevdata(sd);
+ if (csic_dev == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ csic_dev->base = ioremap(csic_dev->mem->start,
+ resource_size(csic_dev->mem));
+ if (!csic_dev->base) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ pr_info("msm_cam_clk_enable: enable csi_pclk, csi_clk, csi_vfe_clk\n");
+ rc = msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
+ csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 1);
+ if (rc < 0) {
+ iounmap(csic_dev->base);
+ return rc;
+ }
+
+#if DBG_CSIC
+ enable_irq(csic_dev->irq->start);
+#endif
+
+ return 0;
+}
+
+static int msm_csic_release(struct v4l2_subdev *sd)
+{
+ struct csic_device *csic_dev;
+ csic_dev = v4l2_get_subdevdata(sd);
+
+#if DBG_CSIC
+ disable_irq(csic_dev->irq->start);
+#endif
+
+ pr_info("msm_cam_clk_enable: disble csi_pclk, csi_clk, csi_vfe_clk\n");
+ msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
+ csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 0);
+
+ iounmap(csic_dev->base);
+ return 0;
+}
+
+static long msm_csic_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct csic_cfg_params cfg_params;
+ switch (cmd) {
+ case VIDIOC_MSM_CSIC_CFG:
+ cfg_params.subdev = sd;
+ cfg_params.parms = arg;
+ return msm_csic_config((struct csic_cfg_params *)&cfg_params);
+ case VIDIOC_MSM_CSIC_INIT:
+ return msm_csic_init(sd, (uint32_t *)arg);
+ case VIDIOC_MSM_CSIC_RELEASE:
+ return msm_csic_release(sd);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct v4l2_subdev_core_ops msm_csic_subdev_core_ops = {
+ .g_chip_ident = &msm_csic_subdev_g_chip_ident,
+ .ioctl = &msm_csic_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csic_subdev_ops = {
+ .core = &msm_csic_subdev_core_ops,
+};
+
+static int __devinit csic_probe(struct platform_device *pdev)
+{
+ struct csic_device *new_csic_dev;
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ new_csic_dev = kzalloc(sizeof(struct csic_device), GFP_KERNEL);
+ if (!new_csic_dev) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&new_csic_dev->subdev, &msm_csic_subdev_ops);
+ v4l2_set_subdevdata(&new_csic_dev->subdev, new_csic_dev);
+ platform_set_drvdata(pdev, &new_csic_dev->subdev);
+ mutex_init(&new_csic_dev->mutex);
+
+ new_csic_dev->mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "csic");
+ if (!new_csic_dev->mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto csic_no_resource;
+ }
+ new_csic_dev->irq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "csic");
+ if (!new_csic_dev->irq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto csic_no_resource;
+ }
+ new_csic_dev->io = request_mem_region(new_csic_dev->mem->start,
+ resource_size(new_csic_dev->mem), pdev->name);
+ if (!new_csic_dev->io) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto csic_no_resource;
+ }
+
+ rc = request_irq(new_csic_dev->irq->start, msm_csic_irq,
+ IRQF_TRIGGER_RISING, "csic", new_csic_dev);
+ if (rc < 0) {
+ release_mem_region(new_csic_dev->mem->start,
+ resource_size(new_csic_dev->mem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto csic_no_resource;
+ }
+ disable_irq(new_csic_dev->irq->start);
+ pr_info("msm_cam_clk_enable: enable csi_pclk\n");
+ msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
+ new_csic_dev->csic_clk, 1, 1);
+ new_csic_dev->base = ioremap(new_csic_dev->mem->start,
+ resource_size(new_csic_dev->mem));
+ if (!new_csic_dev->base) {
+ rc = -ENOMEM;
+ goto csic_no_resource;
+ }
+
+ msm_io_w(MIPI_PWR_CNTL_DIS, new_csic_dev->base + MIPI_PWR_CNTL_DIS);
+ pr_info("msm_cam_clk_enable: disable csi_pclk\n");
+ msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
+ new_csic_dev->csic_clk, 1, 0);
+ iounmap(new_csic_dev->base);
+
+ new_csic_dev->pdev = pdev;
+ return 0;
+
+csic_no_resource:
+ mutex_destroy(&new_csic_dev->mutex);
+ kfree(new_csic_dev);
+ return 0;
+}
+
+static struct platform_driver csic_driver = {
+ .probe = csic_probe,
+ .driver = {
+ .name = MSM_CSIC_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_csic_init_module(void)
+{
+ return platform_driver_register(&csic_driver);
+}
+
+static void __exit msm_csic_exit_module(void)
+{
+ platform_driver_unregister(&csic_driver);
+}
+
+module_init(msm_csic_init_module);
+module_exit(msm_csic_exit_module);
+MODULE_DESCRIPTION("MSM csic driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csic.h b/drivers/media/video/msm/csi/msm_csic.h
new file mode 100644
index 0000000..08dde52
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csic.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2012, 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.
+ */
+
+#ifndef MSM_CSIC_H
+#define MSM_CSIC_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csic_device {
+ struct platform_device *pdev;
+ struct v4l2_subdev subdev;
+ struct resource *mem;
+ struct resource *irq;
+ struct resource *io;
+ void __iomem *base;
+ struct mutex mutex;
+ uint32_t hw_version;
+
+ struct clk *csic_clk[5];
+};
+
+struct csic_cfg_params {
+ struct v4l2_subdev *subdev;
+ void *parms;
+};
+
+#define VIDIOC_MSM_CSIC_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_params)
+
+#define VIDIOC_MSM_CSIC_INIT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSIC_RELEASE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+
+#endif
+
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 363e437..a9aa28b 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1478,15 +1478,14 @@
__func__, rc);
return rc;
}
- rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
- pcam->mctl.isp_sdev->sd_vpe);
- if (rc < 0) {
- mutex_unlock(&pcam->vid_lock);
- pr_err("%s: vpe v4l2_device_register_subdev failed rc = %d\n",
- __func__, rc);
- return rc;
+ if (pcam->mctl.isp_sdev->sd_vpe) {
+ rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
+ pcam->mctl.isp_sdev->sd_vpe);
+ if (rc < 0) {
+ mutex_unlock(&pcam->vid_lock);
+ return rc;
+ }
}
-
rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->pvdev);
if (rc < 0) {
@@ -2395,7 +2394,7 @@
goto client_fail;
*actctrl = *a_ext_ctrl;
- a_ext_ctrl->a_create_subdevice((void *)actuator_info->board_info,
+ a_ext_ctrl->a_create_subdevice((void *)actuator_info,
(void *)act_sdev);
return rc;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 5fc3e6a..cc2e8b4 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -43,6 +43,7 @@
#define MSM_CSIPHY_DRV_NAME "msm_csiphy"
#define MSM_CSID_DRV_NAME "msm_csid"
+#define MSM_CSIC_DRV_NAME "msm_csic"
#define MSM_ISPIF_DRV_NAME "msm_ispif"
#define MSM_VFE_DRV_NAME "msm_vfe"
#define MSM_VPE_DRV_NAME "msm_vpe"
@@ -121,6 +122,8 @@
NOTIFY_PCLK_CHANGE, /* arg = pclk */
NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
+ NOTIFY_CSIC_CFG, /* arg = msm_camera_csic_params */
+ NOTIFY_VFE_BUF_FREE_EVT, /* arg = msm_camera_csic_params */
NOTIFY_INVALID
};
@@ -225,6 +228,7 @@
struct msm_cam_config_dev *config_device;
struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
struct v4l2_subdev *csid_sdev; /*csid sub device*/
+ struct v4l2_subdev *csic_sdev; /*csid sub device*/
struct v4l2_subdev *ispif_sdev; /* ispif sub device */
struct v4l2_subdev *act_sdev; /* actuator sub device */
diff --git a/drivers/media/video/msm/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
new file mode 100644
index 0000000..bee9f49
--- /dev/null
+++ b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
@@ -0,0 +1,258 @@
+/* Copyright (c) 2012, 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 <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pm_qos_params.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <mach/camera.h>
+#include <mach/clk.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+
+
+#define MSM_AXI_QOS_PREVIEW 200000
+#define MSM_AXI_QOS_SNAPSHOT 200000
+#define MSM_AXI_QOS_RECORDING 200000
+
+static struct clk *camio_cam_clk;
+static struct resource *clk_ctrl_mem;
+static struct msm_camera_io_clk camio_clk;
+void __iomem *appbase;
+
+void msm_io_w(u32 data, void __iomem *addr)
+{
+ CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+ writel_relaxed((data), (addr));
+}
+
+u32 msm_io_r(void __iomem *addr)
+{
+ uint32_t data = readl_relaxed(addr);
+ CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+ return data;
+}
+
+void msm_camio_clk_rate_set_2(struct clk *clk, int rate)
+{
+ clk_set_rate(clk, rate);
+}
+int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
+{
+ int rc = 0;
+ struct clk *clk = NULL;
+
+ switch (clktype) {
+ case CAMIO_CAM_MCLK_CLK:
+ clk = clk_get(NULL, "cam_m_clk");
+ camio_cam_clk = clk;
+ msm_camio_clk_rate_set_2(clk, camio_clk.mclk_clk_rate);
+ break;
+ default:
+ break;
+ }
+
+ if (!IS_ERR(clk))
+ clk_enable(clk);
+ else
+ rc = -1;
+ return rc;
+}
+
+int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
+{
+ int rc = 0;
+ struct clk *clk = NULL;
+
+ switch (clktype) {
+ case CAMIO_CAM_MCLK_CLK:
+ clk = camio_cam_clk;
+ break;
+ default:
+ break;
+ }
+
+ if (!IS_ERR(clk)) {
+ clk_disable(clk);
+ clk_put(clk);
+ } else
+ rc = -1;
+ return rc;
+}
+
+void msm_camio_clk_rate_set(int rate)
+{
+ struct clk *clk = camio_cam_clk;
+ clk_set_rate(clk, rate);
+}
+
+int msm_sensor_probe_on(struct device *dev)
+{
+ int rc = 0;
+ struct msm_camera_sensor_info *sinfo = dev->platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+ camio_clk = camdev->ioclk;
+
+ rc = camdev->camera_gpio_on();
+ if (rc < 0)
+ return rc;
+
+ rc = msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
+ if (rc < 0)
+ camdev->camera_gpio_off();
+
+ return rc;
+}
+
+int msm_sensor_probe_off(struct device *dev)
+{
+ struct msm_camera_sensor_info *sinfo = dev->platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+ camdev->camera_gpio_off();
+ return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+}
+
+void msm_camio_vfe_blk_reset(void)
+{
+ uint32_t val;
+
+ /* do apps reset */
+ val = readl_relaxed(appbase + 0x00000210);
+ val |= 0x1;
+ writel_relaxed(val, appbase + 0x00000210);
+ usleep_range(10000, 11000);
+
+ val = readl_relaxed(appbase + 0x00000210);
+ val &= ~0x1;
+ writel_relaxed(val, appbase + 0x00000210);
+ usleep_range(10000, 11000);
+
+ /* do axi reset */
+ val = readl_relaxed(appbase + 0x00000208);
+ val |= 0x1;
+ writel_relaxed(val, appbase + 0x00000208);
+ usleep_range(10000, 11000);
+
+ val = readl_relaxed(appbase + 0x00000208);
+ val &= ~0x1;
+ writel_relaxed(val, appbase + 0x00000208);
+ mb();
+ usleep_range(10000, 11000);
+}
+
+int msm_camio_probe_on(struct platform_device *pdev)
+{
+ int rc = 0;
+ const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+ camio_clk = camdev->ioclk;
+
+ rc = camdev->camera_gpio_on();
+ if (rc < 0)
+ return rc;
+ return msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
+}
+
+int msm_camio_probe_off(struct platform_device *pdev)
+{
+ const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+ camdev->camera_gpio_off();
+ return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+}
+
+void msm_camio_set_perf_lvl(enum msm_bus_perf_setting perf_setting)
+{
+ switch (perf_setting) {
+ case S_INIT:
+ add_axi_qos();
+ break;
+ case S_PREVIEW:
+ update_axi_qos(MSM_AXI_QOS_PREVIEW);
+ break;
+ case S_VIDEO:
+ update_axi_qos(MSM_AXI_QOS_RECORDING);
+ break;
+ case S_CAPTURE:
+ update_axi_qos(MSM_AXI_QOS_SNAPSHOT);
+ break;
+ case S_DEFAULT:
+ update_axi_qos(PM_QOS_DEFAULT_VALUE);
+ break;
+ case S_EXIT:
+ release_axi_qos();
+ break;
+ default:
+ CDBG("%s: INVALID CASE\n", __func__);
+ }
+}
+
+static int __devinit clkctl_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ clk_ctrl_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "clk_ctl");
+ if (!clk_ctrl_mem) {
+ pr_err("%s: no mem resource:3?\n", __func__);
+ return -ENODEV;
+ }
+
+ appbase = ioremap(clk_ctrl_mem->start,
+ resource_size(clk_ctrl_mem));
+ if (!appbase) {
+ pr_err("clkctl_probe: appbase:err\n");
+ rc = -ENOMEM;
+ goto ioremap_fail;
+ }
+ return 0;
+
+ioremap_fail:
+ msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
+ return rc;
+}
+
+static int clkctl_remove(struct platform_device *pdev)
+{
+ if (clk_ctrl_mem)
+ iounmap(clk_ctrl_mem);
+
+ return 0;
+}
+
+static struct platform_driver clkctl_driver = {
+ .probe = clkctl_probe,
+ .remove = clkctl_remove,
+ .driver = {
+ .name = "msm_clk_ctl",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_clkctl_init_module(void)
+{
+ return platform_driver_register(&clkctl_driver);
+}
+
+static void __exit msm_clkctl_exit_module(void)
+{
+ platform_driver_unregister(&clkctl_driver);
+}
+
+module_init(msm_clkctl_init_module);
+module_exit(msm_clkctl_exit_module);
+MODULE_DESCRIPTION("CAM IO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 0a1516b..6a9d7c4 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -69,6 +69,20 @@
}
}
+static int msm_isp_notify_VFE_BUF_FREE_EVT(struct v4l2_subdev *sd, void *arg)
+{
+ struct msm_vfe_cfg_cmd cfgcmd;
+ struct msm_camvfe_params vfe_params;
+ int rc;
+
+ cfgcmd.cmd_type = CMD_VFE_BUFFER_RELEASE;
+ cfgcmd.value = NULL;
+ vfe_params.vfe_cfg = &cfgcmd;
+ vfe_params.data = NULL;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ return 0;
+}
+
static int msm_isp_notify_VFE_BUF_EVT(struct v4l2_subdev *sd, void *arg)
{
int rc = -EINVAL;
@@ -89,6 +103,7 @@
switch (vdata->type) {
case VFE_MSG_V32_START:
case VFE_MSG_V32_START_RECORDING:
+ case VFE_MSG_V2X_PREVIEW:
D("%s Got V32_START_*: Getting ping addr id = %d",
__func__, vfe_id);
msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
@@ -105,6 +120,7 @@
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
break;
case VFE_MSG_V32_CAPTURE:
+ case VFE_MSG_V2X_CAPTURE:
pr_err("%s Got V32_CAPTURE: getting buffer for id = %d",
__func__, vfe_id);
msm_mctl_reserve_free_buf(&pcam->mctl, vfe_id, &free_buf);
@@ -161,6 +177,9 @@
if (notification == NOTIFY_VFE_BUF_EVT)
return msm_isp_notify_VFE_BUF_EVT(sd, arg);
+ if (notification == NOTIFY_VFE_BUF_FREE_EVT)
+ return msm_isp_notify_VFE_BUF_FREE_EVT(sd, arg);
+
isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC);
if (!isp_event) {
pr_err("%s Insufficient memory. return", __func__);
@@ -376,6 +395,19 @@
axi_data.region = ®ion[0];
return msm_isp_subdev_ioctl(sd, &cfgcmd,
&axi_data);
+ case CMD_STATS_AEC_AWB_ENABLE:
+ axi_data.bufnum1 =
+ msm_pmem_region_lookup(&sync->pmem_stats,
+ MSM_PMEM_AEC_AWB, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
+ if (!axi_data.bufnum1) {
+ pr_err("%s %d: pmem region lookup error\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ axi_data.region = ®ion[0];
+ return msm_isp_subdev_ioctl(sd, &cfgcmd,
+ &axi_data);
case CMD_STATS_IHIST_ENABLE:
axi_data.bufnum1 =
msm_pmem_region_lookup(&sync->pmem_stats,
@@ -614,6 +646,8 @@
cfgcmd.cmd_type = CMD_STATS_RS_BUF_RELEASE;
else if (buf.type == STAT_CS)
cfgcmd.cmd_type = CMD_STATS_CS_BUF_RELEASE;
+ else if (buf.type == STAT_AEAW)
+ cfgcmd.cmd_type = CMD_STATS_BUF_RELEASE;
else {
pr_err("%s: invalid buf type %d\n",
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index e13dd62..e76b1d2 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -29,6 +29,7 @@
#include "msm.h"
#include "msm_csid.h"
+#include "msm_csic.h"
#include "msm_csiphy.h"
#include "msm_ispif.h"
#include "msm_sensor.h"
@@ -92,6 +93,14 @@
.colorspace = V4L2_COLORSPACE_JPEG,
},
{
+ .name = "NV21BAYER",
+ .depth = 8,
+ .bitsperpxl = 8,
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .pxlcode = V4L2_MBUS_FMT_SGRBG10_1X10, /* Bayer sensor */
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ {
.name = "YU12BAYER",
.depth = 8,
.bitsperpxl = 8,
@@ -107,6 +116,14 @@
.pxlcode = V4L2_MBUS_FMT_SBGGR10_1X10, /* Bayer sensor */
.colorspace = V4L2_COLORSPACE_JPEG,
},
+ {
+ .name = "RAWBAYER",
+ .depth = 10,
+ .bitsperpxl = 10,
+ .fourcc = V4L2_PIX_FMT_SBGGR10,
+ .pxlcode = V4L2_MBUS_FMT_SGRBG10_1X10, /* Bayer sensor */
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
};
@@ -225,6 +242,7 @@
case NOTIFY_VFE_MSG_OUT:
case NOTIFY_VFE_MSG_STATS:
case NOTIFY_VFE_BUF_EVT:
+ case NOTIFY_VFE_BUF_FREE_EVT:
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
rc = p_mctl->isp_sdev->isp_notify(
p_mctl->isp_sdev->sd, notification, arg);
@@ -248,6 +266,10 @@
rc = v4l2_subdev_call(p_mctl->csid_sdev,
core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
break;
+ case NOTIFY_CSIC_CFG:
+ rc = v4l2_subdev_call(p_mctl->csic_sdev,
+ core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+ break;
default:
break;
}
@@ -416,44 +438,70 @@
struct device *dev;
int rc = -ENODEV;
- /* register csiphy subdev */
- driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
- if (!driver)
- goto out;
+ struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
+ struct msm_camera_sensor_info *sinfo =
+ (struct msm_camera_sensor_info *) s_ctrl->sensordata;
+ struct msm_camera_device_platform_data *pdata = sinfo->pdata;
- dev = driver_find_device(driver, NULL, (void *)core_index,
+ if (pdata->is_csiphy) {
+ /* register csiphy subdev */
+ driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, (void *)core_index,
msm_mctl_subdev_match_core);
- if (!dev)
- goto out_put_driver;
+ if (!dev)
+ goto out_put_driver;
- p_mctl->csiphy_sdev = dev_get_drvdata(dev);
- put_driver(driver);
+ p_mctl->csiphy_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+ }
- /* register csid subdev */
- driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
- if (!driver)
- goto out;
+ if (pdata->is_csic) {
+ /* register csic subdev */
+ driver = driver_find(MSM_CSIC_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
- dev = driver_find_device(driver, NULL, (void *)core_index,
+ dev = driver_find_device(driver, NULL, (void *)core_index,
msm_mctl_subdev_match_core);
- if (!dev)
- goto out_put_driver;
+ if (!dev)
+ goto out_put_driver;
- p_mctl->csid_sdev = dev_get_drvdata(dev);
- put_driver(driver);
+ p_mctl->csic_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+ }
- /* register ispif subdev */
- driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
- if (!driver)
- goto out;
+ if (pdata->is_csid) {
+ /* register csid subdev */
+ driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
- dev = driver_find_device(driver, NULL, 0,
+ dev = driver_find_device(driver, NULL, (void *)core_index,
msm_mctl_subdev_match_core);
- if (!dev)
- goto out_put_driver;
+ if (!dev)
+ goto out_put_driver;
- p_mctl->ispif_sdev = dev_get_drvdata(dev);
- put_driver(driver);
+ p_mctl->csid_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+ }
+
+ if (pdata->is_ispif) {
+ /* register ispif subdev */
+ driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, 0,
+ msm_mctl_subdev_match_core);
+ if (!dev)
+ goto out_put_driver;
+
+ p_mctl->ispif_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+ }
/* register vfe subdev */
driver = driver_find(MSM_VFE_DRV_NAME, &platform_bus_type);
@@ -468,18 +516,20 @@
p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
put_driver(driver);
- /* register vfe subdev */
- driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
- if (!driver)
- goto out;
+ if (pdata->is_vpe) {
+ /* register vfe subdev */
+ driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
- dev = driver_find_device(driver, NULL, 0,
+ dev = driver_find_device(driver, NULL, 0,
msm_mctl_subdev_match_core);
- if (!dev)
- goto out_put_driver;
+ if (!dev)
+ goto out_put_driver;
- p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
- put_driver(driver);
+ p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
+ put_driver(driver);
+ }
rc = 0;
return rc;
@@ -522,20 +572,33 @@
goto msm_open_done;
}
- rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
- VIDIOC_MSM_CSIPHY_INIT, NULL);
- if (rc < 0) {
- pr_err("%s: csiphy initialization failed %d\n",
+ if (camdev->is_csiphy) {
+ rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+ VIDIOC_MSM_CSIPHY_INIT, NULL);
+ if (rc < 0) {
+ pr_err("%s: csiphy initialization failed %d\n",
__func__, rc);
- goto msm_open_done;
+ goto msm_open_done;
+ }
}
- rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
- VIDIOC_MSM_CSID_INIT, &csid_version);
- if (rc < 0) {
- pr_err("%s: csid initialization failed %d\n",
+ if (camdev->is_csid) {
+ rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+ VIDIOC_MSM_CSID_INIT, &csid_version);
+ if (rc < 0) {
+ pr_err("%s: csid initialization failed %d\n",
__func__, rc);
- goto msm_open_done;
+ goto msm_open_done;
+ }
+ }
+ if (camdev->is_csic) {
+ rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+ VIDIOC_MSM_CSIC_INIT, &csid_version);
+ if (rc < 0) {
+ pr_err("%s: csic initialization failed %d\n",
+ __func__, rc);
+ goto msm_open_done;
+ }
}
/* ISP first*/
@@ -548,12 +611,14 @@
goto msm_open_done;
}
- rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
- VIDIOC_MSM_ISPIF_INIT, &csid_version);
- if (rc < 0) {
- pr_err("%s: ispif initialization failed %d\n",
+ if (camdev->is_ispif) {
+ rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+ VIDIOC_MSM_ISPIF_INIT, &csid_version);
+ if (rc < 0) {
+ pr_err("%s: ispif initialization failed %d\n",
__func__, rc);
- goto msm_open_done;
+ goto msm_open_done;
+ }
}
/* then sensor - move sub dev later*/
@@ -563,7 +628,6 @@
pr_err("%s: isp init failed: %d\n", __func__, rc);
goto msm_open_done;
}
-
if (sync->actctrl.a_power_up)
rc = sync->actctrl.a_power_up(
sync->sdata->actuator_info);
@@ -573,12 +637,13 @@
goto msm_open_done;
}
- pm_qos_add_request(&p_mctl->pm_qos_req_list,
+ if (camdev->is_ispif) {
+ pm_qos_add_request(&p_mctl->pm_qos_req_list,
PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
- pm_qos_update_request(&p_mctl->pm_qos_req_list,
+ pm_qos_update_request(&p_mctl->pm_qos_req_list,
MSM_V4L2_SWFI_LATENCY);
-
+ }
sync->apps_id = apps_id;
sync->opencnt++;
}
@@ -591,28 +656,44 @@
static int msm_mctl_release(struct msm_cam_media_controller *p_mctl)
{
int rc = 0;
- v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
- VIDIOC_MSM_ISPIF_RELEASE, NULL);
+ struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
+ struct msm_camera_sensor_info *sinfo =
+ (struct msm_camera_sensor_info *) s_ctrl->sensordata;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
+ if (camdev->is_ispif) {
+ v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+ VIDIOC_MSM_ISPIF_RELEASE, NULL);
+ }
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
p_mctl->isp_sdev->isp_release(&p_mctl->sync);
- v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
- VIDIOC_MSM_CSID_RELEASE, NULL);
+ if (camdev->is_csid) {
+ v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+ VIDIOC_MSM_CSID_RELEASE, NULL);
+ }
- v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
- VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+ if (camdev->is_csic) {
+ v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+ VIDIOC_MSM_CSIC_RELEASE, NULL);
+ }
+
+ if (camdev->is_csiphy) {
+ v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+ VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+ }
if (p_mctl->sync.actctrl.a_power_down)
p_mctl->sync.actctrl.a_power_down(
p_mctl->sync.sdata->actuator_info);
v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
-
- pm_qos_update_request(&p_mctl->pm_qos_req_list,
+ if (camdev->is_ispif) {
+ pm_qos_update_request(&p_mctl->pm_qos_req_list,
PM_QOS_DEFAULT_VALUE);
- pm_qos_remove_request(&p_mctl->pm_qos_req_list);
-
+ pm_qos_remove_request(&p_mctl->pm_qos_req_list);
+ }
wake_unlock(&p_mctl->sync.wake_lock);
return rc;
}
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index b631981..0ba1c0f 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -220,6 +220,7 @@
case MSM_PMEM_CS:
case MSM_PMEM_IHIST:
case MSM_PMEM_SKIN:
+ case MSM_PMEM_AEC_AWB:
rc = msm_pmem_table_add(ptype, pinfo, client);
break;
@@ -246,6 +247,7 @@
case MSM_PMEM_CS:
case MSM_PMEM_IHIST:
case MSM_PMEM_SKIN:
+ case MSM_PMEM_AEC_AWB:
hlist_for_each_entry_safe(region, node, n,
ptype, list) {
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
new file mode 100644
index 0000000..638c51d
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -0,0 +1,1353 @@
+/* Copyright (c) 2012, 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 <linux/msm_adsp.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/android_pmem.h>
+#include <linux/slab.h>
+#include <linux/pm_qos_params.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_isp.h>
+#include <mach/msm_adsp.h>
+#include <mach/clk.h>
+#include <mach/camera.h>
+#include "msm_vfe7x27a_v4l2.h"
+#include "msm.h"
+
+/* ADSP Messages */
+#define MSG_RESET_ACK 0
+#define MSG_STOP_ACK 1
+#define MSG_SNAPSHOT 2
+#define MSG_ILLEGAL_COMMAND 3
+#define MSG_START_ACK 4
+#define MSG_UPDATE_ACK 5
+#define MSG_OUTPUT1 6
+#define MSG_OUTPUT2 7
+#define MSG_STATS_AF 8
+#define MSG_STATS_WE 9
+#define MSG_STATS_HISTOGRAM 10
+#define MSG_EPOCH1 11
+#define MSG_EPOCH2 12
+#define MSG_VFE_ERROR 13
+#define MSG_SYNC_TIMER1_DONE 14
+#define MSG_SYNC_TIMER2_DONE 15
+#define MSG_ASYNC_TIMER1_DONE 16
+#define MSG_ASYNC_TIMER2_DONE 17
+#define MSG_CAPTURE_COMPLETE 18
+#define MSG_TABLE_CMD_ACK 19
+#define MSG_EXP_TIMEOUT_ACK 20
+#define MSG_SOF 21
+#define MSG_OUTPUT_T 22
+#define MSG_OUTPUT_S 23
+
+#define VFE_ADSP_EVENT 0xFFFF
+#define SNAPSHOT_MASK_MODE 0x00000001
+#define MSM_AXI_QOS_PREVIEW 122000
+#define MSM_AXI_QOS_SNAPSHOT 192000
+
+
+#define QDSP_CMDQUEUE 25
+#define QDSP_SCALEQUEUE 26
+#define QDSP_TABLEQUEUE 27
+
+/* ADSP Scler queue Cmd IDs */
+#define VFE_SCALE_OUTPUT1_CONFIG 0
+#define VFE_SCALE_OUTPUT2_CONFIG 1
+#define VFE_SCALE_MAX 0xFFFFFFFF
+
+/* ADSP table queue Cmd IDs */
+#define VFE_AXI_INPUT_CONFIG 0
+#define VFE_AXI_OUTPUT_CONFIG 1
+#define VFE_RGB_GAMMA_CONFIG 2
+#define VFE_Y_GAMMA_CONFIG 3
+#define VFE_ROLL_OFF_CONFIG 4
+#define VFE_DEMOSAICv3_BPC_CFG 6
+#define VFE_DEMOSAICv3_ABF_CFG 7
+#define VFE_DEMOSAICv3_CFG 8
+#define VFE_MAX 0xFFFFFFFF
+
+/* ADSP cfg queue cmd IDs */
+#define VFE_RESET 0
+#define VFE_START 1
+#define VFE_STOP 2
+#define VFE_UPDATE 3
+#define VFE_CAMIF_CONFIG 4
+#define VFE_ACTIVE_REGION_CONFIG 5
+#define VFE_DEMOSAIC_CONFIG 6
+#define VFE_INPUT_FORMAT_CONFIG 7
+#define VFE_OUTPUT_CLAMP_CONFIG 8
+#define VFE_CHROMA_SUBSAMPLE_CONFIG 9
+#define VFE_BLACK_LEVEL_CONFIG 10
+#define VFE_WHITE_BALANCE_CONFIG 11
+#define VFE_COLOR_PROCESSING_CONFIG 12
+#define VFE_ADAPTIVE_FILTER_CONFIG 13
+#define VFE_FRAME_SKIP_CONFIG 14
+#define VFE_FOV_CROP 15
+#define VFE_STATS_AUTOFOCUS_CONFIG 16
+#define VFE_STATS_WB_EXP_CONFIG 17
+#define VFE_STATS_HISTOGRAM_CONFIG 18
+#define VFE_OUTPUT1_ACK 19
+#define VFE_OUTPUT2_ACK 20
+#define VFE_STATS_AUTOFOCUS_ACK 21
+#define VFE_STATS_WB_EXP_ACK 22
+#define VFE_EPOCH1_ACK 23
+#define VFE_EPOCH2_ACK 24
+#define VFE_UPDATE_CAMIF_FRAME_CONFIG 25
+#define VFE_SYNC_TIMER1_CONFIG 26
+#define VFE_SYNC_TIMER2_CONFIG 27
+#define VFE_ASYNC_TIMER1_START 28
+#define VFE_ASYNC_TIMER2_START 29
+#define VFE_STATS_AUTOFOCUS_UPDATE 30
+#define VFE_STATS_WB_EXP_UPDATE 31
+#define VFE_ROLL_OFF_UPDATE 33
+#define VFE_DEMOSAICv3_BPC_UPDATE 34
+#define VFE_TESTGEN_START 35
+#define VFE_STATS_MA 0xFFFFFFFF
+
+struct msg_id_map msgs_map[] = {
+ {MSG_RESET_ACK, MSG_ID_RESET_ACK},
+ {MSG_STOP_ACK, MSG_ID_STOP_ACK},
+ {MSG_SNAPSHOT, MSG_ID_SNAPSHOT_DONE},
+ {MSG_ILLEGAL_COMMAND, VFE_MAX},
+ {MSG_START_ACK, MSG_ID_START_ACK},
+ {MSG_UPDATE_ACK, MSG_ID_UPDATE_ACK},
+ {MSG_OUTPUT1, VFE_MAX},
+ {MSG_OUTPUT2, VFE_MAX},
+ {MSG_STATS_AF, MSG_ID_STATS_AF},
+ {MSG_STATS_WE, MSG_ID_STATS_AWB_AEC},
+ {MSG_STATS_HISTOGRAM, MSG_ID_STATS_IHIST},
+ {MSG_EPOCH1, MSG_ID_EPOCH1},
+ {MSG_EPOCH2, MSG_ID_EPOCH2},
+ {MSG_VFE_ERROR, MSG_ID_CAMIF_ERROR},
+ {MSG_SYNC_TIMER1_DONE, MSG_ID_SYNC_TIMER1_DONE},
+ {MSG_SYNC_TIMER2_DONE, MSG_ID_SYNC_TIMER2_DONE},
+ {MSG_ASYNC_TIMER1_DONE, MSG_ID_ASYNC_TIMER1_DONE},
+ {MSG_ASYNC_TIMER2_DONE, MSG_ID_ASYNC_TIMER2_DONE},
+ {MSG_CAPTURE_COMPLETE, MSG_CAPTURE_COMPLETE},
+ {MSG_TABLE_CMD_ACK, MSG_TABLE_CMD_ACK},
+ {MSG_EXP_TIMEOUT_ACK, MSG_EXP_TIMEOUT_ACK},
+ {MSG_SOF, MSG_ID_SOF_ACK},
+ {MSG_OUTPUT_T, MSG_ID_OUTPUT_T},
+ {MSG_OUTPUT_S, MSG_ID_OUTPUT_S},
+};
+
+struct cmd_id_map cmds_map[] = {
+ {VFE_CMD_DUMMY_0, VFE_MAX, VFE_MAX},
+ {VFE_CMD_SET_CLK, VFE_MAX, VFE_MAX},
+ {VFE_CMD_RESET, VFE_RESET, QDSP_CMDQUEUE,
+ "VFE_CMD_RESET", "VFE_RESET"},
+ {VFE_CMD_START, VFE_START, QDSP_CMDQUEUE,
+ "VFE_CMD_START", "VFE_START"},
+ {VFE_CMD_TEST_GEN_START, VFE_TESTGEN_START, QDSP_CMDQUEUE,
+ "VFE_CMD_TEST_GEN_START", "VFE_TESTGEN_START"},
+ {VFE_CMD_OPERATION_CFG, VFE_MAX , VFE_MAX},
+ {VFE_CMD_AXI_OUT_CFG, VFE_AXI_OUTPUT_CONFIG, QDSP_TABLEQUEUE,
+ "VFE_CMD_AXI_OUT_CFG", "VFE_AXI_OUTPUT_CONFIG"},
+ {VFE_CMD_CAMIF_CFG, VFE_CAMIF_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_CAMIF_CFG", "VFE_CAMIF_CONFIG"},
+ {VFE_CMD_AXI_INPUT_CFG, VFE_AXI_INPUT_CONFIG, QDSP_TABLEQUEUE,
+ "VFE_CMD_AXI_INPUT_CFG", "VFE_AXI_INPUT_CONFIG"},
+ {VFE_CMD_BLACK_LEVEL_CFG, VFE_BLACK_LEVEL_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_BLACK_LEVEL_CFG", "VFE_BLACK_LEVEL_CONFIG"},
+ {VFE_CMD_MESH_ROLL_OFF_CFG, VFE_ROLL_OFF_CONFIG, QDSP_TABLEQUEUE,
+ "VFE_CMD_MESH_ROLL_OFF_CFG", "VFE_ROLL_OFF_CONFIG"},
+ {VFE_CMD_DEMUX_CFG, VFE_INPUT_FORMAT_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_DEMUX_CFG", "VFE_INPUT_FORMAT_CONFIG"},
+ {VFE_CMD_FOV_CFG, VFE_FOV_CROP, QDSP_CMDQUEUE,
+ "VFE_CMD_FOV_CFG", "VFE_FOV_CROP"},
+ {VFE_CMD_MAIN_SCALER_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_WB_CFG, VFE_WHITE_BALANCE_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_WB_CFG", "VFE_WHITE_BALANCE_CONFIG"},
+ {VFE_CMD_COLOR_COR_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_RGB_G_CFG, VFE_RGB_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+ "VFE_CMD_RGB_G_CFG", "VFE_RGB_GAMMA_CONFIG"},
+ {VFE_CMD_LA_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CHROMA_EN_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CHROMA_SUP_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_MCE_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_SK_ENHAN_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_ASF_CFG, VFE_ADAPTIVE_FILTER_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_ASF_CFG", "VFE_ADAPTIVE_FILTER_CONFIG"},
+ {VFE_CMD_S2Y_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_S2CbCr_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CHROMA_SUBS_CFG, VFE_CHROMA_SUBSAMPLE_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_CHROMA_SUBS_CFG", "VFE_CHROMA_SUBSAMPLE_CONFIG"},
+ {VFE_CMD_OUT_CLAMP_CFG, VFE_OUTPUT_CLAMP_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_OUT_CLAMP_CFG", "VFE_OUTPUT_CLAMP_CONFIG"},
+ {VFE_CMD_FRAME_SKIP_CFG, VFE_FRAME_SKIP_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_FRAME_SKIP_CFG", "VFE_FRAME_SKIP_CONFIG"},
+ {VFE_CMD_DUMMY_1, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DUMMY_2, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DUMMY_3, VFE_MAX, VFE_MAX},
+ {VFE_CMD_UPDATE, VFE_UPDATE, QDSP_CMDQUEUE,
+ "VFE_CMD_UPDATE", "VFE_UPDATE"},
+ {VFE_CMD_BL_LVL_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMUX_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_FOV_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_MAIN_SCALER_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_WB_UPDATE, VFE_WHITE_BALANCE_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_WB_UPDATE", "VFE_WHITE_BALANCE_CONFIG"},
+ {VFE_CMD_COLOR_COR_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_RGB_G_UPDATE, VFE_RGB_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+ "VFE_CMD_RGB_G_UPDATE", "VFE_RGB_GAMMA_CONFIG"},
+ {VFE_CMD_LA_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CHROMA_EN_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CHROMA_SUP_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_MCE_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_SK_ENHAN_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_S2CbCr_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_S2Y_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_ASF_UPDATE, VFE_ADAPTIVE_FILTER_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_ASF_UPDATE", "VFE_ADAPTIVE_FILTER_CONFIG"},
+ {VFE_CMD_FRAME_SKIP_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CAMIF_FRAME_UPDATE, VFE_UPDATE_CAMIF_FRAME_CONFIG,
+ QDSP_CMDQUEUE, "VFE_CMD_CAMIF_FRAME_UPDATE",
+ "VFE_UPDATE_CAMIF_FRAME_CONFIG"},
+ {VFE_CMD_STATS_AF_UPDATE, VFE_STATS_AUTOFOCUS_UPDATE, QDSP_CMDQUEUE,
+ "VFE_CMD_STATS_AF_UPDATE", "VFE_STATS_AUTOFOCUS_UPDATE"},
+ {VFE_CMD_STATS_AE_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AWB_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_RS_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_CS_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_SKIN_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_IHIST_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DUMMY_4, VFE_MAX, VFE_MAX},
+ {VFE_CMD_EPOCH1_ACK, VFE_EPOCH1_ACK, QDSP_CMDQUEUE,
+ "VFE_CMD_EPOCH1_ACK", "VFE_EPOCH1_ACK"},
+ {VFE_CMD_EPOCH2_ACK, VFE_EPOCH2_ACK, QDSP_CMDQUEUE,
+ "VFE_CMD_EPOCH2_ACK", "VFE_EPOCH2_ACK"},
+ {VFE_CMD_START_RECORDING, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STOP_RECORDING, VFE_MAX , VFE_MAX},
+ {VFE_CMD_DUMMY_5, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DUMMY_6, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CAPTURE, VFE_START, QDSP_CMDQUEUE,
+ "VFE_CMD_CAPTURE", "VFE_START"},
+ {VFE_CMD_DUMMY_7, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STOP, VFE_STOP, QDSP_CMDQUEUE, "VFE_CMD_STOP", "VFE_STOP"},
+ {VFE_CMD_GET_HW_VERSION, VFE_MAX, VFE_MAX},
+ {VFE_CMD_GET_FRAME_SKIP_COUNTS, VFE_MAX, VFE_MAX},
+ {VFE_CMD_OUTPUT1_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_OUTPUT2_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_OUTPUT3_BUFFER_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_JPEG_OUT_BUF_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_RAW_OUT_BUF_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_RAW_IN_BUF_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AF_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AE_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AWB_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_RS_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_CS_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_SKIN_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_IHIST_ENQ, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DUMMY_8, VFE_MAX, VFE_MAX},
+ {VFE_CMD_JPEG_ENC_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DUMMY_9, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AF_START, VFE_STATS_AUTOFOCUS_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_STATS_AF_START", "VFE_STATS_AUTOFOCUS_CONFIG"},
+ {VFE_CMD_STATS_AF_STOP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AE_START, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AE_STOP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AWB_START, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_AWB_STOP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_RS_START, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_RS_STOP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_CS_START, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_CS_STOP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_SKIN_START, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_SKIN_STOP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_STATS_IHIST_START, VFE_STATS_HISTOGRAM_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_STATS_IHIST_START", "VFE_STATS_HISTOGRAM_CONFIG"},
+ {VFE_CMD_STATS_IHIST_STOP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DUMMY_10, VFE_MAX, VFE_MAX},
+ {VFE_CMD_SYNC_TIMER_SETTING, VFE_MAX, VFE_MAX},
+ {VFE_CMD_ASYNC_TIMER_SETTING, VFE_MAX, VFE_MAX},
+ {VFE_CMD_LIVESHOT, VFE_MAX, VFE_MAX},
+ {VFE_CMD_LA_SETUP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_LINEARIZATION_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMOSAICV3, VFE_DEMOSAICv3_CFG, QDSP_TABLEQUEUE,
+ "VFE_CMD_DEMOSAICV3", "VFE_DEMOSAICv3_CFG"},
+ {VFE_CMD_DEMOSAICV3_ABCC_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMOSAICV3_DBCC_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMOSAICV3_DBPC_CFG, VFE_DEMOSAICv3_BPC_CFG, QDSP_TABLEQUEUE,
+ "VFE_CMD_DEMOSAICV3_DBPC_CFG", "VFE_DEMOSAICv3_BPC_CFG"},
+ {VFE_CMD_DEMOSAICV3_ABF_CFG, VFE_DEMOSAICv3_ABF_CFG, QDSP_TABLEQUEUE,
+ "VFE_CMD_DEMOSAICV3_ABF_CFG", "VFE_DEMOSAICv3_ABF_CFG"},
+ {VFE_CMD_DEMOSAICV3_ABCC_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMOSAICV3_DBCC_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMOSAICV3_DBPC_UPDATE, VFE_DEMOSAICv3_BPC_UPDATE,
+ QDSP_CMDQUEUE, "VFE_CMD_DEMOSAICV3_DBPC_UPDATE",
+ "VFE_DEMOSAICv3_BPC_UPDATE"},
+ {VFE_CMD_XBAR_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_MODULE_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_ZSL, VFE_MAX, VFE_MAX},
+ {VFE_CMD_LINEARIZATION_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMOSAICV3_ABF_UPDATE, VFE_DEMOSAICv3_ABF_CFG,
+ QDSP_TABLEQUEUE, "VFE_CMD_DEMOSAICV3_ABF_UPDATE",
+ "VFE_DEMOSAICv3_ABF_CFG"},
+ {VFE_CMD_CLF_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CLF_LUMA_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_CLF_CHROMA_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_PCA_ROLL_OFF_CFG, VFE_MAX, VFE_MAX},
+ {VFE_CMD_PCA_ROLL_OFF_UPDATE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_GET_REG_DUMP, VFE_MAX, VFE_MAX},
+ {VFE_CMD_GET_LINEARIZATON_TABLE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_GET_MESH_ROLLOFF_TABLE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_GET_PCA_ROLLOFF_TABLE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_GET_RGB_G_TABLE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_GET_LA_TABLE, VFE_MAX, VFE_MAX},
+ {VFE_CMD_DEMOSAICV3_UPDATE, VFE_DEMOSAICv3_CFG, QDSP_TABLEQUEUE,
+ "VFE_CMD_DEMOSAICV3_UPDATE", "VFE_DEMOSAICv3_CFG"},
+ {VFE_CMD_ACTIVE_REGION_CFG, VFE_ACTIVE_REGION_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_ACTIVE_REGION_CFG", "VFE_ACTIVE_REGION_CONFIG"},
+ {VFE_CMD_COLOR_PROCESSING_CONFIG, VFE_COLOR_PROCESSING_CONFIG,
+ QDSP_CMDQUEUE, "VFE_CMD_COLOR_PROCESSING_CONFIG",
+ "VFE_COLOR_PROCESSING_CONFIG"},
+ {VFE_CMD_STATS_WB_AEC_CONFIG, VFE_STATS_WB_EXP_CONFIG, QDSP_CMDQUEUE,
+ "VFE_CMD_STATS_WB_AEC_CONFIG", "VFE_STATS_WB_EXP_CONFIG"},
+ {VFE_CMD_STATS_WB_AEC_UPDATE, VFE_STATS_WB_EXP_UPDATE, QDSP_CMDQUEUE,
+ "VFE_CMD_STATS_WB_AEC_UPDATE", "VFE_STATS_WB_EXP_UPDATE"},
+ {VFE_CMD_Y_GAMMA_CONFIG, VFE_Y_GAMMA_CONFIG, QDSP_TABLEQUEUE,
+ "VFE_CMD_Y_GAMMA_CONFIG", "VFE_Y_GAMMA_CONFIG"},
+ {VFE_CMD_SCALE_OUTPUT1_CONFIG, VFE_SCALE_OUTPUT1_CONFIG,
+ QDSP_SCALEQUEUE, "VFE_CMD_SCALE_OUTPUT1_CONFIG",
+ "VFE_SCALE_OUTPUT1_CONFIG"},
+ {VFE_CMD_SCALE_OUTPUT2_CONFIG, VFE_SCALE_OUTPUT2_CONFIG,
+ QDSP_SCALEQUEUE, "VFE_CMD_SCALE_OUTPUT2_CONFIG",
+ "VFE_SCALE_OUTPUT2_CONFIG"},
+};
+
+
+static struct msm_adsp_module *qcam_mod;
+static struct msm_adsp_module *vfe_mod;
+static void *extdata;
+static uint32_t extlen;
+
+struct mutex vfe_lock;
+static void *vfe_syncdata;
+static uint8_t vfestopped;
+
+static struct stop_event stopevent;
+
+static uint32_t op_mode;
+static uint32_t raw_mode;
+static struct vfe2x_ctrl_type *vfe2x_ctrl;
+
+static void vfe2x_send_isp_msg(
+ struct vfe2x_ctrl_type *vctrl,
+ uint32_t isp_msg_id)
+{
+ struct isp_msg_event isp_msg_evt;
+
+ isp_msg_evt.msg_id = isp_msg_id;
+ isp_msg_evt.sof_count = vfe2x_ctrl->vfeFrameId;
+ v4l2_subdev_notify(&vctrl->subdev,
+ NOTIFY_ISP_MSG_EVT,
+ (void *)&isp_msg_evt);
+}
+
+static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
+ uint32_t ch0_paddr, uint32_t ch1_paddr)
+{
+ struct isp_msg_output msg;
+
+ msg.output_id = msgid;
+ msg.buf.ch_paddr[0] = ch0_paddr;
+ msg.buf.ch_paddr[1] = ch1_paddr;
+ msg.frameCounter = vfe2x_ctrl->vfeFrameId;
+
+ v4l2_subdev_notify(&vfe2x_ctrl->subdev,
+ NOTIFY_VFE_MSG_OUT,
+ &msg);
+ return;
+}
+
+static void vfe_send_stats_msg(uint32_t buf_addr, uint32_t msg_id)
+{
+ struct isp_msg_stats msg_stats;
+
+ msg_stats.frameCounter = vfe2x_ctrl->vfeFrameId;
+ msg_stats.buffer = buf_addr;
+ msg_stats.id = msg_id;
+
+ v4l2_subdev_notify(&vfe2x_ctrl->subdev,
+ NOTIFY_VFE_MSG_STATS,
+ &msg_stats);
+}
+
+static void vfe_7x_ops(void *driver_data, unsigned id, size_t len,
+ void (*getevent)(void *ptr, size_t len))
+{
+ uint32_t evt_buf[3];
+ void *data;
+ struct buf_info *outch = NULL;
+ uint32_t y_phy, cbcr_phy;
+ struct table_cmd *table_pending = NULL;
+ unsigned long flags;
+ void *cmd_data = NULL;
+ unsigned char buf[256];
+ struct msm_free_buf *free_buf = NULL;
+ struct vfe_outputack fack;
+
+ CDBG("%s:id=%d\n", __func__, id);
+
+ if (id != VFE_ADSP_EVENT) {
+ data = kzalloc(len, GFP_KERNEL);
+ if (!data) {
+ pr_err("%s: rp: cannot allocate buffer\n", __func__);
+ return;
+ }
+ }
+ if (id == VFE_ADSP_EVENT) {
+ /* event */
+ getevent(evt_buf, sizeof(evt_buf));
+ CDBG("%s:event:msg_id=%d\n", __func__, id);
+ } else {
+ /* messages */
+ getevent(data, len);
+ CDBG("%s:messages:msg_id=%d\n", __func__, id);
+
+ switch (id) {
+ case MSG_SNAPSHOT:
+ msm_camio_set_perf_lvl(S_PREVIEW);
+ vfe_7x_ops(driver_data, MSG_OUTPUT_S, len, getevent);
+ if (!raw_mode)
+ vfe_7x_ops(driver_data, MSG_OUTPUT_T,
+ len, getevent);
+ vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SNAPSHOT_DONE);
+ return;
+ case MSG_OUTPUT_S:
+ outch = &vfe2x_ctrl->snap;
+ y_phy = outch->ping.ch_paddr[0];
+ cbcr_phy = outch->ping.ch_paddr[1];
+ CDBG("MSG_OUTPUT_S: %x %x\n",
+ (unsigned int)y_phy, (unsigned int)cbcr_phy);
+ vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_S,
+ y_phy, cbcr_phy);
+ break;
+ case MSG_OUTPUT_T:
+ outch = &vfe2x_ctrl->thumb;
+ y_phy = outch->ping.ch_paddr[0];
+ cbcr_phy = outch->ping.ch_paddr[1];
+ CDBG("MSG_OUTPUT_T: %x %x\n",
+ (unsigned int)y_phy, (unsigned int)cbcr_phy);
+ vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_T,
+ y_phy, cbcr_phy);
+ break;
+ case MSG_OUTPUT1:
+ case MSG_OUTPUT2:
+ if (op_mode & SNAPSHOT_MASK_MODE) {
+ kfree(data);
+ return;
+ } else {
+ free_buf = vfe2x_check_free_buffer(
+ VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_P);
+ CDBG("free_buf = %x\n", (unsigned int) free_buf);
+ if (free_buf) {
+ fack.header = VFE_OUTPUT2_ACK;
+
+ fack.output2newybufferaddress =
+ (void *)(free_buf->ch_paddr[0]);
+
+ fack.output2newcbcrbufferaddress =
+ (void *)(free_buf->ch_paddr[1]);
+
+ cmd_data = &fack;
+ len = sizeof(fack);
+ msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+ cmd_data, len);
+ } else {
+ fack.header = VFE_OUTPUT2_ACK;
+ fack.output2newybufferaddress =
+ (void *)
+ ((struct vfe_endframe *)data)->y_address;
+ fack.output2newcbcrbufferaddress =
+ (void *)
+ ((struct vfe_endframe *)data)->cbcr_address;
+ cmd_data = &fack;
+ len = sizeof(fack);
+ msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+ cmd_data, len);
+ }
+ }
+ y_phy = ((struct vfe_endframe *)data)->y_address;
+ cbcr_phy = ((struct vfe_endframe *)data)->cbcr_address;
+
+
+ CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
+ y_phy, cbcr_phy);
+
+ memcpy(((struct vfe_frame_extra *)extdata),
+ &((struct vfe_endframe *)data)->extra,
+ sizeof(struct vfe_frame_extra));
+
+ vfe2x_ctrl->vfeFrameId =
+ ((struct vfe_frame_extra *)extdata)->frame_id;
+ vfe_send_outmsg(&vfe2x_ctrl->subdev,
+ MSG_ID_OUTPUT_P,
+ y_phy, cbcr_phy);
+ break;
+ case MSG_RESET_ACK:
+ case MSG_START_ACK:
+ case MSG_UPDATE_ACK:
+ case MSG_VFE_ERROR:
+ case MSG_SYNC_TIMER1_DONE:
+ case MSG_SYNC_TIMER2_DONE:
+ vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id);
+ if (id == MSG_START_ACK)
+ vfe2x_ctrl->vfe_started = 1;
+ break;
+ case MSG_SOF:
+ vfe2x_ctrl->vfeFrameId++;
+ if (vfe2x_ctrl->vfeFrameId == 0)
+ vfe2x_ctrl->vfeFrameId = 1; /* wrapped back */
+ vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SOF_ACK);
+ if (raw_mode)
+ vfe2x_send_isp_msg(vfe2x_ctrl,
+ MSG_ID_START_ACK);
+ break;
+ case MSG_STOP_ACK:
+ stopevent.state = 1;
+ vfe2x_ctrl->vfe_started = 0;
+ wake_up(&stopevent.wait);
+ vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_STOP_ACK);
+ break;
+ case MSG_STATS_AF:
+ case MSG_STATS_WE:
+ vfe_send_stats_msg(*(uint32_t *)data,
+ msgs_map[id].isp_id);
+ break;
+ default:
+ vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id);
+ break;
+ }
+ }
+ if (MSG_TABLE_CMD_ACK == id) {
+ spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+ if (list_empty(&vfe2x_ctrl->table_q)) {
+ if (vfe2x_ctrl->start_pending) {
+ CDBG("Send START\n");
+ cmd_data = buf;
+ *(uint32_t *)cmd_data = VFE_START;
+ memcpy(((char *)cmd_data) + 4,
+ &vfe2x_ctrl->start_cmd,
+ sizeof(vfe2x_ctrl->start_cmd));
+ /* Send Start cmd here */
+ len = sizeof(vfe2x_ctrl->start_cmd) + 4;
+ msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+ cmd_data, len);
+ vfe2x_ctrl->start_pending = 0;
+ }
+ vfe2x_ctrl->tableack_pending = 0;
+ spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+ return;
+ }
+ table_pending = list_first_entry(&vfe2x_ctrl->table_q,
+ struct table_cmd, list);
+ if (!table_pending) {
+ vfe2x_ctrl->tableack_pending = 0;
+ spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+ return;
+ }
+ msm_adsp_write(vfe_mod, table_pending->queue,
+ table_pending->cmd, table_pending->size);
+ list_del(&table_pending->list);
+ kfree(table_pending->cmd);
+ vfe2x_ctrl->tableack_pending = 1;
+ spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+ } else if (!vfe2x_ctrl->tableack_pending) {
+ if (!list_empty(&vfe2x_ctrl->table_q))
+ return;
+ }
+}
+
+static struct msm_adsp_ops vfe_7x_sync = {
+ .event = vfe_7x_ops,
+};
+
+static int vfe_7x_config_axi(int mode,
+ struct buf_info *ad, struct axiout *ao)
+{
+ unsigned long *bptr;
+ int cnt;
+ int rc = 0;
+
+
+ if (mode == OUTPUT_1) {
+ ao->output1buffer1_y_phy = ad->ping.ch_paddr[0];
+ ao->output1buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+ ao->output1buffer2_y_phy = ad->pong.ch_paddr[0];
+ ao->output1buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+ bptr = &ao->output1buffer3_y_phy;
+ for (cnt = 0; cnt < 6; cnt++) {
+ *bptr = ad->pong.ch_paddr[0];
+ bptr++;
+ *bptr = ad->pong.ch_paddr[1];
+ bptr++;
+ }
+ }
+
+ if (mode == OUTPUT_2) {
+ ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+ ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+ ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+ ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+ ao->output2buffer3_y_phy = ad->free_buf.ch_paddr[0];
+ ao->output2buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
+ bptr = &ao->output2buffer4_y_phy;
+ for (cnt = 0; cnt < 5; cnt++) {
+ *bptr = ad->pong.ch_paddr[0];
+ bptr++;
+ *bptr = ad->pong.ch_paddr[1];
+ bptr++;
+ }
+ }
+
+ if (mode == OUTPUT_1_AND_2) {
+ if (raw_mode) {
+ ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+ ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[0];
+ ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+ ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[0];
+ } else {
+ ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
+ ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+ ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
+ ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+ }
+ bptr = &ao->output2buffer3_y_phy;
+ for (cnt = 0; cnt < 6; cnt++) {
+ *bptr = ad->pong.ch_paddr[0];
+ bptr++;
+ *bptr = ad->pong.ch_paddr[0];
+ bptr++;
+ }
+ }
+
+ return rc;
+}
+
+static void vfe2x_subdev_notify(int id, int path)
+{
+ struct msm_vfe_resp *rp;
+ unsigned long flags = 0;
+ spin_lock_irqsave(&vfe2x_ctrl->sd_notify_lock, flags);
+ rp = msm_isp_sync_alloc(sizeof(struct msm_vfe_resp), GFP_ATOMIC);
+ if (!rp) {
+ CDBG("rp: cannot allocate buffer\n");
+ return;
+ }
+ CDBG("vfe2x_subdev_notify : msgId = %d\n", id);
+ rp->evt_msg.type = MSM_CAMERA_MSG;
+ rp->evt_msg.msg_id = path;
+ rp->type = id;
+ v4l2_subdev_notify(&vfe2x_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
+ spin_unlock_irqrestore(&vfe2x_ctrl->sd_notify_lock, flags);
+}
+
+static struct msm_free_buf *vfe2x_check_free_buffer(int id, int path)
+{
+ struct buf_info *outch = NULL;
+
+ vfe2x_subdev_notify(id, path);
+ if (op_mode & SNAPSHOT_MASK_MODE) {
+ if (path == VFE_MSG_OUTPUT_S)
+ outch = &vfe2x_ctrl->snap;
+ else if (path == VFE_MSG_OUTPUT_T)
+ outch = &vfe2x_ctrl->thumb;
+ } else {
+ if (path == VFE_MSG_OUTPUT_P)
+ outch = &vfe2x_ctrl->prev;
+ }
+ if (outch->free_buf.ch_paddr[0])
+ return &outch->free_buf;
+
+ return NULL;
+}
+
+static int vfe2x_configure_pingpong_buffers(int id, int path)
+{
+ struct buf_info *outch = NULL;
+ int rc = 0;
+
+ vfe2x_subdev_notify(id, path);
+
+ CDBG("Opmode = %d\n", op_mode);
+ if (op_mode & SNAPSHOT_MASK_MODE) {
+ if (path == VFE_MSG_OUTPUT_S)
+ outch = &vfe2x_ctrl->snap;
+ else if (path == VFE_MSG_OUTPUT_T)
+ outch = &vfe2x_ctrl->thumb;
+ } else {
+ if (path == VFE_MSG_OUTPUT_P)
+ outch = &vfe2x_ctrl->prev;
+ }
+ if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
+ /* Configure Preview Ping Pong */
+ CDBG("%s Configure ping/pong address for %d",
+ __func__, path);
+ } else {
+ pr_err("%s ping/pong addr is null!!", __func__);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+static struct buf_info *vfe2x_get_ch(int path)
+{
+ struct buf_info *ch = NULL;
+
+ CDBG("path = %d op_mode = %d\n", path, op_mode);
+ if (op_mode & SNAPSHOT_MASK_MODE) {
+ if (path == VFE_MSG_OUTPUT_T)
+ ch = &vfe2x_ctrl->thumb;
+ else if (path == VFE_MSG_OUTPUT_S)
+ ch = &vfe2x_ctrl->snap;
+ } else {
+ if (path == VFE_MSG_OUTPUT_P)
+ ch = &vfe2x_ctrl->prev;
+ }
+
+ BUG_ON(ch == NULL);
+ return ch;
+}
+
+static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int subdev_cmd, void *arg)
+{
+ struct msm_isp_cmd vfecmd;
+ struct msm_camvfe_params *vfe_params =
+ (struct msm_camvfe_params *)arg;
+ struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+ struct table_cmd *table_pending;
+ long rc = 0;
+ void *data = vfe_params->data;
+
+ struct msm_pmem_region *regptr;
+ unsigned char buf[256];
+
+ struct vfe_stats_ack sack;
+ struct axidata *axid;
+ uint32_t i;
+ uint32_t header = 0;
+ uint32_t queue = 0;
+ struct vfe_stats_we_cfg *scfg = NULL;
+ struct vfe_stats_af_cfg *sfcfg = NULL;
+
+ struct axiout *axio = NULL;
+ void *cmd_data = NULL;
+ void *cmd_data_alloc = NULL;
+ unsigned long flags;
+ struct msm_free_buf *free_buf = NULL;
+ struct vfe_outputack fack;
+
+ CDBG("msm_vfe_subdev_ioctl is called\n");
+ if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE &&
+ cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
+ cmd->cmd_type != CMD_VFE_BUFFER_RELEASE) {
+ if (copy_from_user(&vfecmd,
+ (void __user *)(cmd->value),
+ sizeof(vfecmd))) {
+ pr_err("copy_from_user in msm_vfe_subdev_ioctl fail\n");
+ return -EFAULT;
+ }
+ }
+
+ switch (cmd->cmd_type) {
+ case CMD_VFE_BUFFER_RELEASE: {
+ if (!(vfe2x_ctrl->vfe_started) || op_mode == 1)
+ return 0;
+ if (op_mode & SNAPSHOT_MASK_MODE) {
+ free_buf = vfe2x_check_free_buffer(
+ VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_T);
+ } else {
+ free_buf = vfe2x_check_free_buffer(
+ VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_P);
+ if (free_buf) {
+ fack.header = VFE_OUTPUT2_ACK;
+
+ fack.output2newybufferaddress =
+ (void *)(free_buf->ch_paddr[0]);
+
+ fack.output2newcbcrbufferaddress =
+ (void *)(free_buf->ch_paddr[1]);
+
+ cmd_data = &fack;
+ vfecmd.length = sizeof(fack) - 4;
+ queue = QDSP_CMDQUEUE;
+ }
+ }
+ }
+ break;
+ case CMD_CONFIG_PING_ADDR: {
+ int path = *((int *)cmd->value);
+ struct buf_info *outch = vfe2x_get_ch(path);
+ outch->ping = *((struct msm_free_buf *)data);
+ }
+ return 0;
+ case CMD_CONFIG_PONG_ADDR: {
+ int path = *((int *)cmd->value);
+ struct buf_info *outch = vfe2x_get_ch(path);
+ outch->pong = *((struct msm_free_buf *)data);
+ }
+ return 0;
+
+ case CMD_CONFIG_FREE_BUF_ADDR: {
+ int path = *((int *)cmd->value);
+ struct buf_info *outch = vfe2x_get_ch(path);
+ outch->free_buf = *((struct msm_free_buf *)data);
+ }
+ return 0;
+
+ case CMD_STATS_AEC_AWB_ENABLE:
+ case CMD_STATS_AXI_CFG: {
+ axid = data;
+ if (!axid) {
+ rc = -EFAULT;
+ goto config_failure;
+ }
+
+ scfg =
+ kmalloc(sizeof(struct vfe_stats_we_cfg),
+ GFP_ATOMIC);
+ if (!scfg) {
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+
+ if (copy_from_user((char *)scfg + 4,
+ (void __user *)(vfecmd.value),
+ vfecmd.length)) {
+
+ rc = -EFAULT;
+ goto config_done;
+ }
+
+ CDBG("STATS_ENABLE: bufnum = %d, enabling = %d\n",
+ axid->bufnum1, scfg->wb_expstatsenable);
+
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_failure;
+ }
+ *(uint32_t *)scfg = header;
+ if (axid->bufnum1 > 0) {
+ regptr = axid->region;
+
+ for (i = 0; i < axid->bufnum1; i++) {
+
+ CDBG("STATS_ENABLE, phy = 0x%lx\n",
+ regptr->paddr);
+
+ scfg->wb_expstatoutputbuffer[i] =
+ (void *)regptr->paddr;
+ regptr++;
+ }
+
+ cmd_data = scfg;
+
+ } else {
+ rc = -EINVAL;
+ goto config_done;
+ }
+ }
+ break;
+ case CMD_STATS_AF_ENABLE:
+ case CMD_STATS_AF_AXI_CFG: {
+ axid = data;
+ if (!axid) {
+ rc = -EFAULT;
+ goto config_failure;
+ }
+
+ sfcfg =
+ kmalloc(sizeof(struct vfe_stats_af_cfg),
+ GFP_ATOMIC);
+
+ if (!sfcfg) {
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+
+ if (copy_from_user((char *)sfcfg + 4,
+ (void __user *)(vfecmd.value),
+ vfecmd.length)) {
+
+ rc = -EFAULT;
+ goto config_done;
+ }
+
+ CDBG("AF_ENABLE: bufnum = %d, enabling = %d\n",
+ axid->bufnum1, sfcfg->af_enable);
+
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_failure;
+ }
+ *(uint32_t *)sfcfg = header;
+ if (axid->bufnum1 > 0) {
+ regptr = &axid->region[0];
+
+ for (i = 0; i < axid->bufnum1; i++) {
+
+ CDBG("STATS_ENABLE, phy = 0x%lx\n",
+ regptr->paddr);
+
+ sfcfg->af_outbuf[i] =
+ (void *)regptr->paddr;
+
+ regptr++;
+ }
+
+ cmd_data = sfcfg;
+
+ } else {
+ rc = -EINVAL;
+ goto config_done;
+ }
+ }
+ break;
+ case CMD_SNAP_BUF_RELEASE:
+ break;
+ case CMD_STATS_BUF_RELEASE: {
+ CDBG("vfe_7x_config: CMD_STATS_BUF_RELEASE\n");
+ if (!data) {
+ rc = -EFAULT;
+ goto config_failure;
+ }
+
+ sack.header = VFE_STATS_WB_EXP_ACK;
+ sack.bufaddr = (void *)*(uint32_t *)data;
+
+ queue = QDSP_CMDQUEUE;
+ vfecmd.length = sizeof(struct vfe_stats_ack) - 4;
+ cmd_data = &sack;
+ }
+ break;
+ case CMD_STATS_AF_BUF_RELEASE: {
+ CDBG("vfe_7x_config: CMD_STATS_AF_BUF_RELEASE\n");
+ if (!data) {
+ rc = -EFAULT;
+ goto config_failure;
+ }
+
+ sack.header = VFE_STATS_AUTOFOCUS_ACK;
+ sack.bufaddr = (void *)*(uint32_t *)data;
+
+ queue = QDSP_CMDQUEUE;
+ vfecmd.length = sizeof(struct vfe_stats_ack) - 4;
+ cmd_data = &sack;
+ }
+ break;
+ case CMD_GENERAL:
+ case CMD_STATS_DISABLE: {
+ CDBG("CMD_GENERAL:%d %d\n", vfecmd.id, vfecmd.length);
+ if (vfecmd.id == VFE_CMD_OPERATION_CFG) {
+ if (copy_from_user(&vfe2x_ctrl->start_cmd,
+ (void __user *)(vfecmd.value),
+ vfecmd.length))
+ rc = -EFAULT;
+ op_mode = vfe2x_ctrl->start_cmd.mode_of_operation;
+ return rc;
+ }
+ if (vfecmd.length > 256 - 4) {
+ cmd_data_alloc =
+ cmd_data = kmalloc(vfecmd.length + 4, GFP_ATOMIC);
+ if (!cmd_data) {
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+ } else
+ cmd_data = buf;
+
+ if (copy_from_user(((char *)cmd_data) + 4,
+ (void __user *)(vfecmd.value),
+ vfecmd.length)) {
+
+ rc = -EFAULT;
+ goto config_done;
+ }
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ CDBG("%s %s\n", cmds_map[vfecmd.id].isp_id_name,
+ cmds_map[vfecmd.id].vfe_id_name);
+ *(uint32_t *)cmd_data = header;
+ if (queue == QDSP_CMDQUEUE) {
+ switch (vfecmd.id) {
+ case VFE_CMD_RESET:
+ msm_adsp_enable(qcam_mod);
+ msm_adsp_enable(vfe_mod);
+ msm_camio_vfe_blk_reset();
+ vfestopped = 0;
+ break;
+ case VFE_CMD_START:
+ case VFE_CMD_CAPTURE:
+ spin_lock_irqsave(&vfe2x_ctrl->table_lock,
+ flags);
+ if (!list_empty(&vfe2x_ctrl->table_q)) {
+ vfe2x_ctrl->start_pending = 1;
+ spin_unlock_irqrestore(
+ &vfe2x_ctrl->table_lock,
+ flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&vfe2x_ctrl->table_lock,
+ flags);
+ vfecmd.length = sizeof(vfe2x_ctrl->start_cmd);
+ memcpy(((char *)cmd_data) + 4,
+ &vfe2x_ctrl->start_cmd,
+ sizeof(vfe2x_ctrl->start_cmd));
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ msm_camio_set_perf_lvl(S_CAPTURE);
+ else
+ msm_camio_set_perf_lvl(S_PREVIEW);
+ vfestopped = 0;
+ break;
+ case VFE_CMD_STOP:
+ vfestopped = 1;
+ vfe2x_ctrl->vfe_started = 0;
+ goto config_send;
+
+ default:
+ break;
+ }
+ } /* QDSP_CMDQUEUE */
+ }
+ break;
+ case CMD_AXI_CFG_PREVIEW: {
+ CDBG("CMD_AXI_CFG_PREVIEW\n");
+ raw_mode = 0;
+ axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+ if (!axio) {
+ pr_err("NULL axio\n");
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+
+ if (copy_from_user((char *)axio + 4,
+ (void __user *)(vfecmd.value),
+ sizeof(struct axiout))) {
+ pr_err("copy_from_user failed\n");
+ rc = -EFAULT;
+ goto config_done;
+ }
+ rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_PREVIEW,
+ VFE_MSG_OUTPUT_P);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+
+ free_buf = vfe2x_check_free_buffer(
+ VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_P);
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ *(uint32_t *)axio = header;
+ vfe_7x_config_axi(OUTPUT_2, &vfe2x_ctrl->prev, axio);
+ cmd_data = axio;
+ }
+ break;
+ case CMD_RAW_PICT_AXI_CFG: {
+ CDBG("CMD_RAW_PICT_AXI_CFG:%d\n", op_mode);
+ raw_mode = 1;
+ axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+
+ if (copy_from_user((char *)axio + 4,
+ (void __user *)(vfecmd.value),
+ sizeof(struct axiout))) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+ VFE_MSG_OUTPUT_S);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ *(uint32_t *)axio = header;
+ vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
+ cmd_data = axio;
+ }
+ break;
+ case CMD_AXI_CFG_SNAP: {
+ raw_mode = 0;
+ CDBG("CMD_AXI_CFG_SNAP :%d\n", op_mode);
+ axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+
+ if (copy_from_user((char *)axio + 4,
+ (void __user *)(vfecmd.value),
+ sizeof(struct axiout))) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+ VFE_MSG_OUTPUT_S);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ *(uint32_t *)axio = header;
+ vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
+ rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
+ VFE_MSG_OUTPUT_T);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ vfe_7x_config_axi(OUTPUT_1, &vfe2x_ctrl->thumb, axio);
+ cmd_data = axio;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (vfestopped)
+ goto config_done;
+
+config_send:
+ CDBG("send adsp command = %d\n", *(uint32_t *)cmd_data);
+ if (queue == QDSP_TABLEQUEUE &&
+ vfe2x_ctrl->tableack_pending) {
+ table_pending = kzalloc(sizeof(struct table_cmd), GFP_ATOMIC);
+ if (!table_pending) {
+ rc = -ENOMEM;
+ goto config_done;
+ }
+ table_pending->cmd = kzalloc(vfecmd.length + 4, GFP_ATOMIC);
+ if (!table_pending->cmd) {
+ kfree(table_pending);
+ rc = -ENOMEM;
+ goto config_done;
+ }
+ memcpy(table_pending->cmd, cmd_data, vfecmd.length + 4);
+ table_pending->queue = queue;
+ table_pending->size = vfecmd.length + 4;
+ spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+ list_add_tail(&table_pending->list, &vfe2x_ctrl->table_q);
+ spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+ } else {
+ if (queue == QDSP_TABLEQUEUE) {
+ spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
+ rc = msm_adsp_write(vfe_mod, queue,
+ cmd_data, vfecmd.length + 4);
+ vfe2x_ctrl->tableack_pending = 1;
+ spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
+ } else {
+ if (*(uint32_t *)cmd_data == VFE_OUTPUT2_ACK) {
+ uint32_t *ptr = cmd_data;
+ CDBG("%x %x %x\n", ptr[0], ptr[1], ptr[2]);
+ }
+ rc = msm_adsp_write(vfe_mod, queue,
+ cmd_data, vfecmd.length + 4);
+ CDBG("%x\n", vfecmd.length + 4);
+ }
+ }
+
+config_done:
+ kfree(cmd_data_alloc);
+
+config_failure:
+ kfree(scfg);
+ kfree(axio);
+ return rc;
+}
+
+static struct msm_cam_clk_info vfe2x_clk_info[] = {
+ {"vfe_clk", 192000000},
+};
+
+int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
+ struct platform_device *pdev)
+{
+ int rc = 0;
+ v4l2_set_subdev_hostdata(sd, data);
+ vfe_syncdata = data;
+
+ spin_lock_init(&vfe2x_ctrl->sd_notify_lock);
+ spin_lock_init(&vfe2x_ctrl->table_lock);
+ spin_lock_init(&vfe2x_ctrl->vfe_msg_lock);
+ init_waitqueue_head(&stopevent.wait);
+ INIT_LIST_HEAD(&vfe2x_ctrl->table_q);
+ INIT_LIST_HEAD(&vfe2x_ctrl->vfe_msg_q);
+ stopevent.timeout = 200;
+ stopevent.state = 0;
+ vfe2x_ctrl->vfe_started = 0;
+
+
+ CDBG("msm_cam_clk_enable: enable vfe_clk\n");
+ rc = msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
+ vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 1);
+ if (rc < 0)
+ return rc;
+
+ msm_camio_set_perf_lvl(S_INIT);
+
+ /* TODO : check is it required */
+ extlen = sizeof(struct vfe_frame_extra);
+
+ extdata = kmalloc(extlen, GFP_ATOMIC);
+ if (!extdata) {
+ rc = -ENOMEM;
+ goto init_fail;
+ }
+
+ rc = msm_adsp_get("QCAMTASK", &qcam_mod, &vfe_7x_sync, NULL);
+ if (rc) {
+ rc = -EBUSY;
+ goto get_qcam_fail;
+ }
+
+ rc = msm_adsp_get("VFETASK", &vfe_mod, &vfe_7x_sync, NULL);
+ if (rc) {
+ rc = -EBUSY;
+ goto get_vfe_fail;
+ }
+ return 0;
+
+get_vfe_fail:
+ msm_adsp_put(qcam_mod);
+get_qcam_fail:
+ kfree(extdata);
+init_fail:
+ extlen = 0;
+ return rc;
+}
+
+int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
+ struct platform_device *pdev)
+{
+ return 0;
+}
+
+void msm_vpe_subdev_release(struct platform_device *pdev)
+{
+ return;
+}
+
+void msm_vfe_subdev_release(struct platform_device *pdev)
+{
+ msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
+ vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 0);
+ vfe_syncdata = NULL;
+
+ msm_adsp_disable(qcam_mod);
+ msm_adsp_disable(vfe_mod);
+
+ msm_adsp_put(qcam_mod);
+ msm_adsp_put(vfe_mod);
+
+ kfree(extdata);
+ msm_camio_set_perf_lvl(S_EXIT);
+ return;
+}
+
+static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
+ .ioctl = msm_vfe_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
+ .core = &msm_vfe_subdev_core_ops,
+};
+
+static int __devinit vfe2x_probe(struct platform_device *pdev)
+{
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ vfe2x_ctrl = kzalloc(sizeof(struct vfe2x_ctrl_type), GFP_KERNEL);
+ if (!vfe2x_ctrl) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&vfe2x_ctrl->subdev, &msm_vfe_subdev_ops);
+ snprintf(vfe2x_ctrl->subdev.name,
+ sizeof(vfe2x_ctrl->subdev.name), "vfe2.x");
+ v4l2_set_subdevdata(&vfe2x_ctrl->subdev, vfe2x_ctrl);
+ platform_set_drvdata(pdev, &vfe2x_ctrl->subdev);
+
+ vfe2x_ctrl->pdev = pdev;
+ return 0;
+}
+
+static struct platform_driver vfe2x_driver = {
+ .probe = vfe2x_probe,
+ .driver = {
+ .name = MSM_VFE_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_vfe2x_init_module(void)
+{
+ return platform_driver_register(&vfe2x_driver);
+}
+
+static void __exit msm_vfe2x_exit_module(void)
+{
+ platform_driver_unregister(&vfe2x_driver);
+}
+
+module_init(msm_vfe2x_init_module);
+module_exit(msm_vfe2x_exit_module);
+MODULE_DESCRIPTION("VFE 2.x driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.h b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
new file mode 100644
index 0000000..0f7fb60
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
@@ -0,0 +1,385 @@
+/* Copyright (c) 2012, 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.
+ */
+
+#ifndef __MSM_VFE7X_H__
+#define __MSM_VFE7X_H__
+#include <media/msm_camera.h>
+#include <mach/camera.h>
+#include <linux/list.h>
+#include "msm.h"
+
+struct cmd_id_map {
+ uint32_t isp_id;
+ uint32_t vfe_id;
+ uint32_t queue;
+ char isp_id_name[64];
+ char vfe_id_name[64];
+} __packed;
+
+struct msg_id_map {
+ uint32_t vfe_id;
+ uint32_t isp_id;
+} __packed;
+
+struct table_cmd {
+ struct list_head list;
+ void *cmd;
+ int size;
+ int queue;
+} __packed;
+
+struct vfe_msg {
+ struct list_head list;
+ void *cmd;
+ int len;
+ int id;
+} __packed;
+
+struct buf_info {
+ /* Buffer */
+ struct msm_free_buf ping;
+ struct msm_free_buf pong;
+ struct msm_free_buf free_buf;
+} __packed;
+
+struct vfe_cmd_start {
+ uint32_t input_source:1;
+ uint32_t mode_of_operation:1;
+ uint32_t snap_number:4;
+ uint32_t /* reserved */ : 26;
+
+ /* Image Pipeline Modules */
+ uint32_t blacklevel_correction_enable:1;
+ uint32_t lens_rolloff_correction_enable:1;
+ uint32_t white_balance_enable:1;
+ uint32_t rgb_gamma_enable:1;
+ uint32_t luma_noise_reductionpath_enable:1;
+ uint32_t adaptive_spatialfilter_enable:1;
+ uint32_t chroma_subsample_enable:1;
+ uint32_t /* reserved */ : 25;
+
+ /* The dimension fed to the statistics module */
+ uint32_t last_pixel:12;
+ uint32_t /* reserved */ : 4;
+ uint32_t last_line:12;
+ uint32_t /* reserved */ : 4;
+} __packed;
+
+struct vfe2x_ctrl_type {
+ struct buf_info prev;
+ struct buf_info snap;
+ struct buf_info raw;
+ struct buf_info thumb;
+
+ spinlock_t table_lock;
+ struct list_head table_q;
+ uint32_t tableack_pending;
+ uint32_t vfeFrameId;
+
+ spinlock_t vfe_msg_lock;
+ struct list_head vfe_msg_q;
+
+ struct vfe_cmd_start start_cmd;
+ uint32_t start_pending;
+ uint32_t vfe_started;
+
+ /* v4l2 subdev */
+ struct v4l2_subdev subdev;
+ struct platform_device *pdev;
+ struct clk *vfe_clk[3];
+ spinlock_t sd_notify_lock;
+} __packed;
+
+struct vfe_frame_extra {
+ uint32_t bl_evencol:23;
+ uint32_t rvd1:9;
+ uint32_t bl_oddcol:23;
+ uint32_t rvd2:9;
+
+ uint32_t d_dbpc_stats_hot:16;
+ uint32_t d_dbpc_stats_cold:16;
+
+ uint32_t d_dbpc_stats_0_hot:10;
+ uint32_t rvd3:6;
+ uint32_t d_dbpc_stats_0_cold:10;
+ uint32_t rvd4:6;
+ uint32_t d_dbpc_stats_1_hot:10;
+ uint32_t rvd5:6;
+ uint32_t d_dbpc_stats_1_cold:10;
+ uint32_t rvd6:6;
+
+ uint32_t asf_max_edge;
+
+ uint32_t e_y_wm_pm_stats_0:21;
+ uint32_t rvd7:11;
+ uint32_t e_y_wm_pm_stats_1_bl:8;
+ uint32_t rvd8:8;
+ uint32_t e_y_wm_pm_stats_1_nl:12;
+ uint32_t rvd9:4;
+
+ uint32_t e_cbcr_wm_pm_stats_0:21;
+ uint32_t rvd10:11;
+ uint32_t e_cbcr_wm_pm_stats_1_bl:8;
+ uint32_t rvd11:8;
+ uint32_t e_cbcr_wm_pm_stats_1_nl:12;
+ uint32_t rvd12:4;
+
+ uint32_t v_y_wm_pm_stats_0:21;
+ uint32_t rvd13:11;
+ uint32_t v_y_wm_pm_stats_1_bl:8;
+ uint32_t rvd14:8;
+ uint32_t v_y_wm_pm_stats_1_nl:12;
+ uint32_t rvd15:4;
+
+ uint32_t v_cbcr_wm_pm_stats_0:21;
+ uint32_t rvd16:11;
+ uint32_t v_cbcr_wm_pm_stats_1_bl:8;
+ uint32_t rvd17:8;
+ uint32_t v_cbcr_wm_pm_stats_1_nl:12;
+ uint32_t rvd18:4;
+
+ uint32_t frame_id;
+} __packed;
+
+struct vfe_endframe {
+ uint32_t y_address;
+ uint32_t cbcr_address;
+
+ struct vfe_frame_extra extra;
+} __packed;
+
+struct vfe_outputack {
+ uint32_t header;
+ void *output2newybufferaddress;
+ void *output2newcbcrbufferaddress;
+} __packed;
+
+struct vfe_stats_ack {
+ uint32_t header;
+ /* MUST BE 64 bit ALIGNED */
+ void *bufaddr;
+} __packed;
+
+/* AXI Output Config Command sent to DSP */
+struct axiout {
+ uint32_t cmdheader:32;
+ int outputmode:3;
+ uint8_t format:2;
+ uint32_t /* reserved */ : 27;
+
+ /* AXI Output 1 Y Configuration, Part 1 */
+ uint32_t out1yimageheight:12;
+ uint32_t /* reserved */ : 4;
+ uint32_t out1yimagewidthin64bitwords:10;
+ uint32_t /* reserved */ : 6;
+
+ /* AXI Output 1 Y Configuration, Part 2 */
+ uint8_t out1yburstlen:2;
+ uint32_t out1ynumrows:12;
+ uint32_t out1yrowincin64bitincs:12;
+ uint32_t /* reserved */ : 6;
+
+ /* AXI Output 1 CbCr Configuration, Part 1 */
+ uint32_t out1cbcrimageheight:12;
+ uint32_t /* reserved */ : 4;
+ uint32_t out1cbcrimagewidthin64bitwords:10;
+ uint32_t /* reserved */ : 6;
+
+ /* AXI Output 1 CbCr Configuration, Part 2 */
+ uint8_t out1cbcrburstlen:2;
+ uint32_t out1cbcrnumrows:12;
+ uint32_t out1cbcrrowincin64bitincs:12;
+ uint32_t /* reserved */ : 6;
+
+ /* AXI Output 2 Y Configuration, Part 1 */
+ uint32_t out2yimageheight:12;
+ uint32_t /* reserved */ : 4;
+ uint32_t out2yimagewidthin64bitwords:10;
+ uint32_t /* reserved */ : 6;
+
+ /* AXI Output 2 Y Configuration, Part 2 */
+ uint8_t out2yburstlen:2;
+ uint32_t out2ynumrows:12;
+ uint32_t out2yrowincin64bitincs:12;
+ uint32_t /* reserved */ : 6;
+
+ /* AXI Output 2 CbCr Configuration, Part 1 */
+ uint32_t out2cbcrimageheight:12;
+ uint32_t /* reserved */ : 4;
+ uint32_t out2cbcrimagewidtein64bitwords:10;
+ uint32_t /* reserved */ : 6;
+
+ /* AXI Output 2 CbCr Configuration, Part 2 */
+ uint8_t out2cbcrburstlen:2;
+ uint32_t out2cbcrnumrows:12;
+ uint32_t out2cbcrrowincin64bitincs:12;
+ uint32_t /* reserved */ : 6;
+
+ /* Address configuration:
+ * output1 phisycal address */
+ unsigned long output1buffer1_y_phy;
+ unsigned long output1buffer1_cbcr_phy;
+ unsigned long output1buffer2_y_phy;
+ unsigned long output1buffer2_cbcr_phy;
+ unsigned long output1buffer3_y_phy;
+ unsigned long output1buffer3_cbcr_phy;
+ unsigned long output1buffer4_y_phy;
+ unsigned long output1buffer4_cbcr_phy;
+ unsigned long output1buffer5_y_phy;
+ unsigned long output1buffer5_cbcr_phy;
+ unsigned long output1buffer6_y_phy;
+ unsigned long output1buffer6_cbcr_phy;
+ unsigned long output1buffer7_y_phy;
+ unsigned long output1buffer7_cbcr_phy;
+ unsigned long output1buffer8_y_phy;
+ unsigned long output1buffer8_cbcr_phy;
+
+ /* output2 phisycal address */
+ unsigned long output2buffer1_y_phy;
+ unsigned long output2buffer1_cbcr_phy;
+ unsigned long output2buffer2_y_phy;
+ unsigned long output2buffer2_cbcr_phy;
+ unsigned long output2buffer3_y_phy;
+ unsigned long output2buffer3_cbcr_phy;
+ unsigned long output2buffer4_y_phy;
+ unsigned long output2buffer4_cbcr_phy;
+ unsigned long output2buffer5_y_phy;
+ unsigned long output2buffer5_cbcr_phy;
+ unsigned long output2buffer6_y_phy;
+ unsigned long output2buffer6_cbcr_phy;
+ unsigned long output2buffer7_y_phy;
+ unsigned long output2buffer7_cbcr_phy;
+ unsigned long output2buffer8_y_phy;
+ unsigned long output2buffer8_cbcr_phy;
+} __packed;
+
+struct vfe_stats_we_cfg {
+ uint32_t header;
+
+ /* White Balance/Exposure Statistic Selection */
+ uint8_t wb_expstatsenable:1;
+ uint8_t wb_expstatbuspriorityselection:1;
+ unsigned int wb_expstatbuspriorityvalue:4;
+ unsigned int /* reserved */ : 26;
+
+ /* White Balance/Exposure Statistic Configuration, Part 1 */
+ uint8_t exposurestatregions:1;
+ uint8_t exposurestatsubregions:1;
+ unsigned int /* reserved */ : 14;
+
+ unsigned int whitebalanceminimumy:8;
+ unsigned int whitebalancemaximumy:8;
+
+ /* White Balance/Exposure Statistic Configuration, Part 2 */
+ uint8_t wb_expstatslopeofneutralregionline[
+ NUM_WB_EXP_NEUTRAL_REGION_LINES];
+
+ /* White Balance/Exposure Statistic Configuration, Part 3 */
+ unsigned int wb_expstatcrinterceptofneutralregionline2:12;
+ unsigned int /* reserved */ : 4;
+ unsigned int wb_expstatcbinterceptofneutralreginnline1:12;
+ unsigned int /* reserved */ : 4;
+
+ /* White Balance/Exposure Statistic Configuration, Part 4 */
+ unsigned int wb_expstatcrinterceptofneutralregionline4:12;
+ unsigned int /* reserved */ : 4;
+ unsigned int wb_expstatcbinterceptofneutralregionline3:12;
+ unsigned int /* reserved */ : 4;
+
+ /* White Balance/Exposure Statistic Output Buffer Header */
+ unsigned int wb_expmetricheaderpattern:8;
+ unsigned int /* reserved */ : 24;
+
+ /* White Balance/Exposure Statistic Output Buffers-MUST
+ * BE 64 bit ALIGNED */
+ void *wb_expstatoutputbuffer[NUM_WB_EXP_STAT_OUTPUT_BUFFERS];
+} __packed;
+
+struct vfe_stats_af_cfg {
+ uint32_t header;
+
+ /* Autofocus Statistic Selection */
+ uint8_t af_enable:1;
+ uint8_t af_busprioritysel:1;
+ unsigned int af_buspriorityval:4;
+ unsigned int /* reserved */ : 26;
+
+ /* Autofocus Statistic Configuration, Part 1 */
+ unsigned int af_singlewinvoffset:12;
+ unsigned int /* reserved */ : 4;
+ unsigned int af_singlewinhoffset:12;
+ unsigned int /* reserved */ : 3;
+ uint8_t af_winmode:1;
+
+ /* Autofocus Statistic Configuration, Part 2 */
+ unsigned int af_singglewinvh:11;
+ unsigned int /* reserved */ : 5;
+ unsigned int af_singlewinhw:11;
+ unsigned int /* reserved */ : 5;
+
+ /* Autofocus Statistic Configuration, Parts 3-6 */
+ uint8_t af_multiwingrid[NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS];
+
+ /* Autofocus Statistic Configuration, Part 7 */
+ signed int af_metrichpfcoefa00:5;
+ signed int af_metrichpfcoefa04:5;
+ unsigned int af_metricmaxval:11;
+ uint8_t af_metricsel:1;
+ unsigned int /* reserved */ : 10;
+
+ /* Autofocus Statistic Configuration, Part 8 */
+ signed int af_metrichpfcoefa20:5;
+ signed int af_metrichpfcoefa21:5;
+ signed int af_metrichpfcoefa22:5;
+ signed int af_metrichpfcoefa23:5;
+ signed int af_metrichpfcoefa24:5;
+ unsigned int /* reserved */ : 7;
+
+ /* Autofocus Statistic Output Buffer Header */
+ unsigned int af_metrichp:8;
+ unsigned int /* reserved */ : 24;
+
+ /* Autofocus Statistic Output Buffers - MUST BE 64 bit ALIGNED!!! */
+ void *af_outbuf[NUM_AF_STAT_OUTPUT_BUFFERS];
+} __packed; /* VFE_StatsAutofocusConfigCmdType */
+
+struct msm_camera_frame_msg {
+ unsigned long output_y_address;
+ unsigned long output_cbcr_address;
+
+ unsigned int blacklevelevenColumn:23;
+ uint16_t reserved1:9;
+ unsigned int blackleveloddColumn:23;
+ uint16_t reserved2:9;
+
+ uint16_t greendefectpixelcount:8;
+ uint16_t reserved3:8;
+ uint16_t redbluedefectpixelcount:8;
+ uint16_t reserved4:8;
+} __packed;
+
+/* New one for 7k */
+struct msm_vfe_command_7k {
+ uint16_t queue;
+ uint16_t length;
+ void *value;
+};
+
+struct stop_event {
+ wait_queue_head_t wait;
+ int state;
+ int timeout;
+};
+
+static struct msm_free_buf *vfe2x_check_free_buffer(int id, int path);
+
+#endif /* __MSM_VFE7X_H__ */
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 7b22592..a9b7bc6 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -6,3 +6,6 @@
obj-$(CONFIG_IMX074) += imx074_v4l2.o
obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
obj-$(CONFIG_OV2720) += ov2720.o
+obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
+obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
+obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d31de14..227e606 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -172,6 +172,42 @@
return 0;
}
+int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int res)
+{
+ int32_t rc = 0;
+ static int csi_config;
+
+ s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
+ msleep(30);
+ if (update_type == MSM_SENSOR_REG_INIT) {
+ CDBG("Register INIT\n");
+ s_ctrl->curr_csi_params = NULL;
+ msm_sensor_enable_debugfs(s_ctrl);
+ msm_sensor_write_init_settings(s_ctrl);
+ csi_config = 0;
+ } else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
+ CDBG("PERIODIC : %d\n", res);
+ msm_sensor_write_conf_array(
+ s_ctrl->sensor_i2c_client,
+ s_ctrl->msm_sensor_reg->mode_settings, res);
+ msleep(30);
+ if (!csi_config) {
+ s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
+ CDBG("CSI config in progress\n");
+ v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_CSIC_CFG,
+ s_ctrl->curr_csic_params);
+ CDBG("CSI config is done\n");
+ mb();
+ msleep(30);
+ csi_config = 1;
+ }
+ s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
+ msleep(50);
+ }
+ return rc;
+}
int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
int update_type, int res)
{
@@ -532,6 +568,8 @@
probe_fail:
CDBG("%s_i2c_probe failed\n", client->name);
power_down:
+ if (rc > 0)
+ rc = 0;
s_ctrl->func_tbl->sensor_power_down(s_ctrl);
return rc;
}
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index e06f628..ba366e6 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -158,6 +158,8 @@
struct mutex *msm_sensor_mutex;
struct msm_camera_csi2_params *curr_csi_params;
struct msm_camera_csi2_params **csi_params;
+ struct msm_camera_csi_params **csic_params;
+ struct msm_camera_csi_params *curr_csic_params;
struct v4l2_subdev sensor_v4l2_subdev;
struct v4l2_subdev_info *sensor_v4l2_subdev_info;
@@ -218,6 +220,9 @@
int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
int update_type, int res);
+int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int res);
+
int msm_sensor_enable_debugfs(struct msm_sensor_ctrl_t *s_ctrl);
long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
new file mode 100644
index 0000000..924cbc9
--- /dev/null
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -0,0 +1,507 @@
+/* Copyright (c) 2012, 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_sensor.h"
+#define SENSOR_NAME "mt9e013"
+#define PLATFORM_DRIVER_NAME "msm_camera_mt9e013"
+#define mt9e013_obj mt9e013_##obj
+
+DEFINE_MUTEX(mt9e013_mut);
+static struct msm_sensor_ctrl_t mt9e013_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf mt9e013_groupon_settings[] = {
+ {0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_groupoff_settings[] = {
+ {0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_prev_settings[] = {
+ {0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
+ {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+ {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+ {0x0306, 0x003A},/*PLL_MULTIPLIER*/
+ {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+ {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+ /*Output Size (1632x1224)*/
+ {0x0344, 0x0008},/*X_ADDR_START*/
+ {0x0348, 0x0CC9},/*X_ADDR_END*/
+ {0x0346, 0x0008},/*Y_ADDR_START*/
+ {0x034A, 0x0999},/*Y_ADDR_END*/
+ {0x034C, 0x0660},/*X_OUTPUT_SIZE*/
+ {0x034E, 0x04C8},/*Y_OUTPUT_SIZE*/
+ {0x306E, 0xFCB0},/*DATAPATH_SELECT*/
+ {0x3040, 0x04C3},/*READ_MODE*/
+ {0x3178, 0x0000},/*ANALOG_CONTROL5*/
+ {0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+ {0x0400, 0x0002},/*SCALING_MODE*/
+ {0x0404, 0x0010},/*SCALE_M*/
+ /*Timing configuration*/
+ {0x0342, 0x1018},/*LINE_LENGTH_PCK*/
+ {0x0340, 0x055B},/*FRAME_LENGTH_LINES*/
+ {0x0202, 0x0557},/*COARSE_INTEGRATION_TIME*/
+ {0x3014, 0x0846},/*FINE_INTEGRATION_TIME_*/
+ {0x3010, 0x0130},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_snap_settings[] = {
+ {0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
+ {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+ {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+ {0x0306, 0x003A},/*PLL_MULTIPLIER*/
+ {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+ {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+ /*Output Size (3264x2448)*/
+ {0x0344, 0x0000},/*X_ADDR_START */
+ {0x0348, 0x0CCF},/*X_ADDR_END*/
+ {0x0346, 0x0000},/*Y_ADDR_START */
+ {0x034A, 0x099F},/*Y_ADDR_END*/
+ {0x034C, 0x0CD0},/*X_OUTPUT_SIZE*/
+ {0x034E, 0x09A0},/*Y_OUTPUT_SIZE*/
+ {0x306E, 0xFC80},/*DATAPATH_SELECT*/
+ {0x3040, 0x0041},/*READ_MODE*/
+ {0x3178, 0x0000},/*ANALOG_CONTROL5*/
+ {0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+ {0x0400, 0x0000},/*SCALING_MODE*/
+ {0x0404, 0x0010},/*SCALE_M*/
+ /*Timing configuration*/
+ {0x0342, 0x13F8},/*LINE_LENGTH_PCK*/
+ {0x0340, 0x0A2F},/*FRAME_LENGTH_LINES*/
+ {0x0202, 0x0A1F},/*COARSE_INTEGRATION_TIME*/
+ {0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_ */
+ {0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr60_settings[] = {
+ {0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+ {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+ {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+ {0x0306, 0x0029},/*PLL_MULTIPLIER*/
+ {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+ {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+ {0x0344, 0x0008},/*X_ADDR_START*/
+ {0x0348, 0x0685},/*X_ADDR_END*/
+ {0x0346, 0x013a},/*Y_ADDR_START*/
+ {0x034A, 0x055B},/*Y_ADDR_END*/
+ {0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+ {0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+ {0x306E, 0xFC80},/*DATAPATH_SELECT*/
+ {0x3040, 0x00C3},/*READ_MODE*/
+ {0x3178, 0x0000},/*ANALOG_CONTROL5*/
+ {0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+ {0x0400, 0x0000},/*SCALING_MODE*/
+ {0x0404, 0x0010},/*SCALE_M*/
+ /*Timing configuration*/
+ {0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+ {0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+ {0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+ {0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+ {0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr90_settings[] = {
+ {0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+ {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+ {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+ {0x0306, 0x003D},/*PLL_MULTIPLIER*/
+ {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+ {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+ {0x0344, 0x0008},/*X_ADDR_START*/
+ {0x0348, 0x0685},/*X_ADDR_END*/
+ {0x0346, 0x013a},/*Y_ADDR_START*/
+ {0x034A, 0x055B},/*Y_ADDR_END*/
+ {0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+ {0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+ {0x306E, 0xFC80},/*DATAPATH_SELECT*/
+ {0x3040, 0x00C3},/*READ_MODE*/
+ {0x3178, 0x0000},/*ANALOG_CONTROL5*/
+ {0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+ {0x0400, 0x0000},/*SCALING_MODE*/
+ {0x0404, 0x0010},/*SCALE_M*/
+ /*Timing configuration*/
+ {0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+ {0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+ {0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+ {0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+ {0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_hfr120_settings[] = {
+ {0x0300, 0x0005},/*VT_PIX_CLK_DIV*/
+ {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+ {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+ {0x0306, 0x0052},/*PLL_MULTIPLIER*/
+ {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+ {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
+ {0x0344, 0x0008},/*X_ADDR_START*/
+ {0x0348, 0x0685},/*X_ADDR_END*/
+ {0x0346, 0x013a},/*Y_ADDR_START*/
+ {0x034A, 0x055B},/*Y_ADDR_END*/
+ {0x034C, 0x0340},/*X_OUTPUT_SIZE*/
+ {0x034E, 0x0212},/*Y_OUTPUT_SIZE*/
+ {0x306E, 0xFC80},/*DATAPATH_SELECT*/
+ {0x3040, 0x00C3},/*READ_MODE*/
+ {0x3178, 0x0000},/*ANALOG_CONTROL5*/
+ {0x3ED0, 0x1E24},/*DAC_LD_4_5*/
+ {0x0400, 0x0000},/*SCALING_MODE*/
+ {0x0404, 0x0010},/*SCALE_M*/
+ /*Timing configuration*/
+ {0x0342, 0x0970},/*LINE_LENGTH_PCK*/
+ {0x0340, 0x02A1},/*FRAME_LENGTH_LINES*/
+ {0x0202, 0x02A1},/*COARSE_INTEGRATION_TIME*/
+ {0x3014, 0x03F6},/*FINE_INTEGRATION_TIME_*/
+ {0x3010, 0x0078},/*FINE_CORRECTION*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9e013_recommend_settings[] = {
+ /*Disable embedded data*/
+ {0x3064, 0x7800},/*SMIA_TEST*/
+ /*configure 2-lane MIPI*/
+ {0x31AE, 0x0202},/*SERIAL_FORMAT*/
+ {0x31B8, 0x0E3F},/*MIPI_TIMING_2*/
+ /*set data to RAW10 format*/
+ {0x0112, 0x0A0A},/*CCP_DATA_FORMAT*/
+ {0x30F0, 0x8000},/*VCM CONTROL*/
+
+ {0x3044, 0x0590},
+ {0x306E, 0xFC80},
+ {0x30B2, 0xC000},
+ {0x30D6, 0x0800},
+ {0x316C, 0xB42F},
+ {0x316E, 0x869C},
+ {0x3170, 0x210E},
+ {0x317A, 0x010E},
+ {0x31E0, 0x1FB9},
+ {0x31E6, 0x07FC},
+ {0x37C0, 0x0000},
+ {0x37C2, 0x0000},
+ {0x37C4, 0x0000},
+ {0x37C6, 0x0000},
+ {0x3E02, 0x8801},
+ {0x3E04, 0x2301},
+ {0x3E06, 0x8449},
+ {0x3E08, 0x6841},
+ {0x3E0A, 0x400C},
+ {0x3E0C, 0x1001},
+ {0x3E0E, 0x2103},
+ {0x3E10, 0x4B41},
+ {0x3E12, 0x4B26},
+ {0x3E16, 0x8802},
+ {0x3E18, 0x84FF},
+ {0x3E1A, 0x8601},
+ {0x3E1C, 0x8401},
+ {0x3E1E, 0x840A},
+ {0x3E20, 0xFF00},
+ {0x3E22, 0x8401},
+ {0x3E24, 0x00FF},
+ {0x3E26, 0x0088},
+ {0x3E28, 0x2E8A},
+ {0x3E32, 0x8801},
+ {0x3E34, 0x4024},
+ {0x3E38, 0x8469},
+ {0x3E3C, 0x2301},
+ {0x3E3E, 0x3E25},
+ {0x3E40, 0x1C01},
+ {0x3E42, 0x8486},
+ {0x3E44, 0x8401},
+ {0x3E46, 0x00FF},
+ {0x3E48, 0x8401},
+ {0x3E4A, 0x8601},
+ {0x3E4C, 0x8402},
+ {0x3E4E, 0x00FF},
+ {0x3E50, 0x6623},
+ {0x3E52, 0x8340},
+ {0x3E54, 0x00FF},
+ {0x3E56, 0x4A42},
+ {0x3E58, 0x2203},
+ {0x3E5A, 0x674D},
+ {0x3E5C, 0x3F25},
+ {0x3E5E, 0x846A},
+ {0x3E60, 0x4C01},
+ {0x3E62, 0x8401},
+ {0x3E66, 0x3901},
+ {0x3ECC, 0x00EB},
+ {0x3ED0, 0x1E24},
+ {0x3ED4, 0xAFC4},
+ {0x3ED6, 0x909B},
+ {0x3ED8, 0x0006},
+ {0x3EDA, 0xCFC6},
+ {0x3EDC, 0x4FE4},
+ {0x3EE0, 0x2424},
+ {0x3EE2, 0x9797},
+ {0x3EE4, 0xC100},
+ {0x3EE6, 0x0540}
+};
+
+static struct v4l2_subdev_info mt9e013_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array mt9e013_init_conf[] = {
+ {&mt9e013_recommend_settings[0],
+ ARRAY_SIZE(mt9e013_recommend_settings), 0, MSM_CAMERA_I2C_WORD_DATA}
+};
+
+static struct msm_camera_i2c_conf_array mt9e013_confs[] = {
+ {&mt9e013_snap_settings[0],
+ ARRAY_SIZE(mt9e013_snap_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+ {&mt9e013_prev_settings[0],
+ ARRAY_SIZE(mt9e013_prev_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+ {&mt9e013_hfr60_settings[0],
+ ARRAY_SIZE(mt9e013_hfr60_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+ {&mt9e013_hfr90_settings[0],
+ ARRAY_SIZE(mt9e013_hfr90_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+ {&mt9e013_hfr120_settings[0],
+ ARRAY_SIZE(mt9e013_hfr120_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
+};
+
+static struct msm_sensor_output_info_t mt9e013_dimensions[] = {
+ {
+ .x_output = 0xCD0,
+ .y_output = 0x9A0,
+ .line_length_pclk = 0x13F8,
+ .frame_length_lines = 0xA2F,
+ .vt_pixel_clk = 174000000,
+ .op_pixel_clk = 174000000,
+ .binning_factor = 1,
+ },
+ {
+ .x_output = 0x660,
+ .y_output = 0x4C8,
+ .line_length_pclk = 0x1018,
+ .frame_length_lines = 0x55B,
+ .vt_pixel_clk = 174000000,
+ .op_pixel_clk = 174000000,
+ .binning_factor = 1,
+ },
+ {
+ .x_output = 0x340,
+ .y_output = 0x212,
+ .line_length_pclk = 0x970,
+ .frame_length_lines = 0x2A1,
+ .vt_pixel_clk = 98400000,
+ .op_pixel_clk = 98400000,
+ .binning_factor = 1,
+ },
+ {
+ .x_output = 0x340,
+ .y_output = 0x212,
+ .line_length_pclk = 0x970,
+ .frame_length_lines = 0x2A1,
+ .vt_pixel_clk = 146400000,
+ .op_pixel_clk = 146400000,
+ .binning_factor = 1,
+ },
+ {
+ .x_output = 0x340,
+ .y_output = 0x212,
+ .line_length_pclk = 0x970,
+ .frame_length_lines = 0x2A1,
+ .vt_pixel_clk = 196800000,
+ .op_pixel_clk = 196800000,
+ .binning_factor = 1,
+ },
+};
+
+static struct msm_camera_csi_params mt9e013_csi_params = {
+ .data_format = CSI_10BIT,
+ .lane_cnt = 2,
+ .lane_assign = 0xe4,
+ .dpcm_scheme = 0,
+ .settle_cnt = 0x18,
+};
+
+static struct msm_camera_csi_params *mt9e013_csi_params_array[] = {
+ &mt9e013_csi_params,
+ &mt9e013_csi_params,
+ &mt9e013_csi_params,
+ &mt9e013_csi_params,
+ &mt9e013_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t mt9e013_reg_addr = {
+ .x_output = 0x34C,
+ .y_output = 0x34E,
+ .line_length_pclk = 0x342,
+ .frame_length_lines = 0x340,
+};
+
+static struct msm_sensor_id_info_t mt9e013_id_info = {
+ .sensor_id_reg_addr = 0x0,
+ .sensor_id = 0x4B00,
+};
+
+static struct msm_sensor_exp_gain_info_t mt9e013_exp_gain_info = {
+ .coarse_int_time_addr = 0x202,
+ .global_gain_addr = 0x305E,
+ .vert_offset = 0,
+};
+
+static int32_t mt9e013_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line)
+{
+ uint32_t fl_lines;
+ fl_lines =
+ (s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider) / Q10;
+
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr, gain | 0x1000,
+ MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr, line,
+ MSM_CAMERA_I2C_WORD_DATA);
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+ return 0;
+}
+
+static int32_t mt9e013_write_exp_snapshot_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line)
+{
+ uint32_t fl_lines;
+ fl_lines =
+ (s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider) / Q10;
+
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr, gain | 0x1000,
+ MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr, line,
+ MSM_CAMERA_I2C_WORD_DATA);
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x301A, (0x065C|0x2), MSM_CAMERA_I2C_WORD_DATA);
+
+ return 0;
+}
+static void mt9e013_start_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x301A, 0x8250, MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x301A, 0x8650, MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x301A, 0x8658, MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x0104, 0x00, MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x301A, 0x065C, MSM_CAMERA_I2C_WORD_DATA);
+}
+
+static void mt9e013_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x301A, 0x0058, MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x301A, 0x0050, MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ 0x0104, 0x01, MSM_CAMERA_I2C_BYTE_DATA);
+}
+
+static const struct i2c_device_id mt9e013_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&mt9e013_s_ctrl},
+ { }
+};
+
+static struct i2c_driver mt9e013_i2c_driver = {
+ .id_table = mt9e013_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client mt9e013_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ return i2c_add_driver(&mt9e013_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops mt9e013_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops mt9e013_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops mt9e013_subdev_ops = {
+ .core = &mt9e013_subdev_core_ops,
+ .video = &mt9e013_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t mt9e013_func_tbl = {
+ .sensor_start_stream = mt9e013_start_stream,
+ .sensor_stop_stream = mt9e013_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = msm_sensor_set_fps,
+ .sensor_write_exp_gain = mt9e013_write_exp_gain,
+ .sensor_write_snapshot_exp_gain = mt9e013_write_exp_snapshot_gain,
+ .sensor_setting = msm_sensor_setting1,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = msm_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t mt9e013_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .group_hold_on_conf = mt9e013_groupon_settings,
+ .group_hold_on_conf_size = ARRAY_SIZE(mt9e013_groupon_settings),
+ .group_hold_off_conf = mt9e013_groupoff_settings,
+ .group_hold_off_conf_size =
+ ARRAY_SIZE(mt9e013_groupoff_settings),
+ .init_settings = &mt9e013_init_conf[0],
+ .init_size = ARRAY_SIZE(mt9e013_init_conf),
+ .mode_settings = &mt9e013_confs[0],
+ .output_settings = &mt9e013_dimensions[0],
+ .num_conf = ARRAY_SIZE(mt9e013_confs),
+};
+
+static struct msm_sensor_ctrl_t mt9e013_s_ctrl = {
+ .msm_sensor_reg = &mt9e013_regs,
+ .sensor_i2c_client = &mt9e013_sensor_i2c_client,
+ .sensor_i2c_addr = 0x6C,
+ .sensor_output_reg_addr = &mt9e013_reg_addr,
+ .sensor_id_info = &mt9e013_id_info,
+ .sensor_exp_gain_info = &mt9e013_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csic_params = &mt9e013_csi_params_array[0],
+ .msm_sensor_mutex = &mt9e013_mut,
+ .sensor_i2c_driver = &mt9e013_i2c_driver,
+ .sensor_v4l2_subdev_info = mt9e013_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(mt9e013_subdev_info),
+ .sensor_v4l2_subdev_ops = &mt9e013_subdev_ops,
+ .func_tbl = &mt9e013_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Aptina 8MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
new file mode 100644
index 0000000..e345717
--- /dev/null
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -0,0 +1,280 @@
+/* Copyright (c) 2012, 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_sensor.h"
+#define SENSOR_NAME "ov9726"
+#define PLATFORM_DRIVER_NAME "msm_camera_ov9726"
+#define ov9726_obj ov9726_##obj
+
+DEFINE_MUTEX(ov9726_mut);
+static struct msm_sensor_ctrl_t ov9726_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf ov9726_start_settings[] = {
+ {0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_stop_settings[] = {
+ {0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_groupon_settings[] = {
+ {0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_groupoff_settings[] = {
+ {0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_prev_settings[] = {
+};
+
+static struct msm_camera_i2c_reg_conf ov9726_recommend_settings[] = {
+ {0x0103, 0x01}, /* SOFTWARE_RESET */
+ {0x3026, 0x00}, /* OUTPUT_SELECT01 */
+ {0x3027, 0x00}, /* OUTPUT_SELECT02 */
+ {0x3002, 0xe8}, /* IO_CTRL00 */
+ {0x3004, 0x03}, /* IO_CTRL01 */
+ {0x3005, 0xff}, /* IO_CTRL02 */
+ {0x3703, 0x42},
+ {0x3704, 0x10},
+ {0x3705, 0x45},
+ {0x3603, 0xaa},
+ {0x3632, 0x2f},
+ {0x3620, 0x66},
+ {0x3621, 0xc0},
+ {0x0340, 0x03}, /* FRAME_LENGTH_LINES_HI */
+ {0x0341, 0xC1}, /* FRAME_LENGTH_LINES_LO */
+ {0x0342, 0x06}, /* LINE_LENGTH_PCK_HI */
+ {0x0343, 0x80}, /* LINE_LENGTH_PCK_LO */
+ {0x0202, 0x03}, /* COARSE_INTEGRATION_TIME_HI */
+ {0x0203, 0x43}, /* COARSE_INTEGRATION_TIME_LO */
+ {0x3833, 0x04},
+ {0x3835, 0x02},
+ {0x4702, 0x04},
+ {0x4704, 0x00}, /* DVP_CTRL01 */
+ {0x4706, 0x08},
+ {0x5052, 0x01},
+ {0x3819, 0x6e},
+ {0x3817, 0x94},
+ {0x3a18, 0x00}, /* AEC_GAIN_CEILING_HI */
+ {0x3a19, 0x7f}, /* AEC_GAIN_CEILING_LO */
+ {0x404e, 0x7e},
+ {0x3631, 0x52},
+ {0x3633, 0x50},
+ {0x3630, 0xd2},
+ {0x3604, 0x08},
+ {0x3601, 0x40},
+ {0x3602, 0x14},
+ {0x3610, 0xa0},
+ {0x3612, 0x20},
+ {0x034c, 0x05}, /* X_OUTPUT_SIZE_HI */
+ {0x034d, 0x10}, /* X_OUTPUT_SIZE_LO */
+ {0x034e, 0x03}, /* Y_OUTPUT_SIZE_HI */
+ {0x034f, 0x28}, /* Y_OUTPUT_SIZE_LO */
+ {0x0340, 0x03}, /* FRAME_LENGTH_LINES_HI */
+ {0x0341, 0xC1}, /* FRAME_LENGTH_LINES_LO */
+ {0x0342, 0x06}, /* LINE_LENGTH_PCK_HI */
+ {0x0343, 0x80}, /* LINE_LENGTH_PCK_LO */
+ {0x0202, 0x03}, /* COARSE_INTEGRATION_TIME_HI */
+ {0x0203, 0x43}, /* COARSE_INTEGRATION_TIME_LO */
+ {0x0303, 0x01}, /* VT_SYS_CLK_DIV_LO */
+ {0x3002, 0x00}, /* IO_CTRL00 */
+ {0x3004, 0x00}, /* IO_CTRL01 */
+ {0x3005, 0x00}, /* IO_CTRL02 */
+ {0x4801, 0x0f}, /* MIPI_CTRL01 */
+ {0x4803, 0x05}, /* MIPI_CTRL03 */
+ {0x4601, 0x16}, /* VFIFO_READ_CONTROL */
+ {0x3014, 0x05}, /* SC_CMMN_MIPI / SC_CTRL00 */
+ {0x3104, 0x80},
+ {0x0305, 0x04}, /* PRE_PLL_CLK_DIV_LO */
+ {0x0307, 0x64}, /* PLL_MULTIPLIER_LO */
+ {0x300c, 0x02},
+ {0x300d, 0x20},
+ {0x300e, 0x01},
+ {0x3010, 0x01},
+ {0x460e, 0x81}, /* VFIFO_CONTROL00 */
+ {0x0101, 0x01}, /* IMAGE_ORIENTATION */
+ {0x3707, 0x14},
+ {0x3622, 0x9f},
+ {0x5047, 0x3D}, /* ISP_CTRL47 */
+ {0x4002, 0x45}, /* BLC_CTRL02 */
+ {0x5000, 0x06}, /* ISP_CTRL0 */
+ {0x5001, 0x00}, /* ISP_CTRL1 */
+ {0x3406, 0x00}, /* AWB_MANUAL_CTRL */
+ {0x3503, 0x13}, /* AEC_ENABLE */
+ {0x4005, 0x18}, /* BLC_CTRL05 */
+ {0x4837, 0x21},
+ {0x0100, 0x01}, /* MODE_SELECT */
+ {0x3a0f, 0x64}, /* AEC_CTRL0F */
+ {0x3a10, 0x54}, /* AEC_CTRL10 */
+ {0x3a11, 0xc2}, /* AEC_CTRL11 */
+ {0x3a1b, 0x64}, /* AEC_CTRL1B */
+ {0x3a1e, 0x54}, /* AEC_CTRL1E */
+ {0x3a1a, 0x05}, /* AEC_DIFF_MAX */
+};
+
+static struct v4l2_subdev_info ov9726_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array ov9726_init_conf[] = {
+ {&ov9726_recommend_settings[0],
+ ARRAY_SIZE(ov9726_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array ov9726_confs[] = {
+ {&ov9726_prev_settings[0],
+ ARRAY_SIZE(ov9726_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t ov9726_dimensions[] = {
+ {
+ .x_output = 0x510, /* 1296 */
+ .y_output = 0x328, /* 808 */
+ .line_length_pclk = 0x680, /* 1664 */
+ .frame_length_lines = 0x3C1, /* 961 */
+ .vt_pixel_clk = 320000000,
+ .op_pixel_clk = 320000000,
+ .binning_factor = 1,
+ },
+};
+
+static struct msm_camera_csi_params ov9726_csi_params = {
+ .data_format = CSI_10BIT,
+ .lane_cnt = 1,
+ .lane_assign = 0xe4,
+ .dpcm_scheme = 0,
+ .settle_cnt = 7,
+};
+
+static struct msm_camera_csi_params *ov9726_csi_params_array[] = {
+ &ov9726_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t ov9726_reg_addr = {
+ .x_output = 0x034c,
+ .y_output = 0x034e,
+ .line_length_pclk = 0x0342,
+ .frame_length_lines = 0x0340,
+};
+
+static struct msm_sensor_id_info_t ov9726_id_info = {
+ .sensor_id_reg_addr = 0x0000,
+ .sensor_id = 0x9726,
+};
+
+static struct msm_sensor_exp_gain_info_t ov9726_exp_gain_info = {
+ .coarse_int_time_addr = 0x0202,
+ .global_gain_addr = 0x0204,
+ .vert_offset = 6,
+};
+
+static const struct i2c_device_id ov9726_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&ov9726_s_ctrl},
+ { }
+};
+
+static struct i2c_driver ov9726_i2c_driver = {
+ .id_table = ov9726_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client ov9726_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ return i2c_add_driver(&ov9726_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops ov9726_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops ov9726_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops ov9726_subdev_ops = {
+ .core = &ov9726_subdev_core_ops,
+ .video = &ov9726_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t ov9726_func_tbl = {
+ .sensor_start_stream = msm_sensor_start_stream,
+ .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = msm_sensor_set_fps,
+ .sensor_write_exp_gain = msm_sensor_write_exp_gain1,
+ .sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
+ .sensor_setting = msm_sensor_setting1,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = msm_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t ov9726_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .start_stream_conf = ov9726_start_settings,
+ .start_stream_conf_size = ARRAY_SIZE(ov9726_start_settings),
+ .stop_stream_conf = ov9726_stop_settings,
+ .stop_stream_conf_size = ARRAY_SIZE(ov9726_stop_settings),
+ .group_hold_on_conf = ov9726_groupon_settings,
+ .group_hold_on_conf_size = ARRAY_SIZE(ov9726_groupon_settings),
+ .group_hold_off_conf = ov9726_groupoff_settings,
+ .group_hold_off_conf_size =
+ ARRAY_SIZE(ov9726_groupoff_settings),
+ .init_settings = &ov9726_init_conf[0],
+ .init_size = ARRAY_SIZE(ov9726_init_conf),
+ .mode_settings = &ov9726_confs[0],
+ .output_settings = &ov9726_dimensions[0],
+ .num_conf = ARRAY_SIZE(ov9726_confs),
+};
+
+static struct msm_sensor_ctrl_t ov9726_s_ctrl = {
+ .msm_sensor_reg = &ov9726_regs,
+ .sensor_i2c_client = &ov9726_sensor_i2c_client,
+ .sensor_i2c_addr = 0x20,
+ .sensor_output_reg_addr = &ov9726_reg_addr,
+ .sensor_id_info = &ov9726_id_info,
+ .sensor_exp_gain_info = &ov9726_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csic_params = &ov9726_csi_params_array[0],
+ .msm_sensor_mutex = &ov9726_mut,
+ .sensor_i2c_driver = &ov9726_i2c_driver,
+ .sensor_v4l2_subdev_info = ov9726_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov9726_subdev_info),
+ .sensor_v4l2_subdev_ops = &ov9726_subdev_ops,
+ .func_tbl = &ov9726_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Omnivision WXGA Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
new file mode 100644
index 0000000..1f99119
--- /dev/null
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -0,0 +1,503 @@
+/* Copyright (c) 2012, 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_sensor.h"
+#define SENSOR_NAME "s5k4e1"
+#define PLATFORM_DRIVER_NAME "msm_camera_s5k4e1"
+#define s5k4e1_obj s5k4e1_##obj
+#define MSB 1
+#define LSB 0
+
+DEFINE_MUTEX(s5k4e1_mut);
+static struct msm_sensor_ctrl_t s5k4e1_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf s5k4e1_start_settings[] = {
+ {0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_stop_settings[] = {
+ {0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_groupon_settings[] = {
+ {0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_groupoff_settings[] = {
+ {0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_prev_settings[] = {
+ /* output size (1304 x 980) */
+ {0x30A9, 0x02},/* Horizontal Binning On */
+ {0x300E, 0xEB},/* Vertical Binning On */
+ {0x0387, 0x03},/* y_odd_inc 03(10b AVG) */
+ {0x0344, 0x00},/* x_addr_start 0 */
+ {0x0345, 0x00},
+ {0x0348, 0x0A},/* x_addr_end 2607 */
+ {0x0349, 0x2F},
+ {0x0346, 0x00},/* y_addr_start 0 */
+ {0x0347, 0x00},
+ {0x034A, 0x07},/* y_addr_end 1959 */
+ {0x034B, 0xA7},
+ {0x0380, 0x00},/* x_even_inc 1 */
+ {0x0381, 0x01},
+ {0x0382, 0x00},/* x_odd_inc 1 */
+ {0x0383, 0x01},
+ {0x0384, 0x00},/* y_even_inc 1 */
+ {0x0385, 0x01},
+ {0x0386, 0x00},/* y_odd_inc 3 */
+ {0x0387, 0x03},
+ {0x034C, 0x05},/* x_output_size 1304 */
+ {0x034D, 0x18},
+ {0x034E, 0x03},/* y_output_size 980 */
+ {0x034F, 0xd4},
+ {0x30BF, 0xAB},/* outif_enable[7], data_type[5:0](2Bh = bayer 10bit} */
+ {0x30C0, 0xA0},/* video_offset[7:4] 3260%12 */
+ {0x30C8, 0x06},/* video_data_length 1600 = 1304 * 1.25 */
+ {0x30C9, 0x5E},
+ /* Timing Configuration */
+ {0x0202, 0x03},
+ {0x0203, 0x14},
+ {0x0204, 0x00},
+ {0x0205, 0x80},
+ {0x0340, 0x03},/* Frame Length */
+ {0x0341, 0xE0},
+ {0x0342, 0x0A},/* 2738 Line Length */
+ {0x0343, 0xB2},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_snap_settings[] = {
+ /*Output Size (2608x1960)*/
+ {0x30A9, 0x03},/* Horizontal Binning Off */
+ {0x300E, 0xE8},/* Vertical Binning Off */
+ {0x0387, 0x01},/* y_odd_inc */
+ {0x034C, 0x0A},/* x_output size */
+ {0x034D, 0x30},
+ {0x034E, 0x07},/* y_output size */
+ {0x034F, 0xA8},
+ {0x30BF, 0xAB},/* outif_enable[7], data_type[5:0](2Bh = bayer 10bit} */
+ {0x30C0, 0x80},/* video_offset[7:4] 3260%12 */
+ {0x30C8, 0x0C},/* video_data_length 3260 = 2608 * 1.25 */
+ {0x30C9, 0xBC},
+ /*Timing configuration*/
+ {0x0202, 0x06},
+ {0x0203, 0x28},
+ {0x0204, 0x00},
+ {0x0205, 0x80},
+ {0x0340, 0x07},/* Frame Length */
+ {0x0341, 0xB4},
+ {0x0342, 0x0A},/* 2738 Line Length */
+ {0x0343, 0xB2},
+};
+
+static struct msm_camera_i2c_reg_conf s5k4e1_recommend_settings[] = {
+ /* Reset setting */
+ {0x0103, 0x01},
+ /* MIPI settings */
+ {0x30BD, 0x00},/* SEL_CCP[0] */
+ {0x3084, 0x15},/* SYNC Mode */
+ {0x30BE, 0x1A},/* M_PCLKDIV_AUTO[4], M_DIV_PCLK[3:0] */
+ {0x30C1, 0x01},/* pack video enable [0] */
+ {0x30EE, 0x02},/* DPHY enable [ 1] */
+ {0x3111, 0x86},/* Embedded data off [5] */
+
+ /* REC Settings */
+ /*CDS timing setting ... */
+ {0x3000, 0x05},
+ {0x3001, 0x03},
+ {0x3002, 0x08},
+ {0x3003, 0x0A},
+ {0x3004, 0x50},
+ {0x3005, 0x0E},
+ {0x3006, 0x5E},
+ {0x3007, 0x00},
+ {0x3008, 0x78},
+ {0x3009, 0x78},
+ {0x300A, 0x50},
+ {0x300B, 0x08},
+ {0x300C, 0x14},
+ {0x300D, 0x00},
+ {0x300E, 0xE8},
+ {0x300F, 0x82},
+ {0x301B, 0x77},
+
+ /* CDS option setting ... */
+ {0x3010, 0x00},
+ {0x3011, 0x3A},
+ {0x3029, 0x04},
+ {0x3012, 0x30},
+ {0x3013, 0xA0},
+ {0x3014, 0x00},
+ {0x3015, 0x00},
+ {0x3016, 0x30},
+ {0x3017, 0x94},
+ {0x3018, 0x70},
+ {0x301D, 0xD4},
+ {0x3021, 0x02},
+ {0x3022, 0x24},
+ {0x3024, 0x40},
+ {0x3027, 0x08},
+
+ /* Pixel option setting ... */
+ {0x301C, 0x04},
+ {0x30D8, 0x3F},
+ {0x302B, 0x01},
+
+ {0x3070, 0x5F},
+ {0x3071, 0x00},
+ {0x3080, 0x04},
+ {0x3081, 0x38},
+
+ /* PLL settings */
+ {0x0305, 0x04},
+ {0x0306, 0x00},
+ {0x0307, 0x44},
+ {0x30B5, 0x00},
+ {0x30E2, 0x01},/* num lanes[1:0] = 2 */
+ {0x30F1, 0xB0},
+};
+
+static struct v4l2_subdev_info s5k4e1_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SGRBG10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array s5k4e1_init_conf[] = {
+ {&s5k4e1_recommend_settings[0],
+ ARRAY_SIZE(s5k4e1_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array s5k4e1_confs[] = {
+ {&s5k4e1_snap_settings[0],
+ ARRAY_SIZE(s5k4e1_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&s5k4e1_prev_settings[0],
+ ARRAY_SIZE(s5k4e1_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t s5k4e1_dimensions[] = {
+ {
+ .x_output = 0xA30,
+ .y_output = 0x7A8,
+ .line_length_pclk = 0xAB2,
+ .frame_length_lines = 0x7B4,
+ .vt_pixel_clk = 816000000,
+ .op_pixel_clk = 816000000,
+ .binning_factor = 0,
+ },
+ {
+ .x_output = 0x518,
+ .y_output = 0x3D4,
+ .line_length_pclk = 0xAB2,
+ .frame_length_lines = 0x3E0,
+ .vt_pixel_clk = 816000000,
+ .op_pixel_clk = 816000000,
+ .binning_factor = 1,
+ },
+};
+
+static struct msm_camera_csi_params s5k4e1_csi_params = {
+ .data_format = CSI_10BIT,
+ .lane_cnt = 1,
+ .lane_assign = 0xe4,
+ .dpcm_scheme = 0,
+ .settle_cnt = 24,
+};
+
+static struct msm_camera_csi_params *s5k4e1_csi_params_array[] = {
+ &s5k4e1_csi_params,
+ &s5k4e1_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t s5k4e1_reg_addr = {
+ .x_output = 0x034C,
+ .y_output = 0x034E,
+ .line_length_pclk = 0x0342,
+ .frame_length_lines = 0x0340,
+};
+
+static struct msm_sensor_id_info_t s5k4e1_id_info = {
+ .sensor_id_reg_addr = 0x0000,
+ .sensor_id = 0x4E10,
+};
+
+static struct msm_sensor_exp_gain_info_t s5k4e1_exp_gain_info = {
+ .coarse_int_time_addr = 0x0202,
+ .global_gain_addr = 0x0204,
+ .vert_offset = 4,
+};
+
+static inline uint8_t s5k4e1_byte(uint16_t word, uint8_t offset)
+{
+ return word >> (offset * BITS_PER_BYTE);
+}
+
+static int32_t s5k4e1_write_prev_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line)
+{
+ uint16_t max_legal_gain = 0x0200;
+ int32_t rc = 0;
+ static uint32_t fl_lines, offset;
+
+ pr_info("s5k4e1_write_prev_exp_gain :%d %d\n", gain, line);
+ offset = s_ctrl->sensor_exp_gain_info->vert_offset;
+ if (gain > max_legal_gain) {
+ CDBG("Max legal gain Line:%d\n", __LINE__);
+ gain = max_legal_gain;
+ }
+
+ /* Analogue Gain */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr,
+ s5k4e1_byte(gain, MSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+ s5k4e1_byte(gain, LSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ if (line > (s_ctrl->curr_frame_length_lines - offset)) {
+ fl_lines = line + offset;
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->frame_length_lines,
+ s5k4e1_byte(fl_lines, MSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
+ s5k4e1_byte(fl_lines, LSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ /* Coarse Integration Time */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+ s5k4e1_byte(line, MSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+ s5k4e1_byte(line, LSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+ } else if (line < (fl_lines - offset)) {
+ fl_lines = line + offset;
+ if (fl_lines < s_ctrl->curr_frame_length_lines)
+ fl_lines = s_ctrl->curr_frame_length_lines;
+
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+ /* Coarse Integration Time */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+ s5k4e1_byte(line, MSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+ s5k4e1_byte(line, LSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->frame_length_lines,
+ s5k4e1_byte(fl_lines, MSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
+ s5k4e1_byte(fl_lines, LSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+ } else {
+ fl_lines = line+4;
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+ /* Coarse Integration Time */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+ s5k4e1_byte(line, MSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+ s5k4e1_byte(line, LSB),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+ }
+ return rc;
+}
+
+static int32_t s5k4e1_write_pict_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line)
+{
+ uint16_t max_legal_gain = 0x0200;
+ uint16_t min_ll_pck = 0x0AB2;
+ uint32_t ll_pck, fl_lines;
+ uint32_t ll_ratio;
+ uint8_t gain_msb, gain_lsb;
+ uint8_t intg_time_msb, intg_time_lsb;
+ uint8_t ll_pck_msb, ll_pck_lsb;
+
+ if (gain > max_legal_gain) {
+ CDBG("Max legal gain Line:%d\n", __LINE__);
+ gain = max_legal_gain;
+ }
+
+ gain = 32;
+ line = 1465;
+ pr_info("s5k4e1_write_exp_gain : gain = %d line = %d\n", gain, line);
+ line = (uint32_t) (line * s_ctrl->fps_divider);
+ fl_lines = s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider / Q10;
+ ll_pck = s_ctrl->curr_line_length_pclk;
+
+ if (fl_lines < (line / Q10))
+ ll_ratio = (line / (fl_lines - 4));
+ else
+ ll_ratio = Q10;
+
+ ll_pck = ll_pck * ll_ratio / Q10;
+ line = line / ll_ratio;
+ if (ll_pck < min_ll_pck)
+ ll_pck = min_ll_pck;
+
+ gain_msb = (uint8_t) ((gain & 0xFF00) >> 8);
+ gain_lsb = (uint8_t) (gain & 0x00FF);
+
+ intg_time_msb = (uint8_t) ((line & 0xFF00) >> 8);
+ intg_time_lsb = (uint8_t) (line & 0x00FF);
+
+ ll_pck_msb = (uint8_t) ((ll_pck & 0xFF00) >> 8);
+ ll_pck_lsb = (uint8_t) (ll_pck & 0x00FF);
+
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr,
+ gain_msb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+ gain_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->line_length_pclk,
+ ll_pck_msb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->line_length_pclk + 1,
+ ll_pck_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ /* Coarse Integration Time */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+ intg_time_msb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+ intg_time_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+
+ return 0;
+}
+
+static const struct i2c_device_id s5k4e1_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&s5k4e1_s_ctrl},
+ { }
+};
+
+static struct i2c_driver s5k4e1_i2c_driver = {
+ .id_table = s5k4e1_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client s5k4e1_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ return i2c_add_driver(&s5k4e1_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops s5k4e1_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops s5k4e1_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops s5k4e1_subdev_ops = {
+ .core = &s5k4e1_subdev_core_ops,
+ .video = &s5k4e1_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t s5k4e1_func_tbl = {
+ .sensor_start_stream = msm_sensor_start_stream,
+ .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = msm_sensor_set_fps,
+ .sensor_write_exp_gain = s5k4e1_write_prev_exp_gain,
+ .sensor_write_snapshot_exp_gain = s5k4e1_write_pict_exp_gain,
+ .sensor_setting = msm_sensor_setting1,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = msm_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t s5k4e1_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .start_stream_conf = s5k4e1_start_settings,
+ .start_stream_conf_size = ARRAY_SIZE(s5k4e1_start_settings),
+ .stop_stream_conf = s5k4e1_stop_settings,
+ .stop_stream_conf_size = ARRAY_SIZE(s5k4e1_stop_settings),
+ .group_hold_on_conf = s5k4e1_groupon_settings,
+ .group_hold_on_conf_size = ARRAY_SIZE(s5k4e1_groupon_settings),
+ .group_hold_off_conf = s5k4e1_groupoff_settings,
+ .group_hold_off_conf_size =
+ ARRAY_SIZE(s5k4e1_groupoff_settings),
+ .init_settings = &s5k4e1_init_conf[0],
+ .init_size = ARRAY_SIZE(s5k4e1_init_conf),
+ .mode_settings = &s5k4e1_confs[0],
+ .output_settings = &s5k4e1_dimensions[0],
+ .num_conf = ARRAY_SIZE(s5k4e1_confs),
+};
+
+static struct msm_sensor_ctrl_t s5k4e1_s_ctrl = {
+ .msm_sensor_reg = &s5k4e1_regs,
+ .sensor_i2c_client = &s5k4e1_sensor_i2c_client,
+ .sensor_i2c_addr = 0x6C,
+ .sensor_output_reg_addr = &s5k4e1_reg_addr,
+ .sensor_id_info = &s5k4e1_id_info,
+ .sensor_exp_gain_info = &s5k4e1_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csic_params = &s5k4e1_csi_params_array[0],
+ .msm_sensor_mutex = &s5k4e1_mut,
+ .sensor_i2c_driver = &s5k4e1_i2c_driver,
+ .sensor_v4l2_subdev_info = s5k4e1_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k4e1_subdev_info),
+ .sensor_v4l2_subdev_ops = &s5k4e1_subdev_ops,
+ .func_tbl = &s5k4e1_func_tbl,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Samsung 5MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index a984943..d905b22 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -401,6 +401,7 @@
#define CMD_CONFIG_FREE_BUF_ADDR 48
#define CMD_AXI_CFG_ZSL_ALL_CHNLS 49
#define CMD_AXI_CFG_VIDEO_ALL_CHNLS 50
+#define CMD_VFE_BUFFER_RELEASE 51
/* vfe config command: config command(from config thread)*/
struct msm_vfe_cfg_cmd {
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 4694b78..dae4a12 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -41,6 +41,7 @@
#define MSG_ID_BUS_OVERFLOW 36
#define MSG_ID_SOF_ACK 37
#define MSG_ID_STOP_REC_ACK 38
+#define MSG_ID_STATS_AWB_AEC 39
/* ISP command IDs */
#define VFE_CMD_DUMMY_0 0
@@ -172,6 +173,13 @@
#define VFE_CMD_GET_RGB_G_TABLE 126
#define VFE_CMD_GET_LA_TABLE 127
#define VFE_CMD_DEMOSAICV3_UPDATE 128
+#define VFE_CMD_ACTIVE_REGION_CFG 129
+#define VFE_CMD_COLOR_PROCESSING_CONFIG 130
+#define VFE_CMD_STATS_WB_AEC_CONFIG 131
+#define VFE_CMD_STATS_WB_AEC_UPDATE 132
+#define VFE_CMD_Y_GAMMA_CONFIG 133
+#define VFE_CMD_SCALE_OUTPUT1_CONFIG 134
+#define VFE_CMD_SCALE_OUTPUT2_CONFIG 135
struct msm_isp_cmd {
int32_t id;
@@ -179,7 +187,6 @@
void *value;
};
-
#define VPE_CMD_DUMMY_0 0
#define VPE_CMD_INIT 1
#define VPE_CMD_DEINIT 2