media: convert imx179 driver to non-nvc format
Ming Wong [Fri, 10 Jan 2014 20:23:50 +0000 (12:23 -0800)]
bug 1415077

Change-Id: I98ea518ea8de07b2cd78066522c039dadee379bd
Signed-off-by: Ming Wong <miwong@nvidia.com>
Reviewed-on: http://git-master/r/354372
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Frank Chen <frankc@nvidia.com>
Reviewed-by: Prayas Mohanty <pmohanty@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>

drivers/media/platform/tegra/imx179.c
include/media/imx179.h

index 9a540ae..ea04884 100644 (file)
 /*
-* imx179.c - imx179 sensor driver
-*
-* Copyright (c) 2013-2014, NVIDIA Corporation. All Rights Reserved.
-*
-* This file is licensed under the terms of the GNU General Public License
-* version 2. This program is licensed "as is" without any warranty of any
-* kind, whether express or implied.
-*/
+ * imx179.c - imx179 sensor driver
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION, All Rights Reserved.
+ *
+ * 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/clk.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
-#include <linux/delay.h>
 #include <linux/uaccess.h>
-#include <linux/atomic.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
-#include <linux/module.h>
-#include <linux/list.h>
+#include <linux/regmap.h>
 #include <media/imx179.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/edp.h>
 
-#include "nvc_utilities.h"
-
-#define IMX179_ID                      0x0179
-#define IMX179_ID_ADDRESS   0x0002
-#define IMX179_STREAM_CONTROL_REG 0x0100
-#define IMX179_STREAM_ENABLE 0x01
-#define IMX179_STREAM_DISABLE 0x00
-#define IMX179_SENSOR_TYPE             NVC_IMAGER_TYPE_RAW
-#define IMX179_STARTUP_DELAY_MS                50
-#define IMX179_RES_CHG_WAIT_TIME_MS    100
-#define IMX179_SIZEOF_I2C_BUF          16
-#define IMX179_TABLE_WAIT_MS           0
-#define IMX179_TABLE_END               1
-#define IMX179_NUM_MODES               ARRAY_SIZE(imx179_mode_table)
-#define IMX179_MODE_UNKNOWN            (IMX179_NUM_MODES + 1)
-#define IMX179_LENS_MAX_APERTURE       0 /* / _INT2FLOAT_DIVISOR */
-#define IMX179_LENS_FNUMBER            0 /* / _INT2FLOAT_DIVISOR */
-#define IMX179_LENS_FOCAL_LENGTH       3700 /* / _INT2FLOAT_DIVISOR */
-#define IMX179_LENS_VIEW_ANGLE_H       75600 /* / _INT2FLOAT_DIVISOR */
-#define IMX179_LENS_VIEW_ANGLE_V       75600 /* / _INT2FLOAT_DIVISOR */
-#define IMX179_WAIT_MS 3
-#define IMX179_I2C_TABLE_MAX_ENTRIES   400
-
-static u16 imx179_ids[] = {
-       0x0179,
-};
-
-static struct nvc_gpio_init imx179_gpios[] = {
-       {IMX179_GPIO_RESET, GPIOF_OUT_INIT_LOW, "reset", false, true},
-       {IMX179_GPIO_PWDN, GPIOF_OUT_INIT_LOW, "pwdn", false, true},
-       {IMX179_GPIO_GP1, 0, "gp1", false, false},
-};
-
-static struct nvc_regulator_init imx179_vregs[] = {
-       { IMX179_VREG_DVDD, "vdig", },
-       { IMX179_VREG_AVDD, "vana", },
-       { IMX179_VREG_IOVDD, "vif", },
-};
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
-struct imx179_info {
-       atomic_t in_use;
-       struct i2c_client *i2c_client;
-       struct imx179_platform_data *pdata;
-       struct nvc_imager_cap *cap;
-       struct miscdevice miscdev;
-       struct list_head list;
-       struct clk *mclk;
-       struct nvc_gpio gpio[ARRAY_SIZE(imx179_gpios)];
-       struct nvc_regulator vreg[ARRAY_SIZE(imx179_vregs)];
-       int pwr_api;
-       int pwr_dev;
-       u8 s_mode;
-       struct imx179_info *s_info;
-       u32 mode_index;
-       bool mode_valid;
-       bool mode_enable;
-       bool reset_flag;
-       unsigned test_pattern;
-       struct nvc_imager_static_nvc sdata;
-       u8 i2c_buf[IMX179_SIZEOF_I2C_BUF];
-       u8 bin_en;
-#ifdef CONFIG_DEBUG_FS
-       struct dentry *debugfs_root;
-       u16     i2c_reg;
-#endif
-};
+#include "nvc_utilities.h"
 
 struct imx179_reg {
        u16 addr;
-       u16 val;
-};
-
-struct imx179_mode_data {
-       struct nvc_imager_mode sensor_mode;
-       struct nvc_imager_dynamic_nvc sensor_dnvc;
-       struct imx179_reg *p_mode_i2c;
-};
-
-static struct nvc_imager_cap imx179_dflt_cap = {
-       .identifier             = "IMX179",
-       .sensor_nvc_interface   = 3,
-       .pixel_types[0]         = 0x100,
-       .orientation            = 0,
-       .direction              = 0,
-       .initial_clock_rate_khz = 6000,
-       .clock_profiles[0] = {
-               .external_clock_khz     = 24000,
-               .clock_multiplier       = 8500000, /* value / 1,000,000 */
-       },
-       .clock_profiles[1] = {
-               .external_clock_khz     = 0,
-               .clock_multiplier       = 0,
-       },
-       .h_sync_edge            = 0,
-       .v_sync_edge            = 0,
-       .mclk_on_vgp0           = 0,
-       .csi_port               = 0,
-       .data_lanes             = 4,
-       .virtual_channel_id     = 0,
-       .discontinuous_clk_mode = 1,
-       .cil_threshold_settle   = 0x0,
-       .min_blank_time_width   = 16,
-       .min_blank_time_height  = 16,
-       .preferred_mode_index   = 1,
-       .focuser_guid           = NVC_FOCUS_GUID(0),
-       .torch_guid             = 0, /*NVC_TORCH_GUID(0),*/
-       .cap_version            = NVC_IMAGER_CAPABILITIES_VERSION2,
-};
-
-static struct imx179_platform_data imx179_dflt_pdata = {
-       .cfg                    = 0,
-       .num                    = 0,
-       .sync                   = 0,
-       .dev_name               = "camera",
-       .cap                    = &imx179_dflt_cap,
-};
-
-       /* NOTE: static vs dynamic
-        * If a member in the nvc_imager_static_nvc structure is not actually
-        * static data, then leave blank and add the parameter to the parameter
-        * read function that dynamically reads the data.  The NVC user driver
-        * will call the parameter read for the data if the member data is 0.
-        * If the dynamic data becomes static during probe (a one time read
-        * such as device ID) then add the dynamic read to the _sdata_init
-        * function.
-        */
-static struct nvc_imager_static_nvc imx179_dflt_sdata = {
-       .api_version            = NVC_IMAGER_API_STATIC_VER,
-       .sensor_type            = IMX179_SENSOR_TYPE,
-       .bits_per_pixel         = 10,
-       .sensor_id              = IMX179_ID,
-       .sensor_id_minor        = 0,
-       .focal_len              = IMX179_LENS_FOCAL_LENGTH,
-       .max_aperture           = IMX179_LENS_MAX_APERTURE,
-       .fnumber                = IMX179_LENS_FNUMBER,
-       .view_angle_h           = IMX179_LENS_VIEW_ANGLE_H,
-       .view_angle_v           = IMX179_LENS_VIEW_ANGLE_V,
-       .res_chg_wait_time      = IMX179_RES_CHG_WAIT_TIME_MS,
+       u8 val;
 };
 
