media: video: tegra: SH532U: Add the SH532U focuser driver.
Qinggang Zhou [Sat, 12 Mar 2011 08:03:43 +0000 (00:03 -0800)]
This focuser is from SEMCO and is integrated with OV5650 sensor and LC898211 driver.

bug 778859

Original-Change-Id: I6e5dcc129c72aed7d92a00a1d926424050583c1d
Reviewed-on: http://git-master/r/22711
Reviewed-by: Qinggang Zhou <qzhou@nvidia.com>
Tested-by: Qinggang Zhou <qzhou@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-by: Jonathan Mayo <jmayo@nvidia.com>

Rebase-Id: R03b55358626eb34807ce5514e1eee5731124619e

drivers/media/video/tegra/Kconfig
drivers/media/video/tegra/Makefile
drivers/media/video/tegra/sh532u.c [new file with mode: 0644]
include/media/sh532u.h [new file with mode: 0644]

index d6e5368..dcf41a9 100644 (file)
@@ -28,5 +28,11 @@ config TORCH_SSL3250A
         depends on I2C && ARCH_TEGRA
         ---help---
           This is a driver for the SSL3250A flash/torch camera device
+
+config VIDEO_SH532U
+        tristate "SH532U focuser support"
+        depends on I2C && ARCH_TEGRA
+        ---help---
+          This is a driver for the SEMCO SH532U focuser
           for use with the tegra isp.
 
index 8a574bf..f97a6df 100644 (file)
@@ -3,3 +3,5 @@ obj-$(CONFIG_TEGRA_CAMERA)              += tegra_camera.o
 obj-$(CONFIG_VIDEO_OV5650)             += ov5650.o
 obj-$(CONFIG_VIDEO_OV2710)             += ov2710.o
 obj-$(CONFIG_TORCH_SSL3250A)           += ssl3250a.o
