1 /* drivers/hwmon/mt6516/amit/APDS9930.c - APDS9930 ALS/PS driver
3 * Author: MingHsien Hsieh <minghsien.hsieh@mediatek.com>
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/interrupt.h>
17 #include <linux/i2c.h>
18 #include <linux/slab.h>
19 #include <linux/irq.h>
20 #include <linux/miscdevice.h>
21 #include <asm/uaccess.h>
22 #include <linux/delay.h>
23 #include <linux/input.h>
24 #include <linux/workqueue.h>
25 #include <linux/kobject.h>
26 #include <linux/earlysuspend.h>
27 #include <linux/platform_device.h>
28 #include <asm/atomic.h>
30 #include <mach/mt_typedefs.h>
31 #include <mach/mt_gpio.h>
32 #include <mach/mt_pm_ldo.h>
34 #define POWER_NONE_MACRO MT65XX_POWER_NONE
36 #include <linux/hwmsensor.h>
37 #include <linux/hwmsen_dev.h>
38 #include <linux/sensors_io.h>
40 #include <cust_eint.h>
41 #include <cust_alsps.h>
43 #include <linux/sched.h>
44 /******************************************************************************
46 *******************************************************************************/
47 /*----------------------------------------------------------------------------*/
49 #define APDS9930_DEV_NAME "APDS9930"
50 /*----------------------------------------------------------------------------*/
51 #define APS_TAG "[ALS/PS] "
52 #define APS_FUN(f) printk(KERN_INFO APS_TAG"%s\n", __FUNCTION__)
53 #define APS_ERR(fmt, args...) printk(KERN_ERR APS_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)
54 #define APS_LOG(fmt, args...) printk(KERN_ERR APS_TAG fmt, ##args)
55 #define APS_DBG(fmt, args...) printk(KERN_INFO APS_TAG fmt, ##args)
57 #define I2C_FLAG_WRITE 0
58 #define I2C_FLAG_READ 1
61 /******************************************************************************
63 *******************************************************************************/
64 extern void mt_eint_mask(unsigned int eint_num
);
65 extern void mt_eint_unmask(unsigned int eint_num
);
66 extern void mt_eint_set_hw_debounce(unsigned int eint_num
, unsigned int ms
);
67 extern void mt_eint_set_polarity(unsigned int eint_num
, unsigned int pol
);
68 extern unsigned int mt_eint_set_sens(unsigned int eint_num
, unsigned int sens
);
69 extern void mt_eint_registration(unsigned int eint_num
, unsigned int flow
, void (EINT_FUNC_PTR
)(void), unsigned int is_auto_umask
);
70 extern void mt_eint_print_status(void);
72 /*----------------------------------------------------------------------------*/
73 static struct i2c_client
*APDS9930_i2c_client
= NULL
;
74 /*----------------------------------------------------------------------------*/
75 static const struct i2c_device_id APDS9930_i2c_id
[] = {{APDS9930_DEV_NAME
,0},{}};
76 static struct i2c_board_info __initdata i2c_APDS9930
={ I2C_BOARD_INFO("APDS9930", 0x39)};
77 /*----------------------------------------------------------------------------*/
78 static int APDS9930_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
);
79 static int APDS9930_i2c_remove(struct i2c_client
*client
);
80 static int APDS9930_i2c_detect(struct i2c_client
*client
, struct i2c_board_info
*info
);
81 /*----------------------------------------------------------------------------*/
82 static int APDS9930_i2c_suspend(struct i2c_client
*client
, pm_message_t msg
);
83 static int APDS9930_i2c_resume(struct i2c_client
*client
);
85 static DEFINE_MUTEX(APDS9930_mutex
);
88 static struct APDS9930_priv
*g_APDS9930_ptr
= NULL
;
90 struct PS_CALI_DATA_STRUCT
97 static struct PS_CALI_DATA_STRUCT ps_cali
={0,0,0};
98 static int intr_flag_value
= 0;
99 static unsigned long long int_top_time
= 0;
100 /*----------------------------------------------------------------------------*/
105 /*----------------------------------------------------------------------------*/
106 struct APDS9930_i2c_addr
{ /*define a series of i2c slave address*/
108 u8 ps_thd
; /*PS INT threshold*/
110 /*----------------------------------------------------------------------------*/
111 struct APDS9930_priv
{
113 struct i2c_client
*client
;
114 struct work_struct eint_work
;
116 /*i2c address group*/
117 struct APDS9930_i2c_addr addr
;
122 atomic_t als_suspend
;
123 atomic_t als_debounce
; /*debounce time after enabling als*/
124 atomic_t als_deb_on
; /*indicates if the debounce is on*/
125 atomic_t als_deb_end
; /*the jiffies representing the end of debounce*/
126 atomic_t ps_mask
; /*mask ps: always return far away*/
127 atomic_t ps_debounce
; /*debounce time after enabling ps*/
128 atomic_t ps_deb_on
; /*indicates if the debounce is on*/
129 atomic_t ps_deb_end
; /*the jiffies representing the end of debounce*/
139 u32 als_level
[C_CUST_ALS_LEVEL
-1];
140 u32 als_value
[C_CUST_ALS_LEVEL
];
143 atomic_t als_cmd_val
; /*the cmd value can't be read, stored in ram*/
144 atomic_t ps_cmd_val
; /*the cmd value can't be read, stored in ram*/
145 atomic_t ps_thd_val_high
; /*the cmd value can't be read, stored in ram*/
146 atomic_t ps_thd_val_low
; /*the cmd value can't be read, stored in ram*/
147 ulong enable
; /*enable mask*/
148 ulong pending_intr
; /*pending interrupt*/
151 #if defined(CONFIG_HAS_EARLYSUSPEND)
152 struct early_suspend early_drv
;
155 /*----------------------------------------------------------------------------*/
156 static struct i2c_driver APDS9930_i2c_driver
= {
157 .probe
= APDS9930_i2c_probe
,
158 .remove
= APDS9930_i2c_remove
,
159 .detect
= APDS9930_i2c_detect
,
160 .suspend
= APDS9930_i2c_suspend
,
161 .resume
= APDS9930_i2c_resume
,
162 .id_table
= APDS9930_i2c_id
,
164 .name
= APDS9930_DEV_NAME
,
168 static struct APDS9930_priv
*APDS9930_obj
= NULL
;
169 static struct platform_driver APDS9930_alsps_driver
;
170 /*------------------------i2c function for 89-------------------------------------*/
171 int APDS9930_i2c_master_operate(struct i2c_client
*client
, const char *buf
, int count
, int i2c_flag
)
174 mutex_lock(&APDS9930_mutex
);
177 client
->addr
&=I2C_MASK_FLAG
;
178 res
= i2c_master_send(client
, buf
, count
);
179 client
->addr
&=I2C_MASK_FLAG
;
183 client
->addr
&=I2C_MASK_FLAG
;
184 client
->addr
|=I2C_WR_FLAG
;
185 client
->addr
|=I2C_RS_FLAG
;
186 res
= i2c_master_send(client
, buf
, count
);
187 client
->addr
&=I2C_MASK_FLAG
;
190 APS_LOG("APDS9930_i2c_master_operate i2c_flag command not support!\n");
197 mutex_unlock(&APDS9930_mutex
);
200 mutex_unlock(&APDS9930_mutex
);
201 APS_ERR("APDS9930_i2c_transfer fail\n");
205 /*----------------------------------------------------------------------------*/
206 int APDS9930_get_addr(struct alsps_hw
*hw
, struct APDS9930_i2c_addr
*addr
)
212 addr
->write_addr
= hw
->i2c_addr
[0];
215 /*----------------------------------------------------------------------------*/
216 static void APDS9930_power(struct alsps_hw
*hw
, unsigned int on
)
218 static unsigned int power_on
= 0;
220 //APS_LOG("power %s\n", on ? "on" : "off");
222 if(hw
->power_id
!= POWER_NONE_MACRO
)
226 APS_LOG("ignore power control: %d\n", on
);
230 if(!hwPowerOn(hw
->power_id
, hw
->power_vol
, "APDS9930"))
232 APS_ERR("power on fails!!\n");
237 if(!hwPowerDown(hw
->power_id
, "APDS9930"))
239 APS_ERR("power off fail!!\n");
245 /*----------------------------------------------------------------------------*/
246 static long APDS9930_enable_als(struct i2c_client
*client
, int enable
)
248 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
252 databuf
[0]= APDS9930_CMM_ENABLE
;
253 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x101, I2C_FLAG_READ
);
258 //APS_LOG("APDS9930_CMM_ENABLE als value = %x\n",databuf[0]);
262 databuf
[1] = databuf
[0]|0x03;
263 databuf
[0] = APDS9930_CMM_ENABLE
;
264 //APS_LOG("APDS9930_CMM_ENABLE enable als value = %x\n",databuf[1]);
265 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
270 atomic_set(&obj
->als_deb_on
, 1);
271 atomic_set(&obj
->als_deb_end
, jiffies
+atomic_read(&obj
->als_debounce
)/(1000/HZ
));
274 if(test_bit(CMC_BIT_PS
, &obj
->enable
))
275 databuf
[1] = databuf
[0]&0xFD;
277 databuf
[1] = databuf
[0]&0xF8;
279 databuf
[0] = APDS9930_CMM_ENABLE
;
280 //APS_LOG("APDS9930_CMM_ENABLE disable als value = %x\n",databuf[1]);
281 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
290 APS_ERR("APDS9930_enable_als fail\n");
294 /*----------------------------------------------------------------------------*/
295 static long APDS9930_enable_ps(struct i2c_client
*client
, int enable
)
297 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
301 databuf
[0]= APDS9930_CMM_ENABLE
;
302 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x101, I2C_FLAG_READ
);
308 //APS_LOG("APDS9930_CMM_ENABLE ps value = %x\n",databuf[0]);
312 databuf
[1] = databuf
[0]|0x05;
313 databuf
[0] = APDS9930_CMM_ENABLE
;
314 //APS_LOG("APDS9930_CMM_ENABLE enable ps value = %x\n",databuf[1]);
315 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
320 atomic_set(&obj
->ps_deb_on
, 1);
321 atomic_set(&obj
->ps_deb_end
, jiffies
+atomic_read(&obj
->ps_debounce
)/(1000/HZ
));
324 if(test_bit(CMC_BIT_ALS
, &obj
->enable
))
325 databuf
[1] = databuf
[0]&0xFB;
327 databuf
[1] = databuf
[0]&0xF8;
329 databuf
[0] = APDS9930_CMM_ENABLE
;
330 //APS_LOG("APDS9930_CMM_ENABLE disable ps value = %x\n",databuf[1]);
331 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
337 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
338 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_low
)) & 0x00FF);
339 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
344 databuf
[0] = APDS9930_CMM_INT_LOW_THD_HIGH
;
345 databuf
[1] = (u8
)(((atomic_read(&obj
->ps_thd_val_low
)) & 0xFF00) >> 8);
346 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
351 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
352 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_high
)) & 0x00FF);
353 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
358 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_HIGH
;
359 databuf
[1] = (u8
)(((atomic_read(&obj
->ps_thd_val_high
)) & 0xFF00) >> 8);;
360 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
370 APS_ERR("APDS9930_enable_ps fail\n");
373 /*----------------------------------------------------------------------------*/
374 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/
375 static int APDS9930_check_and_clear_intr(struct i2c_client
*client
)
380 if (mt_get_gpio_in(GPIO_ALS_EINT_PIN
) == 1) /*skip if no interrupt*/
383 buffer
[0] = APDS9930_CMM_STATUS
;
384 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x101, I2C_FLAG_READ
);
393 if(0 != (buffer
[0] & 0x20))
398 if(0 != (buffer
[0] & 0x10))
406 if((1 == intp
) && (0 == intl
))
408 buffer
[0] = (TAOS_TRITON_CMD_REG
|TAOS_TRITON_CMD_SPL_FN
|0x05);
410 else if((0 == intp
) && (1 == intl
))
412 buffer
[0] = (TAOS_TRITON_CMD_REG
|TAOS_TRITON_CMD_SPL_FN
|0x06);
416 buffer
[0] = (TAOS_TRITON_CMD_REG
|TAOS_TRITON_CMD_SPL_FN
|0x07);
419 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x1, I2C_FLAG_WRITE
);
433 APS_ERR("APDS9930_check_and_clear_intr fail\n");
436 /*----------------------------------------------------------------------------*/
438 /*yucong add for interrupt mode support MTK inc 2012.3.7*/
439 static int APDS9930_check_intr(struct i2c_client
*client
)
444 if (mt_get_gpio_in(GPIO_ALS_EINT_PIN
) == 1) /*skip if no interrupt*/
447 buffer
[0] = APDS9930_CMM_STATUS
;
448 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x101, I2C_FLAG_READ
);
456 if(0 != (buffer
[0] & 0x20))
461 if(0 != (buffer
[0] & 0x10))
470 APS_ERR("APDS9930_check_intr fail\n");
474 static int APDS9930_clear_intr(struct i2c_client
*client
)
479 buffer
[0] = (TAOS_TRITON_CMD_REG
|TAOS_TRITON_CMD_SPL_FN
|0x07);
480 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x1, I2C_FLAG_WRITE
);
492 APS_ERR("APDS9930_check_and_clear_intr fail\n");
497 /*-----------------------------------------------------------------------------*/
498 void APDS9930_eint_func(void)
500 struct APDS9930_priv
*obj
= g_APDS9930_ptr
;
505 int_top_time
= sched_clock();
506 schedule_work(&obj
->eint_work
);
509 /*----------------------------------------------------------------------------*/
510 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/
511 int APDS9930_setup_eint(struct i2c_client
*client
)
513 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
515 g_APDS9930_ptr
= obj
;
517 mt_set_gpio_dir(GPIO_ALS_EINT_PIN
, GPIO_DIR_IN
);
518 mt_set_gpio_mode(GPIO_ALS_EINT_PIN
, GPIO_ALS_EINT_PIN_M_EINT
);
519 mt_set_gpio_pull_enable(GPIO_ALS_EINT_PIN
, TRUE
);
520 mt_set_gpio_pull_select(GPIO_ALS_EINT_PIN
, GPIO_PULL_UP
);
522 mt_eint_set_hw_debounce(CUST_EINT_ALS_NUM
, CUST_EINT_ALS_DEBOUNCE_CN
);
523 mt_eint_registration(CUST_EINT_ALS_NUM
, CUST_EINT_ALS_TYPE
, APDS9930_eint_func
, 0);
525 mt_eint_unmask(CUST_EINT_ALS_NUM
);
529 /*----------------------------------------------------------------------------*/
531 static int APDS9930_init_client(struct i2c_client
*client
)
533 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
537 databuf
[0] = (TAOS_TRITON_CMD_REG
|TAOS_TRITON_CMD_SPL_FN
|0x00);
538 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x1, I2C_FLAG_WRITE
);
544 databuf
[0] = APDS9930_CMM_ENABLE
;
545 if(obj
->hw
->polling_mode_ps
== 1)
547 if(obj
->hw
->polling_mode_ps
== 0)
549 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
555 databuf
[0] = APDS9930_CMM_ATIME
;
557 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
563 databuf
[0] = APDS9930_CMM_PTIME
;
565 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
571 databuf
[0] = APDS9930_CMM_WTIME
;
573 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
578 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/
579 if(0 == obj
->hw
->polling_mode_ps
)
581 if(1 == ps_cali
.valid
)
583 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
584 databuf
[1] = (u8
)(ps_cali
.far_away
& 0x00FF);
585 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
590 databuf
[0] = APDS9930_CMM_INT_LOW_THD_HIGH
;
591 databuf
[1] = (u8
)((ps_cali
.far_away
& 0xFF00) >> 8);
592 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
597 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
598 databuf
[1] = (u8
)(ps_cali
.close
& 0x00FF);
599 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
604 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_HIGH
;
605 databuf
[1] = (u8
)((ps_cali
.close
& 0xFF00) >> 8);;
606 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
614 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
615 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_low
)) & 0x00FF);
616 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
621 databuf
[0] = APDS9930_CMM_INT_LOW_THD_HIGH
;
622 databuf
[1] = (u8
)(((atomic_read(&obj
->ps_thd_val_low
)) & 0xFF00) >> 8);
623 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
628 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
629 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_high
)) & 0x00FF);
630 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
635 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_HIGH
;
636 databuf
[1] = (u8
)(((atomic_read(&obj
->ps_thd_val_high
)) & 0xFF00) >> 8);;
637 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
645 databuf
[0] = APDS9930_CMM_Persistence
;
647 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
655 databuf
[0] = APDS9930_CMM_CONFIG
;
657 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
663 /*Lenovo-sw chenlj2 add 2011-06-03,modified pulse 2 to 4 */
664 databuf
[0] = APDS9930_CMM_PPCOUNT
;
665 databuf
[1] = APDS9930_CMM_PPCOUNT_VALUE
;
666 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
672 /*Lenovo-sw chenlj2 add 2011-06-03,modified gain 16 to 1 */
673 databuf
[0] = APDS9930_CMM_CONTROL
;
674 databuf
[1] = APDS9930_CMM_CONTROL_VALUE
;
675 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
680 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/
681 if((res
= APDS9930_setup_eint(client
))!=0)
683 APS_ERR("setup eint: %d\n", res
);
686 if((res
= APDS9930_check_and_clear_intr(client
)))
688 APS_ERR("check/clear intr: %d\n", res
);
692 return APDS9930_SUCCESS
;
695 APS_ERR("init dev: %d\n", res
);
699 /******************************************************************************
700 * Function Configuration
701 ******************************************************************************/
702 int APDS9930_read_als(struct i2c_client
*client
, u16
*data
)
704 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
705 u16 c0_value
, c1_value
;
713 APS_DBG("CLIENT CANN'T EQUL NULL\n");
717 buffer
[0]=APDS9930_CMM_C0DATA_L
;
718 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x201, I2C_FLAG_READ
);
724 c0_value
= buffer
[0] | (buffer
[1]<<8);
725 c0_nf
= obj
->als_modulus
*c0_value
;
726 //APS_LOG("c0_value=%d, c0_nf=%d, als_modulus=%d\n", c0_value, c0_nf, obj->als_modulus);
728 buffer
[0]=APDS9930_CMM_C1DATA_L
;
729 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x201, I2C_FLAG_READ
);
735 c1_value
= buffer
[0] | (buffer
[1]<<8);
736 c1_nf
= obj
->als_modulus
*c1_value
;
737 //APS_LOG("c1_value=%d, c1_nf=%d, als_modulus=%d\n", c1_value, c1_nf, obj->als_modulus);
739 if((c0_value
> c1_value
) &&(c0_value
< 50000))
740 { /*Lenovo-sw chenlj2 add 2011-06-03,add {*/
741 atio
= (c1_nf
*100)/c0_nf
;
743 //APS_LOG("atio = %d\n", atio);
746 *data
= (13*c0_nf
- 24*c1_nf
)/10000;
748 else if(atio
>= 30 && atio
<38) /*Lenovo-sw chenlj2 add 2011-06-03,modify > to >=*/
750 *data
= (16*c0_nf
- 35*c1_nf
)/10000;
752 else if(atio
>= 38 && atio
<45) /*Lenovo-sw chenlj2 add 2011-06-03,modify > to >=*/
754 *data
= (9*c0_nf
- 17*c1_nf
)/10000;
756 else if(atio
>= 45 && atio
<54) /*Lenovo-sw chenlj2 add 2011-06-03,modify > to >=*/
758 *data
= (6*c0_nf
- 10*c1_nf
)/10000;
762 /*Lenovo-sw chenlj2 add 2011-06-03,add }*/
764 else if (c0_value
> 50000)
768 else if(c0_value
== 0)
774 APS_DBG("APDS9930_read_als als_value is invalid!!\n");
778 //APS_LOG("APDS9930_read_als als_value_lux = %d\n", *data);
784 APS_ERR("APDS9930_read_ps fail\n");
787 int APDS9930_read_als_ch0(struct i2c_client
*client
, u16
*data
)
789 //struct APDS9930_priv *obj = i2c_get_clientdata(client);
796 APS_DBG("CLIENT CANN'T EQUL NULL\n");
800 //get adc channel 0 value
801 buffer
[0]=APDS9930_CMM_C0DATA_L
;
802 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x201, I2C_FLAG_READ
);
807 c0_value
= buffer
[0] | (buffer
[1]<<8);
809 //APS_LOG("c0_value=%d\n", c0_value);
815 APS_ERR("APDS9930_read_ps fail\n");
818 /*----------------------------------------------------------------------------*/
820 static int APDS9930_get_als_value(struct APDS9930_priv
*obj
, u16 als
)
824 for(idx
= 0; idx
< obj
->als_level_num
; idx
++)
826 if(als
< obj
->hw
->als_level
[idx
])
832 if(idx
>= obj
->als_value_num
)
834 APS_ERR("APDS9930_get_als_value exceed range\n");
835 idx
= obj
->als_value_num
- 1;
838 if(1 == atomic_read(&obj
->als_deb_on
))
840 unsigned long endt
= atomic_read(&obj
->als_deb_end
);
841 if(time_after(jiffies
, endt
))
843 atomic_set(&obj
->als_deb_on
, 0);
846 if(1 == atomic_read(&obj
->als_deb_on
))
854 #if defined(MTK_AAL_SUPPORT)
855 int level_high
= obj
->hw
->als_level
[idx
];
856 int level_low
= (idx
> 0) ? obj
->hw
->als_level
[idx
-1] : 0;
857 int level_diff
= level_high
- level_low
;
858 int value_high
= obj
->hw
->als_value
[idx
];
859 int value_low
= (idx
> 0) ? obj
->hw
->als_value
[idx
-1] : 0;
860 int value_diff
= value_high
- value_low
;
863 if ((level_low
>= level_high
) || (value_low
>= value_high
))
866 value
= (level_diff
* value_low
+ (als
- level_low
) * value_diff
+ ((level_diff
+ 1) >> 1)) / level_diff
;
868 APS_DBG("ALS: %d [%d, %d] => %d [%d, %d] \n", als
, level_low
, level_high
, value
, value_low
, value_high
);
871 //APS_ERR("ALS: %05d => %05d\n", als, obj->hw->als_value[idx]);
872 return obj
->hw
->als_value
[idx
];
876 //APS_ERR("ALS: %05d => %05d (-1)\n", als, obj->hw->als_value[idx]);
880 /*----------------------------------------------------------------------------*/
881 long APDS9930_read_ps(struct i2c_client
*client
, u16
*data
)
883 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
890 APS_DBG("CLIENT CANN'T EQUL NULL\n");
894 buffer
[0]=APDS9930_CMM_PDATA_L
;
895 res
= APDS9930_i2c_master_operate(client
, buffer
, 0x201, I2C_FLAG_READ
);
901 temp_data
= buffer
[0] | (buffer
[1]<<8);
902 //APS_LOG("yucong APDS9930_read_ps ps_data=%d, low:%d high:%d", *data, buffer[0], buffer[1]);
903 if(temp_data
< obj
->ps_cali
)
906 *data
= temp_data
- obj
->ps_cali
;
911 APS_ERR("APDS9930_read_ps fail\n");
914 /*----------------------------------------------------------------------------*/
915 static int APDS9930_get_ps_value(struct APDS9930_priv
*obj
, u16 ps
)
917 int val
;// mask = atomic_read(&obj->ps_mask);
919 static int val_temp
=1;
921 if(ps_cali
.valid
== 1)
923 if((ps
>ps_cali
.close
))
930 else if((ps
< ps_cali
.far_away
))
932 val
= 1; /*far away*/
939 APS_LOG("APDS9930_get_ps_value val = %d",val
);
943 if((ps
> atomic_read(&obj
->ps_thd_val_high
)))
949 else if((ps
< atomic_read(&obj
->ps_thd_val_low
)))
951 val
= 1; /*far away*/
960 if(atomic_read(&obj
->ps_suspend
))
964 else if(1 == atomic_read(&obj
->ps_deb_on
))
966 unsigned long endt
= atomic_read(&obj
->ps_deb_end
);
967 if(time_after(jiffies
, endt
))
969 atomic_set(&obj
->ps_deb_on
, 0);
972 if (1 == atomic_read(&obj
->ps_deb_on
))
977 else if (obj
->als
> 45000)
980 APS_DBG("ligh too high will result to failt proximiy\n");
981 return 1; /*far away*/
986 //APS_DBG("PS: %05d => %05d\n", ps, val);
996 /*----------------------------------------------------------------------------*/
997 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/
998 //#define DEBUG_APDS9930
999 static void APDS9930_eint_work(struct work_struct
*work
)
1001 struct APDS9930_priv
*obj
= (struct APDS9930_priv
*)container_of(work
, struct APDS9930_priv
, eint_work
);
1003 hwm_sensor_data sensor_data
;
1007 if((err
= APDS9930_check_intr(obj
->client
)))
1009 APS_ERR("APDS9930_eint_work check intrs: %d\n", err
);
1014 APDS9930_read_ps(obj
->client
, &obj
->ps
);
1015 APDS9930_read_als_ch0(obj
->client
, &obj
->als
);
1016 APS_LOG("APDS9930_eint_work rawdata ps=%d als_ch0=%d!\n",obj
->ps
,obj
->als
);
1017 APS_LOG("APDS9930 int top half time = %lld\n", int_top_time
);
1019 if(obj
->als
> 40000)
1021 APS_LOG("APDS9930_eint_work ALS too large may under lighting als_ch0=%d!\n",obj
->als
);
1024 sensor_data
.values
[0] = APDS9930_get_ps_value(obj
, obj
->ps
);
1025 sensor_data
.value_divide
= 1;
1026 sensor_data
.status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1028 #ifdef DEBUG_APDS9930
1029 databuf
[0]= APDS9930_CMM_ENABLE
;
1030 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x101, I2C_FLAG_READ
);
1035 APS_LOG("APDS9930_eint_work APDS9930_CMM_ENABLE ps value = %x\n",databuf
[0]);
1037 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
1038 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x201, I2C_FLAG_READ
);
1043 APS_LOG("APDS9930_eint_work APDS9930_CMM_INT_LOW_THD_LOW before databuf[0]=%d databuf[1]=%d!\n",databuf
[0],databuf
[1]);
1045 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
1046 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x201, I2C_FLAG_READ
);
1051 APS_LOG("APDS9930_eint_work APDS9930_CMM_INT_HIGH_THD_LOW before databuf[0]=%d databuf[1]=%d!\n",databuf
[0],databuf
[1]);
1053 /*singal interrupt function add*/
1054 if(intr_flag_value
){
1055 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
1056 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_low
)) & 0x00FF);
1057 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1063 databuf
[0] = APDS9930_CMM_INT_LOW_THD_HIGH
;
1064 databuf
[1] = (u8
)(((atomic_read(&obj
->ps_thd_val_low
)) & 0xFF00) >> 8);
1065 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1070 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
1071 databuf
[1] = (u8
)(0x00FF);
1072 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1078 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_HIGH
;
1079 databuf
[1] = (u8
)((0xFF00) >> 8);
1080 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1088 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
1089 databuf
[1] = (u8
)(0 & 0x00FF);
1090 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1096 databuf
[0] = APDS9930_CMM_INT_LOW_THD_HIGH
;
1097 databuf
[1] = (u8
)((0 & 0xFF00) >> 8);
1098 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1104 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
1105 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_high
)) & 0x00FF);
1106 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1112 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_HIGH
;
1113 databuf
[1] = (u8
)(((atomic_read(&obj
->ps_thd_val_high
)) & 0xFF00) >> 8);
1114 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1115 res
= i2c_master_send(obj
->client
, databuf
, 0x2);
1122 //let up layer to know
1123 #ifdef DEBUG_APDS9930
1124 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
1125 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x201, I2C_FLAG_READ
);
1130 APS_LOG("APDS9930_eint_work APDS9930_CMM_INT_LOW_THD_LOW after databuf[0]=%d databuf[1]=%d!\n",databuf
[0],databuf
[1]);
1132 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
1133 res
= APDS9930_i2c_master_operate(obj
->client
, databuf
, 0x201, I2C_FLAG_READ
);
1138 APS_LOG("APDS9930_eint_work APDS9930_CMM_INT_HIGH_THD_LOW after databuf[0]=%d databuf[1]=%d!\n",databuf
[0],databuf
[1]);
1140 if((err
= hwmsen_get_interrupt_data(ID_PROXIMITY
, &sensor_data
)))
1142 APS_ERR("call hwmsen_get_interrupt_data fail = %d\n", err
);
1146 APDS9930_clear_intr(obj
->client
);
1147 mt_eint_unmask(CUST_EINT_ALS_NUM
);
1150 APDS9930_clear_intr(obj
->client
);
1151 mt_eint_unmask(CUST_EINT_ALS_NUM
);
1152 APS_ERR("i2c_transfer error = %d\n", res
);
1157 /******************************************************************************
1158 * Function Configuration
1159 ******************************************************************************/
1160 static int APDS9930_open(struct inode
*inode
, struct file
*file
)
1162 file
->private_data
= APDS9930_i2c_client
;
1164 if (!file
->private_data
)
1166 APS_ERR("null pointer!!\n");
1170 return nonseekable_open(inode
, file
);
1172 /*----------------------------------------------------------------------------*/
1173 static int APDS9930_release(struct inode
*inode
, struct file
*file
)
1175 file
->private_data
= NULL
;
1178 /*----------------------------------------------------------------------------*/
1179 static int set_psensor_threshold(struct i2c_client
*client
)
1181 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
1184 APS_ERR("set_psensor_threshold function high: 0x%x, low:0x%x\n",atomic_read(&obj
->ps_thd_val_high
),atomic_read(&obj
->ps_thd_val_low
));
1186 databuf
[0] = APDS9930_CMM_INT_LOW_THD_LOW
;
1187 databuf
[1] = (u8
)(atomic_read(&obj
->ps_thd_val_low
) & 0x00FF);
1188 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1193 databuf
[0] = APDS9930_CMM_INT_LOW_THD_HIGH
;
1194 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_low
) & 0xFF00) >> 8);
1195 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1200 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_LOW
;
1201 databuf
[1] = (u8
)(atomic_read(&obj
->ps_thd_val_high
) & 0x00FF);
1202 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1207 databuf
[0] = APDS9930_CMM_INT_HIGH_THD_HIGH
;
1208 databuf
[1] = (u8
)((atomic_read(&obj
->ps_thd_val_high
) & 0xFF00) >> 8);;
1209 res
= APDS9930_i2c_master_operate(client
, databuf
, 0x2, I2C_FLAG_WRITE
);
1218 /*----------------------------------------------------------------------------*/
1219 static long APDS9930_unlocked_ioctl(struct file
*file
, unsigned int cmd
,
1222 struct i2c_client
*client
= (struct i2c_client
*)file
->private_data
;
1223 struct APDS9930_priv
*obj
= i2c_get_clientdata(client
);
1225 void __user
*ptr
= (void __user
*) arg
;
1234 case ALSPS_SET_PS_MODE
:
1235 if(copy_from_user(&enable
, ptr
, sizeof(enable
)))
1242 if((err
= APDS9930_enable_ps(obj
->client
, 1)))
1244 APS_ERR("enable ps fail: %ld\n", err
);
1248 set_bit(CMC_BIT_PS
, &obj
->enable
);
1252 if((err
= APDS9930_enable_ps(obj
->client
, 0)))
1254 APS_ERR("disable ps fail: %ld\n", err
);
1258 clear_bit(CMC_BIT_PS
, &obj
->enable
);
1262 case ALSPS_GET_PS_MODE
:
1263 enable
= test_bit(CMC_BIT_PS
, &obj
->enable
) ? (1) : (0);
1264 if(copy_to_user(ptr
, &enable
, sizeof(enable
)))
1271 case ALSPS_GET_PS_DATA
:
1272 if((err
= APDS9930_read_ps(obj
->client
, &obj
->ps
)))
1277 dat
= APDS9930_get_ps_value(obj
, obj
->ps
);
1278 if(copy_to_user(ptr
, &dat
, sizeof(dat
)))
1285 case ALSPS_GET_PS_RAW_DATA
:
1286 if((err
= APDS9930_read_ps(obj
->client
, &obj
->ps
)))
1292 if(copy_to_user(ptr
, &dat
, sizeof(dat
)))
1299 case ALSPS_SET_ALS_MODE
:
1300 if(copy_from_user(&enable
, ptr
, sizeof(enable
)))
1307 if((err
= APDS9930_enable_als(obj
->client
, 1)))
1309 APS_ERR("enable als fail: %ld\n", err
);
1312 set_bit(CMC_BIT_ALS
, &obj
->enable
);
1316 if((err
= APDS9930_enable_als(obj
->client
, 0)))
1318 APS_ERR("disable als fail: %ld\n", err
);
1321 clear_bit(CMC_BIT_ALS
, &obj
->enable
);
1325 case ALSPS_GET_ALS_MODE
:
1326 enable
= test_bit(CMC_BIT_ALS
, &obj
->enable
) ? (1) : (0);
1327 if(copy_to_user(ptr
, &enable
, sizeof(enable
)))
1334 case ALSPS_GET_ALS_DATA
:
1335 if((err
= APDS9930_read_als(obj
->client
, &obj
->als
)))
1340 dat
= APDS9930_get_als_value(obj
, obj
->als
);
1341 if(copy_to_user(ptr
, &dat
, sizeof(dat
)))
1348 case ALSPS_GET_ALS_RAW_DATA
:
1349 if((err
= APDS9930_read_als(obj
->client
, &obj
->als
)))
1355 if(copy_to_user(ptr
, &dat
, sizeof(dat
)))
1361 /*----------------------------------for factory mode test---------------------------------------*/
1362 case ALSPS_GET_PS_TEST_RESULT
:
1363 if((err
= APDS9930_read_ps(obj
->client
, &obj
->ps
)))
1367 if(obj
->ps
> atomic_read(&obj
->ps_thd_val_high
))
1373 if(copy_to_user(ptr
, &ps_result
, sizeof(ps_result
)))
1380 case ALSPS_IOCTL_CLR_CALI
:
1381 if(copy_from_user(&dat
, ptr
, sizeof(dat
)))
1390 case ALSPS_IOCTL_GET_CALI
:
1391 ps_cali
= obj
->ps_cali
;
1392 if(copy_to_user(ptr
, &ps_cali
, sizeof(ps_cali
)))
1399 case ALSPS_IOCTL_SET_CALI
:
1400 if(copy_from_user(&ps_cali
, ptr
, sizeof(ps_cali
)))
1406 obj
->ps_cali
= ps_cali
;
1409 case ALSPS_SET_PS_THRESHOLD
:
1410 if(copy_from_user(threshold
, ptr
, sizeof(threshold
)))
1415 APS_ERR("%s set threshold high: 0x%x, low: 0x%x\n", __func__
, threshold
[0],threshold
[1]);
1416 atomic_set(&obj
->ps_thd_val_high
, (threshold
[0]+obj
->ps_cali
));
1417 atomic_set(&obj
->ps_thd_val_low
, (threshold
[1]+obj
->ps_cali
));//need to confirm
1419 set_psensor_threshold(obj
->client
);
1423 case ALSPS_GET_PS_THRESHOLD_HIGH
:
1424 threshold
[0] = atomic_read(&obj
->ps_thd_val_high
) - obj
->ps_cali
;
1425 APS_ERR("%s get threshold high: 0x%x\n", __func__
, threshold
[0]);
1426 if(copy_to_user(ptr
, &threshold
[0], sizeof(threshold
[0])))
1433 case ALSPS_GET_PS_THRESHOLD_LOW
:
1434 threshold
[0] = atomic_read(&obj
->ps_thd_val_low
) - obj
->ps_cali
;
1435 APS_ERR("%s get threshold low: 0x%x\n", __func__
, threshold
[0]);
1436 if(copy_to_user(ptr
, &threshold
[0], sizeof(threshold
[0])))
1442 /*------------------------------------------------------------------------------------------*/
1444 APS_ERR("%s not supported = 0x%04x", __FUNCTION__
, cmd
);
1452 /*----------------------------------------------------------------------------*/
1453 static struct file_operations APDS9930_fops
= {
1454 .owner
= THIS_MODULE
,
1455 .open
= APDS9930_open
,
1456 .release
= APDS9930_release
,
1457 .unlocked_ioctl
= APDS9930_unlocked_ioctl
,
1459 /*----------------------------------------------------------------------------*/
1460 static struct miscdevice APDS9930_device
= {
1461 .minor
= MISC_DYNAMIC_MINOR
,
1463 .fops
= &APDS9930_fops
,
1465 /*----------------------------------------------------------------------------*/
1466 static int APDS9930_i2c_suspend(struct i2c_client
*client
, pm_message_t msg
)
1468 // struct APDS9930_priv *obj = i2c_get_clientdata(client);
1472 if(msg
.event
== PM_EVENT_SUSPEND
)
1476 APS_ERR("null pointer!!\n");
1480 atomic_set(&obj
->als_suspend
, 1);
1481 if(err
= APDS9930_enable_als(client
, 0))
1483 APS_ERR("disable als: %d\n", err
);
1487 atomic_set(&obj
->ps_suspend
, 1);
1488 if(err
= APDS9930_enable_ps(client
, 0))
1490 APS_ERR("disable ps: %d\n", err
);
1494 APDS9930_power(obj
->hw
, 0);
1499 /*----------------------------------------------------------------------------*/
1500 static int APDS9930_i2c_resume(struct i2c_client
*client
)
1502 // struct APDS9930_priv *obj = i2c_get_clientdata(client);
1508 APS_ERR("null pointer!!\n");
1512 APDS9930_power(obj
->hw
, 1);
1513 if(err
= APDS9930_init_client(client
))
1515 APS_ERR("initialize client fail!!\n");
1518 atomic_set(&obj
->als_suspend
, 0);
1519 if(test_bit(CMC_BIT_ALS
, &obj
->enable
))
1521 if(err
= APDS9930_enable_als(client
, 1))
1523 APS_ERR("enable als fail: %d\n", err
);
1526 atomic_set(&obj
->ps_suspend
, 0);
1527 if(test_bit(CMC_BIT_PS
, &obj
->enable
))
1529 if(err
= APDS9930_enable_ps(client
, 1))
1531 APS_ERR("enable ps fail: %d\n", err
);
1537 /*----------------------------------------------------------------------------*/
1538 static void APDS9930_early_suspend(struct early_suspend
*h
)
1539 { /*early_suspend is only applied for ALS*/
1540 struct APDS9930_priv
*obj
= container_of(h
, struct APDS9930_priv
, early_drv
);
1546 APS_ERR("null pointer!!\n");
1551 atomic_set(&obj
->als_suspend
, 1);
1552 if(test_bit(CMC_BIT_ALS
, &obj
->enable
))
1554 if((err
= APDS9930_enable_als(obj
->client
, 0)))
1556 APS_ERR("disable als fail: %d\n", err
);
1561 /*----------------------------------------------------------------------------*/
1562 static void APDS9930_late_resume(struct early_suspend
*h
)
1563 { /*early_suspend is only applied for ALS*/
1564 struct APDS9930_priv
*obj
= container_of(h
, struct APDS9930_priv
, early_drv
);
1570 APS_ERR("null pointer!!\n");
1575 atomic_set(&obj
->als_suspend
, 0);
1576 if(test_bit(CMC_BIT_ALS
, &obj
->enable
))
1578 if((err
= APDS9930_enable_als(obj
->client
, 1)))
1580 APS_ERR("enable als fail: %d\n", err
);
1586 /*----------------------------------------------------------------------------*/
1587 static int temp_als
= 0;
1588 static int ALS_FLAG
= 0;
1590 int APDS9930_ps_operate(void* self
, uint32_t command
, void* buff_in
, int size_in
,
1591 void* buff_out
, int size_out
, int* actualout
)
1596 hwm_sensor_data
* sensor_data
;
1597 struct APDS9930_priv
*obj
= (struct APDS9930_priv
*)self
;
1603 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1605 APS_ERR("Set delay parameter error!\n");
1612 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1614 APS_ERR("Enable sensor parameter error!\n");
1619 value
= *(int *)buff_in
;
1622 if((err
= APDS9930_enable_ps(obj
->client
, 1)))
1624 APS_ERR("enable ps fail: %d\n", err
);
1627 set_bit(CMC_BIT_PS
, &obj
->enable
);
1629 if(!test_bit(CMC_BIT_ALS
, &obj
->enable
))
1632 if((err
= APDS9930_enable_als(obj
->client
, 1)))
1634 APS_ERR("enable als fail: %d\n", err
);
1642 if((err
= APDS9930_enable_ps(obj
->client
, 0)))
1644 APS_ERR("disable ps fail: %d\n", err
);
1647 clear_bit(CMC_BIT_PS
, &obj
->enable
);
1651 if((err
= APDS9930_enable_als(obj
->client
, 0)))
1653 APS_ERR("disable als fail: %d\n", err
);
1663 case SENSOR_GET_DATA
:
1664 if((buff_out
== NULL
) || (size_out
< sizeof(hwm_sensor_data
)))
1666 APS_ERR("get sensor data parameter error!\n");
1671 sensor_data
= (hwm_sensor_data
*)buff_out
;
1672 APDS9930_read_ps(obj
->client
, &obj
->ps
);
1673 APDS9930_read_als_ch0(obj
->client
, &obj
->als
);
1674 APS_ERR("APDS9930_ps_operate als data=%d!\n",obj
->als
);
1675 sensor_data
->values
[0] = APDS9930_get_ps_value(obj
, obj
->ps
);
1676 sensor_data
->value_divide
= 1;
1677 sensor_data
->status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1681 APS_ERR("proxmy sensor operate function no this parameter %d!\n", command
);
1690 int APDS9930_als_operate(void* self
, uint32_t command
, void* buff_in
, int size_in
,
1691 void* buff_out
, int size_out
, int* actualout
)
1695 hwm_sensor_data
* sensor_data
;
1696 struct APDS9930_priv
*obj
= (struct APDS9930_priv
*)self
;
1701 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1703 APS_ERR("Set delay parameter error!\n");
1710 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1712 APS_ERR("Enable sensor parameter error!\n");
1717 value
= *(int *)buff_in
;
1720 if((err
= APDS9930_enable_als(obj
->client
, 1)))
1722 APS_ERR("enable als fail: %d\n", err
);
1725 set_bit(CMC_BIT_ALS
, &obj
->enable
);
1729 if((err
= APDS9930_enable_als(obj
->client
, 0)))
1731 APS_ERR("disable als fail: %d\n", err
);
1734 clear_bit(CMC_BIT_ALS
, &obj
->enable
);
1740 case SENSOR_GET_DATA
:
1741 if((buff_out
== NULL
) || (size_out
< sizeof(hwm_sensor_data
)))
1743 APS_ERR("get sensor data parameter error!\n");
1748 sensor_data
= (hwm_sensor_data
*)buff_out
;
1749 /*yucong MTK add for fixing known issue*/
1750 APDS9930_read_als(obj
->client
, &obj
->als
);
1753 sensor_data
->values
[0] = temp_als
;
1757 for(i
= 0;i
< 2;i
++){
1758 APDS9930_read_als(obj
->client
, &obj
->als
);
1761 (b
[1] > b
[0])?(obj
->als
= b
[0]):(obj
->als
= b
[1]);
1762 sensor_data
->values
[0] = APDS9930_get_als_value(obj
, obj
->als
);
1763 temp_als
= sensor_data
->values
[0];
1765 sensor_data
->value_divide
= 1;
1766 sensor_data
->status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1770 APS_ERR("light sensor operate function no this parameter %d!\n", command
);
1779 /*----------------------------------------------------------------------------*/
1780 static int APDS9930_i2c_detect(struct i2c_client
*client
, struct i2c_board_info
*info
)
1782 strcpy(info
->type
, APDS9930_DEV_NAME
);
1786 /*----------------------------------------------------------------------------*/
1787 static int APDS9930_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
)
1789 struct APDS9930_priv
*obj
;
1790 struct hwmsen_object obj_ps
, obj_als
;
1793 if(!(obj
= kzalloc(sizeof(*obj
), GFP_KERNEL
)))
1798 memset(obj
, 0, sizeof(*obj
));
1800 obj
->hw
= get_cust_alsps_hw();
1801 APDS9930_get_addr(obj
->hw
, &obj
->addr
);
1803 /*for interrup work mode support -- by liaoxl.lenovo 12.08.2011*/
1804 INIT_WORK(&obj
->eint_work
, APDS9930_eint_work
);
1805 obj
->client
= client
;
1806 i2c_set_clientdata(client
, obj
);
1807 atomic_set(&obj
->als_debounce
, 50);
1808 atomic_set(&obj
->als_deb_on
, 0);
1809 atomic_set(&obj
->als_deb_end
, 0);
1810 atomic_set(&obj
->ps_debounce
, 10);
1811 atomic_set(&obj
->ps_deb_on
, 0);
1812 atomic_set(&obj
->ps_deb_end
, 0);
1813 atomic_set(&obj
->ps_mask
, 0);
1814 atomic_set(&obj
->als_suspend
, 0);
1815 atomic_set(&obj
->als_cmd_val
, 0xDF);
1816 atomic_set(&obj
->ps_cmd_val
, 0xC1);
1817 atomic_set(&obj
->ps_thd_val_high
, obj
->hw
->ps_threshold_high
);
1818 atomic_set(&obj
->ps_thd_val_low
, obj
->hw
->ps_threshold_low
);
1820 obj
->pending_intr
= 0;
1821 obj
->als_level_num
= sizeof(obj
->hw
->als_level
)/sizeof(obj
->hw
->als_level
[0]);
1822 obj
->als_value_num
= sizeof(obj
->hw
->als_value
)/sizeof(obj
->hw
->als_value
[0]);
1823 /*Lenovo-sw chenlj2 add 2011-06-03,modified gain 16 to 1/5 accoring to actual thing */
1824 obj
->als_modulus
= (400*100*ZOOM_TIME
)/(1*150);//(1/Gain)*(400/Tine), this value is fix after init ATIME and CONTROL register value
1825 //(400)/16*2.72 here is amplify *100 //16
1826 BUG_ON(sizeof(obj
->als_level
) != sizeof(obj
->hw
->als_level
));
1827 memcpy(obj
->als_level
, obj
->hw
->als_level
, sizeof(obj
->als_level
));
1828 BUG_ON(sizeof(obj
->als_value
) != sizeof(obj
->hw
->als_value
));
1829 memcpy(obj
->als_value
, obj
->hw
->als_value
, sizeof(obj
->als_value
));
1830 atomic_set(&obj
->i2c_retry
, 3);
1831 set_bit(CMC_BIT_ALS
, &obj
->enable
);
1832 set_bit(CMC_BIT_PS
, &obj
->enable
);
1836 APDS9930_i2c_client
= client
;
1838 if(1 == obj
->hw
->polling_mode_ps
)
1848 if((err
= APDS9930_init_client(client
)))
1850 goto exit_init_failed
;
1852 APS_LOG("APDS9930_init_client() OK!\n");
1854 if((err
= misc_register(&APDS9930_device
)))
1856 APS_ERR("APDS9930_device register failed\n");
1857 goto exit_misc_device_register_failed
;
1860 if(err = APDS9930_create_attr(&APDS9930_alsps_driver.driver))
1862 APS_ERR("create attribute err = %d\n", err);
1863 goto exit_create_attr_failed;
1866 obj_ps
.self
= APDS9930_obj
;
1868 obj_ps
.sensor_operate
= APDS9930_ps_operate
;
1869 if((err
= hwmsen_attach(ID_PROXIMITY
, &obj_ps
)))
1871 APS_ERR("attach fail = %d\n", err
);
1872 goto exit_create_attr_failed
;
1875 obj_als
.self
= APDS9930_obj
;
1876 obj_als
.polling
= 1;
1877 obj_als
.sensor_operate
= APDS9930_als_operate
;
1878 if((err
= hwmsen_attach(ID_LIGHT
, &obj_als
)))
1880 APS_ERR("attach fail = %d\n", err
);
1881 goto exit_create_attr_failed
;
1885 #if defined(CONFIG_HAS_EARLYSUSPEND)
1886 obj
->early_drv
.level
= EARLY_SUSPEND_LEVEL_DISABLE_FB
- 1,
1887 obj
->early_drv
.suspend
= APDS9930_early_suspend
,
1888 obj
->early_drv
.resume
= APDS9930_late_resume
,
1889 register_early_suspend(&obj
->early_drv
);
1892 APS_LOG("%s: OK\n", __func__
);
1895 exit_create_attr_failed
:
1896 misc_deregister(&APDS9930_device
);
1897 exit_misc_device_register_failed
:
1899 //i2c_detach_client(client);
1903 APDS9930_i2c_client
= NULL
;
1904 // MT6516_EINTIRQMask(CUST_EINT_ALS_NUM); /*mask interrupt if fail*/
1905 APS_ERR("%s: err = %d\n", __func__
, err
);
1908 /*----------------------------------------------------------------------------*/
1909 static int APDS9930_i2c_remove(struct i2c_client
*client
)
1913 if(err = APDS9930_delete_attr(&APDS9930_i2c_driver.driver))
1915 APS_ERR("APDS9930_delete_attr fail: %d\n", err);
1918 if((err
= misc_deregister(&APDS9930_device
)))
1920 APS_ERR("misc_deregister fail: %d\n", err
);
1923 APDS9930_i2c_client
= NULL
;
1924 i2c_unregister_device(client
);
1925 kfree(i2c_get_clientdata(client
));
1929 /*----------------------------------------------------------------------------*/
1930 static int APDS9930_probe(struct platform_device
*pdev
)
1932 struct alsps_hw
*hw
= get_cust_alsps_hw();
1934 APDS9930_power(hw
, 1);
1935 //APDS9930_force[0] = hw->i2c_num;
1936 //APDS9930_force[1] = hw->i2c_addr[0];
1937 //APS_DBG("I2C = %d, addr =0x%x\n",APDS9930_force[0],APDS9930_force[1]);
1938 if(i2c_add_driver(&APDS9930_i2c_driver
))
1940 APS_ERR("add driver error\n");
1945 /*----------------------------------------------------------------------------*/
1946 static int APDS9930_remove(struct platform_device
*pdev
)
1948 struct alsps_hw
*hw
= get_cust_alsps_hw();
1950 APDS9930_power(hw
, 0);
1951 i2c_del_driver(&APDS9930_i2c_driver
);
1954 /*----------------------------------------------------------------------------*/
1955 static struct platform_driver APDS9930_alsps_driver
= {
1956 .probe
= APDS9930_probe
,
1957 .remove
= APDS9930_remove
,
1960 // .owner = THIS_MODULE,
1963 /*----------------------------------------------------------------------------*/
1964 static int __init
APDS9930_init(void)
1967 struct alsps_hw
*hw
= get_cust_alsps_hw();
1968 APS_LOG("%s: i2c_number=%d\n", __func__
,hw
->i2c_num
);
1969 i2c_register_board_info(hw
->i2c_num
, &i2c_APDS9930
, 1);
1970 if(platform_driver_register(&APDS9930_alsps_driver
))
1972 APS_ERR("failed to register driver");
1977 /*----------------------------------------------------------------------------*/
1978 static void __exit
APDS9930_exit(void)
1981 platform_driver_unregister(&APDS9930_alsps_driver
);
1983 /*----------------------------------------------------------------------------*/
1984 module_init(APDS9930_init
);
1985 module_exit(APDS9930_exit
);
1986 /*----------------------------------------------------------------------------*/
1987 MODULE_AUTHOR("Dexiang Liu");
1988 MODULE_DESCRIPTION("APDS9930 driver");
1989 MODULE_LICENSE("GPL");