-static LIST_HEAD(imx179_info_list);
-static DEFINE_SPINLOCK(imx179_spinlock);
-
-
-static struct imx179_reg tp_none_seq[] = {
-       {IMX179_TABLE_END, 0x0000}
+struct imx179_info {
+       struct miscdevice               miscdev_info;
+       int                             mode;
+       struct imx179_power_rail        power;
+       struct imx179_sensordata        sensor_data;
+       struct i2c_client               *i2c_client;
+       struct imx179_platform_data     *pdata;
+       struct clk                      *mclk;
+       struct regmap                   *regmap;
+       struct mutex                    imx179_camera_lock;
+       struct dentry                   *debugdir;
+       atomic_t                        in_use;
+       struct edp_client               *edpc;
+       unsigned int                    edp_state;
 };
 
-static struct imx179_reg tp_cbars_seq[] = {
-       {IMX179_TABLE_END, 0x0000}
+static const struct regmap_config sensor_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 8,
+       .cache_type = REGCACHE_RBTREE,
 };
 
-static struct imx179_reg tp_checker_seq[] = {
-       {IMX179_TABLE_END, 0x0000}
-};
+#define IMX179_TABLE_WAIT_MS 0
+#define IMX179_TABLE_END 1
+#define IMX179_MAX_RETRIES 3
+#define IMX179_WAIT_MS 3
 
-static struct imx179_reg *test_patterns[] = {
-       tp_none_seq,
-       tp_cbars_seq,
-       tp_checker_seq,
-};
+#define MAX_BUFFER_SIZE 32
+#define IMX179_FRAME_LENGTH_ADDR_MSB 0x0340
+#define IMX179_FRAME_LENGTH_ADDR_LSB 0x0341
+#define IMX179_COARSE_TIME_ADDR_MSB 0x0202
+#define IMX179_COARSE_TIME_ADDR_LSB 0x0203
+#define IMX179_GAIN_ADDR 0x0205
 
-static struct imx179_reg imx179_3280x2464_i2c[] = {
-       /*stand by*/
+static struct imx179_reg mode_3280x2464[] = {
+       /* software reset */
        {0x0100, 0x00},
        {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
 
+       /* global settings */
        {0x0101, 0x00},
        {0x0202, 0x09},
-       {0x0203, 0xCC},
+       {0x0203, 0xC7},
        {0x0301, 0x05},
        {0x0303, 0x01},
        {0x0305, 0x06},
@@ -202,7 +95,7 @@ static struct imx179_reg imx179_3280x2464_i2c[] = {
        {0x030C, 0x00},
        {0x030D, 0xA2},
        {0x0340, 0x09},
-       {0x0341, 0xD0},
+       {0x0341, 0xCB},
        {0x0342, 0x0D},
        {0x0343, 0x70},
        {0x0344, 0x00},
@@ -251,1040 +144,434 @@ static struct imx179_reg imx179_3280x2464_i2c[] = {
        {0x4108, 0x01},
        {0x4109, 0x7C},
 
+       {0x0100, 0x01},
        {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
        {IMX179_TABLE_END, 0x00}
 };
 
-static struct imx179_reg imx179_1640x1232_i2c[] = {
-       /*stand by*/
-       {0x0100, 0x00},
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
-
-       {0x0101, 0x00},
-       {0x0202, 0x09},
-       {0x0203, 0xCC},
-       {0x0301, 0x05},
-       {0x0303, 0x01},
-       {0x0305, 0x06},
-       {0x0309, 0x05},
-       {0x030B, 0x01},
-       {0x030C, 0x00},
-       {0x030D, 0xA2},
-       {0x0340, 0x09},
-       {0x0341, 0xD0},
-       {0x0342, 0x0D},
-       {0x0343, 0x70},
-       {0x0344, 0x00},
-       {0x0345, 0x00},
-       {0x0346, 0x00},
-       {0x0347, 0x00},
-       {0x0348, 0x0C},
-       {0x0349, 0xCF},
-       {0x034A, 0x09},
-       {0x034B, 0x9F},
-       {0x034C, 0x06},
-       {0x034D, 0x68},
-       {0x034E, 0x04},
-       {0x034F, 0xD0},
-       {0x0383, 0x01},
-       {0x0387, 0x01},
-       {0x0390, 0x01},
-       {0x0401, 0x00},
-       {0x0405, 0x10},
-       {0x3020, 0x10},
-       {0x3041, 0x15},
-       {0x3042, 0x87},
-       {0x3089, 0x4F},
-       {0x3309, 0x9A},
-       {0x3344, 0x57},
-       {0x3345, 0x1F},
-       {0x3362, 0x0A},
-       {0x3363, 0x0A},
-       {0x3364, 0x00},
-       {0x3368, 0x18},
-       {0x3369, 0x00},
-       {0x3370, 0x77},
-       {0x3371, 0x2F},
-       {0x3372, 0x4F},
-       {0x3373, 0x2F},
-       {0x3374, 0x2F},
-       {0x3375, 0x37},
-       {0x3376, 0x9F},
-       {0x3377, 0x37},
-       {0x33C8, 0x00},
-       {0x33D4, 0x06},
-       {0x33D5, 0x68},
-       {0x33D6, 0x04},
-       {0x33D7, 0xD0},
-       {0x4100, 0x0E},
-       {0x4108, 0x01},
-       {0x4109, 0x7C},
+enum {
+       IMX179_MODE_3280X2464,
+};
 
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
-       {IMX179_TABLE_END, 0x00}
+static struct imx179_reg *mode_table[] = {
+       [IMX179_MODE_3280X2464] = mode_3280x2464,
 };
 
-static struct imx179_reg imx179_1920x1080_i2c[] = {
-       /*stand by*/
-       {0x0100, 0x00},
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
+static void imx179_edp_lowest(struct imx179_info *info)
+{
+       if (!info->edpc)
+               return;
 
-       {0x0101, 0x00},
-       {0x0202, 0x09},
-       {0x0203, 0xCC},
-       {0x0301, 0x05},
-       {0x0303, 0x01},
-       {0x0305, 0x06},
-       {0x0309, 0x05},
-       {0x030B, 0x01},
-       {0x030C, 0x00},
-       {0x030D, 0xA2},
-       {0x0340, 0x09},
-       {0x0341, 0xD0},
-       {0x0342, 0x0D},
-       {0x0343, 0x70},
-       {0x0344, 0x02},
-       {0x0345, 0xA8},
-       {0x0346, 0x02},
-       {0x0347, 0xB4},
-       {0x0348, 0x0A},
-       {0x0349, 0x27},
-       {0x034A, 0x06},
-       {0x034B, 0xEB},
-       {0x034C, 0x07},
-       {0x034D, 0x80},
-       {0x034E, 0x04},
-       {0x034F, 0x38},
-       {0x0383, 0x01},
-       {0x0387, 0x01},
-       {0x0390, 0x00},
-       {0x0401, 0x00},
-       {0x0405, 0x10},
-       {0x3020, 0x10},
-       {0x3041, 0x15},
-       {0x3042, 0x87},
-       {0x3089, 0x4F},
-       {0x3309, 0x9A},
-       {0x3344, 0x57},
-       {0x3345, 0x1F},
-       {0x3362, 0x0A},
-       {0x3363, 0x0A},
-       {0x3364, 0x00},
-       {0x3368, 0x18},
-       {0x3369, 0x00},
-       {0x3370, 0x77},
-       {0x3371, 0x2F},
-       {0x3372, 0x4F},
-       {0x3373, 0x2F},
-       {0x3374, 0x2F},
-       {0x3375, 0x37},
-       {0x3376, 0x9F},
-       {0x3377, 0x37},
-       {0x33C8, 0x00},
-       {0x33D4, 0x07},
-       {0x33D5, 0x80},
-       {0x33D6, 0x04},
-       {0x33D7, 0x38},
-       {0x4100, 0x0E},
-       {0x4108, 0x01},
-       {0x4109, 0x7C},
+       info->edp_state = info->edpc->num_states - 1;
+       dev_dbg(&info->i2c_client->dev, "%s %d\n", __func__, info->edp_state);
+       if (edp_update_client_request(info->edpc, info->edp_state, NULL)) {
+               dev_err(&info->i2c_client->dev, "THIS IS NOT LIKELY HAPPEN!\n");
+               dev_err(&info->i2c_client->dev,
+                       "UNABLE TO SET LOWEST EDP STATE!\n");
+       }
+}
 
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
-       {IMX179_TABLE_END, 0x00}
-};
+static void imx179_edp_throttle(unsigned int new_state, void *priv_data)
+{
+       struct imx179_info *info = priv_data;
 
-static struct imx179_reg imx179_1280x720_i2c[] = {
-       /*stand by*/
-       {0x0100, 0x00},
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
+       if (info->pdata && info->pdata->power_off)
+               info->pdata->power_off(&info->power);
+}
 
-       {0x0101, 0x00},
-       {0x0202, 0x09},
-       {0x0203, 0xCC},
-       {0x0301, 0x05},
-       {0x0303, 0x01},
-       {0x0305, 0x06},
-       {0x0309, 0x05},
-       {0x030B, 0x01},
-       {0x030C, 0x00},
-       {0x030D, 0xA2},
-       {0x0340, 0x09},
-       {0x0341, 0xD0},
-       {0x0342, 0x0D},
-       {0x0343, 0x70},
-       {0x0344, 0x01},
-       {0x0345, 0x68},
-       {0x0346, 0x02},
-       {0x0347, 0x00},
-       {0x0348, 0x0B},
-       {0x0349, 0x67},
-       {0x034A, 0x07},
-       {0x034B, 0x9F},
-       {0x034C, 0x05},
-       {0x034D, 0x00},
-       {0x034E, 0x02},
-       {0x034F, 0xD0},
-       {0x0383, 0x01},
-       {0x0387, 0x01},
-       {0x0390, 0x01},
-       {0x0401, 0x00},
-       {0x0405, 0x10},
-       {0x3020, 0x10},
-       {0x3041, 0x15},
-       {0x3042, 0x87},
-       {0x3089, 0x4F},
-       {0x3309, 0x9A},
-       {0x3344, 0x57},
-       {0x3345, 0x1F},
-       {0x3362, 0x0A},
-       {0x3363, 0x0A},
-       {0x3364, 0x00},
-       {0x3368, 0x18},
-       {0x3369, 0x00},
-       {0x3370, 0x77},
-       {0x3371, 0x2F},
-       {0x3372, 0x4F},
-       {0x3373, 0x2F},
-       {0x3374, 0x2F},
-       {0x3375, 0x37},
-       {0x3376, 0x9F},
-       {0x3377, 0x37},
-       {0x33C8, 0x00},
-       {0x33D4, 0x05},
-       {0x33D5, 0x00},
-       {0x33D6, 0x02},
-       {0x33D7, 0xD0},
-       {0x4100, 0x0E},
-       {0x4108, 0x01},
-       {0x4109, 0x7C},
+static void imx179_edp_register(struct imx179_info *info)
+{
+       struct edp_manager *edp_manager;
+       struct edp_client *edpc = &info->pdata->edpc_config;
+       int ret;
 
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
-       {IMX179_TABLE_END, 0x00}
-};
+       info->edpc = NULL;
+       if (!edpc->num_states) {
+               dev_warn(&info->i2c_client->dev,
+                       "%s: No edp states defined.\n", __func__);
+               return;
+       }
 
-static struct imx179_reg imx179_640x480_i2c[] = {
-       /*stand by*/
-       {0x0100, 0x00},
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
+       strncpy(edpc->name, "imx179", EDP_NAME_LEN - 1);
+       edpc->name[EDP_NAME_LEN - 1] = 0;
+       edpc->private_data = info;
+       edpc->throttle = imx179_edp_throttle;
 
-       {0x0101, 0x00},
-       {0x0202, 0x09},
-       {0x0203, 0xCC},
-       {0x0301, 0x05},
-       {0x0303, 0x01},
-       {0x0305, 0x06},
-       {0x0309, 0x05},
-       {0x030B, 0x01},
-       {0x030C, 0x00},
-       {0x030D, 0xA2},
-       {0x0340, 0x09},
-       {0x0341, 0xD0},
-       {0x0342, 0x0D},
-       {0x0343, 0x70},
-       {0x0344, 0x01},
-       {0x0345, 0x68},
-       {0x0346, 0x01},
-       {0x0347, 0x10},
-       {0x0348, 0x0B},
-       {0x0349, 0x67},
-       {0x034A, 0x08},
-       {0x034B, 0x8F},
-       {0x034C, 0x02},
-       {0x034D, 0x80},
-       {0x034E, 0x01},
-       {0x034F, 0xE0},
-       {0x0383, 0x01},
-       {0x0387, 0x01},
-       {0x0390, 0x02},
-       {0x0401, 0x00},
-       {0x0405, 0x10},
-       {0x3020, 0x10},
-       {0x3041, 0x15},
-       {0x3042, 0x87},
-       {0x3089, 0x4F},
-       {0x3309, 0x9A},
-       {0x3344, 0x57},
-       {0x3345, 0x1F},
-       {0x3362, 0x0A},
-       {0x3363, 0x0A},
-       {0x3364, 0x00},
-       {0x3368, 0x18},
-       {0x3369, 0x00},
-       {0x3370, 0x77},
-       {0x3371, 0x2F},
-       {0x3372, 0x4F},
-       {0x3373, 0x2F},
-       {0x3374, 0x2F},
-       {0x3375, 0x37},
-       {0x3376, 0x9F},
-       {0x3377, 0x37},
-       {0x33C8, 0x00},
-       {0x33D4, 0x02},
-       {0x33D5, 0x80},
-       {0x33D6, 0x01},
-       {0x33D7, 0xE0},
-       {0x4100, 0x0E},
-       {0x4108, 0x01},
-       {0x4109, 0x7C},
+       dev_dbg(&info->i2c_client->dev, "%s: %s, e0 = %d, p %d\n",
+               __func__, edpc->name, edpc->e0_index, edpc->priority);
+       for (ret = 0; ret < edpc->num_states; ret++)
+               dev_dbg(&info->i2c_client->dev, "e%d = %d mA",
+                       ret - edpc->e0_index, edpc->states[ret]);
 
-       {IMX179_TABLE_WAIT_MS, IMX179_WAIT_MS},
-       {IMX179_TABLE_END, 0x00}
-};
-/* Each resolution requires the below data table setup and the corresponding
- * I2C data table.
- * If more NVC data is needed for the NVC driver, be sure and modify the
- * nvc_imager_nvc structure in nvc_imager.h
- * If more data sets are needed per resolution, they can be added to the
- * table format below with the imx179_mode_data structure.  New data sets
- * should conform to an already defined NVC structure.  If it's data for the
- * NVC driver, then it should be added to the nvc_imager_nvc structure.
- * Steps to add a resolution:
- * 1. Add I2C data table
- * 2. Add imx179_mode_data table
- * 3. Add entry to the imx179_mode_table
- */
-static struct imx179_mode_data imx179_3280x2464 = {
-       .sensor_mode = {
-               .res_x                  = 3280,
-               .res_y                  = 2464,
-               .active_start_x         = 0,
-               .active_stary_y         = 0,
-               .peak_frame_rate        = 30000, /* / _INT2FLOAT_DIVISOR */
-               .pixel_aspect_ratio     = 1000, /* / _INT2FLOAT_DIVISOR */
-               .pll_multiplier         = 11000, /* / _INT2FLOAT_DIVISOR */
-               .crop_mode              = NVC_IMAGER_CROPMODE_NONE,
-       },
-       .sensor_dnvc = {
-               .api_version            = NVC_IMAGER_API_DYNAMIC_VER,
-               .region_start_x         = 0,
-               .region_start_y         = 0,
-               .x_scale                = 1,
-               .y_scale                = 1,
-               .bracket_caps           = 1,
-               .flush_count            = 2,
-               .init_intra_frame_skip  = 0,
-               .ss_intra_frame_skip    = 2,
-               .ss_frame_number        = 3,
-               .coarse_time            = 0x09CC,
-               .max_coarse_diff        = 5,
-               .min_exposure_course    = 2,
-               .max_exposure_course    = 0xFFFC,
-               .diff_integration_time  = 110, /* / _INT2FLOAT_DIVISOR */
-               .line_length            = 0x0D70,
-               .frame_length           = 0x09D0,
-               .min_frame_length       = 0x09D0,
-               .max_frame_length       = 0xFFFF,
-               .min_gain               = 1, /* / _INT2FLOAT_DIVISOR */
-               .max_gain               = 16000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain          = 1000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain_bin_en   = 1000, /* / _INT2FLOAT_DIVISOR */
-               .support_bin_control    = 0,
-               .support_fast_mode      = 0,
-               .pll_mult               = 0xA2,
-               .pll_div                = 0x06,
-       },
-       .p_mode_i2c                     = imx179_3280x2464_i2c,
-};
+       edp_manager = edp_get_manager("battery");
+       if (!edp_manager) {
+               dev_err(&info->i2c_client->dev,
+                       "unable to get edp manager: battery\n");
+               return;
+       }
 
-static struct imx179_mode_data imx179_1640x1232 = {
-       .sensor_mode = {
-               .res_x                  = 1640,
-               .res_y                  = 1232,
-               .active_start_x         = 0,
-               .active_stary_y         = 0,
-               .peak_frame_rate        = 30000, /* / _INT2FLOAT_DIVISOR */
-               .pixel_aspect_ratio     = 1000, /* / _INT2FLOAT_DIVISOR */
-               .pll_multiplier         = 11000, /* / _INT2FLOAT_DIVISOR */
-               .crop_mode              = NVC_IMAGER_CROPMODE_NONE,
-       },
-       .sensor_dnvc = {
-               .api_version            = NVC_IMAGER_API_DYNAMIC_VER,
-               .region_start_x         = 0,
-               .region_start_y         = 0,
-               .x_scale                = 1,
-               .y_scale                = 1,
-               .bracket_caps           = 1,
-               .flush_count            = 2,
-               .init_intra_frame_skip  = 0,
-               .ss_intra_frame_skip    = 2,
-               .ss_frame_number        = 3,
-               .coarse_time            = 0x09CC,
-               .max_coarse_diff        = 5,
-               .min_exposure_course    = 2,
-               .max_exposure_course    = 0xFFFC,
-               .diff_integration_time  = 110, /* / _INT2FLOAT_DIVISOR */
-               .line_length            = 0x0D70,
-               .frame_length           = 0x09D0,
-               .min_frame_length       = 0x09D0,
-               .max_frame_length       = 0xFFFF,
-               .min_gain               = 1, /* / _INT2FLOAT_DIVISOR */
-               .max_gain               = 16000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain          = 1000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain_bin_en   = 1000, /* / _INT2FLOAT_DIVISOR */
-               .support_bin_control    = 0,
-               .support_fast_mode      = 0,
-               .pll_mult               = 0xA2,
-               .pll_div                = 0x06,
-       },
-       .p_mode_i2c                     = imx179_1640x1232_i2c,
-};
+       ret = edp_register_client(edp_manager, edpc);
+       if (ret) {
+               dev_err(&info->i2c_client->dev,
+                       "unable to register edp client\n");
+               return;
+       }
 
-static struct imx179_mode_data imx179_1920x1080 = {
-       .sensor_mode = {
-               .res_x                  = 1920,
-               .res_y                  = 1080,
-               .active_start_x         = 0,
-               .active_stary_y         = 0,
-               .peak_frame_rate        = 30000, /* / _INT2FLOAT_DIVISOR */
-               .pixel_aspect_ratio     = 1000, /* / _INT2FLOAT_DIVISOR */
-               .pll_multiplier         = 11000, /* / _INT2FLOAT_DIVISOR */
-               .crop_mode              = NVC_IMAGER_CROPMODE_NONE,
-       },
-       .sensor_dnvc = {
-               .api_version            = NVC_IMAGER_API_DYNAMIC_VER,
-               .region_start_x         = 0,
-               .region_start_y         = 0,
-               .x_scale                = 1,
-               .y_scale                = 1,
-               .bracket_caps           = 1,
-               .flush_count            = 2,
-               .init_intra_frame_skip  = 0,
-               .ss_intra_frame_skip    = 2,
-               .ss_frame_number        = 3,
-               .coarse_time            = 0x09CC,
-               .max_coarse_diff        = 5,
-               .min_exposure_course    = 2,
-               .max_exposure_course    = 0xFFFC,
-               .diff_integration_time  = 110, /* / _INT2FLOAT_DIVISOR */
-               .line_length            = 0x0D70,
-               .frame_length           = 0x09D0,
-               .min_frame_length       = 0x09D0,
-               .max_frame_length       = 0xFFFF,
-               .min_gain               = 1, /* / _INT2FLOAT_DIVISOR */
-               .max_gain               = 16000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain          = 1000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain_bin_en   = 1000, /* / _INT2FLOAT_DIVISOR */
-               .support_bin_control    = 0,
-               .support_fast_mode      = 0,
-               .pll_mult               = 0xA2,
-               .pll_div                = 0x06,
-       },
-       .p_mode_i2c                     = imx179_1920x1080_i2c,
-};
+       info->edpc = edpc;
+       /* set to lowest state at init */
+       imx179_edp_lowest(info);
+}
 
-static struct imx179_mode_data imx179_1280x720 = {
-       .sensor_mode = {
-               .res_x                  = 1280,
-               .res_y                  = 720,
-               .active_start_x         = 0,
-               .active_stary_y         = 0,
-               .peak_frame_rate        = 30000, /* / _INT2FLOAT_DIVISOR */
-               .pixel_aspect_ratio     = 1000, /* / _INT2FLOAT_DIVISOR */
-               .pll_multiplier         = 11000, /* / _INT2FLOAT_DIVISOR */
-               .crop_mode              = NVC_IMAGER_CROPMODE_NONE,
-       },
-       .sensor_dnvc = {
-               .api_version            = NVC_IMAGER_API_DYNAMIC_VER,
-               .region_start_x         = 0,
-               .region_start_y         = 0,
-               .x_scale                = 1,
-               .y_scale                = 1,
-               .bracket_caps           = 1,
-               .flush_count            = 2,
-               .init_intra_frame_skip  = 0,
-               .ss_intra_frame_skip    = 2,
-               .ss_frame_number        = 3,
-               .coarse_time            = 0x09CC,
-               .max_coarse_diff        = 5,
-               .min_exposure_course    = 2,
-               .max_exposure_course    = 0xFFFC,
-               .diff_integration_time  = 110, /* / _INT2FLOAT_DIVISOR */
-               .line_length            = 0x0D70,
-               .frame_length           = 0x09D0,
-               .min_frame_length       = 0x09D0,
-               .max_frame_length       = 0xFFFF,
-               .min_gain               = 1, /* / _INT2FLOAT_DIVISOR */
-               .max_gain               = 16000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain          = 1000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain_bin_en   = 1000, /* / _INT2FLOAT_DIVISOR */
-               .support_bin_control    = 0,
-               .support_fast_mode      = 0,
-               .pll_mult               = 0xA2,
-               .pll_div                = 0x06,
-       },
-       .p_mode_i2c                     = imx179_1280x720_i2c,
-};
+static int imx179_edp_req(struct imx179_info *info, unsigned new_state)
+{
+       unsigned approved;
+       int ret = 0;
 
-static struct imx179_mode_data imx179_640x480 = {
-       .sensor_mode = {
-               .res_x                  = 640,
-               .res_y                  = 480,
-               .active_start_x         = 0,
-               .active_stary_y         = 0,
-               .peak_frame_rate        = 30000, /* / _INT2FLOAT_DIVISOR */
-               .pixel_aspect_ratio     = 1000, /* / _INT2FLOAT_DIVISOR */
-               .pll_multiplier         = 11000, /* / _INT2FLOAT_DIVISOR */
-               .crop_mode              = NVC_IMAGER_CROPMODE_NONE,
-       },
-       .sensor_dnvc = {
-               .api_version            = NVC_IMAGER_API_DYNAMIC_VER,
-               .region_start_x         = 0,
-               .region_start_y         = 0,
-               .x_scale                = 1,
-               .y_scale                = 1,
-               .bracket_caps           = 1,
-               .flush_count            = 2,
-               .init_intra_frame_skip  = 0,
-               .ss_intra_frame_skip    = 2,
-               .ss_frame_number        = 3,
-               .coarse_time            = 0x09CC,
-               .max_coarse_diff        = 5,
-               .min_exposure_course    = 2,
-               .max_exposure_course    = 0xFFFC,
-               .diff_integration_time  = 110, /* / _INT2FLOAT_DIVISOR */
-               .line_length            = 0x0D70,
-               .frame_length           = 0x09D0,
-               .min_frame_length       = 0x09D0,
-               .max_frame_length       = 0xFFFF,
-               .min_gain               = 1, /* / _INT2FLOAT_DIVISOR */
-               .max_gain               = 16000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain          = 1000, /* / _INT2FLOAT_DIVISOR */
-               .inherent_gain_bin_en   = 1000, /* / _INT2FLOAT_DIVISOR */
-               .support_bin_control    = 0,
-               .support_fast_mode      = 0,
-               .pll_mult               = 0xA2,
-               .pll_div                = 0x06,
-       },
-       .p_mode_i2c                     = imx179_640x480_i2c,
-};
+       if (!info->edpc)
+               return 0;
 
-static struct imx179_mode_data *imx179_mode_table[] = {
-       &imx179_3280x2464,
-       &imx179_1640x1232,
-       &imx179_1920x1080,
-       &imx179_1280x720,
-       &imx179_640x480,
-};
+       dev_dbg(&info->i2c_client->dev, "%s %d\n", __func__, new_state);
+       ret = edp_update_client_request(info->edpc, new_state, &approved);
+       if (ret) {
+               dev_err(&info->i2c_client->dev, "E state transition failed\n");
+               return ret;
+       }
 
-static int imx179_i2c_rd8(struct imx179_info *info, u16 reg, u8 *val)
-{
-       struct i2c_msg msg[2];
-       u8 buf[3];
-
-       buf[0] = (reg >> 8);
-       buf[1] = (reg & 0x00FF);
-       msg[0].addr = info->i2c_client->addr;
-       msg[0].flags = 0;
-       msg[0].len = 2;
-       msg[0].buf = &buf[0];
-       msg[1].addr = info->i2c_client->addr;
-       msg[1].flags = I2C_M_RD;
-       msg[1].len = 1;
-       msg[1].buf = &buf[2];
-       *val = 0;
-       if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
-               return -EIO;
-
-       *val = buf[2];
+       if (approved > new_state) {
+               dev_err(&info->i2c_client->dev, "EDP no enough current\n");
+               return -ENODEV;
+       }
+
+       info->edp_state = approved;
        return 0;
 }
 
-static int imx179_i2c_rd16(struct imx179_info *info, u16 reg, u16 *val)
+static inline void
+msleep_range(unsigned int delay_base)
 {
-       struct i2c_msg msg[2];
-       u8 buf[4];
-
-       buf[0] = (reg >> 8);
-       buf[1] = (reg & 0x00FF);
-       msg[0].addr = info->i2c_client->addr;
-       msg[0].flags = 0;
-       msg[0].len = 2;
-       msg[0].buf = &buf[0];
-       msg[1].addr = info->i2c_client->addr;
-       msg[1].flags = I2C_M_RD;
-       msg[1].len = 2;
-       msg[1].buf = &buf[2];
-       *val = 0;
-       if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
-               return -EIO;
-
-       *val = (((u16)buf[2] << 8) | (u16)buf[3]);
-       return 0;
+       usleep_range(delay_base*1000, delay_base*1000+500);
 }
 
-static int imx179_i2c_wr8(struct imx179_info *info, u16 reg, u8 val)
+static inline void
+imx179_get_frame_length_regs(struct imx179_reg *regs, u32 frame_length)
 {
-       struct i2c_msg msg;
-       u8 buf[3];
-
-       buf[0] = (reg >> 8);
-       buf[1] = (reg & 0x00FF);
-       buf[2] = val;
-       msg.addr = info->i2c_client->addr;
-       msg.flags = 0;
-       msg.len = 3;
-       msg.buf = &buf[0];
-       if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
-               return -EIO;
-
-       return 0;
+       regs->addr = IMX179_FRAME_LENGTH_ADDR_MSB;
+       regs->val = (frame_length >> 8) & 0xff;
+       (regs + 1)->addr = IMX179_FRAME_LENGTH_ADDR_LSB;
+       (regs + 1)->val = (frame_length) & 0xff;
 }
 
-static int imx179_i2c_wr16(struct imx179_info *info, u16 reg, u16 val)
+static inline void
+imx179_get_coarse_time_regs(struct imx179_reg *regs, u32 coarse_time)
 {
-       struct i2c_msg msg;
-       u8 buf[4];
-
-       buf[0] = (reg >> 8);
-       buf[1] = (reg & 0x00FF);
-       buf[2] = (val & 0x00FF);
-       buf[3] = (val >> 8);
-       msg.addr = info->i2c_client->addr;
-       msg.flags = 0;
-       msg.len = 4;
-       msg.buf = &buf[0];
-       if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
-               return -EIO;
-
-       return 0;
+       regs->addr = IMX179_COARSE_TIME_ADDR_MSB;
+       regs->val = (coarse_time >> 8) & 0xff;
+       (regs + 1)->addr = IMX179_COARSE_TIME_ADDR_LSB;
+       (regs + 1)->val = (coarse_time) & 0xff;
 }
 
-static int imx179_i2c_rd_table(struct imx179_info *info,
-                              struct imx179_reg table[])
+static inline void
+imx179_get_gain_reg(struct imx179_reg *regs, u16 gain)
 {
-       struct imx179_reg *p_table = table;
-       u8 val;
-       int err = 0;
-
-       while (p_table->addr != IMX179_TABLE_END) {
-               err = imx179_i2c_rd8(info, p_table->addr, &val);
-               if (err)
-                       return err;
-
-               p_table->val = (u16)val;
-               p_table++;
-       }
+       regs->addr = IMX179_GAIN_ADDR;
+       regs->val = gain;
+}
 
-       return err;
+static inline int
+imx179_read_reg(struct imx179_info *info, u16 addr, u8 *val)
+{
+       return regmap_read(info->regmap, addr, (unsigned int *) val);
 }
 
-static int imx179_i2c_wr_blk(struct imx179_info *info, u8 *buf, int len)
+static int
+imx179_write_reg(struct imx179_info *info, u16 addr, u8 val)
 {
-       struct i2c_msg msg;
+       int err;
 
-       msg.addr = info->i2c_client->addr;
-       msg.flags = 0;
-       msg.len = len;
-       msg.buf = buf;
-       if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
-               return -EIO;
+               pr_err("%s:i2c write, %x = %x\n",
+                       __func__, addr, val);
+       err = regmap_write(info->regmap, addr, val);
 
-       return 0;
+       if (err)
+               pr_err("%s:i2c write failed, %x = %x\n",
+                       __func__, addr, val);
+
+       return err;
 }
 
-static int imx179_i2c_wr_table(struct imx179_info *info,
-                              struct imx179_reg table[])
+static int
+imx179_write_table(struct imx179_info *info,
+                                const struct imx179_reg table[],
+                                const struct imx179_reg override_list[],
+                                int num_override_regs)
 {
        int err;
        const struct imx179_reg *next;
-       const struct imx179_reg *n_next;
-       u8 *b_ptr = info->i2c_buf;
-       u16 buf_count = 0;
+       int i;
+       u16 val;
 
        for (next = table; next->addr != IMX179_TABLE_END; next++) {
                if (next->addr == IMX179_TABLE_WAIT_MS) {
-                       msleep(next->val);
+                       msleep_range(next->val);
                        continue;
                }
 
-               if (!buf_count) {
-                       b_ptr = info->i2c_buf;
-                       *b_ptr++ = next->addr >> 8;
-                       *b_ptr++ = next->addr & 0xFF;
-                       buf_count = 2;
+               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;
+                               }
+                       }
                }
-               *b_ptr++ = next->val;
-               buf_count++;
-               n_next = next + 1;
-               if (n_next->addr == next->addr + 1 &&
-                               n_next->addr != IMX179_TABLE_WAIT_MS &&
-                               buf_count < IMX179_SIZEOF_I2C_BUF &&
-                               n_next->addr != IMX179_TABLE_END)
-                       continue;
 
-               err = imx179_i2c_wr_blk(info, info->i2c_buf, buf_count);
-               if (err)
+               err = imx179_write_reg(info, next->addr, val);
+               if (err) {
+                       pr_err("%s:imx179_write_table:%d", __func__, err);
                        return err;
-
-               buf_count = 0;
+               }
        }
-
        return 0;
 }
 
-static inline void imx179_frame_length_reg(struct imx179_reg *regs,
-                                          u32 frame_length)
+static int imx179_get_flash_cap(struct imx179_info *info)
 {
-       regs->addr = 0x0340;
-       regs->val = (frame_length >> 8) & 0xFF;
-       (regs + 1)->addr = 0x0341;
-       (regs + 1)->val = (frame_length) & 0xFF;
-}
+       struct imx179_flash_control *fctl;
 
-static inline void imx179_coarse_time_reg(struct imx179_reg *regs,
-                                         u32 coarse_time)
-{
-       regs->addr = 0x0202;
-       regs->val = (coarse_time >> 8) & 0xFF;
-       (regs + 1)->addr = 0x0203;
-       (regs + 1)->val = (coarse_time) & 0xFF;
+       dev_dbg(&info->i2c_client->dev, "%s: %p\n", __func__, info->pdata);
+       if (info->pdata) {
+               fctl = &info->pdata->flash_cap;
+               dev_dbg(&info->i2c_client->dev,
+                       "edg: %x, st: %x, rpt: %x, dl: %x\n",
+                       fctl->edge_trig_en,
+                       fctl->start_edge,
+                       fctl->repeat,
+                       fctl->delay_frm);
+
+               if (fctl->enable)
+                       return 0;
+       }
+       return -ENODEV;
 }
 
-static inline void imx179_gain_reg(struct imx179_reg *regs, u32 gain)
+static inline int imx179_set_flash_control(
+       struct imx179_info *info, struct imx179_flash_control *fc)
 {
-       regs->addr = 0x0205;
-       regs->val = gain & 0xFF;
+       dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+       return imx179_write_reg(info, 0x0802, 0x01);
 }
 
-static int imx179_bin_wr(struct imx179_info *info, u8 enable)
+static int
+imx179_set_mode(struct imx179_info *info, struct imx179_mode *mode)
 {
-       int err = 0;
+       int sensor_mode;
+       int err;
+       struct imx179_reg reg_list[8];
 
-       if (enable == info->bin_en)
-               return 0;
+       pr_info("%s: xres %u yres %u framelength %u coarsetime %u gain %u\n",
+                        __func__, mode->xres, mode->yres, mode->frame_length,
+                        mode->coarse_time, mode->gain);
 
-       if (!info->mode_valid || !imx179_mode_table[info->mode_index]->
-                                 sensor_dnvc.support_bin_control)
+       if (mode->xres == 3280 && mode->yres == 2464) {
+               sensor_mode = IMX179_MODE_3280X2464;
+       } else {
+               pr_err("%s: invalid resolution supplied to set mode %d %d\n",
+                        __func__, mode->xres, mode->yres);
                return -EINVAL;
+       }
 
-       if (!err)
-               info->bin_en = enable;
-       dev_dbg(&info->i2c_client->dev, "%s bin_en=%x err=%d\n",
-               __func__, info->bin_en, err);
-       return err;
-}
-
-static int imx179_exposure_wr(struct imx179_info *info,
-                             struct nvc_imager_bayer *mode)
-{
-       struct imx179_reg reg_list[8];
-       int err;
+       /* request highest edp state */
+       err = imx179_edp_req(info, 0);
+       if (err) {
+               dev_err(&info->i2c_client->dev,
+                       "%s: ERROR cannot set edp state! %d\n", __func__, err);
+               return err;
+       }
 
-       reg_list[0].addr = 0x0104;
-       reg_list[0].val = 0x01;
-       imx179_frame_length_reg(reg_list+1, mode->frame_length);
-       imx179_coarse_time_reg(reg_list + 3, mode->coarse_time);
-       imx179_gain_reg(reg_list + 5, mode->gain);
-       reg_list[6].addr = 0x0104;
-       reg_list[6].val = 0x00;
-       reg_list[7].addr = IMX179_TABLE_END;
-       err = imx179_i2c_wr_table(info, reg_list);
-       if (!err)
-               err = imx179_bin_wr(info, mode->bin_en);
-       return err;
-}
+       /* get a list of override regs for the asking frame length, */
+       /* coarse integration time, and gain.                       */
+       imx179_get_frame_length_regs(reg_list, mode->frame_length);
+       imx179_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
+       imx179_get_gain_reg(reg_list + 4, mode->gain);
 
-static int imx179_gain_wr(struct imx179_info *info, u32 gain)
-{
-       int err;
+       err = imx179_write_table(info,
+                               mode_table[sensor_mode],
+                               reg_list, 5);
+       if (err)
+               return err;
+       if (err)
+               return err;
 
-       gain &= 0xFF;
-       err = imx179_i2c_wr16(info, 0x0205, (u16)gain);
-       return err;
+       info->mode = sensor_mode;
+       pr_info("[IMX179]: stream on.\n");
+       return 0;
 }
 
-static int imx179_gain_rd(struct imx179_info *info, u32 *gain)
+static int
+imx179_get_status(struct imx179_info *info, u8 *dev_status)
 {
-       int err;
-
-       *gain = 0;
-       err = imx179_i2c_rd8(info, 0x0205, (u8 *)gain);
-       return err;
+       *dev_status = 0;
+       return 0;
 }
 
-static int imx179_group_hold_wr(struct imx179_info *info,
-                               struct nvc_imager_ae *ae)
+static int
+imx179_set_frame_length(struct imx179_info *info, u32 frame_length,
+                                                bool group_hold)
 {
-       int err;
-       bool groupHoldEnable;
-       struct imx179_reg reg_list[6];
-       int count = 0;
+       struct imx179_reg reg_list[2];
+       int i = 0;
+       int ret;
 
-       groupHoldEnable = ae->gain_enable |
-                                       ae->frame_length_enable |
-                                       ae->coarse_time_enable;
+       imx179_get_frame_length_regs(reg_list, frame_length);
 
-       if (groupHoldEnable) {
-               err = imx179_i2c_wr8(info, 0x0104, 1);
-               if (err) {
-                       dev_err(&info->i2c_client->dev,
-                               "Error: %s fail to enable grouphold\n",
-                               __func__);
-                       return err;
-               }
+       if (group_hold) {
+               ret = imx179_write_reg(info, 0x0104, 0x01);
+               if (ret)
+                       return ret;
        }
 
-       if (ae->gain_enable) {
-               imx179_gain_reg(reg_list + count, ae->gain);
-               count += 1;
-       }
-       if (ae->coarse_time_enable) {
-               imx179_coarse_time_reg(reg_list + count, ae->coarse_time);
-               count += 2;
-       }
-       if (ae->frame_length_enable) {
-               imx179_frame_length_reg(reg_list + count, ae->frame_length);
-               count += 2;
-       }
-       reg_list[count].addr = IMX179_TABLE_END;
-       err = imx179_i2c_wr_table(info, reg_list);
-       if (err) {
-               dev_err(&info->i2c_client->dev, "Error: %s i2c wr_table fail\n",
-                       __func__);
+       for (i = 0; i < 2; i++) {
+               ret = imx179_write_reg(info, reg_list[i].addr,
+                        reg_list[i].val);
+               if (ret)
+                       return ret;
        }
 
-       if (groupHoldEnable) {
-               err = imx179_i2c_wr8(info, 0x0104, 0);
-               if (err) {
-                       dev_err(&info->i2c_client->dev,
-                               "Error: %s fail to release grouphold\n",
-                               __func__);
-               }
+       if (group_hold) {
+               ret = imx179_write_reg(info, 0x0104, 0x0);
+               if (ret)
+                       return ret;
        }
-       return err;
-}
 
-static int imx179_test_pattern_wr(struct imx179_info *info, unsigned pattern)
-{
-       if (pattern >= ARRAY_SIZE(test_patterns))
-               return -EINVAL;
-
-       return imx179_i2c_wr_table(info, test_patterns[pattern]);
+       return 0;
 }
 
-static int imx179_set_flash_output(struct imx179_info *info)
+static int
+imx179_set_coarse_time(struct imx179_info *info, u32 coarse_time,
+                                                bool group_hold)
 {
-       struct imx179_flash_config *fcfg;
-       u8 val = 0;
-       int ret = 0;
+       int ret;
 
-       if (!info->pdata)
-               return 0;
+       struct imx179_reg reg_list[2];
+       int i = 0;
 
-       fcfg = &info->pdata->flash_cap;
-       if (fcfg->xvs_trigger_enabled)
-               val |= 0x0c;
-       if (fcfg->sdo_trigger_enabled)
-               val |= 0x02;
-       dev_dbg(&info->i2c_client->dev, "%s: %02x\n", __func__, val);
-       /* disable all flash pulse output */
-       ret = imx179_i2c_wr8(info, 0x304A, 0);
-       /* config XVS/SDO pin output mode */
-       ret |= imx179_i2c_wr8(info, 0x3240, val);
-       /* set the control pulse width settings - Gain + Step
-        * Pulse width(sec) = 64 * 2^(Gain) * (Step + 1) / Logic Clk
-        * Logic Clk = ExtClk * PLL Multipiler / Pre_Div / Post_Div
-        * / Logic Clk Division Ratio
-        * Logic Clk Division Ratio = 5 @4lane, 10 @2lane, 20 @1lane
-        */
-       ret |= imx179_i2c_wr8(info, 0x307C, 0x07);
-       ret |= imx179_i2c_wr8(info, 0x307D, 0x3F);
-       return ret;
-}
+       imx179_get_coarse_time_regs(reg_list, coarse_time);
 
-static void imx179_get_flash_cap(struct imx179_info *info)
-{
-       struct nvc_imager_cap *fcap = info->cap;
-       struct imx179_flash_config *fcfg;
+       if (group_hold) {
+               ret = imx179_write_reg(info, 0x104, 0x01);
+               if (ret)
+                       return ret;
+       }
 
-       if (!info->pdata)
-               return;
+       for (i = 0; i < 2; i++) {
+               ret = imx179_write_reg(info, reg_list[i].addr,
+                        reg_list[i].val);
+               if (ret)
+                       return ret;
+       }
 
-       fcfg = &info->pdata->flash_cap;
-       fcap->flash_control_enabled =
-               fcfg->xvs_trigger_enabled | fcfg->sdo_trigger_enabled;
-       fcap->adjustable_flash_timing = fcfg->adjustable_flash_timing;
+       if (group_hold) {
+               ret = imx179_write_reg(info, 0x104, 0x0);
+               if (ret)
+                       return ret;
+       }
+       return 0;
 }
 
-static int imx179_flash_control(
-       struct imx179_info *info, union nvc_imager_flash_control *fm)
+static int
+imx179_set_gain(struct imx179_info *info, u16 gain, bool group_hold)
 {
        int ret;
-       u8 f_cntl;
-       u8 f_tim;
+       struct imx179_reg reg_list;
 
-       if (!info->pdata)
-               return -EFAULT;
+       imx179_get_gain_reg(&reg_list, gain);
 
-       ret = imx179_i2c_wr8(info, 0x304A, 0);
-       f_tim = 0;
-       f_cntl = 0;
-       if (fm->settings.enable) {
-               if (fm->settings.edge_trig_en) {
-                       f_cntl |= 0x10;
-                       if (fm->settings.start_edge)
-                               f_tim |= 0x08;
-                       if (fm->settings.repeat)
-                               f_tim |= 0x04;
-                       f_tim |= fm->settings.delay_frm & 0x03;
-               } else
-                       f_cntl |= 0x20;
+       if (group_hold) {
+               ret = imx179_write_reg(info, 0x104, 0x1);
+               if (ret)
+                       return ret;
        }
-       ret |= imx179_i2c_wr8(info, 0x307B, f_tim);
-       ret |= imx179_i2c_wr8(info, 0x304A, f_cntl);
 
-       dev_dbg(&info->i2c_client->dev,
-               "%s: %04x %02x %02x\n", __func__, fm->mode, f_tim, f_cntl);
-       return ret;
-}
+       ret = imx179_write_reg(info, reg_list.addr, reg_list.val);
+       if (ret)
+               return ret;
 
-static int imx179_gpio_rd(struct imx179_info *info,
-                         enum imx179_gpio i)
-{
-       int val = -EINVAL;
-
-       if (info->gpio[i].flag) {
-               val = gpio_get_value_cansleep(info->gpio[i].gpio);
-               if (val)
-                       val = 1;
-               dev_dbg(&info->i2c_client->dev, "%s %u %d\n",
-                       __func__, info->gpio[i].gpio, val);
-               if (!info->gpio[i].active_high)
-                       val = !val;
-               val &= 1;
+       if (group_hold) {
+               ret = imx179_write_reg(info, 0x104, 0x0);
+               if (ret)
+                       return ret;
        }
-       return val; /* return read value or error */
+       return 0;
 }
 
-static int imx179_gpio_wr(struct imx179_info *info,
-                         enum imx179_gpio i,
-                         int val) /* val: 0=deassert, 1=assert */
+static int
+imx179_set_group_hold(struct imx179_info *info, struct imx179_ae *ae)
 {
-       int err = -EINVAL;
-
-       if (info->gpio[i].flag) {
-               if (val)
-                       val = 1;
-               if (!info->gpio[i].active_high)
-                       val = !val;
-               val &= 1;
-               err = val;
-               gpio_set_value_cansleep(info->gpio[i].gpio, val);
-               dev_dbg(&info->i2c_client->dev, "%s %u %d\n",
-                       __func__, info->gpio[i].gpio, val);
+       int ret;
+       int count = 0;
+       bool group_hold_enabled = false;
+
+       if (ae->gain_enable)
+               count++;
+       if (ae->coarse_time_enable)
+               count++;
+       if (ae->frame_length_enable)
+               count++;
+       if (count >= 2)
+               group_hold_enabled = true;
+
+       if (group_hold_enabled) {
+               ret = imx179_write_reg(info, 0x104, 0x1);
+               if (ret)
+                       return ret;
        }
-       return err; /* return value written or error */
-}
-
-static int imx179_gpio_pwrdn(struct imx179_info *info, int val)
-{
-       int prev_val;
 
-       prev_val = imx179_gpio_rd(info, IMX179_GPIO_PWDN);
-       if (prev_val < 0)
-               return 1; /* assume PWRDN hardwired deasserted */
-
-       if (val == prev_val)
-               return 0; /* no change */
-
-       imx179_gpio_wr(info, IMX179_GPIO_PWDN, val);
-       return 1; /* return state change */
-}
-
-static int imx179_gpio_reset(struct imx179_info *info, int val)
-{
-       int err = 0;
-
-       if (val) {
-               if (!info->reset_flag) {
-                       info->reset_flag = true;
-                       err = imx179_gpio_wr(info, IMX179_GPIO_RESET, 1);
-                       if (err < 0)
-                               return 0; /* flag no reset */
-
-                       usleep_range(1000, 1500);
-                       imx179_gpio_wr(info, IMX179_GPIO_RESET, 0);
-                       msleep(IMX179_STARTUP_DELAY_MS); /* startup delay */
-                       err = 1; /* flag that a reset was done */
-               }
-       } else {
-               info->reset_flag = false;
+       if (ae->gain_enable)
+               imx179_set_gain(info, ae->gain, false);
+       if (ae->coarse_time_enable)
+               imx179_set_coarse_time(info, ae->coarse_time, true);
+       if (ae->frame_length_enable)
+               imx179_set_frame_length(info, ae->frame_length, false);
+
+       if (group_hold_enabled) {
+               ret = imx179_write_reg(info, 0x104, 0x0);
+               if (ret)
+                       return ret;
        }
-       return err;
-}
 
-static void imx179_gpio_able(struct imx179_info *info, int val)
-{
-       if (val)
-               imx179_gpio_wr(info, IMX179_GPIO_GP1, val);
-       else
-               imx179_gpio_wr(info, IMX179_GPIO_GP1, val);
+       return 0;
 }
 
-static void imx179_gpio_exit(struct imx179_info *info)
+static int imx179_get_sensor_id(struct imx179_info *info)
 {
-       unsigned i;
+       int ret = 0;
+       int i;
+       u8 bak = 0;
 
-       for (i = 0; i < ARRAY_SIZE(imx179_gpios); i++) {
-               if (info->gpio[i].flag && info->gpio[i].own) {
-                       gpio_free(info->gpio[i].gpio);
-                       info->gpio[i].own = false;
-               }
-       }
-}
+       pr_info("%s\n", __func__);
+       if (info->sensor_data.fuse_id_size)
+               return 0;
 
-static void imx179_gpio_init(struct imx179_info *info)
-{
-       char label[32];
-       unsigned long flags;
-       unsigned type;
-       unsigned i;
-       unsigned j;
-       int err;
+       /* Note 1: If the sensor does not have power at this point
+       Need to supply the power, e.g. by calling power on function */
 
-       for (i = 0; i < ARRAY_SIZE(imx179_gpios); i++)
-               info->gpio[i].flag = false;
-       if (!info->pdata->gpio_count || !info->pdata->gpio)
-               return;
+       /*ret |= imx179_write_reg(info, 0x3B02, 0x00);
+       ret |= imx179_write_reg(info, 0x3B00, 0x01);
+       for (i = 0; i < 9; i++) {
+               ret |= imx179_read_reg(info, 0x3B24 + i, &bak);
+               info->sensor_data.fuse_id[i] = bak;
+       }
 
-       for (i = 0; i < ARRAY_SIZE(imx179_gpios); i++) {
-               type = imx179_gpios[i].gpio_type;
-               for (j = 0; j < info->pdata->gpio_count; j++) {
-                       if (type == info->pdata->gpio[j].gpio_type)
-                               break;
-               }
-               if (j == info->pdata->gpio_count)
-                       continue;
+       if (!ret)
+               info->sensor_data.fuse_id_size = i;*/
 
-               info->gpio[type].gpio = info->pdata->gpio[j].gpio;
-               info->gpio[type].flag = true;
-               if (imx179_gpios[i].use_flags) {
-                       flags = imx179_gpios[i].flags;
-                       info->gpio[type].active_high =
-                                                  imx179_gpios[i].active_high;
-               } else {
-                       info->gpio[type].active_high =
-                                             info->pdata->gpio[j].active_high;
-                       if (info->gpio[type].active_high)
-                               flags = GPIOF_OUT_INIT_LOW;
-                       else
-                               flags = GPIOF_OUT_INIT_HIGH;
-               }
-               if (!info->pdata->gpio[j].init_en)
-                       continue;
+       /* Note 2: Need to clean up any action carried out in Note 1 */
 
-               snprintf(label, sizeof(label), "imx179_%u_%s",
-                        info->pdata->num, imx179_gpios[i].label);
-               err = gpio_request_one(info->gpio[type].gpio, flags, label);
-               if (err) {
-                       dev_err(&info->i2c_client->dev, "%s ERR %s %u\n",
-                               __func__, label, info->gpio[type].gpio);
-               } else {
-                       info->gpio[type].own = true;
-                       dev_dbg(&info->i2c_client->dev, "%s %s %u\n",
-                               __func__, label, info->gpio[type].gpio);
-               }
-       }
+       return ret;
 }
 
 static void imx179_mclk_disable(struct imx179_info *info)
@@ -1296,8 +583,7 @@ static void imx179_mclk_disable(struct imx179_info *info)
 static int imx179_mclk_enable(struct imx179_info *info)
 {
        int err;
-       unsigned long mclk_init_rate =
-               nvc_imager_get_mclk(info->cap, &imx179_dflt_cap, 0);
+       unsigned long mclk_init_rate = 24000000;
 
        dev_dbg(&info->i2c_client->dev, "%s: enable MCLK with %lu Hz\n",
                __func__, mclk_init_rate);
@@ -1305,1242 +591,527 @@ static int imx179_mclk_enable(struct imx179_info *info)
        err = clk_set_rate(info->mclk, mclk_init_rate);
        if (!err)
                err = clk_prepare_enable(info->mclk);
-
        return err;
 }
 
-static int imx179_vreg_dis_all(struct imx179_info *info)
-{
-       int err;
-
-       if (!info->pdata || !info->pdata->power_off)
-               return -EFAULT;
-
-       err = info->pdata->power_off(info->vreg);
-
-       imx179_mclk_disable(info);
-
-    return err;
-}
-
-static int imx179_vreg_en_all(struct imx179_info *info)
+static long
+imx179_ioctl(struct file *file,
+                        unsigned int cmd, unsigned long arg)
 {
        int err = 0;
-       if (!info->pdata || !info->pdata->power_on)
-               return -EFAULT;
-
-       err = imx179_mclk_enable(info);
-       if (err)
-               return err;
-
-       err = info->pdata->power_on(info->vreg);
-       if (err < 0)
-               imx179_mclk_disable(info);
-
-       return err;
-}
-
-static void imx179_vreg_exit(struct imx179_info *info)
-{
-       unsigned i;
+       struct imx179_info *info = file->private_data;
 
-       for (i = 0; i < ARRAY_SIZE(imx179_vregs); i++) {
-               regulator_put(info->vreg[i].vreg);
-               info->vreg[i].vreg = NULL;
+       switch (cmd) {
+       case IMX179_IOCTL_SET_POWER:
+               if (!info->pdata)
+                       break;
+               if (arg && info->pdata->power_on) {
+                       err = imx179_mclk_enable(info);
+                       if (!err)
+                               err = info->pdata->power_on(&info->power);
+                       if (err < 0)
+                               imx179_mclk_disable(info);
+               }
+               if (!arg && info->pdata->power_off) {
+                       info->pdata->power_off(&info->power);
+                       imx179_mclk_disable(info);
+                       imx179_edp_lowest(info);
+               }
+               break;
+       case IMX179_IOCTL_SET_MODE:
+       {
+               struct imx179_mode mode;
+               if (copy_from_user(&mode, (const void __user *)arg,
+                       sizeof(struct imx179_mode))) {
+                       pr_err("%s:Failed to get mode from user.\n", __func__);
+                       return -EFAULT;
+               }
+               return imx179_set_mode(info, &mode);
        }
-}
-
-static int imx179_vreg_init(struct imx179_info *info)
-{
-       unsigned i;
-       unsigned j;
-       int err = 0;
+       case IMX179_IOCTL_SET_FRAME_LENGTH:
+               return imx179_set_frame_length(info, (u32)arg, true);
+       case IMX179_IOCTL_SET_COARSE_TIME:
+               return imx179_set_coarse_time(info, (u32)arg, true);
+       case IMX179_IOCTL_SET_GAIN:
+               return imx179_set_gain(info, (u16)arg, true);
+       case IMX179_IOCTL_GET_STATUS:
+       {
+               u8 status;
 
-       for (i = 0; i < ARRAY_SIZE(imx179_vregs); i++) {
-               j = imx179_vregs[i].vreg_num;
-               info->vreg[j].vreg_name = imx179_vregs[i].vreg_name;
-               info->vreg[j].vreg_flag = false;
-               info->vreg[j].vreg = regulator_get(&info->i2c_client->dev,
-                                                  info->vreg[j].vreg_name);
-               if (IS_ERR(info->vreg[j].vreg)) {
-                       dev_dbg(&info->i2c_client->dev, "%s %s ERR: %d\n",
-                               __func__, info->vreg[j].vreg_name,
-                               (int)info->vreg[j].vreg);
-                       err |= PTR_ERR(info->vreg[j].vreg);
-                       info->vreg[j].vreg = NULL;
-               } else {
-                       dev_dbg(&info->i2c_client->dev, "%s: %s\n",
-                               __func__, info->vreg[j].vreg_name);
+               err = imx179_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;
        }
-       return err;
-}
-
-static int imx179_pm_wr(struct imx179_info *info, int pwr)
-{
-       int ret;
-       int err = 0;
+       case IMX179_IOCTL_GET_SENSORDATA:
+       {
+               err = imx179_get_sensor_id(info);
 
-       if ((info->pdata->cfg & (NVC_CFG_OFF2STDBY | NVC_CFG_BOOT_INIT)) &&
-                       (pwr == NVC_PWR_OFF ||
-                        pwr == NVC_PWR_STDBY_OFF))
-               pwr = NVC_PWR_STDBY;
-       if (pwr == info->pwr_dev)
+               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 imx179_sensordata))) {
+                       pr_info("%s:Failed to copy fuse id to user space\n",
+                               __func__);
+                       return -EFAULT;
+               }
                return 0;
+       }
+       case IMX179_IOCTL_SET_GROUP_HOLD:
+       {
+               struct imx179_ae ae;
+               if (copy_from_user(&ae, (const void __user *)arg,
+                       sizeof(struct imx179_ae))) {
+                       pr_info("%s:fail group hold\n", __func__);
+                       return -EFAULT;
+               }
+               return imx179_set_group_hold(info, &ae);
+       }
+       case IMX179_IOCTL_SET_FLASH_MODE:
+       {
+               struct imx179_flash_control values;
 
-       switch (pwr) {
-       case NVC_PWR_OFF_FORCE:
-       case NVC_PWR_OFF:
-       case NVC_PWR_STDBY_OFF:
-               imx179_gpio_pwrdn(info, 1);
-               err = imx179_vreg_dis_all(info);
-               imx179_gpio_able(info, 0);
-               imx179_gpio_reset(info, 0);
-               info->mode_valid = false;
-               info->bin_en = 0;
-               break;
-
-       case NVC_PWR_STDBY:
-               imx179_gpio_pwrdn(info, 1);
-               err = imx179_vreg_en_all(info);
-               imx179_gpio_able(info, 1);
+               dev_dbg(&info->i2c_client->dev,
+                       "IMX179_IOCTL_SET_FLASH_MODE\n");
+               if (copy_from_user(&values,
+                       (const void __user *)arg,
+                       sizeof(struct imx179_flash_control))) {
+                       err = -EFAULT;
+                       break;
+               }
+               err = imx179_set_flash_control(info, &values);
                break;
-
-       case NVC_PWR_COMM:
-       case NVC_PWR_ON:
-               if (info->pwr_dev != NVC_PWR_ON &&
-                               info->pwr_dev != NVC_PWR_COMM)
-                       imx179_gpio_pwrdn(info, 1);
-               err = imx179_vreg_en_all(info);
-               imx179_gpio_able(info, 1);
-               ret = imx179_gpio_pwrdn(info, 0);
-               ret &= !imx179_gpio_reset(info, 1);
-               if (ret) /* if no reset && pwrdn changed states then delay */
-                       msleep(IMX179_STARTUP_DELAY_MS);
+       }
+       case IMX179_IOCTL_GET_FLASH_CAP:
+               err = imx179_get_flash_cap(info);
                break;
-
        default:
+               pr_err("%s:unknown cmd.\n", __func__);
                err = -EINVAL;
-               break;
-       }
-
-       if (err < 0) {
-               dev_err(&info->i2c_client->dev, "%s err %d\n", __func__, err);
-               pwr = NVC_PWR_ERR;
        }
-       info->pwr_dev = pwr;
-       dev_dbg(&info->i2c_client->dev, "%s pwr_dev=%d\n",
-               __func__, info->pwr_dev);
-       if (err > 0)
-               return 0;
 
        return err;
 }
 
-static int imx179_pm_wr_s(struct imx179_info *info, int pwr)
+static int imx179_debugfs_show(struct seq_file *s, void *unused)
 {
-       int err1 = 0;
-       int err2 = 0;
-
-       if ((info->s_mode == NVC_SYNC_OFF) ||
-                       (info->s_mode == NVC_SYNC_MASTER) ||
-                       (info->s_mode == NVC_SYNC_STEREO))
-               err1 = imx179_pm_wr(info, pwr);
-       if ((info->s_mode == NVC_SYNC_SLAVE) ||
-                       (info->s_mode == NVC_SYNC_STEREO))
-               err2 = imx179_pm_wr(info->s_info, pwr);
-       return err1 | err2;
-}
+       struct imx179_info *dev = s->private;
 
-static int imx179_pm_api_wr(struct imx179_info *info, int pwr)
-{
-       int err = 0;
+       dev_dbg(&dev->i2c_client->dev, "%s: ++\n", __func__);
 
-       if (!pwr || (pwr > NVC_PWR_ON))
-               return 0;
+       mutex_lock(&dev->imx179_camera_lock);
+       mutex_unlock(&dev->imx179_camera_lock);
 
-       if (pwr > info->pwr_dev)
-               err = imx179_pm_wr_s(info, pwr);
-       if (!err)
-               info->pwr_api = pwr;
-       else
-               info->pwr_api = NVC_PWR_ERR;
-       if (info->pdata->cfg & NVC_CFG_NOERR)
-               return 0;
-
-       return err;
-}
-
-static int imx179_pm_dev_wr(struct imx179_info *info, int pwr)
-{
-       if (pwr < info->pwr_api)
-               pwr = info->pwr_api;
-       if (info->mode_enable)
-               pwr = NVC_PWR_ON;
-       return imx179_pm_wr(info, pwr);
+       return 0;
 }
 
-static void imx179_pm_exit(struct imx179_info *info)
+static ssize_t imx179_debugfs_write(
+       struct file *file,
+       char const __user *buf,
+       size_t count,
+       loff_t *offset)
 {
-       imx179_pm_wr(info, NVC_PWR_OFF_FORCE);
-       imx179_vreg_exit(info);
-       imx179_gpio_exit(info);
+       struct imx179_info *dev =
+                       ((struct seq_file *)file->private_data)->private;
+       struct i2c_client *i2c_client = dev->i2c_client;
+       int ret = 0;
+       char buffer[MAX_BUFFER_SIZE];
+       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 |= imx179_write_reg(dev, address, data);
+read:
+       ret |= imx179_read_reg(dev, 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 void imx179_pm_init(struct imx179_info *info)
+static int imx179_debugfs_open(struct inode *inode, struct file *file)
 {
-       imx179_gpio_init(info);
-       imx179_vreg_init(info);
-}
+       struct imx179_info *dev = inode->i_private;
+       struct i2c_client *i2c_client = dev->i2c_client;
 
-static int imx179_reset(struct imx179_info *info, u32 level)
-{
-       int err;
+       dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
 
-       if (level == NVC_RESET_SOFT) {
-               err = imx179_pm_wr(info, NVC_PWR_COMM);
-               err |= imx179_i2c_wr8(info, 0x0103, 0x01); /* SW reset */
-       } else {
-               err = imx179_pm_wr(info, NVC_PWR_OFF_FORCE);
-       }
-       err |= imx179_pm_wr(info, info->pwr_api);
-       return err;
-}
-
-static int imx179_dev_id(struct imx179_info *info)
-{
-       u16 val = 0;
-       unsigned i;
-       int err;
-
-       dev_dbg(&info->i2c_client->dev, "%s +++++\n",
-                       __func__);
-       imx179_pm_dev_wr(info, NVC_PWR_COMM);
-       dev_dbg(&info->i2c_client->dev, "DUCK:%s:%d\n",
-                       __func__, __LINE__);
-       err = imx179_i2c_rd16(info, IMX179_ID_ADDRESS, &val);
-       if (!err) {
-               dev_dbg(&info->i2c_client->dev, "%s found devId: %x\n",
-                       __func__, val);
-               info->sdata.sensor_id_minor = 0;
-               for (i = 0; i < ARRAY_SIZE(imx179_ids); i++) {
-                       if (val == imx179_ids[i]) {
-                               info->sdata.sensor_id_minor = val;
-                               break;
-                       }
-               }
-               if (!info->sdata.sensor_id_minor) {
-                       err = -ENODEV;
-                       dev_dbg(&info->i2c_client->dev, "%s No devId match\n",
-                               __func__);
-               }
-       }
-       imx179_pm_dev_wr(info, NVC_PWR_OFF);
-       dev_dbg(&info->i2c_client->dev, "%s -----\n",
-                       __func__);
-       return err;
+       return single_open(file, imx179_debugfs_show, inode->i_private);
 }
 
-static int imx179_mode_able(struct imx179_info *info, bool mode_enable)
-{
-       u8 val;
-       int err;
-
-       if (mode_enable)
-               val = IMX179_STREAM_ENABLE;
-       else
-               val = IMX179_STREAM_DISABLE;
-       err = imx179_i2c_wr8(info, IMX179_STREAM_CONTROL_REG, val);
-       if (!err) {
-               info->mode_enable = mode_enable;
-               dev_dbg(&info->i2c_client->dev, "%s streaming=%x\n",
-                       __func__, info->mode_enable);
-               if (!mode_enable)
-                       imx179_pm_dev_wr(info, NVC_PWR_OFF);
-       }
-       msleep(IMX179_WAIT_MS);
-       return err;
-}
+static const struct file_operations imx179_debugfs_fops = {
+       .open           = imx179_debugfs_open,
+       .read           = seq_read,
+       .write          = imx179_debugfs_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
-static int imx179_mode_rd(struct imx179_info *info,
-                         s32 res_x,
-                         s32 res_y,
-                         u32 *index)
+static void imx179_remove_debugfs(struct imx179_info *dev)
 {
-       int i;
-
-       if (!res_x && !res_y) {
-               *index = info->cap->preferred_mode_index;
-               return 0;
-       }
+       struct i2c_client *i2c_client = dev->i2c_client;
 
-       for (i = 0; i < IMX179_NUM_MODES; i++) {
-               if ((res_x == imx179_mode_table[i]->sensor_mode.res_x) &&
-                   (res_y == imx179_mode_table[i]->sensor_mode.res_y)) {
-                       break;
-               }
-       }
-
-       if (i == IMX179_NUM_MODES) {
-               dev_err(&info->i2c_client->dev,
-                       "%s invalid resolution: %dx%d\n",
-                       __func__, res_x, res_y);
-               return -EINVAL;
-       }
+       dev_dbg(&i2c_client->dev, "%s: ++\n", __func__);
 
-       *index = i;
-       return 0;
+       debugfs_remove_recursive(dev->debugdir);
+       dev->debugdir = NULL;
 }
 
-static int imx179_mode_wr_full(struct imx179_info *info, u32 mode_index)
+static void imx179_create_debugfs(struct imx179_info *dev)
 {
-       int err;
-
-       imx179_pm_dev_wr(info, NVC_PWR_ON);
-       imx179_bin_wr(info, 0);
-       err = imx179_i2c_wr_table(info,
-                                 imx179_mode_table[mode_index]->p_mode_i2c);
-       if (!err) {
-               info->mode_index = mode_index;
-               info->mode_valid = true;
-       } else {
-               info->mode_valid = false;
-       }
-
-       return err;
+       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,
+                               &imx179_debugfs_fops);
+       if (!ret)
+               goto remove_debugfs;
+
+       return;
+remove_debugfs:
+       dev_err(&i2c_client->dev, "couldn't create debugfs\n");
+       imx179_remove_debugfs(dev);
 }
 
-static int imx179_mode_wr(struct imx179_info *info,
-                         struct nvc_imager_bayer *mode)
+static int imx179_get_extra_regulators(struct imx179_power_rail *pw)
 {
-       u32 mode_index;
-       int err;
-
-       err = imx179_mode_rd(info, mode->res_x, mode->res_y, &mode_index);
-       if (err < 0)
-               return err;
-
-       if (!mode->res_x && !mode->res_y) {
-               if (mode->frame_length || mode->coarse_time || mode->gain) {
-                       /* write exposure only */
-                       err = imx179_exposure_wr(info, mode);
-                       return err;
-               } else {
-                       /* turn off streaming */
-                       err = imx179_mode_able(info, false);
-                       return err;
+       if (!pw->ext_reg1) {
+               pw->ext_reg1 = regulator_get(NULL, "imx179_reg1");
+               if (WARN_ON(IS_ERR(pw->ext_reg1))) {
+                       pr_err("%s: can't get regulator imx179_reg1: %ld\n",
+                               __func__, PTR_ERR(pw->ext_reg1));
+                       pw->ext_reg1 = NULL;
+                       return -ENODEV;
                }
        }
 
-       if (!info->mode_valid || (info->mode_index != mode_index))
-               err = imx179_mode_wr_full(info, mode_index);
-       else
-               dev_dbg(&info->i2c_client->dev, "%s short mode\n", __func__);
-       err |= imx179_exposure_wr(info, mode);
-       if (err < 0) {
-               info->mode_valid = false;
-               goto imx179_mode_wr_err;
+       if (!pw->ext_reg2) {
+               pw->ext_reg2 = regulator_get(NULL, "imx179_reg2");
+               if (WARN_ON(IS_ERR(pw->ext_reg2))) {
+                       pr_err("%s: can't get regulator imx179_reg2: %ld\n",
+                               __func__, PTR_ERR(pw->ext_reg2));
+                       pw->ext_reg2 = NULL;
+                       return -ENODEV;
+               }
        }
 
-       err = imx179_set_flash_output(info);
-
-       err |= imx179_mode_able(info, true);
-       if (err < 0)
-               goto imx179_mode_wr_err;
-
        return 0;
-
-imx179_mode_wr_err:
-       if (!info->mode_enable)
-               imx179_pm_dev_wr(info, NVC_PWR_STDBY);
-       return err;
 }
 
-
-static int imx179_param_rd(struct imx179_info *info, unsigned long arg)
+static int imx179_power_on(struct imx179_power_rail *pw)
 {
-       struct nvc_param params;
-       struct imx179_reg *p_i2c_table;
-       const void *data_ptr;
-       u32 data_size = 0;
-       u32 u32val;
        int err;
+       struct imx179_info *info = container_of(pw, struct imx179_info, power);
 
-       if (copy_from_user(&params,
-                          (const void __user *)arg,
-                          sizeof(struct nvc_param))) {
-               dev_err(&info->i2c_client->dev,
-                       "%s copy_from_user err line %d\n", __func__, __LINE__);
+       if (unlikely(WARN_ON(!pw || !pw->iovdd || !pw->avdd)))
                return -EFAULT;
-       }
-
-       if (info->s_mode == NVC_SYNC_SLAVE)
-               info = info->s_info;
-
-       switch (params.param) {
-       case NVC_PARAM_GAIN:
-               imx179_pm_dev_wr(info, NVC_PWR_COMM);
-               err = imx179_gain_rd(info, &u32val);
-               imx179_pm_dev_wr(info, NVC_PWR_OFF);
-               dev_dbg(&info->i2c_client->dev, "%s GAIN: %u err: %d\n",
-                       __func__, u32val, err);
-               if (err)
-                       return err;
-
-               data_ptr = &u32val;
-               data_size = sizeof(u32val);
-               break;
 
-       case NVC_PARAM_STEREO_CAP:
-               if (info->s_info != NULL)
-                       err = 0;
-               else
-                       err = -ENODEV;
-               dev_dbg(&info->i2c_client->dev, "%s STEREO_CAP: %d\n",
-                       __func__, err);
-               data_ptr = &err;
-               data_size = sizeof(err);
-               break;
+       if (info->pdata->ext_reg) {
+               if (imx179_get_extra_regulators(pw))
+                       goto imx179_poweron_fail;
 
-       case NVC_PARAM_STEREO:
-               dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
-                       __func__, info->s_mode);
-               data_ptr = &info->s_mode;
-               data_size = sizeof(info->s_mode);
-               break;
+               err = regulator_enable(pw->ext_reg1);
+               if (unlikely(err))
+                       goto imx179_ext_reg1_fail;
 
-       case NVC_PARAM_STS:
-               err = imx179_dev_id(info);
-               dev_dbg(&info->i2c_client->dev, "%s STS: %d\n",
-                       __func__, err);
-               data_ptr = &err;
-               data_size = sizeof(err);
-               break;
+               err = regulator_enable(pw->ext_reg2);
+               if (unlikely(err))
+                       goto imx179_ext_reg2_fail;
 
-       case NVC_PARAM_DEV_ID:
-               if (!info->sdata.sensor_id_minor)
-                       imx179_dev_id(info);
-               data_ptr = &info->sdata.sensor_id;
-               data_size = sizeof(info->sdata.sensor_id) * 2;
-               dev_dbg(&info->i2c_client->dev, "%s DEV_ID: %x-%x\n",
-                       __func__, info->sdata.sensor_id,
-                       info->sdata.sensor_id_minor);
-               break;
-
-       case NVC_PARAM_SENSOR_TYPE:
-               data_ptr = &info->sdata.sensor_type;
-               data_size = sizeof(info->sdata.sensor_type);
-               dev_dbg(&info->i2c_client->dev, "%s SENSOR_TYPE: %d\n",
-                       __func__, info->sdata.sensor_type);
-               break;
-
-       case NVC_PARAM_FOCAL_LEN:
-               data_ptr = &info->sdata.focal_len;
-               data_size = sizeof(info->sdata.focal_len);
-               dev_dbg(&info->i2c_client->dev, "%s FOCAL_LEN: %u\n",
-                       __func__, info->sdata.focal_len);
-               break;
-
-       case NVC_PARAM_MAX_APERTURE:
-               data_ptr = &info->sdata.max_aperture;
-               data_size = sizeof(info->sdata.max_aperture);
-               dev_dbg(&info->i2c_client->dev, "%s MAX_APERTURE: %u\n",
-                       __func__, info->sdata.max_aperture);
-               break;
-
-       case NVC_PARAM_FNUMBER:
-               data_ptr = &info->sdata.fnumber;
-               data_size = sizeof(info->sdata.fnumber);
-               dev_dbg(&info->i2c_client->dev, "%s FNUMBER: %u\n",
-                       __func__, info->sdata.fnumber);
-               break;
-
-       case NVC_PARAM_VIEW_ANGLE_H:
-               data_ptr = &info->sdata.view_angle_h;
-               data_size = sizeof(info->sdata.view_angle_h);
-               dev_dbg(&info->i2c_client->dev, "%s VIEW_ANGLE_H: %u\n",
-                       __func__, info->sdata.view_angle_h);
-               break;
-
-       case NVC_PARAM_VIEW_ANGLE_V:
-               data_ptr = &info->sdata.view_angle_v;
-               data_size = sizeof(info->sdata.view_angle_v);
-               dev_dbg(&info->i2c_client->dev, "%s VIEW_ANGLE_V: %u\n",
-                       __func__, info->sdata.view_angle_v);
-               break;
-
-       case NVC_PARAM_I2C:
-               dev_dbg(&info->i2c_client->dev, "%s I2C\n", __func__);
-               if (params.sizeofvalue > IMX179_I2C_TABLE_MAX_ENTRIES) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s NVC_PARAM_I2C request size too large\n",
-                               __func__);
-                       return -EINVAL;
-               }
-               p_i2c_table = kzalloc(sizeof(params.sizeofvalue), GFP_KERNEL);
-               if (p_i2c_table == NULL) {
-                       pr_err("%s: kzalloc error\n", __func__);
-                       return -ENOMEM;
-               }
-
-               if (copy_from_user(p_i2c_table,
-                                  (const void __user *)params.p_value,
-                                  params.sizeofvalue)) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_from_user err line %d\n",
-                               __func__, __LINE__);
-                       kfree(p_i2c_table);
-                       return -EINVAL;
-               }
-
-               imx179_pm_dev_wr(info, NVC_PWR_COMM);
-               err = imx179_i2c_rd_table(info, p_i2c_table);
-               imx179_pm_dev_wr(info, NVC_PWR_OFF);
-               if (copy_to_user((void __user *)params.p_value,
-                                p_i2c_table,
-                                params.sizeofvalue)) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_to_user err line %d\n",
-                               __func__, __LINE__);
-                       err = -EINVAL;
-               }
-               kfree(p_i2c_table);
-               return err;
-       default:
-               dev_dbg(&info->i2c_client->dev,
-                       "%s unsupported parameter: %d\n",
-                       __func__, params.param);
-               return -EINVAL;
        }
 
-       if (params.sizeofvalue < data_size) {
-               dev_err(&info->i2c_client->dev,
-                       "%s data size mismatch %d != %d Param: %d\n",
-                       __func__, params.sizeofvalue, data_size, params.param);
-               return -EINVAL;
-       }
+       gpio_set_value(info->pdata->reset_gpio, 0);
+       gpio_set_value(info->pdata->af_gpio, 1);
+       gpio_set_value(info->pdata->cam1_gpio, 0);
+       usleep_range(10, 20);
 
-       if (copy_to_user((void __user *)params.p_value,
-                        data_ptr,
-                        data_size)) {
-               dev_err(&info->i2c_client->dev,
-                       "%s copy_to_user err line %d\n", __func__, __LINE__);
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-static int imx179_param_wr_s(struct imx179_info *info,
-                            struct nvc_param *params,
-                            u32 u32val)
-{
-       struct imx179_reg *p_i2c_table;
-       u8 u8val;
-       int err;
-
-       u8val = (u8)u32val;
-       switch (params->param) {
-       case NVC_PARAM_GAIN:
-               dev_dbg(&info->i2c_client->dev, "%s GAIN: %u\n",
-                       __func__, u32val);
-               imx179_pm_dev_wr(info, NVC_PWR_COMM);
-               err = imx179_gain_wr(info, u32val);
-               if (err) {
-                       dev_err(&info->i2c_client->dev, "Error: %s SET GAIN ERR",
-                                                       __func__);
-               }
-               imx179_pm_dev_wr(info, NVC_PWR_STDBY);
-               return err;
+       err = regulator_enable(pw->avdd);
+       if (err)
+               goto imx179_avdd_fail;
 
-       case NVC_PARAM_RESET:
-               err = imx179_reset(info, u32val);
-               dev_dbg(&info->i2c_client->dev, "%s RESET=%d err=%d\n",
-                       __func__, u32val, err);
-               return err;
+       err = regulator_enable(pw->iovdd);
+       if (err)
+               goto imx179_iovdd_fail;
 
-       case NVC_PARAM_TESTMODE:
-               dev_dbg(&info->i2c_client->dev, "%s TESTMODE: %u\n",
-                       __func__, (unsigned)u8val);
-               if (u8val)
-                       u32val = info->test_pattern;
-               else
-                       u32val = 0;
-               imx179_pm_dev_wr(info, NVC_PWR_ON);
-               err = imx179_test_pattern_wr(info, u32val);
-               if (!u8val)
-                       imx179_pm_dev_wr(info, NVC_PWR_OFF);
-               return err;
+       usleep_range(1, 2);
+       gpio_set_value(info->pdata->reset_gpio, 1);
+       gpio_set_value(info->pdata->cam1_gpio, 1);
 
-       case NVC_PARAM_TEST_PATTERN:
-               dev_dbg(&info->i2c_client->dev, "%s TEST_PATTERN: %d\n",
-                       __func__, u32val);
-               info->test_pattern = u32val;
-               return 0;
+       usleep_range(300, 310);
 
-       case NVC_PARAM_SELF_TEST:
-               err = imx179_dev_id(info);
-               dev_dbg(&info->i2c_client->dev, "%s SELF_TEST: %d\n",
-                       __func__, err);
-               return err;
+       return 1;
 
-       case NVC_PARAM_I2C:
-               dev_dbg(&info->i2c_client->dev, "%s I2C\n", __func__);
-               if (params->sizeofvalue > IMX179_I2C_TABLE_MAX_ENTRIES) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s NVC_PARAM_I2C request size too large\n",
-                               __func__);
-                       return -EINVAL;
-               }
-               p_i2c_table = kzalloc(sizeof(params->sizeofvalue), GFP_KERNEL);
-               if (p_i2c_table == NULL) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s kzalloc err line %d\n",
-                               __func__, __LINE__);
-                       return -ENOMEM;
-               }
 
-               if (copy_from_user(p_i2c_table,
-                                  (const void __user *)params->p_value,
-                                  params->sizeofvalue)) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_from_user err line %d\n",
-                               __func__, __LINE__);
-                       kfree(p_i2c_table);
-                       return -EFAULT;
-               }
+imx179_iovdd_fail:
+       regulator_disable(pw->avdd);
 
-               imx179_pm_dev_wr(info, NVC_PWR_ON);
-               err = imx179_i2c_wr_table(info, p_i2c_table);
-               kfree(p_i2c_table);
-               return err;
+imx179_avdd_fail:
+       if (pw->ext_reg2)
+               regulator_disable(pw->ext_reg2);
 
-       case NVC_PARAM_SET_SENSOR_FLASH_MODE:
-       {
-               union nvc_imager_flash_control fm;
-               if (copy_from_user(&fm,
-                       (const void __user *)params->p_value, sizeof(fm))) {
-                       pr_info("%s:fail set flash mode.\n", __func__);
-                       return -EFAULT;
-               }
-               return imx179_flash_control(info, &fm);
-       }
+imx179_ext_reg2_fail:
+       if (pw->ext_reg1)
+               regulator_disable(pw->ext_reg1);
+       gpio_set_value(info->pdata->af_gpio, 0);
 
-       default:
-               dev_dbg(&info->i2c_client->dev,
-                       "%s unsupported parameter: %d\n",
-                       __func__, params->param);
-               return -EINVAL;
-       }
+imx179_ext_reg1_fail:
+imx179_poweron_fail:
+       pr_err("%s failed.\n", __func__);
+       return -ENODEV;
 }
 
-static int imx179_param_wr(struct imx179_info *info, unsigned long arg)
+static int imx179_power_off(struct imx179_power_rail *pw)
 {
-       struct nvc_param params;
-       u8 u8val;
-       u32 u32val;
-       int err = 0;
+       struct imx179_info *info = container_of(pw, struct imx179_info, power);
 
-       if (copy_from_user(&params, (const void __user *)arg,
-                          sizeof(struct nvc_param))) {
-               dev_err(&info->i2c_client->dev,
-                       "%s copy_from_user err line %d\n", __func__, __LINE__);
+       if (unlikely(WARN_ON(!pw || !pw->iovdd || !pw->avdd)))
                return -EFAULT;
-       }
-
-       if (copy_from_user(&u32val, (const void __user *)params.p_value,
-                          sizeof(u32val))) {
-               dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
-                       __func__, __LINE__);
-               return -EFAULT;
-       }
-
-       u8val = (u8)u32val;
-       /* parameters independent of sync mode */
-       switch (params.param) {
-       case NVC_PARAM_STEREO:
-               dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
-                       __func__, u8val);
-               if (u8val == info->s_mode)
-                       return 0;
 
-               switch (u8val) {
-               case NVC_SYNC_OFF:
-                       info->s_mode = u8val;
-                       if (info->s_info != NULL) {
-                               info->s_info->s_mode = u8val;
-                               imx179_pm_wr(info->s_info, NVC_PWR_OFF);
-                       }
-                       break;
-
-               case NVC_SYNC_MASTER:
-                       info->s_mode = u8val;
-                       if (info->s_info != NULL)
-                               info->s_info->s_mode = u8val;
-                       break;
-
-               case NVC_SYNC_SLAVE:
-                       if (info->s_info != NULL) {
-                               /* sync power */
-                               info->s_info->pwr_api = info->pwr_api;
-                               err = imx179_pm_wr(info->s_info,
-                                                  info->pwr_dev);
-                               if (!err) {
-                                       info->s_mode = u8val;
-                                       info->s_info->s_mode = u8val;
-                               } else {
-                                       if (info->s_mode != NVC_SYNC_STEREO)
-                                               imx179_pm_wr(info->s_info,
-                                                            NVC_PWR_OFF);
-                                       err = -EIO;
-                               }
-                       } else {
-                               err = -EINVAL;
-                       }
-                       break;
+       usleep_range(1, 2);
+       gpio_set_value(info->pdata->cam1_gpio, 0);
+       usleep_range(1, 2);
 
-               case NVC_SYNC_STEREO:
-                       if (info->s_info != NULL) {
-                               /* sync power */
-                               info->s_info->pwr_api = info->pwr_api;
-                               err = imx179_pm_wr(info->s_info,
-                                                  info->pwr_dev);
-                               if (!err) {
-                                       info->s_mode = u8val;
-                                       info->s_info->s_mode = u8val;
-                               } else {
-                                       if (info->s_mode != NVC_SYNC_SLAVE)
-                                               imx179_pm_wr(info->s_info,
-                                                            NVC_PWR_OFF);
-                                       err = -EIO;
-                               }
-                       } else {
-                               err = -EINVAL;
-                       }
-                       break;
-
-               default:
-                       err = -EINVAL;
-               }
-               if (info->pdata->cfg & NVC_CFG_NOERR)
-                       return 0;
+       regulator_disable(pw->iovdd);
+       regulator_disable(pw->avdd);
 
-               return err;
-
-       case NVC_PARAM_GROUP_HOLD:
-       {
-               struct nvc_imager_ae ae;
-               dev_dbg(&info->i2c_client->dev, "%s GROUP_HOLD\n",
-                       __func__);
-               if (copy_from_user(&ae, (const void __user *)params.p_value,
-                               sizeof(struct nvc_imager_ae))) {
-                       dev_err(&info->i2c_client->dev, "Error: %s %d copy_from_user err\n",
-                               __func__, __LINE__);
-                       return -EFAULT;
-               }
-               imx179_pm_dev_wr(info, NVC_PWR_COMM);
-               err = imx179_group_hold_wr(info, &ae);
-               imx179_pm_dev_wr(info, NVC_PWR_STDBY);
-               return err;
+       if (info->pdata->ext_reg) {
+               regulator_disable(pw->ext_reg1);
+               regulator_disable(pw->ext_reg2);
        }
 
-       default:
-       /* parameters dependent on sync mode */
-               switch (info->s_mode) {
-               case NVC_SYNC_OFF:
-               case NVC_SYNC_MASTER:
-                       return imx179_param_wr_s(info, &params, u32val);
-
-               case NVC_SYNC_SLAVE:
-                       return imx179_param_wr_s(info->s_info, &params,
-                                                u32val);
-
-               case NVC_SYNC_STEREO:
-                       err = imx179_param_wr_s(info, &params, u32val);
-                       if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
-                               err |= imx179_param_wr_s(info->s_info,
-                                                        &params, u32val);
-                       return err;
-
-               default:
-                       dev_err(&info->i2c_client->dev, "%s %d internal err\n",
-                               __func__, __LINE__);
-                       return -EINVAL;
-               }
-       }
-}
-
-static long imx179_ioctl(struct file *file,
-                        unsigned int cmd,
-                        unsigned long arg)
-{
-       struct imx179_info *info = file->private_data;
-       struct nvc_imager_bayer mode;
-       struct nvc_imager_mode_list mode_list;
-       struct nvc_imager_mode mode_table[IMX179_NUM_MODES];
-       struct nvc_imager_dnvc dnvc;
-       const void *data_ptr;
-       s32 num_modes;
-       u32 i;
-       int pwr;
-       int err;
-
-       switch (cmd) {
-       case NVC_IOCTL_PARAM_WR:
-               err = imx179_param_wr(info, arg);
-               return err;
-
-       case NVC_IOCTL_PARAM_RD:
-               err = imx179_param_rd(info, arg);
-               return err;
-
-       case NVC_IOCTL_DYNAMIC_RD:
-               if (copy_from_user(&dnvc, (const void __user *)arg,
-                                  sizeof(struct nvc_imager_dnvc))) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_from_user err line %d\n",
-                               __func__, __LINE__);
-                       return -EFAULT;
-               }
-
-               dev_dbg(&info->i2c_client->dev, "%s DYNAMIC_RD x=%d y=%d\n",
-                       __func__, dnvc.res_x, dnvc.res_y);
-               err = imx179_mode_rd(info, dnvc.res_x, dnvc.res_y, &i);
-               if (err)
-                       return -EINVAL;
-
-               if (dnvc.p_mode) {
-                       if (copy_to_user((void __user *)dnvc.p_mode,
-                                        &imx179_mode_table[i]->sensor_mode,
-                                        sizeof(struct nvc_imager_mode))) {
-                               dev_err(&info->i2c_client->dev,
-                                       "%s copy_to_user err line %d\n",
-                                       __func__, __LINE__);
-                               return -EFAULT;
-                       }
-               }
-
-               if (dnvc.p_dnvc) {
-                       if (copy_to_user((void __user *)dnvc.p_dnvc,
-                                     &imx179_mode_table[i]->sensor_dnvc,
-                                     sizeof(struct nvc_imager_dynamic_nvc))) {
-                               dev_err(&info->i2c_client->dev,
-                                       "%s copy_to_user err line %d\n",
-                                       __func__, __LINE__);
-                               return -EFAULT;
-                       }
-               }
-
-               return 0;
-
-       case NVC_IOCTL_MODE_WR:
-               if (copy_from_user(&mode, (const void __user *)arg,
-                                  sizeof(struct nvc_imager_bayer))) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_from_user err line %d\n",
-                               __func__, __LINE__);
-                       return -EFAULT;
-               }
-
-               dev_dbg(&info->i2c_client->dev,
-                       "%s MODE_WR x=%d y=%d coarse=%u frame=%u gain=%u\n",
-                       __func__, mode.res_x, mode.res_y,
-                       mode.coarse_time, mode.frame_length, mode.gain);
-
-               err = imx179_mode_wr(info, &mode);
-               return err;
-
-       case NVC_IOCTL_MODE_RD:
-               /*
-                * Return a list of modes that sensor bayer supports.
-                * If called with a NULL ptr to pModes,
-                * then it just returns the count.
-                */
-               dev_dbg(&info->i2c_client->dev, "%s MODE_RD n=%d\n",
-                       __func__, IMX179_NUM_MODES);
-               if (copy_from_user(&mode_list, (const void __user *)arg,
-                                  sizeof(struct nvc_imager_mode_list))) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_from_user err line %d\n",
-                               __func__, __LINE__);
-                       return -EFAULT;
-               }
-
-               num_modes = IMX179_NUM_MODES;
-               if (mode_list.p_num_mode != NULL) {
-                       if (copy_to_user((void __user *)mode_list.p_num_mode,
-                                        &num_modes, sizeof(num_modes))) {
-                               dev_err(&info->i2c_client->dev,
-                                       "%s copy_to_user err line %d\n",
-                                       __func__, __LINE__);
-                               return -EFAULT;
-                       }
-               }
-
-               if (mode_list.p_modes != NULL) {
-                       for (i = 0; i < IMX179_NUM_MODES; i++) {
-                               mode_table[i] =
-                                            imx179_mode_table[i]->sensor_mode;
-                       }
-                       if (copy_to_user((void __user *)mode_list.p_modes,
-                                        (const void *)&mode_table,
-                                        sizeof(mode_table))) {
-                               dev_err(&info->i2c_client->dev,
-                                       "%s copy_to_user err line %d\n",
-                                       __func__, __LINE__);
-                               return -EFAULT;
-                       }
-               }
-
-               return 0;
-
-       case NVC_IOCTL_PWR_WR:
-               /* This is a Guaranteed Level of Service (GLOS) call */
-               pwr = (int)arg * 2;
-               dev_dbg(&info->i2c_client->dev, "%s PWR_WR: %d\n",
-                       __func__, pwr);
-               err = imx179_pm_api_wr(info, pwr);
-               return err;
-
-       case NVC_IOCTL_PWR_RD:
-               if (info->s_mode == NVC_SYNC_SLAVE)
-                       pwr = info->s_info->pwr_api / 2;
-               else
-                       pwr = info->pwr_api / 2;
-               dev_dbg(&info->i2c_client->dev, "%s PWR_RD: %d\n",
-                       __func__, pwr);
-               if (copy_to_user((void __user *)arg, (const void *)&pwr,
-                                sizeof(pwr))) {
-                       dev_err(&info->i2c_client->dev,
-                                       "%s copy_to_user err line %d\n",
-                                       __func__, __LINE__);
-                       return -EFAULT;
-               }
-
-               return 0;
-
-       case NVC_IOCTL_CAPS_RD:
-               dev_dbg(&info->i2c_client->dev, "%s CAPS_RD n=%d\n",
-                       __func__, sizeof(imx179_dflt_cap));
-               data_ptr = info->cap;
-               if (copy_to_user((void __user *)arg,
-                                data_ptr,
-                                sizeof(imx179_dflt_cap))) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_to_user err line %d\n",
-                               __func__, __LINE__);
-                       return -EFAULT;
-               }
-
-               return 0;
-
-       case NVC_IOCTL_STATIC_RD:
-               dev_dbg(&info->i2c_client->dev, "%s STATIC_RD n=%d\n",
-                       __func__, sizeof(struct nvc_imager_static_nvc));
-               data_ptr = &info->sdata;
-               if (copy_to_user((void __user *)arg,
-                                data_ptr,
-                                sizeof(struct nvc_imager_static_nvc))) {
-                       dev_err(&info->i2c_client->dev,
-                               "%s copy_to_user err line %d\n",
-                               __func__, __LINE__);
-                       return -EFAULT;
-               }
-
-               return 0;
-
-       default:
-               dev_dbg(&info->i2c_client->dev, "%s unsupported ioctl: %x\n",
-                       __func__, cmd);
-       }
-
-       return -EINVAL;
-}
-
-static void imx179_sdata_init(struct imx179_info *info)
-{
-       if (info->pdata->cap)
-               info->cap = info->pdata->cap;
-       else
-               info->cap = &imx179_dflt_cap;
-       memcpy(&info->sdata, &imx179_dflt_sdata, sizeof(info->sdata));
-       if (info->pdata->lens_focal_length)
-               info->sdata.focal_len = info->pdata->lens_focal_length;
-       if (info->pdata->lens_max_aperture)
-               info->sdata.max_aperture = info->pdata->lens_max_aperture;
-       if (info->pdata->lens_fnumber)
-               info->sdata.fnumber = info->pdata->lens_fnumber;
-       if (info->pdata->lens_view_angle_h)
-               info->sdata.view_angle_h = info->pdata->lens_view_angle_h;
-       if (info->pdata->lens_view_angle_v)
-               info->sdata.view_angle_v = info->pdata->lens_view_angle_v;
-}
-
-static int imx179_sync_en(unsigned num, unsigned sync)
-{
-       struct imx179_info *master = NULL;
-       struct imx179_info *slave = NULL;
-       struct imx179_info *pos = NULL;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(pos, &imx179_info_list, list) {
-               if (pos->pdata->num == num) {
-                       master = pos;
-                       break;
-               }
-       }
-       pos = NULL;
-       list_for_each_entry_rcu(pos, &imx179_info_list, list) {
-               if (pos->pdata->num == sync) {
-                       slave = pos;
-                       break;
-               }
-       }
-       rcu_read_unlock();
-       if (master != NULL)
-               master->s_info = NULL;
-       if (slave != NULL)
-               slave->s_info = NULL;
-       if (!sync)
-               return 0; /* no err if sync disabled */
-
-       if (num == sync)
-               return -EINVAL; /* err if sync instance is itself */
-
-       if ((master != NULL) && (slave != NULL)) {
-               master->s_info = slave;
-               slave->s_info = master;
-       }
        return 0;
 }
 
