From 6307cd6953e3feac1b64752f1fc9260774a6ab4b Mon Sep 17 00:00:00 2001 From: linjh Date: Wed, 24 Oct 2012 11:53:42 +0800 Subject: [PATCH] rk2928_phonepad: adjust ap321xx l/p sensor to compatibale sensor framework [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 --- arch/arm/configs/rk2928_phonepad_defconfig | 5 +- arch/arm/mach-rk2928/board-rk2928-phonepad.c | 98 +- arch/arm/mach-rk2928/include/mach/board.h | 7 - drivers/input/misc/Kconfig | 6 - drivers/input/misc/Makefile | 1 - drivers/input/misc/ap321xx.c | 1395 ------------------ drivers/input/sensors/lsensor/Kconfig | 4 + drivers/input/sensors/lsensor/Makefile | 3 +- drivers/input/sensors/lsensor/ls_ap321xx.c | 416 ++++++ drivers/input/sensors/psensor/Kconfig | 4 + drivers/input/sensors/psensor/Makefile | 4 +- drivers/input/sensors/psensor/ps_ap321xx.c | 329 +++++ drivers/input/sensors/sensor-dev.c | 4 +- include/linux/sensor-dev.h | 2 + 14 files changed, 796 insertions(+), 1482 deletions(-) delete mode 100644 drivers/input/misc/ap321xx.c create mode 100644 drivers/input/sensors/lsensor/ls_ap321xx.c create mode 100644 drivers/input/sensors/psensor/ps_ap321xx.c diff --git a/arch/arm/configs/rk2928_phonepad_defconfig b/arch/arm/configs/rk2928_phonepad_defconfig index 12cacb9c6440..69a591609791 100644 --- a/arch/arm/configs/rk2928_phonepad_defconfig +++ b/arch/arm/configs/rk2928_phonepad_defconfig @@ -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 diff --git a/arch/arm/mach-rk2928/board-rk2928-phonepad.c b/arch/arm/mach-rk2928/board-rk2928-phonepad.c index d99b92da9639..d58e9bb6aea0 100755 --- a/arch/arm/mach-rk2928/board-rk2928-phonepad.c +++ b/arch/arm/mach-rk2928/board-rk2928-phonepad.c @@ -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 diff --git a/arch/arm/mach-rk2928/include/mach/board.h b/arch/arm/mach-rk2928/include/mach/board.h index 1c93a099548d..c843b1cdde48 100755 --- a/arch/arm/mach-rk2928/include/mach/board.h +++ b/arch/arm/mach-rk2928/include/mach/board.h @@ -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, diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index f5ab923449ec..b2d165feab47 100755 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -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 diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 1619523e8e58..59575af2c53d 100755 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -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 index 495123bc8ad0..000000000000 --- a/drivers/input/misc/ap321xx.c +++ /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 - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif -#include - -#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); - - diff --git a/drivers/input/sensors/lsensor/Kconfig b/drivers/input/sensors/lsensor/Kconfig index 18bde7618f5d..4c3aec1327c4 100755 --- a/drivers/input/sensors/lsensor/Kconfig +++ b/drivers/input/sensors/lsensor/Kconfig @@ -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 diff --git a/drivers/input/sensors/lsensor/Makefile b/drivers/input/sensors/lsensor/Makefile index 5127b4396f42..1834c514b54e 100755 --- a/drivers/input/sensors/lsensor/Makefile +++ b/drivers/input/sensors/lsensor/Makefile @@ -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 index 000000000000..1fb01b6fb7f7 --- /dev/null +++ b/drivers/input/sensors/lsensor/ls_ap321xx.c @@ -0,0 +1,416 @@ +/* drivers/input/sensors/access/kxtik.c + * + * Copyright (C) 2012-2015 ROCKCHIP. + * Author: luowei + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include + +#if 0 +#define SENSOR_DEBUG_TYPE SENSOR_TYPE_LIGHT +#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x) +#else +#define DBG(x...) +#endif + +#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 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 AL3212_ADC_LSB 0x0c +#define AL3212_ADC_MSB 0x0d + +#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 + +static u16 ap321xx_threshole[8] = {28,444,625,888,1778,3555,7222,0xffff}; + +/* + * register access helpers + */ + +static int __ap321xx_read_reg(struct i2c_client *client, + u32 reg, u8 mask, u8 shift) +{ + u8 val; + + val = i2c_smbus_read_byte_data(client, reg); + return (val & mask) >> shift; +} + +static int __ap321xx_write_reg(struct i2c_client *client, + u32 reg, u8 mask, u8 shift, u8 val) +{ + int ret = 0; + 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; +} + + +/* + * internally used functions + */ +/* range */ +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) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + 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) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int ret; + + ret = __ap321xx_write_reg(client, sensor->ops->ctrl_reg, + AP3212B_MODE_MASK, AP3212B_MODE_SHIFT, mode); + return ret; +} + +static int ap321xx_get_adc_value(struct i2c_client *client) +{ + unsigned int lsb, msb, val; + 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; + + val = msb << 8 | lsb; + for(index = 0; index < 7 && val > ap321xx_threshole[index];index++) + ; + + return index; +} + +/* ALS low threshold */ +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_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; +} + +static int ap321xx_get_intstat(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int val; + + val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg); + val &= AP3212B_INT_MASK; + + return val >> AP3212B_INT_SHIFT; +} + +static int ap321xx_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) ) + { + DBG("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid); + } + 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); + } + else + { + DBG("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) +{ + /* set defaults */ + ap321xx_set_range(client, 0); + ap321xx_set_mode(client, 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 void ap321xx_change_ls_threshold(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int value; + + value = ap321xx_get_adc_value(client); + DBG("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(sensor->input_dev, ABS_MISC, value); + input_sync(sensor->input_dev); +} + + +/****************operate according to sensor chip:start************/ + +static int sensor_active(struct i2c_client *client, int enable, int rate) +{ + int result = 0; + + //register setting according to chip datasheet + if (enable){ + result = ap321xx_lsensor_enable(client); + if(!result){ + msleep(200); + ap321xx_change_ls_threshold(client); + } + } + else + result = ap321xx_lsensor_disable(client); + + if(result) + printk("%s:fail to active sensor\n",__func__); + + return result; + +} + + +static int sensor_init(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int result = 0; + + result = ap321xx_product_detect(client); + if (result) + { + dev_err(&client->dev, "ret: %d, product version detect failed.\n",result); + return result; + } + + /* initialize the AP3212B chip */ + result = ap321xx_init_client(client); + if (result) + return result; + + result = sensor->ops->active(client,0,0); + if(result) + { + printk("%s:line=%d,error\n",__func__,__LINE__); + return result; + } + + sensor->status_cur = SENSOR_OFF; + + return result; +} + +static int sensor_report_value(struct i2c_client *client) +{ + int result = 0; + u8 int_stat; + + int_stat = ap321xx_get_intstat(client); + // ALS int + if (int_stat & AP3212B_INT_AMASK) + { + ap321xx_change_ls_threshold(client); + } + + return result; +} + +struct sensor_operate light_ap321xx_ops = { + .name = "ls_ap321xx", + .type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct + .id_i2c = LIGHT_ID_AP321XX, //i2c id number + .read_reg = SENSOR_UNKNOW_DATA, //read data //there are two regs, we fix them in code. + .read_len = 1, //data length + .id_reg = SENSOR_UNKNOW_DATA, //read device id from this register //there are 3 regs, we fix them in code. + .id_data = SENSOR_UNKNOW_DATA, //device id + .precision = 16, //8 bits + .ctrl_reg = AP3212B_MODE_COMMAND, //enable or disable + .int_status_reg = AP3212B_INT_COMMAND, //intterupt status register + .range = {100,65535}, //range + .brightness ={10,255}, // brightness + .trig = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED, + .active = sensor_active, + .init = sensor_init, + .report = sensor_report_value, +}; + +/****************operate according to sensor chip:end************/ + +//function name should not be changed +static struct sensor_operate *light_get_ops(void) +{ + return &light_ap321xx_ops; +} + + +static int __init light_ap321xx_init(void) +{ + struct sensor_operate *ops = light_get_ops(); + int result = 0; + int type = ops->type; + result = sensor_register_slave(type, NULL, NULL, light_get_ops); + DBG("%s\n",__func__); + return result; +} + +static void __exit light_ap321xx_exit(void) +{ + struct sensor_operate *ops = light_get_ops(); + int type = ops->type; + sensor_unregister_slave(type, NULL, NULL, light_get_ops); +} + + +module_init(light_ap321xx_init); +module_exit(light_ap321xx_exit); + + diff --git a/drivers/input/sensors/psensor/Kconfig b/drivers/input/sensors/psensor/Kconfig index 289280da6020..ce3a55adfeff 100755 --- a/drivers/input/sensors/psensor/Kconfig +++ b/drivers/input/sensors/psensor/Kconfig @@ -16,5 +16,9 @@ config PS_STK3171 bool "psensor stk3171" default n +config PS_AP321XX + bool "psensor ap321xx" + default n + endif diff --git a/drivers/input/sensors/psensor/Makefile b/drivers/input/sensors/psensor/Makefile index 1da405f6f88e..270d1aaad4f2 100755 --- a/drivers/input/sensors/psensor/Makefile +++ b/drivers/input/sensors/psensor/Makefile @@ -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 index 000000000000..d0479859d5d3 --- /dev/null +++ b/drivers/input/sensors/psensor/ps_ap321xx.c @@ -0,0 +1,329 @@ +/* drivers/input/sensors/access/kxtik.c + * + * Copyright (C) 2012-2015 ROCKCHIP. + * Author: luowei + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include + +#if 0 +#define SENSOR_DEBUG_TYPE SENSOR_TYPE_PROXIMITY +#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x) +#else +#define DBG(x...) +#endif + +#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 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_OBJ_COMMAND 0x0f +#define AP3212B_OBJ_MASK 0x80 +#define AP3212B_OBJ_SHIFT (7) + + +/* + * register access helpers + */ + +static int __ap321xx_read_reg(struct i2c_client *client, + u32 reg, u8 mask, u8 shift) +{ + u8 val; + + val = i2c_smbus_read_byte_data(client, reg); + return (val & mask) >> shift; +} + +static int __ap321xx_write_reg(struct i2c_client *client, + u32 reg, u8 mask, u8 shift, u8 val) +{ + int ret = 0; + 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; +} + + +/* + * internally used functions + */ +/* range */ +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) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + 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) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int ret; + + ret = __ap321xx_write_reg(client, sensor->ops->ctrl_reg, + AP3212B_MODE_MASK, AP3212B_MODE_SHIFT, mode); + return ret; +} +static int ap321xx_get_intstat(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int val; + + val = i2c_smbus_read_byte_data(client, sensor->ops->int_status_reg); + val &= AP3212B_INT_MASK; + + return val >> AP3212B_INT_SHIFT; +} + +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_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) ) + { + DBG("RevID [%d], ==> DA3212 v1.5~1.8 ...... AP3212B detected\n", rid); + } + 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); + } + else + { + DBG("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) +{ + /* set defaults */ + ap321xx_set_range(client, 0); + ap321xx_set_mode(client, 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; +} + +/****************operate according to sensor chip:start************/ + +static int sensor_active(struct i2c_client *client, int enable, int rate) +{ + int result = 0; + + //register setting according to chip datasheet + if (enable){ + result = ap321xx_psensor_enable(client); + } + else + result = ap321xx_psensor_disable(client); + + if(result) + printk("%s:fail to active sensor\n",__func__); + + return result; + +} + + +static int sensor_init(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int result = 0; + + result = ap321xx_product_detect(client); + if (result) + { + dev_err(&client->dev, "ret: %d, product version detect failed.\n",result); + return result; + } + + /* initialize the AP3212B chip */ + result = ap321xx_init_client(client); + if (result) + return result; + + result = sensor->ops->active(client,0,0); + if(result) + { + printk("%s:line=%d,error\n",__func__,__LINE__); + return result; + } + + sensor->status_cur = SENSOR_OFF; + + return result; +} + +static int sensor_report_value(struct i2c_client *client) +{ + struct sensor_private_data *sensor = + (struct sensor_private_data *) i2c_get_clientdata(client); + int result = 0; + char value = 0; + u8 int_stat; + + int_stat = ap321xx_get_intstat(client); + // ALS int + if (int_stat & AP3212B_INT_PMASK) + { + value = ap321xx_get_object(client); + input_report_abs(sensor->input_dev, ABS_DISTANCE, value); + input_sync(sensor->input_dev); + } + + return result; +} + +struct sensor_operate proximity_ap321xx_ops = { + .name = "ps_ap321xx", + .type = SENSOR_TYPE_PROXIMITY, //sensor type and it should be correct + .id_i2c = PROXIMITY_ID_AP321XX, //i2c id number + .read_reg = SENSOR_UNKNOW_DATA, //read data //there are two regs, we fix them in code. + .read_len = 1, //data length + .id_reg = SENSOR_UNKNOW_DATA, //read device id from this register //there are 3 regs, we fix them in code. + .id_data = SENSOR_UNKNOW_DATA, //device id + .precision = 8, //8 bits + .ctrl_reg = AP3212B_MODE_COMMAND, //enable or disable + .int_status_reg = AP3212B_INT_COMMAND, //intterupt status register + .range = {0,10}, //range + .brightness ={10,255}, // brightness + .trig = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED, + .active = sensor_active, + .init = sensor_init, + .report = sensor_report_value, +}; + +/****************operate according to sensor chip:end************/ + +//function name should not be changed +static struct sensor_operate *proximity_get_ops(void) +{ + return &proximity_ap321xx_ops; +} + + +static int __init proximity_ap321xx_init(void) +{ + struct sensor_operate *ops = proximity_get_ops(); + int result = 0; + int type = ops->type; + result = sensor_register_slave(type, NULL, NULL, proximity_get_ops); + DBG("%s\n",__func__); + return result; +} + +static void __exit proximity_ap321xx_exit(void) +{ + struct sensor_operate *ops = proximity_get_ops(); + int type = ops->type; + sensor_unregister_slave(type, NULL, NULL, proximity_get_ops); +} + + +module_init(proximity_ap321xx_init); +module_exit(proximity_ap321xx_exit); + + diff --git a/drivers/input/sensors/sensor-dev.c b/drivers/input/sensors/sensor-dev.c index d43432301627..5ae58ff2d64d 100755 --- a/drivers/input/sensors/sensor-dev.c +++ b/drivers/input/sensors/sensor-dev.c @@ -302,7 +302,7 @@ static int sensor_irq_init(struct i2c_client *client) client->irq = irq; if((sensor->pdata->type == SENSOR_TYPE_GYROSCOPE) || (sensor->pdata->type == SENSOR_TYPE_ACCEL)) disable_irq_nosync(client->irq);//disable irq - if(((sensor->pdata->type == SENSOR_TYPE_LIGHT) || ((sensor->pdata->type == SENSOR_TYPE_PROXIMITY))) && (!(sensor->ops->trig & IRQF_SHARED))) + if(((sensor->pdata->type == SENSOR_TYPE_LIGHT) || (sensor->pdata->type == SENSOR_TYPE_PROXIMITY))&& (!(sensor->ops->trig & IRQF_SHARED))) disable_irq_nosync(client->irq);//disable irq printk("%s:use irq=%d\n",__func__,irq); } @@ -1414,10 +1414,12 @@ static const struct i2c_device_id sensor_id[] = { {"light_al3006", LIGHT_ID_AL3006}, {"ls_stk3171", LIGHT_ID_STK3171}, {"ls_isl29023", LIGHT_ID_ISL29023}, + {"ls_ap321xx", LIGHT_ID_AP321XX}, /*proximity sensor*/ {"psensor", PROXIMITY_ID_ALL}, {"proximity_al3006", PROXIMITY_ID_AL3006}, {"ps_stk3171", PROXIMITY_ID_STK3171}, + {"ps_ap321xx", PROXIMITY_ID_AP321XX}, /*temperature*/ {"temperature", TEMPERATURE_ID_ALL}, {}, diff --git a/include/linux/sensor-dev.h b/include/linux/sensor-dev.h index 38f4490ddef2..efabb62369c1 100755 --- a/include/linux/sensor-dev.h +++ b/include/linux/sensor-dev.h @@ -78,10 +78,12 @@ enum sensor_id { LIGHT_ID_AL3006, LIGHT_ID_STK3171, LIGHT_ID_ISL29023, + LIGHT_ID_AP321XX, PROXIMITY_ID_ALL, PROXIMITY_ID_AL3006, PROXIMITY_ID_STK3171, + PROXIMITY_ID_AP321XX, TEMPERATURE_ID_ALL, PRESSURE_ID_ALL, -- 2.34.1