summaryrefslogtreecommitdiff
path: root/drivers/media/video/tegra
diff options
context:
space:
mode:
authorMing Wong <miwong@nvidia.com>2012-11-16 17:34:31 -0800
committerJohn Sasinowski <jsasinowski@nvidia.com>2013-03-18 13:50:38 -0700
commit39402a58f139863c70eb18f8fa927471f36f228a (patch)
tree1a9ad9134f3ae04d9e7bbda4223b6c642dc8b1b4 /drivers/media/video/tegra
parentf8bb703231b580232217e0b25b5dcda83b3afe94 (diff)
media: video: tegra: add imx135 HDR sensor
Added driver support for imx135 HDR sensor. Bug 1250073 Change-Id: I291051453f24ddbb058ad195b1c2e1bf0c7f118e Signed-off-by: Frank Chen <frankc@nvidia.com> Signed-off-by: Ming Wong <miwong@nvidia.com> Reviewed-on: http://git-master/r/206759 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/media/video/tegra')
-rw-r--r--drivers/media/video/tegra/Kconfig7
-rw-r--r--drivers/media/video/tegra/Makefile1
-rw-r--r--drivers/media/video/tegra/imx135.c2401
3 files changed, 2409 insertions, 0 deletions
diff --git a/drivers/media/video/tegra/Kconfig b/drivers/media/video/tegra/Kconfig
index 8d59c895a6e4..79c403202348 100644
--- a/drivers/media/video/tegra/Kconfig
+++ b/drivers/media/video/tegra/Kconfig
@@ -68,6 +68,13 @@ config VIDEO_IMX091
This is a driver for the IMX091 camera sensor
for use with the tegra isp.
+config VIDEO_IMX135
+ tristate "IMX135 camera sensor support"
+ depends on I2C && ARCH_TEGRA
+ ---help---
+ This is a driver for the IMX135 camera sensor
+ for use with the tegra isp.
+
config VIDEO_IMX132
tristate "IMX132 camera sensor support"
depends on I2C && ARCH_TEGRA
diff --git a/drivers/media/video/tegra/Makefile b/drivers/media/video/tegra/Makefile
index d643b3a71d4b..92538d0a9c44 100644
--- a/drivers/media/video/tegra/Makefile
+++ b/drivers/media/video/tegra/Makefile
@@ -24,4 +24,5 @@ obj-$(CONFIG_VIDEO_SH532U) += sh532u.o
obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
obj-$(CONFIG_VIDEO_AD5816) += ad5816.o
obj-$(CONFIG_VIDEO_IMX091) += imx091.o
+obj-$(CONFIG_VIDEO_IMX135) += imx135.o
obj-$(CONFIG_VIDEO_IMX132) += imx132.o
diff --git a/drivers/media/video/tegra/imx135.c b/drivers/media/video/tegra/imx135.c
new file mode 100644
index 000000000000..ff287a219add
--- /dev/null
+++ b/drivers/media/video/tegra/imx135.c
@@ -0,0 +1,2401 @@
+/*
+ * imx135.c - imx135 sensor driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/regulator/consumer.h>
+#include <media/imx135.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+struct imx135_reg {
+ u16 addr;
+ u8 val;
+};
+
+struct imx135_info {
+ struct miscdevice miscdev_info;
+ int mode;
+ struct imx135_power_rail power;
+ struct imx135_sensordata sensor_data;
+ struct i2c_client *i2c_client;
+ struct imx135_platform_data *pdata;
+ struct mutex imx135_camera_lock;
+ struct dentry *debugdir;
+ atomic_t in_use;
+};
+
+#define IMX135_TABLE_WAIT_MS 0
+#define IMX135_TABLE_END 1
+#define IMX135_MAX_RETRIES 3
+#define IMX135_WAIT_MS 3
+
+#define IMX135_4208x3120_HDR
+
+#ifdef IMX135_4208x3120_HDR
+/* HDR */
+static struct imx135_reg mode_4208x3120[] = {
+ /* software standby */
+ {0x0100, 0x00},
+ /* global settings */
+ {0x0101, 0x00},
+ {0x0105, 0x01},
+ {0x0110, 0x00},
+ {0x0220, 0x01},
+ {0x3302, 0x11},
+ {0x3833, 0x20},
+ {0x3873, 0x03},
+ {0x3893, 0x00},
+ {0x3906, 0x08},
+ {0x3907, 0x01},
+ {0x391B, 0x00},
+ {0x3C09, 0x01},
+ {0x600A, 0x00},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x322C, 0x02},
+ {0x3409, 0x0C},
+ {0x340C, 0x2D},
+ {0x3411, 0x39},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x3511, 0x8F},
+ {0x364F, 0x2D},
+
+ /* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0305, 0x0C},
+ {0x0309, 0x05},
+ {0x030B, 0x01},
+ {0x030C, 0x01},
+ {0x030D, 0xC2},
+ {0x030E, 0x01},
+ {0x3A06, 0x11},
+
+ /* Mode Settings */
+ {0x0108, 0x03},
+ {0x0112, 0x0E},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x00},
+ {0x0391, 0x11},
+ {0x0392, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4082, 0x01},
+ {0x4083, 0x01},
+ {0x7006, 0x04},
+
+ /* Optinal/Function settings */
+ {0x0700, 0x00},
+ {0x3A63, 0x00},
+ {0x4100, 0xF8},
+ {0x4203, 0xFF},
+ {0x4344, 0x00},
+ {0x441C, 0x01},
+
+ /* Size Setting */
+ {0x0340, 0x0C},
+ {0x0341, 0xD0},
+ {0x0342, 0x11},
+ {0x0343, 0xDC},
+ {0x0344, 0x00},
+ {0x0345, 0x00},
+ {0x0346, 0x00},
+ {0x0347, 0x00},
+ {0x0348, 0x10},
+ {0x0349, 0x6F},
+ {0x034A, 0x0C},
+ {0x034B, 0x2F},
+ {0x034C, 0x10},
+ {0x034D, 0x70},
+ {0x034E, 0x0C},
+ {0x034F, 0x30},
+ {0x0350, 0x00},
+ {0x0351, 0x00},
+ {0x0352, 0x00},
+ {0x0353, 0x00},
+ {0x0354, 0x10},
+ {0x0355, 0x70},
+ {0x0356, 0x0C},
+ {0x0357, 0x30},
+ {0x301D, 0x30},
+ {0x3310, 0x10},
+ {0x3311, 0x70},
+ {0x3312, 0x0C},
+ {0x3313, 0x30},
+ {0x331C, 0x01},
+ {0x331D, 0x68},
+ {0x4084, 0x00},
+ {0x4085, 0x00},
+ {0x4086, 0x00},
+ {0x4087, 0x00},
+ {0x4400, 0x00},
+
+ /* Global Timing Setting */
+ {0x0830, 0x87},
+ {0x0831, 0x3F},
+ {0x0832, 0x67},
+ {0x0833, 0x3F},
+ {0x0834, 0x3F},
+ {0x0835, 0x4F},
+ {0x0836, 0xDF},
+ {0x0837, 0x47},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+
+ /* Integration Time Setting */
+ {0x0202, 0x0C},
+ {0x0203, 0xCC},
+
+ /* Gain Setting */
+ {0x0205, 0x00},
+ {0x020E, 0x01},
+ {0x020F, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+
+ /* HDR Setting */
+ {0x0230, 0x00},
+ {0x0231, 0x00},
+ {0x0233, 0x00},
+ {0x0234, 0x00},
+ {0x0235, 0x40},
+ {0x0238, 0x01},
+ {0x0239, 0x04},
+ {0x023B, 0x00},
+ {0x023C, 0x01},
+ {0x33B0, 0x10},
+ {0x33B1, 0x70},
+ {0x33B3, 0x01},
+ {0x33B4, 0x01},
+ {0x3800, 0x00},
+
+ {0x3A43, 0x01},
+ /* stream on */
+ {0x0100, 0x01},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+#else
+/* standard */
+static struct imx135_reg mode_4208x3120[] = {
+ /* software standby */
+ {0x0100, 0x00},
+ /* global settings */
+ {0x0101, 0x00},
+ {0x0105, 0x01},
+ {0x0110, 0x00},
+ {0x0220, 0x01},
+ {0x3302, 0x11},
+ {0x3833, 0x20},
+ {0x3893, 0x00},
+ {0x3906, 0x08},
+ {0x3907, 0x01},
+ {0x391B, 0x01},
+ {0x3C09, 0x01},
+ {0x600A, 0x00},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x322C, 0x02},
+ {0x3409, 0x0C},
+ {0x340C, 0x2D},
+ {0x3411, 0x39},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x3511, 0x8F},
+ {0x364F, 0x2D},
+
+ /* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0305, 0x0C},
+ {0x0309, 0x05},
+ {0x030B, 0x01},
+ {0x030C, 0x01},
+ {0x030D, 0xC2},
+ {0x030E, 0x01},
+ {0x3A06, 0x11},
+
+ /* Mode Settings */
+ {0x0108, 0x03},
+ {0x0112, 0x0A},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x00},
+ {0x0391, 0x11},
+ {0x0392, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4082, 0x01},
+ {0x4083, 0x01},
+ {0x7006, 0x04},
+
+ /* Optinal/Function settings */
+ {0x0700, 0x00},
+ {0x3A63, 0x00},
+ {0x4100, 0xF8},
+ {0x4203, 0xFF},
+ {0x4344, 0x00},
+ {0x441C, 0x01},
+
+ /* Size Setting */
+ {0x0340, 0x0C},
+ {0x0341, 0xD0},
+ {0x0342, 0x11},
+ {0x0343, 0xDC},
+ {0x0344, 0x00},
+ {0x0345, 0x00},
+ {0x0346, 0x00},
+ {0x0347, 0x00},
+ {0x0348, 0x10},
+ {0x0349, 0x6F},
+ {0x034A, 0x0C},
+ {0x034B, 0x2F},
+ {0x034C, 0x10},
+ {0x034D, 0x70},
+ {0x034E, 0x0C},
+ {0x034F, 0x30},
+ {0x0350, 0x00},
+ {0x0351, 0x00},
+ {0x0352, 0x00},
+ {0x0353, 0x00},
+ {0x0354, 0x10},
+ {0x0355, 0x70},
+ {0x0356, 0x0C},
+ {0x0357, 0x30},
+ {0x301D, 0x30},
+ {0x3310, 0x10},
+ {0x3311, 0x70},
+ {0x3312, 0x0C},
+ {0x3313, 0x30},
+ {0x331C, 0x01},
+ {0x331D, 0x68},
+ {0x4084, 0x00},
+ {0x4085, 0x00},
+ {0x4086, 0x00},
+ {0x4087, 0x00},
+ {0x4400, 0x00},
+
+ /* Global Timing Setting */
+ {0x0830, 0x87},
+ {0x0831, 0x3F},
+ {0x0832, 0x67},
+ {0x0833, 0x3F},
+ {0x0834, 0x3F},
+ {0x0835, 0x4F},
+ {0x0836, 0xDF},
+ {0x0837, 0x47},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+
+ /* Integration Time Setting */
+ {0x0202, 0x0C},
+ {0x0203, 0xCC},
+
+ /* Gain Setting */
+ {0x0205, 0x04},
+ {0x020E, 0x01},
+ {0x020F, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+
+ /* HDR Setting */
+ {0x0230, 0x00},
+ {0x0231, 0x00},
+ {0x0233, 0x00},
+ {0x0234, 0x00},
+ {0x0235, 0x40},
+ {0x0238, 0x01},
+ {0x0239, 0x04},
+ {0x023B, 0x00},
+ {0x023C, 0x01},
+ {0x33B0, 0x04},
+ {0x33B1, 0x00},
+ {0x33B3, 0x00},
+ {0x33B4, 0x01},
+ {0x3800, 0x00},
+
+ {0x3A43, 0x01},
+ /* stream on */
+ {0x0100, 0x01},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+#endif
+
+static struct imx135_reg mode_1920x1080[] = {
+ /* software standby */
+ {0x0100, 0x00},
+ /* global settings */
+ {0x0101, 0x00},
+ {0x0105, 0x01},
+ {0x0110, 0x00},
+ {0x0220, 0x01},
+ {0x3302, 0x11},
+ {0x3833, 0x20},
+ {0x3893, 0x00},
+ {0x3906, 0x08},
+ {0x3907, 0x01},
+ {0x391B, 0x01},
+ {0x3C09, 0x01},
+ {0x600A, 0x00},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x322C, 0x02},
+ {0x3409, 0x0C},
+ {0x340C, 0x2D},
+ {0x3411, 0x39},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x3511, 0x8F},
+ {0x364F, 0x2D},
+
+ /* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0305, 0x0C},
+ {0x0309, 0x05},
+ {0x030B, 0x02},
+ {0x030C, 0x01},
+ {0x030D, 0xC2},
+ {0x030E, 0x01},
+ {0x3A06, 0x12},
+
+ /* Mode Settings */
+ {0x0108, 0x03},
+ {0x0112, 0x0A},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x01},
+ {0x0391, 0x22},
+ {0x0392, 0x00},
+ {0x0401, 0x02},
+ {0x0404, 0x00},
+ {0x0405, 0x11},
+ {0x4082, 0x00},
+ {0x4083, 0x00},
+ {0x7006, 0x04},
+
+ /* Optinal/Function settings */
+ {0x0700, 0x00},
+ {0x3A63, 0x00},
+ {0x4100, 0xF8},
+ {0x4203, 0xFF},
+ {0x4344, 0x00},
+ {0x441C, 0x01},
+
+ /* Size Setting */
+ {0x0340, 0x0A},
+ {0x0341, 0x40},
+ {0x0342, 0x11},
+ {0x0343, 0xDC},
+ {0x0344, 0x00},
+ {0x0345, 0x40},
+ {0x0346, 0x01},
+ {0x0347, 0x9C},
+ {0x0348, 0x10},
+ {0x0349, 0x2F},
+ {0x034A, 0x0A},
+ {0x034B, 0x93},
+ {0x034C, 0x07},
+ {0x034D, 0x80},
+ {0x034E, 0x04},
+ {0x034F, 0x38},
+ {0x0350, 0x00},
+ {0x0351, 0x00},
+ {0x0352, 0x00},
+ {0x0353, 0x00},
+ {0x0354, 0x07},
+ {0x0355, 0xF8},
+ {0x0356, 0x04},
+ {0x0357, 0x7C},
+ {0x301D, 0x30},
+ {0x3310, 0x07},
+ {0x3311, 0x80},
+ {0x3312, 0x04},
+ {0x3313, 0x38},
+ {0x331C, 0x00},
+ {0x331D, 0xD2},
+ {0x4084, 0x07},
+ {0x4085, 0x80},
+ {0x4086, 0x04},
+ {0x4087, 0x38},
+ {0x4400, 0x00},
+
+ /* Global Timing Setting */
+ {0x0830, 0x67},
+ {0x0831, 0x27},
+ {0x0832, 0x47},
+ {0x0833, 0x27},
+ {0x0834, 0x27},
+ {0x0835, 0x1F},
+ {0x0836, 0x87},
+ {0x0837, 0x2F},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+
+ /* Integration Time Setting */
+ {0x0202, 0x0A},
+ {0x0203, 0x3C},
+
+ /* Gain Setting */
+ {0x0205, 0x00},
+ {0x020E, 0x01},
+ {0x020F, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+
+ /* HDR Setting */
+ {0x0230, 0x00},
+ {0x0231, 0x00},
+ {0x0233, 0x00},
+ {0x0234, 0x00},
+ {0x0235, 0x40},
+ {0x0238, 0x01},
+ {0x0239, 0x04},
+ {0x023B, 0x00},
+ {0x023C, 0x01},
+ {0x33B0, 0x04},
+ {0x33B1, 0x00},
+ {0x33B3, 0x00},
+ {0x33B4, 0x01},
+ {0x3800, 0x00},
+
+ {0x3A43, 0x01},
+ /* stream on */
+ {0x0100, 0x01},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+
+#ifdef IMX135_1280x720_90_FPS
+/* 720p 90fps */
+static struct imx135_reg mode_1280x720[] = {
+ /* software standby */
+ {0x0100, 0x00},
+ /* global settings */
+ {0x0101, 0x00},
+ {0x0105, 0x01},
+ {0x0110, 0x00},
+ {0x0220, 0x01},
+ {0x3302, 0x11},
+ {0x3833, 0x20},
+ {0x3893, 0x00},
+ {0x3906, 0x08},
+ {0x3907, 0x01},
+ {0x391B, 0x01},
+ {0x3C09, 0x01},
+ {0x600A, 0x00},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x322C, 0x02},
+ {0x3409, 0x0C},
+ {0x340C, 0x2D},
+ {0x3411, 0x39},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x3511, 0x8F},
+ {0x364F, 0x2D},
+
+ /* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0305, 0x0C},
+ {0x0309, 0x05},
+ {0x030B, 0x02},
+ {0x030C, 0x01},
+ {0x030D, 0xC2},
+ {0x030E, 0x01},
+ {0x3A06, 0x12},
+
+ /* Mode Settings */
+ {0x0108, 0x03},
+ {0x0112, 0x0A},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x01},
+ {0x0391, 0x22},
+ {0x0392, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4082, 0x01},
+ {0x4083, 0x01},
+ {0x7006, 0x04},
+
+ /* Optinal/Function settings */
+ {0x0700, 0x00},
+ {0x3A63, 0x00},
+ {0x4100, 0xF8},
+ {0x4203, 0xFF},
+ {0x4344, 0x00},
+ {0x441C, 0x01},
+
+ /* Size Setting */
+ {0x0340, 0x03},
+ {0x0341, 0x6A},
+ {0x0342, 0x11},
+ {0x0343, 0xDC},
+ {0x0344, 0x03},
+ {0x0345, 0x38},
+ {0x0346, 0x03},
+ {0x0347, 0x48},
+ {0x0348, 0x0D},
+ {0x0349, 0x37},
+ {0x034A, 0x08},
+ {0x034B, 0xE7},
+ {0x034C, 0x05},
+ {0x034D, 0x00},
+ {0x034E, 0x02},
+ {0x034F, 0xD0},
+ {0x0350, 0x00},
+ {0x0351, 0x00},
+ {0x0352, 0x00},
+ {0x0353, 0x00},
+ {0x0354, 0x05},
+ {0x0355, 0x00},
+ {0x0356, 0x02},
+ {0x0357, 0xD0},
+ {0x301D, 0x30},
+ {0x3310, 0x05},
+ {0x3311, 0x00},
+ {0x3312, 0x02},
+ {0x3313, 0xD0},
+ {0x331C, 0x00},
+ {0x331D, 0x10},
+ {0x4084, 0x00},
+ {0x4085, 0x00},
+ {0x4086, 0x00},
+ {0x4087, 0x00},
+ {0x4400, 0x00},
+
+ /* Global Timing Setting */
+ {0x0830, 0x67},
+ {0x0831, 0x27},
+ {0x0832, 0x47},
+ {0x0833, 0x27},
+ {0x0834, 0x27},
+ {0x0835, 0x1F},
+ {0x0836, 0x87},
+ {0x0837, 0x2F},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+
+ /* Integration Time Setting */
+ {0x0202, 0x03},
+ {0x0203, 0x66},
+
+ /* Gain Setting */
+ {0x0205, 0x00},
+ {0x020E, 0x01},
+ {0x020F, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+
+ /* HDR Setting */
+ {0x0230, 0x00},
+ {0x0231, 0x00},
+ {0x0233, 0x00},
+ {0x0234, 0x00},
+ {0x0235, 0x40},
+ {0x0238, 0x01},
+ {0x0239, 0x04},
+ {0x023B, 0x00},
+ {0x023C, 0x01},
+ {0x33B0, 0x04},
+ {0x33B1, 0x00},
+ {0x33B3, 0x00},
+ {0x33B4, 0x01},
+ {0x3800, 0x00},
+
+ {0x3A43, 0x01},
+ /* stream on */
+ {0x0100, 0x01},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+#else
+/* 720p 30fps */
+static struct imx135_reg mode_1280x720[] = {
+ /* software standby */
+ {0x0100, 0x00},
+ /* global settings */
+ {0x0101, 0x00},
+ {0x0105, 0x01},
+ {0x0110, 0x00},
+ {0x0220, 0x01},
+ {0x3302, 0x11},
+ {0x3833, 0x20},
+ {0x3893, 0x00},
+ {0x3906, 0x08},
+ {0x3907, 0x01},
+ {0x391B, 0x01},
+ {0x3C09, 0x01},
+ {0x600A, 0x00},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x322C, 0x02},
+ {0x3409, 0x0C},
+ {0x340C, 0x2D},
+ {0x3411, 0x39},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x3511, 0x8F},
+ {0x364F, 0x2D},
+
+ /* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0305, 0x0C},
+ {0x0309, 0x05},
+ {0x030B, 0x02},
+ {0x030C, 0x01},
+ {0x030D, 0xC2},
+ {0x030E, 0x01},
+ {0x3A06, 0x12},
+
+ /* Mode Settings */
+ {0x0108, 0x03},
+ {0x0112, 0x0A},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x01},
+ {0x0391, 0x22},
+ {0x0392, 0x00},
+ {0x0401, 0x02},
+ {0x0404, 0x00},
+ {0x0405, 0x1A},
+ {0x4082, 0x00},
+ {0x4083, 0x00},
+ {0x7006, 0x04},
+
+ /* Optinal/Function settings */
+ {0x0700, 0x00},
+ {0x3A63, 0x00},
+ {0x4100, 0xF8},
+ {0x4203, 0xFF},
+ {0x4344, 0x00},
+ {0x441C, 0x01},
+
+ /* Size Setting */
+ {0x0340, 0x0A},
+ {0x0341, 0x40},
+ {0x0342, 0x11},
+ {0x0343, 0xDC},
+ {0x0344, 0x00},
+ {0x0345, 0x18},
+ {0x0346, 0x01},
+ {0x0347, 0x88},
+ {0x0348, 0x10},
+ {0x0349, 0x57},
+ {0x034A, 0x0A},
+ {0x034B, 0xAB},
+ {0x034C, 0x05},
+ {0x034D, 0x00},
+ {0x034E, 0x02},
+ {0x034F, 0xD0},
+ {0x0350, 0x00},
+ {0x0351, 0x00},
+ {0x0352, 0x00},
+ {0x0353, 0x00},
+ {0x0354, 0x08},
+ {0x0355, 0x20},
+ {0x0356, 0x04},
+ {0x0357, 0x92},
+ {0x301D, 0x30},
+ {0x3310, 0x05},
+ {0x3311, 0x00},
+ {0x3312, 0x02},
+ {0x3313, 0xD0},
+ {0x331C, 0x02},
+ {0x331D, 0x18},
+ {0x4084, 0x05},
+ {0x4085, 0x00},
+ {0x4086, 0x02},
+ {0x4087, 0xD0},
+ {0x4400, 0x00},
+
+ /* Global Timing Setting */
+ {0x0830, 0x67},
+ {0x0831, 0x27},
+ {0x0832, 0x47},
+ {0x0833, 0x27},
+ {0x0834, 0x27},
+ {0x0835, 0x1F},
+ {0x0836, 0x87},
+ {0x0837, 0x2F},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+
+ /* Integration Time Setting */
+ {0x0202, 0x0A},
+ {0x0203, 0x3C},
+
+ /* Gain Setting */
+ {0x0205, 0x00},
+ {0x020E, 0x01},
+ {0x020F, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+
+ /* HDR Setting */
+ {0x0230, 0x00},
+ {0x0231, 0x00},
+ {0x0233, 0x00},
+ {0x0234, 0x00},
+ {0x0235, 0x40},
+ {0x0238, 0x01},
+ {0x0239, 0x04},
+ {0x023B, 0x00},
+ {0x023C, 0x01},
+ {0x33B0, 0x04},
+ {0x33B1, 0x00},
+ {0x33B3, 0x00},
+ {0x33B4, 0x01},
+ {0x3800, 0x00},
+
+ {0x3A43, 0x01},
+ /* stream on */
+ {0x0100, 0x01},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+#endif
+
+static struct imx135_reg mode_2616x1472[] = {
+ /* software standby */
+ {0x0100, 0x00},
+ /* global settings */
+ {0x0101, 0x00},
+ {0x0105, 0x01},
+ {0x0110, 0x00},
+ {0x0220, 0x01},
+ {0x3302, 0x11},
+ {0x3833, 0x20},
+ {0x3873, 0x03},
+ {0x3893, 0x00},
+ {0x3906, 0x08},
+ {0x3907, 0x01},
+ {0x391B, 0x00},
+ {0x3C09, 0x01},
+ {0x600A, 0x00},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x322C, 0x02},
+ {0x3409, 0x0C},
+ {0x340C, 0x2D},
+ {0x3411, 0x39},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x3511, 0x8F},
+ {0x364F, 0x2D},
+
+ /* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0305, 0x0C},
+ {0x0309, 0x05},
+ {0x030B, 0x01},
+ {0x030C, 0x01},
+ {0x030D, 0xC2},
+ {0x030E, 0x01},
+ {0x3A06, 0x11},
+
+ /* Mode Settings */
+ {0x0108, 0x03},
+ {0x0112, 0x0E},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x00},
+ {0x0391, 0x11},
+ {0x0392, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4082, 0x01},
+ {0x4083, 0x01},
+ {0x7006, 0x04},
+
+ /* Optinal/Function settings */
+ {0x0700, 0x00},
+ {0x3A63, 0x00},
+ {0x4100, 0xF8},
+ {0x4203, 0xFF},
+ {0x4344, 0x00},
+ {0x441C, 0x01},
+
+ /* Size Setting */
+ {0x0340, 0x0A},
+ {0x0341, 0x40},
+ {0x0342, 0x11},
+ {0x0343, 0xDC},
+ {0x0344, 0x03},
+ {0x0345, 0x1C},
+ {0x0346, 0x03},
+ {0x0347, 0x38},
+ {0x0348, 0x0D},
+ {0x0349, 0x53},
+ {0x034A, 0x08},
+ {0x034B, 0xF7},
+ {0x034C, 0x0A},
+ {0x034D, 0x38},
+ {0x034E, 0x05},
+ {0x034F, 0xC0},
+ {0x0350, 0x00},
+ {0x0351, 0x00},
+ {0x0352, 0x00},
+ {0x0353, 0x00},
+ {0x0354, 0x0A},
+ {0x0355, 0x38},
+ {0x0356, 0x05},
+ {0x0357, 0xC0},
+ {0x301D, 0x30},
+ {0x3310, 0x0A},
+ {0x3311, 0x38},
+ {0x3312, 0x05},
+ {0x3313, 0xC0},
+ {0x331C, 0x08},
+ {0x331D, 0xD4},
+ {0x4084, 0x00},
+ {0x4085, 0x00},
+ {0x4086, 0x00},
+ {0x4087, 0x00},
+ {0x4400, 0x00},
+
+ /* Global Timing Setting */
+ {0x0830, 0x87},
+ {0x0831, 0x3F},
+ {0x0832, 0x67},
+ {0x0833, 0x3F},
+ {0x0834, 0x3F},
+ {0x0835, 0x4F},
+ {0x0836, 0xDF},
+ {0x0837, 0x47},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+
+ /* Integration Time Setting */
+ {0x0202, 0x0A},
+ {0x0203, 0x3C},
+
+ /* Gain Setting */
+ {0x0205, 0x00},
+ {0x020E, 0x01},
+ {0x020F, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+
+ /* HDR Setting */
+ {0x0230, 0x00},
+ {0x0231, 0x00},
+ {0x0233, 0x00},
+ {0x0234, 0x00},
+ {0x0235, 0x40},
+ {0x0238, 0x01},
+ {0x0239, 0x04},
+ {0x023B, 0x00},
+ {0x023C, 0x01},
+ {0x33B0, 0x0A},
+ {0x33B1, 0x38},
+ {0x33B3, 0x01},
+ {0x33B4, 0x01},
+ {0x3800, 0x00},
+
+ {0x3A43, 0x01},
+ /* stream on */
+ {0x0100, 0x01},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+
+static struct imx135_reg mode_3896x2192[] = {
+ /* software standby */
+ {0x0100, 0x00},
+ /* global settings */
+ {0x0101, 0x00},
+ {0x0105, 0x01},
+ {0x0110, 0x00},
+ {0x0220, 0x01},
+ {0x3302, 0x11},
+ {0x3833, 0x20},
+ {0x3873, 0x03},
+ {0x3893, 0x00},
+ {0x3906, 0x08},
+ {0x3907, 0x01},
+ {0x391B, 0x00},
+ {0x3C09, 0x01},
+ {0x600A, 0x00},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x322C, 0x02},
+ {0x3409, 0x0C},
+ {0x340C, 0x2D},
+ {0x3411, 0x39},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x3511, 0x8F},
+ {0x364F, 0x2D},
+
+ /* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0305, 0x0C},
+ {0x0309, 0x05},
+ {0x030B, 0x01},
+ {0x030C, 0x01},
+ {0x030D, 0xC2},
+ {0x030E, 0x01},
+ {0x3A06, 0x11},
+
+ /* Mode Settings */
+ {0x0108, 0x03},
+ {0x0112, 0x0E},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x00},
+ {0x0391, 0x11},
+ {0x0392, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4082, 0x01},
+ {0x4083, 0x01},
+ {0x7006, 0x04},
+
+ /* Optinal/Function settings */
+ {0x0700, 0x00},
+ {0x3A63, 0x00},
+ {0x4100, 0xF8},
+ {0x4203, 0xFF},
+ {0x4344, 0x00},
+ {0x441C, 0x01},
+
+ /* Size Setting */
+ {0x0340, 0x0A},
+ {0x0341, 0x40},
+ {0x0342, 0x11},
+ {0x0343, 0xDC},
+ {0x0344, 0x00},
+ {0x0345, 0x9C},
+ {0x0346, 0x01},
+ {0x0347, 0xD0},
+ {0x0348, 0x0F},
+ {0x0349, 0xD3},
+ {0x034A, 0x0A},
+ {0x034B, 0x5F},
+ {0x034C, 0x0F},
+ {0x034D, 0x38},
+ {0x034E, 0x08},
+ {0x034F, 0x90},
+ {0x0350, 0x00},
+ {0x0351, 0x00},
+ {0x0352, 0x00},
+ {0x0353, 0x00},
+ {0x0354, 0x0F},
+ {0x0355, 0x38},
+ {0x0356, 0x08},
+ {0x0357, 0x90},
+ {0x301D, 0x30},
+ {0x3310, 0x0F},
+ {0x3311, 0x38},
+ {0x3312, 0x08},
+ {0x3313, 0x90},
+ {0x331C, 0x0F},
+ {0x331D, 0x32},
+ {0x4084, 0x00},
+ {0x4085, 0x00},
+ {0x4086, 0x00},
+ {0x4087, 0x00},
+ {0x4400, 0x00},
+
+ /* Global Timing Setting */
+ {0x0830, 0x87},
+ {0x0831, 0x3F},
+ {0x0832, 0x67},
+ {0x0833, 0x3F},
+ {0x0834, 0x3F},
+ {0x0835, 0x4F},
+ {0x0836, 0xDF},
+ {0x0837, 0x47},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+
+ /* Integration Time Setting */
+ {0x0202, 0x0A},
+ {0x0203, 0x3C},
+
+ /* Gain Setting */
+ {0x0205, 0x00},
+ {0x020E, 0x01},
+ {0x020F, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+
+ /* HDR Setting */
+ {0x0230, 0x00},
+ {0x0231, 0x00},
+ {0x0233, 0x00},
+ {0x0234, 0x00},
+ {0x0235, 0x40},
+ {0x0238, 0x01},
+ {0x0239, 0x04},
+ {0x023B, 0x00},
+ {0x023C, 0x01},
+ {0x33B0, 0x0F},
+ {0x33B1, 0x38},
+ {0x33B3, 0x01},
+ {0x33B4, 0x01},
+ {0x3800, 0x00},
+
+ {0x3A43, 0x01},
+ /* stream on */
+ {0x0100, 0x01},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+
+static struct imx135_reg mode_quality_hdr[] = {
+ /* defect correction */
+ {0x380A, 0x00},
+ {0x380B, 0x00},
+ {0x4103, 0x00},
+ /* color artifact */
+ {0x4243, 0x9A},
+ {0x4330, 0x01},
+ {0x4331, 0x90},
+ {0x4332, 0x02},
+ {0x4333, 0x58},
+ {0x4334, 0x03},
+ {0x4335, 0x20},
+ {0x4336, 0x03},
+ {0x4337, 0x84},
+ {0x433C, 0x01},
+ {0x4340, 0x02},
+ {0x4341, 0x58},
+ {0x4342, 0x03},
+ {0x4343, 0x52},
+ /* moire reduction */
+ {0x4364, 0x0B},
+ {0x4368, 0x00},
+ {0x4369, 0x0F},
+ {0x436A, 0x03},
+ {0x436B, 0xA8},
+ {0x436C, 0x00},
+ {0x436D, 0x00},
+ {0x436E, 0x00},
+ {0x436F, 0x06},
+ /* CNR parameter */
+ {0x4281, 0x21},
+ {0x4282, 0x18},
+ {0x4283, 0x04},
+ {0x4284, 0x08},
+ {0x4287, 0x7F},
+ {0x4288, 0x08},
+ {0x428B, 0x7F},
+ {0x428C, 0x08},
+ {0x428F, 0x7F},
+ {0x4297, 0x00},
+ {0x4298, 0x7E},
+ {0x4299, 0x7E},
+ {0x429A, 0x7E},
+ {0x42A4, 0xFB},
+ {0x42A5, 0x7E},
+ {0x42A6, 0xDF},
+ {0x42A7, 0xB7},
+ {0x42AF, 0x03},
+
+ /* ARNR Parameter Settings */
+ {0x4207, 0x03},
+ {0x4216, 0x08},
+ {0x4217, 0x08},
+
+ /* DLC parameter */
+ {0x4218, 0x00},
+ {0x421B, 0x20},
+ {0x421F, 0x04},
+ {0x4222, 0x02},
+ {0x4223, 0x22},
+ {0x422E, 0x54},
+ {0x422F, 0xFB},
+ {0x4230, 0xFF},
+ {0x4231, 0xFE},
+ {0x4232, 0xFF},
+ {0x4235, 0x58},
+ {0x4236, 0xF7},
+ {0x4237, 0xFD},
+ {0x4239, 0x4E},
+ {0x423A, 0xFC},
+ {0x423B, 0xFD},
+
+ /* HDR Setting */
+ {0x4300, 0x00},
+ {0x4316, 0x12},
+ {0x4317, 0x22},
+ {0x4318, 0x00},
+ {0x4319, 0x00},
+ {0x431A, 0x00},
+ {0x4324, 0x03},
+ {0x4325, 0x20},
+ {0x4326, 0x03},
+ {0x4327, 0x84},
+ {0x4328, 0x03},
+ {0x4329, 0x20},
+ {0x432A, 0x03},
+ {0x432B, 0x20},
+ {0x432C, 0x01},
+ {0x432D, 0x01},
+ {0x4338, 0x02},
+ {0x4339, 0x00},
+ {0x433A, 0x00},
+ {0x433B, 0x02},
+ {0x435A, 0x03},
+ {0x435B, 0x84},
+ {0x435E, 0x01},
+ {0x435F, 0xFF},
+ {0x4360, 0x01},
+ {0x4361, 0xF4},
+ {0x4362, 0x03},
+ {0x4363, 0x84},
+ {0x437B, 0x01},
+ {0x4401, 0x3F},
+ {0x4402, 0xFF},
+ {0x4404, 0x13},
+ {0x4405, 0x26},
+ {0x4406, 0x07},
+ {0x4408, 0x20},
+ {0x4409, 0xE5},
+ {0x440A, 0xFB},
+ {0x440C, 0xF6},
+ {0x440D, 0xEA},
+ {0x440E, 0x20},
+ {0x4410, 0x00},
+ {0x4411, 0x00},
+ {0x4412, 0x3F},
+ {0x4413, 0xFF},
+ {0x4414, 0x1F},
+ {0x4415, 0xFF},
+ {0x4416, 0x20},
+ {0x4417, 0x00},
+ {0x4418, 0x1F},
+ {0x4419, 0xFF},
+ {0x441A, 0x20},
+ {0x441B, 0x00},
+ {0x441D, 0x40},
+ {0x441E, 0x1E},
+ {0x441F, 0x38},
+ {0x4420, 0x01},
+ {0x4444, 0x00},
+ {0x4445, 0x00},
+ {0x4446, 0x1D},
+ {0x4447, 0xF9},
+ {0x4452, 0x00},
+ {0x4453, 0xA0},
+ {0x4454, 0x08},
+ {0x4455, 0x00},
+ {0x4456, 0x0F},
+ {0x4457, 0xFF},
+ {0x4458, 0x18},
+ {0x4459, 0x18},
+ {0x445A, 0x3F},
+ {0x445B, 0x3A},
+ {0x445C, 0x00},
+ {0x445D, 0x28},
+ {0x445E, 0x01},
+ {0x445F, 0x90},
+ {0x4460, 0x00},
+ {0x4461, 0x60},
+ {0x4462, 0x00},
+ {0x4463, 0x00},
+ {0x4464, 0x00},
+ {0x4465, 0x00},
+ {0x446C, 0x01},
+ {0x446D, 0x00},
+ {0x446E, 0x00},
+
+ /* LSC setting */
+ {0x452A, 0x02},
+
+ /* White balance */
+ {0x0712, 0x01},
+ {0x0713, 0x00},
+ {0x0714, 0x01},
+ {0x0715, 0x00},
+ {0x0716, 0x01},
+ {0x0717, 0x00},
+ {0x0718, 0x01},
+ {0x0719, 0x00},
+
+ /* Shading */
+ {0x4500, 0x1F},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+
+static struct imx135_reg mode_quality[] = {
+ /* defect correction */
+ {0x380A, 0x00},
+ {0x380B, 0x00},
+ {0x4103, 0x00},
+ /* color artifact */
+ {0x4243, 0x9A},
+ {0x4330, 0x01},
+ {0x4331, 0x90},
+ {0x4332, 0x02},
+ {0x4333, 0x58},
+ {0x4334, 0x03},
+ {0x4335, 0x20},
+ {0x4336, 0x03},
+ {0x4337, 0x84},
+ {0x433C, 0x01},
+ {0x4340, 0x02},
+ {0x4341, 0x58},
+ {0x4342, 0x03},
+ {0x4343, 0x52},
+ /* moire reduction */
+ {0x4364, 0x0B},
+ {0x4368, 0x00},
+ {0x4369, 0x0F},
+ {0x436A, 0x03},
+ {0x436B, 0xA8},
+ {0x436C, 0x00},
+ {0x436D, 0x00},
+ {0x436E, 0x00},
+ {0x436F, 0x06},
+ /* CNR parameter */
+ {0x4281, 0x21},
+ {0x4282, 0x18},
+ {0x4283, 0x04},
+ {0x4284, 0x08},
+ {0x4287, 0x7F},
+ {0x4288, 0x08},
+ {0x428B, 0x7F},
+ {0x428C, 0x08},
+ {0x428F, 0x7F},
+ {0x4297, 0x00},
+ {0x4298, 0x7E},
+ {0x4299, 0x7E},
+ {0x429A, 0x7E},
+ {0x42A4, 0xFB},
+ {0x42A5, 0x7E},
+ {0x42A6, 0xDF},
+ {0x42A7, 0xB7},
+ {0x42AF, 0x03},
+
+ /* ARNR Parameter Settings */
+ {0x4207, 0x03},
+ {0x4216, 0x08},
+ {0x4217, 0x08},
+
+ /* DLC parameter */
+ {0x4218, 0x00},
+ {0x421B, 0x20},
+ {0x421F, 0x04},
+ {0x4222, 0x02},
+ {0x4223, 0x22},
+ {0x422E, 0x54},
+ {0x422F, 0xFB},
+ {0x4230, 0xFF},
+ {0x4231, 0xFE},
+ {0x4232, 0xFF},
+ {0x4235, 0x58},
+ {0x4236, 0xF7},
+ {0x4237, 0xFD},
+ {0x4239, 0x4E},
+ {0x423A, 0xFC},
+ {0x423B, 0xFD},
+
+ /* HDR Setting */
+ {0x4300, 0x00},
+ {0x4316, 0x12},
+ {0x4317, 0x22},
+ {0x4318, 0x00},
+ {0x4319, 0x00},
+ {0x431A, 0x00},
+ {0x4324, 0x03},
+ {0x4325, 0x20},
+ {0x4326, 0x03},
+ {0x4327, 0x84},
+ {0x4328, 0x03},
+ {0x4329, 0x20},
+ {0x432A, 0x03},
+ {0x432B, 0x20},
+ {0x432C, 0x01},
+ {0x432D, 0x01},
+ {0x4338, 0x02},
+ {0x4339, 0x00},
+ {0x433A, 0x00},
+ {0x433B, 0x02},
+ {0x435A, 0x03},
+ {0x435B, 0x84},
+ {0x435E, 0x01},
+ {0x435F, 0xFF},
+ {0x4360, 0x01},
+ {0x4361, 0xF4},
+ {0x4362, 0x03},
+ {0x4363, 0x84},
+ {0x437B, 0x01},
+ {0x4401, 0x3F},
+ {0x4402, 0xFF},
+ {0x4404, 0x13},
+ {0x4405, 0x26},
+ {0x4406, 0x07},
+ {0x4408, 0x20},
+ {0x4409, 0xE5},
+ {0x440A, 0xFB},
+ {0x440C, 0xF6},
+ {0x440D, 0xEA},
+ {0x440E, 0x20},
+ {0x4410, 0x00},
+ {0x4411, 0x00},
+ {0x4412, 0x3F},
+ {0x4413, 0xFF},
+ {0x4414, 0x1F},
+ {0x4415, 0xFF},
+ {0x4416, 0x20},
+ {0x4417, 0x00},
+ {0x4418, 0x1F},
+ {0x4419, 0xFF},
+ {0x441A, 0x20},
+ {0x441B, 0x00},
+ {0x441D, 0x40},
+ {0x441E, 0x1E},
+ {0x441F, 0x38},
+ {0x4420, 0x01},
+ {0x4444, 0x00},
+ {0x4445, 0x00},
+ {0x4446, 0x1D},
+ {0x4447, 0xF9},
+ {0x4452, 0x00},
+ {0x4453, 0xA0},
+ {0x4454, 0x08},
+ {0x4455, 0x00},
+ {0x4456, 0x0F},
+ {0x4457, 0xFF},
+ {0x4458, 0x18},
+ {0x4459, 0x18},
+ {0x445A, 0x3F},
+ {0x445B, 0x3A},
+ {0x445C, 0x00},
+ {0x445D, 0x28},
+ {0x445E, 0x01},
+ {0x445F, 0x90},
+ {0x4460, 0x00},
+ {0x4461, 0x60},
+ {0x4462, 0x00},
+ {0x4463, 0x00},
+ {0x4464, 0x00},
+ {0x4465, 0x00},
+ {0x446C, 0x01},
+ {0x446D, 0x00},
+ {0x446E, 0x00},
+
+ /* LSC setting */
+ {0x452A, 0x02},
+
+ /* White balance */
+ {0x0712, 0x01},
+ {0x0713, 0x00},
+ {0x0714, 0x01},
+ {0x0715, 0x00},
+ {0x0716, 0x01},
+ {0x0717, 0x00},
+ {0x0718, 0x01},
+ {0x0719, 0x00},
+
+ /* Shading */
+ {0x4500, 0x1F},
+
+ {IMX135_TABLE_WAIT_MS, IMX135_WAIT_MS},
+ {IMX135_TABLE_END, 0x00}
+};
+
+enum {
+ IMX135_MODE_4208X3120,
+ IMX135_MODE_1920X1080,
+ IMX135_MODE_1280X720,
+ IMX135_MODE_2616X1472,
+ IMX135_MODE_3896X2192,
+ IMX135_MODE_QUALITY_HDR,
+ IMX135_MODE_QUALITY,
+};
+
+static struct imx135_reg *mode_table[] = {
+ [IMX135_MODE_4208X3120] = mode_4208x3120,
+ [IMX135_MODE_1920X1080] = mode_1920x1080,
+ [IMX135_MODE_1280X720] = mode_1280x720,
+ [IMX135_MODE_2616X1472] = mode_2616x1472,
+ [IMX135_MODE_3896X2192] = mode_3896x2192,
+ [IMX135_MODE_QUALITY_HDR] = mode_quality_hdr,
+ [IMX135_MODE_QUALITY] = mode_quality,
+};
+
+static inline void
+msleep_range(unsigned int delay_base)
+{
+ usleep_range(delay_base*1000, delay_base*1000+500);
+}
+
+static inline void
+imx135_get_frame_length_regs(struct imx135_reg *regs, u32 frame_length)
+{
+ regs->addr = 0x0340;
+ regs->val = (frame_length >> 8) & 0xff;
+ (regs + 1)->addr = 0x0341;
+ (regs + 1)->val = (frame_length) & 0xff;
+}
+
+static inline void
+imx135_get_coarse_time_regs(struct imx135_reg *regs, u32 coarse_time)
+{
+ regs->addr = 0x202;
+ regs->val = (coarse_time >> 8) & 0xff;
+ (regs + 1)->addr = 0x203;
+ (regs + 1)->val = (coarse_time) & 0xff;
+}
+
+static inline void
+imx135_get_coarse_time_short_regs(struct imx135_reg *regs, u32 coarse_time)
+{
+ regs->addr = 0x230;
+ regs->val = (coarse_time >> 8) & 0xff;
+ (regs + 1)->addr = 0x231;
+ (regs + 1)->val = (coarse_time) & 0xff;
+}
+
+static inline void
+imx135_get_gain_reg(struct imx135_reg *regs, u16 gain)
+{
+ regs->addr = 0x205;
+ regs->val = gain;
+}
+
+static int
+imx135_read_reg(struct i2c_client *client, u16 addr, u8 *val)
+{
+ int err;
+ struct i2c_msg msg[2];
+ unsigned char data[3];
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 2;
+ msg[0].buf = data;
+
+ /* high byte goes out first */
+ data[0] = (u8) (addr >> 8);
+ data[1] = (u8) (addr & 0xff);
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = data + 2;
+
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err != 2)
+ return -EINVAL;
+
+ *val = data[2];
+ return 0;
+}
+
+static int
+imx135_write_reg(struct i2c_client *client, u16 addr, u8 val)
+{
+ int err;
+ struct i2c_msg msg;
+ unsigned char data[3];
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ data[0] = (u8) (addr >> 8);
+ data[1] = (u8) (addr & 0xff);
+ data[2] = (u8) (val & 0xff);
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = 3;
+ msg.buf = data;
+
+ err = i2c_transfer(client->adapter, &msg, 1);
+ if (err == 1)
+ return 0;
+
+ pr_err("%s:i2c write failed, %x = %x\n",
+ __func__, addr, val);
+
+ return err;
+}
+
+static int
+imx135_write_table(struct i2c_client *client,
+ const struct imx135_reg table[],
+ const struct imx135_reg override_list[],
+ int num_override_regs)
+{
+ int err;
+ const struct imx135_reg *next;
+ int i;
+ u16 val;
+
+ for (next = table; next->addr != IMX135_TABLE_END; next++) {
+ if (next->addr == IMX135_TABLE_WAIT_MS) {
+ msleep_range(next->val);
+ continue;
+ }
+
+ val = next->val;
+
+ /* When an override list is passed in, replace the reg */
+ /* value to write if the reg is in the list */
+ if (override_list) {
+ for (i = 0; i < num_override_regs; i++) {
+ if (next->addr == override_list[i].addr) {
+ val = override_list[i].val;
+ break;
+ }
+ }
+ }
+
+ err = imx135_write_reg(client, next->addr, val);
+ if (err) {
+ pr_err("%s:imx135_write_table:%d", __func__, err);
+ return err;
+ }
+ }
+ return 0;
+}
+
+static int
+imx135_set_mode(struct imx135_info *info, struct imx135_mode *mode)
+{
+ int sensor_mode;
+ u8 quality_hdr;
+ int err;
+ struct imx135_reg reg_list[8];
+
+ pr_info("%s: xres %u yres %u framelength %u coarsetime %u gain %u, hdr %d\n",
+ __func__, mode->xres, mode->yres, mode->frame_length,
+ mode->coarse_time, mode->gain, mode->hdr_en);
+
+ if (mode->xres == 4208 && mode->yres == 3120) {
+ sensor_mode = IMX135_MODE_4208X3120;
+ quality_hdr = 1;
+ } else if (mode->xres == 1920 && mode->yres == 1080) {
+ sensor_mode = IMX135_MODE_1920X1080;
+ quality_hdr = 0;
+ } else if (mode->xres == 1280 && mode->yres == 720) {
+ sensor_mode = IMX135_MODE_1280X720;
+ quality_hdr = 0;
+ } else if (mode->xres == 2616 && mode->yres == 1472) {
+ sensor_mode = IMX135_MODE_2616X1472;
+ quality_hdr = 1;
+ } else if (mode->xres == 3896 && mode->yres == 2192) {
+ sensor_mode = IMX135_MODE_3896X2192;
+ quality_hdr = 1;
+ } else {
+ pr_err("%s: invalid resolution supplied to set mode %d %d\n",
+ __func__, mode->xres, mode->yres);
+ return -EINVAL;
+ }
+
+ /* get a list of override regs for the asking frame length, */
+ /* coarse integration time, and gain. */
+ imx135_get_frame_length_regs(reg_list, mode->frame_length);
+ imx135_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
+ imx135_get_gain_reg(reg_list + 4, mode->gain);
+ if (mode->hdr_en == 1) /* if HDR is enabled */
+ imx135_get_coarse_time_short_regs(
+ reg_list + 6, mode->coarse_time_short);
+
+ err = imx135_write_table(info->i2c_client,
+ mode_table[sensor_mode],
+ reg_list, mode->hdr_en ? 7 : 5);
+ if (err)
+ return err;
+ if (quality_hdr)
+ err = imx135_write_table(info->i2c_client,
+ mode_table[IMX135_MODE_QUALITY_HDR],
+ reg_list, 0);
+ else
+ err = imx135_write_table(info->i2c_client,
+ mode_table[IMX135_MODE_QUALITY],
+ reg_list, 0);
+ if (err)
+ return err;
+
+ info->mode = sensor_mode;
+ pr_info("[IMX135]: stream on.\n");
+ return 0;
+}
+
+static int
+imx135_get_status(struct imx135_info *info, u8 *dev_status)
+{
+ *dev_status = 0;
+ return 0;
+}
+
+static int
+imx135_set_frame_length(struct imx135_info *info, u32 frame_length,
+ bool group_hold)
+{
+ struct imx135_reg reg_list[2];
+ int i = 0;
+ int ret;
+
+ imx135_get_frame_length_regs(reg_list, frame_length);
+
+ if (group_hold) {
+ ret = imx135_write_reg(info->i2c_client, 0x0104, 0x01);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < 2; i++) {
+ ret = imx135_write_reg(info->i2c_client, reg_list[i].addr,
+ reg_list[i].val);
+ if (ret)
+ return ret;
+ }
+
+ if (group_hold) {
+ ret = imx135_write_reg(info->i2c_client, 0x0104, 0x0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+imx135_set_coarse_time(struct imx135_info *info, u32 coarse_time,
+ bool group_hold)
+{
+ int ret;
+
+ struct imx135_reg reg_list[2];
+ int i = 0;
+
+ imx135_get_coarse_time_regs(reg_list, coarse_time);
+
+ if (group_hold) {
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x01);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < 2; i++) {
+ ret = imx135_write_reg(info->i2c_client, reg_list[i].addr,
+ reg_list[i].val);
+ if (ret)
+ return ret;
+ }
+
+ if (group_hold) {
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int
+imx135_set_gain(struct imx135_info *info, u16 gain, bool group_hold)
+{
+ int ret;
+ struct imx135_reg reg_list;
+
+ imx135_get_gain_reg(&reg_list, gain);
+
+ if (group_hold) {
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x1);
+ if (ret)
+ return ret;
+ }
+
+ ret = imx135_write_reg(info->i2c_client, reg_list.addr, reg_list.val);
+ /* writing second gain register for HDR */
+ ret = imx135_write_reg(info->i2c_client, 0x233, reg_list.val);
+ if (ret)
+ return ret;
+
+ if (group_hold) {
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int
+imx135_set_hdr_coarse_time(struct imx135_info *info, struct imx135_hdr *values)
+{
+ struct imx135_reg reg_list[2];
+ struct imx135_reg reg_list_short[2];
+ int ret, i = 0;
+
+ /* get long and short coarse time registers */
+ imx135_get_coarse_time_regs(reg_list, values->coarse_time_long);
+ imx135_get_coarse_time_short_regs(reg_list_short,
+ values->coarse_time_short);
+ /* set to direct mode */
+ ret = imx135_write_reg(info->i2c_client, 0x238, 0x1);
+ if (ret)
+ return ret;
+ /* set group hold */
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x1);
+ if (ret)
+ return ret;
+ /* writing long exposure */
+ for (i = 0; i < 2; i++) {
+ ret = imx135_write_reg(info->i2c_client, reg_list[i].addr,
+ reg_list[i].val);
+ if (ret)
+ return ret;
+ }
+ /* writing short exposure */
+ for (i = 0; i < 2; i++) {
+ ret = imx135_write_reg(info->i2c_client, reg_list_short[i].addr,
+ reg_list_short[i].val);
+ if (ret)
+ return ret;
+ }
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int
+imx135_set_group_hold(struct imx135_info *info, struct imx135_ae *ae)
+{
+ int ret;
+ int count = 0;
+ bool groupHoldEnabled = false;
+
+ if (ae->gain_enable)
+ count++;
+ if (ae->coarse_time_enable)
+ count++;
+ if (ae->frame_length_enable)
+ count++;
+ if (count >= 2)
+ groupHoldEnabled = true;
+
+ if (groupHoldEnabled) {
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x1);
+ if (ret)
+ return ret;
+ }
+
+ if (ae->gain_enable)
+ imx135_set_gain(info, ae->gain, false);
+ if (ae->coarse_time_enable)
+ imx135_set_coarse_time(info, ae->coarse_time, false);
+ if (ae->frame_length_enable)
+ imx135_set_frame_length(info, ae->frame_length, false);
+
+ if (groupHoldEnabled) {
+ ret = imx135_write_reg(info->i2c_client, 0x104, 0x0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int imx135_get_sensor_id(struct imx135_info *info)
+{
+ int ret = 0;
+ int i;
+ u8 bak = 0;
+
+ pr_info("%s\n", __func__);
+ if (info->sensor_data.fuse_id_size)
+ return 0;
+
+ /* Note 1: If the sensor does not have power at this point
+ Need to supply the power, e.g. by calling power on function */
+
+ ret |= imx135_write_reg(info->i2c_client, 0x3B02, 0x00);
+ ret |= imx135_write_reg(info->i2c_client, 0x3B00, 0x01);
+ for (i = 0; i < 9 ; i++) {
+ ret |= imx135_read_reg(info->i2c_client, 0x3B24 + i, &bak);
+ info->sensor_data.fuse_id[i] = bak;
+ }
+
+ if (!ret)
+ info->sensor_data.fuse_id_size = i;
+
+ /* Note 2: Need to clean up any action carried out in Note 1 */
+
+ return ret;
+}
+
+static long
+imx135_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int err;
+ struct imx135_info *info = file->private_data;
+
+ switch (cmd) {
+ case IMX135_IOCTL_SET_MODE:
+ {
+ struct imx135_mode mode;
+ if (copy_from_user(&mode, (const void __user *)arg,
+ sizeof(struct imx135_mode))) {
+ pr_err("%s:Failed to get mode from user.\n", __func__);
+ return -EFAULT;
+ }
+ return imx135_set_mode(info, &mode);
+ }
+ case IMX135_IOCTL_SET_FRAME_LENGTH:
+ return imx135_set_frame_length(info, (u32)arg, true);
+ case IMX135_IOCTL_SET_COARSE_TIME:
+ return imx135_set_coarse_time(info, (u32)arg, true);
+ case IMX135_IOCTL_SET_GAIN:
+ return imx135_set_gain(info, (u16)arg, true);
+ case IMX135_IOCTL_GET_STATUS:
+ {
+ u8 status;
+
+ err = imx135_get_status(info, &status);
+ if (err)
+ return err;
+ if (copy_to_user((void __user *)arg, &status, 1)) {
+ pr_err("%s:Failed to copy status to user\n", __func__);
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case IMX135_IOCTL_GET_SENSORDATA:
+ {
+ err = imx135_get_sensor_id(info);
+
+ if (err) {
+ pr_err("%s:Failed to get fuse id info.\n", __func__);
+ return err;
+ }
+ if (copy_to_user((void __user *)arg, &info->sensor_data,
+ sizeof(struct imx135_sensordata))) {
+ pr_info("%s:Failed to copy fuse id to user space\n",
+ __func__);
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case IMX135_IOCTL_SET_GROUP_HOLD:
+ {
+ struct imx135_ae ae;
+ if (copy_from_user(&ae, (const void __user *)arg,
+ sizeof(struct imx135_ae))) {
+ pr_info("%s:fail group hold\n", __func__);
+ return -EFAULT;
+ }
+ return imx135_set_group_hold(info, &ae);
+ }
+ case IMX135_IOCTL_SET_HDR_COARSE_TIME:
+ {
+ struct imx135_hdr values;
+
+ dev_dbg(&info->i2c_client->dev,
+ "IMX135_IOCTL_SET_HDR_COARSE_TIME\n");
+ if (copy_from_user(&values,
+ (const void __user *)arg,
+ sizeof(struct imx135_hdr))) {
+ err = -EFAULT;
+ break;
+ }
+ err = imx135_set_hdr_coarse_time(info, &values);
+ break;
+ }
+ default:
+ pr_err("%s:unknown cmd.\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int imx135_debugfs_show(struct seq_file *s, void *unused)
+{
+ struct imx135_info *dev = s->private;
+
+ dev_dbg(&dev->i2c_client->dev, "%s: ++\n", __func__);
+
+ mutex_lock(&dev->imx135_camera_lock);
+ mutex_unlock(&dev->imx135_camera_lock);
+
+ return 0;
+}
+
+static ssize_t imx135_debugfs_write(
+ struct file *file,
+ char const __user *buf,
+ size_t count,
+ loff_t *offset)
+{
+ struct imx135_info *dev =
+ ((struct seq_file *)file->private_data)->private;
+ struct i2c_client *i2c_client = dev->i2c_client;
+ int ret = 0;
+ char buffer[24];
+ u32 address;
+ u32 data;
+ u8 readback;
+
+ dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
+
+ if (copy_from_user(&buffer, buf, sizeof(buffer)))
+ goto debugfs_write_fail;
+
+ if (sscanf(buf, "0x%x 0x%x", &address, &data) == 2)
+ goto set_attr;
+ if (sscanf(buf, "0X%x 0X%x", &address, &data) == 2)
+ goto set_attr;
+ if (sscanf(buf, "%d %d", &address, &data) == 2)
+ goto set_attr;
+
+ if (sscanf(buf, "0x%x 0x%x", &address, &data) == 1)
+ goto read;
+ if (sscanf(buf, "0X%x 0X%x", &address, &data) == 1)
+ goto read;
+ if (sscanf(buf, "%d %d", &address, &data) == 1)
+ goto read;
+
+ dev_err(&i2c_client->dev, "SYNTAX ERROR: %s\n", buf);
+ return -EFAULT;
+
+set_attr:
+ dev_info(&i2c_client->dev,
+ "new address = %x, data = %x\n", address, data);
+ ret |= imx135_write_reg(i2c_client, address, data);
+read:
+ ret |= imx135_read_reg(i2c_client, address, &readback);
+ dev_dbg(&i2c_client->dev,
+ "wrote to address 0x%x with value 0x%x\n",
+ address, readback);
+
+ if (ret)
+ goto debugfs_write_fail;
+
+ return count;
+
+debugfs_write_fail:
+ dev_err(&i2c_client->dev,
+ "%s: test pattern write failed\n", __func__);
+ return -EFAULT;
+}
+
+static int imx135_debugfs_open(struct inode *inode, struct file *file)
+{
+ struct imx135_info *dev = inode->i_private;
+ struct i2c_client *i2c_client = dev->i2c_client;
+
+ dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
+
+ return single_open(file, imx135_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations imx135_debugfs_fops = {
+ .open = imx135_debugfs_open,
+ .read = seq_read,
+ .write = imx135_debugfs_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void imx135_remove_debugfs(struct imx135_info *dev)
+{
+ struct i2c_client *i2c_client = dev->i2c_client;
+
+ dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
+
+ if (dev->debugdir)
+ debugfs_remove_recursive(dev->debugdir);
+ dev->debugdir = NULL;
+}
+
+static void imx135_create_debugfs(struct imx135_info *dev)
+{
+ struct dentry *ret;
+ struct i2c_client *i2c_client = dev->i2c_client;
+
+ dev_dbg(&i2c_client->dev, "%s\n", __func__);
+
+ dev->debugdir =
+ debugfs_create_dir(dev->miscdev_info.this_device->kobj.name,
+ NULL);
+ if (!dev->debugdir)
+ goto remove_debugfs;
+
+ ret = debugfs_create_file("d",
+ S_IWUSR | S_IRUGO,
+ dev->debugdir, dev,
+ &imx135_debugfs_fops);
+ if (!ret)
+ goto remove_debugfs;
+
+ return;
+remove_debugfs:
+ dev_err(&i2c_client->dev, "couldn't create debugfs\n");
+ imx135_remove_debugfs(dev);
+}
+
+static int
+imx135_open(struct inode *inode, struct file *file)
+{
+ struct miscdevice *miscdev = file->private_data;
+ struct imx135_info *info;
+
+ info = container_of(miscdev, struct imx135_info, miscdev_info);
+ /* check if the device is in use */
+ if (atomic_xchg(&info->in_use, 1)) {
+ pr_info("%s:BUSY!\n", __func__);
+ return -EBUSY;
+ }
+
+ file->private_data = info;
+
+ if (info->pdata && info->pdata->power_on)
+ info->pdata->power_on(&info->power);
+ else{
+ pr_err("%s:no valid power_on function.\n", __func__);
+ return -EEXIST;
+ }
+
+ return 0;
+}
+
+static int
+imx135_release(struct inode *inode, struct file *file)
+{
+ struct imx135_info *info = file->private_data;
+
+ if (info->pdata && info->pdata->power_off)
+ info->pdata->power_off(&info->power);
+ file->private_data = NULL;
+
+ /* warn if device is already released */
+ WARN_ON(!atomic_xchg(&info->in_use, 0));
+ return 0;
+}
+
+static int imx135_power_put(struct imx135_power_rail *pw)
+{
+ if (unlikely(!pw))
+ return -EFAULT;
+
+ if (likely(pw->avdd))
+ regulator_put(pw->avdd);
+
+ if (likely(pw->iovdd))
+ regulator_put(pw->iovdd);
+
+ if (likely(pw->dvdd))
+ regulator_put(pw->dvdd);
+
+ pw->avdd = NULL;
+ pw->iovdd = NULL;
+ pw->dvdd = NULL;
+
+ return 0;
+}
+
+static int imx135_regulator_get(struct imx135_info *info,
+ struct regulator **vreg, char vreg_name[])
+{
+ struct regulator *reg = NULL;
+ int err = 0;
+
+ reg = regulator_get(&info->i2c_client->dev, vreg_name);
+ if (unlikely(IS_ERR_OR_NULL(reg))) {
+ dev_err(&info->i2c_client->dev, "%s %s ERR: %d\n",
+ __func__, vreg_name, (int)reg);
+ err = PTR_ERR(reg);
+ reg = NULL;
+ } else
+ dev_dbg(&info->i2c_client->dev, "%s: %s\n",
+ __func__, vreg_name);
+
+ *vreg = reg;
+ return err;
+}
+
+static int imx135_power_get(struct imx135_info *info)
+{
+ struct imx135_power_rail *pw = &info->power;
+
+ imx135_regulator_get(info, &pw->avdd, "vana"); /* ananlog 2.7v */
+ imx135_regulator_get(info, &pw->dvdd, "vdig"); /* digital 1.2v */
+ imx135_regulator_get(info, &pw->iovdd, "vif"); /* interface 1.8v */
+
+ return 0;
+}
+
+static const struct file_operations imx135_fileops = {
+ .owner = THIS_MODULE,
+ .open = imx135_open,
+ .unlocked_ioctl = imx135_ioctl,
+ .release = imx135_release,
+};
+
+static struct miscdevice imx135_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "imx135",
+ .fops = &imx135_fileops,
+};
+
+
+static int
+imx135_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct imx135_info *info;
+ int err;
+
+ pr_info("[IMX135]: probing sensor.\n");
+
+ info = devm_kzalloc(&client->dev,
+ sizeof(struct imx135_info), GFP_KERNEL);
+ if (!info) {
+ pr_err("%s:Unable to allocate memory!\n", __func__);
+ return -ENOMEM;
+ }
+
+ info->pdata = client->dev.platform_data;
+ info->i2c_client = client;
+ atomic_set(&info->in_use, 0);
+ info->mode = -1;
+
+ imx135_power_get(info);
+
+ memcpy(&info->miscdev_info,
+ &imx135_device,
+ sizeof(struct miscdevice));
+
+ err = misc_register(&info->miscdev_info);
+ if (err) {
+ pr_err("%s:Unable to register misc device!\n", __func__);
+ goto imx135_probe_fail;
+ }
+
+ i2c_set_clientdata(client, info);
+ /* create debugfs interface */
+ imx135_create_debugfs(info);
+ return 0;
+
+imx135_probe_fail:
+ imx135_power_put(&info->power);
+
+ return err;
+}
+
+static int
+imx135_remove(struct i2c_client *client)
+{
+ struct imx135_info *info;
+ info = i2c_get_clientdata(client);
+ misc_deregister(&imx135_device);
+
+ imx135_power_put(&info->power);
+
+ imx135_remove_debugfs(info);
+ return 0;
+}
+
+static const struct i2c_device_id imx135_id[] = {
+ { "imx135", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, imx135_id);
+
+static struct i2c_driver imx135_i2c_driver = {
+ .driver = {
+ .name = "imx135",
+ .owner = THIS_MODULE,
+ },
+ .probe = imx135_probe,
+ .remove = imx135_remove,
+ .id_table = imx135_id,
+};
+
+static int __init imx135_init(void)
+{
+ pr_info("[IMX135] sensor driver loading\n");
+ return i2c_add_driver(&imx135_i2c_driver);
+}
+
+static void __exit imx135_exit(void)
+{
+ i2c_del_driver(&imx135_i2c_driver);
+}
+
+module_init(imx135_init);
+module_exit(imx135_exit);