rk2928_phonepad: adjust ap321xx l/p sensor to compatibale sensor framework
authorlinjh <linjh@rock-chips.com>
Wed, 24 Oct 2012 03:53:42 +0000 (11:53 +0800)
committerlinjh <linjh@rock-chips.com>
Wed, 24 Oct 2012 03:58:12 +0000 (11:58 +0800)
[reference files]

modified:
arch/arm/configs/rk2928_phonepad_defconfig
arch/arm/mach-rk2928/board-rk2928-phonepad.c
arch/arm/mach-rk2928/include/mach/board.h
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/sensors/lsensor/Kconfig
drivers/input/sensors/lsensor/Makefile
drivers/input/sensors/psensor/Kconfig
drivers/input/sensors/psensor/Makefile
drivers/input/sensors/sensor-dev.c
include/linux/sensor-dev.h
new file:
drivers/input/sensors/psensor/ps_ap321xx.c
drivers/input/sensors/lsensor/ls_ap321xx.c
deleted:
drivers/input/misc/ap321xx.c

14 files changed:
arch/arm/configs/rk2928_phonepad_defconfig
arch/arm/mach-rk2928/board-rk2928-phonepad.c
arch/arm/mach-rk2928/include/mach/board.h
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ap321xx.c [deleted file]
drivers/input/sensors/lsensor/Kconfig
drivers/input/sensors/lsensor/Makefile
drivers/input/sensors/lsensor/ls_ap321xx.c [new file with mode: 0644]
drivers/input/sensors/psensor/Kconfig
drivers/input/sensors/psensor/Makefile
drivers/input/sensors/psensor/ps_ap321xx.c [new file with mode: 0644]
drivers/input/sensors/sensor-dev.c
include/linux/sensor-dev.h

index 12cacb9c6440ccf5ad3fd4bb1e3561d5cd44fd13..69a59160979194baea9b3e7fc337b3ceffe2b0b8 100644 (file)
@@ -241,12 +241,15 @@ CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_I30=y
 CONFIG_TOUCHSCREEN_BYD693X=y
 CONFIG_INPUT_MISC=y
-CONFIG_INPUT_AP321XX=y
 CONFIG_INPUT_KEYCHORD=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_SENSOR_DEVICE=y
 CONFIG_GSENSOR_DEVICE=y
 CONFIG_GS_KXTIK=y
+CONFIG_LIGHT_DEVICE=y
+CONFIG_LS_AP321XX=y
+CONFIG_PROXIMITY_DEVICE=y
+CONFIG_PS_AP321XX=y
 # CONFIG_SERIO is not set
 # CONFIG_CONSOLE_TRANSLATIONS is not set
 # CONFIG_LEGACY_PTYS is not set
