aboutsummaryrefslogtreecommitdiff
path: root/camera/sensor/csid
diff options
context:
space:
mode:
authorwzedlare <vedatak01@gmail.com>2017-06-18 16:38:26 +0000
committerwzedlare <vedatak01@gmail.com>2017-06-19 16:57:11 +0000
commitc7d4e3fd588e3ba3d3fa4d5cfa224aa54bc288bf (patch)
treeb8b64cb9deb6832c1e41f58f0f143514beafc709 /camera/sensor/csid
parent28c99c87b881bb664c44bb26e80a681f87d54e60 (diff)
p2a42: Import fully working kernel sourceHEADn7.1
Change-Id: Ia4c94f09e29843b1af34d466243378a357e97b70
Diffstat (limited to 'camera/sensor/csid')
-rw-r--r--camera/sensor/csid/Makefile4
-rw-r--r--camera/sensor/csid/include/msm_csid_2_0_hwreg.h65
-rw-r--r--camera/sensor/csid/include/msm_csid_2_2_hwreg.h64
-rw-r--r--camera/sensor/csid/include/msm_csid_3_0_hwreg.h64
-rw-r--r--camera/sensor/csid/include/msm_csid_3_1_hwreg.h64
-rw-r--r--camera/sensor/csid/include/msm_csid_3_2_hwreg.h64
-rw-r--r--camera/sensor/csid/include/msm_csid_3_4_1_hwreg.h63
-rw-r--r--camera/sensor/csid/include/msm_csid_3_4_2_hwreg.h63
-rw-r--r--camera/sensor/csid/include/msm_csid_3_4_3_hwreg.h63
-rw-r--r--camera/sensor/csid/include/msm_csid_3_5_1_hwreg.h64
-rw-r--r--camera/sensor/csid/include/msm_csid_3_5_hwreg.h64
-rw-r--r--camera/sensor/csid/include/msm_csid_3_6_0_hwreg.h63
-rw-r--r--camera/sensor/csid/msm_csid.c1218
-rw-r--r--camera/sensor/csid/msm_csid.h119
14 files changed, 2042 insertions, 0 deletions
diff --git a/camera/sensor/csid/Makefile b/camera/sensor/csid/Makefile
new file mode 100644
index 00000000..507054fe
--- /dev/null
+++ b/camera/sensor/csid/Makefile
@@ -0,0 +1,4 @@
+ccflags-y += -Icamera
+ccflags-y += -Icamera/common
+ccflags-y += -Icamera/sensor/io
+obj-$(CONFIG_MSM_CSID) += msm_csid.o
diff --git a/camera/sensor/csid/include/msm_csid_2_0_hwreg.h b/camera/sensor/csid/include/msm_csid_2_0_hwreg.h
new file mode 100644
index 00000000..dbe672ac
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_2_0_hwreg.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_2_0_HWREG_H
+#define MSM_CSID_2_0_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v2_0[PHY_LANE_MAX] = {0, 1, 2, 3, 4};
+
+struct csid_reg_parms_t csid_v2_0 = {
+
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x4,
+ 0x8,
+ 0xc,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x5c,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6c,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x9C,
+ 0xA0,
+ 0xA8,
+ 0xAC,
+ 0xB0,
+ 11,
+ 0x7FFF,
+ 0x2,
+ 17,
+ 0x02000011,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_2_2_hwreg.h b/camera/sensor/csid/include/msm_csid_2_2_hwreg.h
new file mode 100644
index 00000000..94c62957
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_2_2_hwreg.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_2_2_HWREG_H
+#define MSM_CSID_2_2_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v2_2[PHY_LANE_MAX] = {0, 1, 2, 3, 4};
+
+struct csid_reg_parms_t csid_v2_2 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x4,
+ 0x8,
+ 0xc,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x5c,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6c,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x9C,
+ 0xA0,
+ 0xA8,
+ 0xAC,
+ 0xB0,
+ 11,
+ 0x7FFF,
+ 0x2,
+ 17,
+ 0x02001000,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_0_hwreg.h b/camera/sensor/csid/include/msm_csid_3_0_hwreg.h
new file mode 100644
index 00000000..74f79af7
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_0_hwreg.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_0_HWREG_H
+#define MSM_CSID_3_0_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_0[PHY_LANE_MAX] = {0, 1, 2, 3, 4};
+
+struct csid_reg_parms_t csid_v3_0 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30000000,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_1_hwreg.h b/camera/sensor/csid/include/msm_csid_3_1_hwreg.h
new file mode 100644
index 00000000..23553779
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_1_hwreg.h
@@ -0,0 +1,64 @@
+ /* Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_1_HWREG_H
+#define MSM_CSID_3_1_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_1[PHY_LANE_MAX] = {0, 1, 2, 3, 4};
+
+struct csid_reg_parms_t csid_v3_1 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30010000,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_2_hwreg.h b/camera/sensor/csid/include/msm_csid_3_2_hwreg.h
new file mode 100644
index 00000000..efab52a0
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_2_hwreg.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_2_HWREG_H
+#define MSM_CSID_3_2_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_2[PHY_LANE_MAX] = {0, 1, 2, 3, 4};
+
+struct csid_reg_parms_t csid_v3_2 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30020000,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_4_1_hwreg.h b/camera/sensor/csid/include/msm_csid_3_4_1_hwreg.h
new file mode 100644
index 00000000..31a0fda0
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_4_1_hwreg.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_4_1_HWREG_H
+#define MSM_CSID_3_4_1_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+uint8_t csid_lane_assign_v3_4_1[PHY_LANE_MAX] = {0, 1, 2, 3, 4};
+
+struct csid_reg_parms_t csid_v3_4_1 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30040001,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_4_2_hwreg.h b/camera/sensor/csid/include/msm_csid_3_4_2_hwreg.h
new file mode 100644
index 00000000..70c23edf
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_4_2_hwreg.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_4_2_HWREG_H
+#define MSM_CSID_3_4_2_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_4_2[PHY_LANE_MAX] = {0, 4, 1, 2, 3};
+struct csid_reg_parms_t csid_v3_4_2 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30040002,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_4_3_hwreg.h b/camera/sensor/csid/include/msm_csid_3_4_3_hwreg.h
new file mode 100644
index 00000000..b5d21a50
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_4_3_hwreg.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_4_3_HWREG_H
+#define MSM_CSID_3_4_3_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_4_3[PHY_LANE_MAX] = {0, 4, 1, 2, 3};
+struct csid_reg_parms_t csid_v3_4_3 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30040003,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_5_1_hwreg.h b/camera/sensor/csid/include/msm_csid_3_5_1_hwreg.h
new file mode 100644
index 00000000..e7b83eec
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_5_1_hwreg.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_5_1_HWREG_H
+#define MSM_CSID_3_5_1_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_5_1[PHY_LANE_MAX] = {0, 4, 1, 2, 3};
+
+struct csid_reg_parms_t csid_v3_5_1 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x24,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0x9C,
+ 0xA0,
+ 0xA8,
+ 0xAC,
+ 0xB4,
+ 0xB8,
+ 0xBC,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30050001,
+ 0xC,
+ 0x84,
+ 0xA4,
+ 0x7f010800,
+ 20,
+ 17,
+ 16,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_5_hwreg.h b/camera/sensor/csid/include/msm_csid_3_5_hwreg.h
new file mode 100644
index 00000000..e1623e5a
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_5_hwreg.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_5_HWREG_H
+#define MSM_CSID_3_5_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_5[PHY_LANE_MAX] = {0, 4, 1, 2, 3};
+
+struct csid_reg_parms_t csid_v3_5 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x24,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0x9C,
+ 0xA0,
+ 0xA8,
+ 0xAC,
+ 0xB4,
+ 0xB8,
+ 0xBC,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30050000,
+ 0xC,
+ 0x84,
+ 0xA4,
+ 0x7f010800,
+ 20,
+ 17,
+ 16,
+};
+#endif
diff --git a/camera/sensor/csid/include/msm_csid_3_6_0_hwreg.h b/camera/sensor/csid/include/msm_csid_3_6_0_hwreg.h
new file mode 100644
index 00000000..879b0ba0
--- /dev/null
+++ b/camera/sensor/csid/include/msm_csid_3_6_0_hwreg.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_6_0_HWREG_H
+#define MSM_CSID_3_6_0_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+uint8_t csid_lane_assign_v3_6_0[PHY_LANE_MAX] = {0, 1, 2, 3, 4};
+struct csid_reg_parms_t csid_v3_6_0 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30060000,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/camera/sensor/csid/msm_csid.c b/camera/sensor/csid/msm_csid.c
new file mode 100644
index 00000000..ef07a540
--- /dev/null
+++ b/camera/sensor/csid/msm_csid.c
@@ -0,0 +1,1218 @@
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irqreturn.h>
+#include "msm_csid.h"
+#include "msm_sd.h"
+#include "msm_camera_io_util.h"
+#include "msm_camera_dt_util.h"
+#include "include/msm_csid_2_0_hwreg.h"
+#include "include/msm_csid_2_2_hwreg.h"
+#include "include/msm_csid_3_0_hwreg.h"
+#include "include/msm_csid_3_1_hwreg.h"
+#include "include/msm_csid_3_2_hwreg.h"
+#include "include/msm_csid_3_5_hwreg.h"
+#include "include/msm_csid_3_4_1_hwreg.h"
+#include "include/msm_csid_3_4_2_hwreg.h"
+#include "include/msm_csid_3_4_3_hwreg.h"
+#include "include/msm_csid_3_6_0_hwreg.h"
+#include "include/msm_csid_3_5_1_hwreg.h"
+#include "cam_hw_ops.h"
+
+#define V4L2_IDENT_CSID 50002
+#define CSID_VERSION_V20 0x02000011
+#define CSID_VERSION_V22 0x02001000
+#define CSID_VERSION_V30 0x30000000
+#define CSID_VERSION_V31 0x30010000
+#define CSID_VERSION_V31_1 0x30010001
+#define CSID_VERSION_V31_3 0x30010003
+#define CSID_VERSION_V32 0x30020000
+#define CSID_VERSION_V33 0x30030000
+#define CSID_VERSION_V34 0x30040000
+#define CSID_VERSION_V34_1 0x30040001
+#define CSID_VERSION_V34_2 0x30040002
+#define CSID_VERSION_V34_3 0x30040003
+#define CSID_VERSION_V36 0x30060000
+#define CSID_VERSION_V37 0x30070000
+#define CSID_VERSION_V35 0x30050000
+#define CSID_VERSION_V35_1 0x30050001
+#define CSID_VERSION_V40 0x40000000
+#define MSM_CSID_DRV_NAME "msm_csid"
+
+#define DBG_CSID 0
+#define SHORT_PKT_CAPTURE 0
+#define SHORT_PKT_OFFSET 0x200
+#define ENABLE_3P_BIT 1
+#define SOF_DEBUG_ENABLE 1
+#define SOF_DEBUG_DISABLE 0
+
+#define TRUE 1
+#define FALSE 0
+
+#define CSID_TIMEOUT msecs_to_jiffies(100)
+
+#undef CDBG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+
+static struct camera_vreg_t csid_vreg_info[] = {
+ {"qcom,mipi-csi-vdd", 0, 0, 12000},
+};
+
+#ifdef CONFIG_COMPAT
+static struct v4l2_file_operations msm_csid_v4l2_subdev_fops;
+#endif
+
+static int msm_csid_cid_lut(
+ struct msm_camera_csid_lut_params *csid_lut_params,
+ struct csid_device *csid_dev)
+{
+ int rc = 0, i = 0;
+ uint32_t val = 0;
+
+ if (!csid_lut_params) {
+ pr_err("%s:%d csid_lut_params NULL\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ if (csid_lut_params->num_cid > MAX_CID) {
+ pr_err("%s:%d num_cid exceeded limit num_cid = %d max = %d\n",
+ __func__, __LINE__, csid_lut_params->num_cid, MAX_CID);
+ return -EINVAL;
+ }
+ for (i = 0; i < csid_lut_params->num_cid; i++) {
+ if (csid_lut_params->vc_cfg[i]->cid >= MAX_CID) {
+ pr_err("%s: cid outside range %d\n",
+ __func__, csid_lut_params->vc_cfg[i]->cid);
+ return -EINVAL;
+ }
+ CDBG("%s lut params num_cid = %d, cid = %d\n",
+ __func__,
+ csid_lut_params->num_cid,
+ csid_lut_params->vc_cfg[i]->cid);
+ CDBG("%s lut params dt = 0x%x, df = %d\n", __func__,
+ csid_lut_params->vc_cfg[i]->dt,
+ csid_lut_params->vc_cfg[i]->decode_format);
+ if (csid_lut_params->vc_cfg[i]->dt < 0x12 ||
+ csid_lut_params->vc_cfg[i]->dt > 0x37) {
+ pr_err("%s: unsupported data type 0x%x\n",
+ __func__, csid_lut_params->vc_cfg[i]->dt);
+ return rc;
+ }
+ val = msm_camera_io_r(csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_cid_lut_vc_0_addr +
+ (csid_lut_params->vc_cfg[i]->cid >> 2) * 4)
+ & ~(0xFF << ((csid_lut_params->vc_cfg[i]->cid % 4) *
+ 8));
+ val |= (csid_lut_params->vc_cfg[i]->dt <<
+ ((csid_lut_params->vc_cfg[i]->cid % 4) * 8));
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_cid_lut_vc_0_addr +
+ (csid_lut_params->vc_cfg[i]->cid >> 2) * 4);
+
+ val = (csid_lut_params->vc_cfg[i]->decode_format << 4) | 0x3;
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_cid_n_cfg_addr +
+ (csid_lut_params->vc_cfg[i]->cid * 4));
+ }
+ return rc;
+}
+
+#if (DBG_CSID)
+static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
+ struct msm_camera_csid_params *csid_params)
+{
+ uint32_t val = 0;
+
+ if ((csid_dev->hw_dts_version == CSID_VERSION_V34_1) ||
+ (csid_dev->hw_dts_version == CSID_VERSION_V36)) {
+ val = ((1 << csid_params->lane_cnt) - 1) << 20;
+ msm_camera_io_w(0x7f010800 | val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
+ msm_camera_io_w(0x7f010800 | val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+ } else {
+ if (csid_dev->csid_3p_enabled == 1) {
+ val = ((1 << csid_params->lane_cnt) - 1) <<
+ csid_dev->ctrl_reg->
+ csid_reg.csid_err_lane_overflow_offset_3p;
+ } else {
+ val = ((1 << csid_params->lane_cnt) - 1) <<
+ csid_dev->ctrl_reg->
+ csid_reg.csid_err_lane_overflow_offset_2p;
+ }
+ val |= csid_dev->ctrl_reg->csid_reg.csid_irq_mask_val;
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+ }
+}
+#elif(SHORT_PKT_CAPTURE)
+static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
+ struct msm_camera_csid_params *csid_params)
+{
+ uint32_t val = 0;
+
+ if ((csid_dev->hw_dts_version == CSID_VERSION_V34_1) ||
+ (csid_dev->hw_dts_version == CSID_VERSION_V36)) {
+ val = ((1 << csid_params->lane_cnt) - 1) << 20;
+ msm_camera_io_w(0x7f010a00 | val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
+ msm_camera_io_w(0x7f010a00 | val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+ } else {
+ if (csid_dev->csid_3p_enabled == 1) {
+ val = ((1 << csid_params->lane_cnt) - 1) <<
+ csid_dev->ctrl_reg->
+ csid_reg.csid_err_lane_overflow_offset_3p;
+ } else {
+ val = ((1 << csid_params->lane_cnt) - 1) <<
+ csid_dev->ctrl_reg->
+ csid_reg.csid_err_lane_overflow_offset_2p;
+ }
+ val |= csid_dev->ctrl_reg->csid_reg.csid_irq_mask_val;
+ val |= SHORT_PKT_OFFSET;
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+ }
+}
+#else
+static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
+ struct msm_camera_csid_params *csid_params) {}
+#endif
+
+static void msm_csid_set_sof_freeze_debug_reg(struct csid_device *csid_dev)
+{
+ uint32_t val = 0;
+
+ if (csid_dev->csid_3p_enabled == 1) {
+ val = ((1 << csid_dev->current_csid_params.lane_cnt) - 1) <<
+ csid_dev->ctrl_reg->
+ csid_reg.csid_err_lane_overflow_offset_3p;
+ } else {
+ val = ((1 << csid_dev->current_csid_params.lane_cnt) - 1) <<
+ csid_dev->ctrl_reg->
+ csid_reg.csid_err_lane_overflow_offset_2p;
+ }
+ val |= csid_dev->ctrl_reg->csid_reg.csid_irq_mask_val;
+ val |= SHORT_PKT_OFFSET;
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
+ msm_camera_io_w(val, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+}
+
+static int msm_csid_reset(struct csid_device *csid_dev)
+{
+ int32_t rc = 0;
+ msm_camera_io_w(csid_dev->ctrl_reg->csid_reg.csid_rst_stb_all,
+ csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_rst_cmd_addr);
+ rc = wait_for_completion_timeout(&csid_dev->reset_complete,
+ CSID_TIMEOUT);
+ if (rc <= 0) {
+ pr_err("wait_for_completion in msm_csid_reset fail rc = %d\n",
+ rc);
+ if (rc == 0)
+ rc = -ETIMEDOUT;
+ }
+ return rc;
+}
+
+static bool msm_csid_find_max_clk_rate(struct csid_device *csid_dev)
+{
+ int i;
+ bool ret = FALSE;
+
+ for (i = 0; i < csid_dev->num_clk; i++) {
+ if (!strcmp(csid_dev->csid_clk_info[i].clk_name,
+ "csi_src_clk")) {
+ CDBG("%s:%d, copy csi_src_clk, clk_rate[%d] = %ld",
+ __func__, __LINE__, i,
+ csid_dev->csid_clk_info[i].clk_rate);
+ csid_dev->csid_max_clk =
+ csid_dev->csid_clk_info[i].clk_rate;
+ csid_dev->csid_clk_index = i;
+ ret = TRUE;
+ break;
+ }
+ }
+ return ret;
+}
+static int msm_csid_config(struct csid_device *csid_dev,
+ struct msm_camera_csid_params *csid_params)
+{
+ int rc = 0;
+ uint32_t val = 0;
+ long clk_rate = 0;
+ uint32_t input_sel;
+ uint32_t lane_assign = 0;
+ uint8_t lane_num = 0;
+ uint8_t i, j;
+ void __iomem *csidbase;
+ csidbase = csid_dev->base;
+ if (!csidbase || !csid_params) {
+ pr_err("%s:%d csidbase %p, csid params %p\n", __func__,
+ __LINE__, csidbase, csid_params);
+ return -EINVAL;
+ }
+
+ CDBG("%s csid_params, lane_cnt = %d, lane_assign = 0x%x\n",
+ __func__,
+ csid_params->lane_cnt,
+ csid_params->lane_assign);
+ CDBG("%s csid_params phy_sel = %d\n", __func__,
+ csid_params->phy_sel);
+
+ csid_dev->csid_lane_cnt = csid_params->lane_cnt;
+ rc = msm_csid_reset(csid_dev);
+ if (rc < 0) {
+ pr_err("%s:%d msm_csid_reset failed\n", __func__, __LINE__);
+ return rc;
+ }
+
+ if (!msm_csid_find_max_clk_rate(csid_dev))
+ pr_err("msm_csid_find_max_clk_rate failed\n");
+
+ clk_rate = (csid_params->csi_clk > 0) ?
+ (csid_params->csi_clk) : csid_dev->csid_max_clk;
+
+ clk_rate = msm_camera_clk_set_rate(&csid_dev->pdev->dev,
+ csid_dev->csid_clk[csid_dev->csid_clk_index], clk_rate);
+ if (clk_rate < 0) {
+ pr_err("csi_src_clk set failed\n");
+ return -EINVAL;
+ }
+
+ if (csid_dev->is_testmode == 1) {
+ struct msm_camera_csid_testmode_parms *tm;
+ tm = &csid_dev->testmode_params;
+
+ /* 31:24 V blank, 23:13 H blank, 3:2 num of active DT, 1:0 VC */
+ val = ((tm->v_blanking_count & 0xFF) << 24) |
+ ((tm->h_blanking_count & 0x7FF) << 13);
+ msm_camera_io_w(val, csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_tg_vc_cfg_addr);
+ CDBG("[TG] CSID_TG_VC_CFG_ADDR 0x%08x\n", val);
+
+ /* 28:16 bytes per lines, 12:0 num of lines */
+ val = ((tm->num_bytes_per_line & 0x1FFF) << 16) |
+ (tm->num_lines & 0x1FFF);
+ msm_camera_io_w(val, csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_0_addr);
+ CDBG("[TG] CSID_TG_DT_n_CFG_0_ADDR 0x%08x\n", val);
+
+ /* 5:0 data type */
+ val = csid_params->lut_params.vc_cfg[0]->dt;
+ msm_camera_io_w(val, csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_1_addr);
+ CDBG("[TG] CSID_TG_DT_n_CFG_1_ADDR 0x%08x\n", val);
+
+ /* 2:0 output random */
+ msm_camera_io_w(csid_dev->testmode_params.payload_mode,
+ csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_2_addr);
+ } else {
+ val = csid_params->lane_cnt - 1;
+
+ for (i = 0, j = 0; i < PHY_LANE_MAX; i++) {
+ if (i == PHY_LANE_CLK)
+ continue;
+ lane_num = (csid_params->lane_assign >> j) & 0xF;
+ if (lane_num >= PHY_LANE_MAX) {
+ pr_err("%s:%d invalid lane number %d\n",
+ __func__, __LINE__, lane_num);
+ return -EINVAL;
+ }
+ if (csid_dev->ctrl_reg->csid_lane_assign[lane_num] >=
+ PHY_LANE_MAX){
+ pr_err("%s:%d invalid lane map %d\n",
+ __func__, __LINE__,
+ csid_dev->ctrl_reg->
+ csid_lane_assign[lane_num]);
+ return -EINVAL;
+ }
+ lane_assign |=
+ csid_dev->ctrl_reg->csid_lane_assign[lane_num]
+ << j;
+ j += 4;
+ }
+
+ CDBG("%s csid_params calculated lane_assign = 0x%X\n",
+ __func__, lane_assign);
+
+ val |= lane_assign <<
+ csid_dev->ctrl_reg->csid_reg.csid_dl_input_sel_shift;
+ if (csid_dev->hw_version < CSID_VERSION_V30) {
+ val |= (0xF << 10);
+ msm_camera_io_w(val, csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_0_addr);
+ } else {
+ msm_camera_io_w(val, csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_0_addr);
+ val = csid_params->phy_sel <<
+ csid_dev->ctrl_reg->csid_reg.csid_phy_sel_shift;
+ val |= 0xF;
+ msm_camera_io_w(val, csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_1_addr);
+ }
+ if (csid_dev->hw_version == CSID_VERSION_V35 &&
+ csid_params->csi_3p_sel == 1) {
+ csid_dev->csid_3p_enabled = 1;
+ val = (csid_params->lane_cnt - 1) << ENABLE_3P_BIT;
+
+ for (i = 0; i < csid_params->lane_cnt; i++) {
+ input_sel =
+ (csid_params->lane_assign >> (4*i))
+ & 0xF;
+ val |= input_sel << (4*(i+1));
+ }
+ val |= csid_params->phy_sel <<
+ csid_dev->ctrl_reg->csid_reg.csid_phy_sel_shift_3p;
+ val |= ENABLE_3P_BIT;
+ msm_camera_io_w(val, csidbase + csid_dev->ctrl_reg
+ ->csid_reg.csid_3p_ctrl_0_addr);
+ }
+ }
+
+ rc = msm_csid_cid_lut(&csid_params->lut_params, csid_dev);
+ if (rc < 0) {
+ pr_err("%s:%d config cid lut failed\n", __func__, __LINE__);
+ return rc;
+ }
+ msm_csid_set_debug_reg(csid_dev, csid_params);
+
+ if (csid_dev->is_testmode == 1)
+ msm_camera_io_w(0x00A06437, csidbase +
+ csid_dev->ctrl_reg->csid_reg.csid_tg_ctrl_addr);
+
+ return rc;
+}
+
+#if SHORT_PKT_CAPTURE
+static irqreturn_t msm_csid_irq(int irq_num, void *data)
+{
+ uint32_t irq;
+ uint32_t short_dt = 0;
+ uint32_t count = 0, dt = 0;
+ struct csid_device *csid_dev = data;
+
+ if (!csid_dev) {
+ pr_err("%s:%d csid_dev NULL\n", __func__, __LINE__);
+ return IRQ_HANDLED;
+ }
+ irq = msm_camera_io_r(csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr);
+ CDBG("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
+ __func__, csid_dev->pdev->id, irq);
+ if (irq & (0x1 <<
+ csid_dev->ctrl_reg->csid_reg.csid_rst_done_irq_bitshift))
+ complete(&csid_dev->reset_complete);
+ if (irq & SHORT_PKT_OFFSET) {
+ short_dt = msm_camera_io_r(csid_dev->base +
+ csid_dev->ctrl_reg->
+ csid_reg.csid_captured_short_pkt_addr);
+ count = (short_dt >> 8) & 0xffff;
+ dt = short_dt >> 24;
+ CDBG("CSID:: %s:%d core %d dt: 0x%x, count: %d\n",
+ __func__, __LINE__, csid_dev->pdev->id, dt, count);
+ msm_camera_io_w(0x101, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_rst_cmd_addr);
+ }
+ msm_camera_io_w(irq, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+ return IRQ_HANDLED;
+}
+#else
+static irqreturn_t msm_csid_irq(int irq_num, void *data)
+{
+ uint32_t irq;
+ struct csid_device *csid_dev = data;
+
+ if (!csid_dev) {
+ pr_err("%s:%d csid_dev NULL\n", __func__, __LINE__);
+ return IRQ_HANDLED;
+ }
+ irq = msm_camera_io_r(csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr);
+ pr_err_ratelimited("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
+ __func__, csid_dev->pdev->id, irq);
+ if (irq & (0x1 <<
+ csid_dev->ctrl_reg->csid_reg.csid_rst_done_irq_bitshift))
+ complete(&csid_dev->reset_complete);
+ msm_camera_io_w(irq, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+ return IRQ_HANDLED;
+}
+#endif
+
+static int msm_csid_irq_routine(struct v4l2_subdev *sd, u32 status,
+ bool *handled)
+{
+ struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
+ irqreturn_t ret;
+ CDBG("%s E\n", __func__);
+ ret = msm_csid_irq(csid_dev->irq->start, csid_dev);
+ *handled = TRUE;
+ return 0;
+}
+
+static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
+{
+ int rc = 0;
+
+ if (!csid_version) {
+ pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
+ rc = -EINVAL;
+ return rc;
+ }
+
+ csid_dev->reg_ptr = NULL;
+
+ if (csid_dev->csid_state == CSID_POWER_UP) {
+ pr_err("%s: csid invalid state %d\n", __func__,
+ csid_dev->csid_state);
+ return -EINVAL;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote for AHB\n", __func__);
+ return rc;
+ }
+
+ pr_info("%s: CSID_VERSION = 0x%x\n", __func__,
+ csid_dev->ctrl_reg->csid_reg.csid_version);
+ /* power up */
+ rc = msm_camera_config_vreg(&csid_dev->pdev->dev, csid_dev->csid_vreg,
+ csid_dev->regulator_count, NULL, 0,
+ &csid_dev->csid_reg_ptr[0], 1);
+ if (rc < 0) {
+ pr_err("%s:%d csid config_vreg failed\n", __func__, __LINE__);
+ goto top_vreg_config_failed;
+ }
+
+ rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator on failed\n", __func__);
+ goto csid_vreg_config_failed;
+ }
+
+ rc = msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_dev->csid_vreg,
+ csid_dev->regulator_count, NULL, 0,
+ &csid_dev->csid_reg_ptr[0], 1);
+ if (rc < 0) {
+ pr_err("%s:%d csid enable_vreg failed\n", __func__, __LINE__);
+ goto top_vreg_enable_failed;
+ }
+
+ rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto csid_vreg_enable_failed;
+ }
+ rc = msm_camera_clk_enable(&csid_dev->pdev->dev,
+ csid_dev->csid_clk_info, csid_dev->csid_clk,
+ csid_dev->num_clk, true);
+ if (rc < 0) {
+ pr_err("%s:%d clock enable failed\n",
+ __func__, __LINE__);
+ goto clk_enable_failed;
+ }
+ CDBG("%s:%d called\n", __func__, __LINE__);
+ csid_dev->hw_version =
+ msm_camera_io_r(csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_hw_version_addr);
+ CDBG("%s:%d called csid_dev->hw_version %x\n", __func__, __LINE__,
+ csid_dev->hw_version);
+ *csid_version = csid_dev->hw_version;
+ csid_dev->csid_sof_debug = SOF_DEBUG_DISABLE;
+
+ csid_dev->is_testmode = 0;
+
+ init_completion(&csid_dev->reset_complete);
+
+ rc = msm_camera_enable_irq(csid_dev->irq, true);
+ if (rc < 0)
+ pr_err("%s: irq enable failed\n", __func__);
+ rc = msm_csid_reset(csid_dev);
+ if (rc < 0) {
+ pr_err("%s:%d msm_csid_reset failed\n", __func__, __LINE__);
+ goto msm_csid_reset_fail;
+ }
+
+ csid_dev->csid_state = CSID_POWER_UP;
+ return rc;
+
+msm_csid_reset_fail:
+ msm_camera_enable_irq(csid_dev->irq, false);
+ msm_camera_clk_enable(&csid_dev->pdev->dev, csid_dev->csid_clk_info,
+ csid_dev->csid_clk, csid_dev->num_clk, false);
+clk_enable_failed:
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+csid_vreg_enable_failed:
+ msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_dev->csid_vreg,
+ csid_dev->regulator_count, NULL, 0,
+ &csid_dev->csid_reg_ptr[0], 0);
+top_vreg_enable_failed:
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+csid_vreg_config_failed:
+ msm_camera_config_vreg(&csid_dev->pdev->dev, csid_dev->csid_vreg,
+ csid_dev->regulator_count, NULL, 0,
+ &csid_dev->csid_reg_ptr[0], 0);
+top_vreg_config_failed:
+ if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
+ CAM_AHB_SUSPEND_VOTE) < 0)
+ pr_err("%s: failed to remove vote from AHB\n", __func__);
+ return rc;
+}
+
+static int msm_csid_release(struct csid_device *csid_dev)
+{
+ uint32_t irq;
+
+ if (csid_dev->csid_state != CSID_POWER_UP) {
+ pr_err("%s: csid invalid state %d\n", __func__,
+ csid_dev->csid_state);
+ return -EINVAL;
+ }
+
+ CDBG("%s:%d, hw_version = 0x%x\n", __func__, __LINE__,
+ csid_dev->hw_version);
+
+ irq = msm_camera_io_r(csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr);
+ msm_camera_io_w(irq, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+ msm_camera_io_w(0, csid_dev->base +
+ csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
+
+ msm_camera_enable_irq(csid_dev->irq, false);
+
+ msm_camera_clk_enable(&csid_dev->pdev->dev,
+ csid_dev->csid_clk_info,
+ csid_dev->csid_clk,
+ csid_dev->num_clk, false);
+
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_dev->csid_vreg, csid_dev->regulator_count, NULL,
+ 0, &csid_dev->csid_reg_ptr[0], 0);
+
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_dev->csid_vreg, csid_dev->regulator_count, NULL,
+ 0, &csid_dev->csid_reg_ptr[0], 0);
+
+ if (!IS_ERR_OR_NULL(csid_dev->reg_ptr)) {
+ regulator_disable(csid_dev->reg_ptr);
+ regulator_put(csid_dev->reg_ptr);
+ }
+
+ csid_dev->csid_state = CSID_POWER_DOWN;
+
+ if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
+ CAM_AHB_SUSPEND_VOTE) < 0)
+ pr_err("%s: failed to remove vote from AHB\n", __func__);
+ return 0;
+}
+
+static int32_t msm_csid_cmd(struct csid_device *csid_dev, void __user *arg)
+{
+ int rc = 0;
+ struct csid_cfg_data *cdata = (struct csid_cfg_data *)arg;
+
+ if (!csid_dev || !cdata) {
+ pr_err("%s:%d csid_dev %p, cdata %p\n", __func__, __LINE__,
+ csid_dev, cdata);
+ return -EINVAL;
+ }
+ CDBG("%s cfgtype = %d\n", __func__, cdata->cfgtype);
+ switch (cdata->cfgtype) {
+ case CSID_INIT:
+ rc = msm_csid_init(csid_dev, &cdata->cfg.csid_version);
+ CDBG("%s csid version 0x%x\n", __func__,
+ cdata->cfg.csid_version);
+ break;
+ case CSID_TESTMODE_CFG: {
+ csid_dev->is_testmode = 1;
+ if (copy_from_user(&csid_dev->testmode_params,
+ (void *)cdata->cfg.csid_testmode_params,
+ sizeof(struct msm_camera_csid_testmode_parms))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ break;
+ }
+ case CSID_CFG: {
+ struct msm_camera_csid_params csid_params;
+ struct msm_camera_csid_vc_cfg *vc_cfg = NULL;
+ int i = 0;
+ if (copy_from_user(&csid_params,
+ (void *)cdata->cfg.csid_params,
+ sizeof(struct msm_camera_csid_params))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ if (csid_params.lut_params.num_cid < 1 ||
+ csid_params.lut_params.num_cid > MAX_CID) {
+ pr_err("%s: %d num_cid outside range\n",
+ __func__, __LINE__);
+ rc = -EINVAL;
+ break;
+ }
+ for (i = 0; i < csid_params.lut_params.num_cid; i++) {
+ vc_cfg = kzalloc(sizeof(struct msm_camera_csid_vc_cfg),
+ GFP_KERNEL);
+ if (!vc_cfg) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ goto MEM_CLEAN;
+ }
+ if (copy_from_user(vc_cfg,
+ (void *)csid_params.lut_params.vc_cfg[i],
+ sizeof(struct msm_camera_csid_vc_cfg))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ kfree(vc_cfg);
+ rc = -EFAULT;
+ goto MEM_CLEAN;
+ }
+ csid_params.lut_params.vc_cfg[i] = vc_cfg;
+ }
+ csid_dev->current_csid_params = csid_params;
+ csid_dev->csid_sof_debug = SOF_DEBUG_DISABLE;
+ rc = msm_csid_config(csid_dev, &csid_params);
+MEM_CLEAN:
+ for (i--; i >= 0; i--)
+ kfree(csid_params.lut_params.vc_cfg[i]);
+ break;
+ }
+ case CSID_RELEASE:
+ rc = msm_csid_release(csid_dev);
+ break;
+ default:
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ return rc;
+}
+
+static int32_t msm_csid_get_subdev_id(struct csid_device *csid_dev, void *arg)
+{
+ uint32_t *subdev_id = (uint32_t *)arg;
+ if (!subdev_id) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ *subdev_id = csid_dev->pdev->id;
+ pr_debug("%s:%d subdev_id %d\n", __func__, __LINE__, *subdev_id);
+ return 0;
+}
+
+static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ int rc = -ENOIOCTLCMD;
+ struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
+
+ mutex_lock(&csid_dev->mutex);
+ CDBG("%s:%d id %d\n", __func__, __LINE__, csid_dev->pdev->id);
+ switch (cmd) {
+ case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+ rc = msm_csid_get_subdev_id(csid_dev, arg);
+ break;
+ case VIDIOC_MSM_CSID_IO_CFG:
+ rc = msm_csid_cmd(csid_dev, arg);
+ break;
+ case MSM_SD_NOTIFY_FREEZE:
+ if (csid_dev->csid_state != CSID_POWER_UP)
+ break;
+ if (csid_dev->csid_sof_debug == SOF_DEBUG_DISABLE) {
+ csid_dev->csid_sof_debug = SOF_DEBUG_ENABLE;
+ msm_csid_set_sof_freeze_debug_reg(csid_dev);
+ }
+ break;
+ case MSM_SD_UNNOTIFY_FREEZE:
+ if (csid_dev->csid_state != CSID_POWER_UP)
+ break;
+ csid_dev->csid_sof_debug = SOF_DEBUG_DISABLE;
+ break;
+ case VIDIOC_MSM_CSID_RELEASE:
+ case MSM_SD_SHUTDOWN:
+ rc = msm_csid_release(csid_dev);
+ break;
+ default:
+ pr_err_ratelimited("%s: command not found\n", __func__);
+ }
+ CDBG("%s:%d\n", __func__, __LINE__);
+ mutex_unlock(&csid_dev->mutex);
+ return rc;
+}
+
+
+#ifdef CONFIG_COMPAT
+static int32_t msm_csid_cmd32(struct csid_device *csid_dev, void __user *arg)
+{
+ int rc = 0;
+ struct csid_cfg_data *cdata;
+ struct csid_cfg_data32 *arg32 = (struct csid_cfg_data32 *) (arg);
+ struct csid_cfg_data local_arg;
+ local_arg.cfgtype = arg32->cfgtype;
+ cdata = &local_arg;
+
+ if (!csid_dev || !cdata) {
+ pr_err("%s:%d csid_dev %p, cdata %p\n", __func__, __LINE__,
+ csid_dev, cdata);
+ return -EINVAL;
+ }
+
+ CDBG("%s cfgtype = %d\n", __func__, cdata->cfgtype);
+ switch (cdata->cfgtype) {
+ case CSID_INIT:
+ rc = msm_csid_init(csid_dev, &cdata->cfg.csid_version);
+ arg32->cfg.csid_version = local_arg.cfg.csid_version;
+ CDBG("%s csid version 0x%x\n", __func__,
+ cdata->cfg.csid_version);
+ break;
+ case CSID_TESTMODE_CFG: {
+ csid_dev->is_testmode = 1;
+ if (copy_from_user(&csid_dev->testmode_params,
+ (void *)compat_ptr(arg32->cfg.csid_testmode_params),
+ sizeof(struct msm_camera_csid_testmode_parms))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ break;
+ }
+ case CSID_CFG: {
+
+ struct msm_camera_csid_params csid_params;
+ struct msm_camera_csid_vc_cfg *vc_cfg = NULL;
+ int i = 0;
+ struct msm_camera_csid_lut_params32 lut_par32;
+ struct msm_camera_csid_params32 csid_params32;
+ struct msm_camera_csid_vc_cfg vc_cfg32;
+
+ if (copy_from_user(&csid_params32,
+ (void *)compat_ptr(arg32->cfg.csid_params),
+ sizeof(struct msm_camera_csid_params32))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ csid_params.lane_cnt = csid_params32.lane_cnt;
+ csid_params.lane_assign = csid_params32.lane_assign;
+ csid_params.phy_sel = csid_params32.phy_sel;
+ csid_params.csi_clk = csid_params32.csi_clk;
+ csid_params.csi_3p_sel = csid_params32.csi_3p_sel;
+
+ lut_par32 = csid_params32.lut_params;
+ csid_params.lut_params.num_cid = lut_par32.num_cid;
+
+ if (csid_params.lut_params.num_cid < 1 ||
+ csid_params.lut_params.num_cid > MAX_CID) {
+ pr_err("%s: %d num_cid outside range %d\n", __func__,
+ __LINE__, csid_params.lut_params.num_cid);
+ rc = -EINVAL;
+ break;
+ }
+
+ for (i = 0; i < lut_par32.num_cid; i++) {
+ vc_cfg = kzalloc(sizeof(struct msm_camera_csid_vc_cfg),
+ GFP_KERNEL);
+ if (!vc_cfg) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ goto MEM_CLEAN32;
+ }
+ /* msm_camera_csid_vc_cfg size
+ * does not change in COMPAT MODE
+ */
+ if (copy_from_user(&vc_cfg32,
+ (void *)compat_ptr(lut_par32.vc_cfg[i]),
+ sizeof(vc_cfg32))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ kfree(vc_cfg);
+ vc_cfg = NULL;
+ rc = -EFAULT;
+ goto MEM_CLEAN32;
+ }
+ vc_cfg->cid = vc_cfg32.cid;
+ vc_cfg->dt = vc_cfg32.dt;
+ vc_cfg->decode_format = vc_cfg32.decode_format;
+ csid_params.lut_params.vc_cfg[i] = vc_cfg;
+ }
+ rc = msm_csid_config(csid_dev, &csid_params);
+ csid_dev->current_csid_params = csid_params;
+
+MEM_CLEAN32:
+ for (i--; i >= 0; i--) {
+ kfree(csid_params.lut_params.vc_cfg[i]);
+ csid_params.lut_params.vc_cfg[i] = NULL;
+ }
+ break;
+ }
+ case CSID_RELEASE:
+ rc = msm_csid_release(csid_dev);
+ break;
+ default:
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ return rc;
+}
+
+static long msm_csid_subdev_ioctl32(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ int rc = -ENOIOCTLCMD;
+ struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
+
+ mutex_lock(&csid_dev->mutex);
+ CDBG("%s:%d id %d\n", __func__, __LINE__, csid_dev->pdev->id);
+ switch (cmd) {
+ case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+ rc = msm_csid_get_subdev_id(csid_dev, arg);
+ break;
+ case VIDIOC_MSM_CSID_IO_CFG32:
+ rc = msm_csid_cmd32(csid_dev, arg);
+ break;
+ case MSM_SD_NOTIFY_FREEZE:
+ if (csid_dev->csid_state != CSID_POWER_UP)
+ break;
+ if (csid_dev->csid_sof_debug == SOF_DEBUG_DISABLE) {
+ csid_dev->csid_sof_debug = SOF_DEBUG_ENABLE;
+ msm_csid_set_sof_freeze_debug_reg(csid_dev);
+ }
+ break;
+ case MSM_SD_UNNOTIFY_FREEZE:
+ if (csid_dev->csid_state != CSID_POWER_UP)
+ break;
+ csid_dev->csid_sof_debug = SOF_DEBUG_DISABLE;
+ break;
+ case VIDIOC_MSM_CSID_RELEASE:
+ case MSM_SD_SHUTDOWN:
+ rc = msm_csid_release(csid_dev);
+ break;
+ default:
+ pr_err_ratelimited("%s: command not found\n", __func__);
+ }
+ CDBG("%s:%d\n", __func__, __LINE__);
+ mutex_unlock(&csid_dev->mutex);
+ return rc;
+}
+
+static long msm_csid_subdev_do_ioctl32(
+ struct file *file, unsigned int cmd, void *arg)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+
+ return msm_csid_subdev_ioctl32(sd, cmd, arg);
+}
+
+static long msm_csid_subdev_fops_ioctl32(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return video_usercopy(file, cmd, arg, msm_csid_subdev_do_ioctl32);
+}
+#endif
+static const struct v4l2_subdev_internal_ops msm_csid_internal_ops;
+
+static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
+ .ioctl = &msm_csid_subdev_ioctl,
+ .interrupt_service_routine = msm_csid_irq_routine,
+};
+
+static const struct v4l2_subdev_ops msm_csid_subdev_ops = {
+ .core = &msm_csid_subdev_core_ops,
+};
+
+static int csid_probe(struct platform_device *pdev)
+{
+ struct csid_device *new_csid_dev;
+ uint32_t csi_vdd_voltage = 0;
+ int rc = 0;
+ new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
+ if (!new_csid_dev) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ new_csid_dev->csid_3p_enabled = 0;
+ new_csid_dev->ctrl_reg = NULL;
+ new_csid_dev->ctrl_reg = kzalloc(sizeof(struct csid_ctrl_t),
+ GFP_KERNEL);
+ if (!new_csid_dev->ctrl_reg) {
+ pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+ kfree(new_csid_dev);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&new_csid_dev->msm_sd.sd, &msm_csid_subdev_ops);
+ v4l2_set_subdevdata(&new_csid_dev->msm_sd.sd, new_csid_dev);
+ platform_set_drvdata(pdev, &new_csid_dev->msm_sd.sd);
+ mutex_init(&new_csid_dev->mutex);
+
+ if (pdev->dev.of_node) {
+ rc = of_property_read_u32((&pdev->dev)->of_node,
+ "cell-index", &pdev->id);
+ if (rc < 0) {
+ pr_err("%s:%d failed to read cell-index\n", __func__,
+ __LINE__);
+ goto csid_no_resource;
+ }
+ CDBG("%s device id %d\n", __func__, pdev->id);
+
+ rc = of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,csi-vdd-voltage", &csi_vdd_voltage);
+ if (rc < 0) {
+ pr_err("%s:%d failed to read qcom,csi-vdd-voltage\n",
+ __func__, __LINE__);
+ goto csid_no_resource;
+ }
+ CDBG("%s:%d reading mipi_csi_vdd is %d\n", __func__, __LINE__,
+ csi_vdd_voltage);
+
+ csid_vreg_info[0].min_voltage = csi_vdd_voltage;
+ csid_vreg_info[0].max_voltage = csi_vdd_voltage;
+ }
+
+ rc = msm_camera_get_clk_info(pdev, &new_csid_dev->csid_clk_info,
+ &new_csid_dev->csid_clk, &new_csid_dev->num_clk);
+ if (rc < 0) {
+ pr_err("%s: msm_camera_get_clk_info failed", __func__);
+ rc = -EFAULT;
+ goto csid_no_resource;
+ }
+
+ rc = msm_camera_get_dt_vreg_data(pdev->dev.of_node,
+ &(new_csid_dev->csid_vreg), &(new_csid_dev->regulator_count));
+ if (rc < 0) {
+ pr_err("%s: get vreg data from dtsi fail\n", __func__);
+ rc = -EFAULT;
+ goto csid_no_resource;
+ }
+
+ if ((new_csid_dev->regulator_count < 0) ||
+ (new_csid_dev->regulator_count > MAX_REGULATOR)) {
+ pr_err("%s: invalid reg count = %d, max is %d\n", __func__,
+ new_csid_dev->regulator_count, MAX_REGULATOR);
+ rc = -EFAULT;
+ goto csid_no_resource;
+ }
+
+ new_csid_dev->base = msm_camera_get_reg_base(pdev, "csid", true);
+ if (!new_csid_dev->base) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto csid_invalid_vreg_data;
+ }
+ new_csid_dev->irq = msm_camera_get_irq(pdev, "csid");
+ if (!new_csid_dev->irq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto csid_invalid_irq;
+ }
+ new_csid_dev->pdev = pdev;
+ new_csid_dev->msm_sd.sd.internal_ops = &msm_csid_internal_ops;
+ new_csid_dev->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(new_csid_dev->msm_sd.sd.name,
+ ARRAY_SIZE(new_csid_dev->msm_sd.sd.name), "msm_csid");
+ media_entity_init(&new_csid_dev->msm_sd.sd.entity, 0, NULL, 0);
+ new_csid_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ new_csid_dev->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_CSID;
+ new_csid_dev->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x5;
+ msm_sd_register(&new_csid_dev->msm_sd);
+
+#ifdef CONFIG_COMPAT
+ msm_cam_copy_v4l2_subdev_fops(&msm_csid_v4l2_subdev_fops);
+ msm_csid_v4l2_subdev_fops.compat_ioctl32 = msm_csid_subdev_fops_ioctl32;
+ new_csid_dev->msm_sd.sd.devnode->fops = &msm_csid_v4l2_subdev_fops;
+#endif
+
+ rc = msm_camera_register_irq(pdev, new_csid_dev->irq,
+ msm_csid_irq, IRQF_TRIGGER_RISING, "csid", new_csid_dev);
+ if (rc < 0) {
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto csid_invalid_irq;
+ }
+ rc = msm_camera_enable_irq(new_csid_dev->irq, false);
+ if (rc < 0) {
+ pr_err("%s Error registering irq ", __func__);
+ rc = -EBUSY;
+ goto csid_invalid_irq;
+ }
+
+ if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v2.0")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v2_0;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v2_0;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V20;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v2.2")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v2_2;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v2_2;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V22;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.0")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_0;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_0;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V30;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v4.0")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_0;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_0;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V40;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.1")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_1;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_1;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V31;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.2")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_2;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_2;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V32;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.4.1")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_4_1;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V34_1;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_4_1;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.4.2")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_4_2;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V34_2;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_4_2;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.4.3")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_4_3;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V34_3;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_4_3;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.6.0")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_6_0;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V36;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_6_0;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.5")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_5;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_5;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V35;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.5.1")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_5_1;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_5_1;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V35_1;
+ } else {
+ pr_err("%s:%d, invalid hw version : 0x%x", __func__, __LINE__,
+ new_csid_dev->hw_dts_version);
+ rc = -EINVAL;
+ goto csid_invalid_irq;
+ }
+
+ new_csid_dev->csid_state = CSID_POWER_DOWN;
+ return 0;
+
+csid_invalid_irq:
+ msm_camera_put_reg_base(pdev, new_csid_dev->base, "csid", true);
+csid_invalid_vreg_data:
+ kfree(new_csid_dev->csid_vreg);
+csid_no_resource:
+ mutex_destroy(&new_csid_dev->mutex);
+ kfree(new_csid_dev->ctrl_reg);
+ kfree(new_csid_dev);
+ return rc;
+}
+
+static int msm_csid_exit(struct platform_device *pdev)
+{
+ struct v4l2_subdev *subdev = platform_get_drvdata(pdev);
+ struct csid_device *csid_dev =
+ v4l2_get_subdevdata(subdev);
+
+ msm_camera_put_clk_info(pdev, &csid_dev->csid_clk_info,
+ &csid_dev->csid_clk, csid_dev->num_clk);
+ msm_camera_put_reg_base(pdev, csid_dev->base, "csid", true);
+ kfree(csid_dev);
+ return 0;
+}
+
+static const struct of_device_id msm_csid_dt_match[] = {
+ {.compatible = "qcom,csid"},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, msm_csid_dt_match);
+
+static struct platform_driver csid_driver = {
+ .probe = csid_probe,
+ .remove = msm_csid_exit,
+ .driver = {
+ .name = MSM_CSID_DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = msm_csid_dt_match,
+ },
+};
+
+static int __init msm_csid_init_module(void)
+{
+ return platform_driver_register(&csid_driver);
+}
+
+static void __exit msm_csid_exit_module(void)
+{
+ platform_driver_unregister(&csid_driver);
+}
+
+module_init(msm_csid_init_module);
+module_exit(msm_csid_exit_module);
+MODULE_DESCRIPTION("MSM CSID driver");
+MODULE_LICENSE("GPL v2");
diff --git a/camera/sensor/csid/msm_csid.h b/camera/sensor/csid/msm_csid.h
new file mode 100644
index 00000000..c8937b14
--- /dev/null
+++ b/camera/sensor/csid/msm_csid.h
@@ -0,0 +1,119 @@
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_H
+#define MSM_CSID_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <lenovo_media/msm_cam_sensor.h>
+#include "msm_sd.h"
+#include "cam_soc_api.h"
+
+enum csiphy_lane_assign {
+ PHY_LANE_D0,
+ PHY_LANE_CLK,
+ PHY_LANE_D1,
+ PHY_LANE_D2,
+ PHY_LANE_D3,
+ PHY_LANE_MAX,
+};
+
+struct csid_reg_parms_t {
+/* MIPI CSID registers */
+ uint32_t csid_hw_version_addr;
+ uint32_t csid_core_ctrl_0_addr;
+ uint32_t csid_core_ctrl_1_addr;
+ uint32_t csid_rst_cmd_addr;
+ uint32_t csid_cid_lut_vc_0_addr;
+ uint32_t csid_cid_lut_vc_1_addr;
+ uint32_t csid_cid_lut_vc_2_addr;
+ uint32_t csid_cid_lut_vc_3_addr;
+ uint32_t csid_cid_n_cfg_addr;
+ uint32_t csid_irq_clear_cmd_addr;
+ uint32_t csid_irq_mask_addr;
+ uint32_t csid_irq_status_addr;
+ uint32_t csid_captured_unmapped_long_pkt_hdr_addr;
+ uint32_t csid_captured_mmaped_long_pkt_hdr_addr;
+ uint32_t csid_captured_short_pkt_addr;
+ uint32_t csid_captured_long_pkt_hdr_addr;
+ uint32_t csid_captured_long_pkt_ftr_addr;
+ uint32_t csid_pif_misr_dl0_addr;
+ uint32_t csid_pif_misr_dl1_addr;
+ uint32_t csid_pif_misr_dl2_addr;
+ uint32_t csid_pif_misr_dl3_addr;
+ uint32_t csid_stats_total_pkts_rcvd_addr;
+ uint32_t csid_stats_ecc_addr;
+ uint32_t csid_stats_crc_addr;
+ uint32_t csid_tg_ctrl_addr;
+ uint32_t csid_tg_vc_cfg_addr;
+ uint32_t csid_tg_dt_n_cfg_0_addr;
+ uint32_t csid_tg_dt_n_cfg_1_addr;
+ uint32_t csid_tg_dt_n_cfg_2_addr;
+ uint32_t csid_rst_done_irq_bitshift;
+ uint32_t csid_rst_stb_all;
+ uint32_t csid_dl_input_sel_shift;
+ uint32_t csid_phy_sel_shift;
+ uint32_t csid_version;
+ uint32_t csid_3p_ctrl_0_addr;
+ uint32_t csid_3p_pkt_hdr_addr;
+ uint32_t csid_test_bus_ctrl;
+ uint32_t csid_irq_mask_val;
+ uint32_t csid_err_lane_overflow_offset_2p;
+ uint32_t csid_err_lane_overflow_offset_3p;
+ uint32_t csid_phy_sel_shift_3p;
+};
+
+struct csid_ctrl_t {
+ struct csid_reg_parms_t csid_reg;
+ uint8_t *csid_lane_assign;
+};
+
+enum msm_csid_state_t {
+ CSID_POWER_UP,
+ CSID_POWER_DOWN,
+};
+
+struct csid_device {
+ struct platform_device *pdev;
+ struct msm_sd_subdev msm_sd;
+ struct resource *irq;
+ struct regulator *csi_vdd;
+ void __iomem *base;
+ struct mutex mutex;
+ struct completion reset_complete;
+ uint32_t hw_version;
+ uint32_t hw_dts_version;
+ enum msm_csid_state_t csid_state;
+ struct csid_ctrl_t *ctrl_reg;
+ struct regulator *reg_ptr;
+ size_t num_clk;
+ struct clk **csid_clk;
+ struct msm_cam_clk_info *csid_clk_info;
+ uint32_t csid_clk_index;
+ uint32_t csid_max_clk;
+ uint32_t csid_3p_enabled;
+ struct camera_vreg_t *csid_vreg;
+ struct regulator *csid_reg_ptr[MAX_REGULATOR];
+ int32_t regulator_count;
+ uint8_t is_testmode;
+ struct msm_camera_csid_testmode_parms testmode_params;
+ struct msm_camera_csid_params current_csid_params;
+ uint32_t csid_sof_debug;
+ uint32_t csid_lane_cnt;
+};
+
+#define VIDIOC_MSM_CSID_RELEASE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 12, struct v4l2_subdev*)
+#endif