+obj-$(CONFIG_VIDEO_SH532U)             += sh532u.o
+
diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c
new file mode 100644 (file)
index 0000000..bc9fa43
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * SH532U focuser driver.
+ *
+ * Copyright (C) 2011 NVIDIA Corporation.
+ *
+ * Contributors:
+ *      Qinggang Zhou <qzhou@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <media/sh532u.h>
+
+#include <asm/traps.h>
+
+#define POS_LOW (0xA000)
+#define POS_HIGH (0x6000)
+#define SETTLETIME_MS (7)
+#define FOCAL_LENGTH 0x408d70a4 /* (4.42f) */
+#define FNUMBER 0x40333333 /* (2.8f) */
+
+
+struct sh532u_info {
+       struct i2c_client *i2c_client;
+       struct sh532u_config config;
+};
+
+static struct sh532u_info *info;
+
+static int sh532u_read_u8(u8 dev, u8 addr, u8 *val)
+{
+       struct i2c_client *client = info->i2c_client;
+       struct i2c_msg msg[2];
+       unsigned char data[3];
+
+       if (dev)
+               msg[0].addr = dev;
+       else
+               msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 1;
+       msg[0].buf = data;
+
+       data[0] = (u8)addr;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 1;
+       msg[1].buf = data + 2;
+
+       if (i2c_transfer(client->adapter, msg, 2) != 2)
+               return -1;
+       *val = data[2];
+       return 0;
+}
+
+static int sh532u_read_u16(u8 addr, u16 *val)
+{
+       struct i2c_client *client = info->i2c_client;
+       struct i2c_msg msg[2];
+       u8 buf[4];
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 1;
+       msg[0].buf = &buf[0];
+
+       /* high byte goes out first */
+       buf[0] = (u8) (addr);
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 2;
+       msg[1].buf = &buf[1];
+
+       if (i2c_transfer(client->adapter, msg, 2) != 2)
+               return -1;
+       *val = (((u16)buf[1] << 8) | (u16)buf[2]);
+       return 0;
+}
+
+static int eeprom_read_u32(u8 addr, u32 *val)
+{
+       struct i2c_client *client = info->i2c_client;
+       struct i2c_msg msg[2];
+       union {
+               u8   dataU8[8];
+               u32  dataU32[2];
+       } buffer;
+
+       msg[0].addr = 0x50;
+       msg[0].flags = 0;
+       msg[0].len = 1;
+       msg[0].buf = &(buffer.dataU8[0]);
+
+       /* high byte goes out first */
+       buffer.dataU8[0] = (u8) (addr);
+       buffer.dataU8[1] = (u8) (0);
+
+       msg[1].addr = 0x50;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 4;
+       msg[1].buf = (u8 *)&(buffer.dataU32[1]);
+
+       if (i2c_transfer(client->adapter, msg, 2) != 2)
+               return -1;
+       *val = buffer.dataU32[1];
+       return 0;
+}
+
+static int sh532u_write_u8(u16 addr, u8 val)
+{
+       struct i2c_client *client = info->i2c_client;
+       struct i2c_msg msg;
+       unsigned char data[2];
+       u8 tmp;
+
+       data[0] = (u8) (addr & 0xff);
+       data[1] = (u8) (val & 0xff);
+
+       msg.addr = client->addr;
+       msg.flags = 0;
+       msg.len = 2;
+       msg.buf = data;
+
+       if (i2c_transfer(client->adapter, &msg, 1) != 1)
+               return -1;
+
+       return 0;
+}
+
+static int sh532u_write_u16(u16 addr, u16 val)
+{
+       struct i2c_client *client = info->i2c_client;
+       struct i2c_msg msg;
+       unsigned char data[3];
+
+       data[0] = (u8) (addr & 0xff);
+       data[1] = (u8) (val >> 8);
+       data[2] = (u8) (val & 0xff);
+
+       msg.addr = client->addr;
+       msg.flags = 0;
+       msg.len = 3;
+       msg.buf = data;
+
+       if (i2c_transfer(client->adapter, &msg, 1) != 1)
+               return -1;
+       return 0;
+}
+
+static void move_driver(s16 tarPos)
+{
+       s16 curPos, moveStep;
+       u16 moveDistance;
+       int err;
+
+       /* Read Current Position */
+       err = sh532u_read_u16(RZ_211H, &curPos);
+       if (err)
+               goto move_driver_error;
+       /* Check move distance to Target Position */
+       moveDistance = abs((int)curPos - (int)tarPos);
+
+       /* if move distance is shorter than MS1Z12(=Step width) */
+       if (moveDistance <= STMV_SIZE) {
+               err = sh532u_write_u8(MSSET_211, (INI_MSSET_211 | 0x01));
+               err = err | sh532u_write_u16(MS1Z22_211H, tarPos);
+               if (err)
+                       goto move_driver_error;
+       } else {
+               if (curPos < tarPos)
+                       moveStep = STMV_SIZE;
+               else
+                       moveStep = -STMV_SIZE;
+
+               /* Set StepMove Target Positon */
+               err = sh532u_write_u16(MS1Z12_211H, moveStep);
+               err = err | sh532u_write_u16(STMVENDH_211, tarPos);
+               /* Start StepMove */
+               err = err |
+                     sh532u_write_u8(
+                       STMVEN_211,
+                       (STMCHTG_ON | STMSV_ON | STMLFF_OFF | STMVEN_ON));
+               if (err)
+                       goto move_driver_error;
+       }
+
+       return;
+move_driver_error:
+       pr_err("Focuser: %s failed!\n", __func__);
+}
+
+static void wait_for_move(void)
+{
+       u16 usSmvFin;
+       u8 moveTime, ucParMod, tmp;
+       int err;
+
+       moveTime = 0;
+       do {
+               mdelay(1);
+               err = sh532u_read_u8(0, STMVEN_211, &ucParMod);
+               err = err | sh532u_read_u16(RZ_211H, &usSmvFin);
+               if (err)
+                       goto wait_for_move_error;
+               /* StepMove Error Handling, Unexpected Position */
+               if ((usSmvFin == 0x7FFF) || (usSmvFin == 0x8001)) {
+                       /* Stop StepMove Operation */
+                       err = sh532u_write_u8(STMVEN_211, ucParMod & 0xFE);
+                       if (err)
+                               goto wait_for_move_error;
+               }
+               moveTime++;
+               /* Wait StepMove operation end */
+       } while ((ucParMod & STMVEN_ON) && (moveTime < 50));
+
+       moveTime = 0;
+       if ((ucParMod & 0x08) == STMCHTG_ON) {
+               mdelay(5);
+               do {
+                       mdelay(1);
+                       moveTime++;
+                       err = sh532u_read_u8(0, MSSET_211, &tmp);
+                       if (err)
+                               goto wait_for_move_error;
+               } while ((tmp & CHTGST_ON) && (moveTime < 15));
+       }
+
+       return;
+wait_for_move_error:
+       pr_err("Focuser: %s failed!\n", __func__);
+}
+
+static void lens_move_pulse(s16 position)
+{
+       move_driver(position);
+       wait_for_move();
+}
+
+static void get_rom_info(void)
+{
+       u8 tmp;
+       int err;
+
+       /* Get Inf1, Mac1
+       Inf1 and Mac1 are the mechanical limit position.
+       Inf1     : Bottom limit.
+       Mac1 : Top limit. */
+       err = sh532u_read_u8(0x50, addrMac1, &tmp);
+       if (err)
+               goto get_rom_info_error;
+       info->config.limit_low = (tmp<<8) & 0xff00;
+       err = sh532u_read_u8(0x50, addrInf1, &tmp);
+       if (err)
+               goto get_rom_info_error;
+       info->config.limit_high = (tmp<<8) & 0xff00;
+
+       /* Get Inf2, Mac2
+       Inf2 and Mac2 are the calibration data for SEMCO AF lens.
+       Inf2: Best focus (lens position) when object distance is 1.2M.
+       Mac2: Best focus (lens position) when object distance is 10cm. */
+       err = sh532u_read_u8(0x50, addrMac2, &tmp);
+       if (err)
+               goto get_rom_info_error;
+       info->config.pos_low = (tmp << 8) & 0xff00;
+       err = sh532u_read_u8(0x50, addrInf2, &tmp);
+       if (err)
+               goto get_rom_info_error;
+       info->config.pos_high = (tmp << 8) & 0xff00;
+
+       return;
+get_rom_info_error:
+       pr_err("Focuser: %s failed!\n", __func__);
+       info->config.limit_high = POS_HIGH;
+       info->config.limit_low = POS_LOW;
+       info->config.pos_high = POS_HIGH;
+       info->config.pos_low = POS_LOW;
+}
+
+static void init_hvca_pos(void)
+{
+       short sBottomLimit, sTopLimit;
+
+       get_rom_info();
+       sBottomLimit = (((int)info->config.limit_low * 5) >> 3) & 0xFFC0;
+       lens_move_pulse(sBottomLimit);
+       sTopLimit = (((int)info->config.limit_high * 5) >> 3) & 0xFFC0;
+       lens_move_pulse(sTopLimit);
+       lens_move_pulse(info->config.pos_high);
+}
+
+static unsigned int a2buf[] = {
+       0x0018019c,
+       0x0018019d,
+       0x0000019e,
+       0x007f0192,
+       0x00000194,
+       0x00f00184,
+       0x00850187,
+       0x0000018a,
+       0x00fd7187,
+       0x007f7183,
+       0x0008025a,
+       0x05042218,
+       0x80010216,
+       0x000601a0,
+       0x00808183,
+       0xffffffff
+};
+
+/* Write 1 byte data to the HVCA Drive IC by data type */
+static void sh532u_hvca_wr1(u8 ep_type, u8 ep_data1, u8 ep_addr)
+{
+       int err;
+       u8 us_data;
+
+       switch (ep_type & 0xF0) {
+       case DIRECT_MODE:
+               us_data = ep_data1;
+               break;
+
+       case INDIRECT_EEPROM:
+               err = sh532u_read_u8(0x50, ep_data1, &us_data);
+               break;
+
+       case INDIRECT_HVCA:
+               err = sh532u_read_u8(0, (u16)ep_data1, &us_data);
+               break;
+
+       case MASK_AND:
+               err = sh532u_read_u8(0, (u16)ep_addr, &us_data);
+               us_data = us_data & ep_data1;
+               break;
+
+       case MASK_OR:
+               err = sh532u_read_u8(0, (u16)ep_addr, &us_data);
+               us_data = us_data | ep_data1;
+               break;
+
+       default:
+               err = 1;
+       }
+       if (!err)
+               sh532u_write_u8((u16)ep_addr, us_data);
+}
+
+/* Write 2 byte data to the HVCA Drive IC by data type */
+static void sh532u_hvca_wr2(u8 ep_type, u8 ep_data1, u8 ep_data2, u8 ep_addr)
+{
+       int err;
+       u8 uc_data1;
+       u8 uc_data2;
+       u16 us_data;
+
+       switch (ep_type & 0xF0) {
+       case DIRECT_MODE:
+               us_data = (((u16)ep_data1 << 8) & 0xFF00) |
+                       ((u16)ep_data2 & 0x00FF);
+               break;
+
+       case INDIRECT_EEPROM:
+               err = sh532u_read_u8(0x50, (u16)ep_data1, &uc_data1);
+               err = err | sh532u_read_u8(0x50, (u16)ep_data2, &uc_data2);
+               us_data = (((u16)uc_data1 << 8) & 0xFF00) |
+                       ((u16)uc_data2 & 0x00FF);
+               break;
+
+       case INDIRECT_HVCA:
+               err = sh532u_read_u8(0, (u16)ep_data1, &uc_data1);
+               err = err | sh532u_read_u8(0, (u16)ep_data2, &uc_data2);
+               us_data = (((u16)uc_data1 << 8) & 0xFF00) |
+                       ((u16)uc_data2 & 0x00FF);
+               break;
+
+       case MASK_AND:
+               err = sh532u_read_u16((u16)ep_addr, &us_data);
+               us_data = us_data & ((((u16)ep_data1 << 8) & 0xFF00) |
+                       ((u16)ep_data2 & 0x00FF));
+               break;
+
+       case MASK_OR:
+               err = sh532u_read_u16((u16)ep_addr, &us_data);
+               us_data = us_data | ((((u16)ep_data1 << 8) & 0xFF00) |
+                       ((u16)ep_data2 & 0x00FF));
+               break;
+
+       default:
+               err = 1;
+       }
+       if (!err)
+               sh532u_write_u16((u16)ep_addr, us_data);
+}
+
+static void init_driver(void)
+{
+       int eeprom_addr;
+       unsigned int eeprom_data;
+       u8 ep_addr, ep_type, ep_data1, ep_data2, uc_data;
+
+       for (eeprom_addr = 0x30; eeprom_addr <= 0x013C; eeprom_addr += 4) {
+               if (eeprom_addr > 0xff) {
+                       /* use hardcoded data instead */
+                       eeprom_data = a2buf[(eeprom_addr & 0xFF) / 4];
+               } else {
+                       if (!eeprom_read_u32(eeprom_addr & 0xFF, &eeprom_data))
+                               pr_info("sh532u: cannot read eeprom\n");
+               }
+
+               /* HVCA Address to write eeprom Data1,Data2 by the Data type */
+               ep_addr = (u8)(eeprom_data & 0x000000ff);
+               ep_type = (u8)((eeprom_data & 0x0000ff00) >> 8);
+               ep_data1 = (u8)((eeprom_data & 0x00ff0000) >> 16);
+               ep_data2 = (u8)((eeprom_data & 0xff000000) >> 24);
+
+               if (ep_addr == 0xFF)
+                       break;
+
+               if (ep_addr == 0xDD) {
+                       mdelay((unsigned int)((ep_data1 << 8) | ep_data2));
+               } else {
+                       if ((ep_type & 0x0F) == DATA_1BYTE) {
+                               sh532u_hvca_wr1(ep_type, ep_data1, ep_addr);
+                       } else {
+                               sh532u_hvca_wr2(ep_type,
+                                               ep_data1,
+                                               ep_data2,
+                                               ep_addr);
+                       }
+               }
+       }
+       msleep(300);
+
+       init_hvca_pos();
+}
+
+
+static int sh532u_set_position(struct sh532u_info *info, s16 position)
+{
+       if (position > info->config.limit_high)
+               return -1;
+       lens_move_pulse(position);
+       return 0;
+}
+
+static long sh532u_ioctl(
+       struct file *file,
+       unsigned int cmd,
+       unsigned long arg)
+{
+       struct sh532u_info *info = file->private_data;
+
+       switch (cmd) {
+       case SH532U_IOCTL_GET_CONFIG:
+               if (copy_to_user((void __user *) arg,
+                                &info->config,
+                                sizeof(info->config))) {
+                       pr_err("%s: 0x%x\n", __func__, __LINE__);
+                       return -EFAULT;
+               }
+               return 0;
+
+       case SH532U_IOCTL_SET_POSITION:
+               return sh532u_set_position(info, (s16)(arg & 0xffff));
+
+       default:
+               return -EINVAL;
+       }
+}
+
+
+static int sh532u_open(struct inode *inode, struct file *file)
+{
+       pr_info("sh532 open\n");
+       file->private_data = info;
+       init_driver();
+       return 0;
+}
+
+int sh532u_release(struct inode *inode, struct file *file)
+{
+       pr_info("sh532 release\n");
+       file->private_data = NULL;
+       return 0;
+}
+
+
+static const struct file_operations sh532u_fileops = {
+       .owner = THIS_MODULE,
+       .open = sh532u_open,
+       .unlocked_ioctl = sh532u_ioctl,
+       .release = sh532u_release,
+};
+
+static struct miscdevice sh532u_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "sh532u",
+       .fops = &sh532u_fileops,
+};
+
+static int sh532u_probe(
+       struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int err;
+
+       pr_info("sh532u: probing sensor.\n");
+       info = kzalloc(sizeof(struct sh532u_info), GFP_KERNEL);
+       if (!info) {
+               pr_err("sh532u: Unable to allocate memory!\n");
+               return -ENOMEM;
+       }
+       err = misc_register(&sh532u_device);
+       if (err) {
+               pr_err("sh532u: Unable to register misc device!\n");
+               kfree(info);
+               return err;
+       }
+       info->i2c_client = client;
+       info->config.settle_time = SETTLETIME_MS;
+       info->config.focal_length = FOCAL_LENGTH;
+       info->config.fnumber = FNUMBER;
+       info->config.pos_low = POS_LOW;
+       info->config.pos_high = POS_HIGH;
+       i2c_set_clientdata(client, info);
+       return 0;
+}
+
+static int sh532u_remove(struct i2c_client *client)
+{
+       struct sh532u_info *info;
+       info = i2c_get_clientdata(client);
+       misc_deregister(&sh532u_device);
+       kfree(info);
+       return 0;
+}
+
+static const struct i2c_device_id sh532u_id[] = {
+       { "sh532u", 0 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(i2c, sh532u_id);
+
+static struct i2c_driver sh532u_i2c_driver = {
+       .driver = {
+               .name = "sh532u",
+               .owner = THIS_MODULE,
+       },
+       .probe = sh532u_probe,
+       .remove = sh532u_remove,
+       .id_table = sh532u_id,
+};
+
+static int __init sh532u_init(void)
+{
+       return i2c_add_driver(&sh532u_i2c_driver);
+}
+
+static void __exit sh532u_exit(void)
+{
+       i2c_del_driver(&sh532u_i2c_driver);
+}
+
+module_init(sh532u_init);
+module_exit(sh532u_exit);
+
diff --git a/include/media/sh532u.h b/include/media/sh532u.h
new file mode 100644 (file)
index 0000000..b363c0f
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2011 NVIDIA Corporation.
+ *
+ * Contributors:
+ *      Qinggang Zhou <qzhou@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#ifndef __SH532U_H__
+#define __SH532U_H__
+
+#include <linux/ioctl.h> /* For IOCTL macros */
+
+#define SH532U_IOCTL_GET_CONFIG        _IOR('o', 1, struct sh532u_config)
+#define SH532U_IOCTL_SET_POSITION      _IOW('o', 2, u32)
+
+struct sh532u_config {
+       __u32 settle_time;
+       __u32 focal_length;
+       __u32 fnumber;
+       s16 pos_low;
+       s16 pos_high;
+       s16 limit_low;
+       s16 limit_high;
+};
+
+/* Register Definition  : Sany Driver IC */
+/* EEPROM addresses */
+#define addrHallOffset         0x10
+#define addrHallBias           0x11
+#define addrInf1               0x12
+#define addrMac1               0x13
+#define addrLoopGainH          0x14
+#define addrLoopGainL          0x15
+#define addrInf2               0x16
+#define addrMac2               0x17
+
+#define addrInf1_H             0x20 /* bottom mechanical limit of HVCA */
+#define addrInf1_L             0x21
+#define addrMac1_H             0x22 /* top mechanical limit of HVCA */
+#define addrMac1_L             0x23
+#define addrInf2_H             0x24 /* lens position when object is ?120cm */
+#define addrInf2_L             0x25
+#define addrMac2_H             0x26 /* lens position when object is ?10cm */
+#define addrMac2_L             0x27
+#define addrDacDeltaUp_H       0x28 /* difference between face up and down */
+#define addrDacDeltaUp_L       0x29
+#define addrAFoffset_H         0x2A /* best focus position subtract value */
+#define addrAFoffset_L         0x2B
+
+/* Convergence Judgement */
+#define INI_MSSET_211          0x00
+#define CHTGOKN_TIME           0x80
+#define CHTGOKN_WAIT           1
+#define CHTGOKN_TIMEOUT                50
+#define CHTGSTOKN_TOMEOUT      15
+
+/* StepMove */
+#define STMV_SIZE              0x0180
+
+#define STMCHTG_ON             0x08
+#define STMSV_ON               0x04
+#define STMLFF_ON              0x02
+#define STMVEN_ON              0x01
+#define STMCHTG_OFF            0x00
+#define STMSV_OFF              0x00
+#define STMLFF_OFF             0x00
+#define STMVEN_OFF             0x00
+
+#define STMCHTG_SET            STMCHTG_ON
+#define STMSV_SET              STMSV_ON
+#define STMLFF_SET             STMLFF_OFF
+
+#define CHTGST_ON              0x01
+#define DEFAULT_DADAT          0x8040
+
+/* Delay RAM 00h ~ 3Fh */
+#define ADHXI_211H             0x00
+#define ADHXI_211L             0x01
+#define PIDZO_211H             0x02
+#define PIDZO_211L             0x03
+#define RZ_211H                0x04
+#define RZ_211L                0x05
+#define DZ1_211H               0x06
+#define DZ1_211L               0x07
+#define DZ2_211H               0x08
+#define DZ2_211L               0x09
+#define UZ1_211H               0x0A
+#define UZ1_211L               0x0B
+#define UZ2_211H               0x0C
+#define UZ2_211L               0x0D
+#define IZ1_211H               0x0E
+#define IZ1_211L               0x0F
+#define IZ2_211H               0x10
+#define IZ2_211L               0x11
+#define MS1Z01_211H            0x12
+#define MS1Z01_211L            0x13
+#define MS1Z11_211H            0x14
+#define MS1Z11_211L            0x15
+#define MS1Z12_211H            0x16
+#define MS1Z12_211L            0x17
+#define MS1Z22_211H            0x18
+#define MS1Z22_211L            0x19
+#define MS2Z01_211H            0x1A
+#define MS2Z01_211L            0x1B
+#define MS2Z11_211H            0x1C
+#define MS2Z11_211L            0x1D
+#define MS2Z12_211H            0x1E
+#define MS2Z12_211L            0x1F
+#define MS2Z22_211H            0x20
+#define MS2Z22_211L            0x21
+#define MS2Z23_211H            0x22
+#define MS2Z23_211L            0x23
+#define OZ1_211H               0x24
+#define OZ1_211L               0x25
+#define OZ2_211H               0x26
+#define OZ2_211L               0x27
+#define DAHLXO_211H            0x28
+#define DAHLXO_211L            0x29
+#define OZ3_211H               0x2A
+#define OZ3_211L               0x2B
+#define OZ4_211H               0x2C
+#define OZ4_211L               0x2D
+#define OZ5_211H               0x2E
+#define OZ5_211L               0x2F
+#define oe_211H                0x30
+#define oe_211L                0x31
+#define MSR1CMAX_211H          0x32
+#define MSR1CMAX_211L          0x33
+#define MSR1CMIN_211H          0x34
+#define MSR1CMIN_211L          0x35
+#define MSR2CMAX_211H          0x36
+#define MSR2CMAX_211L          0x37
+#define MSR2CMIN_211H          0x38
+#define MSR2CMIN_211L          0x39
+#define OFFSET_211H            0x3A
+#define OFFSET_211L            0x3B
+#define ADOFFSET_211H          0x3C
+#define ADOFFSET_211L          0x3D
+#define EZ_211H                0x3E
+#define EZ_211L                0x3F
+
+/* Coefficient RAM 40h ~ 7Fh */
+#define ag_211H                0x40
+#define ag_211L                0x41
+#define da_211H                0x42
+#define da_211L                0x43
+#define db_211H                0x44
+#define db_211L                0x45
+#define dc_211H                0x46
+#define dc_211L                0x47
+#define dg_211H                0x48
+#define dg_211L                0x49
+#define pg_211H                0x4A
+#define pg_211L                0x4B
+#define gain1_211H             0x4C
+#define gain1_211L             0x4D
+#define gain2_211H             0x4E
+#define gain2_211L             0x4F
+#define ua_211H                0x50
+#define ua_211L                0x51
+#define uc_211H                0x52
+#define uc_211L                0x53
+#define ia_211H                0x54
+#define ia_211L                0x55
+#define ib_211H                0x56
+#define ib_211L                0x57
+#define i_c_211H               0x58
+#define i_c_211L               0x59
+#define ms11a_211H             0x5A
+#define ms11a_211L             0x5B
+#define ms11c_211H             0x5C
+#define ms11c_211L             0x5D
+#define ms12a_211H             0x5E
+#define ms12a_211L             0x5F
+#define ms12c_211H             0x60
+#define ms12c_211L             0x61
+#define ms21a_211H             0x62
+#define ms21a_211L             0x63
+#define ms21b_211H             0x64
+#define ms21b_211L             0x65
+#define ms21c_211H             0x66
+#define ms21c_211L             0x67
+#define ms22a_211H             0x68
+#define ms22a_211L             0x69
+#define ms22c_211H             0x6A
+#define ms22c_211L             0x6B
+#define ms22d_211H             0x6C
+#define ms22d_211L             0x6D
+#define ms22e_211H             0x6E
+#define ms22e_211L             0x6F
+#define ms23p_211H             0x70
+#define ms23p_211L             0x71
+#define oa_211H                0x72
+#define oa_211L                0x73
+#define oc_211H                0x74
+#define oc_211L                0x75
+#define PX12_211H              0x76
+#define PX12_211L              0x77
+#define PX3_211H               0x78
+#define PX3_211L               0x79
+#define MS2X_211H              0x7A
+#define MS2X_211L              0x7B
+#define CHTGX_211H             0x7C
+#define CHTGX_211L             0x7D
+#define CHTGN_211H             0x7E
+#define CHTGN_211L             0x7F
+
+/* Register 80h ~  9F */
+#define CLKSEL_211             0x80
+#define ADSET_211              0x81
+#define PWMSEL_211             0x82
+#define SWTCH_211              0x83
+#define STBY_211               0x84
+#define CLR_211                0x85
+#define DSSEL_211              0x86
+#define ENBL_211               0x87
+#define ANA1_211               0x88
+#define STMVEN_211             0x8A
+#define STPT_211               0x8B
+#define SWFC_211               0x8C
+#define SWEN_211               0x8D
+#define MSNUM_211              0x8E
+#define MSSET_211              0x8F
+#define DLYMON_211             0x90
+#define MONA_211               0x91
+#define PWMLIMIT_211           0x92
+#define PINSEL_211             0x93
+#define PWMSEL2_211            0x94
+#define SFTRST_211             0x95
+#define TEST_211               0x96
+#define PWMZONE2_211           0x97
+#define PWMZONE1_211           0x98
+#define PWMZONE0_211           0x99
+#define ZONE3_211              0x9A
+#define ZONE2_211              0x9B
+#define ZONE1_211              0x9C
+#define ZONE0_211              0x9D
+#define GCTIM_211              0x9E
+#define GCTIM_211NU            0x9F
+#define STMINT_211             0xA0
+#define STMVENDH_211           0xA1
+#define STMVENDL_211           0xA2
+#define MSNUMR_211             0xA3
+#define  ANA2_211              0xA4
+
+/* Device ID of HVCA Drive IC */
+#define HVCA_DEVICE_ID         0xE4
+
+/* Device ID of E2P ROM */
+#define EEP_DEVICE_ID          0xA0
+#define EEP_PAGE0              0x00
+#define EEP_PAGE1              0x02
+#define EEP_PAGE2              0x04
+#define EEP_PAGE3              0x06
+/* E2P ROM has 1023 bytes. So there are 4 pages memory */
+/* E2PROM Device ID = 1 0 1 0  0 P0 P1 0 */
+/*
+P0  P1
+0   0   : Page 0
+0   1   : Page 1
+1   0   : Page 2
+1   1   : Page 3
+*/
+/* Page 0: address 0x000~0x0FF, E2PROM Device ID = E2P_DEVICE_ID|E2P_PAGE0 */
+/* Page 1: address 0x100~0x1FF, E2PROM Device ID = E2P_DEVICE_ID|E2P_PAGE1 */
+/* Page 2: address 0x200~0x2FF, E2PROM Device ID = E2P_DEVICE_ID|E2P_PAGE2 */
+/* Page 3: address 0x300~0x3FF, E2PROM Device ID = E2P_DEVICE_ID|E2P_PAGE3 */
+/*
+*/
+
+/* E2P data type define of HVCA Initial Value Section */
+#define DIRECT_MODE            0x00
+#define INDIRECT_EEPROM        0x10
+#define INDIRECT_HVCA          0x20
+#define MASK_AND               0x70
+#define MASK_OR                0x80
+
+#define DATA_1BYTE             0x01
+#define DATA_2BYTE             0x02
+
+#define START_ADDR             0x0030
+#define END_ADDR               0x01BF
+
+/*Macro define*/
+#define abs(a)         (((a) > 0) ? (a) : -(a))
+
+#endif
+/* __SH532U_H__ */
+