-static int imx179_sync_dis(struct imx179_info *info)
-{
-       if (info->s_info != NULL) {
-               info->s_info->s_mode = 0;
-               info->s_info->s_info = NULL;
-               info->s_mode = 0;
-               info->s_info = NULL;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int imx179_open(struct inode *inode, struct file *file)
+static int
+imx179_open(struct inode *inode, struct file *file)
 {
-       struct imx179_info *info = NULL;
-       struct imx179_info *pos = NULL;
-       int err;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(pos, &imx179_info_list, list) {
-               if (pos->miscdev.minor == iminor(inode)) {
-                       info = pos;
-                       break;
-               }
-       }
-       rcu_read_unlock();
-       if (!info) {
-               pr_err("%s err @%d info is null\n", __func__, __LINE__);
-               return -ENODEV;
-       }
+       struct miscdevice       *miscdev = file->private_data;
+       struct imx179_info *info;
 
-       dev_dbg(&info->i2c_client->dev, "%s +++++\n", __func__);
-       err = imx179_sync_en(info->pdata->num, info->pdata->sync);
-       if (err == -EINVAL)
-               dev_err(&info->i2c_client->dev,
-                       "%s err: invalid num (%u) and sync (%u) instance\n",
-                       __func__, info->pdata->num, info->pdata->sync);
+       info = container_of(miscdev, struct imx179_info, miscdev_info);
+       /* check if the device is in use */
        if (atomic_xchg(&info->in_use, 1)) {
-               dev_err(&info->i2c_client->dev, "%s err @%d device is busy\n",
-                       __func__, __LINE__);
+               pr_info("%s:BUSY!\n", __func__);
                return -EBUSY;
        }
-       if (info->s_info != NULL) {
-               if (atomic_xchg(&info->s_info->in_use, 1)) {
-                       dev_err(&info->i2c_client->dev, "%s err @%d sync device is busy\n",
-                                       __func__, __LINE__);
-                       return -EBUSY;
-               }
-               info->sdata.stereo_cap = 1;
-       }
 
        file->private_data = info;
-       dev_dbg(&info->i2c_client->dev, "%s -----\n", __func__);
+
        return 0;
 }
 
-static int imx179_release(struct inode *inode, struct file *file)
+static int
+imx179_release(struct inode *inode, struct file *file)
 {
        struct imx179_info *info = file->private_data;
 
-       dev_dbg(&info->i2c_client->dev, "%s +++++\n", __func__);
-       imx179_pm_wr_s(info, NVC_PWR_OFF);
        file->private_data = NULL;
+
+       /* warn if device is already released */
        WARN_ON(!atomic_xchg(&info->in_use, 0));
-       if (info->s_info != NULL)
-               WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
-       imx179_sync_dis(info);
-       dev_dbg(&info->i2c_client->dev, "%s -----\n", __func__);
        return 0;
 }
 
-static const struct file_operations imx179_fileops = {
-       .owner = THIS_MODULE,
-       .open = imx179_open,
-       .unlocked_ioctl = imx179_ioctl,
-       .release = imx179_release,
-};
-
-static void imx179_del(struct imx179_info *info)
+static int imx179_power_put(struct imx179_power_rail *pw)
 {
-       imx179_pm_exit(info);
-       if ((info->s_mode == NVC_SYNC_SLAVE) ||
-                                            (info->s_mode == NVC_SYNC_STEREO))
-               imx179_pm_exit(info->s_info);
-       imx179_sync_dis(info);
-       spin_lock(&imx179_spinlock);
-       list_del_rcu(&info->list);
-       spin_unlock(&imx179_spinlock);
-       synchronize_rcu();
-}
+       if (unlikely(!pw))
+               return -EFAULT;
 
-static int imx179_remove(struct i2c_client *client)
-{
-       struct imx179_info *info = i2c_get_clientdata(client);
+       if (likely(pw->avdd))
+               regulator_put(pw->avdd);
 
-       dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
-#ifdef CONFIG_DEBUG_FS
-       if (info->debugfs_root)
-               debugfs_remove_recursive(info->debugfs_root);
-#endif
-       misc_deregister(&info->miscdev);
-       imx179_del(info);
-       return 0;
-}
+       if (likely(pw->iovdd))
+               regulator_put(pw->iovdd);
 
-#ifdef CONFIG_DEBUG_FS
-static int i2ca_get(void *data, u64 *val)
-{
-       struct imx179_info *info = (struct imx179_info *)(data);
-       *val = (u64)info->i2c_reg;
-       return 0;
-}
+       if (likely(pw->dvdd))
+               regulator_put(pw->dvdd);
 
-static int i2ca_set(void *data, u64 val)
-{
-       struct imx179_info *info = (struct imx179_info *)(data);
+       if (likely(pw->ext_reg1))
+               regulator_put(pw->ext_reg1);
 
-       if (val > 0x36FF) {
-               dev_err(&info->i2c_client->dev, "ERR:%s out of range\n",
-                               __func__);
-               return -EIO;
-       }
+       if (likely(pw->ext_reg2))
+               regulator_put(pw->ext_reg2);
+
+       pw->avdd = NULL;
+       pw->iovdd = NULL;
+       pw->dvdd = NULL;
+       pw->ext_reg1 = NULL;
+       pw->ext_reg2 = NULL;
 
-       info->i2c_reg = (u16) val;
        return 0;
 }
 
-DEFINE_SIMPLE_ATTRIBUTE(i2ca_fops, i2ca_get, i2ca_set, "0x%02llx\n");
-
-static int i2cr_get(void *data, u64 *val)
+static int imx179_regulator_get(struct imx179_info *info,
+       struct regulator **vreg, char vreg_name[])
 {
-       u8 temp = 0;
-       struct imx179_info *info = (struct imx179_info *)(data);
+       struct regulator *reg = NULL;
+       int err = 0;
 
-       if (imx179_i2c_rd8(info, info->i2c_reg, &temp)) {
-               dev_err(&info->i2c_client->dev, "ERR:%s failed\n", __func__);
-               return -EIO;
-       }
-       *val = (u64)temp;
-       return 0;
+       reg = regulator_get(&info->i2c_client->dev, vreg_name);
+       if (unlikely(IS_ERR(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 i2cr_set(void *data, u64 val)
+static int imx179_power_get(struct imx179_info *info)
 {
-       return 0;
-}
+       struct imx179_power_rail *pw = &info->power;
+       int err = 0;
 
-DEFINE_SIMPLE_ATTRIBUTE(i2cr_fops, i2cr_get, i2cr_set, "0x%02llx\n");
+       err |= imx179_regulator_get(info, &pw->avdd, "vana"); /* ananlog 2.7v */
+       err |= imx179_regulator_get(info, &pw->dvdd, "vdig"); /* digital 1.2v */
+       err |= imx179_regulator_get(info, &pw->iovdd, "vif"); /* IO 1.8v */
 
-static int i2cw_get(void *data, u64 *val)
-{
-       return 0;
+       return err;
 }
 
-static int i2cw_set(void *data, u64 val)
-{
-       struct imx179_info *info = (struct imx179_info *)(data);
-
-       val &= 0xFF;
-       if (imx179_i2c_wr8(info, info->i2c_reg, val)) {
-               dev_err(&info->i2c_client->dev, "ERR:%s failed\n", __func__);
-               return -EIO;
-       }
-       return 0;
-}
+static const struct file_operations imx179_fileops = {
+       .owner = THIS_MODULE,
+       .open = imx179_open,
+       .unlocked_ioctl = imx179_ioctl,
+       .release = imx179_release,
+};
 
-DEFINE_SIMPLE_ATTRIBUTE(i2cw_fops, i2cw_get, i2cw_set, "0x%02llx\n");
+static struct miscdevice imx179_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "imx179",
+       .fops = &imx179_fileops,
+};
 
-static int imx179_debug_init(struct imx179_info *info)
-{
-       dev_dbg(&info->i2c_client->dev, "%s", __func__);
+static struct of_device_id imx179_of_match[] = {
+       { .compatible = "nvidia,imx179", },
+       { },
+};
 
-       info->i2c_reg = 0;
-       info->debugfs_root = debugfs_create_dir(info->miscdev.name, NULL);
+MODULE_DEVICE_TABLE(of, imx179_of_match);
 
-       if (!info->debugfs_root)
-               goto err_out;
+static struct imx179_platform_data *imx179_parse_dt(struct i2c_client *client)
+{
+       struct device_node *np = client->dev.of_node;
+       struct imx179_platform_data *board_info_pdata;
+       const struct of_device_id *match;
+
+       match = of_match_device(imx179_of_match, &client->dev);
+       if (!match) {
+               dev_err(&client->dev, "Failed to find matching dt id\n");
+               return NULL;
+       }
 
-       if (!debugfs_create_file("i2ca", S_IRUGO | S_IWUSR,
-                               info->debugfs_root, info, &i2ca_fops))
-               goto err_out;
+       board_info_pdata = devm_kzalloc(&client->dev, sizeof(*board_info_pdata),
+                       GFP_KERNEL);
+       if (!board_info_pdata) {
+               dev_err(&client->dev, "Failed to allocate pdata\n");
+               return NULL;
+       }
 
-       if (!debugfs_create_file("i2cr", S_IRUGO,
-                               info->debugfs_root, info, &i2cr_fops))
-               goto err_out;
+       board_info_pdata->cam1_gpio = of_get_named_gpio(np, "cam1-gpios", 0);
+       board_info_pdata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+       board_info_pdata->af_gpio = of_get_named_gpio(np, "af-gpios", 0);
 
-       if (!debugfs_create_file("i2cw", S_IWUSR,
-                               info->debugfs_root, info, &i2cw_fops))
-               goto err_out;
+       board_info_pdata->ext_reg = of_property_read_bool(np, "nvidia,ext_reg");
 
-       return 0;
+       board_info_pdata->power_on = imx179_power_on;
+       board_info_pdata->power_off = imx179_power_off;
 
-err_out:
-       dev_err(&info->i2c_client->dev, "ERROR:%s failed", __func__);
-       if (info->debugfs_root)
-               debugfs_remove_recursive(info->debugfs_root);
-       return -ENOMEM;
+       return board_info_pdata;
 }
-#endif
 
-static int imx179_probe(
-       struct i2c_client *client,
-       const struct i2c_device_id *id)
+static int
+imx179_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct imx179_info *info;
-       char dname[16];
-       unsigned long clock_probe_rate;
        int err;
        const char *mclk_name;
 
-       dev_dbg(&client->dev, "%s +++++\n", __func__);
-       info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
-       if (info == NULL) {
-               dev_err(&client->dev, "%s: kzalloc error\n", __func__);
+       pr_err("[IMX179]: probing sensor.\n");
+
+       info = devm_kzalloc(&client->dev,
+                       sizeof(struct imx179_info), GFP_KERNEL);
+       if (!info) {
+               pr_err("%s:Unable to allocate memory!\n", __func__);
                return -ENOMEM;
        }
 
-       info->i2c_client = client;
-       if (client->dev.platform_data) {
+       info->regmap = devm_regmap_init_i2c(client, &sensor_regmap_config);
+       if (IS_ERR(info->regmap)) {
+               dev_err(&client->dev,
+                       "regmap init failed: %ld\n", PTR_ERR(info->regmap));
+               return -ENODEV;
+       }
+
+       if (client->dev.of_node)
+               info->pdata = imx179_parse_dt(client);
+       else
                info->pdata = client->dev.platform_data;
-       } else {
-               info->pdata = &imx179_dflt_pdata;
-               dev_dbg(&client->dev,
-                       "%s No platform data.  Using defaults.\n", __func__);
+
+       if (!info->pdata) {
+               pr_err("[IMX179]:%s:Unable to get platform data\n", __func__);
+               return -EFAULT;
        }
 
+       info->i2c_client = client;
+       atomic_set(&info->in_use, 0);
+       info->mode = -1;
+
        mclk_name = info->pdata->mclk_name ?
                    info->pdata->mclk_name : "default_mclk";
        info->mclk = devm_clk_get(&client->dev, mclk_name);
@@ -2550,74 +1121,48 @@ static int imx179_probe(
                return PTR_ERR(info->mclk);
        }
 
-       i2c_set_clientdata(client, info);
-       INIT_LIST_HEAD(&info->list);
-       spin_lock(&imx179_spinlock);
-       list_add_rcu(&info->list, &imx179_info_list);
-       spin_unlock(&imx179_spinlock);
-       imx179_pm_init(info);
-       imx179_sdata_init(info);
-       imx179_get_flash_cap(info);
-       if (info->pdata->cfg & (NVC_CFG_NODEV | NVC_CFG_BOOT_INIT)) {
-               if (info->pdata->probe_clock) {
-                       if (info->cap->initial_clock_rate_khz)
-                               clock_probe_rate = info->cap->
-                                                       initial_clock_rate_khz;
-                       else
-                               clock_probe_rate = imx179_dflt_cap.
-                                                       initial_clock_rate_khz;
-                       clock_probe_rate *= 1000;
-                       info->pdata->probe_clock(clock_probe_rate);
-               }
-               err = imx179_dev_id(info);
-               if (err < 0) {
-                       if (info->pdata->cfg & NVC_CFG_NODEV) {
-                               imx179_del(info);
-                               if (info->pdata->probe_clock)
-                                       info->pdata->probe_clock(0);
-                               return -ENODEV;
-                       } else {
-                               dev_err(&client->dev, "%s device not found\n",
-                                       __func__);
-                       }
-               } else {
-                       dev_dbg(&client->dev, "%s device found\n", __func__);
-                       if (info->pdata->cfg & NVC_CFG_BOOT_INIT)
-                               imx179_mode_wr_full(info, info->cap->
-                                                   preferred_mode_index);
-               }
-               imx179_pm_dev_wr(info, NVC_PWR_OFF);
-               if (info->pdata->probe_clock)
-                       info->pdata->probe_clock(0);
-       }
+       imx179_power_get(info);
 
-       if (info->pdata->dev_name != 0)
-               strcpy(dname, info->pdata->dev_name);
-       else
-               strcpy(dname, "imx179");
-       if (info->pdata->num)
-               snprintf(dname, sizeof(dname), "%s.%u",
-                        dname, info->pdata->num);
-       info->miscdev.name = dname;
-       info->miscdev.fops = &imx179_fileops;
-       info->miscdev.minor = MISC_DYNAMIC_MINOR;
-       if (misc_register(&info->miscdev)) {
-               dev_err(&client->dev, "%s unable to register misc device %s\n",
-                       __func__, dname);
-               imx179_del(info);
-               return -ENODEV;
+       imx179_edp_register(info);
+
+       memcpy(&info->miscdev_info,
+               &imx179_device,
+               sizeof(struct miscdevice));
+
+       err = misc_register(&info->miscdev_info);
+       if (err) {
+               pr_err("%s:Unable to register misc device!\n", __func__);
+               goto imx179_probe_fail;
        }
 
-#ifdef CONFIG_DEBUG_FS
-       imx179_debug_init(info);
-#endif
-       dev_dbg(&client->dev, "%s -----\n", __func__);
+       i2c_set_clientdata(client, info);
+       /* create debugfs interface */
+       imx179_create_debugfs(info);
+       pr_err("[IMX179]: end of probing sensor.\n");
+       return 0;
+
+imx179_probe_fail:
+       imx179_power_put(&info->power);
+
+       return err;
+}
+
+static int
+imx179_remove(struct i2c_client *client)
+{
+       struct imx179_info *info;
+       info = i2c_get_clientdata(client);
+       misc_deregister(&imx179_device);
+
+       imx179_power_put(&info->power);
+
+       imx179_remove_debugfs(info);
        return 0;
 }
 
 static const struct i2c_device_id imx179_id[] = {
        { "imx179", 0 },
-       { },
+       { }
 };
 
 MODULE_DEVICE_TABLE(i2c, imx179_id);
@@ -2627,10 +1172,21 @@ static struct i2c_driver imx179_i2c_driver = {
                .name = "imx179",
                .owner = THIS_MODULE,
        },
-       .id_table = imx179_id,
        .probe = imx179_probe,
        .remove = imx179_remove,
+       .id_table = imx179_id,
 };
 
-module_i2c_driver(imx179_i2c_driver);
-MODULE_LICENSE("GPL v2");
+static int __init imx179_init(void)
+{
+       pr_info("[IMX179] sensor driver loading\n");
+       return i2c_add_driver(&imx179_i2c_driver);
+}
+
+static void __exit imx179_exit(void)
+{
+       i2c_del_driver(&imx179_i2c_driver);
+}
+
+module_init(imx179_init);
+module_exit(imx179_exit);
index 52acf5e..cc6bfd3 100644 (file)
@@ -1,59 +1,90 @@
-/*
-* imx179.h
-*
-* Copyright (c) 2013, NVIDIA CORPORATION, All rights reserved.
-*
-* This file is licensed under the terms of the GNU General Public License
-* version 2. This program is licensed "as is" without any warranty of any
-* kind, whether express or implied.
-*/
+/**
+ * Copyright (c) 2012-2014, NVIDIA Corporation.  All rights reserved.
+ *
+ * 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/>.
+ */
 
 #ifndef __IMX179_H__
 #define __IMX179_H__
 
+#include <linux/ioctl.h>  /* For IOCTL macros */
+#include <linux/edp.h>
 #include <media/nvc.h>
 #include <media/nvc_image.h>
 
-/* See notes in the nvc.h file on the GPIO usage */
-enum imx179_gpio {
-       IMX179_GPIO_RESET = 0,
-       IMX179_GPIO_PWDN,
-       IMX179_GPIO_GP1,
+#define IMX179_IOCTL_SET_MODE          _IOW('o', 1, struct imx179_mode)
+#define IMX179_IOCTL_GET_STATUS                _IOR('o', 2, __u8)
+#define IMX179_IOCTL_SET_FRAME_LENGTH  _IOW('o', 3, __u32)
+#define IMX179_IOCTL_SET_COARSE_TIME   _IOW('o', 4, __u32)
+#define IMX179_IOCTL_SET_GAIN          _IOW('o', 5, __u16)
+#define IMX179_IOCTL_GET_SENSORDATA    _IOR('o', 6, struct imx179_sensordata)
+#define IMX179_IOCTL_SET_GROUP_HOLD    _IOW('o', 7, struct imx179_ae)
+#define IMX179_IOCTL_SET_POWER         _IOW('o', 20, __u32)
+#define IMX179_IOCTL_GET_FLASH_CAP     _IOR('o', 30, __u32)
+#define IMX179_IOCTL_SET_FLASH_MODE    _IOW('o', 31, \
+                                               struct imx179_flash_control)
+
+struct imx179_mode {
+       int xres;
+       int yres;
+       __u32 frame_length;
+       __u32 coarse_time;
+       __u16 gain;
+};
+
+struct imx179_ae {
+       __u32 frame_length;
+       __u8  frame_length_enable;
+       __u32 coarse_time;
+       __u8  coarse_time_enable;
+       __s32 gain;
+       __u8  gain_enable;
 };
 
-/* The enumeration must be in the order the regulators are to be enabled */
-/* See Power Requirements note in the driver */
-enum imx179_vreg {
-       IMX179_VREG_DVDD = 0,
-       IMX179_VREG_AVDD,
-       IMX179_VREG_IOVDD,
+struct imx179_sensordata {
+       __u32 fuse_id_size;
+       __u8  fuse_id[16];
 };
 
-struct imx179_flash_config {
-       u8 xvs_trigger_enabled;
-       u8 sdo_trigger_enabled;
-       u8 adjustable_flash_timing;
-       u16 pulse_width_uS;
+struct imx179_flash_control {
+       u8 enable;
+       u8 edge_trig_en;
+       u8 start_edge;
+       u8 repeat;
+       u16 delay_frm;
+};
+
+
+#ifdef __KERNEL__
+struct imx179_power_rail {
+       struct regulator *dvdd;
+       struct regulator *avdd;
+       struct regulator *iovdd;
+       struct regulator *ext_reg1;
+       struct regulator *ext_reg2;
 };
 
 struct imx179_platform_data {
-       unsigned cfg;
-       unsigned num;
-       unsigned sync;
-       const char *dev_name;
-       unsigned gpio_count; /* see nvc.h GPIO notes */
-       struct nvc_gpio_pdata *gpio; /* see nvc.h GPIO notes */
-       struct imx179_flash_config flash_cap;
-       struct nvc_imager_cap *cap;
-       unsigned lens_focal_length; /* / _INT2FLOAT_DIVISOR */
-       unsigned lens_max_aperture; /* / _INT2FLOAT_DIVISOR */
-       unsigned lens_fnumber; /* / _INT2FLOAT_DIVISOR */
-       unsigned lens_view_angle_h; /* / _INT2FLOAT_DIVISOR */
-       unsigned lens_view_angle_v; /* / _INT2FLOAT_DIVISOR */
+       struct imx179_flash_control flash_cap;
        const char *mclk_name; /* NULL for default default_mclk */
-       int (*probe_clock)(unsigned long);
-       int (*power_on)(struct nvc_regulator *);
-       int (*power_off)(struct nvc_regulator *);
+       struct edp_client edpc_config;
+       unsigned int cam1_gpio;
+       unsigned int reset_gpio;
+       unsigned int af_gpio;
+       bool ext_reg;
+       int (*power_on)(struct imx179_power_rail *pw);
+       int (*power_off)(struct imx179_power_rail *pw);
 };
+#endif /* __KERNEL__ */
 
 #endif  /* __IMX179_H__ */