index d99b92da9639121dd543a017471ad0ab8a6522ad..d58e9bb6aea0f6ddc18151a35748780691bd3df2 100755 (executable)
@@ -418,84 +418,33 @@ static struct sensor_platform_data mma7660_info = {
 
 #if defined (CONFIG_GS_KXTIK)
 #define KXTIK_INT_PIN         RK2928_PIN3_PD1
-#if 0
-
-static int kxtik_init_hw(void)
-{
-       int ret = 0;
-       
-       ret = gpio_request(KXTIK_INT_PIN,"kxtik_irq");
-       if(ret){
-               printk("kxtik gpio request fail!\n");
-               return ret;
-       }
-       else{
-               gpio_direction_input(KXTIK_INT_PIN);
-       }
-       return ret;
-}
-static void kxtik_exit_hw(void)
-{
-       gpio_free(KXTIK_INT_PIN);
-}
-
-static struct gsensor_platform_data kxtik_pdata = {
-       .swap_xy = 0,
-       .swap_xyz = 1,
-       .init_platform_hw = kxtik_init_hw,
-       .exit_platform_hw = kxtik_exit_hw,
-       .orientation = {-1, 0, 0, 0, 0, -1, 0, 1, 0},
-};
-
-#endif
-static int kxtik_init_platform_hw(void)
-{
-       printk("%s: >>>>>>>>>>>>>>>>\n\n\n", __func__);
-       return 0;
-}
 
 static struct sensor_platform_data kxtik_pdata = {
        .type = SENSOR_TYPE_ACCEL,
        .irq_enable = 1,
        .poll_delay_ms = 30,
-       .init_platform_hw = kxtik_init_platform_hw,
        .orientation = {-1, 0, 0, 0, 0, -1, 0, 1, 0},
-       //.orientation = {0, 1, 0, 0, 0, -1, 1, 0, 0},
 };
 
 #endif /* CONFIG_GS_KXTIK*/
 
-#ifdef CONFIG_INPUT_AP321XX
-#define AP321XX_INT_PIN         RK2928_PIN0_PC6
-
-static int AP321XX_init_hw(void)
-{
-       int ret = 0;
-       ret = gpio_request(AP321XX_INT_PIN, NULL);
-       if (ret != 0)
-       {
-               gpio_free(AP321XX_INT_PIN);
-               printk(KERN_ERR "request AP321XX_INT_PIN fail!\n");
-               return -1;
-       }
-       else
-       {
-               gpio_direction_input(AP321XX_INT_PIN);
-       }
-       return 0;
-}
-
-static void AP321XX_exit_hw(void)
-{
-       gpio_free(AP321XX_INT_PIN);
-       return;
-}
+#ifdef CONFIG_LS_AP321XX
+#define LS_AP321XX_INT_PIN         RK2928_PIN0_PC6
 
-static struct ap321xx_platform_data ap321xx_info = {
-       .init_platform_hw = AP321XX_init_hw,
-       .exit_platform_hw = AP321XX_exit_hw,
+static struct sensor_platform_data ls_ap321xx_info = {
+       .type = SENSOR_TYPE_LIGHT,
+       .irq_enable = 1,
+       .poll_delay_ms = 500,
 };
+#endif
+#ifdef CONFIG_PS_AP321XX
+#define PS_AP321XX_INT_PIN         RK2928_PIN0_PC6
 
+static struct sensor_platform_data ps_ap321xx_info = {
+       .type = SENSOR_TYPE_PROXIMITY,
+       .irq_enable = 1,
+       .poll_delay_ms = 500,
+};
 #endif
 
 #if defined(CONFIG_BATTERY_RK30_ADC)||defined(CONFIG_BATTERY_RK30_ADC_FAC)
@@ -909,15 +858,26 @@ static struct i2c_board_info __initdata i2c1_info[] = {
                },
 #endif
 
-#ifdef CONFIG_INPUT_AP321XX
+#ifdef CONFIG_LS_AP321XX
         {
-                .type                   = "ap321xx",
+                .type                   = "ls_ap321xx",
                 .addr                   = 0x1E,
                 .flags                  = 0,
-                .irq                     = AP321XX_INT_PIN,
-                .platform_data = &ap321xx_info
+                .irq                     = LS_AP321XX_INT_PIN,
+                .platform_data = &ls_ap321xx_info
         },
 #endif
+
+#ifdef CONFIG_PS_AP321XX
+        {
+                .type                   = "ps_ap321xx",
+                .addr                   = 0x1E,
+                .flags                  = 0,
+                .irq                     = PS_AP321XX_INT_PIN,
+                .platform_data = &ps_ap321xx_info
+        },
+#endif
+
 #ifdef CONFIG_RDA5990
 #define RDA_WIFI_CORE_ADDR (0x13)
 #define RDA_WIFI_RF_ADDR (0x14) //correct add is 0x14
index 1c93a099548d3ee8b481b197b9a92423eb2bf889..c843b1cdde48d231acc24c740a97ec7205c47012 100755 (executable)
@@ -145,13 +145,6 @@ struct byd_platform_data {
 };
 #endif
 
-#ifdef CONFIG_INPUT_AP321XX
-struct ap321xx_platform_data {
-       int (*init_platform_hw)(void);
-       void (*exit_platform_hw)(void);
-};
-#endif
-
 enum _periph_pll {
        periph_pll_1485mhz = 148500000,
        periph_pll_297mhz = 297000000,
index f5ab923449ecc91a669deb374171b4192f011969..b2d165feab474acadeb1c7add2aa992f054a3043 100755 (executable)
@@ -21,12 +21,6 @@ config INPUT_LPSENSOR_CM3602
 config INPUT_LPSENSOR_AL3006
        tristate "al3006 l/p sensor input support"
 
-config INPUT_AP321XX
-       tristate "ap321xx light and proximity sensor support"
-       default n
-       help     
-         To have support for AP321XX serial light and proximity sensor.
-
 config INPUT_88PM860X_ONKEY
        tristate "88PM860x ONKEY support"
        depends on MFD_88PM860X
index 1619523e8e58c6eeb7d7120b834a5ce03ce6a188..59575af2c53d2251d2cb8dd3393683f7fd068042 100755 (executable)
@@ -52,4 +52,3 @@ obj-$(CONFIG_INPUT_WM831X_ON)         += wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)        += xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
 obj-$(CONFIG_INPUT_LPSENSOR_AL3006)    += al3006.o
-obj-$(CONFIG_INPUT_AP321XX)            += ap321xx.o
diff --git a/drivers/input/misc/ap321xx.c b/drivers/input/misc/ap321xx.c
deleted file mode 100644 (file)
index 495123b..0000000
+++ /dev/null
@@ -1,1395 +0,0 @@
-/*
- * This file is part of the AP3212B, AP3212C and AP3216C sensor driver.
- * AP3212B is combined proximity and ambient light sensor.
- * AP3216C is combined proximity, ambient light sensor and IRLED.
- *
- * Contact: YC Hou <yc.hou@liteonsemi.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., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- *
- * Filename: ap321XX.c
- *
- * Summary:
- *     AP3212B v1.5-1.8 and AP3212C/AP3216C v2.0-v2.3 sensor dirver.
- *
- * Modification History:
- * Date     By       Summary
- * -------- -------- -------------------------------------------------------
- * 06/28/11 YC          Original Creation (Test version:1.0)
- * 06/28/11 YC       Change dev name to dyna for demo purpose (ver 1.5).
- * 08/29/11 YC       Add engineer mode. Change version to 1.6.
- * 09/26/11 YC       Add calibration compensation function and add not power up 
- *                   prompt. Change version to 1.7.
- * 02/02/12 YC       1. Modify irq function to seperate two interrupt routine. 
- *                                      2. Fix the index of reg array error in em write. 
- * 02/22/12 YC       3. Merge AP3212B and AP3216C into the same driver. (ver 1.8)
- * 03/01/12 YC       Add AP3212C into the driver. (ver 1.8)
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/string.h>
-#include <mach/gpio.h>
-#include <linux/miscdevice.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-#include <mach/board.h>
-
-#define AP3212B_DRV_NAME               "ap321xx"
-#define DRIVER_VERSION         "1.8"
-
-#define AP3212B_NUM_CACHABLE_REGS      23
-#define AP3216C_NUM_CACHABLE_REGS      26
-
-#define AP3212B_RAN_COMMAND    0x10
-#define AP3212B_RAN_MASK               0x30
-#define AP3212B_RAN_SHIFT      (4)
-
-#define AP3212B_MODE_COMMAND   0x00
-#define AP3212B_MODE_SHIFT     (0)
-#define AP3212B_MODE_MASK      0x07
-
-#define        AL3212_ADC_LSB          0x0c
-#define        AL3212_ADC_MSB          0x0d
-
-#define        AL3212_PX_LSB           0x0e
-#define        AL3212_PX_MSB           0x0f
-#define        AL3212_PX_LSB_MASK      0x0f
-#define        AL3212_PX_MSB_MASK      0x3f
-
-#define AP3212B_OBJ_COMMAND    0x0f
-#define AP3212B_OBJ_MASK               0x80
-#define AP3212B_OBJ_SHIFT      (7)
-
-#define AP3212B_INT_COMMAND    0x01
-#define AP3212B_INT_SHIFT      (0)
-#define AP3212B_INT_MASK               0x03
-#define AP3212B_INT_PMASK              0x02
-#define AP3212B_INT_AMASK              0x01
-
-#define AP3212B_ALS_LTHL                       0x1a
-#define AP3212B_ALS_LTHL_SHIFT (0)
-#define AP3212B_ALS_LTHL_MASK  0xff
-
-#define AP3212B_ALS_LTHH                       0x1b
-#define AP3212B_ALS_LTHH_SHIFT (0)
-#define AP3212B_ALS_LTHH_MASK  0xff
-
-#define AP3212B_ALS_HTHL                       0x1c
-#define AP3212B_ALS_HTHL_SHIFT (0)
-#define AP3212B_ALS_HTHL_MASK  0xff
-
-#define AP3212B_ALS_HTHH                       0x1d
-#define AP3212B_ALS_HTHH_SHIFT (0)
-#define AP3212B_ALS_HTHH_MASK  0xff
-
-#define AP3212B_PX_LTHL                        0x2a
-#define AP3212B_PX_LTHL_SHIFT  (0)
-#define AP3212B_PX_LTHL_MASK           0x03
-
-#define AP3212B_PX_LTHH                        0x2b
-#define AP3212B_PX_LTHH_SHIFT  (0)
-#define AP3212B_PX_LTHH_MASK           0xff
-
-#define AP3212B_PX_HTHL                        0x2c
-#define AP3212B_PX_HTHL_SHIFT  (0)
-#define AP3212B_PX_HTHL_MASK           0x03
-
-#define AP3212B_PX_HTHH                        0x2d
-#define AP3212B_PX_HTHH_SHIFT  (0)
-#define AP3212B_PX_HTHH_MASK           0xff
-
-#define AP3212B_PX_CONFIGURE   0x20
-
-#define PSENSOR_IOCTL_MAGIC 'c'
-#define PSENSOR_IOCTL_GET_ENABLED _IOR(PSENSOR_IOCTL_MAGIC, 1, int *)
-#define PSENSOR_IOCTL_ENABLE _IOW(PSENSOR_IOCTL_MAGIC, 2, int *)
-
-#define LIGHTSENSOR_IOCTL_MAGIC 'l'
-#define LIGHTSENSOR_IOCTL_GET_ENABLED _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *)
-#define LIGHTSENSOR_IOCTL_ENABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *)
-
-
-#define LSC_DBG
-#ifdef LSC_DBG
-#define LDBG(s,args...)        {printk("LDBG: func [%s], line [%d], ",__func__,__LINE__); printk(s,## args);}
-#else
-#define LDBG(s,args...) {}
-#endif
-
-struct ap321xx_data {
-       struct i2c_client *client;
-       u8 reg_cache[AP3216C_NUM_CACHABLE_REGS];
-       u8 power_state_before_suspend;
-       int irq;
-       struct input_dev        *psensor_input_dev;
-       struct input_dev        *lsensor_input_dev;
-};
-
-// AP3216C / AP3212C register
-static u8 ap3216c_reg[AP3216C_NUM_CACHABLE_REGS] = 
-       {0x00,0x01,0x02,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
-        0x10,0x19,0x1a,0x1b,0x1c,0x1d,
-        0x20,0x21,0x22,0x23,0x24,0x28,0x29,0x2a,0x2b,0x2c,0x2d};
-
-// AP3216C / AP3212C range
-static int ap3216c_range[4] = {23360,5840,1460,265};
-
-// AP3212B register
-static u8 ap3212b_reg[AP3212B_NUM_CACHABLE_REGS] = 
-       {0x00,0x01,0x02,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
-        0x10,0x11,0x1a,0x1b,0x1c,0x1d,
-        0x20,0x21,0x22,0x23,0x2a,0x2b,0x2c,0x2d};
-
-// AP3212B range
-static int ap3212b_range[4] = {65535,16383,4095,1023};
-
-static u16 ap321xx_threshole[8] = {28,444,625,888,1778,3555,7222,0xffff};
-
-static u8 *reg_array;
-static int *range;
-static int reg_num = 0;
-
-static int cali = 100;
-
-#define ADD_TO_IDX(addr,idx)   {                                                                                                               \
-                                                                       int i;                                                                                          \
-                                                                       for(i = 0; i < reg_num; i++)                                            \
-                                                                       {                                                                                                       \
-                                                                               if (addr == reg_array[i])                                               \
-                                                                               {                                                                                               \
-                                                                                       idx = i;                                                                        \
-                                                                                       break;                                                                          \
-                                                                               }                                                                                               \
-                                                                       }                                                                                                       \
-                                                               }
-
-
-/*
- * register access helpers
- */
-
-static int __ap321xx_read_reg(struct i2c_client *client,
-                              u32 reg, u8 mask, u8 shift)
-{
-       struct ap321xx_data *data = i2c_get_clientdata(client);
-       u8 idx = 0xff;
-
-       ADD_TO_IDX(reg,idx)
-       return (data->reg_cache[idx] & mask) >> shift;
-}
-
-static int __ap321xx_write_reg(struct i2c_client *client,
-                               u32 reg, u8 mask, u8 shift, u8 val)
-{
-       struct ap321xx_data *data = i2c_get_clientdata(client);
-       int ret = 0;
-       u8 tmp;
-       u8 idx = 0xff;
-
-       ADD_TO_IDX(reg,idx)
-       if (idx >= reg_num)
-               return -EINVAL;
-
-       tmp = data->reg_cache[idx];
-       tmp &= ~mask;
-       tmp |= val << shift;
-
-       ret = i2c_smbus_write_byte_data(client, reg, tmp);
-       if (!ret)
-               data->reg_cache[idx] = tmp;
-
-       return ret;
-}
-
-/*
- * internally used functions
- */
-
-/* range */
-static int ap321xx_get_range(struct i2c_client *client)
-{
-       u8 idx = __ap321xx_read_reg(client, AP3212B_RAN_COMMAND,
-               AP3212B_RAN_MASK, AP3212B_RAN_SHIFT); 
-       return range[idx];
-}
-
-static int ap321xx_set_range(struct i2c_client *client, int range)
-{
-       return __ap321xx_write_reg(client, AP3212B_RAN_COMMAND,
-               AP3212B_RAN_MASK, AP3212B_RAN_SHIFT, range);;
-}
-
-
-/* mode */
-static int ap321xx_get_mode(struct i2c_client *client)
-{
-       int ret;
-
-       ret = __ap321xx_read_reg(client, AP3212B_MODE_COMMAND,
-                       AP3212B_MODE_MASK, AP3212B_MODE_SHIFT);
-       return ret;
-}
-
-static int ap321xx_set_mode(struct i2c_client *client, int mode)
-{
-       int ret;
-
-       ret = __ap321xx_write_reg(client, AP3212B_MODE_COMMAND,
-                               AP3212B_MODE_MASK, AP3212B_MODE_SHIFT, mode);
-       return ret;
-}
-
-/* ALS low threshold */
-static int ap321xx_get_althres(struct i2c_client *client)
-{
-       int lsb, msb;
-       lsb = __ap321xx_read_reg(client, AP3212B_ALS_LTHL,
-                               AP3212B_ALS_LTHL_MASK, AP3212B_ALS_LTHL_SHIFT);
-       msb = __ap321xx_read_reg(client, AP3212B_ALS_LTHH,
-                               AP3212B_ALS_LTHH_MASK, AP3212B_ALS_LTHH_SHIFT);
-       return ((msb << 8) | lsb);
-}
-
-static int ap321xx_set_althres(struct i2c_client *client, int val)
-{
-       int lsb, msb, err;
-       
-       msb = val >> 8;
-       lsb = val & AP3212B_ALS_LTHL_MASK;
-
-       err = __ap321xx_write_reg(client, AP3212B_ALS_LTHL,
-               AP3212B_ALS_LTHL_MASK, AP3212B_ALS_LTHL_SHIFT, lsb);
-       if (err)
-               return err;
-
-       err = __ap321xx_write_reg(client, AP3212B_ALS_LTHH,
-               AP3212B_ALS_LTHH_MASK, AP3212B_ALS_LTHH_SHIFT, msb);
-
-       return err;
-}
-
-/* ALS high threshold */
-static int ap321xx_get_ahthres(struct i2c_client *client)
-{
-       int lsb, msb;
-       lsb = __ap321xx_read_reg(client, AP3212B_ALS_HTHL,
-                               AP3212B_ALS_HTHL_MASK, AP3212B_ALS_HTHL_SHIFT);
-       msb = __ap321xx_read_reg(client, AP3212B_ALS_HTHH,
-                               AP3212B_ALS_HTHH_MASK, AP3212B_ALS_HTHH_SHIFT);
-       return ((msb << 8) | lsb);
-}
-
-static int ap321xx_set_ahthres(struct i2c_client *client, int val)
-{
-       int lsb, msb, err;
-       
-       msb = val >> 8;
-       lsb = val & AP3212B_ALS_HTHL_MASK;
-       
-       err = __ap321xx_write_reg(client, AP3212B_ALS_HTHL,
-               AP3212B_ALS_HTHL_MASK, AP3212B_ALS_HTHL_SHIFT, lsb);
-       if (err)
-               return err;
-
-       err = __ap321xx_write_reg(client, AP3212B_ALS_HTHH,
-               AP3212B_ALS_HTHH_MASK, AP3212B_ALS_HTHH_SHIFT, msb);
-
-       return err;
-}
-
-/* PX low threshold */
-static int ap321xx_get_plthres(struct i2c_client *client)
-{
-       int lsb, msb;
-       lsb = __ap321xx_read_reg(client, AP3212B_PX_LTHL,
-                               AP3212B_PX_LTHL_MASK, AP3212B_PX_LTHL_SHIFT);
-       msb = __ap321xx_read_reg(client, AP3212B_PX_LTHH,
-                               AP3212B_PX_LTHH_MASK, AP3212B_PX_LTHH_SHIFT);
-       return ((msb << 2) | lsb);
-}
-
-static int ap321xx_set_plthres(struct i2c_client *client, int val)
-{
-       int lsb, msb, err;
-       
-       msb = val >> 2;
-       lsb = val & AP3212B_PX_LTHL_MASK;
-       
-       err = __ap321xx_write_reg(client, AP3212B_PX_LTHL,
-               AP3212B_PX_LTHL_MASK, AP3212B_PX_LTHL_SHIFT, lsb);
-       if (err)
-               return err;
-
-       err = __ap321xx_write_reg(client, AP3212B_PX_LTHH,
-               AP3212B_PX_LTHH_MASK, AP3212B_PX_LTHH_SHIFT, msb);
-
-       return err;
-}
-
-/* PX high threshold */
-static int ap321xx_get_phthres(struct i2c_client *client)
-{
-       int lsb, msb;
-       lsb = __ap321xx_read_reg(client, AP3212B_PX_HTHL,
-                               AP3212B_PX_HTHL_MASK, AP3212B_PX_HTHL_SHIFT);
-       msb = __ap321xx_read_reg(client, AP3212B_PX_HTHH,
-                               AP3212B_PX_HTHH_MASK, AP3212B_PX_HTHH_SHIFT);
-       return ((msb << 2) | lsb);
-}
-
-static int ap321xx_set_phthres(struct i2c_client *client, int val)
-{
-       int lsb, msb, err;
-       
-       msb = val >> 2;
-       lsb = val & AP3212B_ALS_HTHL_MASK;
-       
-       err = __ap321xx_write_reg(client, AP3212B_PX_HTHL,
-               AP3212B_PX_HTHL_MASK, AP3212B_PX_HTHL_SHIFT, lsb);
-       if (err)
-               return err;
-
-       err = __ap321xx_write_reg(client, AP3212B_PX_HTHH,
-               AP3212B_PX_HTHH_MASK, AP3212B_PX_HTHH_SHIFT, msb);
-
-       return err;
-}
-
-static int ap321xx_get_adc_value(struct i2c_client *client)
-{
-       unsigned int lsb, msb, val;
-#ifdef LSC_DBG
-       unsigned int tmp,range;
-#endif
-       unsigned char index=0;
-
-       lsb = i2c_smbus_read_byte_data(client, AL3212_ADC_LSB);
-
-       if (lsb < 0) {
-               return lsb;
-       }
-
-       msb = i2c_smbus_read_byte_data(client, AL3212_ADC_MSB);
-
-       if (msb < 0)
-               return msb;
-
-#ifdef LSC_DBG
-       range = ap321xx_get_range(client);
-       tmp = (((msb << 8) | lsb) * range) >> 16;
-       tmp = tmp * cali / 100;
-       LDBG("ALS val=%d lux\n",tmp);
-#endif
-       val = msb << 8 | lsb;
-       for(index = 0; index < 7 && val > ap321xx_threshole[index];index++)
-               ;
-
-       return index;
-}
-
-static int ap321xx_get_object(struct i2c_client *client)
-{
-       int val;
-
-       val = i2c_smbus_read_byte_data(client, AP3212B_OBJ_COMMAND);
-       val &= AP3212B_OBJ_MASK;
-
-       return val >> AP3212B_OBJ_SHIFT;
-}
-
-static int ap321xx_get_intstat(struct i2c_client *client)
-{
-       int val;
-       
-       val = i2c_smbus_read_byte_data(client, AP3212B_INT_COMMAND);
-       val &= AP3212B_INT_MASK;
-
-       return val >> AP3212B_INT_SHIFT;
-}
-
-
-static int ap321xx_get_px_value(struct i2c_client *client)
-{
-       int lsb, msb;
-
-       lsb = i2c_smbus_read_byte_data(client, AL3212_PX_LSB);
-
-       if (lsb < 0) {
-               return lsb;
-       }
-
-       msb = i2c_smbus_read_byte_data(client, AL3212_PX_MSB);
-
-       if (msb < 0)
-               return msb;
-
-       return (u32)(((msb & AL3212_PX_MSB_MASK) << 4) | (lsb & AL3212_PX_LSB_MASK));
-}
-
-#if 0
-/*
- * sysfs layer
- */
-static int ap321xx_input_init(struct ap321xx_data *data)
-{
-    struct input_dev *dev;
-    int err;
-
-    dev = input_allocate_device();
-    if (!dev) {
-        return -ENOMEM;
-    }
-    dev->name = "lightsensor-level";
-    dev->id.bustype = BUS_I2C;
-
-    input_set_capability(dev, EV_ABS, ABS_MISC);
-    input_set_capability(dev, EV_ABS, ABS_RUDDER);
-    input_set_drvdata(dev, data);
-
-    err = input_register_device(dev);
-    if (err < 0) {
-        input_free_device(dev);
-        return err;
-    }
-    data->input = dev;
-
-    return 0;
-}
-
-static void ap321xx_input_fini(struct ap321xx_data *data)
-{
-    struct input_dev *dev = data->input;
-
-    input_unregister_device(dev);
-    input_free_device(dev);
-}
-#else
-static int ap321xx_lsensor_open(struct inode *inode, struct file *file);
-static int ap321xx_lsensor_release(struct inode *inode, struct file *file);
-static long ap321xx_lsensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-static void ap321xx_change_ls_threshold(struct i2c_client *client);
-
-static int misc_ls_opened = 0;
-static struct file_operations ap321xx_lsensor_fops = {
-       .owner = THIS_MODULE,
-       .open = ap321xx_lsensor_open,
-       .release = ap321xx_lsensor_release,
-       .unlocked_ioctl = ap321xx_lsensor_ioctl
-};
-
-static struct miscdevice ap321xx_lsensor_misc = {
-       .minor = MISC_DYNAMIC_MINOR,
-       .name = "lightsensor",
-       .fops = &ap321xx_lsensor_fops
-};
-
-static int ap321xx_lsensor_open(struct inode *inode, struct file *file)
-{
-       LDBG("\n");
-       if (misc_ls_opened)
-               return -EBUSY;
-       misc_ls_opened = 1;
-       return 0;
-}
-
-static int ap321xx_lsensor_release(struct inode *inode, struct file *file)
-{
-       LDBG("\n");
-       misc_ls_opened = 0;
-       return 0;
-}
-
-static int ap321xx_lsensor_enable(struct i2c_client *client)
-{
-       int ret = 0,mode;
-       
-       mode = ap321xx_get_mode(client);
-       if((mode & 0x01) == 0){
-               mode |= 0x01;
-               ret = ap321xx_set_mode(client,mode);
-       }
-       
-       return ret;
-}
-
-static int ap321xx_lsensor_disable(struct i2c_client *client)
-{
-       int ret = 0,mode;
-       
-       mode = ap321xx_get_mode(client);
-       if(mode & 0x01){
-               mode &= ~0x01;
-               if(mode == 0x04)
-                       mode = 0;
-               ret = ap321xx_set_mode(client,mode);
-       }
-       
-       return ret;
-}
-
-static long ap321xx_lsensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       char val;
-       int ret;
-       struct i2c_client *client = container_of(ap321xx_lsensor_misc.parent, struct i2c_client, dev);
-
-       LDBG("%s cmd %d\n", __FUNCTION__, _IOC_NR(cmd));
-       
-       switch (cmd) {
-       case LIGHTSENSOR_IOCTL_ENABLE:
-               if (get_user(val, (unsigned long __user *)arg))
-                       return -EFAULT;
-               if (val){
-                       ret = ap321xx_lsensor_enable(client);
-                       if(!ret){
-                               msleep(200);
-                               ap321xx_change_ls_threshold(client);
-                       }
-                       return ret;
-               }
-               else
-                       return ap321xx_lsensor_disable(client);
-               break;
-       case LIGHTSENSOR_IOCTL_GET_ENABLED:
-               val = ap321xx_get_mode(client);
-               val &= 0x01;
-               return put_user(val, (unsigned long __user *)arg);
-               break;
-       default:
-               pr_err("%s: invalid cmd %d\n", __func__, _IOC_NR(cmd));
-               return -EINVAL;
-       }
-}
-
-static int ap321xx_register_lsensor_device(struct i2c_client *client, struct ap321xx_data *data)
-{
-       struct input_dev *input_dev;
-       int rc;
-
-       LDBG("allocating input device lsensor\n");
-       input_dev = input_allocate_device();
-       if (!input_dev) {
-               dev_err(&client->dev,"%s: could not allocate input device for lsensor\n", __FUNCTION__);
-               rc = -ENOMEM;
-               goto done;
-       }
-       data->lsensor_input_dev = input_dev;
-       input_set_drvdata(input_dev, data);
-       input_dev->name = "lightsensor-level";
-       input_dev->dev.parent = &client->dev;
-       set_bit(EV_ABS, input_dev->evbit);
-       input_set_abs_params(input_dev, ABS_MISC, 0, 8, 0, 0);
-
-       rc = input_register_device(input_dev);
-       if (rc < 0) {
-               pr_err("%s: could not register input device for lsensor\n", __FUNCTION__);
-               goto done;
-       }
-       rc = misc_register(&ap321xx_lsensor_misc);
-       if (rc < 0) {
-               pr_err("%s: could not register misc device lsensor\n", __FUNCTION__);
-               goto err_unregister_input_device;
-       }
-
-       ap321xx_lsensor_misc.parent = &client->dev;
-       return 0;
-
-err_unregister_input_device:
-       input_unregister_device(input_dev);
-done:
-       return rc;
-}
-
-static void ap321xx_unregister_lsensor_device(struct i2c_client *client, struct ap321xx_data *data)
-{
-       misc_deregister(&ap321xx_lsensor_misc);
-       input_unregister_device(data->lsensor_input_dev);
-}
-
-static void ap321xx_change_ls_threshold(struct i2c_client *client)
-{
-       struct ap321xx_data *data = i2c_get_clientdata(client);
-       int value;
-
-       value = ap321xx_get_adc_value(client);
-       LDBG("ALS lux index: %u\n", value);
-       if(value > 0){
-               ap321xx_set_althres(client,ap321xx_threshole[value-1]);
-               ap321xx_set_ahthres(client,ap321xx_threshole[value]);
-       }
-       else{
-               ap321xx_set_althres(client,0);
-               ap321xx_set_ahthres(client,ap321xx_threshole[value]);
-       }
-       
-       input_report_abs(data->lsensor_input_dev, ABS_MISC, value);
-       input_sync(data->lsensor_input_dev);
-       
-}
-
-
-static int misc_ps_opened = 0;
-static int ap321xx_psensor_open(struct inode *inode, struct file *file);
-static int ap321xx_psensor_release(struct inode *inode, struct file *file);
-static long ap321xx_psensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-
-static struct file_operations ap321xx_psensor_fops = {
-       .owner = THIS_MODULE,
-       .open = ap321xx_psensor_open,
-       .release = ap321xx_psensor_release,
-       .unlocked_ioctl = ap321xx_psensor_ioctl
-};
-
-static struct miscdevice ap321xx_psensor_misc = {
-       .minor = MISC_DYNAMIC_MINOR,
-       .name = "psensor",
-       .fops = &ap321xx_psensor_fops
-};
-
-static int ap321xx_psensor_open(struct inode *inode, struct file *file)
-{
-       LDBG("\n");
-       if (misc_ps_opened)
-               return -EBUSY;
-       misc_ps_opened = 1;
-       return 0;
-}
-
-static int ap321xx_psensor_release(struct inode *inode, struct file *file)
-{
-       LDBG("\n");
-       misc_ps_opened = 0;
-       return 0;
-}
-
-static int ap321xx_psensor_enable(struct i2c_client *client)
-{
-       int ret = 0,mode;
-       
-       mode = ap321xx_get_mode(client);
-       if((mode & 0x02) == 0){
-               mode |= 0x02;
-               ret = ap321xx_set_mode(client,mode);
-       }
-       
-       return ret;
-}
-
-static int ap321xx_psensor_disable(struct i2c_client *client)
-{
-       int ret = 0,mode;
-       
-       mode = ap321xx_get_mode(client);
-       if(mode & 0x02){
-               mode &= ~0x02;
-               if(mode == 0x04)
-                       mode = 0x00;
-               ret = ap321xx_set_mode(client,mode);
-       }
-       return ret;
-}
-
-
-static long ap321xx_psensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       char val;
-       struct i2c_client *client = container_of(ap321xx_psensor_misc.parent,struct i2c_client,dev);
-
-       LDBG("%s cmd %d\n", __func__, _IOC_NR(cmd));
-       
-       switch (cmd) {
-       case PSENSOR_IOCTL_ENABLE:
-               if (get_user(val, (unsigned long __user *)arg))
-                       return -EFAULT;
-               if (val)
-                       return ap321xx_psensor_enable(client);
-               else
-                       return ap321xx_psensor_disable(client);
-               break;
-       case PSENSOR_IOCTL_GET_ENABLED:
-               val = ap321xx_get_mode(client);
-               val = (val >> 1) & 0x01;
-               return put_user(val, (unsigned long __user *)arg);
-               break;
-       default:
-               pr_err("%s: invalid cmd %d\n", __func__, _IOC_NR(cmd));
-               return -EINVAL;
-       }
-}
-
-static int ap321xx_register_psensor_device(struct i2c_client *client, struct ap321xx_data *data)
-{
-       struct input_dev *input_dev;
-       int rc;
-
-       LDBG("allocating input device psensor\n");
-       input_dev = input_allocate_device();
-       if (!input_dev) {
-               dev_err(&client->dev,"%s: could not allocate input device for psensor\n", __FUNCTION__);
-               rc = -ENOMEM;
-               goto done;
-       }
-       data->psensor_input_dev = input_dev;
-       input_set_drvdata(input_dev, data);
-       input_dev->name = "proximity";
-       input_dev->dev.parent = &client->dev;
-       set_bit(EV_ABS, input_dev->evbit);
-       input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0);
-
-       rc = input_register_device(input_dev);
-       if (rc < 0) {
-               pr_err("%s: could not register input device for psensor\n", __FUNCTION__);
-               goto done;
-       }
-
-       rc = misc_register(&ap321xx_psensor_misc);
-       if (rc < 0) {
-               pr_err("%s: could not register misc device psensor\n", __FUNCTION__);
-               goto err_unregister_input_device;
-       }
-       ap321xx_psensor_misc.parent = &client->dev;
-       return 0;
-
-err_unregister_input_device:
-       input_unregister_device(input_dev);
-done:
-       return rc;
-}
-
-static void ap321xx_unregister_psensor_device(struct i2c_client *client, struct ap321xx_data *data)
-{
-       misc_deregister(&ap321xx_psensor_misc);
-       input_unregister_device(data->psensor_input_dev);
-}
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static struct early_suspend ap321xx_early_suspend;
-static void ap321xx_suspend(struct early_suspend *h)
-{
-       struct i2c_client *client = container_of(ap321xx_lsensor_misc.parent, struct i2c_client, dev);
-
-       if (misc_ps_opened)
-               ap321xx_psensor_disable(client);
-       if (misc_ls_opened)
-               ap321xx_lsensor_disable(client);
-}
-
-static void ap321xx_resume(struct early_suspend *h)
-{
-       struct i2c_client *client = container_of(ap321xx_lsensor_misc.parent, struct i2c_client, dev);
-
-       if (misc_ls_opened)
-               ap321xx_lsensor_enable(client);
-       if (misc_ps_opened)
-               ap321xx_psensor_enable(client);
-}
-#endif
-
-#endif
-
-/* range */
-static ssize_t ap321xx_show_range(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       return sprintf(buf, "%i\n", ap321xx_get_range(data->client));
-}
-
-static ssize_t ap321xx_store_range(struct device *dev,
-                                   struct device_attribute *attr,
-                                   const char *buf, size_t count)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       unsigned long val;
-       int ret;
-
-       if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3))
-               return -EINVAL;
-
-       ret = ap321xx_set_range(data->client, val);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(range, S_IWUSR | S_IRUGO,
-                  ap321xx_show_range, ap321xx_store_range);
-
-
-/* mode */
-static ssize_t ap321xx_show_mode(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       return sprintf(buf, "%d\n", ap321xx_get_mode(data->client));
-}
-
-static ssize_t ap321xx_store_mode(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       unsigned long val;
-       int ret;
-
-       if ((strict_strtoul(buf, 10, &val) < 0) || (val > 7))
-               return -EINVAL;
-
-       ret = ap321xx_set_mode(data->client, val);
-       
-       if (ret < 0)
-               return ret;
-       return count;
-}
-
-static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO,
-                  ap321xx_show_mode, ap321xx_store_mode);
-
-
-/* lux */
-static ssize_t ap321xx_show_lux(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-
-       /* No LUX data if power down */
-       if (ap321xx_get_mode(data->client) == 0x00)
-               return sprintf((char*) buf, "%s\n", "Please power up first!");
-
-       return sprintf(buf, "%d\n", ap321xx_get_adc_value(data->client));
-}
-
-static DEVICE_ATTR(lux, S_IRUGO, ap321xx_show_lux, NULL);
-
-
-/* Px data */
-static ssize_t ap321xx_show_pxvalue(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-
-       /* No Px data if power down */
-       if (ap321xx_get_mode(data->client) == 0x00)
-               return -EBUSY;
-
-       return sprintf(buf, "%d\n", ap321xx_get_px_value(data->client));
-}
-
-static DEVICE_ATTR(pxvalue, S_IRUGO, ap321xx_show_pxvalue, NULL);
-
-
-/* proximity object detect */
-static ssize_t ap321xx_show_object(struct device *dev,
-                                        struct device_attribute *attr,
-                                        char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       return sprintf(buf, "%d\n", ap321xx_get_object(data->client));
-}
-
-static DEVICE_ATTR(object, S_IRUGO, ap321xx_show_object, NULL);
-
-
-/* ALS low threshold */
-static ssize_t ap321xx_show_althres(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       return sprintf(buf, "%d\n", ap321xx_get_althres(data->client));
-}
-
-static ssize_t ap321xx_store_althres(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       unsigned long val;
-       int ret;
-
-       if (strict_strtoul(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       ret = ap321xx_set_althres(data->client, val);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(althres, S_IWUSR | S_IRUGO,
-                  ap321xx_show_althres, ap321xx_store_althres);
-
-
-/* ALS high threshold */
-static ssize_t ap321xx_show_ahthres(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       return sprintf(buf, "%d\n", ap321xx_get_ahthres(data->client));
-}
-
-static ssize_t ap321xx_store_ahthres(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       unsigned long val;
-       int ret;
-
-       if (strict_strtoul(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       ret = ap321xx_set_ahthres(data->client, val);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(ahthres, S_IWUSR | S_IRUGO,
-                  ap321xx_show_ahthres, ap321xx_store_ahthres);
-
-/* Px low threshold */
-static ssize_t ap321xx_show_plthres(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       return sprintf(buf, "%d\n", ap321xx_get_plthres(data->client));
-}
-
-static ssize_t ap321xx_store_plthres(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       unsigned long val;
-       int ret;
-
-       if (strict_strtoul(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       ret = ap321xx_set_plthres(data->client, val);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(plthres, S_IWUSR | S_IRUGO,
-                  ap321xx_show_plthres, ap321xx_store_plthres);
-
-/* Px high threshold */
-static ssize_t ap321xx_show_phthres(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       return sprintf(buf, "%d\n", ap321xx_get_phthres(data->client));
-}
-
-static ssize_t ap321xx_store_phthres(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       unsigned long val;
-       int ret;
-
-       if (strict_strtoul(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       ret = ap321xx_set_phthres(data->client, val);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(phthres, S_IWUSR | S_IRUGO,
-                  ap321xx_show_phthres, ap321xx_store_phthres);
-
-
-/* calibration */
-static ssize_t ap321xx_show_calibration_state(struct device *dev,
-                                        struct device_attribute *attr,
-                                        char *buf)
-{
-       return sprintf(buf, "%d\n", cali);
-}
-
-static ssize_t ap321xx_store_calibration_state(struct device *dev,
-                                         struct device_attribute *attr,
-                                         const char *buf, size_t count)
-{
-       struct input_dev *input = to_input_dev(dev);
-       struct ap321xx_data *data = input_get_drvdata(input);
-       int stdls, lux; 
-       char tmp[10];
-
-       /* No LUX data if not operational */
-       if (ap321xx_get_mode(data->client) == 0x00)
-       {
-               printk("Please power up first!");
-               return -EINVAL;
-       }
-
-       cali = 100;
-       sscanf(buf, "%d %s", &stdls, tmp);
-
-       if (!strncmp(tmp, "-setcv", 6))
-       {
-               cali = stdls;
-               return -EBUSY;
-       }
-
-       if (stdls < 0)
-       {
-               printk("Std light source: [%d] < 0 !!!\nCheck again, please.\n\
-               Set calibration factor to 100.\n", stdls);
-               return -EBUSY;
-       }
-
-       lux = ap321xx_get_adc_value(data->client);
-       cali = stdls * 100 / lux;
-
-       return -EBUSY;
-}
-
-static DEVICE_ATTR(calibration, S_IWUSR | S_IRUGO,
-                  ap321xx_show_calibration_state, ap321xx_store_calibration_state);
-
-#ifdef LSC_DBG
-/* engineer mode */
-static ssize_t ap321xx_em_read(struct device *dev,
-                                        struct device_attribute *attr,
-                                        char *buf)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct ap321xx_data *data = i2c_get_clientdata(client);
-       int i;
-       u8 tmp;
-       
-       for (i = 0; i < reg_num; i++)
-       {
-               tmp = i2c_smbus_read_byte_data(data->client, reg_array[i]);
-
-               printk("Reg[0x%x] Val[0x%x]\n", reg_array[i], tmp);
-       }
-
-       return 0;
-}
-
-static ssize_t ap321xx_em_write(struct device *dev,
-                                         struct device_attribute *attr,
-                                         const char *buf, size_t count)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct ap321xx_data *data = i2c_get_clientdata(client);
-       u32 addr,val,idx=0;
-       int ret = 0;
-
-       sscanf(buf, "%x%x", &addr, &val);
-
-       printk("Write [%x] to Reg[%x]...\n",val,addr);
-
-       ret = i2c_smbus_write_byte_data(data->client, addr, val);
-       ADD_TO_IDX(addr,idx)
-       if (!ret)
-               data->reg_cache[idx] = val;
-
-       return count;
-}
-static DEVICE_ATTR(em, S_IWUSR |S_IRUGO,
-                                  ap321xx_em_read, ap321xx_em_write);
-#endif
-
-static struct attribute *ap321xx_attributes[] = {
-       &dev_attr_range.attr,
-       &dev_attr_mode.attr,
-       &dev_attr_lux.attr,
-       &dev_attr_object.attr,
-       &dev_attr_pxvalue.attr,
-       &dev_attr_althres.attr,
-       &dev_attr_ahthres.attr,
-       &dev_attr_plthres.attr,
-       &dev_attr_phthres.attr,
-       &dev_attr_calibration.attr,
-#ifdef LSC_DBG
-       &dev_attr_em.attr,
-#endif
-       NULL
-};
-
-static const struct attribute_group ap321xx_attr_group = {
-       .attrs = ap321xx_attributes,
-};
-
-static int Product_Detect(struct i2c_client *client)
-{
-       int mid = i2c_smbus_read_byte_data(client, 0x03);
-       int pid = i2c_smbus_read_byte_data(client, 0x04);
-       int rid = i2c_smbus_read_byte_data(client, 0x05);
-
-       if ( mid == 0x01 && pid == 0x01 && 
-           (rid == 0x03 || rid == 0x04) )
-       {
-               LDBG("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid)
-               reg_array = ap3212b_reg;
-               range = ap3212b_range;
-               reg_num = AP3212B_NUM_CACHABLE_REGS;
-       }
-       else if ( (mid == 0x01 && pid == 0x02 && rid == 0x00) || 
-                     (mid == 0x02 && pid == 0x02 && rid == 0x01))
-       {
-               LDBG("RevID [%d], ==> DA3212 v2.0 ...... AP3212C/AP3216C detected\n", rid)
-               reg_array = ap3216c_reg;
-               range = ap3216c_range;
-               reg_num = AP3216C_NUM_CACHABLE_REGS;
-       }
-       else
-       {
-               LDBG("MakeID[%d] ProductID[%d] RevID[%d] .... can't detect ... bad reversion!!!\n", mid, pid, rid)
-               return -EIO;
-       }
-               
-
-       return 0;
-}
-
-static int ap321xx_init_client(struct i2c_client *client)
-{
-       struct ap321xx_data *data = i2c_get_clientdata(client);
-       int i;
-
-       /* read all the registers once to fill the cache.
-        * if one of the reads fails, we consider the init failed */
-       for (i = 0; i < reg_num; i++) {
-               int v = i2c_smbus_read_byte_data(client, reg_array[i]);
-               if (v < 0)
-                       return -ENODEV;
-
-               data->reg_cache[i] = v;
-       }
-
-       /* set defaults */
-       ap321xx_set_range(client, 0);
-       ap321xx_set_mode(client, 0);
-
-       return 0;
-}
-
-/*
- * I2C layer
- */
-
-static irqreturn_t ap321xx_irq(int irq, void *data_)
-{
-       struct ap321xx_data *data = data_;
-       u8 int_stat;
-       int Pval;
-       int_stat = ap321xx_get_intstat(data->client);
-
-       // ALS int
-       if (int_stat & AP3212B_INT_AMASK)
-       {
-               ap321xx_change_ls_threshold(data->client);
-       }
-       
-       // PX int
-       if (int_stat & AP3212B_INT_PMASK)
-       {
-               Pval = ap321xx_get_object(data->client);
-               LDBG("%s\n", Pval ? "obj near":"obj far");
-               input_report_abs(data->psensor_input_dev, ABS_DISTANCE, Pval);
-               input_sync(data->psensor_input_dev);
-       }
-
-    return IRQ_HANDLED;
-}
-
-static int __devinit ap321xx_probe(struct i2c_client *client,
-                                   const struct i2c_device_id *id)
-{
-       const struct ap321xx_platform_data *pdata = client->dev.platform_data;
-       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct ap321xx_data *data;
-       int err = 0;
-
-       LDBG("ap321xx_probe\n");
-       
-       if (pdata->init_platform_hw) {
-               err = pdata->init_platform_hw();
-               if (err < 0)
-                       goto exit_free_gpio;
-       }
-
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)){
-               err = -EIO;
-               goto exit_free_gpio;
-       }
-       err = Product_Detect(client);
-       if (err)
-       {
-               dev_err(&client->dev, "ret: %d, product version detect failed.\n",err);
-               err = -EIO;
-               goto exit_free_gpio;
-       }
-
-       data = kzalloc(sizeof(struct ap321xx_data), GFP_KERNEL);
-       if (!data){
-               err = -ENOMEM;
-               goto exit_free_gpio;
-       }
-       
-       data->client = client;
-       i2c_set_clientdata(client, data);
-       data->irq = client->irq;
-
-       /* initialize the AP3212B chip */
-       err = ap321xx_init_client(client);
-       if (err)
-               goto exit_kfree;
-
-       err = ap321xx_register_lsensor_device(client,data);
-       if (err){
-               dev_err(&client->dev, "failed to register_lsensor_device\n");
-               goto exit_kfree;
-       }
-               
-       err = ap321xx_register_psensor_device(client, data);
-       if (err) {
-               dev_err(&client->dev, "failed to register_psensor_device\n");
-               goto exit_free_ls_device;
-       }
-
-#if 0
-       /* register sysfs hooks */
-       err = sysfs_create_group(&data->input->dev.kobj, &ap321xx_attr_group);
-       if (err)
-               goto exit_free_ps_device;
-#endif
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-       ap321xx_early_suspend.suspend = ap321xx_suspend;
-       ap321xx_early_suspend.resume  = ap321xx_resume;
-       ap321xx_early_suspend.level   = 0x02;
-       register_early_suspend(&ap321xx_early_suspend);
-#endif
-
-
-       err = request_threaded_irq(client->irq, NULL, ap321xx_irq,
-                               IRQF_TRIGGER_FALLING,
-                               "ap321xx", data);
-    if (err) {
-               dev_err(&client->dev, "ret: %d, could not get IRQ %d\n",err,client->irq);
-            goto exit_free_ps_device;
-    }
-
-       dev_info(&client->dev, "Driver version %s enabled\n", DRIVER_VERSION);
-       return 0;
-
-exit_free_ps_device:
-       ap321xx_unregister_psensor_device(client,data);
-
-exit_free_ls_device:
-       ap321xx_unregister_lsensor_device(client,data);
-
-exit_kfree:
-       kfree(data);
-exit_free_gpio:
-       if (pdata->exit_platform_hw) {
-               pdata->exit_platform_hw();
-       }
-       return err;
-}
-
-static int __devexit ap321xx_remove(struct i2c_client *client)
-{
-       const struct ap321xx_platform_data *pdata = client->dev.platform_data;
-       struct ap321xx_data *data = i2c_get_clientdata(client);
-       free_irq(data->irq, data);
-
-//     sysfs_remove_group(&data->input->dev.kobj, &ap321xx_attr_group);
-       ap321xx_unregister_psensor_device(client,data);
-       ap321xx_unregister_lsensor_device(client,data);
-#ifdef CONFIG_HAS_EARLYSUSPEND
-    unregister_early_suspend(&ap321xx_early_suspend);
-#endif
-
-       ap321xx_set_mode(client, 0);
-       kfree(i2c_get_clientdata(client));
-       if (pdata->exit_platform_hw) {
-               pdata->exit_platform_hw();
-       }
-       return 0;
-}
-
-static const struct i2c_device_id ap321xx_id[] = {
-       { AP3212B_DRV_NAME, 0 },
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, ap321xx_id);
-
-static struct i2c_driver ap321xx_driver = {
-       .driver = {
-               .name   = AP3212B_DRV_NAME,
-               .owner  = THIS_MODULE,
-       },
-       .probe  = ap321xx_probe,
-       .remove = __devexit_p(ap321xx_remove),
-       .id_table = ap321xx_id,
-};
-
-static int __init ap321xx_init(void)
-{
-       LDBG("ap321xx_init\n");
-       return i2c_add_driver(&ap321xx_driver);
-}
-
-static void __exit ap321xx_exit(void)
-{
-       i2c_del_driver(&ap321xx_driver);
-}
-
-MODULE_AUTHOR("YC Hou, LiteOn-semi corporation.");
-MODULE_DESCRIPTION("Test AP3212B, AP3212C and AP3216C driver on mini6410.");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRIVER_VERSION);
-
-module_init(ap321xx_init);
-module_exit(ap321xx_exit);
-
-
index 18bde7618f5d86bd80c0c3dbbacf0a170e6f8e3c..4c3aec1327c4251ae85222ff2a00b706ba9627eb 100755 (executable)
@@ -22,5 +22,9 @@ config LS_STK3171
 config LS_ISL29023
   bool "light sensor isl29023"
        default n         
+       
+config LS_AP321XX
+  bool "light sensor ap321xx"
+       default n         
 endif
 
index 5127b4396f42a52c4e2e0c6b87bae93e86748be5..1834c514b54ee41dd22a9833b0c5696967b62f27 100755 (executable)
@@ -3,4 +3,5 @@
 obj-$(CONFIG_LS_CM3217)                += cm3217.o
 obj-$(CONFIG_LS_AL3006)                += ls_al3006.o
 obj-$(CONFIG_LS_STK3171)               += ls_stk3171.o
-obj-$(CONFIG_LS_ISL29023)              += isl29023.o
\ No newline at end of file
+obj-$(CONFIG_LS_ISL29023)              += isl29023.o
+obj-$(CONFIG_LS_AP321XX)               += ls_ap321xx.o
diff --git a/drivers/input/sensors/lsensor/ls_ap321xx.c b/drivers/input/sensors/lsensor/ls_ap321xx.c
new file mode 100644 (file)
index 0000000..1fb01b6
--- /dev/null
@@ -0,0 +1,416 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define AP3212B_NUM_CACHABLE_REGS      23
+#define AP3216C_NUM_CACHABLE_REGS      26\r
+\r
+#define AP3212B_RAN_COMMAND    0x10
+#define AP3212B_RAN_MASK               0x30
+#define AP3212B_RAN_SHIFT      (4)
+
+#define AP3212B_MODE_COMMAND   0x00
+#define AP3212B_MODE_SHIFT     (0)
+#define AP3212B_MODE_MASK      0x07\r
+\r
+#define AP3212B_INT_COMMAND    0x01
+#define AP3212B_INT_SHIFT      (0)
+#define AP3212B_INT_MASK               0x03
+#define AP3212B_INT_PMASK              0x02
+#define AP3212B_INT_AMASK              0x01
+\r
+#define        AL3212_ADC_LSB          0x0c
+#define        AL3212_ADC_MSB          0x0d
+\r
+#define AP3212B_ALS_LTHL                       0x1a
+#define AP3212B_ALS_LTHL_SHIFT (0)
+#define AP3212B_ALS_LTHL_MASK  0xff
+
+#define AP3212B_ALS_LTHH                       0x1b
+#define AP3212B_ALS_LTHH_SHIFT (0)
+#define AP3212B_ALS_LTHH_MASK  0xff
+
+#define AP3212B_ALS_HTHL                       0x1c
+#define AP3212B_ALS_HTHL_SHIFT (0)
+#define AP3212B_ALS_HTHL_MASK  0xff
+
+#define AP3212B_ALS_HTHH                       0x1d
+#define AP3212B_ALS_HTHH_SHIFT (0)
+#define AP3212B_ALS_HTHH_MASK  0xff
+\r
+static u16 ap321xx_threshole[8] = {28,444,625,888,1778,3555,7222,0xffff};\r
+\r
+/*
+ * register access helpers
+ */
+
+static int __ap321xx_read_reg(struct i2c_client *client,
+                              u32 reg, u8 mask, u8 shift)
+{
+       u8 val;\r
+\r
+       val = i2c_smbus_read_byte_data(client, reg);\r
+       return (val & mask) >> shift;\r
+}
+
+static int __ap321xx_write_reg(struct i2c_client *client,
+                               u32 reg, u8 mask, u8 shift, u8 val)
+{
+       int ret = 0;\r
+       u8 tmp;
+\r
+       tmp = i2c_smbus_read_byte_data(client, reg);\r
+       tmp &= ~mask;
+       tmp |= val << shift;
+
+       ret = i2c_smbus_write_byte_data(client, reg, tmp);\r
+       \r
+       return ret;\r
+}
+\r
+\r
+/*
+ * internally used functions
+ */\r
+/* range */
+static int ap321xx_set_range(struct i2c_client *client, int range)\r
+{
+       return __ap321xx_write_reg(client, AP3212B_RAN_COMMAND,
+               AP3212B_RAN_MASK, AP3212B_RAN_SHIFT, range);;
+}
+
+
+/* mode */
+static int ap321xx_get_mode(struct i2c_client *client)
+{
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int ret;
+
+       ret = __ap321xx_read_reg(client, sensor->ops->ctrl_reg,\r
+                       AP3212B_MODE_MASK, AP3212B_MODE_SHIFT);
+       return ret;
+}
+static int ap321xx_set_mode(struct i2c_client *client, int mode)\r
+{
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int ret;\r
+
+       ret = __ap321xx_write_reg(client, sensor->ops->ctrl_reg,\r
+                               AP3212B_MODE_MASK, AP3212B_MODE_SHIFT, mode);
+       return ret;
+}\r
+\r
+static int ap321xx_get_adc_value(struct i2c_client *client)
+{
+       unsigned int lsb, msb, val;
+       unsigned char index=0;\r
+
+       lsb = i2c_smbus_read_byte_data(client, AL3212_ADC_LSB);\r
+       if (lsb < 0) {
+               return lsb;
+       }
+
+       msb = i2c_smbus_read_byte_data(client, AL3212_ADC_MSB);\r
+       if (msb < 0)
+               return msb;
+
+       val = msb << 8 | lsb;\r
+       for(index = 0; index < 7 && val > ap321xx_threshole[index];index++)
+               ;
+
+       return index;
+}\r
+\r
+/* ALS low threshold */\r
+static int ap321xx_set_althres(struct i2c_client *client, int val)
+{
+       int lsb, msb, err;
+       
+       msb = val >> 8;
+       lsb = val & AP3212B_ALS_LTHL_MASK;
+
+       err = __ap321xx_write_reg(client, AP3212B_ALS_LTHL,
+               AP3212B_ALS_LTHL_MASK, AP3212B_ALS_LTHL_SHIFT, lsb);
+       if (err)
+               return err;
+
+       err = __ap321xx_write_reg(client, AP3212B_ALS_LTHH,
+               AP3212B_ALS_LTHH_MASK, AP3212B_ALS_LTHH_SHIFT, msb);
+
+       return err;
+}
+
+/* ALS high threshold */\r
+static int ap321xx_set_ahthres(struct i2c_client *client, int val)
+{
+       int lsb, msb, err;
+       
+       msb = val >> 8;
+       lsb = val & AP3212B_ALS_HTHL_MASK;
+       
+       err = __ap321xx_write_reg(client, AP3212B_ALS_HTHL,
+               AP3212B_ALS_HTHL_MASK, AP3212B_ALS_HTHL_SHIFT, lsb);
+       if (err)
+               return err;
+
+       err = __ap321xx_write_reg(client, AP3212B_ALS_HTHH,
+               AP3212B_ALS_HTHH_MASK, AP3212B_ALS_HTHH_SHIFT, msb);
+
+       return err;
+}\r
+\r
+static int ap321xx_get_intstat(struct i2c_client *client)
+{
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int val;
+       
+       val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg);\r
+       val &= AP3212B_INT_MASK;
+
+       return val >> AP3212B_INT_SHIFT;
+}\r
+\r
+static int ap321xx_product_detect(struct i2c_client *client)\r
+{
+       int mid = i2c_smbus_read_byte_data(client, 0x03);
+       int pid = i2c_smbus_read_byte_data(client, 0x04);
+       int rid = i2c_smbus_read_byte_data(client, 0x05);
+
+       if ( mid == 0x01 && pid == 0x01 && 
+           (rid == 0x03 || rid == 0x04) )
+       {
+               DBG("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid);\r
+       }\r
+       else if ( (mid == 0x01 && pid == 0x02 && rid == 0x00) || 
+                     (mid == 0x02 && pid == 0x02 && rid == 0x01))
+       {
+               DBG("RevID [%d], ==> DA3212 v2.0 ...... AP3212C/AP3216C detected\n", rid);\r
+       }\r
+       else
+       {
+               DBG("MakeID[%d] ProductID[%d] RevID[%d] .... can't detect ... bad reversion!!!\n", mid, pid, rid);\r
+               return -EIO;
+       }
+\r
+       return 0;
+}\r
+\r
+static int ap321xx_init_client(struct i2c_client *client)
+{
+       /* set defaults */\r
+       ap321xx_set_range(client, 0);
+       ap321xx_set_mode(client, 0);
+
+       return 0;
+}\r
+\r
+static int ap321xx_lsensor_enable(struct i2c_client *client)
+{
+       int ret = 0,mode;
+       
+       mode = ap321xx_get_mode(client);
+       if((mode & 0x01) == 0){
+               mode |= 0x01;
+               ret = ap321xx_set_mode(client,mode);
+       }
+       
+       return ret;
+}
+
+static int ap321xx_lsensor_disable(struct i2c_client *client)
+{
+       int ret = 0,mode;
+       
+       mode = ap321xx_get_mode(client);
+       if(mode & 0x01){
+               mode &= ~0x01;
+               if(mode == 0x04)
+                       mode = 0;
+               ret = ap321xx_set_mode(client,mode);
+       }
+       
+       return ret;
+}\r
+\r
+static void ap321xx_change_ls_threshold(struct i2c_client *client)
+{
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int value;
+
+       value = ap321xx_get_adc_value(client);
+       DBG("ALS lux index: %u\n", value);\r
+       if(value > 0){
+               ap321xx_set_althres(client,ap321xx_threshole[value-1]);
+               ap321xx_set_ahthres(client,ap321xx_threshole[value]);
+       }
+       else{
+               ap321xx_set_althres(client,0);
+               ap321xx_set_ahthres(client,ap321xx_threshole[value]);
+       }
+       
+       input_report_abs(sensor->input_dev, ABS_MISC, value);\r
+       input_sync(sensor->input_dev);\r
+}\r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       int result = 0;\r
+       \r
+       //register setting according to chip datasheet          \r
+       if (enable){\r
+               result = ap321xx_lsensor_enable(client);\r
+               if(!result){\r
+                       msleep(200);\r
+                       ap321xx_change_ls_threshold(client);\r
+               }\r
+       }\r
+       else\r
+               result = ap321xx_lsensor_disable(client);\r
+\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+\r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+\r
+       result = ap321xx_product_detect(client);\r
+       if (result)\r
+       {
+               dev_err(&client->dev, "ret: %d, product version detect failed.\n",result);\r
+               return result;\r
+       }\r
+\r
+       /* initialize the AP3212B chip */
+       result = ap321xx_init_client(client);\r
+       if (result)\r
+               return result;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+               \r
+       return result;\r
+}\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       int result = 0;\r
+       u8 int_stat;\r
+       \r
+       int_stat = ap321xx_get_intstat(client);\r
+       // ALS int
+       if (int_stat & AP3212B_INT_AMASK)\r
+       {
+               ap321xx_change_ls_threshold(client);\r
+       }
+       \r
+       return result;\r
+}\r
+\r
+struct sensor_operate light_ap321xx_ops = {\r
+       .name                           = "ls_ap321xx",\r
+       .type                           = SENSOR_TYPE_LIGHT,    //sensor type and it should be correct\r
+       .id_i2c                         = LIGHT_ID_AP321XX,     //i2c id number\r
+       .read_reg                       = SENSOR_UNKNOW_DATA,   //read data             //there are two regs, we fix them in code.\r
+       .read_len                       = 1,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register   //there are 3 regs, we fix them in code.\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 16,                   //8 bits\r
+       .ctrl_reg                       = AP3212B_MODE_COMMAND,         //enable or disable \r
+       .int_status_reg                 = AP3212B_INT_COMMAND,  //intterupt status register\r
+       .range                          = {100,65535},          //range\r
+       .brightness                                        ={10,255},                          // brightness\r
+       .trig                           = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED,            \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+static struct sensor_operate *light_get_ops(void)\r
+{\r
+       return &light_ap321xx_ops;\r
+}\r
+\r
+\r
+static int __init light_ap321xx_init(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, light_get_ops);\r
+       DBG("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit light_ap321xx_exit(void)\r
+{\r
+       struct sensor_operate *ops = light_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, light_get_ops);\r
+}\r
+\r
+\r
+module_init(light_ap321xx_init);\r
+module_exit(light_ap321xx_exit);\r
+\r
+\r
index 289280da6020e6690839f02745a15229dda2d559..ce3a55adfeffc2a040244c38881dbccfec6911cc 100755 (executable)
@@ -16,5 +16,9 @@ config PS_STK3171
   bool "psensor stk3171"
        default n
 
+config PS_AP321XX
+  bool "psensor ap321xx"
+       default n
+
 endif
 
index 1da405f6f88ea3d4bf77ec9d073db92f6cd507cc..270d1aaad4f2ca31d85d659920d29a96f623bb7a 100755 (executable)
@@ -1,4 +1,6 @@
 # gsensor drivers
 
 obj-$(CONFIG_PS_AL3006)                += ps_al3006.o
-obj-$(CONFIG_PS_STK3171)               += ps_stk3171.o
\ No newline at end of file
+obj-$(CONFIG_PS_STK3171)               += ps_stk3171.o
+obj-$(CONFIG_PS_AP321XX)               += ps_ap321xx.o
+
diff --git a/drivers/input/sensors/psensor/ps_ap321xx.c b/drivers/input/sensors/psensor/ps_ap321xx.c
new file mode 100644 (file)
index 0000000..d047985
--- /dev/null
@@ -0,0 +1,329 @@
+/* drivers/input/sensors/access/kxtik.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_PROXIMITY\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define AP3212B_NUM_CACHABLE_REGS      23
+#define AP3216C_NUM_CACHABLE_REGS      26\r
+\r
+#define AP3212B_RAN_COMMAND    0x10
+#define AP3212B_RAN_MASK               0x30
+#define AP3212B_RAN_SHIFT      (4)
+
+#define AP3212B_MODE_COMMAND   0x00
+#define AP3212B_MODE_SHIFT     (0)
+#define AP3212B_MODE_MASK      0x07\r
+\r
+#define AP3212B_INT_COMMAND    0x01
+#define AP3212B_INT_SHIFT      (0)
+#define AP3212B_INT_MASK               0x03
+#define AP3212B_INT_PMASK              0x02
+#define AP3212B_INT_AMASK              0x01
+\r
+#define AP3212B_OBJ_COMMAND    0x0f
+#define AP3212B_OBJ_MASK               0x80
+#define AP3212B_OBJ_SHIFT      (7)\r
+\r
+\r
+/*
+ * register access helpers
+ */
+
+static int __ap321xx_read_reg(struct i2c_client *client,
+                              u32 reg, u8 mask, u8 shift)
+{
+       u8 val;\r
+
+       val = i2c_smbus_read_byte_data(client, reg);
+       return (val & mask) >> shift;\r
+}
+
+static int __ap321xx_write_reg(struct i2c_client *client,
+                               u32 reg, u8 mask, u8 shift, u8 val)
+{
+       int ret = 0;\r
+       u8 tmp;
+
+       tmp = i2c_smbus_read_byte_data(client, reg);
+       tmp &= ~mask;
+       tmp |= val << shift;
+
+       ret = i2c_smbus_write_byte_data(client, reg, tmp);
+       
+       return ret;
+}
+\r
+\r
+/*
+ * internally used functions
+ */\r
+/* range */
+static int ap321xx_set_range(struct i2c_client *client, int range)\r
+{
+       return __ap321xx_write_reg(client, AP3212B_RAN_COMMAND,
+               AP3212B_RAN_MASK, AP3212B_RAN_SHIFT, range);;
+}
+
+
+/* mode */
+static int ap321xx_get_mode(struct i2c_client *client)
+{
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int ret;
+
+       ret = __ap321xx_read_reg(client, sensor->ops->ctrl_reg,
+                       AP3212B_MODE_MASK, AP3212B_MODE_SHIFT);
+       return ret;
+}
+static int ap321xx_set_mode(struct i2c_client *client, int mode)\r
+{
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int ret;
+
+       ret = __ap321xx_write_reg(client, sensor->ops->ctrl_reg,
+                               AP3212B_MODE_MASK, AP3212B_MODE_SHIFT, mode);
+       return ret;
+}\r
+static int ap321xx_get_intstat(struct i2c_client *client)
+{
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int val;\r
+       \r
+       val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg);\r
+       val &= AP3212B_INT_MASK;\r
+\r
+       return val >> AP3212B_INT_SHIFT;\r
+}\r
+\r
+static int ap321xx_get_object(struct i2c_client *client)
+{
+       int val;
+
+       val = i2c_smbus_read_byte_data(client, AP3212B_OBJ_COMMAND);
+       val &= AP3212B_OBJ_MASK;
+
+       return val >> AP3212B_OBJ_SHIFT;
+}
+\r
+\r
+static int ap321xx_product_detect(struct i2c_client *client)\r
+{
+       int mid = i2c_smbus_read_byte_data(client, 0x03);
+       int pid = i2c_smbus_read_byte_data(client, 0x04);
+       int rid = i2c_smbus_read_byte_data(client, 0x05);
+
+       if ( mid == 0x01 && pid == 0x01 && 
+           (rid == 0x03 || rid == 0x04) )
+       {
+               DBG("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid);\r
+       }
+       else if ( (mid == 0x01 && pid == 0x02 && rid == 0x00) || 
+                     (mid == 0x02 && pid == 0x02 && rid == 0x01))
+       {
+               DBG("RevID [%d], ==> DA3212 v2.0 ...... AP3212C/AP3216C detected\n", rid);\r
+       }
+       else
+       {
+               DBG("MakeID[%d] ProductID[%d] RevID[%d] .... can't detect ... bad reversion!!!\n", mid, pid, rid);\r
+               return -EIO;
+       }
+\r
+       return 0;
+}\r
+\r
+static int ap321xx_init_client(struct i2c_client *client)
+{
+       /* set defaults */
+       ap321xx_set_range(client, 0);
+       ap321xx_set_mode(client, 0);
+
+       return 0;
+}\r
+\r
+static int ap321xx_psensor_enable(struct i2c_client *client)
+{
+       int ret = 0,mode;
+       
+       mode = ap321xx_get_mode(client);
+       if((mode & 0x02) == 0){
+               mode |= 0x02;
+               ret = ap321xx_set_mode(client,mode);
+       }
+       
+       return ret;
+}
+
+static int ap321xx_psensor_disable(struct i2c_client *client)
+{
+       int ret = 0,mode;
+       
+       mode = ap321xx_get_mode(client);
+       if(mode & 0x02){
+               mode &= ~0x02;
+               if(mode == 0x04)
+                       mode = 0x00;
+               ret = ap321xx_set_mode(client,mode);
+       }
+       return ret;
+}\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       int result = 0;\r
+       \r
+       //register setting according to chip datasheet          \r
+       if (enable){\r
+               result = ap321xx_psensor_enable(client);\r
+       }\r
+       else\r
+               result = ap321xx_psensor_disable(client);\r
+\r
+       if(result)\r
+               printk("%s:fail to active sensor\n",__func__);\r
+\r
+       return result;\r
+\r
+}\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+\r
+       result = ap321xx_product_detect(client);\r
+       if (result)\r
+       {
+               dev_err(&client->dev, "ret: %d, product version detect failed.\n",result);\r
+               return result;\r
+       }\r
+\r
+       /* initialize the AP3212B chip */
+       result = ap321xx_init_client(client);\r
+       if (result)\r
+               return result;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+               \r
+       return result;\r
+}\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       char value = 0;\r
+       u8 int_stat;\r
+       \r
+       int_stat = ap321xx_get_intstat(client);\r
+       // ALS int
+       if (int_stat & AP3212B_INT_PMASK)\r
+       {
+               value = ap321xx_get_object(client);\r
+               input_report_abs(sensor->input_dev, ABS_DISTANCE, value);\r
+               input_sync(sensor->input_dev);\r
+       }
+       \r
+       return result;\r
+}\r
+\r
+struct sensor_operate proximity_ap321xx_ops = {\r
+       .name                           = "ps_ap321xx",\r
+       .type                           = SENSOR_TYPE_PROXIMITY,        //sensor type and it should be correct\r
+       .id_i2c                         = PROXIMITY_ID_AP321XX, //i2c id number\r
+       .read_reg                       = SENSOR_UNKNOW_DATA,   //read data             //there are two regs, we fix them in code.\r
+       .read_len                       = 1,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register   //there are 3 regs, we fix them in code.\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 8,                    //8 bits\r
+       .ctrl_reg                       = AP3212B_MODE_COMMAND,         //enable or disable \r
+       .int_status_reg                 = AP3212B_INT_COMMAND,  //intterupt status register\r
+       .range                          = {0,10},               //range\r
+       .brightness                                        ={10,255},                          // brightness\r
+       .trig                           = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED,            \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+static struct sensor_operate *proximity_get_ops(void)\r
+{\r
+       return &proximity_ap321xx_ops;\r
+}\r
+\r
+\r
+static int __init proximity_ap321xx_init(void)\r
+{\r
+       struct sensor_operate *ops = proximity_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, proximity_get_ops);\r
+       DBG("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit proximity_ap321xx_exit(void)\r
+{\r
+       struct sensor_operate *ops = proximity_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, proximity_get_ops);\r
+}\r
+\r
+\r
+module_init(proximity_ap321xx_init);\r
+module_exit(proximity_ap321xx_exit);\r
+\r
+\r
index d43432301627df20e9db184c4aeed8c6af778951..5ae58ff2d64db490a935310fe28d94f0533f4897 100755 (executable)
@@ -302,7 +302,7 @@ static int sensor_irq_init(struct i2c_client *client)
                client->irq = irq;\r
                if((sensor->pdata->type == SENSOR_TYPE_GYROSCOPE) || (sensor->pdata->type == SENSOR_TYPE_ACCEL))\r
                disable_irq_nosync(client->irq);//disable irq\r
-               if(((sensor->pdata->type == SENSOR_TYPE_LIGHT) || ((sensor->pdata->type == SENSOR_TYPE_PROXIMITY))) && (!(sensor->ops->trig & IRQF_SHARED)))    \r
+               if(((sensor->pdata->type == SENSOR_TYPE_LIGHT) || (sensor->pdata->type == SENSOR_TYPE_PROXIMITY))&& (!(sensor->ops->trig & IRQF_SHARED)))       \r
                disable_irq_nosync(client->irq);//disable irq\r
                printk("%s:use irq=%d\n",__func__,irq);\r
        }\r
@@ -1414,10 +1414,12 @@ static const struct i2c_device_id sensor_id[] = {
        {"light_al3006", LIGHT_ID_AL3006},\r
        {"ls_stk3171", LIGHT_ID_STK3171},\r
        {"ls_isl29023", LIGHT_ID_ISL29023},\r
+       {"ls_ap321xx", LIGHT_ID_AP321XX},\r
        /*proximity sensor*/\r
        {"psensor", PROXIMITY_ID_ALL},\r
        {"proximity_al3006", PROXIMITY_ID_AL3006},      \r
        {"ps_stk3171", PROXIMITY_ID_STK3171},\r
+       {"ps_ap321xx", PROXIMITY_ID_AP321XX},\r
        /*temperature*/\r
        {"temperature", TEMPERATURE_ID_ALL},\r
        {},\r
index 38f4490ddef2db4b9b0da23a12041ebb51d1d97d..efabb62369c175545dae319654e0742be475bb99 100755 (executable)
@@ -78,10 +78,12 @@ enum sensor_id {
        LIGHT_ID_AL3006,\r
        LIGHT_ID_STK3171,\r
        LIGHT_ID_ISL29023,\r
+       LIGHT_ID_AP321XX,\r
        \r
        PROXIMITY_ID_ALL,\r
        PROXIMITY_ID_AL3006,\r
        PROXIMITY_ID_STK3171,\r
+       PROXIMITY_ID_AP321XX,\r
        TEMPERATURE_ID_ALL,\r
 \r
        PRESSURE_ID_ALL,\r